diff options
Diffstat (limited to 'arch/cris/arch-v32/drivers')
-rw-r--r-- | arch/cris/arch-v32/drivers/Kconfig | 711 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/Makefile | 5 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/axisflashmap.c | 488 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/cryptocop.c | 104 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/i2c.c | 206 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/i2c.h | 2 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/iop_fw_load.c | 16 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/mach-a3/Makefile | 6 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/mach-a3/gpio.c | 984 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/mach-a3/nandflash.c | 180 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/mach-fs/Makefile | 6 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/mach-fs/gpio.c (renamed from arch/cris/arch-v32/drivers/gpio.c) | 612 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/mach-fs/nandflash.c (renamed from arch/cris/arch-v32/drivers/nandflash.c) | 122 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/pcf8563.c | 296 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/sync_serial.c | 938 |
15 files changed, 3472 insertions, 1204 deletions
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig index c329cce2a0c3..2a92cb1886ca 100644 --- a/arch/cris/arch-v32/drivers/Kconfig +++ b/arch/cris/arch-v32/drivers/Kconfig | |||
@@ -4,64 +4,102 @@ config ETRAX_ETHERNET | |||
4 | bool "Ethernet support" | 4 | bool "Ethernet support" |
5 | depends on ETRAX_ARCH_V32 | 5 | depends on ETRAX_ARCH_V32 |
6 | select NET_ETHERNET | 6 | select NET_ETHERNET |
7 | select MII | ||
7 | help | 8 | help |
8 | This option enables the ETRAX FS built-in 10/100Mbit Ethernet | 9 | This option enables the ETRAX FS built-in 10/100Mbit Ethernet |
9 | controller. | 10 | controller. |
10 | 11 | ||
11 | config ETRAX_ETHERNET_HW_CSUM | 12 | config ETRAX_NO_PHY |
12 | bool "Hardware accelerated ethernet checksum and scatter/gather" | 13 | bool "PHY not present" |
13 | depends on ETRAX_ETHERNET | 14 | depends on ETRAX_ETHERNET |
14 | depends on ETRAX_STREAMCOPROC | 15 | default N |
15 | default y | ||
16 | help | 16 | help |
17 | Hardware acceleration of checksumming and scatter/gather | 17 | This option disables all MDIO communication with an ethernet |
18 | transceiver connected to the MII interface. This option shall | ||
19 | typically be enabled if the MII interface is connected to a | ||
20 | switch. This option should normally be disabled. If enabled, | ||
21 | speed and duplex will be locked to 100 Mbit and full duplex. | ||
18 | 22 | ||
19 | config ETRAX_ETHERNET_IFACE0 | 23 | config ETRAX_ETHERNET_IFACE0 |
20 | depends on ETRAX_ETHERNET | 24 | depends on ETRAX_ETHERNET |
21 | bool "Enable network interface 0" | 25 | bool "Enable network interface 0" |
22 | 26 | ||
23 | config ETRAX_ETHERNET_IFACE1 | 27 | config ETRAX_ETHERNET_IFACE1 |
24 | depends on ETRAX_ETHERNET | 28 | depends on (ETRAX_ETHERNET && ETRAXFS) |
25 | bool "Enable network interface 1 (uses DMA6 and DMA7)" | 29 | bool "Enable network interface 1 (uses DMA6 and DMA7)" |
26 | 30 | ||
31 | config ETRAX_ETHERNET_GBIT | ||
32 | depends on (ETRAX_ETHERNET && CRIS_MACH_ARTPEC3) | ||
33 | bool "Enable gigabit Ethernet support" | ||
34 | |||
27 | choice | 35 | choice |
28 | prompt "Network LED behavior" | 36 | prompt "Eth0 led group" |
29 | depends on ETRAX_ETHERNET | 37 | depends on ETRAX_ETHERNET_IFACE0 |
30 | default ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY | 38 | default ETRAX_ETH0_USE_LEDGRP0 |
31 | 39 | ||
32 | config ETRAX_NETWORK_LED_ON_WHEN_LINK | 40 | config ETRAX_ETH0_USE_LEDGRP0 |
33 | bool "LED_on_when_link" | 41 | bool "Use LED grp 0" |
42 | depends on ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO | ||
34 | help | 43 | help |
35 | Selecting LED_on_when_link will light the LED when there is a | 44 | Use LED grp 0 for eth0 |
36 | connection and will flash off when there is activity. | ||
37 | 45 | ||
38 | Selecting LED_on_when_activity will light the LED only when | 46 | config ETRAX_ETH0_USE_LEDGRP1 |
39 | there is activity. | 47 | bool "Use LED grp 1" |
40 | 48 | depends on ETRAX_NBR_LED_GRP_TWO | |
41 | This setting will also affect the behaviour of other activity LEDs | 49 | help |
42 | e.g. Bluetooth. | 50 | Use LED grp 1 for eth0 |
43 | 51 | ||
44 | config ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY | 52 | config ETRAX_ETH0_USE_LEDGRPNULL |
45 | bool "LED_on_when_activity" | 53 | bool "Use no LEDs for eth0" |
46 | help | 54 | help |
47 | Selecting LED_on_when_link will light the LED when there is a | 55 | Use no LEDs for eth0 |
48 | connection and will flash off when there is activity. | 56 | endchoice |
49 | 57 | ||
50 | Selecting LED_on_when_activity will light the LED only when | 58 | choice |
51 | there is activity. | 59 | prompt "Eth1 led group" |
60 | depends on ETRAX_ETHERNET_IFACE1 | ||
61 | default ETRAX_ETH1_USE_LEDGRP1 | ||
62 | |||
63 | config ETRAX_ETH1_USE_LEDGRP0 | ||
64 | bool "Use LED grp 0" | ||
65 | depends on ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO | ||
66 | help | ||
67 | Use LED grp 0 for eth1 | ||
52 | 68 | ||
53 | This setting will also affect the behaviour of other activity LEDs | 69 | config ETRAX_ETH1_USE_LEDGRP1 |
54 | e.g. Bluetooth. | 70 | bool "Use LED grp 1" |
71 | depends on ETRAX_NBR_LED_GRP_TWO | ||
72 | help | ||
73 | Use LED grp 1 for eth1 | ||
55 | 74 | ||
75 | config ETRAX_ETH1_USE_LEDGRPNULL | ||
76 | bool "Use no LEDs for eth1" | ||
77 | help | ||
78 | Use no LEDs for eth1 | ||
56 | endchoice | 79 | endchoice |
57 | 80 | ||
58 | config ETRAXFS_SERIAL | 81 | config ETRAXFS_SERIAL |
59 | bool "Serial-port support" | 82 | bool "Serial-port support" |
60 | depends on ETRAX_ARCH_V32 | 83 | depends on ETRAX_ARCH_V32 |
84 | select SERIAL_CORE | ||
85 | select SERIAL_CORE_CONSOLE | ||
61 | help | 86 | help |
62 | Enables the ETRAX FS serial driver for ser0 (ttyS0) | 87 | Enables the ETRAX FS serial driver for ser0 (ttyS0) |
63 | You probably want this enabled. | 88 | You probably want this enabled. |
64 | 89 | ||
90 | config ETRAX_RS485 | ||
91 | bool "RS-485 support" | ||
92 | depends on ETRAXFS_SERIAL | ||
93 | help | ||
94 | Enables support for RS-485 serial communication. | ||
95 | |||
96 | config ETRAX_RS485_DISABLE_RECEIVER | ||
97 | bool "Disable serial receiver" | ||
98 | depends on ETRAX_RS485 | ||
99 | help | ||
100 | It is necessary to disable the serial receiver to avoid serial | ||
101 | loopback. Not all products are able to do this in software only. | ||
102 | |||
65 | config ETRAX_SERIAL_PORT0 | 103 | config ETRAX_SERIAL_PORT0 |
66 | bool "Serial port 0 enabled" | 104 | bool "Serial port 0 enabled" |
67 | depends on ETRAXFS_SERIAL | 105 | depends on ETRAXFS_SERIAL |
@@ -72,50 +110,28 @@ config ETRAX_SERIAL_PORT0 | |||
72 | ser0 can use dma4 or dma6 for output and dma5 or dma7 for input. | 110 | ser0 can use dma4 or dma6 for output and dma5 or dma7 for input. |
73 | 111 | ||
74 | choice | 112 | choice |
75 | prompt "Ser0 DMA in channel " | 113 | prompt "Ser0 default port type " |
76 | depends on ETRAX_SERIAL_PORT0 | 114 | depends on ETRAX_SERIAL_PORT0 |
77 | default ETRAX_SERIAL_PORT0_NO_DMA_IN | 115 | default ETRAX_SERIAL_PORT0_TYPE_232 |
78 | help | 116 | help |
79 | What DMA channel to use for ser0. | 117 | Type of serial port. |
80 | |||
81 | 118 | ||
82 | config ETRAX_SERIAL_PORT0_NO_DMA_IN | 119 | config ETRAX_SERIAL_PORT0_TYPE_232 |
83 | bool "Ser0 uses no DMA for input" | 120 | bool "Ser0 is a RS-232 port" |
84 | help | 121 | help |
85 | Do not use DMA for ser0 input. | 122 | Configure serial port 0 to be a RS-232 port. |
86 | 123 | ||
87 | config ETRAX_SERIAL_PORT0_DMA7_IN | 124 | config ETRAX_SERIAL_PORT0_TYPE_485HD |
88 | bool "Ser0 uses DMA7 for input" | 125 | bool "Ser0 is a half duplex RS-485 port" |
89 | depends on ETRAX_SERIAL_PORT0 | 126 | depends on ETRAX_RS485 |
90 | help | ||
91 | Enables the DMA7 input channel for ser0 (ttyS0). | ||
92 | If you do not enable DMA, an interrupt for each character will be | ||
93 | used when receiving data. | ||
94 | Normally you want to use DMA, unless you use the DMA channel for | ||
95 | something else. | ||
96 | |||
97 | endchoice | ||
98 | |||
99 | choice | ||
100 | prompt "Ser0 DMA out channel" | ||
101 | depends on ETRAX_SERIAL_PORT0 | ||
102 | default ETRAX_SERIAL_PORT0_NO_DMA_OUT | ||
103 | |||
104 | config ETRAX_SERIAL_PORT0_NO_DMA_OUT | ||
105 | bool "Ser0 uses no DMA for output" | ||
106 | help | 127 | help |
107 | Do not use DMA for ser0 output. | 128 | Configure serial port 0 to be a half duplex (two wires) RS-485 port. |
108 | 129 | ||
109 | config ETRAX_SERIAL_PORT0_DMA6_OUT | 130 | config ETRAX_SERIAL_PORT0_TYPE_485FD |
110 | bool "Ser0 uses DMA6 for output" | 131 | bool "Ser0 is a full duplex RS-485 port" |
111 | depends on ETRAX_SERIAL_PORT0 | 132 | depends on ETRAX_RS485 |
112 | help | 133 | help |
113 | Enables the DMA6 output channel for ser0 (ttyS0). | 134 | Configure serial port 0 to be a full duplex (four wires) RS-485 port. |
114 | If you do not enable DMA, an interrupt for each character will be | ||
115 | used when transmitting data. | ||
116 | Normally you want to use DMA, unless you use the DMA channel for | ||
117 | something else. | ||
118 | |||
119 | endchoice | 135 | endchoice |
120 | 136 | ||
121 | config ETRAX_SER0_DTR_BIT | 137 | config ETRAX_SER0_DTR_BIT |
@@ -141,52 +157,28 @@ config ETRAX_SERIAL_PORT1 | |||
141 | Enables the ETRAX FS serial driver for ser1 (ttyS1). | 157 | Enables the ETRAX FS serial driver for ser1 (ttyS1). |
142 | 158 | ||
143 | choice | 159 | choice |
144 | prompt "Ser1 DMA in channel " | 160 | prompt "Ser1 default port type" |
145 | depends on ETRAX_SERIAL_PORT1 | 161 | depends on ETRAX_SERIAL_PORT1 |
146 | default ETRAX_SERIAL_PORT1_NO_DMA_IN | 162 | default ETRAX_SERIAL_PORT1_TYPE_232 |
147 | help | ||
148 | What DMA channel to use for ser1. | ||
149 | |||
150 | |||
151 | config ETRAX_SERIAL_PORT1_NO_DMA_IN | ||
152 | bool "Ser1 uses no DMA for input" | ||
153 | help | 163 | help |
154 | Do not use DMA for ser1 input. | 164 | Type of serial port. |
155 | 165 | ||
156 | config ETRAX_SERIAL_PORT1_DMA5_IN | 166 | config ETRAX_SERIAL_PORT1_TYPE_232 |
157 | bool "Ser1 uses DMA5 for input" | 167 | bool "Ser1 is a RS-232 port" |
158 | depends on ETRAX_SERIAL_PORT1 | ||
159 | help | 168 | help |
160 | Enables the DMA5 input channel for ser1 (ttyS1). | 169 | Configure serial port 1 to be a RS-232 port. |
161 | If you do not enable DMA, an interrupt for each character will be | ||
162 | used when receiving data. | ||
163 | Normally you want this on, unless you use the DMA channel for | ||
164 | something else. | ||
165 | |||
166 | endchoice | ||
167 | 170 | ||
168 | choice | 171 | config ETRAX_SERIAL_PORT1_TYPE_485HD |
169 | prompt "Ser1 DMA out channel " | 172 | bool "Ser1 is a half duplex RS-485 port" |
170 | depends on ETRAX_SERIAL_PORT1 | 173 | depends on ETRAX_RS485 |
171 | default ETRAX_SERIAL_PORT1_NO_DMA_OUT | ||
172 | help | ||
173 | What DMA channel to use for ser1. | ||
174 | |||
175 | config ETRAX_SERIAL_PORT1_NO_DMA_OUT | ||
176 | bool "Ser1 uses no DMA for output" | ||
177 | help | 174 | help |
178 | Do not use DMA for ser1 output. | 175 | Configure serial port 1 to be a half duplex (two wires) RS-485 port. |
179 | 176 | ||
180 | config ETRAX_SERIAL_PORT1_DMA4_OUT | 177 | config ETRAX_SERIAL_PORT1_TYPE_485FD |
181 | bool "Ser1 uses DMA4 for output" | 178 | bool "Ser1 is a full duplex RS-485 port" |
182 | depends on ETRAX_SERIAL_PORT1 | 179 | depends on ETRAX_RS485 |
183 | help | 180 | help |
184 | Enables the DMA4 output channel for ser1 (ttyS1). | 181 | Configure serial port 1 to be a full duplex (four wires) RS-485 port. |
185 | If you do not enable DMA, an interrupt for each character will be | ||
186 | used when transmitting data. | ||
187 | Normally you want this on, unless you use the DMA channel for | ||
188 | something else. | ||
189 | |||
190 | endchoice | 182 | endchoice |
191 | 183 | ||
192 | config ETRAX_SER1_DTR_BIT | 184 | config ETRAX_SER1_DTR_BIT |
@@ -212,52 +204,31 @@ config ETRAX_SERIAL_PORT2 | |||
212 | Enables the ETRAX FS serial driver for ser2 (ttyS2). | 204 | Enables the ETRAX FS serial driver for ser2 (ttyS2). |
213 | 205 | ||
214 | choice | 206 | choice |
215 | prompt "Ser2 DMA in channel " | 207 | prompt "Ser2 default port type" |
216 | depends on ETRAX_SERIAL_PORT2 | 208 | depends on ETRAX_SERIAL_PORT2 |
217 | default ETRAX_SERIAL_PORT2_NO_DMA_IN | 209 | default ETRAX_SERIAL_PORT2_TYPE_232 |
218 | help | 210 | help |
219 | What DMA channel to use for ser2. | 211 | What DMA channel to use for ser2 |
220 | 212 | ||
221 | 213 | config ETRAX_SERIAL_PORT2_TYPE_232 | |
222 | config ETRAX_SERIAL_PORT2_NO_DMA_IN | 214 | bool "Ser2 is a RS-232 port" |
223 | bool "Ser2 uses no DMA for input" | ||
224 | help | 215 | help |
225 | Do not use DMA for ser2 input. | 216 | Configure serial port 2 to be a RS-232 port. |
226 | 217 | ||
227 | config ETRAX_SERIAL_PORT2_DMA3_IN | 218 | config ETRAX_SERIAL_PORT2_TYPE_485HD |
228 | bool "Ser2 uses DMA3 for input" | 219 | bool "Ser2 is a half duplex RS-485 port" |
229 | depends on ETRAX_SERIAL_PORT2 | 220 | depends on ETRAX_RS485 |
230 | help | ||
231 | Enables the DMA3 input channel for ser2 (ttyS2). | ||
232 | If you do not enable DMA, an interrupt for each character will be | ||
233 | used when receiving data. | ||
234 | Normally you want to use DMA, unless you use the DMA channel for | ||
235 | something else. | ||
236 | |||
237 | endchoice | ||
238 | |||
239 | choice | ||
240 | prompt "Ser2 DMA out channel" | ||
241 | depends on ETRAX_SERIAL_PORT2 | ||
242 | default ETRAX_SERIAL_PORT2_NO_DMA_OUT | ||
243 | |||
244 | config ETRAX_SERIAL_PORT2_NO_DMA_OUT | ||
245 | bool "Ser2 uses no DMA for output" | ||
246 | help | 221 | help |
247 | Do not use DMA for ser2 output. | 222 | Configure serial port 2 to be a half duplex (two wires) RS-485 port. |
248 | 223 | ||
249 | config ETRAX_SERIAL_PORT2_DMA2_OUT | 224 | config ETRAX_SERIAL_PORT2_TYPE_485FD |
250 | bool "Ser2 uses DMA2 for output" | 225 | bool "Ser2 is a full duplex RS-485 port" |
251 | depends on ETRAX_SERIAL_PORT2 | 226 | depends on ETRAX_RS485 |
252 | help | 227 | help |
253 | Enables the DMA2 output channel for ser2 (ttyS2). | 228 | Configure serial port 2 to be a full duplex (four wires) RS-485 port. |
254 | If you do not enable DMA, an interrupt for each character will be | ||
255 | used when transmitting data. | ||
256 | Normally you want to use DMA, unless you use the DMA channel for | ||
257 | something else. | ||
258 | |||
259 | endchoice | 229 | endchoice |
260 | 230 | ||
231 | |||
261 | config ETRAX_SER2_DTR_BIT | 232 | config ETRAX_SER2_DTR_BIT |
262 | string "Ser 2 DTR bit (empty = not used)" | 233 | string "Ser 2 DTR bit (empty = not used)" |
263 | depends on ETRAX_SERIAL_PORT2 | 234 | depends on ETRAX_SERIAL_PORT2 |
@@ -281,71 +252,121 @@ config ETRAX_SERIAL_PORT3 | |||
281 | Enables the ETRAX FS serial driver for ser3 (ttyS3). | 252 | Enables the ETRAX FS serial driver for ser3 (ttyS3). |
282 | 253 | ||
283 | choice | 254 | choice |
284 | prompt "Ser3 DMA in channel " | 255 | prompt "Ser3 default port type" |
285 | depends on ETRAX_SERIAL_PORT3 | 256 | depends on ETRAX_SERIAL_PORT3 |
286 | default ETRAX_SERIAL_PORT3_NO_DMA_IN | 257 | default ETRAX_SERIAL_PORT3_TYPE_232 |
287 | help | 258 | help |
288 | What DMA channel to use for ser3. | 259 | What DMA channel to use for ser3. |
289 | 260 | ||
261 | config ETRAX_SERIAL_PORT3_TYPE_232 | ||
262 | bool "Ser3 is a RS-232 port" | ||
263 | help | ||
264 | Configure serial port 3 to be a RS-232 port. | ||
290 | 265 | ||
291 | config ETRAX_SERIAL_PORT3_NO_DMA_IN | 266 | config ETRAX_SERIAL_PORT3_TYPE_485HD |
292 | bool "Ser3 uses no DMA for input" | 267 | bool "Ser3 is a half duplex RS-485 port" |
268 | depends on ETRAX_RS485 | ||
293 | help | 269 | help |
294 | Do not use DMA for ser3 input. | 270 | Configure serial port 3 to be a half duplex (two wires) RS-485 port. |
295 | 271 | ||
296 | config ETRAX_SERIAL_PORT3_DMA9_IN | 272 | config ETRAX_SERIAL_PORT3_TYPE_485FD |
297 | bool "Ser3 uses DMA9 for input" | 273 | bool "Ser3 is a full duplex RS-485 port" |
274 | depends on ETRAX_RS485 | ||
275 | help | ||
276 | Configure serial port 3 to be a full duplex (four wires) RS-485 port. | ||
277 | endchoice | ||
278 | |||
279 | config ETRAX_SER3_DTR_BIT | ||
280 | string "Ser 3 DTR bit (empty = not used)" | ||
281 | depends on ETRAX_SERIAL_PORT3 | ||
282 | |||
283 | config ETRAX_SER3_RI_BIT | ||
284 | string "Ser 3 RI bit (empty = not used)" | ||
285 | depends on ETRAX_SERIAL_PORT3 | ||
286 | |||
287 | config ETRAX_SER3_DSR_BIT | ||
288 | string "Ser 3 DSR bit (empty = not used)" | ||
289 | depends on ETRAX_SERIAL_PORT3 | ||
290 | |||
291 | config ETRAX_SER3_CD_BIT | ||
292 | string "Ser 3 CD bit (empty = not used)" | ||
298 | depends on ETRAX_SERIAL_PORT3 | 293 | depends on ETRAX_SERIAL_PORT3 |
294 | |||
295 | config ETRAX_SERIAL_PORT4 | ||
296 | bool "Serial port 4 enabled" | ||
297 | depends on ETRAXFS_SERIAL && CRIS_MACH_ARTPEC3 | ||
299 | help | 298 | help |
300 | Enables the DMA9 input channel for ser3 (ttyS3). | 299 | Enables the ETRAX FS serial driver for ser4 (ttyS4). |
301 | If you do not enable DMA, an interrupt for each character will be | 300 | |
302 | used when receiving data. | 301 | choice |
303 | Normally you want to use DMA, unless you use the DMA channel for | 302 | prompt "Ser4 default port type" |
304 | something else. | 303 | depends on ETRAX_SERIAL_PORT4 |
304 | default ETRAX_SERIAL_PORT4_TYPE_232 | ||
305 | help | ||
306 | What DMA channel to use for ser4. | ||
305 | 307 | ||
308 | config ETRAX_SERIAL_PORT4_TYPE_232 | ||
309 | bool "Ser4 is a RS-232 port" | ||
310 | help | ||
311 | Configure serial port 4 to be a RS-232 port. | ||
312 | |||
313 | config ETRAX_SERIAL_PORT4_TYPE_485HD | ||
314 | bool "Ser4 is a half duplex RS-485 port" | ||
315 | depends on ETRAX_RS485 | ||
316 | help | ||
317 | Configure serial port 4 to be a half duplex (two wires) RS-485 port. | ||
318 | |||
319 | config ETRAX_SERIAL_PORT4_TYPE_485FD | ||
320 | bool "Ser4 is a full duplex RS-485 port" | ||
321 | depends on ETRAX_RS485 | ||
322 | help | ||
323 | Configure serial port 4 to be a full duplex (four wires) RS-485 port. | ||
306 | endchoice | 324 | endchoice |
307 | 325 | ||
308 | choice | 326 | choice |
309 | prompt "Ser3 DMA out channel" | 327 | prompt "Ser4 DMA in channel " |
310 | depends on ETRAX_SERIAL_PORT3 | 328 | depends on ETRAX_SERIAL_PORT4 |
311 | default ETRAX_SERIAL_PORT3_NO_DMA_OUT | 329 | default ETRAX_SERIAL_PORT4_NO_DMA_IN |
330 | help | ||
331 | What DMA channel to use for ser4. | ||
332 | |||
312 | 333 | ||
313 | config ETRAX_SERIAL_PORT3_NO_DMA_OUT | 334 | config ETRAX_SERIAL_PORT4_NO_DMA_IN |
314 | bool "Ser3 uses no DMA for output" | 335 | bool "Ser4 uses no DMA for input" |
315 | help | 336 | help |
316 | Do not use DMA for ser3 output. | 337 | Do not use DMA for ser4 input. |
317 | 338 | ||
318 | config ETRAX_SERIAL_PORT3_DMA8_OUT | 339 | config ETRAX_SERIAL_PORT4_DMA9_IN |
319 | bool "Ser3 uses DMA8 for output" | 340 | bool "Ser4 uses DMA9 for input" |
320 | depends on ETRAX_SERIAL_PORT3 | 341 | depends on ETRAX_SERIAL_PORT4 |
321 | help | 342 | help |
322 | Enables the DMA8 output channel for ser3 (ttyS3). | 343 | Enables the DMA9 input channel for ser4 (ttyS4). |
323 | If you do not enable DMA, an interrupt for each character will be | 344 | If you do not enable DMA, an interrupt for each character will be |
324 | used when transmitting data. | 345 | used when receiveing data. |
325 | Normally you want to use DMA, unless you use the DMA channel for | 346 | Normally you want to use DMA, unless you use the DMA channel for |
326 | something else. | 347 | something else. |
327 | 348 | ||
328 | endchoice | 349 | endchoice |
329 | 350 | ||
330 | config ETRAX_SER3_DTR_BIT | 351 | config ETRAX_SER4_DTR_BIT |
331 | string "Ser 3 DTR bit (empty = not used)" | 352 | string "Ser 4 DTR bit (empty = not used)" |
332 | depends on ETRAX_SERIAL_PORT3 | 353 | depends on ETRAX_SERIAL_PORT4 |
333 | 354 | ||
334 | config ETRAX_SER3_RI_BIT | 355 | config ETRAX_SER4_RI_BIT |
335 | string "Ser 3 RI bit (empty = not used)" | 356 | string "Ser 4 RI bit (empty = not used)" |
336 | depends on ETRAX_SERIAL_PORT3 | 357 | depends on ETRAX_SERIAL_PORT4 |
337 | 358 | ||
338 | config ETRAX_SER3_DSR_BIT | 359 | config ETRAX_SER4_DSR_BIT |
339 | string "Ser 3 DSR bit (empty = not used)" | 360 | string "Ser 4 DSR bit (empty = not used)" |
340 | depends on ETRAX_SERIAL_PORT3 | 361 | depends on ETRAX_SERIAL_PORT4 |
341 | 362 | ||
342 | config ETRAX_SER3_CD_BIT | 363 | config ETRAX_SER3_CD_BIT |
343 | string "Ser 3 CD bit (empty = not used)" | 364 | string "Ser 4 CD bit (empty = not used)" |
344 | depends on ETRAX_SERIAL_PORT3 | 365 | depends on ETRAX_SERIAL_PORT4 |
345 | 366 | ||
346 | config ETRAX_RS485 | 367 | config ETRAX_RS485 |
347 | bool "RS-485 support" | 368 | bool "RS-485 support" |
348 | depends on ETRAX_SERIAL | 369 | depends on ETRAXFS_SERIAL |
349 | help | 370 | help |
350 | Enables support for RS-485 serial communication. For a primer on | 371 | Enables support for RS-485 serial communication. For a primer on |
351 | RS-485, see <http://www.hw.cz/english/docs/rs485/rs485.html>. | 372 | RS-485, see <http://www.hw.cz/english/docs/rs485/rs485.html>. |
@@ -356,22 +377,6 @@ config ETRAX_RS485_DISABLE_RECEIVER | |||
356 | help | 377 | help |
357 | It is necessary to disable the serial receiver to avoid serial | 378 | It is necessary to disable the serial receiver to avoid serial |
358 | loopback. Not all products are able to do this in software only. | 379 | loopback. Not all products are able to do this in software only. |
359 | Axis 2400/2401 must disable receiver. | ||
360 | |||
361 | config ETRAX_AXISFLASHMAP | ||
362 | bool "Axis flash-map support" | ||
363 | depends on ETRAX_ARCH_V32 | ||
364 | select MTD | ||
365 | select MTD_CFI | ||
366 | select MTD_CFI_AMDSTD | ||
367 | select MTD_CHAR | ||
368 | select MTD_BLOCK | ||
369 | select MTD_PARTITIONS | ||
370 | select MTD_CONCAT | ||
371 | select MTD_COMPLEX_MAPPINGS | ||
372 | help | ||
373 | This option enables MTD mapping of flash devices. Needed to use | ||
374 | flash memories. If unsure, say Y. | ||
375 | 380 | ||
376 | config ETRAX_SYNCHRONOUS_SERIAL | 381 | config ETRAX_SYNCHRONOUS_SERIAL |
377 | bool "Synchronous serial-port support" | 382 | bool "Synchronous serial-port support" |
@@ -394,7 +399,7 @@ config ETRAX_SYNCHRONOUS_SERIAL0_DMA | |||
394 | 399 | ||
395 | config ETRAX_SYNCHRONOUS_SERIAL_PORT1 | 400 | config ETRAX_SYNCHRONOUS_SERIAL_PORT1 |
396 | bool "Synchronous serial port 1 enabled" | 401 | bool "Synchronous serial port 1 enabled" |
397 | depends on ETRAX_SYNCHRONOUS_SERIAL | 402 | depends on ETRAX_SYNCHRONOUS_SERIAL && ETRAXFS |
398 | help | 403 | help |
399 | Enabled synchronous serial port 1. | 404 | Enabled synchronous serial port 1. |
400 | 405 | ||
@@ -405,6 +410,31 @@ config ETRAX_SYNCHRONOUS_SERIAL1_DMA | |||
405 | A synchronous serial port can run in manual or DMA mode. | 410 | A synchronous serial port can run in manual or DMA mode. |
406 | Selecting this option will make it run in DMA mode. | 411 | Selecting this option will make it run in DMA mode. |
407 | 412 | ||
413 | config ETRAX_AXISFLASHMAP | ||
414 | bool "Axis flash-map support" | ||
415 | depends on ETRAX_ARCH_V32 | ||
416 | select MTD | ||
417 | select MTD_CFI | ||
418 | select MTD_CFI_AMDSTD | ||
419 | select MTD_JEDECPROBE | ||
420 | select MTD_CHAR | ||
421 | select MTD_BLOCK | ||
422 | select MTD_PARTITIONS | ||
423 | select MTD_CONCAT | ||
424 | select MTD_COMPLEX_MAPPINGS | ||
425 | help | ||
426 | This option enables MTD mapping of flash devices. Needed to use | ||
427 | flash memories. If unsure, say Y. | ||
428 | |||
429 | config ETRAX_AXISFLASHMAP_MTD0WHOLE | ||
430 | bool "MTD0 is whole boot flash device" | ||
431 | depends on ETRAX_AXISFLASHMAP | ||
432 | default N | ||
433 | help | ||
434 | When this option is not set, mtd0 refers to the first partition | ||
435 | on the boot flash device. When set, mtd0 refers to the whole | ||
436 | device, with mtd1 referring to the first partition etc. | ||
437 | |||
408 | config ETRAX_PTABLE_SECTOR | 438 | config ETRAX_PTABLE_SECTOR |
409 | int "Byte-offset of partition table sector" | 439 | int "Byte-offset of partition table sector" |
410 | depends on ETRAX_AXISFLASHMAP | 440 | depends on ETRAX_AXISFLASHMAP |
@@ -425,42 +455,32 @@ config ETRAX_NANDFLASH | |||
425 | This option enables MTD mapping of NAND flash devices. Needed to use | 455 | This option enables MTD mapping of NAND flash devices. Needed to use |
426 | NAND flash memories. If unsure, say Y. | 456 | NAND flash memories. If unsure, say Y. |
427 | 457 | ||
458 | config ETRAX_NANDBOOT | ||
459 | bool "Boot from NAND flash" | ||
460 | depends on ETRAX_NANDFLASH | ||
461 | help | ||
462 | This options enables booting from NAND flash devices. | ||
463 | Say Y if your boot code, kernel and root file system is in | ||
464 | NAND flash. Say N if they are in NOR flash. | ||
465 | |||
428 | config ETRAX_I2C | 466 | config ETRAX_I2C |
429 | bool "I2C driver" | 467 | bool "I2C driver" |
430 | depends on ETRAX_ARCH_V32 | 468 | depends on ETRAX_ARCH_V32 |
431 | help | 469 | help |
432 | This option enabled the I2C driver used by e.g. the RTC driver. | 470 | This option enables the I2C driver used by e.g. the RTC driver. |
433 | 471 | ||
434 | config ETRAX_I2C_DATA_PORT | 472 | config ETRAX_V32_I2C_DATA_PORT |
435 | string "I2C data pin" | 473 | string "I2C data pin" |
436 | depends on ETRAX_I2C | 474 | depends on ETRAX_I2C |
437 | help | 475 | help |
438 | The pin to use for I2C data. | 476 | The pin to use for I2C data. |
439 | 477 | ||
440 | config ETRAX_I2C_CLK_PORT | 478 | config ETRAX_V32_I2C_CLK_PORT |
441 | string "I2C clock pin" | 479 | string "I2C clock pin" |
442 | depends on ETRAX_I2C | 480 | depends on ETRAX_I2C |
443 | help | 481 | help |
444 | The pin to use for I2C clock. | 482 | The pin to use for I2C clock. |
445 | 483 | ||
446 | config ETRAX_RTC | ||
447 | bool "Real Time Clock support" | ||
448 | depends on ETRAX_ARCH_V32 | ||
449 | help | ||
450 | Enabled RTC support. | ||
451 | |||
452 | choice | ||
453 | prompt "RTC chip" | ||
454 | depends on ETRAX_RTC | ||
455 | default ETRAX_PCF8563 | ||
456 | |||
457 | config ETRAX_PCF8563 | ||
458 | bool "PCF8563" | ||
459 | help | ||
460 | Philips PCF8563 RTC | ||
461 | |||
462 | endchoice | ||
463 | |||
464 | config ETRAX_GPIO | 484 | config ETRAX_GPIO |
465 | bool "GPIO support" | 485 | bool "GPIO support" |
466 | depends on ETRAX_ARCH_V32 | 486 | depends on ETRAX_ARCH_V32 |
@@ -476,33 +496,36 @@ config ETRAX_GPIO | |||
476 | Remember that you need to setup the port directions appropriately in | 496 | Remember that you need to setup the port directions appropriately in |
477 | the General configuration. | 497 | the General configuration. |
478 | 498 | ||
479 | config ETRAX_PA_BUTTON_BITMASK | 499 | config ETRAX_VIRTUAL_GPIO |
480 | hex "PA-buttons bitmask" | 500 | bool "Virtual GPIO support" |
481 | depends on ETRAX_GPIO | 501 | depends on ETRAX_GPIO |
482 | default "0x02" | ||
483 | help | 502 | help |
484 | This is a bitmask (8 bits) with information about what bits on PA | 503 | Enables the virtual Etrax general port device (major 120, minor 6). |
485 | that are used for buttons. | 504 | It uses an I/O expander for the I2C-bus. |
486 | Most products has a so called TEST button on PA1, if that is true | 505 | |
487 | use 0x02 here. | 506 | config ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN |
488 | Use 00 if there are no buttons on PA. | 507 | int "Virtual GPIO interrupt pin on PA pin" |
489 | If the bitmask is <> 00 a button driver will be included in the gpio | 508 | range 0 7 |
490 | driver. ETRAX general I/O support must be enabled. | 509 | depends on ETRAX_VIRTUAL_GPIO |
510 | help | ||
511 | The pin to use on PA for virtual gpio interrupt. | ||
491 | 512 | ||
492 | config ETRAX_PA_CHANGEABLE_DIR | 513 | config ETRAX_PA_CHANGEABLE_DIR |
493 | hex "PA user changeable dir mask" | 514 | hex "PA user changeable dir mask" |
494 | depends on ETRAX_GPIO | 515 | depends on ETRAX_GPIO |
495 | default "0x00" | 516 | default "0x00" if ETRAXFS |
517 | default "0x00000000" if !ETRAXFS | ||
496 | help | 518 | help |
497 | This is a bitmask (8 bits) with information of what bits in PA that a | 519 | This is a bitmask (8 bits) with information of what bits in PA that a |
498 | user can change direction on using ioctl's. | 520 | user can change direction on using ioctl's. |
499 | Bit set = changeable. | 521 | Bit set = changeable. |
500 | You probably want 0x00 here, but it depends on your hardware. | 522 | You probably want 0 here, but it depends on your hardware. |
501 | 523 | ||
502 | config ETRAX_PA_CHANGEABLE_BITS | 524 | config ETRAX_PA_CHANGEABLE_BITS |
503 | hex "PA user changeable bits mask" | 525 | hex "PA user changeable bits mask" |
504 | depends on ETRAX_GPIO | 526 | depends on ETRAX_GPIO |
505 | default "0x00" | 527 | default "0x00" if ETRAXFS |
528 | default "0x00000000" if !ETRAXFS | ||
506 | help | 529 | help |
507 | This is a bitmask (8 bits) with information of what bits in PA | 530 | This is a bitmask (8 bits) with information of what bits in PA |
508 | that a user can change the value on using ioctl's. | 531 | that a user can change the value on using ioctl's. |
@@ -511,17 +534,19 @@ config ETRAX_PA_CHANGEABLE_BITS | |||
511 | config ETRAX_PB_CHANGEABLE_DIR | 534 | config ETRAX_PB_CHANGEABLE_DIR |
512 | hex "PB user changeable dir mask" | 535 | hex "PB user changeable dir mask" |
513 | depends on ETRAX_GPIO | 536 | depends on ETRAX_GPIO |
514 | default "0x00000" | 537 | default "0x00000" if ETRAXFS |
538 | default "0x00000000" if !ETRAXFS | ||
515 | help | 539 | help |
516 | This is a bitmask (18 bits) with information of what bits in PB | 540 | This is a bitmask (18 bits) with information of what bits in PB |
517 | that a user can change direction on using ioctl's. | 541 | that a user can change direction on using ioctl's. |
518 | Bit set = changeable. | 542 | Bit set = changeable. |
519 | You probably want 0x00000 here, but it depends on your hardware. | 543 | You probably want 0 here, but it depends on your hardware. |
520 | 544 | ||
521 | config ETRAX_PB_CHANGEABLE_BITS | 545 | config ETRAX_PB_CHANGEABLE_BITS |
522 | hex "PB user changeable bits mask" | 546 | hex "PB user changeable bits mask" |
523 | depends on ETRAX_GPIO | 547 | depends on ETRAX_GPIO |
524 | default "0x00000" | 548 | default "0x00000" if ETRAXFS |
549 | default "0x00000000" if !ETRAXFS | ||
525 | help | 550 | help |
526 | This is a bitmask (18 bits) with information of what bits in PB | 551 | This is a bitmask (18 bits) with information of what bits in PB |
527 | that a user can change the value on using ioctl's. | 552 | that a user can change the value on using ioctl's. |
@@ -530,17 +555,19 @@ config ETRAX_PB_CHANGEABLE_BITS | |||
530 | config ETRAX_PC_CHANGEABLE_DIR | 555 | config ETRAX_PC_CHANGEABLE_DIR |
531 | hex "PC user changeable dir mask" | 556 | hex "PC user changeable dir mask" |
532 | depends on ETRAX_GPIO | 557 | depends on ETRAX_GPIO |
533 | default "0x00000" | 558 | default "0x00000" if ETRAXFS |
559 | default "0x00000000" if !ETRAXFS | ||
534 | help | 560 | help |
535 | This is a bitmask (18 bits) with information of what bits in PC | 561 | This is a bitmask (18 bits) with information of what bits in PC |
536 | that a user can change direction on using ioctl's. | 562 | that a user can change direction on using ioctl's. |
537 | Bit set = changeable. | 563 | Bit set = changeable. |
538 | You probably want 0x00000 here, but it depends on your hardware. | 564 | You probably want 0 here, but it depends on your hardware. |
539 | 565 | ||
540 | config ETRAX_PC_CHANGEABLE_BITS | 566 | config ETRAX_PC_CHANGEABLE_BITS |
541 | hex "PC user changeable bits mask" | 567 | hex "PC user changeable bits mask" |
542 | depends on ETRAX_GPIO | 568 | depends on ETRAX_GPIO |
543 | default "0x00000" | 569 | default "0x00000" if ETRAXFS |
570 | default "0x00000000" if ETRAXFS | ||
544 | help | 571 | help |
545 | This is a bitmask (18 bits) with information of what bits in PC | 572 | This is a bitmask (18 bits) with information of what bits in PC |
546 | that a user can change the value on using ioctl's. | 573 | that a user can change the value on using ioctl's. |
@@ -548,7 +575,7 @@ config ETRAX_PC_CHANGEABLE_BITS | |||
548 | 575 | ||
549 | config ETRAX_PD_CHANGEABLE_DIR | 576 | config ETRAX_PD_CHANGEABLE_DIR |
550 | hex "PD user changeable dir mask" | 577 | hex "PD user changeable dir mask" |
551 | depends on ETRAX_GPIO | 578 | depends on ETRAX_GPIO && ETRAXFS |
552 | default "0x00000" | 579 | default "0x00000" |
553 | help | 580 | help |
554 | This is a bitmask (18 bits) with information of what bits in PD | 581 | This is a bitmask (18 bits) with information of what bits in PD |
@@ -558,7 +585,7 @@ config ETRAX_PD_CHANGEABLE_DIR | |||
558 | 585 | ||
559 | config ETRAX_PD_CHANGEABLE_BITS | 586 | config ETRAX_PD_CHANGEABLE_BITS |
560 | hex "PD user changeable bits mask" | 587 | hex "PD user changeable bits mask" |
561 | depends on ETRAX_GPIO | 588 | depends on ETRAX_GPIO && ETRAXFS |
562 | default "0x00000" | 589 | default "0x00000" |
563 | help | 590 | help |
564 | This is a bitmask (18 bits) with information of what bits in PD | 591 | This is a bitmask (18 bits) with information of what bits in PD |
@@ -567,7 +594,7 @@ config ETRAX_PD_CHANGEABLE_BITS | |||
567 | 594 | ||
568 | config ETRAX_PE_CHANGEABLE_DIR | 595 | config ETRAX_PE_CHANGEABLE_DIR |
569 | hex "PE user changeable dir mask" | 596 | hex "PE user changeable dir mask" |
570 | depends on ETRAX_GPIO | 597 | depends on ETRAX_GPIO && ETRAXFS |
571 | default "0x00000" | 598 | default "0x00000" |
572 | help | 599 | help |
573 | This is a bitmask (18 bits) with information of what bits in PE | 600 | This is a bitmask (18 bits) with information of what bits in PE |
@@ -577,20 +604,36 @@ config ETRAX_PE_CHANGEABLE_DIR | |||
577 | 604 | ||
578 | config ETRAX_PE_CHANGEABLE_BITS | 605 | config ETRAX_PE_CHANGEABLE_BITS |
579 | hex "PE user changeable bits mask" | 606 | hex "PE user changeable bits mask" |
580 | depends on ETRAX_GPIO | 607 | depends on ETRAX_GPIO && ETRAXFS |
581 | default "0x00000" | 608 | default "0x00000" |
582 | help | 609 | help |
583 | This is a bitmask (18 bits) with information of what bits in PE | 610 | This is a bitmask (18 bits) with information of what bits in PE |
584 | that a user can change the value on using ioctl's. | 611 | that a user can change the value on using ioctl's. |
585 | Bit set = changeable. | 612 | Bit set = changeable. |
586 | 613 | ||
614 | config ETRAX_PV_CHANGEABLE_DIR | ||
615 | hex "PV user changeable dir mask" | ||
616 | depends on ETRAX_VIRTUAL_GPIO | ||
617 | default "0x0000" | ||
618 | help | ||
619 | This is a bitmask (16 bits) with information of what bits in PV | ||
620 | that a user can change direction on using ioctl's. | ||
621 | Bit set = changeable. | ||
622 | You probably want 0x0000 here, but it depends on your hardware. | ||
623 | |||
624 | config ETRAX_PV_CHANGEABLE_BITS | ||
625 | hex "PV user changeable bits mask" | ||
626 | depends on ETRAX_VIRTUAL_GPIO | ||
627 | default "0x0000" | ||
628 | help | ||
629 | This is a bitmask (16 bits) with information of what bits in PV | ||
630 | that a user can change the value on using ioctl's. | ||
631 | Bit set = changeable. | ||
632 | |||
587 | config ETRAX_CARDBUS | 633 | config ETRAX_CARDBUS |
588 | bool "Cardbus support" | 634 | bool "Cardbus support" |
589 | depends on ETRAX_ARCH_V32 | 635 | depends on ETRAX_ARCH_V32 |
590 | select PCCARD | ||
591 | select CARDBUS | ||
592 | select HOTPLUG | 636 | select HOTPLUG |
593 | select PCCARD_NONSTATIC | ||
594 | help | 637 | help |
595 | Enabled the ETRAX Cardbus driver. | 638 | Enabled the ETRAX Cardbus driver. |
596 | 639 | ||
@@ -613,4 +656,202 @@ config ETRAX_STREAMCOPROC | |||
613 | This option enables a driver for the stream co-processor | 656 | This option enables a driver for the stream co-processor |
614 | for cryptographic operations. | 657 | for cryptographic operations. |
615 | 658 | ||
659 | source drivers/mmc/Kconfig | ||
660 | |||
661 | config ETRAX_MMC_IOP | ||
662 | tristate "MMC/SD host driver using IO-processor" | ||
663 | depends on ETRAX_ARCH_V32 && MMC | ||
664 | help | ||
665 | This option enables the SD/MMC host controller interface. | ||
666 | The host controller is implemented using the built in | ||
667 | IO-Processor. Only the SPU is used in this implementation. | ||
668 | |||
669 | config ETRAX_SPI_MMC | ||
670 | # Make this one of several "choices" (possible simultaneously but | ||
671 | # suggested uniquely) when an IOP driver emerges for "real" MMC/SD | ||
672 | # protocol support. | ||
673 | tristate | ||
674 | depends on !ETRAX_MMC_IOP | ||
675 | default MMC | ||
676 | select SPI | ||
677 | select MMC_SPI | ||
678 | select ETRAX_SPI_MMC_BOARD | ||
679 | |||
680 | # For the parts that can't be a module (due to restrictions in | ||
681 | # framework elsewhere). | ||
682 | config ETRAX_SPI_MMC_BOARD | ||
683 | boolean | ||
684 | default n | ||
685 | |||
686 | # While the board info is MMC_SPI only, the drivers are written to be | ||
687 | # independent of MMC_SPI, so we'll keep SPI non-dependent on the | ||
688 | # MMC_SPI config choices (well, except for a single depends-on-line | ||
689 | # for the board-info file until a separate non-MMC SPI board file | ||
690 | # emerges). | ||
691 | # FIXME: When that happens, we'll need to be able to ask for and | ||
692 | # configure non-MMC SPI ports together with MMC_SPI ports (if multiple | ||
693 | # SPI ports are enabled). | ||
694 | |||
695 | config SPI_ETRAX_SSER | ||
696 | tristate | ||
697 | depends on SPI_MASTER && ETRAX_ARCH_V32 && EXPERIMENTAL | ||
698 | select SPI_BITBANG | ||
699 | help | ||
700 | This enables using an synchronous serial (sser) port as a | ||
701 | SPI master controller on Axis ETRAX FS and later. The | ||
702 | driver can be configured to use any sser port. | ||
703 | |||
704 | config SPI_ETRAX_GPIO | ||
705 | tristate | ||
706 | depends on SPI_MASTER && ETRAX_ARCH_V32 && EXPERIMENTAL | ||
707 | select SPI_BITBANG | ||
708 | help | ||
709 | This enables using GPIO pins port as a SPI master controller | ||
710 | on Axis ETRAX FS and later. The driver can be configured to | ||
711 | use any GPIO pins. | ||
712 | |||
713 | config ETRAX_SPI_SSER0 | ||
714 | tristate "SPI using synchronous serial port 0 (sser0)" | ||
715 | depends on ETRAX_SPI_MMC | ||
716 | default m if MMC_SPI=m | ||
717 | default y if MMC_SPI=y | ||
718 | default y if MMC_SPI=n | ||
719 | select SPI_ETRAX_SSER | ||
720 | help | ||
721 | Say Y for an MMC/SD socket connected to synchronous serial port 0, | ||
722 | or for devices using the SPI protocol on that port. Say m if you | ||
723 | want to build it as a module, which will be named spi_crisv32_sser. | ||
724 | (You need to select MMC separately.) | ||
725 | |||
726 | config ETRAX_SPI_SSER0_DMA | ||
727 | bool "DMA for SPI on sser0 enabled" | ||
728 | depends on ETRAX_SPI_SSER0 | ||
729 | depends on !ETRAX_SERIAL_PORT1_DMA4_OUT && !ETRAX_SERIAL_PORT1_DMA5_IN | ||
730 | default y | ||
731 | help | ||
732 | Say Y if using DMA (dma4/dma5) for SPI on synchronous serial port 0. | ||
733 | |||
734 | config ETRAX_SPI_MMC_CD_SSER0_PIN | ||
735 | string "MMC/SD card detect pin for SPI on sser0" | ||
736 | depends on ETRAX_SPI_SSER0 && MMC_SPI | ||
737 | default "pd11" | ||
738 | help | ||
739 | The pin to use for SD/MMC card detect. This pin should be pulled up | ||
740 | and grounded when a card is present. If defined as " " (space), no | ||
741 | pin is selected. A card must then always be inserted for proper | ||
742 | action. | ||
743 | |||
744 | config ETRAX_SPI_MMC_WP_SSER0_PIN | ||
745 | string "MMC/SD card write-protect pin for SPI on sser0" | ||
746 | depends on ETRAX_SPI_SSER0 && MMC_SPI | ||
747 | default "pd10" | ||
748 | help | ||
749 | The pin to use for the SD/MMC write-protect signal for a memory | ||
750 | card. If defined as " " (space), the card is considered writable. | ||
751 | |||
752 | config ETRAX_SPI_SSER1 | ||
753 | tristate "SPI using synchronous serial port 1 (sser1)" | ||
754 | depends on ETRAX_SPI_MMC | ||
755 | default m if MMC_SPI=m && ETRAX_SPI_SSER0=n | ||
756 | default y if MMC_SPI=y && ETRAX_SPI_SSER0=n | ||
757 | default y if MMC_SPI=n && ETRAX_SPI_SSER0=n | ||
758 | select SPI_ETRAX_SSER | ||
759 | help | ||
760 | Say Y for an MMC/SD socket connected to synchronous serial port 1, | ||
761 | or for devices using the SPI protocol on that port. Say m if you | ||
762 | want to build it as a module, which will be named spi_crisv32_sser. | ||
763 | (You need to select MMC separately.) | ||
764 | |||
765 | config ETRAX_SPI_SSER1_DMA | ||
766 | bool "DMA for SPI on sser1 enabled" | ||
767 | depends on ETRAX_SPI_SSER1 && !ETRAX_ETHERNET_IFACE1 | ||
768 | depends on !ETRAX_SERIAL_PORT0_DMA6_OUT && !ETRAX_SERIAL_PORT0_DMA7_IN | ||
769 | default y | ||
770 | help | ||
771 | Say Y if using DMA (dma6/dma7) for SPI on synchronous serial port 1. | ||
772 | |||
773 | config ETRAX_SPI_MMC_CD_SSER1_PIN | ||
774 | string "MMC/SD card detect pin for SPI on sser1" | ||
775 | depends on ETRAX_SPI_SSER1 && MMC_SPI | ||
776 | default "pd12" | ||
777 | help | ||
778 | The pin to use for SD/MMC card detect. This pin should be pulled up | ||
779 | and grounded when a card is present. If defined as " " (space), no | ||
780 | pin is selected. A card must then always be inserted for proper | ||
781 | action. | ||
782 | |||
783 | config ETRAX_SPI_MMC_WP_SSER1_PIN | ||
784 | string "MMC/SD card write-protect pin for SPI on sser1" | ||
785 | depends on ETRAX_SPI_SSER1 && MMC_SPI | ||
786 | default "pd9" | ||
787 | help | ||
788 | The pin to use for the SD/MMC write-protect signal for a memory | ||
789 | card. If defined as " " (space), the card is considered writable. | ||
790 | |||
791 | config ETRAX_SPI_GPIO | ||
792 | tristate "Bitbanged SPI using gpio pins" | ||
793 | depends on ETRAX_SPI_MMC | ||
794 | select SPI_ETRAX_GPIO | ||
795 | default m if MMC_SPI=m && ETRAX_SPI_SSER0=n && ETRAX_SPI_SSER1=n | ||
796 | default y if MMC_SPI=y && ETRAX_SPI_SSER0=n && ETRAX_SPI_SSER1=n | ||
797 | default y if MMC_SPI=n && ETRAX_SPI_SSER0=n && ETRAX_SPI_SSER1=n | ||
798 | help | ||
799 | Say Y for an MMC/SD socket connected to general I/O pins (but not | ||
800 | a complete synchronous serial ports), or for devices using the SPI | ||
801 | protocol on general I/O pins. Slow and slows down the system. | ||
802 | Say m to build it as a module, which will be called spi_crisv32_gpio. | ||
803 | (You need to select MMC separately.) | ||
804 | |||
805 | # The default match that of sser0, only because that's how it was tested. | ||
806 | config ETRAX_SPI_CS_PIN | ||
807 | string "SPI chip select pin" | ||
808 | depends on ETRAX_SPI_GPIO | ||
809 | default "pc3" | ||
810 | help | ||
811 | The pin to use for SPI chip select. | ||
812 | |||
813 | config ETRAX_SPI_CLK_PIN | ||
814 | string "SPI clock pin" | ||
815 | depends on ETRAX_SPI_GPIO | ||
816 | default "pc1" | ||
817 | help | ||
818 | The pin to use for the SPI clock. | ||
819 | |||
820 | config ETRAX_SPI_DATAIN_PIN | ||
821 | string "SPI MISO (data in) pin" | ||
822 | depends on ETRAX_SPI_GPIO | ||
823 | default "pc16" | ||
824 | help | ||
825 | The pin to use for SPI data in from the device. | ||
826 | |||
827 | config ETRAX_SPI_DATAOUT_PIN | ||
828 | string "SPI MOSI (data out) pin" | ||
829 | depends on ETRAX_SPI_GPIO | ||
830 | default "pc0" | ||
831 | help | ||
832 | The pin to use for SPI data out to the device. | ||
833 | |||
834 | config ETRAX_SPI_MMC_CD_GPIO_PIN | ||
835 | string "MMC/SD card detect pin for SPI using gpio (space for none)" | ||
836 | depends on ETRAX_SPI_GPIO && MMC_SPI | ||
837 | default "pd11" | ||
838 | help | ||
839 | The pin to use for SD/MMC card detect. This pin should be pulled up | ||
840 | and grounded when a card is present. If defined as " " (space), no | ||
841 | pin is selected. A card must then always be inserted for proper | ||
842 | action. | ||
843 | |||
844 | config ETRAX_SPI_MMC_WP_GPIO_PIN | ||
845 | string "MMC/SD card write-protect pin for SPI using gpio (space for none)" | ||
846 | depends on ETRAX_SPI_GPIO && MMC_SPI | ||
847 | default "pd10" | ||
848 | help | ||
849 | The pin to use for the SD/MMC write-protect signal for a memory | ||
850 | card. If defined as " " (space), the card is considered writable. | ||
851 | |||
852 | # Avoid choices causing non-working configs by conditionalizing the inclusion. | ||
853 | if ETRAX_SPI_MMC | ||
854 | source drivers/spi/Kconfig | ||
855 | endif | ||
856 | |||
616 | endif | 857 | endif |
diff --git a/arch/cris/arch-v32/drivers/Makefile b/arch/cris/arch-v32/drivers/Makefile index a359cd20ae75..e8c02437edaf 100644 --- a/arch/cris/arch-v32/drivers/Makefile +++ b/arch/cris/arch-v32/drivers/Makefile | |||
@@ -4,10 +4,11 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_ETRAX_STREAMCOPROC) += cryptocop.o | 5 | obj-$(CONFIG_ETRAX_STREAMCOPROC) += cryptocop.o |
6 | obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o | 6 | obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o |
7 | obj-$(CONFIG_ETRAX_NANDFLASH) += nandflash.o | 7 | obj-$(CONFIG_ETRAXFS) += mach-fs/ |
8 | obj-$(CONFIG_ETRAX_GPIO) += gpio.o | 8 | obj-$(CONFIG_CRIS_MACH_ARTPEC3) += mach-a3/ |
9 | obj-$(CONFIG_ETRAX_IOP_FW_LOAD) += iop_fw_load.o | 9 | obj-$(CONFIG_ETRAX_IOP_FW_LOAD) += iop_fw_load.o |
10 | obj-$(CONFIG_ETRAX_PCF8563) += pcf8563.o | 10 | obj-$(CONFIG_ETRAX_PCF8563) += pcf8563.o |
11 | obj-$(CONFIG_ETRAX_I2C) += i2c.o | 11 | obj-$(CONFIG_ETRAX_I2C) += i2c.o |
12 | obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o | 12 | obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o |
13 | obj-$(CONFIG_PCI) += pci/ | 13 | obj-$(CONFIG_PCI) += pci/ |
14 | obj-$(CONFIG_ETRAX_SPI_MMC_BOARD) += board_mmcspi.o | ||
diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c index c5ff95e18269..51e1e85df96d 100644 --- a/arch/cris/arch-v32/drivers/axisflashmap.c +++ b/arch/cris/arch-v32/drivers/axisflashmap.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Physical mapping layer for MTD using the Axis partitiontable format | 2 | * Physical mapping layer for MTD using the Axis partitiontable format |
3 | * | 3 | * |
4 | * Copyright (c) 2001, 2002, 2003 Axis Communications AB | 4 | * Copyright (c) 2001-2007 Axis Communications AB |
5 | * | 5 | * |
6 | * This file is under the GPL. | 6 | * This file is under the GPL. |
7 | * | 7 | * |
@@ -10,9 +10,6 @@ | |||
10 | * tells us what other partitions to define. If there isn't, we use a default | 10 | * tells us what other partitions to define. If there isn't, we use a default |
11 | * partition split defined below. | 11 | * partition split defined below. |
12 | * | 12 | * |
13 | * Copy of os/lx25/arch/cris/arch-v10/drivers/axisflashmap.c 1.5 | ||
14 | * with minor changes. | ||
15 | * | ||
16 | */ | 13 | */ |
17 | 14 | ||
18 | #include <linux/module.h> | 15 | #include <linux/module.h> |
@@ -27,7 +24,8 @@ | |||
27 | #include <linux/mtd/mtdram.h> | 24 | #include <linux/mtd/mtdram.h> |
28 | #include <linux/mtd/partitions.h> | 25 | #include <linux/mtd/partitions.h> |
29 | 26 | ||
30 | #include <asm/arch/hwregs/config_defs.h> | 27 | #include <linux/cramfs_fs.h> |
28 | |||
31 | #include <asm/axisflashmap.h> | 29 | #include <asm/axisflashmap.h> |
32 | #include <asm/mmu.h> | 30 | #include <asm/mmu.h> |
33 | 31 | ||
@@ -37,16 +35,24 @@ | |||
37 | #define FLASH_UNCACHED_ADDR KSEG_E | 35 | #define FLASH_UNCACHED_ADDR KSEG_E |
38 | #define FLASH_CACHED_ADDR KSEG_F | 36 | #define FLASH_CACHED_ADDR KSEG_F |
39 | 37 | ||
38 | #define PAGESIZE (512) | ||
39 | |||
40 | #if CONFIG_ETRAX_FLASH_BUSWIDTH==1 | 40 | #if CONFIG_ETRAX_FLASH_BUSWIDTH==1 |
41 | #define flash_data __u8 | 41 | #define flash_data __u8 |
42 | #elif CONFIG_ETRAX_FLASH_BUSWIDTH==2 | 42 | #elif CONFIG_ETRAX_FLASH_BUSWIDTH==2 |
43 | #define flash_data __u16 | 43 | #define flash_data __u16 |
44 | #elif CONFIG_ETRAX_FLASH_BUSWIDTH==4 | 44 | #elif CONFIG_ETRAX_FLASH_BUSWIDTH==4 |
45 | #define flash_data __u16 | 45 | #define flash_data __u32 |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | /* From head.S */ | 48 | /* From head.S */ |
49 | extern unsigned long romfs_start, romfs_length, romfs_in_flash; | 49 | extern unsigned long romfs_in_flash; /* 1 when romfs_start, _length in flash */ |
50 | extern unsigned long romfs_start, romfs_length; | ||
51 | extern unsigned long nand_boot; /* 1 when booted from nand flash */ | ||
52 | |||
53 | struct partition_name { | ||
54 | char name[6]; | ||
55 | }; | ||
50 | 56 | ||
51 | /* The master mtd for the entire flash. */ | 57 | /* The master mtd for the entire flash. */ |
52 | struct mtd_info* axisflash_mtd = NULL; | 58 | struct mtd_info* axisflash_mtd = NULL; |
@@ -112,32 +118,20 @@ static struct map_info map_cse1 = { | |||
112 | .map_priv_1 = FLASH_UNCACHED_ADDR + MEM_CSE0_SIZE | 118 | .map_priv_1 = FLASH_UNCACHED_ADDR + MEM_CSE0_SIZE |
113 | }; | 119 | }; |
114 | 120 | ||
115 | /* If no partition-table was found, we use this default-set. */ | 121 | #define MAX_PARTITIONS 7 |
116 | #define MAX_PARTITIONS 7 | 122 | #ifdef CONFIG_ETRAX_NANDBOOT |
117 | #define NUM_DEFAULT_PARTITIONS 3 | 123 | #define NUM_DEFAULT_PARTITIONS 4 |
124 | #define DEFAULT_ROOTFS_PARTITION_NO 2 | ||
125 | #define DEFAULT_MEDIA_SIZE 0x2000000 /* 32 megs */ | ||
126 | #else | ||
127 | #define NUM_DEFAULT_PARTITIONS 3 | ||
128 | #define DEFAULT_ROOTFS_PARTITION_NO (-1) | ||
129 | #define DEFAULT_MEDIA_SIZE 0x800000 /* 8 megs */ | ||
130 | #endif | ||
118 | 131 | ||
119 | /* | 132 | #if (MAX_PARTITIONS < NUM_DEFAULT_PARTITIONS) |
120 | * Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the | 133 | #error MAX_PARTITIONS must be >= than NUM_DEFAULT_PARTITIONS |
121 | * size of one flash block and "filesystem"-partition needs 5 blocks to be able | 134 | #endif |
122 | * to use JFFS. | ||
123 | */ | ||
124 | static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = { | ||
125 | { | ||
126 | .name = "boot firmware", | ||
127 | .size = CONFIG_ETRAX_PTABLE_SECTOR, | ||
128 | .offset = 0 | ||
129 | }, | ||
130 | { | ||
131 | .name = "kernel", | ||
132 | .size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR), | ||
133 | .offset = CONFIG_ETRAX_PTABLE_SECTOR | ||
134 | }, | ||
135 | { | ||
136 | .name = "filesystem", | ||
137 | .size = 5 * CONFIG_ETRAX_PTABLE_SECTOR, | ||
138 | .offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR) | ||
139 | } | ||
140 | }; | ||
141 | 135 | ||
142 | /* Initialize the ones normally used. */ | 136 | /* Initialize the ones normally used. */ |
143 | static struct mtd_partition axis_partitions[MAX_PARTITIONS] = { | 137 | static struct mtd_partition axis_partitions[MAX_PARTITIONS] = { |
@@ -178,6 +172,56 @@ static struct mtd_partition axis_partitions[MAX_PARTITIONS] = { | |||
178 | }, | 172 | }, |
179 | }; | 173 | }; |
180 | 174 | ||
175 | |||
176 | /* If no partition-table was found, we use this default-set. | ||
177 | * Default flash size is 8MB (NOR). CONFIG_ETRAX_PTABLE_SECTOR is most | ||
178 | * likely the size of one flash block and "filesystem"-partition needs | ||
179 | * to be >=5 blocks to be able to use JFFS. | ||
180 | */ | ||
181 | static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = { | ||
182 | { | ||
183 | .name = "boot firmware", | ||
184 | .size = CONFIG_ETRAX_PTABLE_SECTOR, | ||
185 | .offset = 0 | ||
186 | }, | ||
187 | { | ||
188 | .name = "kernel", | ||
189 | .size = 10 * CONFIG_ETRAX_PTABLE_SECTOR, | ||
190 | .offset = CONFIG_ETRAX_PTABLE_SECTOR | ||
191 | }, | ||
192 | #define FILESYSTEM_SECTOR (11 * CONFIG_ETRAX_PTABLE_SECTOR) | ||
193 | #ifdef CONFIG_ETRAX_NANDBOOT | ||
194 | { | ||
195 | .name = "rootfs", | ||
196 | .size = 10 * CONFIG_ETRAX_PTABLE_SECTOR, | ||
197 | .offset = FILESYSTEM_SECTOR | ||
198 | }, | ||
199 | #undef FILESYSTEM_SECTOR | ||
200 | #define FILESYSTEM_SECTOR (21 * CONFIG_ETRAX_PTABLE_SECTOR) | ||
201 | #endif | ||
202 | { | ||
203 | .name = "rwfs", | ||
204 | .size = DEFAULT_MEDIA_SIZE - FILESYSTEM_SECTOR, | ||
205 | .offset = FILESYSTEM_SECTOR | ||
206 | } | ||
207 | }; | ||
208 | |||
209 | #ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE | ||
210 | /* Main flash device */ | ||
211 | static struct mtd_partition main_partition = { | ||
212 | .name = "main", | ||
213 | .size = 0, | ||
214 | .offset = 0 | ||
215 | }; | ||
216 | #endif | ||
217 | |||
218 | /* Auxilliary partition if we find another flash */ | ||
219 | static struct mtd_partition aux_partition = { | ||
220 | .name = "aux", | ||
221 | .size = 0, | ||
222 | .offset = 0 | ||
223 | }; | ||
224 | |||
181 | /* | 225 | /* |
182 | * Probe a chip select for AMD-compatible (JEDEC) or CFI-compatible flash | 226 | * Probe a chip select for AMD-compatible (JEDEC) or CFI-compatible flash |
183 | * chips in that order (because the amd_flash-driver is faster). | 227 | * chips in that order (because the amd_flash-driver is faster). |
@@ -191,7 +235,7 @@ static struct mtd_info *probe_cs(struct map_info *map_cs) | |||
191 | map_cs->name, map_cs->size, map_cs->map_priv_1); | 235 | map_cs->name, map_cs->size, map_cs->map_priv_1); |
192 | 236 | ||
193 | #ifdef CONFIG_MTD_CFI | 237 | #ifdef CONFIG_MTD_CFI |
194 | mtd_cs = do_map_probe("cfi_probe", map_cs); | 238 | mtd_cs = do_map_probe("cfi_probe", map_cs); |
195 | #endif | 239 | #endif |
196 | #ifdef CONFIG_MTD_JEDECPROBE | 240 | #ifdef CONFIG_MTD_JEDECPROBE |
197 | if (!mtd_cs) | 241 | if (!mtd_cs) |
@@ -204,7 +248,7 @@ static struct mtd_info *probe_cs(struct map_info *map_cs) | |||
204 | /* | 248 | /* |
205 | * Probe each chip select individually for flash chips. If there are chips on | 249 | * Probe each chip select individually for flash chips. If there are chips on |
206 | * both cse0 and cse1, the mtd_info structs will be concatenated to one struct | 250 | * both cse0 and cse1, the mtd_info structs will be concatenated to one struct |
207 | * so that MTD partitions can cross chip boundaries. | 251 | * so that MTD partitions can cross chip boundries. |
208 | * | 252 | * |
209 | * The only known restriction to how you can mount your chips is that each | 253 | * The only known restriction to how you can mount your chips is that each |
210 | * chip select must hold similar flash chips. But you need external hardware | 254 | * chip select must hold similar flash chips. But you need external hardware |
@@ -216,9 +260,8 @@ static struct mtd_info *flash_probe(void) | |||
216 | { | 260 | { |
217 | struct mtd_info *mtd_cse0; | 261 | struct mtd_info *mtd_cse0; |
218 | struct mtd_info *mtd_cse1; | 262 | struct mtd_info *mtd_cse1; |
219 | struct mtd_info *mtd_nand = NULL; | ||
220 | struct mtd_info *mtd_total; | 263 | struct mtd_info *mtd_total; |
221 | struct mtd_info *mtds[3]; | 264 | struct mtd_info *mtds[2]; |
222 | int count = 0; | 265 | int count = 0; |
223 | 266 | ||
224 | if ((mtd_cse0 = probe_cs(&map_cse0)) != NULL) | 267 | if ((mtd_cse0 = probe_cs(&map_cse0)) != NULL) |
@@ -226,12 +269,7 @@ static struct mtd_info *flash_probe(void) | |||
226 | if ((mtd_cse1 = probe_cs(&map_cse1)) != NULL) | 269 | if ((mtd_cse1 = probe_cs(&map_cse1)) != NULL) |
227 | mtds[count++] = mtd_cse1; | 270 | mtds[count++] = mtd_cse1; |
228 | 271 | ||
229 | #ifdef CONFIG_ETRAX_NANDFLASH | 272 | if (!mtd_cse0 && !mtd_cse1) { |
230 | if ((mtd_nand = crisv32_nand_flash_probe()) != NULL) | ||
231 | mtds[count++] = mtd_nand; | ||
232 | #endif | ||
233 | |||
234 | if (!mtd_cse0 && !mtd_cse1 && !mtd_nand) { | ||
235 | /* No chip found. */ | 273 | /* No chip found. */ |
236 | return NULL; | 274 | return NULL; |
237 | } | 275 | } |
@@ -245,9 +283,7 @@ static struct mtd_info *flash_probe(void) | |||
245 | * So we use the MTD concatenation layer instead of further | 283 | * So we use the MTD concatenation layer instead of further |
246 | * complicating the probing procedure. | 284 | * complicating the probing procedure. |
247 | */ | 285 | */ |
248 | mtd_total = mtd_concat_create(mtds, | 286 | mtd_total = mtd_concat_create(mtds, count, "cse0+cse1"); |
249 | count, | ||
250 | "cse0+cse1+nand"); | ||
251 | #else | 287 | #else |
252 | printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel " | 288 | printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel " |
253 | "(mis)configuration!\n", map_cse0.name, map_cse1.name); | 289 | "(mis)configuration!\n", map_cse0.name, map_cse1.name); |
@@ -255,61 +291,162 @@ static struct mtd_info *flash_probe(void) | |||
255 | #endif | 291 | #endif |
256 | if (!mtd_total) { | 292 | if (!mtd_total) { |
257 | printk(KERN_ERR "%s and %s: Concatenation failed!\n", | 293 | printk(KERN_ERR "%s and %s: Concatenation failed!\n", |
258 | map_cse0.name, map_cse1.name); | 294 | map_cse0.name, map_cse1.name); |
259 | 295 | ||
260 | /* The best we can do now is to only use what we found | 296 | /* The best we can do now is to only use what we found |
261 | * at cse0. | 297 | * at cse0. */ |
262 | */ | ||
263 | mtd_total = mtd_cse0; | 298 | mtd_total = mtd_cse0; |
264 | map_destroy(mtd_cse1); | 299 | map_destroy(mtd_cse1); |
265 | } | 300 | } |
266 | } else { | 301 | } else |
267 | mtd_total = mtd_cse0? mtd_cse0 : mtd_cse1 ? mtd_cse1 : mtd_nand; | 302 | mtd_total = mtd_cse0 ? mtd_cse0 : mtd_cse1; |
268 | |||
269 | } | ||
270 | 303 | ||
271 | return mtd_total; | 304 | return mtd_total; |
272 | } | 305 | } |
273 | 306 | ||
274 | extern unsigned long crisv32_nand_boot; | ||
275 | extern unsigned long crisv32_nand_cramfs_offset; | ||
276 | |||
277 | /* | 307 | /* |
278 | * Probe the flash chip(s) and, if it succeeds, read the partition-table | 308 | * Probe the flash chip(s) and, if it succeeds, read the partition-table |
279 | * and register the partitions with MTD. | 309 | * and register the partitions with MTD. |
280 | */ | 310 | */ |
281 | static int __init init_axis_flash(void) | 311 | static int __init init_axis_flash(void) |
282 | { | 312 | { |
283 | struct mtd_info *mymtd; | 313 | struct mtd_info *main_mtd; |
314 | struct mtd_info *aux_mtd = NULL; | ||
284 | int err = 0; | 315 | int err = 0; |
285 | int pidx = 0; | 316 | int pidx = 0; |
286 | struct partitiontable_head *ptable_head = NULL; | 317 | struct partitiontable_head *ptable_head = NULL; |
287 | struct partitiontable_entry *ptable; | 318 | struct partitiontable_entry *ptable; |
288 | int use_default_ptable = 1; /* Until proven otherwise. */ | 319 | int ptable_ok = 0; |
289 | const char *pmsg = KERN_INFO " /dev/flash%d at 0x%08x, size 0x%08x\n"; | 320 | static char page[PAGESIZE]; |
290 | static char page[512]; | ||
291 | size_t len; | 321 | size_t len; |
322 | int ram_rootfs_partition = -1; /* -1 => no RAM rootfs partition */ | ||
323 | int part; | ||
324 | |||
325 | /* We need a root fs. If it resides in RAM, we need to use an | ||
326 | * MTDRAM device, so it must be enabled in the kernel config, | ||
327 | * but its size must be configured as 0 so as not to conflict | ||
328 | * with our usage. | ||
329 | */ | ||
330 | #if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || (CONFIG_MTDRAM_ABS_POS != 0) | ||
331 | if (!romfs_in_flash && !nand_boot) { | ||
332 | printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM " | ||
333 | "device; configure CONFIG_MTD_MTDRAM with size = 0!\n"); | ||
334 | panic("This kernel cannot boot from RAM!\n"); | ||
335 | } | ||
336 | #endif | ||
337 | |||
338 | #ifndef CONFIG_ETRAX_VCS_SIM | ||
339 | main_mtd = flash_probe(); | ||
340 | if (main_mtd) | ||
341 | printk(KERN_INFO "%s: 0x%08x bytes of NOR flash memory.\n", | ||
342 | main_mtd->name, main_mtd->size); | ||
343 | |||
344 | #ifdef CONFIG_ETRAX_NANDFLASH | ||
345 | aux_mtd = crisv32_nand_flash_probe(); | ||
346 | if (aux_mtd) | ||
347 | printk(KERN_INFO "%s: 0x%08x bytes of NAND flash memory.\n", | ||
348 | aux_mtd->name, aux_mtd->size); | ||
349 | |||
350 | #ifdef CONFIG_ETRAX_NANDBOOT | ||
351 | { | ||
352 | struct mtd_info *tmp_mtd; | ||
292 | 353 | ||
293 | #ifndef CONFIG_ETRAXFS_SIM | 354 | printk(KERN_INFO "axisflashmap: Set to boot from NAND flash, " |
294 | mymtd = flash_probe(); | 355 | "making NAND flash primary device.\n"); |
295 | mymtd->read(mymtd, CONFIG_ETRAX_PTABLE_SECTOR, 512, &len, page); | 356 | tmp_mtd = main_mtd; |
296 | ptable_head = (struct partitiontable_head *)(page + PARTITION_TABLE_OFFSET); | 357 | main_mtd = aux_mtd; |
358 | aux_mtd = tmp_mtd; | ||
359 | } | ||
360 | #endif /* CONFIG_ETRAX_NANDBOOT */ | ||
361 | #endif /* CONFIG_ETRAX_NANDFLASH */ | ||
297 | 362 | ||
298 | if (!mymtd) { | 363 | if (!main_mtd && !aux_mtd) { |
299 | /* There's no reason to use this module if no flash chip can | 364 | /* There's no reason to use this module if no flash chip can |
300 | * be identified. Make sure that's understood. | 365 | * be identified. Make sure that's understood. |
301 | */ | 366 | */ |
302 | printk(KERN_INFO "axisflashmap: Found no flash chip.\n"); | 367 | printk(KERN_INFO "axisflashmap: Found no flash chip.\n"); |
303 | } else { | ||
304 | printk(KERN_INFO "%s: 0x%08x bytes of flash memory.\n", | ||
305 | mymtd->name, mymtd->size); | ||
306 | axisflash_mtd = mymtd; | ||
307 | } | 368 | } |
308 | 369 | ||
309 | if (mymtd) { | 370 | #if 0 /* Dump flash memory so we can see what is going on */ |
310 | mymtd->owner = THIS_MODULE; | 371 | if (main_mtd) { |
372 | int sectoraddr, i; | ||
373 | for (sectoraddr = 0; sectoraddr < 2*65536+4096; | ||
374 | sectoraddr += PAGESIZE) { | ||
375 | main_mtd->read(main_mtd, sectoraddr, PAGESIZE, &len, | ||
376 | page); | ||
377 | printk(KERN_INFO | ||
378 | "Sector at %d (length %d):\n", | ||
379 | sectoraddr, len); | ||
380 | for (i = 0; i < PAGESIZE; i += 16) { | ||
381 | printk(KERN_INFO | ||
382 | "%02x %02x %02x %02x " | ||
383 | "%02x %02x %02x %02x " | ||
384 | "%02x %02x %02x %02x " | ||
385 | "%02x %02x %02x %02x\n", | ||
386 | page[i] & 255, page[i+1] & 255, | ||
387 | page[i+2] & 255, page[i+3] & 255, | ||
388 | page[i+4] & 255, page[i+5] & 255, | ||
389 | page[i+6] & 255, page[i+7] & 255, | ||
390 | page[i+8] & 255, page[i+9] & 255, | ||
391 | page[i+10] & 255, page[i+11] & 255, | ||
392 | page[i+12] & 255, page[i+13] & 255, | ||
393 | page[i+14] & 255, page[i+15] & 255); | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | #endif | ||
398 | |||
399 | if (main_mtd) { | ||
400 | main_mtd->owner = THIS_MODULE; | ||
401 | axisflash_mtd = main_mtd; | ||
402 | |||
403 | loff_t ptable_sector = CONFIG_ETRAX_PTABLE_SECTOR; | ||
404 | |||
405 | /* First partition (rescue) is always set to the default. */ | ||
406 | pidx++; | ||
407 | #ifdef CONFIG_ETRAX_NANDBOOT | ||
408 | /* We know where the partition table should be located, | ||
409 | * it will be in first good block after that. | ||
410 | */ | ||
411 | int blockstat; | ||
412 | do { | ||
413 | blockstat = main_mtd->block_isbad(main_mtd, | ||
414 | ptable_sector); | ||
415 | if (blockstat < 0) | ||
416 | ptable_sector = 0; /* read error */ | ||
417 | else if (blockstat) | ||
418 | ptable_sector += main_mtd->erasesize; | ||
419 | } while (blockstat && ptable_sector); | ||
420 | #endif | ||
421 | if (ptable_sector) { | ||
422 | main_mtd->read(main_mtd, ptable_sector, PAGESIZE, | ||
423 | &len, page); | ||
424 | ptable_head = &((struct partitiontable *) page)->head; | ||
425 | } | ||
426 | |||
427 | #if 0 /* Dump partition table so we can see what is going on */ | ||
428 | printk(KERN_INFO | ||
429 | "axisflashmap: flash read %d bytes at 0x%08x, data: " | ||
430 | "%02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
431 | len, CONFIG_ETRAX_PTABLE_SECTOR, | ||
432 | page[0] & 255, page[1] & 255, | ||
433 | page[2] & 255, page[3] & 255, | ||
434 | page[4] & 255, page[5] & 255, | ||
435 | page[6] & 255, page[7] & 255); | ||
436 | printk(KERN_INFO | ||
437 | "axisflashmap: partition table offset %d, data: " | ||
438 | "%02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
439 | PARTITION_TABLE_OFFSET, | ||
440 | page[PARTITION_TABLE_OFFSET+0] & 255, | ||
441 | page[PARTITION_TABLE_OFFSET+1] & 255, | ||
442 | page[PARTITION_TABLE_OFFSET+2] & 255, | ||
443 | page[PARTITION_TABLE_OFFSET+3] & 255, | ||
444 | page[PARTITION_TABLE_OFFSET+4] & 255, | ||
445 | page[PARTITION_TABLE_OFFSET+5] & 255, | ||
446 | page[PARTITION_TABLE_OFFSET+6] & 255, | ||
447 | page[PARTITION_TABLE_OFFSET+7] & 255); | ||
448 | #endif | ||
311 | } | 449 | } |
312 | pidx++; /* First partition is always set to the default. */ | ||
313 | 450 | ||
314 | if (ptable_head && (ptable_head->magic == PARTITION_TABLE_MAGIC) | 451 | if (ptable_head && (ptable_head->magic == PARTITION_TABLE_MAGIC) |
315 | && (ptable_head->size < | 452 | && (ptable_head->size < |
@@ -322,7 +459,6 @@ static int __init init_axis_flash(void) | |||
322 | /* Looks like a start, sane length and end of a | 459 | /* Looks like a start, sane length and end of a |
323 | * partition table, lets check csum etc. | 460 | * partition table, lets check csum etc. |
324 | */ | 461 | */ |
325 | int ptable_ok = 0; | ||
326 | struct partitiontable_entry *max_addr = | 462 | struct partitiontable_entry *max_addr = |
327 | (struct partitiontable_entry *) | 463 | (struct partitiontable_entry *) |
328 | ((unsigned long)ptable_head + sizeof(*ptable_head) + | 464 | ((unsigned long)ptable_head + sizeof(*ptable_head) + |
@@ -346,104 +482,170 @@ static int __init init_axis_flash(void) | |||
346 | ptable_ok = (csum == ptable_head->checksum); | 482 | ptable_ok = (csum == ptable_head->checksum); |
347 | 483 | ||
348 | /* Read the entries and use/show the info. */ | 484 | /* Read the entries and use/show the info. */ |
349 | printk(KERN_INFO " Found a%s partition table at 0x%p-0x%p.\n", | 485 | printk(KERN_INFO "axisflashmap: " |
486 | "Found a%s partition table at 0x%p-0x%p.\n", | ||
350 | (ptable_ok ? " valid" : "n invalid"), ptable_head, | 487 | (ptable_ok ? " valid" : "n invalid"), ptable_head, |
351 | max_addr); | 488 | max_addr); |
352 | 489 | ||
353 | /* We have found a working bootblock. Now read the | 490 | /* We have found a working bootblock. Now read the |
354 | * partition table. Scan the table. It ends when | 491 | * partition table. Scan the table. It ends with 0xffffffff. |
355 | * there is 0xffffffff, that is, empty flash. | ||
356 | */ | 492 | */ |
357 | while (ptable_ok | 493 | while (ptable_ok |
358 | && ptable->offset != 0xffffffff | 494 | && ptable->offset != PARTITIONTABLE_END_MARKER |
359 | && ptable < max_addr | 495 | && ptable < max_addr |
360 | && pidx < MAX_PARTITIONS) { | 496 | && pidx < MAX_PARTITIONS - 1) { |
361 | 497 | ||
362 | axis_partitions[pidx].offset = offset + ptable->offset + (crisv32_nand_boot ? 16384 : 0); | 498 | axis_partitions[pidx].offset = offset + ptable->offset; |
363 | axis_partitions[pidx].size = ptable->size; | 499 | #ifdef CONFIG_ETRAX_NANDFLASH |
364 | 500 | if (main_mtd->type == MTD_NANDFLASH) { | |
365 | printk(pmsg, pidx, axis_partitions[pidx].offset, | 501 | axis_partitions[pidx].size = |
366 | axis_partitions[pidx].size); | 502 | (((ptable+1)->offset == |
503 | PARTITIONTABLE_END_MARKER) ? | ||
504 | main_mtd->size : | ||
505 | ((ptable+1)->offset + offset)) - | ||
506 | (ptable->offset + offset); | ||
507 | |||
508 | } else | ||
509 | #endif /* CONFIG_ETRAX_NANDFLASH */ | ||
510 | axis_partitions[pidx].size = ptable->size; | ||
511 | #ifdef CONFIG_ETRAX_NANDBOOT | ||
512 | /* Save partition number of jffs2 ro partition. | ||
513 | * Needed if RAM booting or root file system in RAM. | ||
514 | */ | ||
515 | if (!nand_boot && | ||
516 | ram_rootfs_partition < 0 && /* not already set */ | ||
517 | ptable->type == PARTITION_TYPE_JFFS2 && | ||
518 | (ptable->flags & PARTITION_FLAGS_READONLY_MASK) == | ||
519 | PARTITION_FLAGS_READONLY) | ||
520 | ram_rootfs_partition = pidx; | ||
521 | #endif /* CONFIG_ETRAX_NANDBOOT */ | ||
367 | pidx++; | 522 | pidx++; |
368 | ptable++; | 523 | ptable++; |
369 | } | 524 | } |
370 | use_default_ptable = !ptable_ok; | ||
371 | } | 525 | } |
372 | 526 | ||
373 | if (romfs_in_flash) { | 527 | /* Decide whether to use default partition table. */ |
374 | /* Add an overlapping device for the root partition (romfs). */ | 528 | /* Only use default table if we actually have a device (main_mtd) */ |
375 | 529 | ||
376 | axis_partitions[pidx].name = "romfs"; | 530 | struct mtd_partition *partition = &axis_partitions[0]; |
377 | if (crisv32_nand_boot) { | 531 | if (main_mtd && !ptable_ok) { |
378 | char* data = kmalloc(1024, GFP_KERNEL); | 532 | memcpy(axis_partitions, axis_default_partitions, |
379 | int len; | 533 | sizeof(axis_default_partitions)); |
380 | int offset = crisv32_nand_cramfs_offset & ~(1024-1); | 534 | pidx = NUM_DEFAULT_PARTITIONS; |
381 | char* tmp; | 535 | ram_rootfs_partition = DEFAULT_ROOTFS_PARTITION_NO; |
382 | 536 | } | |
383 | mymtd->read(mymtd, offset, 1024, &len, data); | ||
384 | tmp = &data[crisv32_nand_cramfs_offset % 512]; | ||
385 | axis_partitions[pidx].size = *(unsigned*)(tmp + 4); | ||
386 | axis_partitions[pidx].offset = crisv32_nand_cramfs_offset; | ||
387 | kfree(data); | ||
388 | } else { | ||
389 | axis_partitions[pidx].size = romfs_length; | ||
390 | axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR; | ||
391 | } | ||
392 | 537 | ||
538 | /* Add artificial partitions for rootfs if necessary */ | ||
539 | if (romfs_in_flash) { | ||
540 | /* rootfs is in directly accessible flash memory = NOR flash. | ||
541 | Add an overlapping device for the rootfs partition. */ | ||
542 | printk(KERN_INFO "axisflashmap: Adding partition for " | ||
543 | "overlapping root file system image\n"); | ||
544 | axis_partitions[pidx].size = romfs_length; | ||
545 | axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR; | ||
546 | axis_partitions[pidx].name = "romfs"; | ||
393 | axis_partitions[pidx].mask_flags |= MTD_WRITEABLE; | 547 | axis_partitions[pidx].mask_flags |= MTD_WRITEABLE; |
394 | 548 | ram_rootfs_partition = -1; | |
395 | printk(KERN_INFO | ||
396 | " Adding readonly flash partition for romfs image:\n"); | ||
397 | printk(pmsg, pidx, axis_partitions[pidx].offset, | ||
398 | axis_partitions[pidx].size); | ||
399 | pidx++; | 549 | pidx++; |
400 | } | 550 | } else if (romfs_length && !nand_boot) { |
401 | 551 | /* romfs exists in memory, but not in flash, so must be in RAM. | |
402 | if (mymtd) { | 552 | * Configure an MTDRAM partition. */ |
403 | if (use_default_ptable) { | 553 | if (ram_rootfs_partition < 0) { |
404 | printk(KERN_INFO " Using default partition table.\n"); | 554 | /* None set yet, put it at the end */ |
405 | err = add_mtd_partitions(mymtd, axis_default_partitions, | 555 | ram_rootfs_partition = pidx; |
406 | NUM_DEFAULT_PARTITIONS); | 556 | pidx++; |
407 | } else { | ||
408 | err = add_mtd_partitions(mymtd, axis_partitions, pidx); | ||
409 | } | 557 | } |
558 | printk(KERN_INFO "axisflashmap: Adding partition for " | ||
559 | "root file system image in RAM\n"); | ||
560 | axis_partitions[ram_rootfs_partition].size = romfs_length; | ||
561 | axis_partitions[ram_rootfs_partition].offset = romfs_start; | ||
562 | axis_partitions[ram_rootfs_partition].name = "romfs"; | ||
563 | axis_partitions[ram_rootfs_partition].mask_flags |= | ||
564 | MTD_WRITEABLE; | ||
565 | } | ||
410 | 566 | ||
411 | if (err) { | 567 | #ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE |
412 | panic("axisflashmap could not add MTD partitions!\n"); | 568 | if (main_mtd) { |
413 | } | 569 | main_partition.size = main_mtd->size; |
570 | err = add_mtd_partitions(main_mtd, &main_partition, 1); | ||
571 | if (err) | ||
572 | panic("axisflashmap: Could not initialize " | ||
573 | "partition for whole main mtd device!\n"); | ||
414 | } | 574 | } |
415 | /* CONFIG_EXTRAXFS_SIM */ | ||
416 | #endif | 575 | #endif |
417 | 576 | ||
418 | if (!romfs_in_flash) { | 577 | /* Now, register all partitions with mtd. |
419 | /* Create an RAM device for the root partition (romfs). */ | 578 | * We do this one at a time so we can slip in an MTDRAM device |
579 | * in the proper place if required. */ | ||
580 | |||
581 | for (part = 0; part < pidx; part++) { | ||
582 | if (part == ram_rootfs_partition) { | ||
583 | /* add MTDRAM partition here */ | ||
584 | struct mtd_info *mtd_ram; | ||
585 | |||
586 | mtd_ram = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); | ||
587 | if (!mtd_ram) | ||
588 | panic("axisflashmap: Couldn't allocate memory " | ||
589 | "for mtd_info!\n"); | ||
590 | printk(KERN_INFO "axisflashmap: Adding RAM partition " | ||
591 | "for rootfs image.\n"); | ||
592 | err = mtdram_init_device(mtd_ram, | ||
593 | (void *)partition[part].offset, | ||
594 | partition[part].size, | ||
595 | partition[part].name); | ||
596 | if (err) | ||
597 | panic("axisflashmap: Could not initialize " | ||
598 | "MTD RAM device!\n"); | ||
599 | /* JFFS2 likes to have an erasesize. Keep potential | ||
600 | * JFFS2 rootfs happy by providing one. Since image | ||
601 | * was most likely created for main mtd, use that | ||
602 | * erasesize, if available. Otherwise, make a guess. */ | ||
603 | mtd_ram->erasesize = (main_mtd ? main_mtd->erasesize : | ||
604 | CONFIG_ETRAX_PTABLE_SECTOR); | ||
605 | } else { | ||
606 | err = add_mtd_partitions(main_mtd, &partition[part], 1); | ||
607 | if (err) | ||
608 | panic("axisflashmap: Could not add mtd " | ||
609 | "partition %d\n", part); | ||
610 | } | ||
611 | } | ||
612 | #endif /* CONFIG_EXTRAX_VCS_SIM */ | ||
613 | |||
614 | #ifdef CONFIG_ETRAX_VCS_SIM | ||
615 | /* For simulator, always use a RAM partition. | ||
616 | * The rootfs will be found after the kernel in RAM, | ||
617 | * with romfs_start and romfs_end indicating location and size. | ||
618 | */ | ||
619 | struct mtd_info *mtd_ram; | ||
620 | |||
621 | mtd_ram = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); | ||
622 | if (!mtd_ram) { | ||
623 | panic("axisflashmap: Couldn't allocate memory for " | ||
624 | "mtd_info!\n"); | ||
625 | } | ||
420 | 626 | ||
421 | #if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || (CONFIG_MTDRAM_ABS_POS != 0) | 627 | printk(KERN_INFO "axisflashmap: Adding RAM partition for romfs, " |
422 | /* No use trying to boot this kernel from RAM. Panic! */ | 628 | "at %u, size %u\n", |
423 | printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM " | 629 | (unsigned) romfs_start, (unsigned) romfs_length); |
424 | "device due to kernel (mis)configuration!\n"); | ||
425 | panic("This kernel cannot boot from RAM!\n"); | ||
426 | #else | ||
427 | struct mtd_info *mtd_ram; | ||
428 | 630 | ||
429 | mtd_ram = kmalloc(sizeof(struct mtd_info), | 631 | err = mtdram_init_device(mtd_ram, (void *)romfs_start, |
430 | GFP_KERNEL); | 632 | romfs_length, "romfs"); |
431 | if (!mtd_ram) { | 633 | if (err) { |
432 | panic("axisflashmap couldn't allocate memory for " | 634 | panic("axisflashmap: Could not initialize MTD RAM " |
433 | "mtd_info!\n"); | 635 | "device!\n"); |
434 | } | 636 | } |
637 | #endif /* CONFIG_EXTRAX_VCS_SIM */ | ||
435 | 638 | ||
436 | printk(KERN_INFO " Adding RAM partition for romfs image:\n"); | 639 | #ifndef CONFIG_ETRAX_VCS_SIM |
437 | printk(pmsg, pidx, romfs_start, romfs_length); | 640 | if (aux_mtd) { |
641 | aux_partition.size = aux_mtd->size; | ||
642 | err = add_mtd_partitions(aux_mtd, &aux_partition, 1); | ||
643 | if (err) | ||
644 | panic("axisflashmap: Could not initialize " | ||
645 | "aux mtd device!\n"); | ||
438 | 646 | ||
439 | err = mtdram_init_device(mtd_ram, (void*)romfs_start, | ||
440 | romfs_length, "romfs"); | ||
441 | if (err) { | ||
442 | panic("axisflashmap could not initialize MTD RAM " | ||
443 | "device!\n"); | ||
444 | } | ||
445 | #endif | ||
446 | } | 647 | } |
648 | #endif /* CONFIG_EXTRAX_VCS_SIM */ | ||
447 | 649 | ||
448 | return err; | 650 | return err; |
449 | } | 651 | } |
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c index e8914d401696..9fb58202be99 100644 --- a/arch/cris/arch-v32/drivers/cryptocop.c +++ b/arch/cris/arch-v32/drivers/cryptocop.c | |||
@@ -1,8 +1,7 @@ | |||
1 | /* $Id: cryptocop.c,v 1.13 2005/04/21 17:27:55 henriken Exp $ | 1 | /* |
2 | * | ||
3 | * Stream co-processor driver for the ETRAX FS | 2 | * Stream co-processor driver for the ETRAX FS |
4 | * | 3 | * |
5 | * Copyright (C) 2003-2005 Axis Communications AB | 4 | * Copyright (C) 2003-2007 Axis Communications AB |
6 | */ | 5 | */ |
7 | 6 | ||
8 | #include <linux/init.h> | 7 | #include <linux/init.h> |
@@ -25,17 +24,29 @@ | |||
25 | #include <asm/signal.h> | 24 | #include <asm/signal.h> |
26 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
27 | 26 | ||
28 | #include <asm/arch/dma.h> | 27 | #include <dma.h> |
29 | #include <asm/arch/hwregs/dma.h> | 28 | #include <hwregs/dma.h> |
30 | #include <asm/arch/hwregs/reg_map.h> | 29 | #include <hwregs/reg_map.h> |
31 | #include <asm/arch/hwregs/reg_rdwr.h> | 30 | #include <hwregs/reg_rdwr.h> |
32 | #include <asm/arch/hwregs/intr_vect_defs.h> | 31 | #include <hwregs/intr_vect_defs.h> |
33 | 32 | ||
34 | #include <asm/arch/hwregs/strcop.h> | 33 | #include <hwregs/strcop.h> |
35 | #include <asm/arch/hwregs/strcop_defs.h> | 34 | #include <hwregs/strcop_defs.h> |
36 | #include <asm/arch/cryptocop.h> | 35 | #include <cryptocop.h> |
37 | 36 | ||
38 | 37 | #ifdef CONFIG_ETRAXFS | |
38 | #define IN_DMA 9 | ||
39 | #define OUT_DMA 8 | ||
40 | #define IN_DMA_INST regi_dma9 | ||
41 | #define OUT_DMA_INST regi_dma8 | ||
42 | #define DMA_IRQ DMA9_INTR_VECT | ||
43 | #else | ||
44 | #define IN_DMA 3 | ||
45 | #define OUT_DMA 2 | ||
46 | #define IN_DMA_INST regi_dma3 | ||
47 | #define OUT_DMA_INST regi_dma2 | ||
48 | #define DMA_IRQ DMA3_INTR_VECT | ||
49 | #endif | ||
39 | 50 | ||
40 | #define DESCR_ALLOC_PAD (31) | 51 | #define DESCR_ALLOC_PAD (31) |
41 | 52 | ||
@@ -1886,14 +1897,14 @@ static void cryptocop_do_tasklet(unsigned long unused) | |||
1886 | } | 1897 | } |
1887 | 1898 | ||
1888 | static irqreturn_t | 1899 | static irqreturn_t |
1889 | dma_done_interrupt(int irq, void *dev_id, struct pt_regs * regs) | 1900 | dma_done_interrupt(int irq, void *dev_id) |
1890 | { | 1901 | { |
1891 | struct cryptocop_prio_job *done_job; | 1902 | struct cryptocop_prio_job *done_job; |
1892 | reg_dma_rw_ack_intr ack_intr = { | 1903 | reg_dma_rw_ack_intr ack_intr = { |
1893 | .data = 1, | 1904 | .data = 1, |
1894 | }; | 1905 | }; |
1895 | 1906 | ||
1896 | REG_WR (dma, regi_dma9, rw_ack_intr, ack_intr); | 1907 | REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr); |
1897 | 1908 | ||
1898 | DEBUG(printk("cryptocop DMA done\n")); | 1909 | DEBUG(printk("cryptocop DMA done\n")); |
1899 | 1910 | ||
@@ -1937,7 +1948,6 @@ dma_done_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
1937 | static int init_cryptocop(void) | 1948 | static int init_cryptocop(void) |
1938 | { | 1949 | { |
1939 | unsigned long flags; | 1950 | unsigned long flags; |
1940 | reg_intr_vect_rw_mask intr_mask; | ||
1941 | reg_dma_rw_cfg dma_cfg = {.en = 1}; | 1951 | reg_dma_rw_cfg dma_cfg = {.en = 1}; |
1942 | reg_dma_rw_intr_mask intr_mask_in = {.data = regk_dma_yes}; /* Only want descriptor interrupts from the DMA in channel. */ | 1952 | reg_dma_rw_intr_mask intr_mask_in = {.data = regk_dma_yes}; /* Only want descriptor interrupts from the DMA in channel. */ |
1943 | reg_dma_rw_ack_intr ack_intr = {.data = 1,.in_eop = 1 }; | 1953 | reg_dma_rw_ack_intr ack_intr = {.data = 1,.in_eop = 1 }; |
@@ -1950,10 +1960,14 @@ static int init_cryptocop(void) | |||
1950 | .en = 1 | 1960 | .en = 1 |
1951 | }; | 1961 | }; |
1952 | 1962 | ||
1953 | if (request_irq(DMA9_INTR_VECT, dma_done_interrupt, 0, "stream co-processor DMA", NULL)) panic("request_irq stream co-processor irq dma9"); | 1963 | if (request_irq(DMA_IRQ, dma_done_interrupt, 0, |
1964 | "stream co-processor DMA", NULL)) | ||
1965 | panic("request_irq stream co-processor irq dma9"); | ||
1954 | 1966 | ||
1955 | (void)crisv32_request_dma(8, "strcop", DMA_PANIC_ON_ERROR, 0, dma_strp); | 1967 | (void)crisv32_request_dma(OUT_DMA, "strcop", DMA_PANIC_ON_ERROR, |
1956 | (void)crisv32_request_dma(9, "strcop", DMA_PANIC_ON_ERROR, 0, dma_strp); | 1968 | 0, dma_strp); |
1969 | (void)crisv32_request_dma(IN_DMA, "strcop", DMA_PANIC_ON_ERROR, | ||
1970 | 0, dma_strp); | ||
1957 | 1971 | ||
1958 | local_irq_save(flags); | 1972 | local_irq_save(flags); |
1959 | 1973 | ||
@@ -1963,24 +1977,19 @@ static int init_cryptocop(void) | |||
1963 | strcop_cfg.en = 1; | 1977 | strcop_cfg.en = 1; |
1964 | REG_WR(strcop, regi_strcop, rw_cfg, strcop_cfg); | 1978 | REG_WR(strcop, regi_strcop, rw_cfg, strcop_cfg); |
1965 | 1979 | ||
1966 | /* Enable DMA9 interrupt */ | ||
1967 | intr_mask = REG_RD(intr_vect, regi_irq, rw_mask); | ||
1968 | intr_mask.dma9 = 1; | ||
1969 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); | ||
1970 | |||
1971 | /* Enable DMAs. */ | 1980 | /* Enable DMAs. */ |
1972 | REG_WR(dma, regi_dma9, rw_cfg, dma_cfg); /* input DMA */ | 1981 | REG_WR(dma, IN_DMA_INST, rw_cfg, dma_cfg); /* input DMA */ |
1973 | REG_WR(dma, regi_dma8, rw_cfg, dma_cfg); /* output DMA */ | 1982 | REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_cfg); /* output DMA */ |
1974 | 1983 | ||
1975 | /* Set up wordsize = 4 for DMAs. */ | 1984 | /* Set up wordsize = 4 for DMAs. */ |
1976 | DMA_WR_CMD (regi_dma8, regk_dma_set_w_size4); | 1985 | DMA_WR_CMD(OUT_DMA_INST, regk_dma_set_w_size4); |
1977 | DMA_WR_CMD (regi_dma9, regk_dma_set_w_size4); | 1986 | DMA_WR_CMD(IN_DMA_INST, regk_dma_set_w_size4); |
1978 | 1987 | ||
1979 | /* Enable interrupts. */ | 1988 | /* Enable interrupts. */ |
1980 | REG_WR(dma, regi_dma9, rw_intr_mask, intr_mask_in); | 1989 | REG_WR(dma, IN_DMA_INST, rw_intr_mask, intr_mask_in); |
1981 | 1990 | ||
1982 | /* Clear intr ack. */ | 1991 | /* Clear intr ack. */ |
1983 | REG_WR(dma, regi_dma9, rw_ack_intr, ack_intr); | 1992 | REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr); |
1984 | 1993 | ||
1985 | local_irq_restore(flags); | 1994 | local_irq_restore(flags); |
1986 | 1995 | ||
@@ -1991,7 +2000,6 @@ static int init_cryptocop(void) | |||
1991 | static void release_cryptocop(void) | 2000 | static void release_cryptocop(void) |
1992 | { | 2001 | { |
1993 | unsigned long flags; | 2002 | unsigned long flags; |
1994 | reg_intr_vect_rw_mask intr_mask; | ||
1995 | reg_dma_rw_cfg dma_cfg = {.en = 0}; | 2003 | reg_dma_rw_cfg dma_cfg = {.en = 0}; |
1996 | reg_dma_rw_intr_mask intr_mask_in = {0}; | 2004 | reg_dma_rw_intr_mask intr_mask_in = {0}; |
1997 | reg_dma_rw_ack_intr ack_intr = {.data = 1,.in_eop = 1 }; | 2005 | reg_dma_rw_ack_intr ack_intr = {.data = 1,.in_eop = 1 }; |
@@ -1999,26 +2007,21 @@ static void release_cryptocop(void) | |||
1999 | local_irq_save(flags); | 2007 | local_irq_save(flags); |
2000 | 2008 | ||
2001 | /* Clear intr ack. */ | 2009 | /* Clear intr ack. */ |
2002 | REG_WR(dma, regi_dma9, rw_ack_intr, ack_intr); | 2010 | REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr); |
2003 | |||
2004 | /* Disable DMA9 interrupt */ | ||
2005 | intr_mask = REG_RD(intr_vect, regi_irq, rw_mask); | ||
2006 | intr_mask.dma9 = 0; | ||
2007 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); | ||
2008 | 2011 | ||
2009 | /* Disable DMAs. */ | 2012 | /* Disable DMAs. */ |
2010 | REG_WR(dma, regi_dma9, rw_cfg, dma_cfg); /* input DMA */ | 2013 | REG_WR(dma, IN_DMA_INST, rw_cfg, dma_cfg); /* input DMA */ |
2011 | REG_WR(dma, regi_dma8, rw_cfg, dma_cfg); /* output DMA */ | 2014 | REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_cfg); /* output DMA */ |
2012 | 2015 | ||
2013 | /* Disable interrupts. */ | 2016 | /* Disable interrupts. */ |
2014 | REG_WR(dma, regi_dma9, rw_intr_mask, intr_mask_in); | 2017 | REG_WR(dma, IN_DMA_INST, rw_intr_mask, intr_mask_in); |
2015 | 2018 | ||
2016 | local_irq_restore(flags); | 2019 | local_irq_restore(flags); |
2017 | 2020 | ||
2018 | free_irq(DMA9_INTR_VECT, NULL); | 2021 | free_irq(DMA_IRQ, NULL); |
2019 | 2022 | ||
2020 | (void)crisv32_free_dma(8); | 2023 | (void)crisv32_free_dma(OUT_DMA); |
2021 | (void)crisv32_free_dma(9); | 2024 | (void)crisv32_free_dma(IN_DMA); |
2022 | } | 2025 | } |
2023 | 2026 | ||
2024 | 2027 | ||
@@ -2076,13 +2079,13 @@ static void cryptocop_job_queue_close(void) | |||
2076 | reg_dma_rw_cfg dma_out_cfg, dma_in_cfg; | 2079 | reg_dma_rw_cfg dma_out_cfg, dma_in_cfg; |
2077 | 2080 | ||
2078 | /* Stop DMA. */ | 2081 | /* Stop DMA. */ |
2079 | dma_out_cfg = REG_RD(dma, regi_dma8, rw_cfg); | 2082 | dma_out_cfg = REG_RD(dma, OUT_DMA_INST, rw_cfg); |
2080 | dma_out_cfg.en = regk_dma_no; | 2083 | dma_out_cfg.en = regk_dma_no; |
2081 | REG_WR(dma, regi_dma8, rw_cfg, dma_out_cfg); | 2084 | REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_out_cfg); |
2082 | 2085 | ||
2083 | dma_in_cfg = REG_RD(dma, regi_dma9, rw_cfg); | 2086 | dma_in_cfg = REG_RD(dma, IN_DMA_INST, rw_cfg); |
2084 | dma_in_cfg.en = regk_dma_no; | 2087 | dma_in_cfg.en = regk_dma_no; |
2085 | REG_WR(dma, regi_dma9, rw_cfg, dma_in_cfg); | 2088 | REG_WR(dma, IN_DMA_INST, rw_cfg, dma_in_cfg); |
2086 | 2089 | ||
2087 | /* Disble the cryptocop. */ | 2090 | /* Disble the cryptocop. */ |
2088 | rw_cfg = REG_RD(strcop, regi_strcop, rw_cfg); | 2091 | rw_cfg = REG_RD(strcop, regi_strcop, rw_cfg); |
@@ -2226,10 +2229,11 @@ static void cryptocop_start_job(void) | |||
2226 | &pj->iop->ctx_out, (char*)virt_to_phys(&pj->iop->ctx_out))); | 2229 | &pj->iop->ctx_out, (char*)virt_to_phys(&pj->iop->ctx_out))); |
2227 | 2230 | ||
2228 | /* Start input DMA. */ | 2231 | /* Start input DMA. */ |
2229 | DMA_START_CONTEXT(regi_dma9, virt_to_phys(&pj->iop->ctx_in)); | 2232 | flush_dma_context(&pj->iop->ctx_in); |
2233 | DMA_START_CONTEXT(IN_DMA_INST, virt_to_phys(&pj->iop->ctx_in)); | ||
2230 | 2234 | ||
2231 | /* Start output DMA. */ | 2235 | /* Start output DMA. */ |
2232 | DMA_START_CONTEXT(regi_dma8, virt_to_phys(&pj->iop->ctx_out)); | 2236 | DMA_START_CONTEXT(OUT_DMA_INST, virt_to_phys(&pj->iop->ctx_out)); |
2233 | 2237 | ||
2234 | spin_unlock_irqrestore(&running_job_lock, running_job_flags); | 2238 | spin_unlock_irqrestore(&running_job_lock, running_job_flags); |
2235 | DEBUG(printk("cryptocop_start_job: exiting\n")); | 2239 | DEBUG(printk("cryptocop_start_job: exiting\n")); |
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c index f1edd2e359b2..c2fb7a5c1396 100644 --- a/arch/cris/arch-v32/drivers/i2c.c +++ b/arch/cris/arch-v32/drivers/i2c.c | |||
@@ -19,10 +19,10 @@ | |||
19 | *! | 19 | *! |
20 | *! --------------------------------------------------------------------------- | 20 | *! --------------------------------------------------------------------------- |
21 | *! | 21 | *! |
22 | *! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN | 22 | *! (C) Copyright 1999-2007 Axis Communications AB, LUND, SWEDEN |
23 | *! | 23 | *! |
24 | *!***************************************************************************/ | 24 | *!***************************************************************************/ |
25 | /* $Id: i2c.c,v 1.2 2005/05/09 15:29:49 starvik Exp $ */ | 25 | |
26 | /****************** INCLUDE FILES SECTION ***********************************/ | 26 | /****************** INCLUDE FILES SECTION ***********************************/ |
27 | 27 | ||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
@@ -79,6 +79,8 @@ static const char i2c_name[] = "i2c"; | |||
79 | 79 | ||
80 | #define i2c_delay(usecs) udelay(usecs) | 80 | #define i2c_delay(usecs) udelay(usecs) |
81 | 81 | ||
82 | static DEFINE_SPINLOCK(i2c_lock); /* Protect directions etc */ | ||
83 | |||
82 | /****************** VARIABLE SECTION ************************************/ | 84 | /****************** VARIABLE SECTION ************************************/ |
83 | 85 | ||
84 | static struct crisv32_iopin cris_i2c_clk; | 86 | static struct crisv32_iopin cris_i2c_clk; |
@@ -252,6 +254,7 @@ i2c_getack(void) | |||
252 | * generate ACK clock pulse | 254 | * generate ACK clock pulse |
253 | */ | 255 | */ |
254 | i2c_clk(I2C_CLOCK_HIGH); | 256 | i2c_clk(I2C_CLOCK_HIGH); |
257 | #if 0 | ||
255 | /* | 258 | /* |
256 | * Use PORT PB instead of I2C | 259 | * Use PORT PB instead of I2C |
257 | * for input. (I2C not working) | 260 | * for input. (I2C not working) |
@@ -264,6 +267,8 @@ i2c_getack(void) | |||
264 | i2c_data(1); | 267 | i2c_data(1); |
265 | i2c_disable(); | 268 | i2c_disable(); |
266 | i2c_dir_in(); | 269 | i2c_dir_in(); |
270 | #endif | ||
271 | |||
267 | /* | 272 | /* |
268 | * now wait for ack | 273 | * now wait for ack |
269 | */ | 274 | */ |
@@ -271,11 +276,11 @@ i2c_getack(void) | |||
271 | /* | 276 | /* |
272 | * check for ack | 277 | * check for ack |
273 | */ | 278 | */ |
274 | if(i2c_getbit()) | 279 | if (i2c_getbit()) |
275 | ack = 0; | 280 | ack = 0; |
276 | i2c_delay(CLOCK_HIGH_TIME/2); | 281 | i2c_delay(CLOCK_HIGH_TIME/2); |
277 | if(!ack){ | 282 | if (!ack) { |
278 | if(!i2c_getbit()) /* receiver pulled SDA low */ | 283 | if (!i2c_getbit()) /* receiver pulld SDA low */ |
279 | ack = 1; | 284 | ack = 1; |
280 | i2c_delay(CLOCK_HIGH_TIME/2); | 285 | i2c_delay(CLOCK_HIGH_TIME/2); |
281 | } | 286 | } |
@@ -285,6 +290,7 @@ i2c_getack(void) | |||
285 | * before we enable our output. If we keep data high | 290 | * before we enable our output. If we keep data high |
286 | * and enable output, we would generate a stop condition. | 291 | * and enable output, we would generate a stop condition. |
287 | */ | 292 | */ |
293 | #if 0 | ||
288 | i2c_data(I2C_DATA_LOW); | 294 | i2c_data(I2C_DATA_LOW); |
289 | 295 | ||
290 | /* | 296 | /* |
@@ -292,6 +298,7 @@ i2c_getack(void) | |||
292 | */ | 298 | */ |
293 | i2c_enable(); | 299 | i2c_enable(); |
294 | i2c_dir_out(); | 300 | i2c_dir_out(); |
301 | #endif | ||
295 | i2c_clk(I2C_CLOCK_LOW); | 302 | i2c_clk(I2C_CLOCK_LOW); |
296 | i2c_delay(CLOCK_HIGH_TIME/4); | 303 | i2c_delay(CLOCK_HIGH_TIME/4); |
297 | /* | 304 | /* |
@@ -375,6 +382,121 @@ i2c_sendnack(void) | |||
375 | 382 | ||
376 | /*#--------------------------------------------------------------------------- | 383 | /*#--------------------------------------------------------------------------- |
377 | *# | 384 | *# |
385 | *# FUNCTION NAME: i2c_write | ||
386 | *# | ||
387 | *# DESCRIPTION : Writes a value to an I2C device | ||
388 | *# | ||
389 | *#--------------------------------------------------------------------------*/ | ||
390 | int | ||
391 | i2c_write(unsigned char theSlave, void *data, size_t nbytes) | ||
392 | { | ||
393 | int error, cntr = 3; | ||
394 | unsigned char bytes_wrote = 0; | ||
395 | unsigned char value; | ||
396 | unsigned long flags; | ||
397 | |||
398 | spin_lock_irqsave(&i2c_lock, flags); | ||
399 | |||
400 | do { | ||
401 | error = 0; | ||
402 | |||
403 | i2c_start(); | ||
404 | /* | ||
405 | * send slave address | ||
406 | */ | ||
407 | i2c_outbyte((theSlave & 0xfe)); | ||
408 | /* | ||
409 | * wait for ack | ||
410 | */ | ||
411 | if (!i2c_getack()) | ||
412 | error = 1; | ||
413 | /* | ||
414 | * send data | ||
415 | */ | ||
416 | for (bytes_wrote = 0; bytes_wrote < nbytes; bytes_wrote++) { | ||
417 | memcpy(&value, data + bytes_wrote, sizeof value); | ||
418 | i2c_outbyte(value); | ||
419 | /* | ||
420 | * now it's time to wait for ack | ||
421 | */ | ||
422 | if (!i2c_getack()) | ||
423 | error |= 4; | ||
424 | } | ||
425 | /* | ||
426 | * end byte stream | ||
427 | */ | ||
428 | i2c_stop(); | ||
429 | |||
430 | } while (error && cntr--); | ||
431 | |||
432 | i2c_delay(CLOCK_LOW_TIME); | ||
433 | |||
434 | spin_unlock_irqrestore(&i2c_lock, flags); | ||
435 | |||
436 | return -error; | ||
437 | } | ||
438 | |||
439 | /*#--------------------------------------------------------------------------- | ||
440 | *# | ||
441 | *# FUNCTION NAME: i2c_read | ||
442 | *# | ||
443 | *# DESCRIPTION : Reads a value from an I2C device | ||
444 | *# | ||
445 | *#--------------------------------------------------------------------------*/ | ||
446 | int | ||
447 | i2c_read(unsigned char theSlave, void *data, size_t nbytes) | ||
448 | { | ||
449 | unsigned char b = 0; | ||
450 | unsigned char bytes_read = 0; | ||
451 | int error, cntr = 3; | ||
452 | unsigned long flags; | ||
453 | |||
454 | spin_lock_irqsave(&i2c_lock, flags); | ||
455 | |||
456 | do { | ||
457 | error = 0; | ||
458 | memset(data, 0, nbytes); | ||
459 | /* | ||
460 | * generate start condition | ||
461 | */ | ||
462 | i2c_start(); | ||
463 | /* | ||
464 | * send slave address | ||
465 | */ | ||
466 | i2c_outbyte((theSlave | 0x01)); | ||
467 | /* | ||
468 | * wait for ack | ||
469 | */ | ||
470 | if (!i2c_getack()) | ||
471 | error = 1; | ||
472 | /* | ||
473 | * fetch data | ||
474 | */ | ||
475 | for (bytes_read = 0; bytes_read < nbytes; bytes_read++) { | ||
476 | b = i2c_inbyte(); | ||
477 | memcpy(data + bytes_read, &b, sizeof b); | ||
478 | |||
479 | if (bytes_read < (nbytes - 1)) | ||
480 | i2c_sendack(); | ||
481 | } | ||
482 | /* | ||
483 | * last received byte needs to be nacked | ||
484 | * instead of acked | ||
485 | */ | ||
486 | i2c_sendnack(); | ||
487 | /* | ||
488 | * end sequence | ||
489 | */ | ||
490 | i2c_stop(); | ||
491 | } while (error && cntr--); | ||
492 | |||
493 | spin_unlock_irqrestore(&i2c_lock, flags); | ||
494 | |||
495 | return -error; | ||
496 | } | ||
497 | |||
498 | /*#--------------------------------------------------------------------------- | ||
499 | *# | ||
378 | *# FUNCTION NAME: i2c_writereg | 500 | *# FUNCTION NAME: i2c_writereg |
379 | *# | 501 | *# |
380 | *# DESCRIPTION : Writes a value to an I2C device | 502 | *# DESCRIPTION : Writes a value to an I2C device |
@@ -387,12 +509,10 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg, | |||
387 | int error, cntr = 3; | 509 | int error, cntr = 3; |
388 | unsigned long flags; | 510 | unsigned long flags; |
389 | 511 | ||
512 | spin_lock_irqsave(&i2c_lock, flags); | ||
513 | |||
390 | do { | 514 | do { |
391 | error = 0; | 515 | error = 0; |
392 | /* | ||
393 | * we don't like to be interrupted | ||
394 | */ | ||
395 | local_irq_save(flags); | ||
396 | 516 | ||
397 | i2c_start(); | 517 | i2c_start(); |
398 | /* | 518 | /* |
@@ -427,15 +547,12 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg, | |||
427 | * end byte stream | 547 | * end byte stream |
428 | */ | 548 | */ |
429 | i2c_stop(); | 549 | i2c_stop(); |
430 | /* | ||
431 | * enable interrupt again | ||
432 | */ | ||
433 | local_irq_restore(flags); | ||
434 | |||
435 | } while(error && cntr--); | 550 | } while(error && cntr--); |
436 | 551 | ||
437 | i2c_delay(CLOCK_LOW_TIME); | 552 | i2c_delay(CLOCK_LOW_TIME); |
438 | 553 | ||
554 | spin_unlock_irqrestore(&i2c_lock, flags); | ||
555 | |||
439 | return -error; | 556 | return -error; |
440 | } | 557 | } |
441 | 558 | ||
@@ -453,13 +570,11 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
453 | int error, cntr = 3; | 570 | int error, cntr = 3; |
454 | unsigned long flags; | 571 | unsigned long flags; |
455 | 572 | ||
573 | spin_lock_irqsave(&i2c_lock, flags); | ||
574 | |||
456 | do { | 575 | do { |
457 | error = 0; | 576 | error = 0; |
458 | /* | 577 | /* |
459 | * we don't like to be interrupted | ||
460 | */ | ||
461 | local_irq_save(flags); | ||
462 | /* | ||
463 | * generate start condition | 578 | * generate start condition |
464 | */ | 579 | */ |
465 | i2c_start(); | 580 | i2c_start(); |
@@ -482,7 +597,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
482 | * now it's time to wait for ack | 597 | * now it's time to wait for ack |
483 | */ | 598 | */ |
484 | if(!i2c_getack()) | 599 | if(!i2c_getack()) |
485 | error = 1; | 600 | error |= 2; |
486 | /* | 601 | /* |
487 | * repeat start condition | 602 | * repeat start condition |
488 | */ | 603 | */ |
@@ -496,7 +611,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
496 | * wait for ack | 611 | * wait for ack |
497 | */ | 612 | */ |
498 | if(!i2c_getack()) | 613 | if(!i2c_getack()) |
499 | error = 1; | 614 | error |= 4; |
500 | /* | 615 | /* |
501 | * fetch register | 616 | * fetch register |
502 | */ | 617 | */ |
@@ -510,13 +625,11 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
510 | * end sequence | 625 | * end sequence |
511 | */ | 626 | */ |
512 | i2c_stop(); | 627 | i2c_stop(); |
513 | /* | ||
514 | * enable interrupt again | ||
515 | */ | ||
516 | local_irq_restore(flags); | ||
517 | 628 | ||
518 | } while(error && cntr--); | 629 | } while(error && cntr--); |
519 | 630 | ||
631 | spin_unlock_irqrestore(&i2c_lock, flags); | ||
632 | |||
520 | return b; | 633 | return b; |
521 | } | 634 | } |
522 | 635 | ||
@@ -540,7 +653,7 @@ i2c_ioctl(struct inode *inode, struct file *file, | |||
540 | unsigned int cmd, unsigned long arg) | 653 | unsigned int cmd, unsigned long arg) |
541 | { | 654 | { |
542 | if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) { | 655 | if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) { |
543 | return -EINVAL; | 656 | return -ENOTTY; |
544 | } | 657 | } |
545 | 658 | ||
546 | switch (_IOC_NR(cmd)) { | 659 | switch (_IOC_NR(cmd)) { |
@@ -580,31 +693,52 @@ static const struct file_operations i2c_fops = { | |||
580 | .release = i2c_release, | 693 | .release = i2c_release, |
581 | }; | 694 | }; |
582 | 695 | ||
583 | int __init | 696 | static int __init i2c_init(void) |
584 | i2c_init(void) | ||
585 | { | 697 | { |
586 | int res; | 698 | static int res; |
699 | static int first = 1; | ||
587 | 700 | ||
588 | /* Setup and enable the Port B I2C interface */ | 701 | if (!first) |
702 | return res; | ||
589 | 703 | ||
590 | crisv32_io_get_name(&cris_i2c_data, CONFIG_ETRAX_I2C_DATA_PORT); | 704 | first = 0; |
591 | crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_I2C_CLK_PORT); | 705 | |
706 | /* Setup and enable the DATA and CLK pins */ | ||
707 | |||
708 | res = crisv32_io_get_name(&cris_i2c_data, | ||
709 | CONFIG_ETRAX_V32_I2C_DATA_PORT); | ||
710 | if (res < 0) | ||
711 | return res; | ||
712 | |||
713 | res = crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_V32_I2C_CLK_PORT); | ||
714 | crisv32_io_set_dir(&cris_i2c_clk, crisv32_io_dir_out); | ||
715 | |||
716 | return res; | ||
717 | } | ||
718 | |||
719 | |||
720 | static int __init i2c_register(void) | ||
721 | { | ||
722 | int res; | ||
723 | |||
724 | res = i2c_init(); | ||
725 | if (res < 0) | ||
726 | return res; | ||
592 | 727 | ||
593 | /* register char device */ | 728 | /* register char device */ |
594 | 729 | ||
595 | res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops); | 730 | res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops); |
596 | if(res < 0) { | 731 | if (res < 0) { |
597 | printk(KERN_ERR "i2c: couldn't get a major number.\n"); | 732 | printk(KERN_ERR "i2c: couldn't get a major number.\n"); |
598 | return res; | 733 | return res; |
599 | } | 734 | } |
600 | 735 | ||
601 | printk(KERN_INFO "I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n"); | 736 | printk(KERN_INFO |
737 | "I2C driver v2.2, (c) 1999-2007 Axis Communications AB\n"); | ||
602 | 738 | ||
603 | return 0; | 739 | return 0; |
604 | } | 740 | } |
605 | |||
606 | /* this makes sure that i2c_init is called during boot */ | 741 | /* this makes sure that i2c_init is called during boot */ |
607 | 742 | module_init(i2c_register); | |
608 | module_init(i2c_init); | ||
609 | 743 | ||
610 | /****************** END OF FILE i2c.c ********************************/ | 744 | /****************** END OF FILE i2c.c ********************************/ |
diff --git a/arch/cris/arch-v32/drivers/i2c.h b/arch/cris/arch-v32/drivers/i2c.h index bfe1a13f9f35..c073cf4ba016 100644 --- a/arch/cris/arch-v32/drivers/i2c.h +++ b/arch/cris/arch-v32/drivers/i2c.h | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | /* High level I2C actions */ | 4 | /* High level I2C actions */ |
5 | int __init i2c_init(void); | 5 | int __init i2c_init(void); |
6 | int i2c_write(unsigned char theSlave, void *data, size_t nbytes); | ||
7 | int i2c_read(unsigned char theSlave, void *data, size_t nbytes); | ||
6 | int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue); | 8 | int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue); |
7 | unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg); | 9 | unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg); |
8 | 10 | ||
diff --git a/arch/cris/arch-v32/drivers/iop_fw_load.c b/arch/cris/arch-v32/drivers/iop_fw_load.c index f4bdc1dfa320..3b3857ec1f15 100644 --- a/arch/cris/arch-v32/drivers/iop_fw_load.c +++ b/arch/cris/arch-v32/drivers/iop_fw_load.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* $Id: iop_fw_load.c,v 1.4 2005/04/07 09:27:46 larsv Exp $ | 1 | /* |
2 | * | ||
3 | * Firmware loader for ETRAX FS IO-Processor | 2 | * Firmware loader for ETRAX FS IO-Processor |
4 | * | 3 | * |
5 | * Copyright (C) 2004 Axis Communications AB | 4 | * Copyright (C) 2004 Axis Communications AB |
@@ -11,12 +10,13 @@ | |||
11 | #include <linux/device.h> | 10 | #include <linux/device.h> |
12 | #include <linux/firmware.h> | 11 | #include <linux/firmware.h> |
13 | 12 | ||
14 | #include <asm/arch/hwregs/reg_map.h> | 13 | #include <hwregs/reg_rdwr.h> |
15 | #include <asm/arch/hwregs/iop/iop_reg_space.h> | 14 | #include <hwregs/reg_map.h> |
16 | #include <asm/arch/hwregs/iop/iop_mpu_macros.h> | 15 | #include <hwregs/iop/iop_reg_space.h> |
17 | #include <asm/arch/hwregs/iop/iop_mpu_defs.h> | 16 | #include <hwregs/iop/iop_mpu_macros.h> |
18 | #include <asm/arch/hwregs/iop/iop_spu_defs.h> | 17 | #include <hwregs/iop/iop_mpu_defs.h> |
19 | #include <asm/arch/hwregs/iop/iop_sw_cpu_defs.h> | 18 | #include <hwregs/iop/iop_spu_defs.h> |
19 | #include <hwregs/iop/iop_sw_cpu_defs.h> | ||
20 | 20 | ||
21 | #define IOP_TIMEOUT 100 | 21 | #define IOP_TIMEOUT 100 |
22 | 22 | ||
diff --git a/arch/cris/arch-v32/drivers/mach-a3/Makefile b/arch/cris/arch-v32/drivers/mach-a3/Makefile new file mode 100644 index 000000000000..5c6d2a2a080e --- /dev/null +++ b/arch/cris/arch-v32/drivers/mach-a3/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for Etrax-specific drivers | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_ETRAX_NANDFLASH) += nandflash.o | ||
6 | obj-$(CONFIG_ETRAX_GPIO) += gpio.o | ||
diff --git a/arch/cris/arch-v32/drivers/mach-a3/gpio.c b/arch/cris/arch-v32/drivers/mach-a3/gpio.c new file mode 100644 index 000000000000..de107dad9f4f --- /dev/null +++ b/arch/cris/arch-v32/drivers/mach-a3/gpio.c | |||
@@ -0,0 +1,984 @@ | |||
1 | /* | ||
2 | * Artec-3 general port I/O device | ||
3 | * | ||
4 | * Copyright (c) 2007 Axis Communications AB | ||
5 | * | ||
6 | * Authors: Bjorn Wesen (initial version) | ||
7 | * Ola Knutsson (LED handling) | ||
8 | * Johan Adolfsson (read/set directions, write, port G, | ||
9 | * port to ETRAX FS. | ||
10 | * Ricard Wanderlof (PWM for Artpec-3) | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/ioport.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/fs.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/poll.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | |||
27 | #include <asm/etraxgpio.h> | ||
28 | #include <hwregs/reg_map.h> | ||
29 | #include <hwregs/reg_rdwr.h> | ||
30 | #include <hwregs/gio_defs.h> | ||
31 | #include <hwregs/intr_vect_defs.h> | ||
32 | #include <asm/io.h> | ||
33 | #include <asm/system.h> | ||
34 | #include <asm/irq.h> | ||
35 | #include <asm/arch/mach/pinmux.h> | ||
36 | |||
37 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
38 | #include "../i2c.h" | ||
39 | |||
40 | #define VIRT_I2C_ADDR 0x40 | ||
41 | #endif | ||
42 | |||
43 | /* The following gio ports on ARTPEC-3 is available: | ||
44 | * pa 32 bits | ||
45 | * pb 32 bits | ||
46 | * pc 16 bits | ||
47 | * each port has a rw_px_dout, r_px_din and rw_px_oe register. | ||
48 | */ | ||
49 | |||
50 | #define GPIO_MAJOR 120 /* experimental MAJOR number */ | ||
51 | |||
52 | #define I2C_INTERRUPT_BITS 0x300 /* i2c0_done and i2c1_done bits */ | ||
53 | |||
54 | #define D(x) | ||
55 | |||
56 | #if 0 | ||
57 | static int dp_cnt; | ||
58 | #define DP(x) \ | ||
59 | do { \ | ||
60 | dp_cnt++; \ | ||
61 | if (dp_cnt % 1000 == 0) \ | ||
62 | x; \ | ||
63 | } while (0) | ||
64 | #else | ||
65 | #define DP(x) | ||
66 | #endif | ||
67 | |||
68 | static char gpio_name[] = "etrax gpio"; | ||
69 | |||
70 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
71 | static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, | ||
72 | unsigned long arg); | ||
73 | #endif | ||
74 | static int gpio_ioctl(struct inode *inode, struct file *file, | ||
75 | unsigned int cmd, unsigned long arg); | ||
76 | static ssize_t gpio_write(struct file *file, const char __user *buf, | ||
77 | size_t count, loff_t *off); | ||
78 | static int gpio_open(struct inode *inode, struct file *filp); | ||
79 | static int gpio_release(struct inode *inode, struct file *filp); | ||
80 | static unsigned int gpio_poll(struct file *filp, | ||
81 | struct poll_table_struct *wait); | ||
82 | |||
83 | /* private data per open() of this driver */ | ||
84 | |||
85 | struct gpio_private { | ||
86 | struct gpio_private *next; | ||
87 | /* The IO_CFG_WRITE_MODE_VALUE only support 8 bits: */ | ||
88 | unsigned char clk_mask; | ||
89 | unsigned char data_mask; | ||
90 | unsigned char write_msb; | ||
91 | unsigned char pad1; | ||
92 | /* These fields are generic */ | ||
93 | unsigned long highalarm, lowalarm; | ||
94 | wait_queue_head_t alarm_wq; | ||
95 | int minor; | ||
96 | }; | ||
97 | |||
98 | static void gpio_set_alarm(struct gpio_private *priv); | ||
99 | static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg); | ||
100 | static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd, | ||
101 | unsigned long arg); | ||
102 | |||
103 | |||
104 | /* linked list of alarms to check for */ | ||
105 | |||
106 | static struct gpio_private *alarmlist; | ||
107 | |||
108 | static int wanted_interrupts; | ||
109 | |||
110 | static DEFINE_SPINLOCK(gpio_lock); | ||
111 | |||
112 | #define NUM_PORTS (GPIO_MINOR_LAST+1) | ||
113 | #define GIO_REG_RD_ADDR(reg) \ | ||
114 | (unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg) | ||
115 | #define GIO_REG_WR_ADDR(reg) \ | ||
116 | (unsigned long *)(regi_gio + REG_WR_ADDR_gio_##reg) | ||
117 | static unsigned long led_dummy; | ||
118 | static unsigned long port_d_dummy; /* Only input on Artpec-3 */ | ||
119 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
120 | static unsigned long port_e_dummy; /* Non existent on Artpec-3 */ | ||
121 | static unsigned long virtual_dummy; | ||
122 | static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE; | ||
123 | static unsigned short cached_virtual_gpio_read; | ||
124 | #endif | ||
125 | |||
126 | static unsigned long *data_out[NUM_PORTS] = { | ||
127 | GIO_REG_WR_ADDR(rw_pa_dout), | ||
128 | GIO_REG_WR_ADDR(rw_pb_dout), | ||
129 | &led_dummy, | ||
130 | GIO_REG_WR_ADDR(rw_pc_dout), | ||
131 | &port_d_dummy, | ||
132 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
133 | &port_e_dummy, | ||
134 | &virtual_dummy, | ||
135 | #endif | ||
136 | }; | ||
137 | |||
138 | static unsigned long *data_in[NUM_PORTS] = { | ||
139 | GIO_REG_RD_ADDR(r_pa_din), | ||
140 | GIO_REG_RD_ADDR(r_pb_din), | ||
141 | &led_dummy, | ||
142 | GIO_REG_RD_ADDR(r_pc_din), | ||
143 | GIO_REG_RD_ADDR(r_pd_din), | ||
144 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
145 | &port_e_dummy, | ||
146 | &virtual_dummy, | ||
147 | #endif | ||
148 | }; | ||
149 | |||
150 | static unsigned long changeable_dir[NUM_PORTS] = { | ||
151 | CONFIG_ETRAX_PA_CHANGEABLE_DIR, | ||
152 | CONFIG_ETRAX_PB_CHANGEABLE_DIR, | ||
153 | 0, | ||
154 | CONFIG_ETRAX_PC_CHANGEABLE_DIR, | ||
155 | 0, | ||
156 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
157 | 0, | ||
158 | CONFIG_ETRAX_PV_CHANGEABLE_DIR, | ||
159 | #endif | ||
160 | }; | ||
161 | |||
162 | static unsigned long changeable_bits[NUM_PORTS] = { | ||
163 | CONFIG_ETRAX_PA_CHANGEABLE_BITS, | ||
164 | CONFIG_ETRAX_PB_CHANGEABLE_BITS, | ||
165 | 0, | ||
166 | CONFIG_ETRAX_PC_CHANGEABLE_BITS, | ||
167 | 0, | ||
168 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
169 | 0, | ||
170 | CONFIG_ETRAX_PV_CHANGEABLE_BITS, | ||
171 | #endif | ||
172 | }; | ||
173 | |||
174 | static unsigned long *dir_oe[NUM_PORTS] = { | ||
175 | GIO_REG_WR_ADDR(rw_pa_oe), | ||
176 | GIO_REG_WR_ADDR(rw_pb_oe), | ||
177 | &led_dummy, | ||
178 | GIO_REG_WR_ADDR(rw_pc_oe), | ||
179 | &port_d_dummy, | ||
180 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
181 | &port_e_dummy, | ||
182 | &virtual_rw_pv_oe, | ||
183 | #endif | ||
184 | }; | ||
185 | |||
186 | static void gpio_set_alarm(struct gpio_private *priv) | ||
187 | { | ||
188 | int bit; | ||
189 | int intr_cfg; | ||
190 | int mask; | ||
191 | int pins; | ||
192 | unsigned long flags; | ||
193 | |||
194 | spin_lock_irqsave(&gpio_lock, flags); | ||
195 | intr_cfg = REG_RD_INT(gio, regi_gio, rw_intr_cfg); | ||
196 | pins = REG_RD_INT(gio, regi_gio, rw_intr_pins); | ||
197 | mask = REG_RD_INT(gio, regi_gio, rw_intr_mask) & I2C_INTERRUPT_BITS; | ||
198 | |||
199 | for (bit = 0; bit < 32; bit++) { | ||
200 | int intr = bit % 8; | ||
201 | int pin = bit / 8; | ||
202 | if (priv->minor < GPIO_MINOR_LEDS) | ||
203 | pin += priv->minor * 4; | ||
204 | else | ||
205 | pin += (priv->minor - 1) * 4; | ||
206 | |||
207 | if (priv->highalarm & (1<<bit)) { | ||
208 | intr_cfg |= (regk_gio_hi << (intr * 3)); | ||
209 | mask |= 1 << intr; | ||
210 | wanted_interrupts = mask & 0xff; | ||
211 | pins |= pin << (intr * 4); | ||
212 | } else if (priv->lowalarm & (1<<bit)) { | ||
213 | intr_cfg |= (regk_gio_lo << (intr * 3)); | ||
214 | mask |= 1 << intr; | ||
215 | wanted_interrupts = mask & 0xff; | ||
216 | pins |= pin << (intr * 4); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | REG_WR_INT(gio, regi_gio, rw_intr_cfg, intr_cfg); | ||
221 | REG_WR_INT(gio, regi_gio, rw_intr_pins, pins); | ||
222 | REG_WR_INT(gio, regi_gio, rw_intr_mask, mask); | ||
223 | |||
224 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
225 | } | ||
226 | |||
227 | static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait) | ||
228 | { | ||
229 | unsigned int mask = 0; | ||
230 | struct gpio_private *priv = file->private_data; | ||
231 | unsigned long data; | ||
232 | unsigned long tmp; | ||
233 | |||
234 | if (priv->minor >= GPIO_MINOR_PWM0 && | ||
235 | priv->minor <= GPIO_MINOR_LAST_PWM) | ||
236 | return 0; | ||
237 | |||
238 | poll_wait(file, &priv->alarm_wq, wait); | ||
239 | if (priv->minor <= GPIO_MINOR_D) { | ||
240 | data = readl(data_in[priv->minor]); | ||
241 | REG_WR_INT(gio, regi_gio, rw_ack_intr, wanted_interrupts); | ||
242 | tmp = REG_RD_INT(gio, regi_gio, rw_intr_mask); | ||
243 | tmp &= I2C_INTERRUPT_BITS; | ||
244 | tmp |= wanted_interrupts; | ||
245 | REG_WR_INT(gio, regi_gio, rw_intr_mask, tmp); | ||
246 | } else | ||
247 | return 0; | ||
248 | |||
249 | if ((data & priv->highalarm) || (~data & priv->lowalarm)) | ||
250 | mask = POLLIN|POLLRDNORM; | ||
251 | |||
252 | DP(printk(KERN_DEBUG "gpio_poll ready: mask 0x%08X\n", mask)); | ||
253 | return mask; | ||
254 | } | ||
255 | |||
256 | static irqreturn_t gpio_interrupt(int irq, void *dev_id) | ||
257 | { | ||
258 | reg_gio_rw_intr_mask intr_mask; | ||
259 | reg_gio_r_masked_intr masked_intr; | ||
260 | reg_gio_rw_ack_intr ack_intr; | ||
261 | unsigned long flags; | ||
262 | unsigned long tmp; | ||
263 | unsigned long tmp2; | ||
264 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
265 | unsigned char enable_gpiov_ack = 0; | ||
266 | #endif | ||
267 | |||
268 | /* Find what PA interrupts are active */ | ||
269 | masked_intr = REG_RD(gio, regi_gio, r_masked_intr); | ||
270 | tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr); | ||
271 | |||
272 | /* Find those that we have enabled */ | ||
273 | spin_lock_irqsave(&gpio_lock, flags); | ||
274 | tmp &= wanted_interrupts; | ||
275 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
276 | |||
277 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
278 | /* Something changed on virtual GPIO. Interrupt is acked by | ||
279 | * reading the device. | ||
280 | */ | ||
281 | if (tmp & (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN)) { | ||
282 | i2c_read(VIRT_I2C_ADDR, (void *)&cached_virtual_gpio_read, | ||
283 | sizeof(cached_virtual_gpio_read)); | ||
284 | enable_gpiov_ack = 1; | ||
285 | } | ||
286 | #endif | ||
287 | |||
288 | /* Ack them */ | ||
289 | ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp); | ||
290 | REG_WR(gio, regi_gio, rw_ack_intr, ack_intr); | ||
291 | |||
292 | /* Disable those interrupts.. */ | ||
293 | intr_mask = REG_RD(gio, regi_gio, rw_intr_mask); | ||
294 | tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask); | ||
295 | tmp2 &= ~tmp; | ||
296 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
297 | /* Do not disable interrupt on virtual GPIO. Changes on virtual | ||
298 | * pins are only noticed by an interrupt. | ||
299 | */ | ||
300 | if (enable_gpiov_ack) | ||
301 | tmp2 |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); | ||
302 | #endif | ||
303 | intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2); | ||
304 | REG_WR(gio, regi_gio, rw_intr_mask, intr_mask); | ||
305 | |||
306 | return IRQ_RETVAL(tmp); | ||
307 | } | ||
308 | |||
309 | static void gpio_write_bit(unsigned long *port, unsigned char data, int bit, | ||
310 | unsigned char clk_mask, unsigned char data_mask) | ||
311 | { | ||
312 | unsigned long shadow = readl(port) & ~clk_mask; | ||
313 | writel(shadow, port); | ||
314 | if (data & 1 << bit) | ||
315 | shadow |= data_mask; | ||
316 | else | ||
317 | shadow &= ~data_mask; | ||
318 | writel(shadow, port); | ||
319 | /* For FPGA: min 5.0ns (DCC) before CCLK high */ | ||
320 | shadow |= clk_mask; | ||
321 | writel(shadow, port); | ||
322 | } | ||
323 | |||
324 | static void gpio_write_byte(struct gpio_private *priv, unsigned long *port, | ||
325 | unsigned char data) | ||
326 | { | ||
327 | int i; | ||
328 | |||
329 | if (priv->write_msb) | ||
330 | for (i = 7; i >= 0; i--) | ||
331 | gpio_write_bit(port, data, i, priv->clk_mask, | ||
332 | priv->data_mask); | ||
333 | else | ||
334 | for (i = 0; i <= 7; i++) | ||
335 | gpio_write_bit(port, data, i, priv->clk_mask, | ||
336 | priv->data_mask); | ||
337 | } | ||
338 | |||
339 | |||
340 | static ssize_t gpio_write(struct file *file, const char __user *buf, | ||
341 | size_t count, loff_t *off) | ||
342 | { | ||
343 | struct gpio_private *priv = file->private_data; | ||
344 | unsigned long flags; | ||
345 | ssize_t retval = count; | ||
346 | /* Only bits 0-7 may be used for write operations but allow all | ||
347 | devices except leds... */ | ||
348 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
349 | if (priv->minor == GPIO_MINOR_V) | ||
350 | return -EFAULT; | ||
351 | #endif | ||
352 | if (priv->minor == GPIO_MINOR_LEDS) | ||
353 | return -EFAULT; | ||
354 | |||
355 | if (priv->minor >= GPIO_MINOR_PWM0 && | ||
356 | priv->minor <= GPIO_MINOR_LAST_PWM) | ||
357 | return -EFAULT; | ||
358 | |||
359 | if (!access_ok(VERIFY_READ, buf, count)) | ||
360 | return -EFAULT; | ||
361 | |||
362 | /* It must have been configured using the IO_CFG_WRITE_MODE */ | ||
363 | /* Perhaps a better error code? */ | ||
364 | if (priv->clk_mask == 0 || priv->data_mask == 0) | ||
365 | return -EPERM; | ||
366 | |||
367 | D(printk(KERN_DEBUG "gpio_write: %lu to data 0x%02X clk 0x%02X " | ||
368 | "msb: %i\n", | ||
369 | count, priv->data_mask, priv->clk_mask, priv->write_msb)); | ||
370 | |||
371 | spin_lock_irqsave(&gpio_lock, flags); | ||
372 | |||
373 | while (count--) | ||
374 | gpio_write_byte(priv, data_out[priv->minor], *buf++); | ||
375 | |||
376 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
377 | return retval; | ||
378 | } | ||
379 | |||
380 | static int gpio_open(struct inode *inode, struct file *filp) | ||
381 | { | ||
382 | struct gpio_private *priv; | ||
383 | int p = iminor(inode); | ||
384 | |||
385 | if (p > GPIO_MINOR_LAST_PWM || | ||
386 | (p > GPIO_MINOR_LAST && p < GPIO_MINOR_PWM0)) | ||
387 | return -EINVAL; | ||
388 | |||
389 | priv = kmalloc(sizeof(struct gpio_private), GFP_KERNEL); | ||
390 | |||
391 | if (!priv) | ||
392 | return -ENOMEM; | ||
393 | memset(priv, 0, sizeof(*priv)); | ||
394 | |||
395 | priv->minor = p; | ||
396 | filp->private_data = priv; | ||
397 | |||
398 | /* initialize the io/alarm struct, not for PWM ports though */ | ||
399 | if (p <= GPIO_MINOR_LAST) { | ||
400 | |||
401 | priv->clk_mask = 0; | ||
402 | priv->data_mask = 0; | ||
403 | priv->highalarm = 0; | ||
404 | priv->lowalarm = 0; | ||
405 | |||
406 | init_waitqueue_head(&priv->alarm_wq); | ||
407 | |||
408 | /* link it into our alarmlist */ | ||
409 | spin_lock_irq(&gpio_lock); | ||
410 | priv->next = alarmlist; | ||
411 | alarmlist = priv; | ||
412 | spin_unlock_irq(&gpio_lock); | ||
413 | } | ||
414 | |||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | static int gpio_release(struct inode *inode, struct file *filp) | ||
419 | { | ||
420 | struct gpio_private *p; | ||
421 | struct gpio_private *todel; | ||
422 | /* local copies while updating them: */ | ||
423 | unsigned long a_high, a_low; | ||
424 | |||
425 | /* prepare to free private structure */ | ||
426 | todel = filp->private_data; | ||
427 | |||
428 | /* unlink from alarmlist - only for non-PWM ports though */ | ||
429 | if (todel->minor <= GPIO_MINOR_LAST) { | ||
430 | spin_lock_irq(&gpio_lock); | ||
431 | p = alarmlist; | ||
432 | |||
433 | if (p == todel) | ||
434 | alarmlist = todel->next; | ||
435 | else { | ||
436 | while (p->next != todel) | ||
437 | p = p->next; | ||
438 | p->next = todel->next; | ||
439 | } | ||
440 | |||
441 | /* Check if there are still any alarms set */ | ||
442 | p = alarmlist; | ||
443 | a_high = 0; | ||
444 | a_low = 0; | ||
445 | while (p) { | ||
446 | if (p->minor == GPIO_MINOR_A) { | ||
447 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
448 | p->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); | ||
449 | #endif | ||
450 | a_high |= p->highalarm; | ||
451 | a_low |= p->lowalarm; | ||
452 | } | ||
453 | |||
454 | p = p->next; | ||
455 | } | ||
456 | |||
457 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
458 | /* Variable 'a_low' needs to be set here again | ||
459 | * to ensure that interrupt for virtual GPIO is handled. | ||
460 | */ | ||
461 | a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); | ||
462 | #endif | ||
463 | |||
464 | spin_unlock_irq(&gpio_lock); | ||
465 | } | ||
466 | kfree(todel); | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | /* Main device API. ioctl's to read/set/clear bits, as well as to | ||
472 | * set alarms to wait for using a subsequent select(). | ||
473 | */ | ||
474 | |||
475 | inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg) | ||
476 | { | ||
477 | /* Set direction 0=unchanged 1=input, | ||
478 | * return mask with 1=input | ||
479 | */ | ||
480 | unsigned long flags; | ||
481 | unsigned long dir_shadow; | ||
482 | |||
483 | spin_lock_irqsave(&gpio_lock, flags); | ||
484 | |||
485 | dir_shadow = readl(dir_oe[priv->minor]) & | ||
486 | ~(arg & changeable_dir[priv->minor]); | ||
487 | writel(dir_shadow, dir_oe[priv->minor]); | ||
488 | |||
489 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
490 | |||
491 | if (priv->minor == GPIO_MINOR_C) | ||
492 | dir_shadow ^= 0xFFFF; /* Only 16 bits */ | ||
493 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
494 | else if (priv->minor == GPIO_MINOR_V) | ||
495 | dir_shadow ^= 0xFFFF; /* Only 16 bits */ | ||
496 | #endif | ||
497 | else | ||
498 | dir_shadow ^= 0xFFFFFFFF; /* PA, PB and PD 32 bits */ | ||
499 | |||
500 | return dir_shadow; | ||
501 | |||
502 | } /* setget_input */ | ||
503 | |||
504 | static inline unsigned long setget_output(struct gpio_private *priv, | ||
505 | unsigned long arg) | ||
506 | { | ||
507 | unsigned long flags; | ||
508 | unsigned long dir_shadow; | ||
509 | |||
510 | spin_lock_irqsave(&gpio_lock, flags); | ||
511 | |||
512 | dir_shadow = readl(dir_oe[priv->minor]) | | ||
513 | (arg & changeable_dir[priv->minor]); | ||
514 | writel(dir_shadow, dir_oe[priv->minor]); | ||
515 | |||
516 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
517 | return dir_shadow; | ||
518 | } /* setget_output */ | ||
519 | |||
520 | static int gpio_ioctl(struct inode *inode, struct file *file, | ||
521 | unsigned int cmd, unsigned long arg) | ||
522 | { | ||
523 | unsigned long flags; | ||
524 | unsigned long val; | ||
525 | unsigned long shadow; | ||
526 | struct gpio_private *priv = file->private_data; | ||
527 | |||
528 | if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) | ||
529 | return -ENOTTY; | ||
530 | |||
531 | /* Check for special ioctl handlers first */ | ||
532 | |||
533 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
534 | if (priv->minor == GPIO_MINOR_V) | ||
535 | return virtual_gpio_ioctl(file, cmd, arg); | ||
536 | #endif | ||
537 | |||
538 | if (priv->minor == GPIO_MINOR_LEDS) | ||
539 | return gpio_leds_ioctl(cmd, arg); | ||
540 | |||
541 | if (priv->minor >= GPIO_MINOR_PWM0 && | ||
542 | priv->minor <= GPIO_MINOR_LAST_PWM) | ||
543 | return gpio_pwm_ioctl(priv, cmd, arg); | ||
544 | |||
545 | switch (_IOC_NR(cmd)) { | ||
546 | case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ | ||
547 | /* Read the port. */ | ||
548 | return readl(data_in[priv->minor]); | ||
549 | case IO_SETBITS: | ||
550 | spin_lock_irqsave(&gpio_lock, flags); | ||
551 | /* Set changeable bits with a 1 in arg. */ | ||
552 | shadow = readl(data_out[priv->minor]) | | ||
553 | (arg & changeable_bits[priv->minor]); | ||
554 | writel(shadow, data_out[priv->minor]); | ||
555 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
556 | break; | ||
557 | case IO_CLRBITS: | ||
558 | spin_lock_irqsave(&gpio_lock, flags); | ||
559 | /* Clear changeable bits with a 1 in arg. */ | ||
560 | shadow = readl(data_out[priv->minor]) & | ||
561 | ~(arg & changeable_bits[priv->minor]); | ||
562 | writel(shadow, data_out[priv->minor]); | ||
563 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
564 | break; | ||
565 | case IO_HIGHALARM: | ||
566 | /* Set alarm when bits with 1 in arg go high. */ | ||
567 | priv->highalarm |= arg; | ||
568 | gpio_set_alarm(priv); | ||
569 | break; | ||
570 | case IO_LOWALARM: | ||
571 | /* Set alarm when bits with 1 in arg go low. */ | ||
572 | priv->lowalarm |= arg; | ||
573 | gpio_set_alarm(priv); | ||
574 | break; | ||
575 | case IO_CLRALARM: | ||
576 | /* Clear alarm for bits with 1 in arg. */ | ||
577 | priv->highalarm &= ~arg; | ||
578 | priv->lowalarm &= ~arg; | ||
579 | gpio_set_alarm(priv); | ||
580 | break; | ||
581 | case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ | ||
582 | /* Read direction 0=input 1=output */ | ||
583 | return readl(dir_oe[priv->minor]); | ||
584 | |||
585 | case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */ | ||
586 | /* Set direction 0=unchanged 1=input, | ||
587 | * return mask with 1=input | ||
588 | */ | ||
589 | return setget_input(priv, arg); | ||
590 | |||
591 | case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */ | ||
592 | /* Set direction 0=unchanged 1=output, | ||
593 | * return mask with 1=output | ||
594 | */ | ||
595 | return setget_output(priv, arg); | ||
596 | |||
597 | case IO_CFG_WRITE_MODE: | ||
598 | { | ||
599 | int res = -EPERM; | ||
600 | unsigned long dir_shadow, clk_mask, data_mask, write_msb; | ||
601 | |||
602 | clk_mask = arg & 0xFF; | ||
603 | data_mask = (arg >> 8) & 0xFF; | ||
604 | write_msb = (arg >> 16) & 0x01; | ||
605 | |||
606 | /* Check if we're allowed to change the bits and | ||
607 | * the direction is correct | ||
608 | */ | ||
609 | spin_lock_irqsave(&gpio_lock, flags); | ||
610 | dir_shadow = readl(dir_oe[priv->minor]); | ||
611 | if ((clk_mask & changeable_bits[priv->minor]) && | ||
612 | (data_mask & changeable_bits[priv->minor]) && | ||
613 | (clk_mask & dir_shadow) && | ||
614 | (data_mask & dir_shadow)) { | ||
615 | priv->clk_mask = clk_mask; | ||
616 | priv->data_mask = data_mask; | ||
617 | priv->write_msb = write_msb; | ||
618 | res = 0; | ||
619 | } | ||
620 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
621 | |||
622 | return res; | ||
623 | } | ||
624 | case IO_READ_INBITS: | ||
625 | /* *arg is result of reading the input pins */ | ||
626 | val = readl(data_in[priv->minor]); | ||
627 | if (copy_to_user((void __user *)arg, &val, sizeof(val))) | ||
628 | return -EFAULT; | ||
629 | return 0; | ||
630 | case IO_READ_OUTBITS: | ||
631 | /* *arg is result of reading the output shadow */ | ||
632 | val = *data_out[priv->minor]; | ||
633 | if (copy_to_user((void __user *)arg, &val, sizeof(val))) | ||
634 | return -EFAULT; | ||
635 | break; | ||
636 | case IO_SETGET_INPUT: | ||
637 | /* bits set in *arg is set to input, | ||
638 | * *arg updated with current input pins. | ||
639 | */ | ||
640 | if (copy_from_user(&val, (void __user *)arg, sizeof(val))) | ||
641 | return -EFAULT; | ||
642 | val = setget_input(priv, val); | ||
643 | if (copy_to_user((void __user *)arg, &val, sizeof(val))) | ||
644 | return -EFAULT; | ||
645 | break; | ||
646 | case IO_SETGET_OUTPUT: | ||
647 | /* bits set in *arg is set to output, | ||
648 | * *arg updated with current output pins. | ||
649 | */ | ||
650 | if (copy_from_user(&val, (void __user *)arg, sizeof(val))) | ||
651 | return -EFAULT; | ||
652 | val = setget_output(priv, val); | ||
653 | if (copy_to_user((void __user *)arg, &val, sizeof(val))) | ||
654 | return -EFAULT; | ||
655 | break; | ||
656 | default: | ||
657 | return -EINVAL; | ||
658 | } /* switch */ | ||
659 | |||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
664 | static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, | ||
665 | unsigned long arg) | ||
666 | { | ||
667 | unsigned long flags; | ||
668 | unsigned short val; | ||
669 | unsigned short shadow; | ||
670 | struct gpio_private *priv = file->private_data; | ||
671 | |||
672 | switch (_IOC_NR(cmd)) { | ||
673 | case IO_SETBITS: | ||
674 | spin_lock_irqsave(&gpio_lock, flags); | ||
675 | /* Set changeable bits with a 1 in arg. */ | ||
676 | i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); | ||
677 | shadow |= ~readl(dir_oe[priv->minor]) | | ||
678 | (arg & changeable_bits[priv->minor]); | ||
679 | i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); | ||
680 | spin_lock_irqrestore(&gpio_lock, flags); | ||
681 | break; | ||
682 | case IO_CLRBITS: | ||
683 | spin_lock_irqsave(&gpio_lock, flags); | ||
684 | /* Clear changeable bits with a 1 in arg. */ | ||
685 | i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); | ||
686 | shadow |= ~readl(dir_oe[priv->minor]) & | ||
687 | ~(arg & changeable_bits[priv->minor]); | ||
688 | i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); | ||
689 | spin_lock_irqrestore(&gpio_lock, flags); | ||
690 | break; | ||
691 | case IO_HIGHALARM: | ||
692 | /* Set alarm when bits with 1 in arg go high. */ | ||
693 | priv->highalarm |= arg; | ||
694 | break; | ||
695 | case IO_LOWALARM: | ||
696 | /* Set alarm when bits with 1 in arg go low. */ | ||
697 | priv->lowalarm |= arg; | ||
698 | break; | ||
699 | case IO_CLRALARM: | ||
700 | /* Clear alarm for bits with 1 in arg. */ | ||
701 | priv->highalarm &= ~arg; | ||
702 | priv->lowalarm &= ~arg; | ||
703 | break; | ||
704 | case IO_CFG_WRITE_MODE: | ||
705 | { | ||
706 | unsigned long dir_shadow; | ||
707 | dir_shadow = readl(dir_oe[priv->minor]); | ||
708 | |||
709 | priv->clk_mask = arg & 0xFF; | ||
710 | priv->data_mask = (arg >> 8) & 0xFF; | ||
711 | priv->write_msb = (arg >> 16) & 0x01; | ||
712 | /* Check if we're allowed to change the bits and | ||
713 | * the direction is correct | ||
714 | */ | ||
715 | if (!((priv->clk_mask & changeable_bits[priv->minor]) && | ||
716 | (priv->data_mask & changeable_bits[priv->minor]) && | ||
717 | (priv->clk_mask & dir_shadow) && | ||
718 | (priv->data_mask & dir_shadow))) { | ||
719 | priv->clk_mask = 0; | ||
720 | priv->data_mask = 0; | ||
721 | return -EPERM; | ||
722 | } | ||
723 | break; | ||
724 | } | ||
725 | case IO_READ_INBITS: | ||
726 | /* *arg is result of reading the input pins */ | ||
727 | val = cached_virtual_gpio_read & ~readl(dir_oe[priv->minor]); | ||
728 | if (copy_to_user((void __user *)arg, &val, sizeof(val))) | ||
729 | return -EFAULT; | ||
730 | return 0; | ||
731 | |||
732 | case IO_READ_OUTBITS: | ||
733 | /* *arg is result of reading the output shadow */ | ||
734 | i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val)); | ||
735 | val &= readl(dir_oe[priv->minor]); | ||
736 | if (copy_to_user((void __user *)arg, &val, sizeof(val))) | ||
737 | return -EFAULT; | ||
738 | break; | ||
739 | case IO_SETGET_INPUT: | ||
740 | { | ||
741 | /* bits set in *arg is set to input, | ||
742 | * *arg updated with current input pins. | ||
743 | */ | ||
744 | unsigned short input_mask = ~readl(dir_oe[priv->minor]); | ||
745 | if (copy_from_user(&val, (void __user *)arg, sizeof(val))) | ||
746 | return -EFAULT; | ||
747 | val = setget_input(priv, val); | ||
748 | if (copy_to_user((void __user *)arg, &val, sizeof(val))) | ||
749 | return -EFAULT; | ||
750 | if ((input_mask & val) != input_mask) { | ||
751 | /* Input pins changed. All ports desired as input | ||
752 | * should be set to logic 1. | ||
753 | */ | ||
754 | unsigned short change = input_mask ^ val; | ||
755 | i2c_read(VIRT_I2C_ADDR, (void *)&shadow, | ||
756 | sizeof(shadow)); | ||
757 | shadow &= ~change; | ||
758 | shadow |= val; | ||
759 | i2c_write(VIRT_I2C_ADDR, (void *)&shadow, | ||
760 | sizeof(shadow)); | ||
761 | } | ||
762 | break; | ||
763 | } | ||
764 | case IO_SETGET_OUTPUT: | ||
765 | /* bits set in *arg is set to output, | ||
766 | * *arg updated with current output pins. | ||
767 | */ | ||
768 | if (copy_from_user(&val, (void __user *)arg, sizeof(val))) | ||
769 | return -EFAULT; | ||
770 | val = setget_output(priv, val); | ||
771 | if (copy_to_user((void __user *)arg, &val, sizeof(val))) | ||
772 | return -EFAULT; | ||
773 | break; | ||
774 | default: | ||
775 | return -EINVAL; | ||
776 | } /* switch */ | ||
777 | return 0; | ||
778 | } | ||
779 | #endif /* CONFIG_ETRAX_VIRTUAL_GPIO */ | ||
780 | |||
781 | static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg) | ||
782 | { | ||
783 | unsigned char green; | ||
784 | unsigned char red; | ||
785 | |||
786 | switch (_IOC_NR(cmd)) { | ||
787 | case IO_LEDACTIVE_SET: | ||
788 | green = ((unsigned char) arg) & 1; | ||
789 | red = (((unsigned char) arg) >> 1) & 1; | ||
790 | CRIS_LED_ACTIVE_SET_G(green); | ||
791 | CRIS_LED_ACTIVE_SET_R(red); | ||
792 | break; | ||
793 | |||
794 | default: | ||
795 | return -EINVAL; | ||
796 | } /* switch */ | ||
797 | |||
798 | return 0; | ||
799 | } | ||
800 | |||
801 | static int gpio_pwm_set_mode(unsigned long arg, int pwm_port) | ||
802 | { | ||
803 | int pinmux_pwm = pinmux_pwm0 + pwm_port; | ||
804 | int mode; | ||
805 | reg_gio_rw_pwm0_ctrl rw_pwm_ctrl = { | ||
806 | .ccd_val = 0, | ||
807 | .ccd_override = regk_gio_no, | ||
808 | .mode = regk_gio_no | ||
809 | }; | ||
810 | int allocstatus; | ||
811 | |||
812 | if (get_user(mode, &((struct io_pwm_set_mode *) arg)->mode)) | ||
813 | return -EFAULT; | ||
814 | rw_pwm_ctrl.mode = mode; | ||
815 | if (mode != PWM_OFF) | ||
816 | allocstatus = crisv32_pinmux_alloc_fixed(pinmux_pwm); | ||
817 | else | ||
818 | allocstatus = crisv32_pinmux_dealloc_fixed(pinmux_pwm); | ||
819 | if (allocstatus) | ||
820 | return allocstatus; | ||
821 | REG_WRITE(reg_gio_rw_pwm0_ctrl, REG_ADDR(gio, regi_gio, rw_pwm0_ctrl) + | ||
822 | 12 * pwm_port, rw_pwm_ctrl); | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static int gpio_pwm_set_period(unsigned long arg, int pwm_port) | ||
827 | { | ||
828 | struct io_pwm_set_period periods; | ||
829 | reg_gio_rw_pwm0_var rw_pwm_widths; | ||
830 | |||
831 | if (copy_from_user(&periods, (void __user *)arg, sizeof(periods))) | ||
832 | return -EFAULT; | ||
833 | if (periods.lo > 8191 || periods.hi > 8191) | ||
834 | return -EINVAL; | ||
835 | rw_pwm_widths.lo = periods.lo; | ||
836 | rw_pwm_widths.hi = periods.hi; | ||
837 | REG_WRITE(reg_gio_rw_pwm0_var, REG_ADDR(gio, regi_gio, rw_pwm0_var) + | ||
838 | 12 * pwm_port, rw_pwm_widths); | ||
839 | return 0; | ||
840 | } | ||
841 | |||
842 | static int gpio_pwm_set_duty(unsigned long arg, int pwm_port) | ||
843 | { | ||
844 | unsigned int duty; | ||
845 | reg_gio_rw_pwm0_data rw_pwm_duty; | ||
846 | |||
847 | if (get_user(duty, &((struct io_pwm_set_duty *) arg)->duty)) | ||
848 | return -EFAULT; | ||
849 | if (duty > 255) | ||
850 | return -EINVAL; | ||
851 | rw_pwm_duty.data = duty; | ||
852 | REG_WRITE(reg_gio_rw_pwm0_data, REG_ADDR(gio, regi_gio, rw_pwm0_data) + | ||
853 | 12 * pwm_port, rw_pwm_duty); | ||
854 | return 0; | ||
855 | } | ||
856 | |||
857 | static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd, | ||
858 | unsigned long arg) | ||
859 | { | ||
860 | int pwm_port = priv->minor - GPIO_MINOR_PWM0; | ||
861 | |||
862 | switch (_IOC_NR(cmd)) { | ||
863 | case IO_PWM_SET_MODE: | ||
864 | return gpio_pwm_set_mode(arg, pwm_port); | ||
865 | case IO_PWM_SET_PERIOD: | ||
866 | return gpio_pwm_set_period(arg, pwm_port); | ||
867 | case IO_PWM_SET_DUTY: | ||
868 | return gpio_pwm_set_duty(arg, pwm_port); | ||
869 | default: | ||
870 | return -EINVAL; | ||
871 | } | ||
872 | return 0; | ||
873 | } | ||
874 | |||
875 | static const struct file_operations gpio_fops = { | ||
876 | .owner = THIS_MODULE, | ||
877 | .poll = gpio_poll, | ||
878 | .ioctl = gpio_ioctl, | ||
879 | .write = gpio_write, | ||
880 | .open = gpio_open, | ||
881 | .release = gpio_release, | ||
882 | }; | ||
883 | |||
884 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
885 | static void __init virtual_gpio_init(void) | ||
886 | { | ||
887 | reg_gio_rw_intr_cfg intr_cfg; | ||
888 | reg_gio_rw_intr_mask intr_mask; | ||
889 | unsigned short shadow; | ||
890 | |||
891 | shadow = ~virtual_rw_pv_oe; /* Input ports should be set to logic 1 */ | ||
892 | shadow |= CONFIG_ETRAX_DEF_GIO_PV_OUT; | ||
893 | i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); | ||
894 | |||
895 | /* Set interrupt mask and on what state the interrupt shall trigger. | ||
896 | * For virtual gpio the interrupt shall trigger on logic '0'. | ||
897 | */ | ||
898 | intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg); | ||
899 | intr_mask = REG_RD(gio, regi_gio, rw_intr_mask); | ||
900 | |||
901 | switch (CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN) { | ||
902 | case 0: | ||
903 | intr_cfg.pa0 = regk_gio_lo; | ||
904 | intr_mask.pa0 = regk_gio_yes; | ||
905 | break; | ||
906 | case 1: | ||
907 | intr_cfg.pa1 = regk_gio_lo; | ||
908 | intr_mask.pa1 = regk_gio_yes; | ||
909 | break; | ||
910 | case 2: | ||
911 | intr_cfg.pa2 = regk_gio_lo; | ||
912 | intr_mask.pa2 = regk_gio_yes; | ||
913 | break; | ||
914 | case 3: | ||
915 | intr_cfg.pa3 = regk_gio_lo; | ||
916 | intr_mask.pa3 = regk_gio_yes; | ||
917 | break; | ||
918 | case 4: | ||
919 | intr_cfg.pa4 = regk_gio_lo; | ||
920 | intr_mask.pa4 = regk_gio_yes; | ||
921 | break; | ||
922 | case 5: | ||
923 | intr_cfg.pa5 = regk_gio_lo; | ||
924 | intr_mask.pa5 = regk_gio_yes; | ||
925 | break; | ||
926 | case 6: | ||
927 | intr_cfg.pa6 = regk_gio_lo; | ||
928 | intr_mask.pa6 = regk_gio_yes; | ||
929 | break; | ||
930 | case 7: | ||
931 | intr_cfg.pa7 = regk_gio_lo; | ||
932 | intr_mask.pa7 = regk_gio_yes; | ||
933 | break; | ||
934 | } | ||
935 | |||
936 | REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg); | ||
937 | REG_WR(gio, regi_gio, rw_intr_mask, intr_mask); | ||
938 | } | ||
939 | #endif | ||
940 | |||
941 | /* main driver initialization routine, called from mem.c */ | ||
942 | |||
943 | static int __init gpio_init(void) | ||
944 | { | ||
945 | int res; | ||
946 | |||
947 | printk(KERN_INFO "ETRAX FS GPIO driver v2.7, (c) 2003-2008 " | ||
948 | "Axis Communications AB\n"); | ||
949 | |||
950 | /* do the formalities */ | ||
951 | |||
952 | res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops); | ||
953 | if (res < 0) { | ||
954 | printk(KERN_ERR "gpio: couldn't get a major number.\n"); | ||
955 | return res; | ||
956 | } | ||
957 | |||
958 | /* Clear all leds */ | ||
959 | CRIS_LED_NETWORK_GRP0_SET(0); | ||
960 | CRIS_LED_NETWORK_GRP1_SET(0); | ||
961 | CRIS_LED_ACTIVE_SET(0); | ||
962 | CRIS_LED_DISK_READ(0); | ||
963 | CRIS_LED_DISK_WRITE(0); | ||
964 | |||
965 | int res2 = request_irq(GIO_INTR_VECT, gpio_interrupt, | ||
966 | IRQF_SHARED | IRQF_DISABLED, "gpio", &alarmlist); | ||
967 | if (res2) { | ||
968 | printk(KERN_ERR "err: irq for gpio\n"); | ||
969 | return res2; | ||
970 | } | ||
971 | |||
972 | /* No IRQs by default. */ | ||
973 | REG_WR_INT(gio, regi_gio, rw_intr_pins, 0); | ||
974 | |||
975 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
976 | virtual_gpio_init(); | ||
977 | #endif | ||
978 | |||
979 | return res; | ||
980 | } | ||
981 | |||
982 | /* this makes sure that gpio_init is called during kernel boot */ | ||
983 | |||
984 | module_init(gpio_init); | ||
diff --git a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c new file mode 100644 index 000000000000..01ed0be2d0d1 --- /dev/null +++ b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * arch/cris/arch-v32/drivers/nandflash.c | ||
3 | * | ||
4 | * Copyright (c) 2007 | ||
5 | * | ||
6 | * Derived from drivers/mtd/nand/spia.c | ||
7 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/slab.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/mtd/mtd.h> | ||
19 | #include <linux/mtd/nand.h> | ||
20 | #include <linux/mtd/partitions.h> | ||
21 | #include <asm/arch/memmap.h> | ||
22 | #include <hwregs/reg_map.h> | ||
23 | #include <hwregs/reg_rdwr.h> | ||
24 | #include <hwregs/pio_defs.h> | ||
25 | #include <pinmux.h> | ||
26 | #include <asm/io.h> | ||
27 | |||
28 | #define MANUAL_ALE_CLE_CONTROL 1 | ||
29 | |||
30 | #define regf_ALE a0 | ||
31 | #define regf_CLE a1 | ||
32 | #define regf_NCE ce0_n | ||
33 | |||
34 | #define CLE_BIT 10 | ||
35 | #define ALE_BIT 11 | ||
36 | #define CE_BIT 12 | ||
37 | |||
38 | struct mtd_info_wrapper { | ||
39 | struct mtd_info info; | ||
40 | struct nand_chip chip; | ||
41 | }; | ||
42 | |||
43 | /* Bitmask for control pins */ | ||
44 | #define PIN_BITMASK ((1 << CE_BIT) | (1 << CLE_BIT) | (1 << ALE_BIT)) | ||
45 | |||
46 | static struct mtd_info *crisv32_mtd; | ||
47 | /* | ||
48 | * hardware specific access to control-lines | ||
49 | */ | ||
50 | static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd, | ||
51 | unsigned int ctrl) | ||
52 | { | ||
53 | unsigned long flags; | ||
54 | reg_pio_rw_dout dout; | ||
55 | struct nand_chip *this = mtd->priv; | ||
56 | |||
57 | local_irq_save(flags); | ||
58 | |||
59 | /* control bits change */ | ||
60 | if (ctrl & NAND_CTRL_CHANGE) { | ||
61 | dout = REG_RD(pio, regi_pio, rw_dout); | ||
62 | dout.regf_NCE = (ctrl & NAND_NCE) ? 0 : 1; | ||
63 | |||
64 | #if !MANUAL_ALE_CLE_CONTROL | ||
65 | if (ctrl & NAND_ALE) { | ||
66 | /* A0 = ALE high */ | ||
67 | this->IO_ADDR_W = (void __iomem *)REG_ADDR(pio, | ||
68 | regi_pio, rw_io_access1); | ||
69 | } else if (ctrl & NAND_CLE) { | ||
70 | /* A1 = CLE high */ | ||
71 | this->IO_ADDR_W = (void __iomem *)REG_ADDR(pio, | ||
72 | regi_pio, rw_io_access2); | ||
73 | } else { | ||
74 | /* A1 = CLE and A0 = ALE low */ | ||
75 | this->IO_ADDR_W = (void __iomem *)REG_ADDR(pio, | ||
76 | regi_pio, rw_io_access0); | ||
77 | } | ||
78 | #else | ||
79 | |||
80 | dout.regf_CLE = (ctrl & NAND_CLE) ? 1 : 0; | ||
81 | dout.regf_ALE = (ctrl & NAND_ALE) ? 1 : 0; | ||
82 | #endif | ||
83 | REG_WR(pio, regi_pio, rw_dout, dout); | ||
84 | } | ||
85 | |||
86 | /* command to chip */ | ||
87 | if (cmd != NAND_CMD_NONE) | ||
88 | writeb(cmd, this->IO_ADDR_W); | ||
89 | |||
90 | local_irq_restore(flags); | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * read device ready pin | ||
95 | */ | ||
96 | static int crisv32_device_ready(struct mtd_info *mtd) | ||
97 | { | ||
98 | reg_pio_r_din din = REG_RD(pio, regi_pio, r_din); | ||
99 | return din.rdy; | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * Main initialization routine | ||
104 | */ | ||
105 | struct mtd_info *__init crisv32_nand_flash_probe(void) | ||
106 | { | ||
107 | void __iomem *read_cs; | ||
108 | void __iomem *write_cs; | ||
109 | |||
110 | struct mtd_info_wrapper *wrapper; | ||
111 | struct nand_chip *this; | ||
112 | int err = 0; | ||
113 | |||
114 | reg_pio_rw_man_ctrl man_ctrl = { | ||
115 | .regf_NCE = regk_pio_yes, | ||
116 | #if MANUAL_ALE_CLE_CONTROL | ||
117 | .regf_ALE = regk_pio_yes, | ||
118 | .regf_CLE = regk_pio_yes | ||
119 | #endif | ||
120 | }; | ||
121 | reg_pio_rw_oe oe = { | ||
122 | .regf_NCE = regk_pio_yes, | ||
123 | #if MANUAL_ALE_CLE_CONTROL | ||
124 | .regf_ALE = regk_pio_yes, | ||
125 | .regf_CLE = regk_pio_yes | ||
126 | #endif | ||
127 | }; | ||
128 | reg_pio_rw_dout dout = { .regf_NCE = 1 }; | ||
129 | |||
130 | /* Allocate pio pins to pio */ | ||
131 | crisv32_pinmux_alloc_fixed(pinmux_pio); | ||
132 | /* Set up CE, ALE, CLE (ce0_n, a0, a1) for manual control and output */ | ||
133 | REG_WR(pio, regi_pio, rw_man_ctrl, man_ctrl); | ||
134 | REG_WR(pio, regi_pio, rw_dout, dout); | ||
135 | REG_WR(pio, regi_pio, rw_oe, oe); | ||
136 | |||
137 | /* Allocate memory for MTD device structure and private data */ | ||
138 | wrapper = kzalloc(sizeof(struct mtd_info_wrapper), GFP_KERNEL); | ||
139 | if (!wrapper) { | ||
140 | printk(KERN_ERR "Unable to allocate CRISv32 NAND MTD " | ||
141 | "device structure.\n"); | ||
142 | err = -ENOMEM; | ||
143 | return NULL; | ||
144 | } | ||
145 | |||
146 | read_cs = write_cs = (void __iomem *)REG_ADDR(pio, regi_pio, | ||
147 | rw_io_access0); | ||
148 | |||
149 | /* Get pointer to private data */ | ||
150 | this = &wrapper->chip; | ||
151 | crisv32_mtd = &wrapper->info; | ||
152 | |||
153 | /* Link the private data with the MTD structure */ | ||
154 | crisv32_mtd->priv = this; | ||
155 | |||
156 | /* Set address of NAND IO lines */ | ||
157 | this->IO_ADDR_R = read_cs; | ||
158 | this->IO_ADDR_W = write_cs; | ||
159 | this->cmd_ctrl = crisv32_hwcontrol; | ||
160 | this->dev_ready = crisv32_device_ready; | ||
161 | /* 20 us command delay time */ | ||
162 | this->chip_delay = 20; | ||
163 | this->ecc.mode = NAND_ECC_SOFT; | ||
164 | |||
165 | /* Enable the following for a flash based bad block table */ | ||
166 | /* this->options = NAND_USE_FLASH_BBT; */ | ||
167 | |||
168 | /* Scan to find existance of the device */ | ||
169 | if (nand_scan(crisv32_mtd, 1)) { | ||
170 | err = -ENXIO; | ||
171 | goto out_mtd; | ||
172 | } | ||
173 | |||
174 | return crisv32_mtd; | ||
175 | |||
176 | out_mtd: | ||
177 | kfree(wrapper); | ||
178 | return NULL; | ||
179 | } | ||
180 | |||
diff --git a/arch/cris/arch-v32/drivers/mach-fs/Makefile b/arch/cris/arch-v32/drivers/mach-fs/Makefile new file mode 100644 index 000000000000..5c6d2a2a080e --- /dev/null +++ b/arch/cris/arch-v32/drivers/mach-fs/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for Etrax-specific drivers | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_ETRAX_NANDFLASH) += nandflash.o | ||
6 | obj-$(CONFIG_ETRAX_GPIO) += gpio.o | ||
diff --git a/arch/cris/arch-v32/drivers/gpio.c b/arch/cris/arch-v32/drivers/mach-fs/gpio.c index d82c5c561135..7863fd4efc2b 100644 --- a/arch/cris/arch-v32/drivers/gpio.c +++ b/arch/cris/arch-v32/drivers/mach-fs/gpio.c | |||
@@ -1,68 +1,15 @@ | |||
1 | /* $Id: gpio.c,v 1.16 2005/06/19 17:06:49 starvik Exp $ | 1 | /* |
2 | * | ||
3 | * ETRAX CRISv32 general port I/O device | 2 | * ETRAX CRISv32 general port I/O device |
4 | * | 3 | * |
5 | * Copyright (c) 1999, 2000, 2001, 2002, 2003 Axis Communications AB | 4 | * Copyright (c) 1999-2006 Axis Communications AB |
6 | * | 5 | * |
7 | * Authors: Bjorn Wesen (initial version) | 6 | * Authors: Bjorn Wesen (initial version) |
8 | * Ola Knutsson (LED handling) | 7 | * Ola Knutsson (LED handling) |
9 | * Johan Adolfsson (read/set directions, write, port G, | 8 | * Johan Adolfsson (read/set directions, write, port G, |
10 | * port to ETRAX FS. | 9 | * port to ETRAX FS. |
11 | * | 10 | * |
12 | * $Log: gpio.c,v $ | ||
13 | * Revision 1.16 2005/06/19 17:06:49 starvik | ||
14 | * Merge of Linux 2.6.12. | ||
15 | * | ||
16 | * Revision 1.15 2005/05/25 08:22:20 starvik | ||
17 | * Changed GPIO port order to fit packages/devices/axis-2.4. | ||
18 | * | ||
19 | * Revision 1.14 2005/04/24 18:35:08 starvik | ||
20 | * Updated with final register headers. | ||
21 | * | ||
22 | * Revision 1.13 2005/03/15 15:43:00 starvik | ||
23 | * dev_id needs to be supplied for shared IRQs. | ||
24 | * | ||
25 | * Revision 1.12 2005/03/10 17:12:00 starvik | ||
26 | * Protect alarm list with spinlock. | ||
27 | * | ||
28 | * Revision 1.11 2005/01/05 06:08:59 starvik | ||
29 | * No need to do local_irq_disable after local_irq_save. | ||
30 | * | ||
31 | * Revision 1.10 2004/11/19 08:38:31 starvik | ||
32 | * Removed old crap. | ||
33 | * | ||
34 | * Revision 1.9 2004/05/14 07:58:02 starvik | ||
35 | * Merge of changes from 2.4 | ||
36 | * | ||
37 | * Revision 1.8 2003/09/11 07:29:50 starvik | ||
38 | * Merge of Linux 2.6.0-test5 | ||
39 | * | ||
40 | * Revision 1.7 2003/07/10 13:25:46 starvik | ||
41 | * Compiles for 2.5.74 | ||
42 | * Lindented ethernet.c | ||
43 | * | ||
44 | * Revision 1.6 2003/07/04 08:27:46 starvik | ||
45 | * Merge of Linux 2.5.74 | ||
46 | * | ||
47 | * Revision 1.5 2003/06/10 08:26:37 johana | ||
48 | * Etrax -> ETRAX CRISv32 | ||
49 | * | ||
50 | * Revision 1.4 2003/06/05 14:22:48 johana | ||
51 | * Initialise some_alarms. | ||
52 | * | ||
53 | * Revision 1.3 2003/06/05 10:15:46 johana | ||
54 | * New INTR_VECT macros. | ||
55 | * Enable interrupts in global config. | ||
56 | * | ||
57 | * Revision 1.2 2003/06/03 15:52:50 johana | ||
58 | * Initial CRIS v32 version. | ||
59 | * | ||
60 | * Revision 1.1 2003/06/03 08:53:15 johana | ||
61 | * Copy of os/lx25/arch/cris/arch-v10/drivers/gpio.c version 1.7. | ||
62 | * | ||
63 | */ | 11 | */ |
64 | 12 | ||
65 | |||
66 | #include <linux/module.h> | 13 | #include <linux/module.h> |
67 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
68 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
@@ -77,14 +24,20 @@ | |||
77 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
78 | 25 | ||
79 | #include <asm/etraxgpio.h> | 26 | #include <asm/etraxgpio.h> |
80 | #include <asm/arch/hwregs/reg_map.h> | 27 | #include <hwregs/reg_map.h> |
81 | #include <asm/arch/hwregs/reg_rdwr.h> | 28 | #include <hwregs/reg_rdwr.h> |
82 | #include <asm/arch/hwregs/gio_defs.h> | 29 | #include <hwregs/gio_defs.h> |
83 | #include <asm/arch/hwregs/intr_vect_defs.h> | 30 | #include <hwregs/intr_vect_defs.h> |
84 | #include <asm/io.h> | 31 | #include <asm/io.h> |
85 | #include <asm/system.h> | 32 | #include <asm/system.h> |
86 | #include <asm/irq.h> | 33 | #include <asm/irq.h> |
87 | 34 | ||
35 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
36 | #include "../i2c.h" | ||
37 | |||
38 | #define VIRT_I2C_ADDR 0x40 | ||
39 | #endif | ||
40 | |||
88 | /* The following gio ports on ETRAX FS is available: | 41 | /* The following gio ports on ETRAX FS is available: |
89 | * pa 8 bits, supports interrupts off, hi, low, set, posedge, negedge anyedge | 42 | * pa 8 bits, supports interrupts off, hi, low, set, posedge, negedge anyedge |
90 | * pb 18 bits | 43 | * pb 18 bits |
@@ -100,7 +53,12 @@ | |||
100 | 53 | ||
101 | #if 0 | 54 | #if 0 |
102 | static int dp_cnt; | 55 | static int dp_cnt; |
103 | #define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0) | 56 | #define DP(x) \ |
57 | do { \ | ||
58 | dp_cnt++; \ | ||
59 | if (dp_cnt % 1000 == 0) \ | ||
60 | x; \ | ||
61 | } while (0) | ||
104 | #else | 62 | #else |
105 | #define DP(x) | 63 | #define DP(x) |
106 | #endif | 64 | #endif |
@@ -111,13 +69,18 @@ static char gpio_name[] = "etrax gpio"; | |||
111 | static wait_queue_head_t *gpio_wq; | 69 | static wait_queue_head_t *gpio_wq; |
112 | #endif | 70 | #endif |
113 | 71 | ||
72 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
73 | static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, | ||
74 | unsigned long arg); | ||
75 | #endif | ||
114 | static int gpio_ioctl(struct inode *inode, struct file *file, | 76 | static int gpio_ioctl(struct inode *inode, struct file *file, |
115 | unsigned int cmd, unsigned long arg); | 77 | unsigned int cmd, unsigned long arg); |
116 | static ssize_t gpio_write(struct file * file, const char * buf, size_t count, | 78 | static ssize_t gpio_write(struct file *file, const char *buf, size_t count, |
117 | loff_t *off); | 79 | loff_t *off); |
118 | static int gpio_open(struct inode *inode, struct file *filp); | 80 | static int gpio_open(struct inode *inode, struct file *filp); |
119 | static int gpio_release(struct inode *inode, struct file *filp); | 81 | static int gpio_release(struct inode *inode, struct file *filp); |
120 | static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait); | 82 | static unsigned int gpio_poll(struct file *filp, |
83 | struct poll_table_struct *wait); | ||
121 | 84 | ||
122 | /* private data per open() of this driver */ | 85 | /* private data per open() of this driver */ |
123 | 86 | ||
@@ -136,18 +99,25 @@ struct gpio_private { | |||
136 | 99 | ||
137 | /* linked list of alarms to check for */ | 100 | /* linked list of alarms to check for */ |
138 | 101 | ||
139 | static struct gpio_private *alarmlist = 0; | 102 | static struct gpio_private *alarmlist; |
140 | 103 | ||
141 | static int gpio_some_alarms = 0; /* Set if someone uses alarm */ | 104 | static int gpio_some_alarms; /* Set if someone uses alarm */ |
142 | static unsigned long gpio_pa_high_alarms = 0; | 105 | static unsigned long gpio_pa_high_alarms; |
143 | static unsigned long gpio_pa_low_alarms = 0; | 106 | static unsigned long gpio_pa_low_alarms; |
144 | 107 | ||
145 | static DEFINE_SPINLOCK(alarm_lock); | 108 | static DEFINE_SPINLOCK(alarm_lock); |
146 | 109 | ||
147 | #define NUM_PORTS (GPIO_MINOR_LAST+1) | 110 | #define NUM_PORTS (GPIO_MINOR_LAST+1) |
148 | #define GIO_REG_RD_ADDR(reg) (volatile unsigned long*) (regi_gio + REG_RD_ADDR_gio_##reg ) | 111 | #define GIO_REG_RD_ADDR(reg) \ |
149 | #define GIO_REG_WR_ADDR(reg) (volatile unsigned long*) (regi_gio + REG_RD_ADDR_gio_##reg ) | 112 | (volatile unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg) |
113 | #define GIO_REG_WR_ADDR(reg) \ | ||
114 | (volatile unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg) | ||
150 | unsigned long led_dummy; | 115 | unsigned long led_dummy; |
116 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
117 | static unsigned long virtual_dummy; | ||
118 | static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE; | ||
119 | static unsigned short cached_virtual_gpio_read; | ||
120 | #endif | ||
151 | 121 | ||
152 | static volatile unsigned long *data_out[NUM_PORTS] = { | 122 | static volatile unsigned long *data_out[NUM_PORTS] = { |
153 | GIO_REG_WR_ADDR(rw_pa_dout), | 123 | GIO_REG_WR_ADDR(rw_pa_dout), |
@@ -156,6 +126,9 @@ static volatile unsigned long *data_out[NUM_PORTS] = { | |||
156 | GIO_REG_WR_ADDR(rw_pc_dout), | 126 | GIO_REG_WR_ADDR(rw_pc_dout), |
157 | GIO_REG_WR_ADDR(rw_pd_dout), | 127 | GIO_REG_WR_ADDR(rw_pd_dout), |
158 | GIO_REG_WR_ADDR(rw_pe_dout), | 128 | GIO_REG_WR_ADDR(rw_pe_dout), |
129 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
130 | &virtual_dummy, | ||
131 | #endif | ||
159 | }; | 132 | }; |
160 | 133 | ||
161 | static volatile unsigned long *data_in[NUM_PORTS] = { | 134 | static volatile unsigned long *data_in[NUM_PORTS] = { |
@@ -165,6 +138,9 @@ static volatile unsigned long *data_in[NUM_PORTS] = { | |||
165 | GIO_REG_RD_ADDR(r_pc_din), | 138 | GIO_REG_RD_ADDR(r_pc_din), |
166 | GIO_REG_RD_ADDR(r_pd_din), | 139 | GIO_REG_RD_ADDR(r_pd_din), |
167 | GIO_REG_RD_ADDR(r_pe_din), | 140 | GIO_REG_RD_ADDR(r_pe_din), |
141 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
142 | &virtual_dummy, | ||
143 | #endif | ||
168 | }; | 144 | }; |
169 | 145 | ||
170 | static unsigned long changeable_dir[NUM_PORTS] = { | 146 | static unsigned long changeable_dir[NUM_PORTS] = { |
@@ -174,6 +150,9 @@ static unsigned long changeable_dir[NUM_PORTS] = { | |||
174 | CONFIG_ETRAX_PC_CHANGEABLE_DIR, | 150 | CONFIG_ETRAX_PC_CHANGEABLE_DIR, |
175 | CONFIG_ETRAX_PD_CHANGEABLE_DIR, | 151 | CONFIG_ETRAX_PD_CHANGEABLE_DIR, |
176 | CONFIG_ETRAX_PE_CHANGEABLE_DIR, | 152 | CONFIG_ETRAX_PE_CHANGEABLE_DIR, |
153 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
154 | CONFIG_ETRAX_PV_CHANGEABLE_DIR, | ||
155 | #endif | ||
177 | }; | 156 | }; |
178 | 157 | ||
179 | static unsigned long changeable_bits[NUM_PORTS] = { | 158 | static unsigned long changeable_bits[NUM_PORTS] = { |
@@ -183,6 +162,9 @@ static unsigned long changeable_bits[NUM_PORTS] = { | |||
183 | CONFIG_ETRAX_PC_CHANGEABLE_BITS, | 162 | CONFIG_ETRAX_PC_CHANGEABLE_BITS, |
184 | CONFIG_ETRAX_PD_CHANGEABLE_BITS, | 163 | CONFIG_ETRAX_PD_CHANGEABLE_BITS, |
185 | CONFIG_ETRAX_PE_CHANGEABLE_BITS, | 164 | CONFIG_ETRAX_PE_CHANGEABLE_BITS, |
165 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
166 | CONFIG_ETRAX_PV_CHANGEABLE_BITS, | ||
167 | #endif | ||
186 | }; | 168 | }; |
187 | 169 | ||
188 | static volatile unsigned long *dir_oe[NUM_PORTS] = { | 170 | static volatile unsigned long *dir_oe[NUM_PORTS] = { |
@@ -192,13 +174,14 @@ static volatile unsigned long *dir_oe[NUM_PORTS] = { | |||
192 | GIO_REG_WR_ADDR(rw_pc_oe), | 174 | GIO_REG_WR_ADDR(rw_pc_oe), |
193 | GIO_REG_WR_ADDR(rw_pd_oe), | 175 | GIO_REG_WR_ADDR(rw_pd_oe), |
194 | GIO_REG_WR_ADDR(rw_pe_oe), | 176 | GIO_REG_WR_ADDR(rw_pe_oe), |
177 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
178 | &virtual_rw_pv_oe, | ||
179 | #endif | ||
195 | }; | 180 | }; |
196 | 181 | ||
197 | 182 | ||
198 | 183 | ||
199 | static unsigned int | 184 | static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait) |
200 | gpio_poll(struct file *file, | ||
201 | poll_table *wait) | ||
202 | { | 185 | { |
203 | unsigned int mask = 0; | 186 | unsigned int mask = 0; |
204 | struct gpio_private *priv = (struct gpio_private *)file->private_data; | 187 | struct gpio_private *priv = (struct gpio_private *)file->private_data; |
@@ -210,65 +193,50 @@ gpio_poll(struct file *file, | |||
210 | unsigned long flags; | 193 | unsigned long flags; |
211 | 194 | ||
212 | local_irq_save(flags); | 195 | local_irq_save(flags); |
213 | data = REG_TYPE_CONV(unsigned long, reg_gio_r_pa_din, REG_RD(gio, regi_gio, r_pa_din)); | 196 | data = REG_TYPE_CONV(unsigned long, reg_gio_r_pa_din, |
197 | REG_RD(gio, regi_gio, r_pa_din)); | ||
214 | /* PA has support for interrupt | 198 | /* PA has support for interrupt |
215 | * lets activate high for those low and with highalarm set | 199 | * lets activate high for those low and with highalarm set |
216 | */ | 200 | */ |
217 | intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg); | 201 | intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg); |
218 | 202 | ||
219 | tmp = ~data & priv->highalarm & 0xFF; | 203 | tmp = ~data & priv->highalarm & 0xFF; |
220 | if (tmp & (1 << 0)) { | 204 | if (tmp & (1 << 0)) |
221 | intr_cfg.pa0 = regk_gio_hi; | 205 | intr_cfg.pa0 = regk_gio_hi; |
222 | } | 206 | if (tmp & (1 << 1)) |
223 | if (tmp & (1 << 1)) { | ||
224 | intr_cfg.pa1 = regk_gio_hi; | 207 | intr_cfg.pa1 = regk_gio_hi; |
225 | } | 208 | if (tmp & (1 << 2)) |
226 | if (tmp & (1 << 2)) { | ||
227 | intr_cfg.pa2 = regk_gio_hi; | 209 | intr_cfg.pa2 = regk_gio_hi; |
228 | } | 210 | if (tmp & (1 << 3)) |
229 | if (tmp & (1 << 3)) { | ||
230 | intr_cfg.pa3 = regk_gio_hi; | 211 | intr_cfg.pa3 = regk_gio_hi; |
231 | } | 212 | if (tmp & (1 << 4)) |
232 | if (tmp & (1 << 4)) { | ||
233 | intr_cfg.pa4 = regk_gio_hi; | 213 | intr_cfg.pa4 = regk_gio_hi; |
234 | } | 214 | if (tmp & (1 << 5)) |
235 | if (tmp & (1 << 5)) { | ||
236 | intr_cfg.pa5 = regk_gio_hi; | 215 | intr_cfg.pa5 = regk_gio_hi; |
237 | } | 216 | if (tmp & (1 << 6)) |
238 | if (tmp & (1 << 6)) { | ||
239 | intr_cfg.pa6 = regk_gio_hi; | 217 | intr_cfg.pa6 = regk_gio_hi; |
240 | } | 218 | if (tmp & (1 << 7)) |
241 | if (tmp & (1 << 7)) { | ||
242 | intr_cfg.pa7 = regk_gio_hi; | 219 | intr_cfg.pa7 = regk_gio_hi; |
243 | } | ||
244 | /* | 220 | /* |
245 | * lets activate low for those high and with lowalarm set | 221 | * lets activate low for those high and with lowalarm set |
246 | */ | 222 | */ |
247 | tmp = data & priv->lowalarm & 0xFF; | 223 | tmp = data & priv->lowalarm & 0xFF; |
248 | if (tmp & (1 << 0)) { | 224 | if (tmp & (1 << 0)) |
249 | intr_cfg.pa0 = regk_gio_lo; | 225 | intr_cfg.pa0 = regk_gio_lo; |
250 | } | 226 | if (tmp & (1 << 1)) |
251 | if (tmp & (1 << 1)) { | ||
252 | intr_cfg.pa1 = regk_gio_lo; | 227 | intr_cfg.pa1 = regk_gio_lo; |
253 | } | 228 | if (tmp & (1 << 2)) |
254 | if (tmp & (1 << 2)) { | ||
255 | intr_cfg.pa2 = regk_gio_lo; | 229 | intr_cfg.pa2 = regk_gio_lo; |
256 | } | 230 | if (tmp & (1 << 3)) |
257 | if (tmp & (1 << 3)) { | ||
258 | intr_cfg.pa3 = regk_gio_lo; | 231 | intr_cfg.pa3 = regk_gio_lo; |
259 | } | 232 | if (tmp & (1 << 4)) |
260 | if (tmp & (1 << 4)) { | ||
261 | intr_cfg.pa4 = regk_gio_lo; | 233 | intr_cfg.pa4 = regk_gio_lo; |
262 | } | 234 | if (tmp & (1 << 5)) |
263 | if (tmp & (1 << 5)) { | ||
264 | intr_cfg.pa5 = regk_gio_lo; | 235 | intr_cfg.pa5 = regk_gio_lo; |
265 | } | 236 | if (tmp & (1 << 6)) |
266 | if (tmp & (1 << 6)) { | ||
267 | intr_cfg.pa6 = regk_gio_lo; | 237 | intr_cfg.pa6 = regk_gio_lo; |
268 | } | 238 | if (tmp & (1 << 7)) |
269 | if (tmp & (1 << 7)) { | ||
270 | intr_cfg.pa7 = regk_gio_lo; | 239 | intr_cfg.pa7 = regk_gio_lo; |
271 | } | ||
272 | 240 | ||
273 | REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg); | 241 | REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg); |
274 | local_irq_restore(flags); | 242 | local_irq_restore(flags); |
@@ -277,50 +245,65 @@ gpio_poll(struct file *file, | |||
277 | else | 245 | else |
278 | return 0; | 246 | return 0; |
279 | 247 | ||
280 | if ((data & priv->highalarm) || | 248 | if ((data & priv->highalarm) || (~data & priv->lowalarm)) |
281 | (~data & priv->lowalarm)) { | ||
282 | mask = POLLIN|POLLRDNORM; | 249 | mask = POLLIN|POLLRDNORM; |
283 | } | ||
284 | 250 | ||
285 | DP(printk("gpio_poll ready: mask 0x%08X\n", mask)); | 251 | DP(printk(KERN_DEBUG "gpio_poll ready: mask 0x%08X\n", mask)); |
286 | return mask; | 252 | return mask; |
287 | } | 253 | } |
288 | 254 | ||
289 | int etrax_gpio_wake_up_check(void) | 255 | int etrax_gpio_wake_up_check(void) |
290 | { | 256 | { |
291 | struct gpio_private *priv = alarmlist; | 257 | struct gpio_private *priv; |
292 | unsigned long data = 0; | 258 | unsigned long data = 0; |
293 | int ret = 0; | 259 | unsigned long flags; |
260 | int ret = 0; | ||
261 | spin_lock_irqsave(&alarm_lock, flags); | ||
262 | priv = alarmlist; | ||
294 | while (priv) { | 263 | while (priv) { |
264 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
265 | if (priv->minor == GPIO_MINOR_V) | ||
266 | data = (unsigned long)cached_virtual_gpio_read; | ||
267 | else { | ||
268 | data = *data_in[priv->minor]; | ||
269 | if (priv->minor == GPIO_MINOR_A) | ||
270 | priv->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); | ||
271 | } | ||
272 | #else | ||
295 | data = *data_in[priv->minor]; | 273 | data = *data_in[priv->minor]; |
274 | #endif | ||
296 | if ((data & priv->highalarm) || | 275 | if ((data & priv->highalarm) || |
297 | (~data & priv->lowalarm)) { | 276 | (~data & priv->lowalarm)) { |
298 | DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor)); | 277 | DP(printk(KERN_DEBUG |
278 | "etrax_gpio_wake_up_check %i\n", priv->minor)); | ||
299 | wake_up_interruptible(&priv->alarm_wq); | 279 | wake_up_interruptible(&priv->alarm_wq); |
300 | ret = 1; | 280 | ret = 1; |
301 | } | 281 | } |
302 | priv = priv->next; | 282 | priv = priv->next; |
303 | } | 283 | } |
304 | return ret; | 284 | spin_unlock_irqrestore(&alarm_lock, flags); |
285 | return ret; | ||
305 | } | 286 | } |
306 | 287 | ||
307 | static irqreturn_t | 288 | static irqreturn_t |
308 | gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 289 | gpio_poll_timer_interrupt(int irq, void *dev_id) |
309 | { | 290 | { |
310 | if (gpio_some_alarms) { | 291 | if (gpio_some_alarms) |
311 | return IRQ_RETVAL(etrax_gpio_wake_up_check()); | 292 | return IRQ_RETVAL(etrax_gpio_wake_up_check()); |
312 | } | 293 | return IRQ_NONE; |
313 | return IRQ_NONE; | ||
314 | } | 294 | } |
315 | 295 | ||
316 | static irqreturn_t | 296 | static irqreturn_t |
317 | gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 297 | gpio_pa_interrupt(int irq, void *dev_id) |
318 | { | 298 | { |
319 | reg_gio_rw_intr_mask intr_mask; | 299 | reg_gio_rw_intr_mask intr_mask; |
320 | reg_gio_r_masked_intr masked_intr; | 300 | reg_gio_r_masked_intr masked_intr; |
321 | reg_gio_rw_ack_intr ack_intr; | 301 | reg_gio_rw_ack_intr ack_intr; |
322 | unsigned long tmp; | 302 | unsigned long tmp; |
323 | unsigned long tmp2; | 303 | unsigned long tmp2; |
304 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
305 | unsigned char enable_gpiov_ack = 0; | ||
306 | #endif | ||
324 | 307 | ||
325 | /* Find what PA interrupts are active */ | 308 | /* Find what PA interrupts are active */ |
326 | masked_intr = REG_RD(gio, regi_gio, r_masked_intr); | 309 | masked_intr = REG_RD(gio, regi_gio, r_masked_intr); |
@@ -331,6 +314,17 @@ gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
331 | tmp &= (gpio_pa_high_alarms | gpio_pa_low_alarms); | 314 | tmp &= (gpio_pa_high_alarms | gpio_pa_low_alarms); |
332 | spin_unlock(&alarm_lock); | 315 | spin_unlock(&alarm_lock); |
333 | 316 | ||
317 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
318 | /* Something changed on virtual GPIO. Interrupt is acked by | ||
319 | * reading the device. | ||
320 | */ | ||
321 | if (tmp & (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN)) { | ||
322 | i2c_read(VIRT_I2C_ADDR, (void *)&cached_virtual_gpio_read, | ||
323 | sizeof(cached_virtual_gpio_read)); | ||
324 | enable_gpiov_ack = 1; | ||
325 | } | ||
326 | #endif | ||
327 | |||
334 | /* Ack them */ | 328 | /* Ack them */ |
335 | ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp); | 329 | ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp); |
336 | REG_WR(gio, regi_gio, rw_ack_intr, ack_intr); | 330 | REG_WR(gio, regi_gio, rw_ack_intr, ack_intr); |
@@ -339,18 +333,24 @@ gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
339 | intr_mask = REG_RD(gio, regi_gio, rw_intr_mask); | 333 | intr_mask = REG_RD(gio, regi_gio, rw_intr_mask); |
340 | tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask); | 334 | tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask); |
341 | tmp2 &= ~tmp; | 335 | tmp2 &= ~tmp; |
336 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
337 | /* Do not disable interrupt on virtual GPIO. Changes on virtual | ||
338 | * pins are only noticed by an interrupt. | ||
339 | */ | ||
340 | if (enable_gpiov_ack) | ||
341 | tmp2 |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); | ||
342 | #endif | ||
342 | intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2); | 343 | intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2); |
343 | REG_WR(gio, regi_gio, rw_intr_mask, intr_mask); | 344 | REG_WR(gio, regi_gio, rw_intr_mask, intr_mask); |
344 | 345 | ||
345 | if (gpio_some_alarms) { | 346 | if (gpio_some_alarms) |
346 | return IRQ_RETVAL(etrax_gpio_wake_up_check()); | 347 | return IRQ_RETVAL(etrax_gpio_wake_up_check()); |
347 | } | 348 | return IRQ_NONE; |
348 | return IRQ_NONE; | ||
349 | } | 349 | } |
350 | 350 | ||
351 | 351 | ||
352 | static ssize_t gpio_write(struct file * file, const char * buf, size_t count, | 352 | static ssize_t gpio_write(struct file *file, const char *buf, size_t count, |
353 | loff_t *off) | 353 | loff_t *off) |
354 | { | 354 | { |
355 | struct gpio_private *priv = (struct gpio_private *)file->private_data; | 355 | struct gpio_private *priv = (struct gpio_private *)file->private_data; |
356 | unsigned char data, clk_mask, data_mask, write_msb; | 356 | unsigned char data, clk_mask, data_mask, write_msb; |
@@ -360,29 +360,31 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count, | |||
360 | ssize_t retval = count; | 360 | ssize_t retval = count; |
361 | /* Only bits 0-7 may be used for write operations but allow all | 361 | /* Only bits 0-7 may be used for write operations but allow all |
362 | devices except leds... */ | 362 | devices except leds... */ |
363 | if (priv->minor == GPIO_MINOR_LEDS) { | 363 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO |
364 | if (priv->minor == GPIO_MINOR_V) | ||
365 | return -EFAULT; | ||
366 | #endif | ||
367 | if (priv->minor == GPIO_MINOR_LEDS) | ||
364 | return -EFAULT; | 368 | return -EFAULT; |
365 | } | ||
366 | 369 | ||
367 | if (!access_ok(VERIFY_READ, buf, count)) { | 370 | if (!access_ok(VERIFY_READ, buf, count)) |
368 | return -EFAULT; | 371 | return -EFAULT; |
369 | } | ||
370 | clk_mask = priv->clk_mask; | 372 | clk_mask = priv->clk_mask; |
371 | data_mask = priv->data_mask; | 373 | data_mask = priv->data_mask; |
372 | /* It must have been configured using the IO_CFG_WRITE_MODE */ | 374 | /* It must have been configured using the IO_CFG_WRITE_MODE */ |
373 | /* Perhaps a better error code? */ | 375 | /* Perhaps a better error code? */ |
374 | if (clk_mask == 0 || data_mask == 0) { | 376 | if (clk_mask == 0 || data_mask == 0) |
375 | return -EPERM; | 377 | return -EPERM; |
376 | } | ||
377 | write_msb = priv->write_msb; | 378 | write_msb = priv->write_msb; |
378 | D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb)); | 379 | D(printk(KERN_DEBUG "gpio_write: %lu to data 0x%02X clk 0x%02X " |
380 | "msb: %i\n", count, data_mask, clk_mask, write_msb)); | ||
379 | port = data_out[priv->minor]; | 381 | port = data_out[priv->minor]; |
380 | 382 | ||
381 | while (count--) { | 383 | while (count--) { |
382 | int i; | 384 | int i; |
383 | data = *buf++; | 385 | data = *buf++; |
384 | if (priv->write_msb) { | 386 | if (priv->write_msb) { |
385 | for (i = 7; i >= 0;i--) { | 387 | for (i = 7; i >= 0; i--) { |
386 | local_irq_save(flags); | 388 | local_irq_save(flags); |
387 | shadow = *port; | 389 | shadow = *port; |
388 | *port = shadow &= ~clk_mask; | 390 | *port = shadow &= ~clk_mask; |
@@ -395,7 +397,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count, | |||
395 | local_irq_restore(flags); | 397 | local_irq_restore(flags); |
396 | } | 398 | } |
397 | } else { | 399 | } else { |
398 | for (i = 0; i <= 7;i++) { | 400 | for (i = 0; i <= 7; i++) { |
399 | local_irq_save(flags); | 401 | local_irq_save(flags); |
400 | shadow = *port; | 402 | shadow = *port; |
401 | *port = shadow &= ~clk_mask; | 403 | *port = shadow &= ~clk_mask; |
@@ -423,18 +425,16 @@ gpio_open(struct inode *inode, struct file *filp) | |||
423 | if (p > GPIO_MINOR_LAST) | 425 | if (p > GPIO_MINOR_LAST) |
424 | return -EINVAL; | 426 | return -EINVAL; |
425 | 427 | ||
426 | priv = kmalloc(sizeof(struct gpio_private), | 428 | priv = kmalloc(sizeof(struct gpio_private), GFP_KERNEL); |
427 | GFP_KERNEL); | ||
428 | 429 | ||
429 | if (!priv) | 430 | if (!priv) |
430 | return -ENOMEM; | 431 | return -ENOMEM; |
432 | memset(priv, 0, sizeof(*priv)); | ||
431 | 433 | ||
432 | priv->minor = p; | 434 | priv->minor = p; |
433 | 435 | ||
434 | /* initialize the io/alarm struct and link it into our alarmlist */ | 436 | /* initialize the io/alarm struct */ |
435 | 437 | ||
436 | priv->next = alarmlist; | ||
437 | alarmlist = priv; | ||
438 | priv->clk_mask = 0; | 438 | priv->clk_mask = 0; |
439 | priv->data_mask = 0; | 439 | priv->data_mask = 0; |
440 | priv->highalarm = 0; | 440 | priv->highalarm = 0; |
@@ -443,20 +443,30 @@ gpio_open(struct inode *inode, struct file *filp) | |||
443 | 443 | ||
444 | filp->private_data = (void *)priv; | 444 | filp->private_data = (void *)priv; |
445 | 445 | ||
446 | /* link it into our alarmlist */ | ||
447 | spin_lock_irq(&alarm_lock); | ||
448 | priv->next = alarmlist; | ||
449 | alarmlist = priv; | ||
450 | spin_unlock_irq(&alarm_lock); | ||
451 | |||
446 | return 0; | 452 | return 0; |
447 | } | 453 | } |
448 | 454 | ||
449 | static int | 455 | static int |
450 | gpio_release(struct inode *inode, struct file *filp) | 456 | gpio_release(struct inode *inode, struct file *filp) |
451 | { | 457 | { |
452 | struct gpio_private *p = alarmlist; | 458 | struct gpio_private *p; |
453 | struct gpio_private *todel = (struct gpio_private *)filp->private_data; | 459 | struct gpio_private *todel; |
454 | /* local copies while updating them: */ | 460 | /* local copies while updating them: */ |
455 | unsigned long a_high, a_low; | 461 | unsigned long a_high, a_low; |
456 | unsigned long some_alarms; | 462 | unsigned long some_alarms; |
457 | 463 | ||
458 | /* unlink from alarmlist and free the private structure */ | 464 | /* unlink from alarmlist and free the private structure */ |
459 | 465 | ||
466 | spin_lock_irq(&alarm_lock); | ||
467 | p = alarmlist; | ||
468 | todel = (struct gpio_private *)filp->private_data; | ||
469 | |||
460 | if (p == todel) { | 470 | if (p == todel) { |
461 | alarmlist = todel->next; | 471 | alarmlist = todel->next; |
462 | } else { | 472 | } else { |
@@ -468,26 +478,35 @@ gpio_release(struct inode *inode, struct file *filp) | |||
468 | kfree(todel); | 478 | kfree(todel); |
469 | /* Check if there are still any alarms set */ | 479 | /* Check if there are still any alarms set */ |
470 | p = alarmlist; | 480 | p = alarmlist; |
471 | some_alarms = 0; | 481 | some_alarms = 0; |
472 | a_high = 0; | 482 | a_high = 0; |
473 | a_low = 0; | 483 | a_low = 0; |
474 | while (p) { | 484 | while (p) { |
475 | if (p->minor == GPIO_MINOR_A) { | 485 | if (p->minor == GPIO_MINOR_A) { |
486 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
487 | p->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); | ||
488 | #endif | ||
476 | a_high |= p->highalarm; | 489 | a_high |= p->highalarm; |
477 | a_low |= p->lowalarm; | 490 | a_low |= p->lowalarm; |
478 | } | 491 | } |
479 | 492 | ||
480 | if (p->highalarm | p->lowalarm) { | 493 | if (p->highalarm | p->lowalarm) |
481 | some_alarms = 1; | 494 | some_alarms = 1; |
482 | } | ||
483 | p = p->next; | 495 | p = p->next; |
484 | } | 496 | } |
485 | 497 | ||
486 | spin_lock(&alarm_lock); | 498 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO |
499 | /* Variables 'some_alarms' and 'a_low' needs to be set here again | ||
500 | * to ensure that interrupt for virtual GPIO is handled. | ||
501 | */ | ||
502 | some_alarms = 1; | ||
503 | a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); | ||
504 | #endif | ||
505 | |||
487 | gpio_some_alarms = some_alarms; | 506 | gpio_some_alarms = some_alarms; |
488 | gpio_pa_high_alarms = a_high; | 507 | gpio_pa_high_alarms = a_high; |
489 | gpio_pa_low_alarms = a_low; | 508 | gpio_pa_low_alarms = a_low; |
490 | spin_unlock(&alarm_lock); | 509 | spin_unlock_irq(&alarm_lock); |
491 | 510 | ||
492 | return 0; | 511 | return 0; |
493 | } | 512 | } |
@@ -496,7 +515,7 @@ gpio_release(struct inode *inode, struct file *filp) | |||
496 | * set alarms to wait for using a subsequent select(). | 515 | * set alarms to wait for using a subsequent select(). |
497 | */ | 516 | */ |
498 | 517 | ||
499 | unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg) | 518 | inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg) |
500 | { | 519 | { |
501 | /* Set direction 0=unchanged 1=input, | 520 | /* Set direction 0=unchanged 1=input, |
502 | * return mask with 1=input | 521 | * return mask with 1=input |
@@ -512,13 +531,17 @@ unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg) | |||
512 | 531 | ||
513 | if (priv->minor == GPIO_MINOR_A) | 532 | if (priv->minor == GPIO_MINOR_A) |
514 | dir_shadow ^= 0xFF; /* Only 8 bits */ | 533 | dir_shadow ^= 0xFF; /* Only 8 bits */ |
534 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
535 | else if (priv->minor == GPIO_MINOR_V) | ||
536 | dir_shadow ^= 0xFFFF; /* Only 16 bits */ | ||
537 | #endif | ||
515 | else | 538 | else |
516 | dir_shadow ^= 0x3FFFF; /* Only 18 bits */ | 539 | dir_shadow ^= 0x3FFFF; /* Only 18 bits */ |
517 | return dir_shadow; | 540 | return dir_shadow; |
518 | 541 | ||
519 | } /* setget_input */ | 542 | } /* setget_input */ |
520 | 543 | ||
521 | unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg) | 544 | inline unsigned long setget_output(struct gpio_private *priv, unsigned long arg) |
522 | { | 545 | { |
523 | unsigned long flags; | 546 | unsigned long flags; |
524 | unsigned long dir_shadow; | 547 | unsigned long dir_shadow; |
@@ -542,20 +565,22 @@ gpio_ioctl(struct inode *inode, struct file *file, | |||
542 | unsigned long val; | 565 | unsigned long val; |
543 | unsigned long shadow; | 566 | unsigned long shadow; |
544 | struct gpio_private *priv = (struct gpio_private *)file->private_data; | 567 | struct gpio_private *priv = (struct gpio_private *)file->private_data; |
545 | if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) { | 568 | if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) |
546 | return -EINVAL; | 569 | return -EINVAL; |
547 | } | 570 | |
571 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
572 | if (priv->minor == GPIO_MINOR_V) | ||
573 | return virtual_gpio_ioctl(file, cmd, arg); | ||
574 | #endif | ||
548 | 575 | ||
549 | switch (_IOC_NR(cmd)) { | 576 | switch (_IOC_NR(cmd)) { |
550 | case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ | 577 | case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ |
551 | // read the port | 578 | /* Read the port. */ |
552 | return *data_in[priv->minor]; | 579 | return *data_in[priv->minor]; |
553 | break; | 580 | break; |
554 | case IO_SETBITS: | 581 | case IO_SETBITS: |
555 | local_irq_save(flags); | 582 | local_irq_save(flags); |
556 | if (arg & 0x04) | 583 | /* Set changeable bits with a 1 in arg. */ |
557 | printk("GPIO SET 2\n"); | ||
558 | // set changeable bits with a 1 in arg | ||
559 | shadow = *data_out[priv->minor]; | 584 | shadow = *data_out[priv->minor]; |
560 | shadow |= (arg & changeable_bits[priv->minor]); | 585 | shadow |= (arg & changeable_bits[priv->minor]); |
561 | *data_out[priv->minor] = shadow; | 586 | *data_out[priv->minor] = shadow; |
@@ -563,46 +588,42 @@ gpio_ioctl(struct inode *inode, struct file *file, | |||
563 | break; | 588 | break; |
564 | case IO_CLRBITS: | 589 | case IO_CLRBITS: |
565 | local_irq_save(flags); | 590 | local_irq_save(flags); |
566 | if (arg & 0x04) | 591 | /* Clear changeable bits with a 1 in arg. */ |
567 | printk("GPIO CLR 2\n"); | ||
568 | // clear changeable bits with a 1 in arg | ||
569 | shadow = *data_out[priv->minor]; | 592 | shadow = *data_out[priv->minor]; |
570 | shadow &= ~(arg & changeable_bits[priv->minor]); | 593 | shadow &= ~(arg & changeable_bits[priv->minor]); |
571 | *data_out[priv->minor] = shadow; | 594 | *data_out[priv->minor] = shadow; |
572 | local_irq_restore(flags); | 595 | local_irq_restore(flags); |
573 | break; | 596 | break; |
574 | case IO_HIGHALARM: | 597 | case IO_HIGHALARM: |
575 | // set alarm when bits with 1 in arg go high | 598 | /* Set alarm when bits with 1 in arg go high. */ |
576 | priv->highalarm |= arg; | 599 | priv->highalarm |= arg; |
577 | spin_lock(&alarm_lock); | 600 | spin_lock_irqsave(&alarm_lock, flags); |
578 | gpio_some_alarms = 1; | 601 | gpio_some_alarms = 1; |
579 | if (priv->minor == GPIO_MINOR_A) { | 602 | if (priv->minor == GPIO_MINOR_A) |
580 | gpio_pa_high_alarms |= arg; | 603 | gpio_pa_high_alarms |= arg; |
581 | } | 604 | spin_unlock_irqrestore(&alarm_lock, flags); |
582 | spin_unlock(&alarm_lock); | ||
583 | break; | 605 | break; |
584 | case IO_LOWALARM: | 606 | case IO_LOWALARM: |
585 | // set alarm when bits with 1 in arg go low | 607 | /* Set alarm when bits with 1 in arg go low. */ |
586 | priv->lowalarm |= arg; | 608 | priv->lowalarm |= arg; |
587 | spin_lock(&alarm_lock); | 609 | spin_lock_irqsave(&alarm_lock, flags); |
588 | gpio_some_alarms = 1; | 610 | gpio_some_alarms = 1; |
589 | if (priv->minor == GPIO_MINOR_A) { | 611 | if (priv->minor == GPIO_MINOR_A) |
590 | gpio_pa_low_alarms |= arg; | 612 | gpio_pa_low_alarms |= arg; |
591 | } | 613 | spin_unlock_irqrestore(&alarm_lock, flags); |
592 | spin_unlock(&alarm_lock); | ||
593 | break; | 614 | break; |
594 | case IO_CLRALARM: | 615 | case IO_CLRALARM: |
595 | // clear alarm for bits with 1 in arg | 616 | /* Clear alarm for bits with 1 in arg. */ |
596 | priv->highalarm &= ~arg; | 617 | priv->highalarm &= ~arg; |
597 | priv->lowalarm &= ~arg; | 618 | priv->lowalarm &= ~arg; |
598 | spin_lock(&alarm_lock); | 619 | spin_lock_irqsave(&alarm_lock, flags); |
599 | if (priv->minor == GPIO_MINOR_A) { | 620 | if (priv->minor == GPIO_MINOR_A) { |
600 | if (gpio_pa_high_alarms & arg || | 621 | if (gpio_pa_high_alarms & arg || |
601 | gpio_pa_low_alarms & arg) { | 622 | gpio_pa_low_alarms & arg) |
602 | /* Must update the gpio_pa_*alarms masks */ | 623 | /* Must update the gpio_pa_*alarms masks */ |
603 | } | 624 | ; |
604 | } | 625 | } |
605 | spin_unlock(&alarm_lock); | 626 | spin_unlock_irqrestore(&alarm_lock, flags); |
606 | break; | 627 | break; |
607 | case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ | 628 | case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ |
608 | /* Read direction 0=input 1=output */ | 629 | /* Read direction 0=input 1=output */ |
@@ -633,8 +654,7 @@ gpio_ioctl(struct inode *inode, struct file *file, | |||
633 | if (!((priv->clk_mask & changeable_bits[priv->minor]) && | 654 | if (!((priv->clk_mask & changeable_bits[priv->minor]) && |
634 | (priv->data_mask & changeable_bits[priv->minor]) && | 655 | (priv->data_mask & changeable_bits[priv->minor]) && |
635 | (priv->clk_mask & dir_shadow) && | 656 | (priv->clk_mask & dir_shadow) && |
636 | (priv->data_mask & dir_shadow))) | 657 | (priv->data_mask & dir_shadow))) { |
637 | { | ||
638 | priv->clk_mask = 0; | 658 | priv->clk_mask = 0; |
639 | priv->data_mask = 0; | 659 | priv->data_mask = 0; |
640 | return -EPERM; | 660 | return -EPERM; |
@@ -644,34 +664,34 @@ gpio_ioctl(struct inode *inode, struct file *file, | |||
644 | case IO_READ_INBITS: | 664 | case IO_READ_INBITS: |
645 | /* *arg is result of reading the input pins */ | 665 | /* *arg is result of reading the input pins */ |
646 | val = *data_in[priv->minor]; | 666 | val = *data_in[priv->minor]; |
647 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) | 667 | if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) |
648 | return -EFAULT; | 668 | return -EFAULT; |
649 | return 0; | 669 | return 0; |
650 | break; | 670 | break; |
651 | case IO_READ_OUTBITS: | 671 | case IO_READ_OUTBITS: |
652 | /* *arg is result of reading the output shadow */ | 672 | /* *arg is result of reading the output shadow */ |
653 | val = *data_out[priv->minor]; | 673 | val = *data_out[priv->minor]; |
654 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) | 674 | if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) |
655 | return -EFAULT; | 675 | return -EFAULT; |
656 | break; | 676 | break; |
657 | case IO_SETGET_INPUT: | 677 | case IO_SETGET_INPUT: |
658 | /* bits set in *arg is set to input, | 678 | /* bits set in *arg is set to input, |
659 | * *arg updated with current input pins. | 679 | * *arg updated with current input pins. |
660 | */ | 680 | */ |
661 | if (copy_from_user(&val, (unsigned long*)arg, sizeof(val))) | 681 | if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) |
662 | return -EFAULT; | 682 | return -EFAULT; |
663 | val = setget_input(priv, val); | 683 | val = setget_input(priv, val); |
664 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) | 684 | if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) |
665 | return -EFAULT; | 685 | return -EFAULT; |
666 | break; | 686 | break; |
667 | case IO_SETGET_OUTPUT: | 687 | case IO_SETGET_OUTPUT: |
668 | /* bits set in *arg is set to output, | 688 | /* bits set in *arg is set to output, |
669 | * *arg updated with current output pins. | 689 | * *arg updated with current output pins. |
670 | */ | 690 | */ |
671 | if (copy_from_user(&val, (unsigned long*)arg, sizeof(val))) | 691 | if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) |
672 | return -EFAULT; | 692 | return -EFAULT; |
673 | val = setget_output(priv, val); | 693 | val = setget_output(priv, val); |
674 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) | 694 | if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) |
675 | return -EFAULT; | 695 | return -EFAULT; |
676 | break; | 696 | break; |
677 | default: | 697 | default: |
@@ -684,6 +704,133 @@ gpio_ioctl(struct inode *inode, struct file *file, | |||
684 | return 0; | 704 | return 0; |
685 | } | 705 | } |
686 | 706 | ||
707 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
708 | static int | ||
709 | virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
710 | { | ||
711 | unsigned long flags; | ||
712 | unsigned short val; | ||
713 | unsigned short shadow; | ||
714 | struct gpio_private *priv = (struct gpio_private *)file->private_data; | ||
715 | |||
716 | switch (_IOC_NR(cmd)) { | ||
717 | case IO_SETBITS: | ||
718 | local_irq_save(flags); | ||
719 | /* Set changeable bits with a 1 in arg. */ | ||
720 | i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); | ||
721 | shadow |= ~*dir_oe[priv->minor]; | ||
722 | shadow |= (arg & changeable_bits[priv->minor]); | ||
723 | i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); | ||
724 | local_irq_restore(flags); | ||
725 | break; | ||
726 | case IO_CLRBITS: | ||
727 | local_irq_save(flags); | ||
728 | /* Clear changeable bits with a 1 in arg. */ | ||
729 | i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); | ||
730 | shadow |= ~*dir_oe[priv->minor]; | ||
731 | shadow &= ~(arg & changeable_bits[priv->minor]); | ||
732 | i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); | ||
733 | local_irq_restore(flags); | ||
734 | break; | ||
735 | case IO_HIGHALARM: | ||
736 | /* Set alarm when bits with 1 in arg go high. */ | ||
737 | priv->highalarm |= arg; | ||
738 | spin_lock(&alarm_lock); | ||
739 | gpio_some_alarms = 1; | ||
740 | spin_unlock(&alarm_lock); | ||
741 | break; | ||
742 | case IO_LOWALARM: | ||
743 | /* Set alarm when bits with 1 in arg go low. */ | ||
744 | priv->lowalarm |= arg; | ||
745 | spin_lock(&alarm_lock); | ||
746 | gpio_some_alarms = 1; | ||
747 | spin_unlock(&alarm_lock); | ||
748 | break; | ||
749 | case IO_CLRALARM: | ||
750 | /* Clear alarm for bits with 1 in arg. */ | ||
751 | priv->highalarm &= ~arg; | ||
752 | priv->lowalarm &= ~arg; | ||
753 | spin_lock(&alarm_lock); | ||
754 | spin_unlock(&alarm_lock); | ||
755 | break; | ||
756 | case IO_CFG_WRITE_MODE: | ||
757 | { | ||
758 | unsigned long dir_shadow; | ||
759 | dir_shadow = *dir_oe[priv->minor]; | ||
760 | |||
761 | priv->clk_mask = arg & 0xFF; | ||
762 | priv->data_mask = (arg >> 8) & 0xFF; | ||
763 | priv->write_msb = (arg >> 16) & 0x01; | ||
764 | /* Check if we're allowed to change the bits and | ||
765 | * the direction is correct | ||
766 | */ | ||
767 | if (!((priv->clk_mask & changeable_bits[priv->minor]) && | ||
768 | (priv->data_mask & changeable_bits[priv->minor]) && | ||
769 | (priv->clk_mask & dir_shadow) && | ||
770 | (priv->data_mask & dir_shadow))) { | ||
771 | priv->clk_mask = 0; | ||
772 | priv->data_mask = 0; | ||
773 | return -EPERM; | ||
774 | } | ||
775 | break; | ||
776 | } | ||
777 | case IO_READ_INBITS: | ||
778 | /* *arg is result of reading the input pins */ | ||
779 | val = cached_virtual_gpio_read; | ||
780 | val &= ~*dir_oe[priv->minor]; | ||
781 | if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) | ||
782 | return -EFAULT; | ||
783 | return 0; | ||
784 | break; | ||
785 | case IO_READ_OUTBITS: | ||
786 | /* *arg is result of reading the output shadow */ | ||
787 | i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val)); | ||
788 | val &= *dir_oe[priv->minor]; | ||
789 | if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) | ||
790 | return -EFAULT; | ||
791 | break; | ||
792 | case IO_SETGET_INPUT: | ||
793 | { | ||
794 | /* bits set in *arg is set to input, | ||
795 | * *arg updated with current input pins. | ||
796 | */ | ||
797 | unsigned short input_mask = ~*dir_oe[priv->minor]; | ||
798 | if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) | ||
799 | return -EFAULT; | ||
800 | val = setget_input(priv, val); | ||
801 | if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) | ||
802 | return -EFAULT; | ||
803 | if ((input_mask & val) != input_mask) { | ||
804 | /* Input pins changed. All ports desired as input | ||
805 | * should be set to logic 1. | ||
806 | */ | ||
807 | unsigned short change = input_mask ^ val; | ||
808 | i2c_read(VIRT_I2C_ADDR, (void *)&shadow, | ||
809 | sizeof(shadow)); | ||
810 | shadow &= ~change; | ||
811 | shadow |= val; | ||
812 | i2c_write(VIRT_I2C_ADDR, (void *)&shadow, | ||
813 | sizeof(shadow)); | ||
814 | } | ||
815 | break; | ||
816 | } | ||
817 | case IO_SETGET_OUTPUT: | ||
818 | /* bits set in *arg is set to output, | ||
819 | * *arg updated with current output pins. | ||
820 | */ | ||
821 | if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) | ||
822 | return -EFAULT; | ||
823 | val = setget_output(priv, val); | ||
824 | if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) | ||
825 | return -EFAULT; | ||
826 | break; | ||
827 | default: | ||
828 | return -EINVAL; | ||
829 | } /* switch */ | ||
830 | return 0; | ||
831 | } | ||
832 | #endif /* CONFIG_ETRAX_VIRTUAL_GPIO */ | ||
833 | |||
687 | static int | 834 | static int |
688 | gpio_leds_ioctl(unsigned int cmd, unsigned long arg) | 835 | gpio_leds_ioctl(unsigned int cmd, unsigned long arg) |
689 | { | 836 | { |
@@ -694,8 +841,8 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg) | |||
694 | case IO_LEDACTIVE_SET: | 841 | case IO_LEDACTIVE_SET: |
695 | green = ((unsigned char) arg) & 1; | 842 | green = ((unsigned char) arg) & 1; |
696 | red = (((unsigned char) arg) >> 1) & 1; | 843 | red = (((unsigned char) arg) >> 1) & 1; |
697 | LED_ACTIVE_SET_G(green); | 844 | CRIS_LED_ACTIVE_SET_G(green); |
698 | LED_ACTIVE_SET_R(red); | 845 | CRIS_LED_ACTIVE_SET_R(red); |
699 | break; | 846 | break; |
700 | 847 | ||
701 | default: | 848 | default: |
@@ -705,7 +852,7 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg) | |||
705 | return 0; | 852 | return 0; |
706 | } | 853 | } |
707 | 854 | ||
708 | const struct file_operations gpio_fops = { | 855 | struct file_operations gpio_fops = { |
709 | .owner = THIS_MODULE, | 856 | .owner = THIS_MODULE, |
710 | .poll = gpio_poll, | 857 | .poll = gpio_poll, |
711 | .ioctl = gpio_ioctl, | 858 | .ioctl = gpio_ioctl, |
@@ -714,6 +861,66 @@ const struct file_operations gpio_fops = { | |||
714 | .release = gpio_release, | 861 | .release = gpio_release, |
715 | }; | 862 | }; |
716 | 863 | ||
864 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO | ||
865 | static void | ||
866 | virtual_gpio_init(void) | ||
867 | { | ||
868 | reg_gio_rw_intr_cfg intr_cfg; | ||
869 | reg_gio_rw_intr_mask intr_mask; | ||
870 | unsigned short shadow; | ||
871 | |||
872 | shadow = ~virtual_rw_pv_oe; /* Input ports should be set to logic 1 */ | ||
873 | shadow |= CONFIG_ETRAX_DEF_GIO_PV_OUT; | ||
874 | i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); | ||
875 | |||
876 | /* Set interrupt mask and on what state the interrupt shall trigger. | ||
877 | * For virtual gpio the interrupt shall trigger on logic '0'. | ||
878 | */ | ||
879 | intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg); | ||
880 | intr_mask = REG_RD(gio, regi_gio, rw_intr_mask); | ||
881 | |||
882 | switch (CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN) { | ||
883 | case 0: | ||
884 | intr_cfg.pa0 = regk_gio_lo; | ||
885 | intr_mask.pa0 = regk_gio_yes; | ||
886 | break; | ||
887 | case 1: | ||
888 | intr_cfg.pa1 = regk_gio_lo; | ||
889 | intr_mask.pa1 = regk_gio_yes; | ||
890 | break; | ||
891 | case 2: | ||
892 | intr_cfg.pa2 = regk_gio_lo; | ||
893 | intr_mask.pa2 = regk_gio_yes; | ||
894 | break; | ||
895 | case 3: | ||
896 | intr_cfg.pa3 = regk_gio_lo; | ||
897 | intr_mask.pa3 = regk_gio_yes; | ||
898 | break; | ||
899 | case 4: | ||
900 | intr_cfg.pa4 = regk_gio_lo; | ||
901 | intr_mask.pa4 = regk_gio_yes; | ||
902 | break; | ||
903 | case 5: | ||
904 | intr_cfg.pa5 = regk_gio_lo; | ||
905 | intr_mask.pa5 = regk_gio_yes; | ||
906 | break; | ||
907 | case 6: | ||
908 | intr_cfg.pa6 = regk_gio_lo; | ||
909 | intr_mask.pa6 = regk_gio_yes; | ||
910 | break; | ||
911 | case 7: | ||
912 | intr_cfg.pa7 = regk_gio_lo; | ||
913 | intr_mask.pa7 = regk_gio_yes; | ||
914 | break; | ||
915 | } | ||
916 | |||
917 | REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg); | ||
918 | REG_WR(gio, regi_gio, rw_intr_mask, intr_mask); | ||
919 | |||
920 | gpio_pa_low_alarms |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); | ||
921 | gpio_some_alarms = 1; | ||
922 | } | ||
923 | #endif | ||
717 | 924 | ||
718 | /* main driver initialization routine, called from mem.c */ | 925 | /* main driver initialization routine, called from mem.c */ |
719 | 926 | ||
@@ -721,7 +928,6 @@ static __init int | |||
721 | gpio_init(void) | 928 | gpio_init(void) |
722 | { | 929 | { |
723 | int res; | 930 | int res; |
724 | reg_intr_vect_rw_mask intr_mask; | ||
725 | 931 | ||
726 | /* do the formalities */ | 932 | /* do the formalities */ |
727 | 933 | ||
@@ -732,30 +938,30 @@ gpio_init(void) | |||
732 | } | 938 | } |
733 | 939 | ||
734 | /* Clear all leds */ | 940 | /* Clear all leds */ |
735 | LED_NETWORK_SET(0); | 941 | CRIS_LED_NETWORK_GRP0_SET(0); |
736 | LED_ACTIVE_SET(0); | 942 | CRIS_LED_NETWORK_GRP1_SET(0); |
737 | LED_DISK_READ(0); | 943 | CRIS_LED_ACTIVE_SET(0); |
738 | LED_DISK_WRITE(0); | 944 | CRIS_LED_DISK_READ(0); |
739 | 945 | CRIS_LED_DISK_WRITE(0); | |
740 | printk("ETRAX FS GPIO driver v2.5, (c) 2003-2005 Axis Communications AB\n"); | 946 | |
947 | printk(KERN_INFO "ETRAX FS GPIO driver v2.5, (c) 2003-2007 " | ||
948 | "Axis Communications AB\n"); | ||
741 | /* We call etrax_gpio_wake_up_check() from timer interrupt and | 949 | /* We call etrax_gpio_wake_up_check() from timer interrupt and |
742 | * from cpu_idle() in kernel/process.c | 950 | * from cpu_idle() in kernel/process.c |
743 | * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms | 951 | * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms |
744 | * in some tests. | 952 | * in some tests. |
745 | */ | 953 | */ |
746 | if (request_irq(TIMER_INTR_VECT, gpio_poll_timer_interrupt, | 954 | if (request_irq(TIMER0_INTR_VECT, gpio_poll_timer_interrupt, |
747 | IRQF_SHARED | IRQF_DISABLED,"gpio poll", &alarmlist)) { | 955 | IRQF_SHARED | IRQF_DISABLED, "gpio poll", &alarmlist)) |
748 | printk("err: timer0 irq for gpio\n"); | 956 | printk(KERN_ERR "timer0 irq for gpio\n"); |
749 | } | 957 | |
750 | if (request_irq(GEN_IO_INTR_VECT, gpio_pa_interrupt, | 958 | if (request_irq(GIO_INTR_VECT, gpio_pa_interrupt, |
751 | IRQF_SHARED | IRQF_DISABLED,"gpio PA", &alarmlist)) { | 959 | IRQF_SHARED | IRQF_DISABLED, "gpio PA", &alarmlist)) |
752 | printk("err: PA irq for gpio\n"); | 960 | printk(KERN_ERR "PA irq for gpio\n"); |
753 | } | 961 | |
754 | /* enable the gio and timer irq in global config */ | 962 | #ifdef CONFIG_ETRAX_VIRTUAL_GPIO |
755 | intr_mask = REG_RD(intr_vect, regi_irq, rw_mask); | 963 | virtual_gpio_init(); |
756 | intr_mask.timer = 1; | 964 | #endif |
757 | intr_mask.gen_io = 1; | ||
758 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); | ||
759 | 965 | ||
760 | return res; | 966 | return res; |
761 | } | 967 | } |
diff --git a/arch/cris/arch-v32/drivers/nandflash.c b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c index 5ce015c6bb0d..aa01b134458a 100644 --- a/arch/cris/arch-v32/drivers/nandflash.c +++ b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c | |||
@@ -4,9 +4,7 @@ | |||
4 | * Copyright (c) 2004 | 4 | * Copyright (c) 2004 |
5 | * | 5 | * |
6 | * Derived from drivers/mtd/nand/spia.c | 6 | * Derived from drivers/mtd/nand/spia.c |
7 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) | 7 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) |
8 | * | ||
9 | * $Id: nandflash.c,v 1.3 2005/06/01 10:57:12 starvik Exp $ | ||
10 | * | 8 | * |
11 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
@@ -21,10 +19,10 @@ | |||
21 | #include <linux/mtd/nand.h> | 19 | #include <linux/mtd/nand.h> |
22 | #include <linux/mtd/partitions.h> | 20 | #include <linux/mtd/partitions.h> |
23 | #include <asm/arch/memmap.h> | 21 | #include <asm/arch/memmap.h> |
24 | #include <asm/arch/hwregs/reg_map.h> | 22 | #include <hwregs/reg_map.h> |
25 | #include <asm/arch/hwregs/reg_rdwr.h> | 23 | #include <hwregs/reg_rdwr.h> |
26 | #include <asm/arch/hwregs/gio_defs.h> | 24 | #include <hwregs/gio_defs.h> |
27 | #include <asm/arch/hwregs/bif_core_defs.h> | 25 | #include <hwregs/bif_core_defs.h> |
28 | #include <asm/io.h> | 26 | #include <asm/io.h> |
29 | 27 | ||
30 | #define CE_BIT 4 | 28 | #define CE_BIT 4 |
@@ -32,44 +30,65 @@ | |||
32 | #define ALE_BIT 6 | 30 | #define ALE_BIT 6 |
33 | #define BY_BIT 7 | 31 | #define BY_BIT 7 |
34 | 32 | ||
35 | static struct mtd_info *crisv32_mtd = NULL; | 33 | struct mtd_info_wrapper { |
34 | struct mtd_info info; | ||
35 | struct nand_chip chip; | ||
36 | }; | ||
37 | |||
38 | /* Bitmask for control pins */ | ||
39 | #define PIN_BITMASK ((1 << CE_BIT) | (1 << CLE_BIT) | (1 << ALE_BIT)) | ||
40 | |||
41 | /* Bitmask for mtd nand control bits */ | ||
42 | #define CTRL_BITMASK (NAND_NCE | NAND_CLE | NAND_ALE) | ||
43 | |||
44 | |||
45 | static struct mtd_info *crisv32_mtd; | ||
36 | /* | 46 | /* |
37 | * hardware specific access to control-lines | 47 | * hardware specific access to control-lines |
38 | */ | 48 | */ |
39 | static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd) | 49 | static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd, |
50 | unsigned int ctrl) | ||
40 | { | 51 | { |
41 | unsigned long flags; | 52 | unsigned long flags; |
42 | reg_gio_rw_pa_dout dout = REG_RD(gio, regi_gio, rw_pa_dout); | 53 | reg_gio_rw_pa_dout dout; |
54 | struct nand_chip *this = mtd->priv; | ||
43 | 55 | ||
44 | local_irq_save(flags); | 56 | local_irq_save(flags); |
45 | switch(cmd){ | 57 | |
46 | case NAND_CTL_SETCLE: | 58 | /* control bits change */ |
47 | dout.data |= (1<<CLE_BIT); | 59 | if (ctrl & NAND_CTRL_CHANGE) { |
48 | break; | 60 | dout = REG_RD(gio, regi_gio, rw_pa_dout); |
49 | case NAND_CTL_CLRCLE: | 61 | dout.data &= ~PIN_BITMASK; |
50 | dout.data &= ~(1<<CLE_BIT); | 62 | |
51 | break; | 63 | #if (CE_BIT == 4 && NAND_NCE == 1 && \ |
52 | case NAND_CTL_SETALE: | 64 | CLE_BIT == 5 && NAND_CLE == 2 && \ |
53 | dout.data |= (1<<ALE_BIT); | 65 | ALE_BIT == 6 && NAND_ALE == 4) |
54 | break; | 66 | /* Pins in same order as control bits, but shifted. |
55 | case NAND_CTL_CLRALE: | 67 | * Optimize for this case; works for 2.6.18 */ |
56 | dout.data &= ~(1<<ALE_BIT); | 68 | dout.data |= ((ctrl & CTRL_BITMASK) ^ NAND_NCE) << CE_BIT; |
57 | break; | 69 | #else |
58 | case NAND_CTL_SETNCE: | 70 | /* the slow way */ |
59 | dout.data |= (1<<CE_BIT); | 71 | if (!(ctrl & NAND_NCE)) |
60 | break; | 72 | dout.data |= (1 << CE_BIT); |
61 | case NAND_CTL_CLRNCE: | 73 | if (ctrl & NAND_CLE) |
62 | dout.data &= ~(1<<CE_BIT); | 74 | dout.data |= (1 << CLE_BIT); |
63 | break; | 75 | if (ctrl & NAND_ALE) |
76 | dout.data |= (1 << ALE_BIT); | ||
77 | #endif | ||
78 | REG_WR(gio, regi_gio, rw_pa_dout, dout); | ||
64 | } | 79 | } |
65 | REG_WR(gio, regi_gio, rw_pa_dout, dout); | 80 | |
81 | /* command to chip */ | ||
82 | if (cmd != NAND_CMD_NONE) | ||
83 | writeb(cmd, this->IO_ADDR_W); | ||
84 | |||
66 | local_irq_restore(flags); | 85 | local_irq_restore(flags); |
67 | } | 86 | } |
68 | 87 | ||
69 | /* | 88 | /* |
70 | * read device ready pin | 89 | * read device ready pin |
71 | */ | 90 | */ |
72 | int crisv32_device_ready(struct mtd_info *mtd) | 91 | static int crisv32_device_ready(struct mtd_info *mtd) |
73 | { | 92 | { |
74 | reg_gio_r_pa_din din = REG_RD(gio, regi_gio, r_pa_din); | 93 | reg_gio_r_pa_din din = REG_RD(gio, regi_gio, r_pa_din); |
75 | return ((din.data & (1 << BY_BIT)) >> BY_BIT); | 94 | return ((din.data & (1 << BY_BIT)) >> BY_BIT); |
@@ -78,21 +97,23 @@ int crisv32_device_ready(struct mtd_info *mtd) | |||
78 | /* | 97 | /* |
79 | * Main initialization routine | 98 | * Main initialization routine |
80 | */ | 99 | */ |
81 | struct mtd_info* __init crisv32_nand_flash_probe (void) | 100 | struct mtd_info *__init crisv32_nand_flash_probe(void) |
82 | { | 101 | { |
83 | void __iomem *read_cs; | 102 | void __iomem *read_cs; |
84 | void __iomem *write_cs; | 103 | void __iomem *write_cs; |
85 | 104 | ||
86 | reg_bif_core_rw_grp3_cfg bif_cfg = REG_RD(bif_core, regi_bif_core, rw_grp3_cfg); | 105 | reg_bif_core_rw_grp3_cfg bif_cfg = REG_RD(bif_core, regi_bif_core, |
106 | rw_grp3_cfg); | ||
87 | reg_gio_rw_pa_oe pa_oe = REG_RD(gio, regi_gio, rw_pa_oe); | 107 | reg_gio_rw_pa_oe pa_oe = REG_RD(gio, regi_gio, rw_pa_oe); |
108 | struct mtd_info_wrapper *wrapper; | ||
88 | struct nand_chip *this; | 109 | struct nand_chip *this; |
89 | int err = 0; | 110 | int err = 0; |
90 | 111 | ||
91 | /* Allocate memory for MTD device structure and private data */ | 112 | /* Allocate memory for MTD device structure and private data */ |
92 | crisv32_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), | 113 | wrapper = kzalloc(sizeof(struct mtd_info_wrapper), GFP_KERNEL); |
93 | GFP_KERNEL); | 114 | if (!wrapper) { |
94 | if (!crisv32_mtd) { | 115 | printk(KERN_ERR "Unable to allocate CRISv32 NAND MTD " |
95 | printk ("Unable to allocate CRISv32 NAND MTD device structure.\n"); | 116 | "device structure.\n"); |
96 | err = -ENOMEM; | 117 | err = -ENOMEM; |
97 | return NULL; | 118 | return NULL; |
98 | } | 119 | } |
@@ -101,45 +122,42 @@ struct mtd_info* __init crisv32_nand_flash_probe (void) | |||
101 | write_cs = ioremap(MEM_CSP1_START | MEM_NON_CACHEABLE, 8192); | 122 | write_cs = ioremap(MEM_CSP1_START | MEM_NON_CACHEABLE, 8192); |
102 | 123 | ||
103 | if (!read_cs || !write_cs) { | 124 | if (!read_cs || !write_cs) { |
104 | printk("CRISv32 NAND ioremap failed\n"); | 125 | printk(KERN_ERR "CRISv32 NAND ioremap failed\n"); |
105 | err = -EIO; | 126 | err = -EIO; |
106 | goto out_mtd; | 127 | goto out_mtd; |
107 | } | 128 | } |
108 | 129 | ||
109 | /* Get pointer to private data */ | 130 | /* Get pointer to private data */ |
110 | this = (struct nand_chip *) (&crisv32_mtd[1]); | 131 | this = &wrapper->chip; |
132 | crisv32_mtd = &wrapper->info; | ||
111 | 133 | ||
112 | pa_oe.oe |= 1 << CE_BIT; | 134 | pa_oe.oe |= 1 << CE_BIT; |
113 | pa_oe.oe |= 1 << ALE_BIT; | 135 | pa_oe.oe |= 1 << ALE_BIT; |
114 | pa_oe.oe |= 1 << CLE_BIT; | 136 | pa_oe.oe |= 1 << CLE_BIT; |
115 | pa_oe.oe &= ~ (1 << BY_BIT); | 137 | pa_oe.oe &= ~(1 << BY_BIT); |
116 | REG_WR(gio, regi_gio, rw_pa_oe, pa_oe); | 138 | REG_WR(gio, regi_gio, rw_pa_oe, pa_oe); |
117 | 139 | ||
118 | bif_cfg.gated_csp0 = regk_bif_core_rd; | 140 | bif_cfg.gated_csp0 = regk_bif_core_rd; |
119 | bif_cfg.gated_csp1 = regk_bif_core_wr; | 141 | bif_cfg.gated_csp1 = regk_bif_core_wr; |
120 | REG_WR(bif_core, regi_bif_core, rw_grp3_cfg, bif_cfg); | 142 | REG_WR(bif_core, regi_bif_core, rw_grp3_cfg, bif_cfg); |
121 | 143 | ||
122 | /* Initialize structures */ | ||
123 | memset((char *) crisv32_mtd, 0, sizeof(struct mtd_info)); | ||
124 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
125 | |||
126 | /* Link the private data with the MTD structure */ | 144 | /* Link the private data with the MTD structure */ |
127 | crisv32_mtd->priv = this; | 145 | crisv32_mtd->priv = this; |
128 | 146 | ||
129 | /* Set address of NAND IO lines */ | 147 | /* Set address of NAND IO lines */ |
130 | this->IO_ADDR_R = read_cs; | 148 | this->IO_ADDR_R = read_cs; |
131 | this->IO_ADDR_W = write_cs; | 149 | this->IO_ADDR_W = write_cs; |
132 | this->hwcontrol = crisv32_hwcontrol; | 150 | this->cmd_ctrl = crisv32_hwcontrol; |
133 | this->dev_ready = crisv32_device_ready; | 151 | this->dev_ready = crisv32_device_ready; |
134 | /* 20 us command delay time */ | 152 | /* 20 us command delay time */ |
135 | this->chip_delay = 20; | 153 | this->chip_delay = 20; |
136 | this->eccmode = NAND_ECC_SOFT; | 154 | this->ecc.mode = NAND_ECC_SOFT; |
137 | 155 | ||
138 | /* Enable the following for a flash based bad block table */ | 156 | /* Enable the following for a flash based bad block table */ |
139 | this->options = NAND_USE_FLASH_BBT; | 157 | /* this->options = NAND_USE_FLASH_BBT; */ |
140 | 158 | ||
141 | /* Scan to find existence of the device */ | 159 | /* Scan to find existance of the device */ |
142 | if (nand_scan (crisv32_mtd, 1)) { | 160 | if (nand_scan(crisv32_mtd, 1)) { |
143 | err = -ENXIO; | 161 | err = -ENXIO; |
144 | goto out_ior; | 162 | goto out_ior; |
145 | } | 163 | } |
@@ -150,7 +168,7 @@ out_ior: | |||
150 | iounmap((void *)read_cs); | 168 | iounmap((void *)read_cs); |
151 | iounmap((void *)write_cs); | 169 | iounmap((void *)write_cs); |
152 | out_mtd: | 170 | out_mtd: |
153 | kfree (crisv32_mtd); | 171 | kfree(wrapper); |
154 | return NULL; | 172 | return NULL; |
155 | } | 173 | } |
156 | 174 | ||
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c index 6dbd700d3d66..53db3870ba04 100644 --- a/arch/cris/arch-v32/drivers/pcf8563.c +++ b/arch/cris/arch-v32/drivers/pcf8563.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * 400 kbits/s. The built-in word address register is incremented | 10 | * 400 kbits/s. The built-in word address register is incremented |
11 | * automatically after each written or read byte. | 11 | * automatically after each written or read byte. |
12 | * | 12 | * |
13 | * Copyright (c) 2002-2003, Axis Communications AB | 13 | * Copyright (c) 2002-2007, Axis Communications AB |
14 | * All rights reserved. | 14 | * All rights reserved. |
15 | * | 15 | * |
16 | * Author: Tobias Anderberg <tobiasa@axis.com>. | 16 | * Author: Tobias Anderberg <tobiasa@axis.com>. |
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/ioctl.h> | 26 | #include <linux/ioctl.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/bcd.h> | 28 | #include <linux/bcd.h> |
29 | #include <linux/mutex.h> | ||
29 | 30 | ||
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
31 | #include <asm/system.h> | 32 | #include <asm/system.h> |
@@ -37,24 +38,27 @@ | |||
37 | #define PCF8563_MAJOR 121 /* Local major number. */ | 38 | #define PCF8563_MAJOR 121 /* Local major number. */ |
38 | #define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */ | 39 | #define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */ |
39 | #define PCF8563_NAME "PCF8563" | 40 | #define PCF8563_NAME "PCF8563" |
40 | #define DRIVER_VERSION "$Revision: 1.1 $" | 41 | #define DRIVER_VERSION "$Revision: 1.17 $" |
41 | 42 | ||
42 | /* Two simple wrapper macros, saves a few keystrokes. */ | 43 | /* Two simple wrapper macros, saves a few keystrokes. */ |
43 | #define rtc_read(x) i2c_readreg(RTC_I2C_READ, x) | 44 | #define rtc_read(x) i2c_readreg(RTC_I2C_READ, x) |
44 | #define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y) | 45 | #define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y) |
45 | 46 | ||
47 | static DEFINE_MUTEX(rtc_lock); /* Protect state etc */ | ||
48 | |||
46 | static const unsigned char days_in_month[] = | 49 | static const unsigned char days_in_month[] = |
47 | { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; | 50 | { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
48 | 51 | ||
49 | int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long); | 52 | int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long); |
50 | int pcf8563_open(struct inode *, struct file *); | 53 | |
51 | int pcf8563_release(struct inode *, struct file *); | 54 | /* Cache VL bit value read at driver init since writing the RTC_SECOND |
55 | * register clears the VL status. | ||
56 | */ | ||
57 | static int voltage_low; | ||
52 | 58 | ||
53 | static const struct file_operations pcf8563_fops = { | 59 | static const struct file_operations pcf8563_fops = { |
54 | .owner = THIS_MODULE, | 60 | .owner = THIS_MODULE, |
55 | .ioctl = pcf8563_ioctl, | 61 | .ioctl = pcf8563_ioctl |
56 | .open = pcf8563_open, | ||
57 | .release = pcf8563_release, | ||
58 | }; | 62 | }; |
59 | 63 | ||
60 | unsigned char | 64 | unsigned char |
@@ -62,7 +66,7 @@ pcf8563_readreg(int reg) | |||
62 | { | 66 | { |
63 | unsigned char res = rtc_read(reg); | 67 | unsigned char res = rtc_read(reg); |
64 | 68 | ||
65 | /* The PCF8563 does not return 0 for unimplemented bits */ | 69 | /* The PCF8563 does not return 0 for unimplemented bits. */ |
66 | switch (reg) { | 70 | switch (reg) { |
67 | case RTC_SECONDS: | 71 | case RTC_SECONDS: |
68 | case RTC_MINUTES: | 72 | case RTC_MINUTES: |
@@ -95,11 +99,6 @@ pcf8563_readreg(int reg) | |||
95 | void | 99 | void |
96 | pcf8563_writereg(int reg, unsigned char val) | 100 | pcf8563_writereg(int reg, unsigned char val) |
97 | { | 101 | { |
98 | #ifdef CONFIG_ETRAX_RTC_READONLY | ||
99 | if (reg == RTC_CONTROL1 || (reg >= RTC_SECONDS && reg <= RTC_YEAR)) | ||
100 | return; | ||
101 | #endif | ||
102 | |||
103 | rtc_write(reg, val); | 102 | rtc_write(reg, val); |
104 | } | 103 | } |
105 | 104 | ||
@@ -114,11 +113,13 @@ get_rtc_time(struct rtc_time *tm) | |||
114 | tm->tm_mon = rtc_read(RTC_MONTH); | 113 | tm->tm_mon = rtc_read(RTC_MONTH); |
115 | tm->tm_year = rtc_read(RTC_YEAR); | 114 | tm->tm_year = rtc_read(RTC_YEAR); |
116 | 115 | ||
117 | if (tm->tm_sec & 0x80) | 116 | if (tm->tm_sec & 0x80) { |
118 | printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time " | 117 | printk(KERN_ERR "%s: RTC Voltage Low - reliable date/time " |
119 | "information is no longer guaranteed!\n", PCF8563_NAME); | 118 | "information is no longer guaranteed!\n", PCF8563_NAME); |
119 | } | ||
120 | 120 | ||
121 | tm->tm_year = BCD_TO_BIN(tm->tm_year) + ((tm->tm_mon & 0x80) ? 100 : 0); | 121 | tm->tm_year = BCD_TO_BIN(tm->tm_year) + |
122 | ((tm->tm_mon & 0x80) ? 100 : 0); | ||
122 | tm->tm_sec &= 0x7F; | 123 | tm->tm_sec &= 0x7F; |
123 | tm->tm_min &= 0x7F; | 124 | tm->tm_min &= 0x7F; |
124 | tm->tm_hour &= 0x3F; | 125 | tm->tm_hour &= 0x3F; |
@@ -137,8 +138,19 @@ get_rtc_time(struct rtc_time *tm) | |||
137 | int __init | 138 | int __init |
138 | pcf8563_init(void) | 139 | pcf8563_init(void) |
139 | { | 140 | { |
141 | static int res; | ||
142 | static int first = 1; | ||
143 | |||
144 | if (!first) | ||
145 | return res; | ||
146 | first = 0; | ||
147 | |||
140 | /* Initiate the i2c protocol. */ | 148 | /* Initiate the i2c protocol. */ |
141 | i2c_init(); | 149 | res = i2c_init(); |
150 | if (res < 0) { | ||
151 | printk(KERN_CRIT "pcf8563_init: Failed to init i2c.\n"); | ||
152 | return res; | ||
153 | } | ||
142 | 154 | ||
143 | /* | 155 | /* |
144 | * First of all we need to reset the chip. This is done by | 156 | * First of all we need to reset the chip. This is done by |
@@ -170,24 +182,20 @@ pcf8563_init(void) | |||
170 | if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0) | 182 | if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0) |
171 | goto err; | 183 | goto err; |
172 | 184 | ||
173 | if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) { | 185 | /* Check for low voltage, and warn about it. */ |
174 | printk(KERN_INFO "%s: Unable to get major number %d for RTC device.\n", | 186 | if (rtc_read(RTC_SECONDS) & 0x80) { |
175 | PCF8563_NAME, PCF8563_MAJOR); | 187 | voltage_low = 1; |
176 | return -1; | 188 | printk(KERN_WARNING "%s: RTC Voltage Low - reliable " |
189 | "date/time information is no longer guaranteed!\n", | ||
190 | PCF8563_NAME); | ||
177 | } | 191 | } |
178 | 192 | ||
179 | printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME, DRIVER_VERSION); | 193 | return res; |
180 | |||
181 | /* Check for low voltage, and warn about it.. */ | ||
182 | if (rtc_read(RTC_SECONDS) & 0x80) | ||
183 | printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time " | ||
184 | "information is no longer guaranteed!\n", PCF8563_NAME); | ||
185 | |||
186 | return 0; | ||
187 | 194 | ||
188 | err: | 195 | err: |
189 | printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME); | 196 | printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME); |
190 | return -1; | 197 | res = -1; |
198 | return res; | ||
191 | } | 199 | } |
192 | 200 | ||
193 | void __exit | 201 | void __exit |
@@ -200,8 +208,8 @@ pcf8563_exit(void) | |||
200 | * ioctl calls for this driver. Why return -ENOTTY upon error? Because | 208 | * ioctl calls for this driver. Why return -ENOTTY upon error? Because |
201 | * POSIX says so! | 209 | * POSIX says so! |
202 | */ | 210 | */ |
203 | int | 211 | int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, |
204 | pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) | 212 | unsigned long arg) |
205 | { | 213 | { |
206 | /* Some sanity checks. */ | 214 | /* Some sanity checks. */ |
207 | if (_IOC_TYPE(cmd) != RTC_MAGIC) | 215 | if (_IOC_TYPE(cmd) != RTC_MAGIC) |
@@ -211,125 +219,147 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned | |||
211 | return -ENOTTY; | 219 | return -ENOTTY; |
212 | 220 | ||
213 | switch (cmd) { | 221 | switch (cmd) { |
214 | case RTC_RD_TIME: | 222 | case RTC_RD_TIME: |
215 | { | 223 | { |
216 | struct rtc_time tm; | 224 | struct rtc_time tm; |
217 | 225 | ||
218 | memset(&tm, 0, sizeof (struct rtc_time)); | 226 | mutex_lock(&rtc_lock); |
219 | get_rtc_time(&tm); | 227 | memset(&tm, 0, sizeof tm); |
220 | 228 | get_rtc_time(&tm); | |
221 | if (copy_to_user((struct rtc_time *) arg, &tm, sizeof tm)) { | 229 | |
222 | return -EFAULT; | 230 | if (copy_to_user((struct rtc_time *) arg, &tm, |
223 | } | 231 | sizeof tm)) { |
224 | 232 | spin_unlock(&rtc_lock); | |
225 | return 0; | 233 | return -EFAULT; |
226 | } | 234 | } |
227 | 235 | ||
228 | case RTC_SET_TIME: | 236 | mutex_unlock(&rtc_lock); |
229 | { | 237 | |
230 | #ifdef CONFIG_ETRAX_RTC_READONLY | 238 | return 0; |
239 | } | ||
240 | case RTC_SET_TIME: | ||
241 | { | ||
242 | int leap; | ||
243 | int year; | ||
244 | int century; | ||
245 | struct rtc_time tm; | ||
246 | |||
247 | memset(&tm, 0, sizeof tm); | ||
248 | if (!capable(CAP_SYS_TIME)) | ||
231 | return -EPERM; | 249 | return -EPERM; |
232 | #else | ||
233 | int leap; | ||
234 | int year; | ||
235 | int century; | ||
236 | struct rtc_time tm; | ||
237 | |||
238 | if (!capable(CAP_SYS_TIME)) | ||
239 | return -EPERM; | ||
240 | |||
241 | if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof tm)) | ||
242 | return -EFAULT; | ||
243 | |||
244 | /* Convert from struct tm to struct rtc_time. */ | ||
245 | tm.tm_year += 1900; | ||
246 | tm.tm_mon += 1; | ||
247 | |||
248 | /* | ||
249 | * Check if tm.tm_year is a leap year. A year is a leap | ||
250 | * year if it is divisible by 4 but not 100, except | ||
251 | * that years divisible by 400 _are_ leap years. | ||
252 | */ | ||
253 | year = tm.tm_year; | ||
254 | leap = (tm.tm_mon == 2) && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0); | ||
255 | |||
256 | /* Perform some sanity checks. */ | ||
257 | if ((tm.tm_year < 1970) || | ||
258 | (tm.tm_mon > 12) || | ||
259 | (tm.tm_mday == 0) || | ||
260 | (tm.tm_mday > days_in_month[tm.tm_mon] + leap) || | ||
261 | (tm.tm_wday >= 7) || | ||
262 | (tm.tm_hour >= 24) || | ||
263 | (tm.tm_min >= 60) || | ||
264 | (tm.tm_sec >= 60)) | ||
265 | return -EINVAL; | ||
266 | |||
267 | century = (tm.tm_year >= 2000) ? 0x80 : 0; | ||
268 | tm.tm_year = tm.tm_year % 100; | ||
269 | |||
270 | BIN_TO_BCD(tm.tm_year); | ||
271 | BIN_TO_BCD(tm.tm_mday); | ||
272 | BIN_TO_BCD(tm.tm_hour); | ||
273 | BIN_TO_BCD(tm.tm_min); | ||
274 | BIN_TO_BCD(tm.tm_sec); | ||
275 | tm.tm_mon |= century; | ||
276 | |||
277 | rtc_write(RTC_YEAR, tm.tm_year); | ||
278 | rtc_write(RTC_MONTH, tm.tm_mon); | ||
279 | rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */ | ||
280 | rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday); | ||
281 | rtc_write(RTC_HOURS, tm.tm_hour); | ||
282 | rtc_write(RTC_MINUTES, tm.tm_min); | ||
283 | rtc_write(RTC_SECONDS, tm.tm_sec); | ||
284 | |||
285 | return 0; | ||
286 | #endif /* !CONFIG_ETRAX_RTC_READONLY */ | ||
287 | } | ||
288 | 250 | ||
289 | case RTC_VLOW_RD: | 251 | if (copy_from_user(&tm, (struct rtc_time *) arg, |
290 | { | 252 | sizeof tm)) |
291 | int vl_bit = 0; | 253 | return -EFAULT; |
254 | |||
255 | /* Convert from struct tm to struct rtc_time. */ | ||
256 | tm.tm_year += 1900; | ||
257 | tm.tm_mon += 1; | ||
258 | |||
259 | /* | ||
260 | * Check if tm.tm_year is a leap year. A year is a leap | ||
261 | * year if it is divisible by 4 but not 100, except | ||
262 | * that years divisible by 400 _are_ leap years. | ||
263 | */ | ||
264 | year = tm.tm_year; | ||
265 | leap = (tm.tm_mon == 2) && | ||
266 | ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0); | ||
267 | |||
268 | /* Perform some sanity checks. */ | ||
269 | if ((tm.tm_year < 1970) || | ||
270 | (tm.tm_mon > 12) || | ||
271 | (tm.tm_mday == 0) || | ||
272 | (tm.tm_mday > days_in_month[tm.tm_mon] + leap) || | ||
273 | (tm.tm_wday >= 7) || | ||
274 | (tm.tm_hour >= 24) || | ||
275 | (tm.tm_min >= 60) || | ||
276 | (tm.tm_sec >= 60)) | ||
277 | return -EINVAL; | ||
278 | |||
279 | century = (tm.tm_year >= 2000) ? 0x80 : 0; | ||
280 | tm.tm_year = tm.tm_year % 100; | ||
281 | |||
282 | BIN_TO_BCD(tm.tm_year); | ||
283 | BIN_TO_BCD(tm.tm_mon); | ||
284 | BIN_TO_BCD(tm.tm_mday); | ||
285 | BIN_TO_BCD(tm.tm_hour); | ||
286 | BIN_TO_BCD(tm.tm_min); | ||
287 | BIN_TO_BCD(tm.tm_sec); | ||
288 | tm.tm_mon |= century; | ||
289 | |||
290 | mutex_lock(&rtc_lock); | ||
291 | |||
292 | rtc_write(RTC_YEAR, tm.tm_year); | ||
293 | rtc_write(RTC_MONTH, tm.tm_mon); | ||
294 | rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */ | ||
295 | rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday); | ||
296 | rtc_write(RTC_HOURS, tm.tm_hour); | ||
297 | rtc_write(RTC_MINUTES, tm.tm_min); | ||
298 | rtc_write(RTC_SECONDS, tm.tm_sec); | ||
299 | |||
300 | mutex_unlock(&rtc_lock); | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | case RTC_VL_READ: | ||
305 | if (voltage_low) | ||
306 | printk(KERN_ERR "%s: RTC Voltage Low - " | ||
307 | "reliable date/time information is no " | ||
308 | "longer guaranteed!\n", PCF8563_NAME); | ||
292 | 309 | ||
293 | if (rtc_read(RTC_SECONDS) & 0x80) { | 310 | if (copy_to_user((int *) arg, &voltage_low, sizeof(int))) |
294 | vl_bit = 1; | 311 | return -EFAULT; |
295 | printk(KERN_WARNING "%s: RTC Voltage Low - reliable " | 312 | return 0; |
296 | "date/time information is no longer guaranteed!\n", | ||
297 | PCF8563_NAME); | ||
298 | } | ||
299 | if (copy_to_user((int *) arg, &vl_bit, sizeof(int))) | ||
300 | return -EFAULT; | ||
301 | 313 | ||
302 | return 0; | 314 | case RTC_VL_CLR: |
303 | } | 315 | { |
316 | /* Clear the VL bit in the seconds register in case | ||
317 | * the time has not been set already (which would | ||
318 | * have cleared it). This does not really matter | ||
319 | * because of the cached voltage_low value but do it | ||
320 | * anyway for consistency. */ | ||
304 | 321 | ||
305 | case RTC_VLOW_SET: | 322 | int ret = rtc_read(RTC_SECONDS); |
306 | { | ||
307 | /* Clear the VL bit in the seconds register */ | ||
308 | int ret = rtc_read(RTC_SECONDS); | ||
309 | 323 | ||
310 | rtc_write(RTC_SECONDS, (ret & 0x7F)); | 324 | rtc_write(RTC_SECONDS, (ret & 0x7F)); |
311 | 325 | ||
312 | return 0; | 326 | /* Clear the cached value. */ |
313 | } | 327 | voltage_low = 0; |
314 | 328 | ||
315 | default: | 329 | return 0; |
316 | return -ENOTTY; | 330 | } |
331 | default: | ||
332 | return -ENOTTY; | ||
317 | } | 333 | } |
318 | 334 | ||
319 | return 0; | 335 | return 0; |
320 | } | 336 | } |
321 | 337 | ||
322 | int | 338 | static int __init pcf8563_register(void) |
323 | pcf8563_open(struct inode *inode, struct file *filp) | ||
324 | { | 339 | { |
325 | return 0; | 340 | if (pcf8563_init() < 0) { |
326 | } | 341 | printk(KERN_INFO "%s: Unable to initialize Real-Time Clock " |
342 | "Driver, %s\n", PCF8563_NAME, DRIVER_VERSION); | ||
343 | return -1; | ||
344 | } | ||
345 | |||
346 | if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) { | ||
347 | printk(KERN_INFO "%s: Unable to get major numer %d for RTC " | ||
348 | "device.\n", PCF8563_NAME, PCF8563_MAJOR); | ||
349 | return -1; | ||
350 | } | ||
351 | |||
352 | printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME, | ||
353 | DRIVER_VERSION); | ||
354 | |||
355 | /* Check for low voltage, and warn about it. */ | ||
356 | if (voltage_low) { | ||
357 | printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time " | ||
358 | "information is no longer guaranteed!\n", PCF8563_NAME); | ||
359 | } | ||
327 | 360 | ||
328 | int | ||
329 | pcf8563_release(struct inode *inode, struct file *filp) | ||
330 | { | ||
331 | return 0; | 361 | return 0; |
332 | } | 362 | } |
333 | 363 | ||
334 | module_init(pcf8563_init); | 364 | module_init(pcf8563_register); |
335 | module_exit(pcf8563_exit); | 365 | module_exit(pcf8563_exit); |
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c index d581b0a92a3f..47c377df6fb3 100644 --- a/arch/cris/arch-v32/drivers/sync_serial.c +++ b/arch/cris/arch-v32/drivers/sync_serial.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Simple synchronous serial port driver for ETRAX FS. | 2 | * Simple synchronous serial port driver for ETRAX FS and Artpec-3. |
3 | * | 3 | * |
4 | * Copyright (c) 2005 Axis Communications AB | 4 | * Copyright (c) 2005 Axis Communications AB |
5 | * | 5 | * |
@@ -21,17 +21,18 @@ | |||
21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
22 | 22 | ||
23 | #include <asm/io.h> | 23 | #include <asm/io.h> |
24 | #include <asm/arch/dma.h> | 24 | #include <dma.h> |
25 | #include <asm/arch/pinmux.h> | 25 | #include <pinmux.h> |
26 | #include <asm/arch/hwregs/reg_rdwr.h> | 26 | #include <hwregs/reg_rdwr.h> |
27 | #include <asm/arch/hwregs/sser_defs.h> | 27 | #include <hwregs/sser_defs.h> |
28 | #include <asm/arch/hwregs/dma_defs.h> | 28 | #include <hwregs/dma_defs.h> |
29 | #include <asm/arch/hwregs/dma.h> | 29 | #include <hwregs/dma.h> |
30 | #include <asm/arch/hwregs/intr_vect_defs.h> | 30 | #include <hwregs/intr_vect_defs.h> |
31 | #include <asm/arch/hwregs/intr_vect.h> | 31 | #include <hwregs/intr_vect.h> |
32 | #include <asm/arch/hwregs/reg_map.h> | 32 | #include <hwregs/reg_map.h> |
33 | #include <asm/sync_serial.h> | 33 | #include <asm/sync_serial.h> |
34 | 34 | ||
35 | |||
35 | /* The receiver is a bit tricky beacuse of the continuous stream of data.*/ | 36 | /* The receiver is a bit tricky beacuse of the continuous stream of data.*/ |
36 | /* */ | 37 | /* */ |
37 | /* Three DMA descriptors are linked together. Each DMA descriptor is */ | 38 | /* Three DMA descriptors are linked together. Each DMA descriptor is */ |
@@ -63,8 +64,10 @@ | |||
63 | /* words can be handled */ | 64 | /* words can be handled */ |
64 | #define IN_BUFFER_SIZE 12288 | 65 | #define IN_BUFFER_SIZE 12288 |
65 | #define IN_DESCR_SIZE 256 | 66 | #define IN_DESCR_SIZE 256 |
66 | #define NUM_IN_DESCR (IN_BUFFER_SIZE/IN_DESCR_SIZE) | 67 | #define NBR_IN_DESCR (IN_BUFFER_SIZE/IN_DESCR_SIZE) |
67 | #define OUT_BUFFER_SIZE 4096 | 68 | |
69 | #define OUT_BUFFER_SIZE 1024*8 | ||
70 | #define NBR_OUT_DESCR 8 | ||
68 | 71 | ||
69 | #define DEFAULT_FRAME_RATE 0 | 72 | #define DEFAULT_FRAME_RATE 0 |
70 | #define DEFAULT_WORD_RATE 7 | 73 | #define DEFAULT_WORD_RATE 7 |
@@ -78,6 +81,8 @@ | |||
78 | #define DEBUGPOLL(x) | 81 | #define DEBUGPOLL(x) |
79 | #define DEBUGRXINT(x) | 82 | #define DEBUGRXINT(x) |
80 | #define DEBUGTXINT(x) | 83 | #define DEBUGTXINT(x) |
84 | #define DEBUGTRDMA(x) | ||
85 | #define DEBUGOUTBUF(x) | ||
81 | 86 | ||
82 | typedef struct sync_port | 87 | typedef struct sync_port |
83 | { | 88 | { |
@@ -97,10 +102,11 @@ typedef struct sync_port | |||
97 | int output; | 102 | int output; |
98 | int input; | 103 | int input; |
99 | 104 | ||
100 | volatile unsigned int out_count; /* Remaining bytes for current transfer */ | 105 | /* Next byte to be read by application */ |
101 | unsigned char* outp; /* Current position in out_buffer */ | 106 | volatile unsigned char *volatile readp; |
102 | volatile unsigned char* volatile readp; /* Next byte to be read by application */ | 107 | /* Next byte to be written by etrax */ |
103 | volatile unsigned char* volatile writep; /* Next byte to be written by etrax */ | 108 | volatile unsigned char *volatile writep; |
109 | |||
104 | unsigned int in_buffer_size; | 110 | unsigned int in_buffer_size; |
105 | unsigned int inbufchunk; | 111 | unsigned int inbufchunk; |
106 | unsigned char out_buffer[OUT_BUFFER_SIZE] __attribute__ ((aligned(32))); | 112 | unsigned char out_buffer[OUT_BUFFER_SIZE] __attribute__ ((aligned(32))); |
@@ -108,11 +114,30 @@ typedef struct sync_port | |||
108 | unsigned char flip[IN_BUFFER_SIZE] __attribute__ ((aligned(32))); | 114 | unsigned char flip[IN_BUFFER_SIZE] __attribute__ ((aligned(32))); |
109 | struct dma_descr_data* next_rx_desc; | 115 | struct dma_descr_data* next_rx_desc; |
110 | struct dma_descr_data* prev_rx_desc; | 116 | struct dma_descr_data* prev_rx_desc; |
117 | |||
118 | /* Pointer to the first available descriptor in the ring, | ||
119 | * unless active_tr_descr == catch_tr_descr and a dma | ||
120 | * transfer is active */ | ||
121 | struct dma_descr_data *active_tr_descr; | ||
122 | |||
123 | /* Pointer to the first allocated descriptor in the ring */ | ||
124 | struct dma_descr_data *catch_tr_descr; | ||
125 | |||
126 | /* Pointer to the descriptor with the current end-of-list */ | ||
127 | struct dma_descr_data *prev_tr_descr; | ||
111 | int full; | 128 | int full; |
112 | 129 | ||
113 | dma_descr_data in_descr[NUM_IN_DESCR] __attribute__ ((__aligned__(16))); | 130 | /* Pointer to the first byte being read by DMA |
131 | * or current position in out_buffer if not using DMA. */ | ||
132 | unsigned char *out_rd_ptr; | ||
133 | |||
134 | /* Number of bytes currently locked for being read by DMA */ | ||
135 | int out_buf_count; | ||
136 | |||
137 | dma_descr_data in_descr[NBR_IN_DESCR] __attribute__ ((__aligned__(16))); | ||
114 | dma_descr_context in_context __attribute__ ((__aligned__(32))); | 138 | dma_descr_context in_context __attribute__ ((__aligned__(32))); |
115 | dma_descr_data out_descr __attribute__ ((__aligned__(16))); | 139 | dma_descr_data out_descr[NBR_OUT_DESCR] |
140 | __attribute__ ((__aligned__(16))); | ||
116 | dma_descr_context out_context __attribute__ ((__aligned__(32))); | 141 | dma_descr_context out_context __attribute__ ((__aligned__(32))); |
117 | wait_queue_head_t out_wait_q; | 142 | wait_queue_head_t out_wait_q; |
118 | wait_queue_head_t in_wait_q; | 143 | wait_queue_head_t in_wait_q; |
@@ -143,11 +168,11 @@ static ssize_t sync_serial_read(struct file *file, char *buf, | |||
143 | #endif | 168 | #endif |
144 | 169 | ||
145 | static void send_word(sync_port* port); | 170 | static void send_word(sync_port* port); |
146 | static void start_dma(struct sync_port *port, const char* data, int count); | 171 | static void start_dma_out(struct sync_port *port, const char *data, int count); |
147 | static void start_dma_in(sync_port* port); | 172 | static void start_dma_in(sync_port* port); |
148 | #ifdef SYNC_SER_DMA | 173 | #ifdef SYNC_SER_DMA |
149 | static irqreturn_t tr_interrupt(int irq, void *dev_id, struct pt_regs * regs); | 174 | static irqreturn_t tr_interrupt(int irq, void *dev_id); |
150 | static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs); | 175 | static irqreturn_t rx_interrupt(int irq, void *dev_id); |
151 | #endif | 176 | #endif |
152 | 177 | ||
153 | #if (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \ | 178 | #if (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \ |
@@ -157,22 +182,49 @@ static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs); | |||
157 | #define SYNC_SER_MANUAL | 182 | #define SYNC_SER_MANUAL |
158 | #endif | 183 | #endif |
159 | #ifdef SYNC_SER_MANUAL | 184 | #ifdef SYNC_SER_MANUAL |
160 | static irqreturn_t manual_interrupt(int irq, void *dev_id, struct pt_regs * regs); | 185 | static irqreturn_t manual_interrupt(int irq, void *dev_id); |
186 | #endif | ||
187 | |||
188 | #ifdef CONFIG_ETRAXFS /* ETRAX FS */ | ||
189 | #define OUT_DMA_NBR 4 | ||
190 | #define IN_DMA_NBR 5 | ||
191 | #define PINMUX_SSER pinmux_sser0 | ||
192 | #define SYNCSER_INST regi_sser0 | ||
193 | #define SYNCSER_INTR_VECT SSER0_INTR_VECT | ||
194 | #define OUT_DMA_INST regi_dma4 | ||
195 | #define IN_DMA_INST regi_dma5 | ||
196 | #define DMA_OUT_INTR_VECT DMA4_INTR_VECT | ||
197 | #define DMA_IN_INTR_VECT DMA5_INTR_VECT | ||
198 | #define REQ_DMA_SYNCSER dma_sser0 | ||
199 | #else /* Artpec-3 */ | ||
200 | #define OUT_DMA_NBR 6 | ||
201 | #define IN_DMA_NBR 7 | ||
202 | #define PINMUX_SSER pinmux_sser | ||
203 | #define SYNCSER_INST regi_sser | ||
204 | #define SYNCSER_INTR_VECT SSER_INTR_VECT | ||
205 | #define OUT_DMA_INST regi_dma6 | ||
206 | #define IN_DMA_INST regi_dma7 | ||
207 | #define DMA_OUT_INTR_VECT DMA6_INTR_VECT | ||
208 | #define DMA_IN_INTR_VECT DMA7_INTR_VECT | ||
209 | #define REQ_DMA_SYNCSER dma_sser | ||
161 | #endif | 210 | #endif |
162 | 211 | ||
163 | /* The ports */ | 212 | /* The ports */ |
164 | static struct sync_port ports[]= | 213 | static struct sync_port ports[]= |
165 | { | 214 | { |
166 | { | 215 | { |
167 | .regi_sser = regi_sser0, | 216 | .regi_sser = SYNCSER_INST, |
168 | .regi_dmaout = regi_dma4, | 217 | .regi_dmaout = OUT_DMA_INST, |
169 | .regi_dmain = regi_dma5, | 218 | .regi_dmain = IN_DMA_INST, |
170 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA) | 219 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA) |
171 | .use_dma = 1, | 220 | .use_dma = 1, |
172 | #else | 221 | #else |
173 | .use_dma = 0, | 222 | .use_dma = 0, |
174 | #endif | 223 | #endif |
175 | }, | 224 | } |
225 | #ifdef CONFIG_ETRAXFS | ||
226 | , | ||
227 | |||
176 | { | 228 | { |
177 | .regi_sser = regi_sser1, | 229 | .regi_sser = regi_sser1, |
178 | .regi_dmaout = regi_dma6, | 230 | .regi_dmaout = regi_dma6, |
@@ -183,9 +235,10 @@ static struct sync_port ports[]= | |||
183 | .use_dma = 0, | 235 | .use_dma = 0, |
184 | #endif | 236 | #endif |
185 | } | 237 | } |
238 | #endif | ||
186 | }; | 239 | }; |
187 | 240 | ||
188 | #define NUMBER_OF_PORTS ARRAY_SIZE(ports) | 241 | #define NBR_PORTS ARRAY_SIZE(ports) |
189 | 242 | ||
190 | static const struct file_operations sync_serial_fops = { | 243 | static const struct file_operations sync_serial_fops = { |
191 | .owner = THIS_MODULE, | 244 | .owner = THIS_MODULE, |
@@ -200,19 +253,21 @@ static const struct file_operations sync_serial_fops = { | |||
200 | static int __init etrax_sync_serial_init(void) | 253 | static int __init etrax_sync_serial_init(void) |
201 | { | 254 | { |
202 | ports[0].enabled = 0; | 255 | ports[0].enabled = 0; |
256 | #ifdef CONFIG_ETRAXFS | ||
203 | ports[1].enabled = 0; | 257 | ports[1].enabled = 0; |
204 | 258 | #endif | |
205 | if (register_chrdev(SYNC_SERIAL_MAJOR,"sync serial", &sync_serial_fops) <0 ) | 259 | if (register_chrdev(SYNC_SERIAL_MAJOR, "sync serial", |
206 | { | 260 | &sync_serial_fops) < 0) { |
207 | printk("unable to get major for synchronous serial port\n"); | 261 | printk(KERN_WARNING |
262 | "Unable to get major for synchronous serial port\n"); | ||
208 | return -EBUSY; | 263 | return -EBUSY; |
209 | } | 264 | } |
210 | 265 | ||
211 | /* Initialize Ports */ | 266 | /* Initialize Ports */ |
212 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) | 267 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) |
213 | if (crisv32_pinmux_alloc_fixed(pinmux_sser0)) | 268 | if (crisv32_pinmux_alloc_fixed(PINMUX_SSER)) { |
214 | { | 269 | printk(KERN_WARNING |
215 | printk("Unable to allocate pins for syncrhronous serial port 0\n"); | 270 | "Unable to alloc pins for synchronous serial port 0\n"); |
216 | return -EIO; | 271 | return -EIO; |
217 | } | 272 | } |
218 | ports[0].enabled = 1; | 273 | ports[0].enabled = 1; |
@@ -220,33 +275,40 @@ static int __init etrax_sync_serial_init(void) | |||
220 | #endif | 275 | #endif |
221 | 276 | ||
222 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) | 277 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) |
223 | if (crisv32_pinmux_alloc_fixed(pinmux_sser1)) | 278 | if (crisv32_pinmux_alloc_fixed(pinmux_sser1)) { |
224 | { | 279 | printk(KERN_WARNING |
225 | printk("Unable to allocate pins for syncrhronous serial port 0\n"); | 280 | "Unable to alloc pins for synchronous serial port 0\n"); |
226 | return -EIO; | 281 | return -EIO; |
227 | } | 282 | } |
228 | ports[1].enabled = 1; | 283 | ports[1].enabled = 1; |
229 | initialize_port(1); | 284 | initialize_port(1); |
230 | #endif | 285 | #endif |
231 | 286 | ||
232 | printk("ETRAX FS synchronous serial port driver\n"); | 287 | #ifdef CONFIG_ETRAXFS |
288 | printk(KERN_INFO "ETRAX FS synchronous serial port driver\n"); | ||
289 | #else | ||
290 | printk(KERN_INFO "Artpec-3 synchronous serial port driver\n"); | ||
291 | #endif | ||
233 | return 0; | 292 | return 0; |
234 | } | 293 | } |
235 | 294 | ||
236 | static void __init initialize_port(int portnbr) | 295 | static void __init initialize_port(int portnbr) |
237 | { | 296 | { |
238 | struct sync_port* port = &ports[portnbr]; | 297 | int __attribute__((unused)) i; |
298 | struct sync_port *port = &ports[portnbr]; | ||
239 | reg_sser_rw_cfg cfg = {0}; | 299 | reg_sser_rw_cfg cfg = {0}; |
240 | reg_sser_rw_frm_cfg frm_cfg = {0}; | 300 | reg_sser_rw_frm_cfg frm_cfg = {0}; |
241 | reg_sser_rw_tr_cfg tr_cfg = {0}; | 301 | reg_sser_rw_tr_cfg tr_cfg = {0}; |
242 | reg_sser_rw_rec_cfg rec_cfg = {0}; | 302 | reg_sser_rw_rec_cfg rec_cfg = {0}; |
243 | 303 | ||
244 | DEBUG(printk("Init sync serial port %d\n", portnbr)); | 304 | DEBUG(printk(KERN_DEBUG "Init sync serial port %d\n", portnbr)); |
245 | 305 | ||
246 | port->port_nbr = portnbr; | 306 | port->port_nbr = portnbr; |
247 | port->init_irqs = 1; | 307 | port->init_irqs = 1; |
248 | 308 | ||
249 | port->outp = port->out_buffer; | 309 | port->out_rd_ptr = port->out_buffer; |
310 | port->out_buf_count = 0; | ||
311 | |||
250 | port->output = 1; | 312 | port->output = 1; |
251 | port->input = 0; | 313 | port->input = 0; |
252 | 314 | ||
@@ -255,7 +317,7 @@ static void __init initialize_port(int portnbr) | |||
255 | port->in_buffer_size = IN_BUFFER_SIZE; | 317 | port->in_buffer_size = IN_BUFFER_SIZE; |
256 | port->inbufchunk = IN_DESCR_SIZE; | 318 | port->inbufchunk = IN_DESCR_SIZE; |
257 | port->next_rx_desc = &port->in_descr[0]; | 319 | port->next_rx_desc = &port->in_descr[0]; |
258 | port->prev_rx_desc = &port->in_descr[NUM_IN_DESCR-1]; | 320 | port->prev_rx_desc = &port->in_descr[NBR_IN_DESCR-1]; |
259 | port->prev_rx_desc->eol = 1; | 321 | port->prev_rx_desc->eol = 1; |
260 | 322 | ||
261 | init_waitqueue_head(&port->out_wait_q); | 323 | init_waitqueue_head(&port->out_wait_q); |
@@ -286,8 +348,13 @@ static void __init initialize_port(int portnbr) | |||
286 | tr_cfg.sample_size = 7; | 348 | tr_cfg.sample_size = 7; |
287 | tr_cfg.sh_dir = regk_sser_msbfirst; | 349 | tr_cfg.sh_dir = regk_sser_msbfirst; |
288 | tr_cfg.use_dma = port->use_dma ? regk_sser_yes : regk_sser_no; | 350 | tr_cfg.use_dma = port->use_dma ? regk_sser_yes : regk_sser_no; |
351 | #if 0 | ||
289 | tr_cfg.rate_ctrl = regk_sser_bulk; | 352 | tr_cfg.rate_ctrl = regk_sser_bulk; |
290 | tr_cfg.data_pin_use = regk_sser_dout; | 353 | tr_cfg.data_pin_use = regk_sser_dout; |
354 | #else | ||
355 | tr_cfg.rate_ctrl = regk_sser_iso; | ||
356 | tr_cfg.data_pin_use = regk_sser_dout; | ||
357 | #endif | ||
291 | tr_cfg.bulk_wspace = 1; | 358 | tr_cfg.bulk_wspace = 1; |
292 | REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg); | 359 | REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg); |
293 | 360 | ||
@@ -296,6 +363,27 @@ static void __init initialize_port(int portnbr) | |||
296 | rec_cfg.use_dma = port->use_dma ? regk_sser_yes : regk_sser_no; | 363 | rec_cfg.use_dma = port->use_dma ? regk_sser_yes : regk_sser_no; |
297 | rec_cfg.fifo_thr = regk_sser_inf; | 364 | rec_cfg.fifo_thr = regk_sser_inf; |
298 | REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg); | 365 | REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg); |
366 | |||
367 | #ifdef SYNC_SER_DMA | ||
368 | /* Setup the descriptor ring for dma out/transmit. */ | ||
369 | for (i = 0; i < NBR_OUT_DESCR; i++) { | ||
370 | port->out_descr[i].wait = 0; | ||
371 | port->out_descr[i].intr = 1; | ||
372 | port->out_descr[i].eol = 0; | ||
373 | port->out_descr[i].out_eop = 0; | ||
374 | port->out_descr[i].next = | ||
375 | (dma_descr_data *)virt_to_phys(&port->out_descr[i+1]); | ||
376 | } | ||
377 | |||
378 | /* Create a ring from the list. */ | ||
379 | port->out_descr[NBR_OUT_DESCR-1].next = | ||
380 | (dma_descr_data *)virt_to_phys(&port->out_descr[0]); | ||
381 | |||
382 | /* Setup context for traversing the ring. */ | ||
383 | port->active_tr_descr = &port->out_descr[0]; | ||
384 | port->prev_tr_descr = &port->out_descr[NBR_OUT_DESCR-1]; | ||
385 | port->catch_tr_descr = &port->out_descr[0]; | ||
386 | #endif | ||
299 | } | 387 | } |
300 | 388 | ||
301 | static inline int sync_data_avail(struct sync_port *port) | 389 | static inline int sync_data_avail(struct sync_port *port) |
@@ -311,7 +399,7 @@ static inline int sync_data_avail(struct sync_port *port) | |||
311 | * ^rp ^wp ^wp ^rp | 399 | * ^rp ^wp ^wp ^rp |
312 | */ | 400 | */ |
313 | 401 | ||
314 | if (end >= start) | 402 | if (end >= start) |
315 | avail = end - start; | 403 | avail = end - start; |
316 | else | 404 | else |
317 | avail = port->in_buffer_size - (start - end); | 405 | avail = port->in_buffer_size - (start - end); |
@@ -331,7 +419,7 @@ static inline int sync_data_avail_to_end(struct sync_port *port) | |||
331 | * ^rp ^wp ^wp ^rp | 419 | * ^rp ^wp ^wp ^rp |
332 | */ | 420 | */ |
333 | 421 | ||
334 | if (end >= start) | 422 | if (end >= start) |
335 | avail = end - start; | 423 | avail = end - start; |
336 | else | 424 | else |
337 | avail = port->flip + port->in_buffer_size - start; | 425 | avail = port->flip + port->in_buffer_size - start; |
@@ -341,66 +429,69 @@ static inline int sync_data_avail_to_end(struct sync_port *port) | |||
341 | static int sync_serial_open(struct inode *inode, struct file *file) | 429 | static int sync_serial_open(struct inode *inode, struct file *file) |
342 | { | 430 | { |
343 | int dev = iminor(inode); | 431 | int dev = iminor(inode); |
344 | sync_port* port; | 432 | sync_port *port; |
345 | reg_dma_rw_cfg cfg = {.en = regk_dma_yes}; | 433 | reg_dma_rw_cfg cfg = {.en = regk_dma_yes}; |
346 | reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes}; | 434 | reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes}; |
347 | 435 | ||
348 | DEBUG(printk("Open sync serial port %d\n", dev)); | 436 | DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev)); |
349 | 437 | ||
350 | if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) | 438 | if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) |
351 | { | 439 | { |
352 | DEBUG(printk("Invalid minor %d\n", dev)); | 440 | DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); |
353 | return -ENODEV; | 441 | return -ENODEV; |
354 | } | 442 | } |
355 | port = &ports[dev]; | 443 | port = &ports[dev]; |
356 | /* Allow open this device twice (assuming one reader and one writer) */ | 444 | /* Allow open this device twice (assuming one reader and one writer) */ |
357 | if (port->busy == 2) | 445 | if (port->busy == 2) |
358 | { | 446 | { |
359 | DEBUG(printk("Device is busy.. \n")); | 447 | DEBUG(printk(KERN_DEBUG "Device is busy.. \n")); |
360 | return -EBUSY; | 448 | return -EBUSY; |
361 | } | 449 | } |
450 | |||
451 | |||
362 | if (port->init_irqs) { | 452 | if (port->init_irqs) { |
363 | if (port->use_dma) { | 453 | if (port->use_dma) { |
364 | if (port == &ports[0]){ | 454 | if (port == &ports[0]) { |
365 | #ifdef SYNC_SER_DMA | 455 | #ifdef SYNC_SER_DMA |
366 | if(request_irq(DMA4_INTR_VECT, | 456 | if (request_irq(DMA_OUT_INTR_VECT, |
367 | tr_interrupt, | 457 | tr_interrupt, |
368 | 0, | 458 | 0, |
369 | "synchronous serial 0 dma tr", | 459 | "synchronous serial 0 dma tr", |
370 | &ports[0])) { | 460 | &ports[0])) { |
371 | printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ"); | 461 | printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ"); |
372 | return -EBUSY; | 462 | return -EBUSY; |
373 | } else if(request_irq(DMA5_INTR_VECT, | 463 | } else if (request_irq(DMA_IN_INTR_VECT, |
374 | rx_interrupt, | 464 | rx_interrupt, |
375 | 0, | 465 | 0, |
376 | "synchronous serial 1 dma rx", | 466 | "synchronous serial 1 dma rx", |
377 | &ports[0])) { | 467 | &ports[0])) { |
378 | free_irq(DMA4_INTR_VECT, &port[0]); | 468 | free_irq(DMA_OUT_INTR_VECT, &port[0]); |
379 | printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ"); | 469 | printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ"); |
380 | return -EBUSY; | 470 | return -EBUSY; |
381 | } else if (crisv32_request_dma(SYNC_SER0_TX_DMA_NBR, | 471 | } else if (crisv32_request_dma(OUT_DMA_NBR, |
382 | "synchronous serial 0 dma tr", | 472 | "synchronous serial 0 dma tr", |
383 | DMA_VERBOSE_ON_ERROR, | 473 | DMA_VERBOSE_ON_ERROR, |
384 | 0, | 474 | 0, |
385 | dma_sser0)) { | 475 | REQ_DMA_SYNCSER)) { |
386 | free_irq(DMA4_INTR_VECT, &port[0]); | 476 | free_irq(DMA_OUT_INTR_VECT, &port[0]); |
387 | free_irq(DMA5_INTR_VECT, &port[0]); | 477 | free_irq(DMA_IN_INTR_VECT, &port[0]); |
388 | printk(KERN_CRIT "Can't allocate sync serial port 0 TX DMA channel"); | 478 | printk(KERN_CRIT "Can't allocate sync serial port 0 TX DMA channel"); |
389 | return -EBUSY; | 479 | return -EBUSY; |
390 | } else if (crisv32_request_dma(SYNC_SER0_RX_DMA_NBR, | 480 | } else if (crisv32_request_dma(IN_DMA_NBR, |
391 | "synchronous serial 0 dma rec", | 481 | "synchronous serial 0 dma rec", |
392 | DMA_VERBOSE_ON_ERROR, | 482 | DMA_VERBOSE_ON_ERROR, |
393 | 0, | 483 | 0, |
394 | dma_sser0)) { | 484 | REQ_DMA_SYNCSER)) { |
395 | crisv32_free_dma(SYNC_SER0_TX_DMA_NBR); | 485 | crisv32_free_dma(OUT_DMA_NBR); |
396 | free_irq(DMA4_INTR_VECT, &port[0]); | 486 | free_irq(DMA_OUT_INTR_VECT, &port[0]); |
397 | free_irq(DMA5_INTR_VECT, &port[0]); | 487 | free_irq(DMA_IN_INTR_VECT, &port[0]); |
398 | printk(KERN_CRIT "Can't allocate sync serial port 1 RX DMA channel"); | 488 | printk(KERN_CRIT "Can't allocate sync serial port 1 RX DMA channel"); |
399 | return -EBUSY; | 489 | return -EBUSY; |
400 | } | 490 | } |
401 | #endif | 491 | #endif |
402 | } | 492 | } |
403 | else if (port == &ports[1]){ | 493 | #ifdef CONFIG_ETRAXFS |
494 | else if (port == &ports[1]) { | ||
404 | #ifdef SYNC_SER_DMA | 495 | #ifdef SYNC_SER_DMA |
405 | if (request_irq(DMA6_INTR_VECT, | 496 | if (request_irq(DMA6_INTR_VECT, |
406 | tr_interrupt, | 497 | tr_interrupt, |
@@ -417,20 +508,22 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
417 | free_irq(DMA6_INTR_VECT, &ports[1]); | 508 | free_irq(DMA6_INTR_VECT, &ports[1]); |
418 | printk(KERN_CRIT "Can't allocate sync serial port 3 IRQ"); | 509 | printk(KERN_CRIT "Can't allocate sync serial port 3 IRQ"); |
419 | return -EBUSY; | 510 | return -EBUSY; |
420 | } else if (crisv32_request_dma(SYNC_SER1_TX_DMA_NBR, | 511 | } else if (crisv32_request_dma( |
421 | "synchronous serial 1 dma tr", | 512 | SYNC_SER1_TX_DMA_NBR, |
422 | DMA_VERBOSE_ON_ERROR, | 513 | "synchronous serial 1 dma tr", |
423 | 0, | 514 | DMA_VERBOSE_ON_ERROR, |
424 | dma_sser1)) { | 515 | 0, |
425 | free_irq(21, &ports[1]); | 516 | dma_sser1)) { |
426 | free_irq(20, &ports[1]); | 517 | free_irq(DMA6_INTR_VECT, &ports[1]); |
518 | free_irq(DMA7_INTR_VECT, &ports[1]); | ||
427 | printk(KERN_CRIT "Can't allocate sync serial port 3 TX DMA channel"); | 519 | printk(KERN_CRIT "Can't allocate sync serial port 3 TX DMA channel"); |
428 | return -EBUSY; | 520 | return -EBUSY; |
429 | } else if (crisv32_request_dma(SYNC_SER1_RX_DMA_NBR, | 521 | } else if (crisv32_request_dma( |
430 | "synchronous serial 3 dma rec", | 522 | SYNC_SER1_RX_DMA_NBR, |
431 | DMA_VERBOSE_ON_ERROR, | 523 | "synchronous serial 3 dma rec", |
432 | 0, | 524 | DMA_VERBOSE_ON_ERROR, |
433 | dma_sser1)) { | 525 | 0, |
526 | dma_sser1)) { | ||
434 | crisv32_free_dma(SYNC_SER1_TX_DMA_NBR); | 527 | crisv32_free_dma(SYNC_SER1_TX_DMA_NBR); |
435 | free_irq(DMA6_INTR_VECT, &ports[1]); | 528 | free_irq(DMA6_INTR_VECT, &ports[1]); |
436 | free_irq(DMA7_INTR_VECT, &ports[1]); | 529 | free_irq(DMA7_INTR_VECT, &ports[1]); |
@@ -439,14 +532,14 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
439 | } | 532 | } |
440 | #endif | 533 | #endif |
441 | } | 534 | } |
442 | 535 | #endif | |
443 | /* Enable DMAs */ | 536 | /* Enable DMAs */ |
444 | REG_WR(dma, port->regi_dmain, rw_cfg, cfg); | 537 | REG_WR(dma, port->regi_dmain, rw_cfg, cfg); |
445 | REG_WR(dma, port->regi_dmaout, rw_cfg, cfg); | 538 | REG_WR(dma, port->regi_dmaout, rw_cfg, cfg); |
446 | /* Enable DMA IRQs */ | 539 | /* Enable DMA IRQs */ |
447 | REG_WR(dma, port->regi_dmain, rw_intr_mask, intr_mask); | 540 | REG_WR(dma, port->regi_dmain, rw_intr_mask, intr_mask); |
448 | REG_WR(dma, port->regi_dmaout, rw_intr_mask, intr_mask); | 541 | REG_WR(dma, port->regi_dmaout, rw_intr_mask, intr_mask); |
449 | /* Set up wordsize = 2 for DMAs. */ | 542 | /* Set up wordsize = 1 for DMAs. */ |
450 | DMA_WR_CMD (port->regi_dmain, regk_dma_set_w_size1); | 543 | DMA_WR_CMD (port->regi_dmain, regk_dma_set_w_size1); |
451 | DMA_WR_CMD (port->regi_dmaout, regk_dma_set_w_size1); | 544 | DMA_WR_CMD (port->regi_dmaout, regk_dma_set_w_size1); |
452 | 545 | ||
@@ -455,7 +548,7 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
455 | } else { /* !port->use_dma */ | 548 | } else { /* !port->use_dma */ |
456 | #ifdef SYNC_SER_MANUAL | 549 | #ifdef SYNC_SER_MANUAL |
457 | if (port == &ports[0]) { | 550 | if (port == &ports[0]) { |
458 | if (request_irq(SSER0_INTR_VECT, | 551 | if (request_irq(SYNCSER_INTR_VECT, |
459 | manual_interrupt, | 552 | manual_interrupt, |
460 | 0, | 553 | 0, |
461 | "synchronous serial manual irq", | 554 | "synchronous serial manual irq", |
@@ -463,7 +556,9 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
463 | printk("Can't allocate sync serial manual irq"); | 556 | printk("Can't allocate sync serial manual irq"); |
464 | return -EBUSY; | 557 | return -EBUSY; |
465 | } | 558 | } |
466 | } else if (port == &ports[1]) { | 559 | } |
560 | #ifdef CONFIG_ETRAXFS | ||
561 | else if (port == &ports[1]) { | ||
467 | if (request_irq(SSER1_INTR_VECT, | 562 | if (request_irq(SSER1_INTR_VECT, |
468 | manual_interrupt, | 563 | manual_interrupt, |
469 | 0, | 564 | 0, |
@@ -473,11 +568,13 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
473 | return -EBUSY; | 568 | return -EBUSY; |
474 | } | 569 | } |
475 | } | 570 | } |
571 | #endif | ||
476 | port->init_irqs = 0; | 572 | port->init_irqs = 0; |
477 | #else | 573 | #else |
478 | panic("sync_serial: Manual mode not supported.\n"); | 574 | panic("sync_serial: Manual mode not supported.\n"); |
479 | #endif /* SYNC_SER_MANUAL */ | 575 | #endif /* SYNC_SER_MANUAL */ |
480 | } | 576 | } |
577 | |||
481 | } /* port->init_irqs */ | 578 | } /* port->init_irqs */ |
482 | 579 | ||
483 | port->busy++; | 580 | port->busy++; |
@@ -487,9 +584,9 @@ static int sync_serial_open(struct inode *inode, struct file *file) | |||
487 | static int sync_serial_release(struct inode *inode, struct file *file) | 584 | static int sync_serial_release(struct inode *inode, struct file *file) |
488 | { | 585 | { |
489 | int dev = iminor(inode); | 586 | int dev = iminor(inode); |
490 | sync_port* port; | 587 | sync_port *port; |
491 | 588 | ||
492 | if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) | 589 | if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) |
493 | { | 590 | { |
494 | DEBUG(printk("Invalid minor %d\n", dev)); | 591 | DEBUG(printk("Invalid minor %d\n", dev)); |
495 | return -ENODEV; | 592 | return -ENODEV; |
@@ -506,17 +603,37 @@ static unsigned int sync_serial_poll(struct file *file, poll_table *wait) | |||
506 | { | 603 | { |
507 | int dev = iminor(file->f_path.dentry->d_inode); | 604 | int dev = iminor(file->f_path.dentry->d_inode); |
508 | unsigned int mask = 0; | 605 | unsigned int mask = 0; |
509 | sync_port* port; | 606 | sync_port *port; |
510 | DEBUGPOLL( static unsigned int prev_mask = 0; ); | 607 | DEBUGPOLL( static unsigned int prev_mask = 0; ); |
511 | 608 | ||
512 | port = &ports[dev]; | 609 | port = &ports[dev]; |
610 | |||
611 | if (!port->started) { | ||
612 | reg_sser_rw_cfg cfg = REG_RD(sser, port->regi_sser, rw_cfg); | ||
613 | reg_sser_rw_rec_cfg rec_cfg = | ||
614 | REG_RD(sser, port->regi_sser, rw_rec_cfg); | ||
615 | cfg.en = regk_sser_yes; | ||
616 | rec_cfg.rec_en = port->input; | ||
617 | REG_WR(sser, port->regi_sser, rw_cfg, cfg); | ||
618 | REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg); | ||
619 | port->started = 1; | ||
620 | } | ||
621 | |||
513 | poll_wait(file, &port->out_wait_q, wait); | 622 | poll_wait(file, &port->out_wait_q, wait); |
514 | poll_wait(file, &port->in_wait_q, wait); | 623 | poll_wait(file, &port->in_wait_q, wait); |
515 | /* Some room to write */ | 624 | |
516 | if (port->out_count < OUT_BUFFER_SIZE) | 625 | /* No active transfer, descriptors are available */ |
626 | if (port->output && !port->tr_running) | ||
627 | mask |= POLLOUT | POLLWRNORM; | ||
628 | |||
629 | /* Descriptor and buffer space available. */ | ||
630 | if (port->output && | ||
631 | port->active_tr_descr != port->catch_tr_descr && | ||
632 | port->out_buf_count < OUT_BUFFER_SIZE) | ||
517 | mask |= POLLOUT | POLLWRNORM; | 633 | mask |= POLLOUT | POLLWRNORM; |
634 | |||
518 | /* At least an inbufchunk of data */ | 635 | /* At least an inbufchunk of data */ |
519 | if (sync_data_avail(port) >= port->inbufchunk) | 636 | if (port->input && sync_data_avail(port) >= port->inbufchunk) |
520 | mask |= POLLIN | POLLRDNORM; | 637 | mask |= POLLIN | POLLRDNORM; |
521 | 638 | ||
522 | DEBUGPOLL(if (mask != prev_mask) | 639 | DEBUGPOLL(if (mask != prev_mask) |
@@ -531,15 +648,16 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, | |||
531 | unsigned int cmd, unsigned long arg) | 648 | unsigned int cmd, unsigned long arg) |
532 | { | 649 | { |
533 | int return_val = 0; | 650 | int return_val = 0; |
651 | int dma_w_size = regk_dma_set_w_size1; | ||
534 | int dev = iminor(file->f_path.dentry->d_inode); | 652 | int dev = iminor(file->f_path.dentry->d_inode); |
535 | sync_port* port; | 653 | sync_port *port; |
536 | reg_sser_rw_tr_cfg tr_cfg; | 654 | reg_sser_rw_tr_cfg tr_cfg; |
537 | reg_sser_rw_rec_cfg rec_cfg; | 655 | reg_sser_rw_rec_cfg rec_cfg; |
538 | reg_sser_rw_frm_cfg frm_cfg; | 656 | reg_sser_rw_frm_cfg frm_cfg; |
539 | reg_sser_rw_cfg gen_cfg; | 657 | reg_sser_rw_cfg gen_cfg; |
540 | reg_sser_rw_intr_mask intr_mask; | 658 | reg_sser_rw_intr_mask intr_mask; |
541 | 659 | ||
542 | if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) | 660 | if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) |
543 | { | 661 | { |
544 | DEBUG(printk("Invalid minor %d\n", dev)); | 662 | DEBUG(printk("Invalid minor %d\n", dev)); |
545 | return -1; | 663 | return -1; |
@@ -558,61 +676,81 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, | |||
558 | case SSP_SPEED: | 676 | case SSP_SPEED: |
559 | if (GET_SPEED(arg) == CODEC) | 677 | if (GET_SPEED(arg) == CODEC) |
560 | { | 678 | { |
679 | unsigned int freq; | ||
680 | |||
561 | gen_cfg.base_freq = regk_sser_f32; | 681 | gen_cfg.base_freq = regk_sser_f32; |
562 | /* FREQ = 0 => 4 MHz => clk_div = 7*/ | 682 | |
563 | gen_cfg.clk_div = 6 + (1 << GET_FREQ(arg)); | 683 | /* Clock divider will internally be |
564 | } | 684 | * gen_cfg.clk_div + 1. |
565 | else | 685 | */ |
566 | { | 686 | |
687 | freq = GET_FREQ(arg); | ||
688 | switch (freq) { | ||
689 | case FREQ_32kHz: | ||
690 | case FREQ_64kHz: | ||
691 | case FREQ_128kHz: | ||
692 | case FREQ_256kHz: | ||
693 | gen_cfg.clk_div = 125 * | ||
694 | (1 << (freq - FREQ_256kHz)) - 1; | ||
695 | break; | ||
696 | case FREQ_512kHz: | ||
697 | gen_cfg.clk_div = 62; | ||
698 | break; | ||
699 | case FREQ_1MHz: | ||
700 | case FREQ_2MHz: | ||
701 | case FREQ_4MHz: | ||
702 | gen_cfg.clk_div = 8 * (1 << freq) - 1; | ||
703 | break; | ||
704 | } | ||
705 | } else { | ||
567 | gen_cfg.base_freq = regk_sser_f29_493; | 706 | gen_cfg.base_freq = regk_sser_f29_493; |
568 | switch (GET_SPEED(arg)) | 707 | switch (GET_SPEED(arg)) { |
569 | { | 708 | case SSP150: |
570 | case SSP150: | 709 | gen_cfg.clk_div = 29493000 / (150 * 8) - 1; |
571 | gen_cfg.clk_div = 29493000 / (150 * 8) - 1; | 710 | break; |
572 | break; | 711 | case SSP300: |
573 | case SSP300: | 712 | gen_cfg.clk_div = 29493000 / (300 * 8) - 1; |
574 | gen_cfg.clk_div = 29493000 / (300 * 8) - 1; | 713 | break; |
575 | break; | 714 | case SSP600: |
576 | case SSP600: | 715 | gen_cfg.clk_div = 29493000 / (600 * 8) - 1; |
577 | gen_cfg.clk_div = 29493000 / (600 * 8) - 1; | 716 | break; |
578 | break; | 717 | case SSP1200: |
579 | case SSP1200: | 718 | gen_cfg.clk_div = 29493000 / (1200 * 8) - 1; |
580 | gen_cfg.clk_div = 29493000 / (1200 * 8) - 1; | 719 | break; |
581 | break; | 720 | case SSP2400: |
582 | case SSP2400: | 721 | gen_cfg.clk_div = 29493000 / (2400 * 8) - 1; |
583 | gen_cfg.clk_div = 29493000 / (2400 * 8) - 1; | 722 | break; |
584 | break; | 723 | case SSP4800: |
585 | case SSP4800: | 724 | gen_cfg.clk_div = 29493000 / (4800 * 8) - 1; |
586 | gen_cfg.clk_div = 29493000 / (4800 * 8) - 1; | 725 | break; |
587 | break; | 726 | case SSP9600: |
588 | case SSP9600: | 727 | gen_cfg.clk_div = 29493000 / (9600 * 8) - 1; |
589 | gen_cfg.clk_div = 29493000 / (9600 * 8) - 1; | 728 | break; |
590 | break; | 729 | case SSP19200: |
591 | case SSP19200: | 730 | gen_cfg.clk_div = 29493000 / (19200 * 8) - 1; |
592 | gen_cfg.clk_div = 29493000 / (19200 * 8) - 1; | 731 | break; |
593 | break; | 732 | case SSP28800: |
594 | case SSP28800: | 733 | gen_cfg.clk_div = 29493000 / (28800 * 8) - 1; |
595 | gen_cfg.clk_div = 29493000 / (28800 * 8) - 1; | 734 | break; |
596 | break; | 735 | case SSP57600: |
597 | case SSP57600: | 736 | gen_cfg.clk_div = 29493000 / (57600 * 8) - 1; |
598 | gen_cfg.clk_div = 29493000 / (57600 * 8) - 1; | 737 | break; |
599 | break; | 738 | case SSP115200: |
600 | case SSP115200: | 739 | gen_cfg.clk_div = 29493000 / (115200 * 8) - 1; |
601 | gen_cfg.clk_div = 29493000 / (115200 * 8) - 1; | 740 | break; |
602 | break; | 741 | case SSP230400: |
603 | case SSP230400: | 742 | gen_cfg.clk_div = 29493000 / (230400 * 8) - 1; |
604 | gen_cfg.clk_div = 29493000 / (230400 * 8) - 1; | 743 | break; |
605 | break; | 744 | case SSP460800: |
606 | case SSP460800: | 745 | gen_cfg.clk_div = 29493000 / (460800 * 8) - 1; |
607 | gen_cfg.clk_div = 29493000 / (460800 * 8) - 1; | 746 | break; |
608 | break; | 747 | case SSP921600: |
609 | case SSP921600: | 748 | gen_cfg.clk_div = 29493000 / (921600 * 8) - 1; |
610 | gen_cfg.clk_div = 29493000 / (921600 * 8) - 1; | 749 | break; |
611 | break; | 750 | case SSP3125000: |
612 | case SSP3125000: | 751 | gen_cfg.base_freq = regk_sser_f100; |
613 | gen_cfg.base_freq = regk_sser_f100; | 752 | gen_cfg.clk_div = 100000000 / (3125000 * 8) - 1; |
614 | gen_cfg.clk_div = 100000000 / (3125000 * 8) - 1; | 753 | break; |
615 | break; | ||
616 | 754 | ||
617 | } | 755 | } |
618 | } | 756 | } |
@@ -625,46 +763,60 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, | |||
625 | case MASTER_OUTPUT: | 763 | case MASTER_OUTPUT: |
626 | port->output = 1; | 764 | port->output = 1; |
627 | port->input = 0; | 765 | port->input = 0; |
766 | frm_cfg.out_on = regk_sser_tr; | ||
767 | frm_cfg.frame_pin_dir = regk_sser_out; | ||
628 | gen_cfg.clk_dir = regk_sser_out; | 768 | gen_cfg.clk_dir = regk_sser_out; |
629 | break; | 769 | break; |
630 | case SLAVE_OUTPUT: | 770 | case SLAVE_OUTPUT: |
631 | port->output = 1; | 771 | port->output = 1; |
632 | port->input = 0; | 772 | port->input = 0; |
773 | frm_cfg.frame_pin_dir = regk_sser_in; | ||
633 | gen_cfg.clk_dir = regk_sser_in; | 774 | gen_cfg.clk_dir = regk_sser_in; |
634 | break; | 775 | break; |
635 | case MASTER_INPUT: | 776 | case MASTER_INPUT: |
636 | port->output = 0; | 777 | port->output = 0; |
637 | port->input = 1; | 778 | port->input = 1; |
779 | frm_cfg.frame_pin_dir = regk_sser_out; | ||
780 | frm_cfg.out_on = regk_sser_intern_tb; | ||
638 | gen_cfg.clk_dir = regk_sser_out; | 781 | gen_cfg.clk_dir = regk_sser_out; |
639 | break; | 782 | break; |
640 | case SLAVE_INPUT: | 783 | case SLAVE_INPUT: |
641 | port->output = 0; | 784 | port->output = 0; |
642 | port->input = 1; | 785 | port->input = 1; |
786 | frm_cfg.frame_pin_dir = regk_sser_in; | ||
643 | gen_cfg.clk_dir = regk_sser_in; | 787 | gen_cfg.clk_dir = regk_sser_in; |
644 | break; | 788 | break; |
645 | case MASTER_BIDIR: | 789 | case MASTER_BIDIR: |
646 | port->output = 1; | 790 | port->output = 1; |
647 | port->input = 1; | 791 | port->input = 1; |
792 | frm_cfg.frame_pin_dir = regk_sser_out; | ||
793 | frm_cfg.out_on = regk_sser_intern_tb; | ||
648 | gen_cfg.clk_dir = regk_sser_out; | 794 | gen_cfg.clk_dir = regk_sser_out; |
649 | break; | 795 | break; |
650 | case SLAVE_BIDIR: | 796 | case SLAVE_BIDIR: |
651 | port->output = 1; | 797 | port->output = 1; |
652 | port->input = 1; | 798 | port->input = 1; |
799 | frm_cfg.frame_pin_dir = regk_sser_in; | ||
653 | gen_cfg.clk_dir = regk_sser_in; | 800 | gen_cfg.clk_dir = regk_sser_in; |
654 | break; | 801 | break; |
655 | default: | 802 | default: |
656 | spin_unlock_irq(&port->lock); | 803 | spin_unlock_irq(&port->lock); |
657 | return -EINVAL; | 804 | return -EINVAL; |
658 | |||
659 | } | 805 | } |
660 | if (!port->use_dma || (arg == MASTER_OUTPUT || arg == SLAVE_OUTPUT)) | 806 | if (!port->use_dma || (arg == MASTER_OUTPUT || arg == SLAVE_OUTPUT)) |
661 | intr_mask.rdav = regk_sser_yes; | 807 | intr_mask.rdav = regk_sser_yes; |
662 | break; | 808 | break; |
663 | case SSP_FRAME_SYNC: | 809 | case SSP_FRAME_SYNC: |
664 | if (arg & NORMAL_SYNC) | 810 | if (arg & NORMAL_SYNC) { |
811 | frm_cfg.rec_delay = 1; | ||
665 | frm_cfg.tr_delay = 1; | 812 | frm_cfg.tr_delay = 1; |
813 | } | ||
666 | else if (arg & EARLY_SYNC) | 814 | else if (arg & EARLY_SYNC) |
667 | frm_cfg.tr_delay = 0; | 815 | frm_cfg.rec_delay = frm_cfg.tr_delay = 0; |
816 | else if (arg & SECOND_WORD_SYNC) { | ||
817 | frm_cfg.rec_delay = 7; | ||
818 | frm_cfg.tr_delay = 1; | ||
819 | } | ||
668 | 820 | ||
669 | tr_cfg.bulk_wspace = frm_cfg.tr_delay; | 821 | tr_cfg.bulk_wspace = frm_cfg.tr_delay; |
670 | frm_cfg.early_wend = regk_sser_yes; | 822 | frm_cfg.early_wend = regk_sser_yes; |
@@ -680,9 +832,11 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, | |||
680 | else if (arg & SYNC_OFF) | 832 | else if (arg & SYNC_OFF) |
681 | frm_cfg.frame_pin_use = regk_sser_gio0; | 833 | frm_cfg.frame_pin_use = regk_sser_gio0; |
682 | 834 | ||
683 | if (arg & WORD_SIZE_8) | 835 | dma_w_size = regk_dma_set_w_size2; |
836 | if (arg & WORD_SIZE_8) { | ||
684 | rec_cfg.sample_size = tr_cfg.sample_size = 7; | 837 | rec_cfg.sample_size = tr_cfg.sample_size = 7; |
685 | else if (arg & WORD_SIZE_12) | 838 | dma_w_size = regk_dma_set_w_size1; |
839 | } else if (arg & WORD_SIZE_12) | ||
686 | rec_cfg.sample_size = tr_cfg.sample_size = 11; | 840 | rec_cfg.sample_size = tr_cfg.sample_size = 11; |
687 | else if (arg & WORD_SIZE_16) | 841 | else if (arg & WORD_SIZE_16) |
688 | rec_cfg.sample_size = tr_cfg.sample_size = 15; | 842 | rec_cfg.sample_size = tr_cfg.sample_size = 15; |
@@ -696,10 +850,13 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, | |||
696 | else if (arg & BIT_ORDER_LSB) | 850 | else if (arg & BIT_ORDER_LSB) |
697 | rec_cfg.sh_dir = tr_cfg.sh_dir = regk_sser_lsbfirst; | 851 | rec_cfg.sh_dir = tr_cfg.sh_dir = regk_sser_lsbfirst; |
698 | 852 | ||
699 | if (arg & FLOW_CONTROL_ENABLE) | 853 | if (arg & FLOW_CONTROL_ENABLE) { |
854 | frm_cfg.status_pin_use = regk_sser_frm; | ||
700 | rec_cfg.fifo_thr = regk_sser_thr16; | 855 | rec_cfg.fifo_thr = regk_sser_thr16; |
701 | else if (arg & FLOW_CONTROL_DISABLE) | 856 | } else if (arg & FLOW_CONTROL_DISABLE) { |
857 | frm_cfg.status_pin_use = regk_sser_gio0; | ||
702 | rec_cfg.fifo_thr = regk_sser_inf; | 858 | rec_cfg.fifo_thr = regk_sser_inf; |
859 | } | ||
703 | 860 | ||
704 | if (arg & CLOCK_NOT_GATED) | 861 | if (arg & CLOCK_NOT_GATED) |
705 | gen_cfg.gate_clk = regk_sser_no; | 862 | gen_cfg.gate_clk = regk_sser_no; |
@@ -726,9 +883,9 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, | |||
726 | break; | 883 | break; |
727 | case SSP_OPOLARITY: | 884 | case SSP_OPOLARITY: |
728 | if (arg & CLOCK_NORMAL) | 885 | if (arg & CLOCK_NORMAL) |
729 | gen_cfg.out_clk_pol = regk_sser_neg; | ||
730 | else if (arg & CLOCK_INVERT) | ||
731 | gen_cfg.out_clk_pol = regk_sser_pos; | 886 | gen_cfg.out_clk_pol = regk_sser_pos; |
887 | else if (arg & CLOCK_INVERT) | ||
888 | gen_cfg.out_clk_pol = regk_sser_neg; | ||
732 | 889 | ||
733 | if (arg & FRAME_NORMAL) | 890 | if (arg & FRAME_NORMAL) |
734 | frm_cfg.level = regk_sser_pos_hi; | 891 | frm_cfg.level = regk_sser_pos_hi; |
@@ -770,10 +927,9 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, | |||
770 | } | 927 | } |
771 | 928 | ||
772 | 929 | ||
773 | if (port->started) | 930 | if (port->started) { |
774 | { | ||
775 | tr_cfg.tr_en = port->output; | ||
776 | rec_cfg.rec_en = port->input; | 931 | rec_cfg.rec_en = port->input; |
932 | gen_cfg.en = (port->output | port->input); | ||
777 | } | 933 | } |
778 | 934 | ||
779 | REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg); | 935 | REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg); |
@@ -782,138 +938,145 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, | |||
782 | REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask); | 938 | REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask); |
783 | REG_WR(sser, port->regi_sser, rw_cfg, gen_cfg); | 939 | REG_WR(sser, port->regi_sser, rw_cfg, gen_cfg); |
784 | 940 | ||
941 | |||
942 | if (cmd == SSP_FRAME_SYNC && (arg & (WORD_SIZE_8 | WORD_SIZE_12 | | ||
943 | WORD_SIZE_16 | WORD_SIZE_24 | WORD_SIZE_32))) { | ||
944 | int en = gen_cfg.en; | ||
945 | gen_cfg.en = 0; | ||
946 | REG_WR(sser, port->regi_sser, rw_cfg, gen_cfg); | ||
947 | /* ##### Should DMA be stoped before we change dma size? */ | ||
948 | DMA_WR_CMD(port->regi_dmain, dma_w_size); | ||
949 | DMA_WR_CMD(port->regi_dmaout, dma_w_size); | ||
950 | gen_cfg.en = en; | ||
951 | REG_WR(sser, port->regi_sser, rw_cfg, gen_cfg); | ||
952 | } | ||
953 | |||
785 | spin_unlock_irq(&port->lock); | 954 | spin_unlock_irq(&port->lock); |
786 | return return_val; | 955 | return return_val; |
787 | } | 956 | } |
788 | 957 | ||
789 | static ssize_t sync_serial_write(struct file * file, const char * buf, | 958 | /* NOTE: sync_serial_write does not support concurrency */ |
790 | size_t count, loff_t *ppos) | 959 | static ssize_t sync_serial_write(struct file *file, const char *buf, |
960 | size_t count, loff_t *ppos) | ||
791 | { | 961 | { |
792 | int dev = iminor(file->f_path.dentry->d_inode); | 962 | int dev = iminor(file->f_path.dentry->d_inode); |
793 | DECLARE_WAITQUEUE(wait, current); | 963 | DECLARE_WAITQUEUE(wait, current); |
794 | sync_port *port; | 964 | struct sync_port *port; |
795 | unsigned long c, c1; | 965 | int trunc_count; |
796 | unsigned long free_outp; | ||
797 | unsigned long outp; | ||
798 | unsigned long out_buffer; | ||
799 | unsigned long flags; | 966 | unsigned long flags; |
967 | int bytes_free; | ||
968 | int out_buf_count; | ||
800 | 969 | ||
801 | if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) | 970 | unsigned char *rd_ptr; /* First allocated byte in the buffer */ |
802 | { | 971 | unsigned char *wr_ptr; /* First free byte in the buffer */ |
972 | unsigned char *buf_stop_ptr; /* Last byte + 1 */ | ||
973 | |||
974 | if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) { | ||
803 | DEBUG(printk("Invalid minor %d\n", dev)); | 975 | DEBUG(printk("Invalid minor %d\n", dev)); |
804 | return -ENODEV; | 976 | return -ENODEV; |
805 | } | 977 | } |
806 | port = &ports[dev]; | 978 | port = &ports[dev]; |
807 | 979 | ||
808 | DEBUGWRITE(printk("W d%d c %lu (%d/%d)\n", port->port_nbr, count, port->out_count, OUT_BUFFER_SIZE)); | 980 | /* |<- OUT_BUFFER_SIZE ->| |
809 | /* Space to end of buffer */ | 981 | * |<- out_buf_count ->| |
810 | /* | 982 | * |<- trunc_count ->| ...->| |
811 | * out_buffer <c1>012345<- c ->OUT_BUFFER_SIZE | 983 | * ______________________________________________________ |
812 | * outp^ +out_count | 984 | * | free | data | free | |
813 | ^free_outp | 985 | * |_________|___________________|________________________| |
814 | * out_buffer 45<- c ->0123OUT_BUFFER_SIZE | 986 | * ^ rd_ptr ^ wr_ptr |
815 | * +out_count outp^ | ||
816 | * free_outp | ||
817 | * | ||
818 | */ | 987 | */ |
988 | DEBUGWRITE(printk(KERN_DEBUG "W d%d c %lu a: %p c: %p\n", | ||
989 | port->port_nbr, count, port->active_tr_descr, | ||
990 | port->catch_tr_descr)); | ||
819 | 991 | ||
820 | /* Read variables that may be updated by interrupts */ | 992 | /* Read variables that may be updated by interrupts */ |
821 | spin_lock_irqsave(&port->lock, flags); | 993 | spin_lock_irqsave(&port->lock, flags); |
822 | count = count > OUT_BUFFER_SIZE - port->out_count ? OUT_BUFFER_SIZE - port->out_count : count; | 994 | rd_ptr = port->out_rd_ptr; |
823 | outp = (unsigned long)port->outp; | 995 | out_buf_count = port->out_buf_count; |
824 | free_outp = outp + port->out_count; | ||
825 | spin_unlock_irqrestore(&port->lock, flags); | 996 | spin_unlock_irqrestore(&port->lock, flags); |
826 | out_buffer = (unsigned long)port->out_buffer; | ||
827 | 997 | ||
828 | /* Find out where and how much to write */ | 998 | /* Check if resources are available */ |
829 | if (free_outp >= out_buffer + OUT_BUFFER_SIZE) | 999 | if (port->tr_running && |
830 | free_outp -= OUT_BUFFER_SIZE; | 1000 | ((port->use_dma && port->active_tr_descr == port->catch_tr_descr) || |
831 | if (free_outp >= outp) | 1001 | out_buf_count >= OUT_BUFFER_SIZE)) { |
832 | c = out_buffer + OUT_BUFFER_SIZE - free_outp; | 1002 | DEBUGWRITE(printk(KERN_DEBUG "sser%d full\n", dev)); |
833 | else | 1003 | return -EAGAIN; |
834 | c = outp - free_outp; | 1004 | } |
835 | if (c > count) | 1005 | |
836 | c = count; | 1006 | buf_stop_ptr = port->out_buffer + OUT_BUFFER_SIZE; |
1007 | |||
1008 | /* Determine pointer to the first free byte, before copying. */ | ||
1009 | wr_ptr = rd_ptr + out_buf_count; | ||
1010 | if (wr_ptr >= buf_stop_ptr) | ||
1011 | wr_ptr -= OUT_BUFFER_SIZE; | ||
837 | 1012 | ||
838 | // DEBUGWRITE(printk("w op %08lX fop %08lX c %lu\n", outp, free_outp, c)); | 1013 | /* If we wrap the ring buffer, let the user space program handle it by |
839 | if (copy_from_user((void*)free_outp, buf, c)) | 1014 | * truncating the data. This could be more elegant, small buffer |
1015 | * fragments may occur. | ||
1016 | */ | ||
1017 | bytes_free = OUT_BUFFER_SIZE - out_buf_count; | ||
1018 | if (wr_ptr + bytes_free > buf_stop_ptr) | ||
1019 | bytes_free = buf_stop_ptr - wr_ptr; | ||
1020 | trunc_count = (count < bytes_free) ? count : bytes_free; | ||
1021 | |||
1022 | if (copy_from_user(wr_ptr, buf, trunc_count)) | ||
840 | return -EFAULT; | 1023 | return -EFAULT; |
841 | 1024 | ||
842 | if (c != count) { | 1025 | DEBUGOUTBUF(printk(KERN_DEBUG "%-4d + %-4d = %-4d %p %p %p\n", |
843 | buf += c; | 1026 | out_buf_count, trunc_count, |
844 | c1 = count - c; | 1027 | port->out_buf_count, port->out_buffer, |
845 | DEBUGWRITE(printk("w2 fi %lu c %lu c1 %lu\n", free_outp-out_buffer, c, c1)); | 1028 | wr_ptr, buf_stop_ptr)); |
846 | if (copy_from_user((void*)out_buffer, buf, c1)) | ||
847 | return -EFAULT; | ||
848 | } | ||
849 | spin_lock_irqsave(&port->lock, flags); | ||
850 | port->out_count += count; | ||
851 | spin_unlock_irqrestore(&port->lock, flags); | ||
852 | 1029 | ||
853 | /* Make sure transmitter/receiver is running */ | 1030 | /* Make sure transmitter/receiver is running */ |
854 | if (!port->started) | 1031 | if (!port->started) { |
855 | { | ||
856 | reg_sser_rw_cfg cfg = REG_RD(sser, port->regi_sser, rw_cfg); | 1032 | reg_sser_rw_cfg cfg = REG_RD(sser, port->regi_sser, rw_cfg); |
857 | reg_sser_rw_tr_cfg tr_cfg = REG_RD(sser, port->regi_sser, rw_tr_cfg); | ||
858 | reg_sser_rw_rec_cfg rec_cfg = REG_RD(sser, port->regi_sser, rw_rec_cfg); | 1033 | reg_sser_rw_rec_cfg rec_cfg = REG_RD(sser, port->regi_sser, rw_rec_cfg); |
859 | cfg.en = regk_sser_yes; | 1034 | cfg.en = regk_sser_yes; |
860 | tr_cfg.tr_en = port->output; | ||
861 | rec_cfg.rec_en = port->input; | 1035 | rec_cfg.rec_en = port->input; |
862 | REG_WR(sser, port->regi_sser, rw_cfg, cfg); | 1036 | REG_WR(sser, port->regi_sser, rw_cfg, cfg); |
863 | REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg); | ||
864 | REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg); | 1037 | REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg); |
865 | port->started = 1; | 1038 | port->started = 1; |
866 | } | 1039 | } |
867 | 1040 | ||
868 | if (file->f_flags & O_NONBLOCK) { | 1041 | /* Setup wait if blocking */ |
869 | spin_lock_irqsave(&port->lock, flags); | 1042 | if (!(file->f_flags & O_NONBLOCK)) { |
870 | if (!port->tr_running) { | 1043 | add_wait_queue(&port->out_wait_q, &wait); |
871 | if (!port->use_dma) { | 1044 | set_current_state(TASK_INTERRUPTIBLE); |
872 | reg_sser_rw_intr_mask intr_mask; | ||
873 | intr_mask = REG_RD(sser, port->regi_sser, rw_intr_mask); | ||
874 | /* Start sender by writing data */ | ||
875 | send_word(port); | ||
876 | /* and enable transmitter ready IRQ */ | ||
877 | intr_mask.trdy = 1; | ||
878 | REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask); | ||
879 | } else { | ||
880 | start_dma(port, (unsigned char* volatile )port->outp, c); | ||
881 | } | ||
882 | } | ||
883 | spin_unlock_irqrestore(&port->lock, flags); | ||
884 | DEBUGWRITE(printk("w d%d c %lu NB\n", | ||
885 | port->port_nbr, count)); | ||
886 | return count; | ||
887 | } | 1045 | } |
888 | 1046 | ||
889 | /* Sleep until all sent */ | ||
890 | |||
891 | add_wait_queue(&port->out_wait_q, &wait); | ||
892 | set_current_state(TASK_INTERRUPTIBLE); | ||
893 | spin_lock_irqsave(&port->lock, flags); | 1047 | spin_lock_irqsave(&port->lock, flags); |
894 | if (!port->tr_running) { | 1048 | port->out_buf_count += trunc_count; |
895 | if (!port->use_dma) { | 1049 | if (port->use_dma) { |
896 | reg_sser_rw_intr_mask intr_mask; | 1050 | start_dma_out(port, wr_ptr, trunc_count); |
897 | intr_mask = REG_RD(sser, port->regi_sser, rw_intr_mask); | 1051 | } else if (!port->tr_running) { |
898 | /* Start sender by writing data */ | 1052 | reg_sser_rw_intr_mask intr_mask; |
899 | send_word(port); | 1053 | intr_mask = REG_RD(sser, port->regi_sser, rw_intr_mask); |
900 | /* and enable transmitter ready IRQ */ | 1054 | /* Start sender by writing data */ |
901 | intr_mask.trdy = 1; | 1055 | send_word(port); |
902 | REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask); | 1056 | /* and enable transmitter ready IRQ */ |
903 | } else { | 1057 | intr_mask.trdy = 1; |
904 | start_dma(port, port->outp, c); | 1058 | REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask); |
905 | } | ||
906 | } | 1059 | } |
907 | spin_unlock_irqrestore(&port->lock, flags); | 1060 | spin_unlock_irqrestore(&port->lock, flags); |
1061 | |||
1062 | /* Exit if non blocking */ | ||
1063 | if (file->f_flags & O_NONBLOCK) { | ||
1064 | DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu %08x\n", | ||
1065 | port->port_nbr, trunc_count, | ||
1066 | REG_RD_INT(dma, port->regi_dmaout, r_intr))); | ||
1067 | return trunc_count; | ||
1068 | } | ||
1069 | |||
908 | schedule(); | 1070 | schedule(); |
909 | set_current_state(TASK_RUNNING); | 1071 | set_current_state(TASK_RUNNING); |
910 | remove_wait_queue(&port->out_wait_q, &wait); | 1072 | remove_wait_queue(&port->out_wait_q, &wait); |
1073 | |||
911 | if (signal_pending(current)) | 1074 | if (signal_pending(current)) |
912 | { | ||
913 | return -EINTR; | 1075 | return -EINTR; |
914 | } | 1076 | |
915 | DEBUGWRITE(printk("w d%d c %lu\n", port->port_nbr, count)); | 1077 | DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu\n", |
916 | return count; | 1078 | port->port_nbr, trunc_count)); |
1079 | return trunc_count; | ||
917 | } | 1080 | } |
918 | 1081 | ||
919 | static ssize_t sync_serial_read(struct file * file, char * buf, | 1082 | static ssize_t sync_serial_read(struct file * file, char * buf, |
@@ -926,7 +1089,7 @@ static ssize_t sync_serial_read(struct file * file, char * buf, | |||
926 | unsigned char* end; | 1089 | unsigned char* end; |
927 | unsigned long flags; | 1090 | unsigned long flags; |
928 | 1091 | ||
929 | if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) | 1092 | if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) |
930 | { | 1093 | { |
931 | DEBUG(printk("Invalid minor %d\n", dev)); | 1094 | DEBUG(printk("Invalid minor %d\n", dev)); |
932 | return -ENODEV; | 1095 | return -ENODEV; |
@@ -949,7 +1112,6 @@ static ssize_t sync_serial_read(struct file * file, char * buf, | |||
949 | port->started = 1; | 1112 | port->started = 1; |
950 | } | 1113 | } |
951 | 1114 | ||
952 | |||
953 | /* Calculate number of available bytes */ | 1115 | /* Calculate number of available bytes */ |
954 | /* Save pointers to avoid that they are modified by interrupt */ | 1116 | /* Save pointers to avoid that they are modified by interrupt */ |
955 | spin_lock_irqsave(&port->lock, flags); | 1117 | spin_lock_irqsave(&port->lock, flags); |
@@ -958,16 +1120,14 @@ static ssize_t sync_serial_read(struct file * file, char * buf, | |||
958 | spin_unlock_irqrestore(&port->lock, flags); | 1120 | spin_unlock_irqrestore(&port->lock, flags); |
959 | while ((start == end) && !port->full) /* No data */ | 1121 | while ((start == end) && !port->full) /* No data */ |
960 | { | 1122 | { |
1123 | DEBUGREAD(printk(KERN_DEBUG "&")); | ||
961 | if (file->f_flags & O_NONBLOCK) | 1124 | if (file->f_flags & O_NONBLOCK) |
962 | { | ||
963 | return -EAGAIN; | 1125 | return -EAGAIN; |
964 | } | ||
965 | 1126 | ||
966 | interruptible_sleep_on(&port->in_wait_q); | 1127 | interruptible_sleep_on(&port->in_wait_q); |
967 | if (signal_pending(current)) | 1128 | if (signal_pending(current)) |
968 | { | ||
969 | return -EINTR; | 1129 | return -EINTR; |
970 | } | 1130 | |
971 | spin_lock_irqsave(&port->lock, flags); | 1131 | spin_lock_irqsave(&port->lock, flags); |
972 | start = (unsigned char*)port->readp; /* cast away volatile */ | 1132 | start = (unsigned char*)port->readp; /* cast away volatile */ |
973 | end = (unsigned char*)port->writep; /* cast away volatile */ | 1133 | end = (unsigned char*)port->writep; /* cast away volatile */ |
@@ -1004,83 +1164,105 @@ static void send_word(sync_port* port) | |||
1004 | switch(tr_cfg.sample_size) | 1164 | switch(tr_cfg.sample_size) |
1005 | { | 1165 | { |
1006 | case 8: | 1166 | case 8: |
1007 | port->out_count--; | 1167 | port->out_buf_count--; |
1008 | tr_data.data = *port->outp++; | 1168 | tr_data.data = *port->out_rd_ptr++; |
1009 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); | 1169 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); |
1010 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | 1170 | if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE) |
1011 | port->outp = port->out_buffer; | 1171 | port->out_rd_ptr = port->out_buffer; |
1012 | break; | 1172 | break; |
1013 | case 12: | 1173 | case 12: |
1014 | { | 1174 | { |
1015 | int data = (*port->outp++) << 8; | 1175 | int data = (*port->out_rd_ptr++) << 8; |
1016 | data |= *port->outp++; | 1176 | data |= *port->out_rd_ptr++; |
1017 | port->out_count-=2; | 1177 | port->out_buf_count -= 2; |
1018 | tr_data.data = data; | 1178 | tr_data.data = data; |
1019 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); | 1179 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); |
1020 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | 1180 | if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE) |
1021 | port->outp = port->out_buffer; | 1181 | port->out_rd_ptr = port->out_buffer; |
1022 | } | 1182 | } |
1023 | break; | 1183 | break; |
1024 | case 16: | 1184 | case 16: |
1025 | port->out_count-=2; | 1185 | port->out_buf_count -= 2; |
1026 | tr_data.data = *(unsigned short *)port->outp; | 1186 | tr_data.data = *(unsigned short *)port->out_rd_ptr; |
1027 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); | 1187 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); |
1028 | port->outp+=2; | 1188 | port->out_rd_ptr += 2; |
1029 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | 1189 | if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE) |
1030 | port->outp = port->out_buffer; | 1190 | port->out_rd_ptr = port->out_buffer; |
1031 | break; | 1191 | break; |
1032 | case 24: | 1192 | case 24: |
1033 | port->out_count-=3; | 1193 | port->out_buf_count -= 3; |
1034 | tr_data.data = *(unsigned short *)port->outp; | 1194 | tr_data.data = *(unsigned short *)port->out_rd_ptr; |
1035 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); | 1195 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); |
1036 | port->outp+=2; | 1196 | port->out_rd_ptr += 2; |
1037 | tr_data.data = *port->outp++; | 1197 | tr_data.data = *port->out_rd_ptr++; |
1038 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); | 1198 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); |
1039 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | 1199 | if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE) |
1040 | port->outp = port->out_buffer; | 1200 | port->out_rd_ptr = port->out_buffer; |
1041 | break; | 1201 | break; |
1042 | case 32: | 1202 | case 32: |
1043 | port->out_count-=4; | 1203 | port->out_buf_count -= 4; |
1044 | tr_data.data = *(unsigned short *)port->outp; | 1204 | tr_data.data = *(unsigned short *)port->out_rd_ptr; |
1045 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); | 1205 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); |
1046 | port->outp+=2; | 1206 | port->out_rd_ptr += 2; |
1047 | tr_data.data = *(unsigned short *)port->outp; | 1207 | tr_data.data = *(unsigned short *)port->out_rd_ptr; |
1048 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); | 1208 | REG_WR(sser, port->regi_sser, rw_tr_data, tr_data); |
1049 | port->outp+=2; | 1209 | port->out_rd_ptr += 2; |
1050 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | 1210 | if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE) |
1051 | port->outp = port->out_buffer; | 1211 | port->out_rd_ptr = port->out_buffer; |
1052 | break; | 1212 | break; |
1053 | } | 1213 | } |
1054 | } | 1214 | } |
1055 | 1215 | ||
1056 | 1216 | static void start_dma_out(struct sync_port *port, | |
1057 | static void start_dma(struct sync_port* port, const char* data, int count) | 1217 | const char *data, int count) |
1058 | { | 1218 | { |
1059 | port->tr_running = 1; | 1219 | port->active_tr_descr->buf = (char *) virt_to_phys((char *) data); |
1060 | port->out_descr.buf = (char*)virt_to_phys((char*)data); | 1220 | port->active_tr_descr->after = port->active_tr_descr->buf + count; |
1061 | port->out_descr.after = port->out_descr.buf + count; | 1221 | port->active_tr_descr->intr = 1; |
1062 | port->out_descr.eol = port->out_descr.intr = 1; | 1222 | |
1223 | port->active_tr_descr->eol = 1; | ||
1224 | port->prev_tr_descr->eol = 0; | ||
1225 | |||
1226 | DEBUGTRDMA(printk(KERN_DEBUG "Inserting eolr:%p eol@:%p\n", | ||
1227 | port->prev_tr_descr, port->active_tr_descr)); | ||
1228 | port->prev_tr_descr = port->active_tr_descr; | ||
1229 | port->active_tr_descr = phys_to_virt((int) port->active_tr_descr->next); | ||
1230 | |||
1231 | if (!port->tr_running) { | ||
1232 | reg_sser_rw_tr_cfg tr_cfg = REG_RD(sser, port->regi_sser, | ||
1233 | rw_tr_cfg); | ||
1063 | 1234 | ||
1064 | port->out_context.saved_data = (dma_descr_data*)virt_to_phys(&port->out_descr); | 1235 | port->out_context.next = 0; |
1065 | port->out_context.saved_data_buf = port->out_descr.buf; | 1236 | port->out_context.saved_data = |
1237 | (dma_descr_data *)virt_to_phys(port->prev_tr_descr); | ||
1238 | port->out_context.saved_data_buf = port->prev_tr_descr->buf; | ||
1239 | |||
1240 | DMA_START_CONTEXT(port->regi_dmaout, | ||
1241 | virt_to_phys((char *)&port->out_context)); | ||
1242 | |||
1243 | tr_cfg.tr_en = regk_sser_yes; | ||
1244 | REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg); | ||
1245 | DEBUGTRDMA(printk(KERN_DEBUG "dma s\n");); | ||
1246 | } else { | ||
1247 | DMA_CONTINUE_DATA(port->regi_dmaout); | ||
1248 | DEBUGTRDMA(printk(KERN_DEBUG "dma c\n");); | ||
1249 | } | ||
1066 | 1250 | ||
1067 | DMA_START_CONTEXT(port->regi_dmaout, virt_to_phys((char*)&port->out_context)); | 1251 | port->tr_running = 1; |
1068 | DEBUGTXINT(printk("dma %08lX c %d\n", (unsigned long)data, count)); | ||
1069 | } | 1252 | } |
1070 | 1253 | ||
1071 | static void start_dma_in(sync_port* port) | 1254 | static void start_dma_in(sync_port *port) |
1072 | { | 1255 | { |
1073 | int i; | 1256 | int i; |
1074 | char* buf; | 1257 | char *buf; |
1075 | port->writep = port->flip; | 1258 | port->writep = port->flip; |
1076 | 1259 | ||
1077 | if (port->writep > port->flip + port->in_buffer_size) | 1260 | if (port->writep > port->flip + port->in_buffer_size) { |
1078 | { | ||
1079 | panic("Offset too large in sync serial driver\n"); | 1261 | panic("Offset too large in sync serial driver\n"); |
1080 | return; | 1262 | return; |
1081 | } | 1263 | } |
1082 | buf = (char*)virt_to_phys(port->in_buffer); | 1264 | buf = (char*)virt_to_phys(port->in_buffer); |
1083 | for (i = 0; i < NUM_IN_DESCR; i++) { | 1265 | for (i = 0; i < NBR_IN_DESCR; i++) { |
1084 | port->in_descr[i].buf = buf; | 1266 | port->in_descr[i].buf = buf; |
1085 | port->in_descr[i].after = buf + port->inbufchunk; | 1267 | port->in_descr[i].after = buf + port->inbufchunk; |
1086 | port->in_descr[i].intr = 1; | 1268 | port->in_descr[i].intr = 1; |
@@ -1092,59 +1274,126 @@ static void start_dma_in(sync_port* port) | |||
1092 | port->in_descr[i-1].next = (dma_descr_data*)virt_to_phys(&port->in_descr[0]); | 1274 | port->in_descr[i-1].next = (dma_descr_data*)virt_to_phys(&port->in_descr[0]); |
1093 | port->in_descr[i-1].eol = regk_sser_yes; | 1275 | port->in_descr[i-1].eol = regk_sser_yes; |
1094 | port->next_rx_desc = &port->in_descr[0]; | 1276 | port->next_rx_desc = &port->in_descr[0]; |
1095 | port->prev_rx_desc = &port->in_descr[NUM_IN_DESCR - 1]; | 1277 | port->prev_rx_desc = &port->in_descr[NBR_IN_DESCR - 1]; |
1096 | port->in_context.saved_data = (dma_descr_data*)virt_to_phys(&port->in_descr[0]); | 1278 | port->in_context.saved_data = (dma_descr_data*)virt_to_phys(&port->in_descr[0]); |
1097 | port->in_context.saved_data_buf = port->in_descr[0].buf; | 1279 | port->in_context.saved_data_buf = port->in_descr[0].buf; |
1098 | DMA_START_CONTEXT(port->regi_dmain, virt_to_phys(&port->in_context)); | 1280 | DMA_START_CONTEXT(port->regi_dmain, virt_to_phys(&port->in_context)); |
1099 | } | 1281 | } |
1100 | 1282 | ||
1101 | #ifdef SYNC_SER_DMA | 1283 | #ifdef SYNC_SER_DMA |
1102 | static irqreturn_t tr_interrupt(int irq, void *dev_id, struct pt_regs * regs) | 1284 | static irqreturn_t tr_interrupt(int irq, void *dev_id) |
1103 | { | 1285 | { |
1104 | reg_dma_r_masked_intr masked; | 1286 | reg_dma_r_masked_intr masked; |
1105 | reg_dma_rw_ack_intr ack_intr = {.data = regk_dma_yes}; | 1287 | reg_dma_rw_ack_intr ack_intr = {.data = regk_dma_yes}; |
1288 | reg_dma_rw_stat stat; | ||
1106 | int i; | 1289 | int i; |
1107 | struct dma_descr_data *descr; | ||
1108 | unsigned int sentl; | ||
1109 | int found = 0; | 1290 | int found = 0; |
1291 | int stop_sser = 0; | ||
1110 | 1292 | ||
1111 | for (i = 0; i < NUMBER_OF_PORTS; i++) | 1293 | for (i = 0; i < NBR_PORTS; i++) { |
1112 | { | ||
1113 | sync_port *port = &ports[i]; | 1294 | sync_port *port = &ports[i]; |
1114 | if (!port->enabled || !port->use_dma ) | 1295 | if (!port->enabled || !port->use_dma) |
1115 | continue; | 1296 | continue; |
1116 | 1297 | ||
1298 | /* IRQ active for the port? */ | ||
1117 | masked = REG_RD(dma, port->regi_dmaout, r_masked_intr); | 1299 | masked = REG_RD(dma, port->regi_dmaout, r_masked_intr); |
1300 | if (!masked.data) | ||
1301 | continue; | ||
1118 | 1302 | ||
1119 | if (masked.data) /* IRQ active for the port? */ | 1303 | found = 1; |
1120 | { | 1304 | |
1121 | found = 1; | 1305 | /* Check if we should stop the DMA transfer */ |
1122 | /* Clear IRQ */ | 1306 | stat = REG_RD(dma, port->regi_dmaout, rw_stat); |
1123 | REG_WR(dma, port->regi_dmaout, rw_ack_intr, ack_intr); | 1307 | if (stat.list_state == regk_dma_data_at_eol) |
1124 | descr = &port->out_descr; | 1308 | stop_sser = 1; |
1125 | sentl = descr->after - descr->buf; | 1309 | |
1126 | port->out_count -= sentl; | 1310 | /* Clear IRQ */ |
1127 | port->outp += sentl; | 1311 | REG_WR(dma, port->regi_dmaout, rw_ack_intr, ack_intr); |
1128 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | 1312 | |
1129 | port->outp = port->out_buffer; | 1313 | if (!stop_sser) { |
1130 | if (port->out_count) { | 1314 | /* The DMA has completed a descriptor, EOL was not |
1131 | int c; | 1315 | * encountered, so step relevant descriptor and |
1132 | c = port->out_buffer + OUT_BUFFER_SIZE - port->outp; | 1316 | * datapointers forward. */ |
1133 | if (c > port->out_count) | 1317 | int sent; |
1134 | c = port->out_count; | 1318 | sent = port->catch_tr_descr->after - |
1135 | DEBUGTXINT(printk("tx_int DMAWRITE %i %i\n", sentl, c)); | 1319 | port->catch_tr_descr->buf; |
1136 | start_dma(port, port->outp, c); | 1320 | DEBUGTXINT(printk(KERN_DEBUG "%-4d - %-4d = %-4d\t" |
1137 | } else { | 1321 | "in descr %p (ac: %p)\n", |
1138 | DEBUGTXINT(printk("tx_int DMA stop %i\n", sentl)); | 1322 | port->out_buf_count, sent, |
1139 | port->tr_running = 0; | 1323 | port->out_buf_count - sent, |
1324 | port->catch_tr_descr, | ||
1325 | port->active_tr_descr);); | ||
1326 | port->out_buf_count -= sent; | ||
1327 | port->catch_tr_descr = | ||
1328 | phys_to_virt((int) port->catch_tr_descr->next); | ||
1329 | port->out_rd_ptr = | ||
1330 | phys_to_virt((int) port->catch_tr_descr->buf); | ||
1331 | } else { | ||
1332 | int i, sent; | ||
1333 | /* EOL handler. | ||
1334 | * Note that if an EOL was encountered during the irq | ||
1335 | * locked section of sync_ser_write the DMA will be | ||
1336 | * restarted and the eol flag will be cleared. | ||
1337 | * The remaining descriptors will be traversed by | ||
1338 | * the descriptor interrupts as usual. | ||
1339 | */ | ||
1340 | i = 0; | ||
1341 | while (!port->catch_tr_descr->eol) { | ||
1342 | sent = port->catch_tr_descr->after - | ||
1343 | port->catch_tr_descr->buf; | ||
1344 | DEBUGOUTBUF(printk(KERN_DEBUG | ||
1345 | "traversing descr %p -%d (%d)\n", | ||
1346 | port->catch_tr_descr, | ||
1347 | sent, | ||
1348 | port->out_buf_count)); | ||
1349 | port->out_buf_count -= sent; | ||
1350 | port->catch_tr_descr = phys_to_virt( | ||
1351 | (int)port->catch_tr_descr->next); | ||
1352 | i++; | ||
1353 | if (i >= NBR_OUT_DESCR) { | ||
1354 | /* TODO: Reset and recover */ | ||
1355 | panic("sync_serial: missing eol"); | ||
1356 | } | ||
1140 | } | 1357 | } |
1141 | wake_up_interruptible(&port->out_wait_q); /* wake up the waiting process */ | 1358 | sent = port->catch_tr_descr->after - |
1359 | port->catch_tr_descr->buf; | ||
1360 | DEBUGOUTBUF(printk(KERN_DEBUG | ||
1361 | "eol at descr %p -%d (%d)\n", | ||
1362 | port->catch_tr_descr, | ||
1363 | sent, | ||
1364 | port->out_buf_count)); | ||
1365 | |||
1366 | port->out_buf_count -= sent; | ||
1367 | |||
1368 | /* Update read pointer to first free byte, we | ||
1369 | * may already be writing data there. */ | ||
1370 | port->out_rd_ptr = | ||
1371 | phys_to_virt((int) port->catch_tr_descr->after); | ||
1372 | if (port->out_rd_ptr > port->out_buffer + | ||
1373 | OUT_BUFFER_SIZE) | ||
1374 | port->out_rd_ptr = port->out_buffer; | ||
1375 | |||
1376 | reg_sser_rw_tr_cfg tr_cfg = | ||
1377 | REG_RD(sser, port->regi_sser, rw_tr_cfg); | ||
1378 | DEBUGTXINT(printk(KERN_DEBUG | ||
1379 | "tr_int DMA stop %d, set catch @ %p\n", | ||
1380 | port->out_buf_count, | ||
1381 | port->active_tr_descr)); | ||
1382 | if (port->out_buf_count != 0) | ||
1383 | printk(KERN_CRIT "sync_ser: buffer not " | ||
1384 | "empty after eol.\n"); | ||
1385 | port->catch_tr_descr = port->active_tr_descr; | ||
1386 | port->tr_running = 0; | ||
1387 | tr_cfg.tr_en = regk_sser_no; | ||
1388 | REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg); | ||
1142 | } | 1389 | } |
1390 | /* wake up the waiting process */ | ||
1391 | wake_up_interruptible(&port->out_wait_q); | ||
1143 | } | 1392 | } |
1144 | return IRQ_RETVAL(found); | 1393 | return IRQ_RETVAL(found); |
1145 | } /* tr_interrupt */ | 1394 | } /* tr_interrupt */ |
1146 | 1395 | ||
1147 | static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs) | 1396 | static irqreturn_t rx_interrupt(int irq, void *dev_id) |
1148 | { | 1397 | { |
1149 | reg_dma_r_masked_intr masked; | 1398 | reg_dma_r_masked_intr masked; |
1150 | reg_dma_rw_ack_intr ack_intr = {.data = regk_dma_yes}; | 1399 | reg_dma_rw_ack_intr ack_intr = {.data = regk_dma_yes}; |
@@ -1152,7 +1401,7 @@ static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
1152 | int i; | 1401 | int i; |
1153 | int found = 0; | 1402 | int found = 0; |
1154 | 1403 | ||
1155 | for (i = 0; i < NUMBER_OF_PORTS; i++) | 1404 | for (i = 0; i < NBR_PORTS; i++) |
1156 | { | 1405 | { |
1157 | sync_port *port = &ports[i]; | 1406 | sync_port *port = &ports[i]; |
1158 | 1407 | ||
@@ -1166,7 +1415,7 @@ static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
1166 | found = 1; | 1415 | found = 1; |
1167 | while (REG_RD(dma, port->regi_dmain, rw_data) != | 1416 | while (REG_RD(dma, port->regi_dmain, rw_data) != |
1168 | virt_to_phys(port->next_rx_desc)) { | 1417 | virt_to_phys(port->next_rx_desc)) { |
1169 | 1418 | DEBUGRXINT(printk(KERN_DEBUG "!")); | |
1170 | if (port->writep + port->inbufchunk > port->flip + port->in_buffer_size) { | 1419 | if (port->writep + port->inbufchunk > port->flip + port->in_buffer_size) { |
1171 | int first_size = port->flip + port->in_buffer_size - port->writep; | 1420 | int first_size = port->flip + port->in_buffer_size - port->writep; |
1172 | memcpy((char*)port->writep, phys_to_virt((unsigned)port->next_rx_desc->buf), first_size); | 1421 | memcpy((char*)port->writep, phys_to_virt((unsigned)port->next_rx_desc->buf), first_size); |
@@ -1185,11 +1434,16 @@ static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
1185 | port->full = 1; | 1434 | port->full = 1; |
1186 | } | 1435 | } |
1187 | 1436 | ||
1188 | port->next_rx_desc->eol = 0; | 1437 | port->next_rx_desc->eol = 1; |
1189 | port->prev_rx_desc->eol = 1; | 1438 | port->prev_rx_desc->eol = 0; |
1190 | port->prev_rx_desc = phys_to_virt((unsigned)port->next_rx_desc); | 1439 | /* Cache bug workaround */ |
1440 | flush_dma_descr(port->prev_rx_desc, 0); | ||
1441 | port->prev_rx_desc = port->next_rx_desc; | ||
1191 | port->next_rx_desc = phys_to_virt((unsigned)port->next_rx_desc->next); | 1442 | port->next_rx_desc = phys_to_virt((unsigned)port->next_rx_desc->next); |
1192 | wake_up_interruptible(&port->in_wait_q); /* wake up the waiting process */ | 1443 | /* Cache bug workaround */ |
1444 | flush_dma_descr(port->prev_rx_desc, 1); | ||
1445 | /* wake up the waiting process */ | ||
1446 | wake_up_interruptible(&port->in_wait_q); | ||
1193 | DMA_CONTINUE(port->regi_dmain); | 1447 | DMA_CONTINUE(port->regi_dmain); |
1194 | REG_WR(dma, port->regi_dmain, rw_ack_intr, ack_intr); | 1448 | REG_WR(dma, port->regi_dmain, rw_ack_intr, ack_intr); |
1195 | 1449 | ||
@@ -1201,15 +1455,15 @@ static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
1201 | #endif /* SYNC_SER_DMA */ | 1455 | #endif /* SYNC_SER_DMA */ |
1202 | 1456 | ||
1203 | #ifdef SYNC_SER_MANUAL | 1457 | #ifdef SYNC_SER_MANUAL |
1204 | static irqreturn_t manual_interrupt(int irq, void *dev_id, struct pt_regs * regs) | 1458 | static irqreturn_t manual_interrupt(int irq, void *dev_id) |
1205 | { | 1459 | { |
1206 | int i; | 1460 | int i; |
1207 | int found = 0; | 1461 | int found = 0; |
1208 | reg_sser_r_masked_intr masked; | 1462 | reg_sser_r_masked_intr masked; |
1209 | 1463 | ||
1210 | for (i = 0; i < NUMBER_OF_PORTS; i++) | 1464 | for (i = 0; i < NBR_PORTS; i++) |
1211 | { | 1465 | { |
1212 | sync_port* port = &ports[i]; | 1466 | sync_port *port = &ports[i]; |
1213 | 1467 | ||
1214 | if (!port->enabled || port->use_dma) | 1468 | if (!port->enabled || port->use_dma) |
1215 | { | 1469 | { |
@@ -1263,7 +1517,7 @@ static irqreturn_t manual_interrupt(int irq, void *dev_id, struct pt_regs * regs | |||
1263 | if (masked.trdy) /* Transmitter ready? */ | 1517 | if (masked.trdy) /* Transmitter ready? */ |
1264 | { | 1518 | { |
1265 | found = 1; | 1519 | found = 1; |
1266 | if (port->out_count > 0) /* More data to send */ | 1520 | if (port->out_buf_count > 0) /* More data to send */ |
1267 | send_word(port); | 1521 | send_word(port); |
1268 | else /* transmission finished */ | 1522 | else /* transmission finished */ |
1269 | { | 1523 | { |