mini2440: Use Can mcp2510 with Pengutronix BSP

Markus Mehlan
Hi,

I want connect a mcp2510/2515 can-controller with my mini2440 board. I am
using Pengutronics BSP with version
OSELAS.BSP-Pengutronix-Mini2440-2011.11.0/. Is there a patch for this task
or some hints?

I have read the following web pages yet, but with little success.
http://cor-net.org/2009/09/can-interface-for-the-mini2440-dev-board/
http://pastebin.com/D6RFdXd6

Friendly regards,
Markus

Markus Mehlan
Attachment: add_mcp251x_support.diff (3.39 KB)
Hello,

I've made tests with some kernel patches (see attachement), but I cannot
start the interface.

# ip link set can0 type can bitrate 250000
# ifconfigi can0 up

No such irq type 15
setting trigger mode 15 for irq 61 failed (0xc00131c4)
mcp251x spi0.0: failed to acquire irq 61
ifconfig: SIOCSIFFLAGS: Operation not permitted

Who has got a good idea?


Kernel log:
user.info kernel: s3c24xx-nand s3c2440-nand: clock idle support enabled
user.debug kernel: s3c2410-spi s3c2410-spi.0: bitbang at c38cb8f0          
   
user.warn kernel: s3c24xx_spi_gpiocfg_bus0_gpe11_12_13: enabled
user.debug kernel: s3c2410-spi s3c2410-spi.0: registered master spi0 
user.debug kernel: spi spi0.0: pre-scaler=12 (wanted 2000000, got 1947115)
user.debug kernel: spi spi0.0: setup mode 0, 8 bits/w, 2000000 Hz max --> 0
user.debug kernel: s3c2410-spi s3c2410-spi.0: registered child spi0.0
user.info kernel: CAN device driver interface                        
user.err kernel: MINI2440: Loading MCP251x setup                     
user.debug kernel: mcp251x spi0.0: setup mode 0, 8 bits/w, 2000000 Hz max
--> 0
user.debug kernel: mcp251x spi0.0: CANSTAT 0x80 CANCTRL 0x07         
user.info kernel: mcp251x spi0.0: probed 
...
user.info kernel: can: controller area network core (rev 20090105 abi 8)   
   
user.info kernel: NET: Registered protocol family 29           
user.info kernel: can: raw protocol (rev 20090105) 

root@mithralog01:~ cat /sys/kernel/debug/gpio 
GPIOs 0-23, GPIOA:

GPIOs 32-47, GPIOB:
 gpio-34  (s3c24xx_uda134x     ) out lo
 gpio-35  (s3c24xx_uda134x     ) out hi
 gpio-36  (s3c24xx_uda134x     ) out hi
 gpio-37  (led1                ) out hi
 gpio-38  (led2                ) out hi
 gpio-39  (led3                ) out hi
 gpio-40  (led4                ) out hi

GPIOs 64-79, GPIOC:
 gpio-69  (udc pullup          ) out lo

GPIOs 96-111, GPIOD:

GPIOs 128-143, GPIOE:
 gpio-133 (s3c2440-sdi         ) out hi
 gpio-134 (s3c2440-sdi         ) in  hi
 gpio-135 (s3c2440-sdi         ) in  hi
 gpio-136 (s3c2440-sdi         ) in  hi
 gpio-137 (s3c2440-sdi         ) in  hi
 gpio-138 (s3c2440-sdi         ) in  hi

GPIOs 160-167, GPIOF:

GPIOs 192-207, GPIOG:
 gpio-192 (Button 1            ) in  hi
 gpio-194 (s3c2410-spi.0       ) out hi
 gpio-195 (Button 2            ) in  hi
 gpio-196 (backlight           ) out lo
 gpio-197 (Button 3            ) in  hi
 gpio-198 (Power               ) in  hi
 gpio-199 (Button 5            ) in  hi
 gpio-200 (s3cmci detect       ) in  lo
 gpio-203 (Button 6            ) in  hi

GPIOs 224-234, GPIOH:
 gpio-232 (s3cmci wp           ) in  lo

GPIOs 256-271, GPIOJ:

cat /proc/interrupts 
           CPU0       
 24:          0       s3c  s3c2410-rtc tick
 30:    1313282       s3c  S3C2410 Timer Tick
 32:          0       s3c  s3c2410-lcd
 37:       2268       s3c  s3c-mci
 38:         14       s3c  s3c2410-spi
 41:          1       s3c  s3c2410_udc
 42:          0       s3c  ohci_hcd:usb1
 43:          0       s3c  s3c2440-i2c
 46:          0       s3c  s3c2410-rtc alarm
 51:         60   s3c-ext  eth0
 52:          0   s3c-ext  Button 1
 55:          0   s3c-ext  Button 2
 57:          0   s3c-ext  Button 3
 58:          0   s3c-ext  Power
 59:          0   s3c-ext  Button 5
 60:          1   s3c-ext  s3c-mci
 63:          0   s3c-ext  Button 6
 70:        151  s3c-uart0  s3c2440-uart
 71:        802  s3c-uart0  s3c2440-uart
 79:          0   s3c-adc  s3c2410_ts_pen
 80:          0   s3c-adc  s3c24xx-adc
 83:          0         -  s3c2410-wdt
Err:          0

Juergen Beisert
"No such irq type 15"

After a look into the mcp251x.c driver code, this driver requests the IRQ
with the option IRQF_TRIGGER_FALLING if you do not specify the correct IRQ
level/edge in the ".irq_flags" member. Seems the Samsung world does not
know "IRQF_TRIGGER_FALLING". Search for a corresponding "IRQ_TYPE_EDGE_*"
symbol.

Markus Mehlan
Hello Juergen,

thank you for your reply!

It seems that the platform-struct "mcp251x_info" is not correctly
transmitted to the mcp251x-driver.


Jan 23 08:17:44 mithralog01 user.debug kernel: mcp251x spi0.0:
mcp251x_open: irq_flags: -1887347719 oscillator_frequency: -1096950842

I made following changes:

in mcp251x.c
---------------------
static int mcp251x_open(struct net_device *net)
{
        struct mcp251x_priv *priv = netdev_priv(net);
        struct spi_device *spi = priv->spi;
        struct mcp251x_platform_data *pdata = spi->dev.platform_data;
        int ret;

        dev_dbg(&spi->dev, "%s: irq_flags: %d oscillator_frequency: %d\n",
                __FUNCTION__, pdata->irq_flags,
pdata->oscillator_frequency);


in mach-mini2440.c
-----------------------
static struct mcp251x_platform_data mcp251x_info __initdata = {
        .oscillator_frequency = 16000000,
        .board_specific_setup = &mcp251x_setup,
        .irq_flags            = 2,//IRQF_TRIGGER_FALLING,
        .power_enable = NULL,
        .transceiver_enable = NULL,
};


After ifconfig can0 up I got a kernel oops:

Unable to handle kernel paging request at virtual address bd345674
pgd = c3b58000
[bd345674] *pgd=00000000
Internal error: Oops: 80000005 [#1] PREEMPT
Modules linked in: s3c2410_udc
CPU: 0    Not tainted  (3.1.1-ptx-2011.11.0 #49)
pc : [<bd345674>]    lr : [<c022e3a4>]    psr: a0000013
sp : c3b6be98  ip : 60000013  fp : c3b6bf10
r10: 00000000  r9 : c38b2bf0  r8 : c383ef00
r7 : c03f74b8  r6 : c38b2b60  r5 : c383ee00  r4 : c38b2800
r3 : bd345674  r2 : 00000000  r1 : 00000000  r0 : 00000001
Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: c000717f  Table: 33b58000  DAC: 00000015
Process ifconfig (pid: 613, stack limit = 0xc3b6a270)
Stack: (0xc3b6be98 to 0xc3b6c000)
be80:                                                       8f815bf9
be9ddbc6
bea0: c38b2800 c0358ad4 00040080 00000001 c383ef00 00000000 c383ef0c
c02bf2e0
bec0: c02bf238 c38b2800 000000c1 c02bf508 00008914 c38b2800 00040080
00000001
bee0: c38b2800 c02bf5fc 00008914 00000000 00000001 c0301d0c beb5eac8
00000001
bf00: 306e6163 00000000 00000000 00000000 000000c1 00000001 0006a9ee
400a204c
bf20: 000000c1 00000001 0006a9ee 400a204c 306e6163 00008914 beb5eac8
00008914
bf40: 00000003 c00091a8 c3b6a000 00000000 00000000 c02acc1c beb5eac8
00000003
bf60: 00008914 c0096b6c 00000000 00000002 00070f5f 00070f5f beb5eac8
c3ad6f00
bf80: beb5eac8 c0096bd4 00000003 00000000 beb5eac8 00070f5f 00000004
beb5eac8
bfa0: 00000036 c0009000 00070f5f 00000004 00000003 00008914 beb5eac8
00070f5f
bfc0: 00070f5f 00000004 beb5eac8 00000036 0006b208 00000000 400b3000
00000000
bfe0: beb5edd7 beb5eaa0 0000df20 401c686c 20000010 00000003 00000000
00000000
Function entered at [<c022e3a4>] from [<c02bf2e0>]
Function entered at [<c02bf2e0>] from [<c02bf508>]
Function entered at [<c02bf508>] from [<c02bf5fc>]
Function entered at [<c02bf5fc>] from [<c0301d0c>]
Function entered at [<c0301d0c>] from [<c02acc1c>]
Function entered at [<c02acc1c>] from [<c0096b6c>]
Function entered at [<c0096b6c>] from [<c0096bd4>]
Function entered at [<c0096bd4>] from [<c0009000>]
Code: bad PC value
---[ end trace c67783fbbfd88146 ]---
Jan 23 08:17:44 mithralog01 user.debug kernel: mcp251x spi0.0:
mcp251x_open: irq_flags: -1887347719 oscillator_frequency: -1096950842
Jan 23 08:17:44 mithralog01 user.alert kernel: Unable to handle kernel
paging request at virtual address bd345674
Jan 23 08:17:44 mithralog01 user.alert kernel: pgd = c3b58000
Jan 23 08:17:44 mithralog01 user.alert kernel: [bd345674] *pgd=00000000
Jan 23 08:17:44 mithralog01 user.emerg kernel: Internal error: Oops:
80000005 [#1] PREEMPT
Jan 23 08:17:44 mithralog01 user.warn kernel: Modules linked in:
s3c2410_udc
Jan 23 08:17:44 mithralog01 user.warn kernel: CPU: 0    Not tainted 
(3.1.1-ptx-2011.11.0 #49)
Jan 23 08:17:44 mithralog01 user.warn kernel: pc : [<bd345674>]    lr :
[<c022e3a4>]    psr: a0000013
Jan 23 08:17:44 mithralog01 user.warn kernel: sp : c3b6be98  ip : 60000013 
fp : c3b6bf10
Jan 23 08:17:44 mithralog01 user.warn kernel: r10: 00000000  r9 : c38b2bf0 
r8 : c383ef00
Jan 23 08:17:44 mithralog01 user.warn kernel: r7 : c03f74b8  r6 : c38b2b60 
r5 : c383ee00  r4 : c38b2800
Jan 23 08:17:44 mithralog01 user.warn kernel: r3 : bd345674  r2 : 00000000 
r1 : 00000000  r0 : 00000001
Jan 23 08:17:44 mithralog01 user.warn kernel: Flags: NzCv  IRQs on  FIQs on
 Mode SVC_32  ISA ARM  Segment user
Jan 23 08:17:44 mithralog01 user.warn kernel: Control: c000717f  Table:
33b58000  DAC: 00000015
Jan 23 08:17:44 mithralog01 user.emerg kernel: Process ifconfig (pid: 613,
stack limit = 0xc3b6a270)
Jan 23 08:17:44 mithralog01 user.emerg kernel: Stack: (0xc3b6be98 to
0xc3b6c000)
Jan 23 08:17:44 mithralog01 user.emerg kernel: be80:                       
                               8f815bf9 be9ddbc6
Jan 23 08:17:44 mithralog01 user.emerg kernel: bea0: c38b2800 c0358ad4
00040080 00000001 c383ef00 00000000 c383ef0c c02bf2e0
Jan 23 08:17:44 mithralog01 user.emerg kernel: bec0: c02bf238 c38b2800
000000c1 c02bf508 00008914 c38b2800 00040080 00000001
Jan 23 08:17:44 mithralog01 user.emerg kernel: bee0: c38b2800 c02bf5fc
00008914 00000000 00000001 c0301d0c beb5eac8 00000001
Jan 23 08:17:44 mithralog01 user.emerg kernel: bf00: 306e6163 00000000
00000000 00000000 000000c1 00000001 0006a9ee 400a204c
Jan 23 08:17:44 mithralog01 user.emerg kernel: bf20: 000000c1 00000001
0006a9ee 400a204c 306e6163 00008914 beb5eac8 00008914
Jan 23 08:17:44 mithralog01 user.emerg kernel: bf40: 00000003 c00091a8
c3b6a000 00000000 00000000 c02acc1c beb5eac8 00000003
Jan 23 08:17:44 mithralog01 user.emerg kernel: bf60: 00008914 c0096b6c
00000000 00000002 00070f5f 00070f5f beb5eac8 c3ad6f00
Jan 23 08:17:44 mithralog01 user.emerg kernel: bf80: beb5eac8 c0096bd4
00000003 00000000 beb5eac8 00070f5f 00000004 beb5eac8
Jan 23 08:17:44 mithralog01 user.emerg kernel: bfa0: 00000036 c0009000
00070f5f 00000004 00000003 00008914 beb5eac8 00070f5f
Jan 23 08:17:44 mithralog01 user.emerg kernel: bfc0: 00070f5f 00000004
beb5eac8 00000036 0006b208 00000000 400b3000 00000000
Jan 23 08:17:44 mithralog01 user.emerg kernel: bfe0: beb5edd7 beb5eaa0
0000df20 401c686c 20000010 00000003 00000000 00000000
Jan 23 08:17:44 mithralog01 user.warn kernel: Function entered at
[<c022e3a4>] from [<c02bf2e0>]
Jan 23 08:17:44 mithralog01 user.warn kernel: Function entered at
[<c02bf2e0>] from [<c02bf508>]
Jan 23 08:17:44 mithralog01 user.warn kernel: Function entered at
[<c02bf508>] from [<c02bf5fc>]
Jan 23 08:17:44 mithralog01 user.warn kernel: Function entered at
[<c02bf5fc>] from [<c0301d0c>]
Jan 23 08:17:44 mithralog01 user.warn kernel: Function entered at
[<c0301d0c>] from [<c02acc1c>]
Jan 23 08:17:44 mithralog01 user.warn kernel: Function entered at
[<c02acc1c>] from [<c0096b6c>]
Jan 23 08:17:44 mithralog01 user.warn kernel: Function entered at
[<c0096b6c>] from [<c0096bd4>]
Jan 23 08:17:44 mithralog01 user.warn kernel: Function entered at
[<c0096bd4>] from [<c0009000>]
Jan 23 08:17:44 mithralog01 user.emerg kernel: Code: bad PC value
Jan 23 08:17:44 mithralog01 user.warn kernel: ---[ end trace
c67783fbbfd88146 ]---

Juergen Beisert
Try the same with the 2012.12.0 release of my BSP and its Linux-3.7 kernel.
If you face the same error, you should send a message to the maintainer of
this driver how to fix it in mainline.

Markus Mehlan
Hi Juergen,

I added some code to the mcp251x-driver to check if the problem is caused
by the wrong platform_data.

Now I can do a "ifconfig can0 up" and send and receive via cansend/candump
with a baudrate up to 1Mbit.

"ifconfig can0 down" causes a segmentation fault and I have to restart the
system. So I will change to BSP 2012.12.0.

Best regards,
Markus

static void mcp251x_open_clean(struct net_device *net)
{
        struct mcp251x_priv *priv = netdev_priv(net);
        struct spi_device *spi = priv->spi;
        struct mcp251x_platform_data *pdata = spi->dev.platform_data;

+        //TEST
+        struct mcp251x_platform_data pdataTmp;
+        memset(&pdataTmp, 0, sizeof(pdataTmp));
+        pdataTmp.oscillator_frequency = 16000000;
+        pdataTmp.irq_flags = IRQF_TRIGGER_FALLING;
+        pdata = &pdataTmp;
+        //TEST

        free_irq(spi->irq, priv);

static int mcp251x_open(struct net_device *net)
{
        struct mcp251x_priv *priv = netdev_priv(net);
        struct spi_device *spi = priv->spi;
        struct mcp251x_platform_data *pdata = spi->dev.platform_data;
        int ret;

 +       //TEST
 +       struct mcp251x_platform_data pdataTmp;
 +       memset(&pdataTmp, 0, sizeof(pdataTmp));
 +       pdataTmp.oscillator_frequency = 16000000;
 +       pdataTmp.irq_flags = IRQF_TRIGGER_FALLING;
 +       pdata = &pdataTmp;
 +       //TEST

Markus Mehlan
I tried the same with the 2012.12.0 release of my BSP and its Linux-3.7
kernel and the problem remains. The platform_struct is not transmitted
correctly to the driver's open function. If I define a local platform_data
struct inside the open function, the driver works as ecpected, but this is
not the right way.
I have sent a mail to the maintainer and hope that he has got a solution.

Best regards,
Markus

Juergen Beisert
Keep an eye on the "__initdata" attribute. Some register functions will
copy the structur's content, some other not. Remove it as a test case.

Markus Mehlan
Attachment: add_can_mcp2515.diff (3.67 KB)
Thank you Juergen,

that was the right hint! 

+static struct mcp251x_platform_data mcp251x_info = {
+       .oscillator_frequency = 16000000,
+       .board_specific_setup = &mcp251x_setup,
+       .irq_flags            = IRQF_TRIGGER_FALLING|IRQF_ONESHOT,
+       .power_enable = NULL,
+       .transceiver_enable = NULL,
+};

Now the can driver works without bad workarounds. I have made a patch for
2012.12.0 release of the BSP and Linux-3.7.

If somebody uses the mcp2515-Chip, he has to change the modalias in the
spi_board_info struct:

static struct spi_board_info mini2440_spi_devs[] __initdata = {
   {   
       .modalias      = "mcp2510",
       .platform_data = &mcp251x_info,
       .irq           = IRQ_EINT17, // GPG9 (Interrupt 61)
       .chip_select   = 0,
       .max_speed_hz  = 2*1000*1000,
       .bus_num       = 0,
       .mode          = SPI_MODE_0,
   },
};

Best regards,
Markus