von
ALrK3uMW (Gast)
14.04.2011 21:27
Hi,
wie kriege ich den SPI-Bus unter dem aktuellen Openwrt (backfire) mit
GPIOs zum Laufen? Wo finde ich Einstellungen zu den verwendeten GPIOs,
oder eine zugehörige Doku?
Openwrt kompiliert, kmod-spi-bitbang, kmod-spi-dev, kmod-spi-gpio und
spidev-test sind fest eingebaut, scheinen aber kein device zu erzeugen.
Hardware: Edimax BR-6104KP
VG
von
MBS (Gast)
02.07.2011 17:17
Weiß nicht, ob es noch aktuell ist. Die Infos findet man im Quellcode
(spi_gpio.c). Gibt also 2 Möglichkeiten:
1.: entsprechende platform_data in deiner
arch/mips/adm5120/edimax/br-6104kp.c definieren. Näheres dazu beschreibt
auch die Datei include/linux/spi/spi_gpio.h. Komplettes Image neu bauen.
2.: in spi_gpio.c gleich folgende Sachen auskommentieren und auf deine
GPIO-Nummern ändern:
* #define DRIVER_NAME "myboard_spi2"
* #define SPI_MISO_GPIO 119
* #define SPI_MOSI_GPIO 120
* #define SPI_SCK_GPIO 121
* #define SPI_N_CHIPSEL 4
* #include "spi_gpio.c"
Also das abschließende */ entsprechend vor die erste Zeile hier
verschieben und die Zeichen vor der Raute entfernen. Dann müsste man
eigentlich nur noch diese Datei kompilieren.
Hallo ALrK3uMW,
bist du schon weiter... ich versuche nun seit ein paar Tagen SPI am
WGT634 zum laufen zu bringen. Und habe zur Zeit die "selbe" Frage / bin
auf dem selben Stand wie du.
-alex
von
Mountain (Gast)
05.04.2012 18:32
Hallo,
ich habe ein CAN-Bus Controller mit einem BR-6104K (SoC ADM5120)
verbunden. Über SPI kann ich den Controller initialisieren: 1 BusyBox v1 . 19 . 3 ( 2012 - 04 - 05 12 : 15 : 53 CEST ) built - in shell ( ash )
2 Enter ' help ' for a list of built - in commands .
3
4 _______ ________ __
5 | | . ----- . ----- . ----- . | | | | . ---- . | | _
6 | - || _ | - __ | || | | || _ || _ |
7 | _______ || __ | _____ | __ | __ || ________ || __ | | ____ |
8 | __ | W I R E L E S S F R E E D O M
9 ATTITUDE ADJUSTMENT ( bleeding edge , r30857 ) ----------
10
11 root @ OpenWrt :/ # uname - a
12 Linux OpenWrt 3 . 1 . 10 # 6 Thu Apr 5 16 : 39 : 22 CEST 2012 mips GNU / Linux
13
14 root @ OpenWrt :/ # insmod mcp251x
15 root @ OpenWrt :/ # cat / sys / kernel / debug / gpio
16 GPIOs 0 - 3 , adm5120 gpio0 :
17 gpio - 2 ( MCP251x CAN INT ) in hi
18
19 GPIOs 8 - 22 , adm5120 gpio1 :
20 gpio - 17 ( spi_gpio . 1 ) in lo
21 gpio - 18 ( spi_gpio . 1 ) out lo
22 gpio - 20 ( spi_gpio . 1 ) out lo
23 gpio - 21 ( spi1 . 0 ) out hi
24 root @ OpenWrt :/ # insmod mcp251x
25 [ 368 . 736000 ] mcp251x spi1 . 0 : probed
26
27 root @ OpenWrt :/ # ip link set can0 type can bitrate 125000 loopback on
28
29 root @ OpenWrt :/ # ifconfig can0 up
30 [ 402 . 324000 ] mcp251x spi1 . 0 : CNF : 0x03 0xb5 0x01
31
32 root @ OpenWrt :/ # ip - details link show can0
33 10 : can0 : < NOARP , UP , LOWER_UP , ECHO > mtu 16 qdisc pfifo_fast state UNKNOWN qlen 10
34 link / can
35 can < LOOPBACK > state ERROR - ACTIVE restart - ms 0
36 bitrate 125000 sample - point 0 . 875
37 tq 500 prop - seg 6 phase - seg1 7 phase - seg2 2 sjw 1
38 mcp251x : tseg1 3 .. 16 tseg2 2 .. 8 sjw 1 .. 4 brp 1 .. 64 brp - inc 1
39 clock 8000000
40
41 root @ OpenWrt :/ # cat / sys / kernel / debug / gpio
42 GPIOs 0 - 3 , adm5120 gpio0 :
43 gpio - 2 ( MCP251x CAN INT ) in hi
44
45 GPIOs 8 - 22 , adm5120 gpio1 :
46 gpio - 17 ( spi_gpio . 1 ) in lo
47 gpio - 18 ( spi_gpio . 1 ) out lo
48 gpio - 20 ( spi_gpio . 1 ) out lo
49 gpio - 21 ( spi1 . 0 ) out hi
50
51 root @ OpenWrt :/ # cat / proc / interrupts
52 CPU0
53 2 : 0 MIPS cascade [ INTC ]
54 7 : 33933 MIPS timer
55 9 : 2477 INTC uart - pl010
56 12 : 0 INTC mcp251x
57 17 : 614 INTC eth0 , eth1
58 ERR : 0
59
60 root @ OpenWrt :/ # dmesg | tail - 5
61 [ 368 . 732000 ] mcp251x spi1 . 0 : CANSTAT 0x80 CANCTRL 0x07
62 [ 368 . 736000 ] mcp251x spi1 . 0 : probed
63 [ 402 . 308000 ] mcp251x spi1 . 0 : INTC_REG_IRQ_ENABLE = 0x212
64 [ 402 . 308000 ] mcp251x spi1 . 0 : GPIO2 IRQ initialized
65 [ 402 . 324000 ] mcp251x spi1 . 0 : CNF : 0x03 0xb5 0x01
Sieht soweit gut aus, aber es wird kein IRQ ausgelöst, wenn ich eine CAN
Nachricht sende: 1 root @ OpenWrt :/ # cansend can0 123 # DEADBEEF
2 root @ OpenWrt :/ # cat / proc / interrupts
3 CPU0
4 2 : 0 MIPS cascade [ INTC ]
5 7 : 34334 MIPS timer
6 9 : 2845 INTC uart - pl010
7 12 : 0 INTC mcp251x
8 17 : 669 INTC eth0 , eth1
9 ERR : 0
10
11 root @ OpenWrt :/ # cat / sys / kernel / debug / gpio
12 GPIOs 0 - 3 , adm5120 gpio0 :
13 gpio - 2 ( MCP251x CAN INT ) in lo
14
15 GPIOs 8 - 22 , adm5120 gpio1 :
16 gpio - 17 ( spi_gpio . 1 ) in lo
17 gpio - 18 ( spi_gpio . 1 ) out lo
18 gpio - 20 ( spi_gpio . 1 ) out lo
19 gpio - 21 ( spi1 . 0 ) out hi
GPIO2 ist im Status "in lo" und sollte einen IRQ auslösen.
Ich habe zuerst versucht, den IRQ Initialisierung in der Board
Definition unterzubringen - ohne Erfolg. Daher habe ich
versuchsweise dies nun in den CAN Controller Treiber
eingebaut (mcp251x.c):
1 static irqreturn_t mcp251x_can_ist ( int irq , void * dev_id )
2 {
3 struct mcp251x_priv * priv = dev_id ;
4 struct spi_device * spi = priv -> spi ;
5 struct net_device * net = priv -> net ;
6 unsigned long flags ;
7 unsigned int intc_reg_int_level ;
8
9 mutex_lock ( & priv -> mcp_lock );
10 dev_dbg ( & spi -> dev , " in mcp251x_can_ist ... \n " );
11
12 // ADM5120 IRQs can only be level, not edge so we are going
13 // switch level and only use high to low trigger
14 spin_lock_irqsave ( & level_register_lock , flags );
15 {
16 intc_reg_int_level = BIT ( 4 ) ^ intc_read_reg ( INTC_REG_INT_LEVEL );
17 intc_write_reg ( INTC_REG_INT_LEVEL , intc_reg_int_level );
18 }
19 spin_unlock_irqrestore ( & level_register_lock , flags );
20 // we only need falling edge
21 if ( BIT ( 4 ) & intc_reg_int_level )
22 return ( IRQ_HANDLED );
23 while ( ! priv -> force_quit ) {
24 ...
25 }
26 }
27
28 ...
29 static int mcp251x_open ( struct net_device * net )
30 {
31 struct mcp251x_priv * priv = netdev_priv ( net );
32 struct spi_device * spi = priv -> spi ;
33 struct mcp251x_platform_data * pdata = spi -> dev . platform_data ;
34 int ret ;
35 unsigned int ire ;
36 unsigned long flags ;
37
38 ret = open_candev ( net );
39 if ( ret ) {
40 dev_err ( & spi -> dev , "unable to set initial baudrate! \n " );
41 return ret ;
42 }
43
44 mutex_lock ( & priv -> mcp_lock );
45 if ( pdata -> transceiver_enable )
46 pdata -> transceiver_enable ( 1 );
47
48 priv -> force_quit = 0 ;
49 priv -> tx_skb = NULL ;
50 priv -> tx_len = 0 ;
51
52 ret = request_threaded_irq ( spi -> irq , NULL , mcp251x_can_ist ,
53 pdata -> irq_flags ? pdata -> irq_flags : IRQF_TRIGGER_FALLING ,
54 DEVICE_NAME , priv );
55 if ( ret ) {
56 dev_err ( & spi -> dev , "failed to acquire irq %d \n " , spi -> irq );
57 if ( pdata -> transceiver_enable )
58 pdata -> transceiver_enable ( 0 );
59 close_candev ( net );
60 goto open_unlock ;
61 } else {
62 spin_lock_irqsave ( & level_register_lock , flags );
63 // enable interrupt on GPIO 2
64 // pp37 ADM5120 manual
65 ire = intc_read_reg ( INTC_REG_IRQ_ENABLE );
66 ire |= BIT ( 4 ) | BIT ( 9 ); // II0E | SWIE
67 intc_write_reg ( INTC_REG_IRQ_ENABLE , ire );
68 dev_dbg ( & spi -> dev , " INTC_REG_IRQ_ENABLE = 0x%x \n " , ire );
69
70 // Enable CSX0/INTX0 processing as described on pp131 of ADM5120 manual
71 SW_WRITE_REG ( SWITCH_REG_GPIO_CONF2 , BIT ( 4 ));
72 // sets GPIO4 and 2 as active low
73 // pp41/42 of ADM5120 manual.
74 intc_write_reg ( INTC_REG_INT_LEVEL , BIT ( 4 ) | intc_read_reg ( INTC_REG_INT_LEVEL ));
75 spin_unlock_irqrestore ( & level_register_lock , flags );
76 dev_dbg ( & spi -> dev , " GPIO2 IRQ initialized \n " );
77 }
78 ...
79 }
Ein simples GPIO2 Modul hingegen funktioniert:
http://www.omnima.co.uk/forums/lofiversion/index.php?t72.html 1 root @ OpenWrt :/ # insmod gpio2
2 [ 130 . 380000 ] INTC_REG_IRQ_ENABLE = 0x212
3 [ 130 . 384000 ] GPIO_RESET : requesting IRQ -> fine
4 root @ OpenWrt :/ # [ 133 . 820000 ] pressed
5 [ 134 . 040000 ] released
6 [ 135 . 196000 ] pressed
7 [ 135 . 412000 ] released
8 [ 136 . 076000 ] pressed
9 [ 136 . 220000 ] released
10
11 root @ OpenWrt :/ # cat / proc / interrupts
12 CPU0
13 2 : 0 MIPS cascade [ INTC ]
14 7 : 28970 MIPS timer
15 9 : 180 INTC uart - pl010
16 12 : 6 INTC gpio_reset
17 17 : 334 INTC eth0 , eth1
18 ERR : 0
Hier die Board Initialisierung: 1 nizza ~/ projekte / openwrt / trunk_3 . 1 ( svn ) - [ trunk : 30857 ] % cat build_dir / linux - adm5120_router_le / linux - 3 . 1 . 10 / arch / mips / adm5120 / edimax / br - 61 xx . c
2 /*
3 * Edimax BR-61xx support
4 *
5 * Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published
9 * by the Free Software Foundation.
10 *
11 */
12
13 #include "br-61xx.h"
14
15 #include <prom/admboot.h>
16 #include <linux/spi/spi_gpio.h>
17 #include <linux/can/platform/mcp251x.h>
18
19 #include <linux/irq.h>
20 #include <linux/interrupt.h>
21 #include <linux/kernel.h>
Hat jemand eine Idee, warum der IRQ im MCP251x Modul nicht ausgelöst
wird ?
von
Mountain (Gast)
05.04.2012 18:40
Hoppla,
die Board Definitions-Datei wurde abgeschnitten
von
Mountain (Gast)
18.04.2012 16:06
:-) habs zum Fliegen bekommen:
1 root @ OpenWrt :~ # cansend can0 666 # DEADBEEF
2
3 root @ OpenWrt :~ # candump any , 0 : 0 , # FFFFFFFF
4 can0 666 [ 4 ] DE AD BE EF
5 can0 666 [ 4 ] DE AD BE EF
6
7 root @ OpenWrt :~ # ip - s - details link show can0
8 9 : can0 : < NOARP , UP , LOWER_UP , ECHO > mtu 16 qdisc pfifo_fast state UNKNOWN
9 qlen 10
10 link / can
11 can < LOOPBACK > state ERROR - ACTIVE restart - ms 0
12 bitrate 125000 sample - point 0 . 875
13 tq 500 prop - seg 6 phase - seg1 7 phase - seg2 2 sjw 1
14 mcp251x : tseg1 3 .. 16 tseg2 2 .. 8 sjw 1 .. 4 brp 1 .. 64 brp - inc 1
15 clock 8000000
16 re - started bus - errors arbit - lost error - warn error - pass bus - off
17 0 0 0 0 0 0
18 RX : bytes packets errors dropped overrun mcast
19 48 10 0 0 0 0
20 TX : bytes packets errors dropped carrier collsns
21 48 10 0 0 0 0
22
23 root @ OpenWrt :~ # cat / sys / kernel / debug / gpio
24 GPIOs 0 - 3 , adm5120 gpio0 :
25 gpio - 2 ( MCP251x / INT ) in hi
26
27 GPIOs 8 - 22 , adm5120 gpio1 :
28 gpio - 17 ( spi_gpio . 1 ) in lo
29 gpio - 18 ( spi_gpio . 1 ) out lo
30 gpio - 20 ( spi_gpio . 1 ) out lo
31 gpio - 21 ( spi1 . 0 ) out hi
32
33 root @ OpenWrt :~ # cat / proc / interrupts
34 CPU0
35 2 : 0 MIPS cascade [ INTC ]
36 7 : 553160 MIPS timer
37 9 : 1482 INTC uart - pl010
38 12 : 20 INTC mcp251x
39 17 : 119245 INTC eth0 , eth1
40 ERR : 0
1 --- mcp251x . c 2012 - 01 - 18 16 : 33 : 18 . 000000000 + 0100
2 +++ mcp251x_funkt2 . c 2012 - 04 - 18 15 : 33 : 49 . 926203717 + 0200
3 @@ - 76 , 6 + 76 , 15 @@
4 #include <linux/spi/spi.h>
5 #include <linux/uaccess.h>
6
7 + # include < linux / irq . h >
8 + # include < linux / interrupt . h >
9 +
10 + # include < adm5120_defs . h >
11 + # include < asm / mipsregs . h >
12 + # include < asm / mach - adm5120 / adm5120_info . h >
13 + # include < asm / mach - adm5120 / adm5120_defs . h >
14 + # include < asm / mach - adm5120 / adm5120_switch . h >
15 +
16 /* SPI interface instruction set */
17 #define INSTRUCTION_WRITE 0x02
18 #define INSTRUCTION_READ 0x03
19 @@ - 210 , 6 + 219 , 21 @@
20
21 #define DEVICE_NAME "mcp251x"
22
23 + static inline void intc_write_reg ( unsigned int reg , u32 val )
24 + {
25 + void __iomem * base = ( void __iomem * ) KSEG1ADDR ( ADM5120_INTC_BASE );
26 +
27 + __raw_writel ( val , base + reg );
28 + }
29 +
30 + static inline u32 intc_read_reg ( unsigned int reg )
31 + {
32 + void __iomem * base = ( void __iomem * ) KSEG1ADDR ( ADM5120_INTC_BASE );
33 +
34 + return __raw_readl ( base + reg );
35 + }
36 +
37 +
38 static int mcp251x_enable_dma ; /* Enable SPI DMA. Default: 0 (Off) */
39 module_param ( mcp251x_enable_dma , int , S_IRUGO );
40 MODULE_PARM_DESC ( mcp251x_enable_dma , "Enable SPI DMA. Default: 0 (Off)" );
41 @@ - 779 , 6 + 803 , 39 @@
42 mutex_unlock ( & priv -> mcp_lock );
43 }
44
45 + static DEFINE_SPINLOCK ( level_register_lock );
46 +
47 +
48 + static irqreturn_t mcp251x_can_hardirq ( int irq , void * dev_id )
49 + {
50 + struct mcp251x_priv * priv = dev_id ;
51 + struct spi_device * spi = priv -> spi ;
52 + unsigned long flags ;
53 + unsigned int intc_reg_int_level ;
54 +
55 + // ADM5120 IRQs can only be level, not edge so we are going
56 + // switch level and only use high to low trigger
57 + spin_lock_irqsave ( & level_register_lock , flags );
58 + intc_reg_int_level = intc_read_reg ( INTC_REG_INT_LEVEL ) ^ BIT ( 4 );
59 + intc_write_reg ( INTC_REG_INT_LEVEL , intc_reg_int_level );
60 + dev_info ( & spi -> dev , " mcp251x INT level 0x%X \n " , intc_reg_int_level );
61 +
62 + // we ignore raising edge - we have already xored
63 + // if (intc_reg_int_level && BIT(4))
64 + if ( intc_reg_int_level &= 0x10 )
65 + {
66 + dev_info ( & spi -> dev , " mcp251x INT high -> IRQ_HANDLED \n " );
67 + spin_unlock_irqrestore ( & level_register_lock , flags );
68 + return IRQ_HANDLED ;
69 + } else {
70 + dev_info ( & spi -> dev , " mcp251x INT low -> IRQ_WAKE_THREAD \n " );
71 + spin_unlock_irqrestore ( & level_register_lock , flags );
72 + return IRQ_WAKE_THREAD ;
73 + }
74 + }
75 +
76 +
77 +
78 static irqreturn_t mcp251x_can_ist ( int irq , void * dev_id )
79 {
80 struct mcp251x_priv * priv = dev_id ;
81 @@ - 786 , 6 + 843 , 8 @@
82 struct net_device * net = priv -> net ;
83
84 mutex_lock ( & priv -> mcp_lock );
85 + dev_info ( & spi -> dev , " in mcp251x_can_ist ... \n " );
86 +
87 while ( ! priv -> force_quit ) {
88 enum can_state new_state ;
89 u8 intf , eflag ;
90 @@ - 909 , 12 + 968 , 15 @@
91 return IRQ_HANDLED ;
92 }
93
94 +
95 static int mcp251x_open ( struct net_device * net )
96 {
97 struct mcp251x_priv * priv = netdev_priv ( net );
98 struct spi_device * spi = priv -> spi ;
99 struct mcp251x_platform_data * pdata = spi -> dev . platform_data ;
100 int ret ;
101 + unsigned int ire ;
102 + unsigned long flags ;
103
104 ret = open_candev ( net );
105 if ( ret ) {
106 @@ - 930 , 8 + 992 , 9 @@
107 priv -> tx_skb = NULL ;
108 priv -> tx_len = 0 ;
109
110 - ret = request_threaded_irq ( spi -> irq , NULL , mcp251x_can_ist ,
111 - pdata -> irq_flags ? pdata -> irq_flags : IRQF_TRIGGER_FALLING ,
112 + ret = request_threaded_irq ( spi -> irq , mcp251x_can_hardirq , mcp251x_can_ist ,
113 + // pdata->irq_flags ? pdata->irq_flags : IRQF_TRIGGER_FALLING,
114 + pdata -> irq_flags ? pdata -> irq_flags : IRQF_TRIGGER_NONE ,
115 DEVICE_NAME , priv );
116 if ( ret ) {
117 dev_err ( & spi -> dev , "failed to acquire irq %d \n " , spi -> irq );
118 @@ - 939 , 6 + 1002 , 24 @@
119 pdata -> transceiver_enable ( 0 );
120 close_candev ( net );
121 goto open_unlock ;
122 + } else {
123 + spin_lock_irqsave ( & level_register_lock , flags );
124 + // enable interrupt on GPIO 2
125 + // pp37 ADM5120 manual
126 + ire = intc_read_reg ( INTC_REG_IRQ_ENABLE );
127 + dev_info ( & spi -> dev , " INTC_REG_IRQ_ENABLE was = 0x%x \n " , ire );
128 + ire |= BIT ( 4 ) | BIT ( 9 ); // II0E | SWIE
129 + // ire |= BIT(4); // II0E
130 + intc_write_reg ( INTC_REG_IRQ_ENABLE , ire );
131 + dev_info ( & spi -> dev , " INTC_REG_IRQ_ENABLE now = 0x%x \n " , ire );
132 +
133 + // Enable CSX0/INTX0 processing as described on pp131 of ADM5120 manual
134 + SW_WRITE_REG ( SWITCH_REG_GPIO_CONF2 , BIT ( 4 ));
135 + // sets GPIO4 and 2 as active low
136 + // pp41/42 of ADM5120 manual.
137 + intc_write_reg ( INTC_REG_INT_LEVEL , BIT ( 4 ) | intc_read_reg ( INTC_REG_INT_LEVEL ));
138 + spin_unlock_irqrestore ( & level_register_lock , flags );
139 + dev_info ( & spi -> dev , " GPIO2 IRQ initialized: IRQ %d \n " , spi -> irq );
140 }
141
142 priv -> wq = create_freezable_workqueue ( "mcp251x_wq" );
Boardefintionsdatei br-61xx.c: 1 static struct mcp251x_platform_data mcp251x_info = {
2 . oscillator_frequency = 16000000 ,
3 . board_specific_setup = NULL ,
4 . irq_flags = IRQF_TRIGGER_NONE ,
5 . power_enable = NULL ,
6 . transceiver_enable = NULL ,
7 };
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.