diff options
author | Jesper Nilsson <jesper.nilsson@axis.com> | 2008-01-21 05:44:11 -0500 |
---|---|---|
committer | Jesper Nilsson <jesper.nilsson@axis.com> | 2008-02-08 05:06:31 -0500 |
commit | c974a9e5a3c52f1c61501b22a0b0a278250a6bd1 (patch) | |
tree | ee24ac27dfc10c4f2ae664a07b982c606b8881d7 /arch | |
parent | 4f073eff3fb738dce5ad0d8a3d126e5c09cbfba7 (diff) |
CRIS v10: Add synchronous serial port driver for CRIS v10.
Diffstat (limited to 'arch')
-rw-r--r-- | arch/cris/Kconfig | 31 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/Makefile | 1 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/sync_serial.c | 1441 |
3 files changed, 1473 insertions, 0 deletions
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index 4a27ef374203..e6d440ae5e5b 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig | |||
@@ -292,6 +292,37 @@ config ETRAX_PCF8563 | |||
292 | 292 | ||
293 | endchoice | 293 | endchoice |
294 | 294 | ||
295 | config ETRAX_SYNCHRONOUS_SERIAL | ||
296 | bool "Synchronous serial-port support" | ||
297 | help | ||
298 | Select this to enable the synchronous serial port driver. | ||
299 | |||
300 | config ETRAX_SYNCHRONOUS_SERIAL_PORT0 | ||
301 | bool "Synchronous serial port 0 enabled" | ||
302 | depends on ETRAX_SYNCHRONOUS_SERIAL | ||
303 | help | ||
304 | Enabled synchronous serial port 0. | ||
305 | |||
306 | config ETRAX_SYNCHRONOUS_SERIAL0_DMA | ||
307 | bool "Enable DMA on synchronous serial port 0." | ||
308 | depends on ETRAX_SYNCHRONOUS_SERIAL_PORT0 | ||
309 | help | ||
310 | A synchronous serial port can run in manual or DMA mode. | ||
311 | Selecting this option will make it run in DMA mode. | ||
312 | |||
313 | config ETRAX_SYNCHRONOUS_SERIAL_PORT1 | ||
314 | bool "Synchronous serial port 1 enabled" | ||
315 | depends on ETRAX_SYNCHRONOUS_SERIAL && (ETRAXFS || ETRAX_ARCH_V10) | ||
316 | help | ||
317 | Enabled synchronous serial port 1. | ||
318 | |||
319 | config ETRAX_SYNCHRONOUS_SERIAL1_DMA | ||
320 | bool "Enable DMA on synchronous serial port 1." | ||
321 | depends on ETRAX_SYNCHRONOUS_SERIAL_PORT1 | ||
322 | help | ||
323 | A synchronous serial port can run in manual or DMA mode. | ||
324 | Selecting this option will make it run in DMA mode. | ||
325 | |||
295 | choice | 326 | choice |
296 | prompt "Network LED behavior" | 327 | prompt "Network LED behavior" |
297 | depends on ETRAX_ETHERNET | 328 | depends on ETRAX_ETHERNET |
diff --git a/arch/cris/arch-v10/drivers/Makefile b/arch/cris/arch-v10/drivers/Makefile index 074e10ff4156..44bf2e88c26e 100644 --- a/arch/cris/arch-v10/drivers/Makefile +++ b/arch/cris/arch-v10/drivers/Makefile | |||
@@ -8,4 +8,5 @@ obj-$(CONFIG_ETRAX_I2C_EEPROM) += eeprom.o | |||
8 | obj-$(CONFIG_ETRAX_GPIO) += gpio.o | 8 | obj-$(CONFIG_ETRAX_GPIO) += gpio.o |
9 | obj-$(CONFIG_ETRAX_DS1302) += ds1302.o | 9 | obj-$(CONFIG_ETRAX_DS1302) += ds1302.o |
10 | obj-$(CONFIG_ETRAX_PCF8563) += pcf8563.o | 10 | obj-$(CONFIG_ETRAX_PCF8563) += pcf8563.o |
11 | obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o | ||
11 | 12 | ||
diff --git a/arch/cris/arch-v10/drivers/sync_serial.c b/arch/cris/arch-v10/drivers/sync_serial.c new file mode 100644 index 000000000000..069546e342c5 --- /dev/null +++ b/arch/cris/arch-v10/drivers/sync_serial.c | |||
@@ -0,0 +1,1441 @@ | |||
1 | /* | ||
2 | * Simple synchronous serial port driver for ETRAX 100LX. | ||
3 | * | ||
4 | * Synchronous serial ports are used for continuous streamed data like audio. | ||
5 | * The default setting for this driver is compatible with the STA 013 MP3 | ||
6 | * decoder. The driver can easily be tuned to fit other audio encoder/decoders | ||
7 | * and SPI | ||
8 | * | ||
9 | * Copyright (c) 2001-2008 Axis Communications AB | ||
10 | * | ||
11 | * Author: Mikael Starvik, Johan Adolfsson | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/major.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/poll.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/timer.h> | ||
25 | #include <asm/irq.h> | ||
26 | #include <asm/dma.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/arch/svinto.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | #include <asm/system.h> | ||
31 | #include <asm/sync_serial.h> | ||
32 | #include <asm/arch/io_interface_mux.h> | ||
33 | |||
34 | /* The receiver is a bit tricky beacuse of the continuous stream of data.*/ | ||
35 | /* */ | ||
36 | /* Three DMA descriptors are linked together. Each DMA descriptor is */ | ||
37 | /* responsible for port->bufchunk of a common buffer. */ | ||
38 | /* */ | ||
39 | /* +---------------------------------------------+ */ | ||
40 | /* | +----------+ +----------+ +----------+ | */ | ||
41 | /* +-> | Descr[0] |-->| Descr[1] |-->| Descr[2] |-+ */ | ||
42 | /* +----------+ +----------+ +----------+ */ | ||
43 | /* | | | */ | ||
44 | /* v v v */ | ||
45 | /* +-------------------------------------+ */ | ||
46 | /* | BUFFER | */ | ||
47 | /* +-------------------------------------+ */ | ||
48 | /* |<- data_avail ->| */ | ||
49 | /* readp writep */ | ||
50 | /* */ | ||
51 | /* If the application keeps up the pace readp will be right after writep.*/ | ||
52 | /* If the application can't keep the pace we have to throw away data. */ | ||
53 | /* The idea is that readp should be ready with the data pointed out by */ | ||
54 | /* Descr[i] when the DMA has filled in Descr[i+1]. */ | ||
55 | /* Otherwise we will discard */ | ||
56 | /* the rest of the data pointed out by Descr1 and set readp to the start */ | ||
57 | /* of Descr2 */ | ||
58 | |||
59 | #define SYNC_SERIAL_MAJOR 125 | ||
60 | |||
61 | /* IN_BUFFER_SIZE should be a multiple of 6 to make sure that 24 bit */ | ||
62 | /* words can be handled */ | ||
63 | #define IN_BUFFER_SIZE 12288 | ||
64 | #define IN_DESCR_SIZE 256 | ||
65 | #define NUM_IN_DESCR (IN_BUFFER_SIZE/IN_DESCR_SIZE) | ||
66 | #define OUT_BUFFER_SIZE 4096 | ||
67 | |||
68 | #define DEFAULT_FRAME_RATE 0 | ||
69 | #define DEFAULT_WORD_RATE 7 | ||
70 | |||
71 | /* NOTE: Enabling some debug will likely cause overrun or underrun, | ||
72 | * especially if manual mode is use. | ||
73 | */ | ||
74 | #define DEBUG(x) | ||
75 | #define DEBUGREAD(x) | ||
76 | #define DEBUGWRITE(x) | ||
77 | #define DEBUGPOLL(x) | ||
78 | #define DEBUGRXINT(x) | ||
79 | #define DEBUGTXINT(x) | ||
80 | |||
81 | /* Define some macros to access ETRAX 100 registers */ | ||
82 | #define SETF(var, reg, field, val) \ | ||
83 | do { \ | ||
84 | var = (var & ~IO_MASK_(reg##_, field##_)) | \ | ||
85 | IO_FIELD_(reg##_, field##_, val); \ | ||
86 | } while (0) | ||
87 | |||
88 | #define SETS(var, reg, field, val) \ | ||
89 | do { \ | ||
90 | var = (var & ~IO_MASK_(reg##_, field##_)) | \ | ||
91 | IO_STATE_(reg##_, field##_, _##val); \ | ||
92 | } while (0) | ||
93 | |||
94 | struct sync_port { | ||
95 | /* Etrax registers and bits*/ | ||
96 | const volatile unsigned *const status; | ||
97 | volatile unsigned *const ctrl_data; | ||
98 | volatile unsigned *const output_dma_first; | ||
99 | volatile unsigned char *const output_dma_cmd; | ||
100 | volatile unsigned char *const output_dma_clr_irq; | ||
101 | volatile unsigned *const input_dma_first; | ||
102 | volatile unsigned char *const input_dma_cmd; | ||
103 | volatile unsigned *const input_dma_descr; | ||
104 | /* 8*4 */ | ||
105 | volatile unsigned char *const input_dma_clr_irq; | ||
106 | volatile unsigned *const data_out; | ||
107 | const volatile unsigned *const data_in; | ||
108 | char data_avail_bit; /* In R_IRQ_MASK1_RD/SET/CLR */ | ||
109 | char transmitter_ready_bit; /* In R_IRQ_MASK1_RD/SET/CLR */ | ||
110 | char input_dma_descr_bit; /* In R_IRQ_MASK2_RD */ | ||
111 | |||
112 | char output_dma_bit; /* In R_IRQ_MASK2_RD */ | ||
113 | /* End of fields initialised in array */ | ||
114 | char started; /* 1 if port has been started */ | ||
115 | char port_nbr; /* Port 0 or 1 */ | ||
116 | char busy; /* 1 if port is busy */ | ||
117 | |||
118 | char enabled; /* 1 if port is enabled */ | ||
119 | char use_dma; /* 1 if port uses dma */ | ||
120 | char tr_running; | ||
121 | |||
122 | char init_irqs; | ||
123 | |||
124 | /* Register shadow */ | ||
125 | unsigned int ctrl_data_shadow; | ||
126 | /* Remaining bytes for current transfer */ | ||
127 | volatile unsigned int out_count; | ||
128 | /* Current position in out_buffer */ | ||
129 | unsigned char *outp; | ||
130 | /* 16*4 */ | ||
131 | /* Next byte to be read by application */ | ||
132 | volatile unsigned char *volatile readp; | ||
133 | /* Next byte to be written by etrax */ | ||
134 | volatile unsigned char *volatile writep; | ||
135 | |||
136 | unsigned int in_buffer_size; | ||
137 | unsigned int inbufchunk; | ||
138 | struct etrax_dma_descr out_descr __attribute__ ((aligned(32))); | ||
139 | struct etrax_dma_descr in_descr[NUM_IN_DESCR] __attribute__ ((aligned(32))); | ||
140 | unsigned char out_buffer[OUT_BUFFER_SIZE] __attribute__ ((aligned(32))); | ||
141 | unsigned char in_buffer[IN_BUFFER_SIZE]__attribute__ ((aligned(32))); | ||
142 | unsigned char flip[IN_BUFFER_SIZE] __attribute__ ((aligned(32))); | ||
143 | struct etrax_dma_descr *next_rx_desc; | ||
144 | struct etrax_dma_descr *prev_rx_desc; | ||
145 | int full; | ||
146 | |||
147 | wait_queue_head_t out_wait_q; | ||
148 | wait_queue_head_t in_wait_q; | ||
149 | }; | ||
150 | |||
151 | |||
152 | static int etrax_sync_serial_init(void); | ||
153 | static void initialize_port(int portnbr); | ||
154 | static inline int sync_data_avail(struct sync_port *port); | ||
155 | |||
156 | static int sync_serial_open(struct inode *inode, struct file *file); | ||
157 | static int sync_serial_release(struct inode *inode, struct file *file); | ||
158 | static unsigned int sync_serial_poll(struct file *filp, poll_table *wait); | ||
159 | |||
160 | static int sync_serial_ioctl(struct inode *inode, struct file *file, | ||
161 | unsigned int cmd, unsigned long arg); | ||
162 | static ssize_t sync_serial_write(struct file *file, const char *buf, | ||
163 | size_t count, loff_t *ppos); | ||
164 | static ssize_t sync_serial_read(struct file *file, char *buf, | ||
165 | size_t count, loff_t *ppos); | ||
166 | |||
167 | #if ((defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \ | ||
168 | defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)) || \ | ||
169 | (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) && \ | ||
170 | defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA))) | ||
171 | #define SYNC_SER_DMA | ||
172 | #endif | ||
173 | |||
174 | static void send_word(struct sync_port *port); | ||
175 | static void start_dma(struct sync_port *port, const char *data, int count); | ||
176 | static void start_dma_in(struct sync_port *port); | ||
177 | #ifdef SYNC_SER_DMA | ||
178 | static irqreturn_t tr_interrupt(int irq, void *dev_id); | ||
179 | static irqreturn_t rx_interrupt(int irq, void *dev_id); | ||
180 | #endif | ||
181 | #if ((defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \ | ||
182 | !defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)) || \ | ||
183 | (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) && \ | ||
184 | !defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA))) | ||
185 | #define SYNC_SER_MANUAL | ||
186 | #endif | ||
187 | #ifdef SYNC_SER_MANUAL | ||
188 | static irqreturn_t manual_interrupt(int irq, void *dev_id); | ||
189 | #endif | ||
190 | |||
191 | /* The ports */ | ||
192 | static struct sync_port ports[] = { | ||
193 | { | ||
194 | .status = R_SYNC_SERIAL1_STATUS, | ||
195 | .ctrl_data = R_SYNC_SERIAL1_CTRL, | ||
196 | .output_dma_first = R_DMA_CH8_FIRST, | ||
197 | .output_dma_cmd = R_DMA_CH8_CMD, | ||
198 | .output_dma_clr_irq = R_DMA_CH8_CLR_INTR, | ||
199 | .input_dma_first = R_DMA_CH9_FIRST, | ||
200 | .input_dma_cmd = R_DMA_CH9_CMD, | ||
201 | .input_dma_descr = R_DMA_CH9_DESCR, | ||
202 | .input_dma_clr_irq = R_DMA_CH9_CLR_INTR, | ||
203 | .data_out = R_SYNC_SERIAL1_TR_DATA, | ||
204 | .data_in = R_SYNC_SERIAL1_REC_DATA, | ||
205 | .data_avail_bit = IO_BITNR(R_IRQ_MASK1_RD, ser1_data), | ||
206 | .transmitter_ready_bit = IO_BITNR(R_IRQ_MASK1_RD, ser1_ready), | ||
207 | .input_dma_descr_bit = IO_BITNR(R_IRQ_MASK2_RD, dma9_descr), | ||
208 | .output_dma_bit = IO_BITNR(R_IRQ_MASK2_RD, dma8_eop), | ||
209 | .init_irqs = 1, | ||
210 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA) | ||
211 | .use_dma = 1, | ||
212 | #else | ||
213 | .use_dma = 0, | ||
214 | #endif | ||
215 | }, | ||
216 | { | ||
217 | .status = R_SYNC_SERIAL3_STATUS, | ||
218 | .ctrl_data = R_SYNC_SERIAL3_CTRL, | ||
219 | .output_dma_first = R_DMA_CH4_FIRST, | ||
220 | .output_dma_cmd = R_DMA_CH4_CMD, | ||
221 | .output_dma_clr_irq = R_DMA_CH4_CLR_INTR, | ||
222 | .input_dma_first = R_DMA_CH5_FIRST, | ||
223 | .input_dma_cmd = R_DMA_CH5_CMD, | ||
224 | .input_dma_descr = R_DMA_CH5_DESCR, | ||
225 | .input_dma_clr_irq = R_DMA_CH5_CLR_INTR, | ||
226 | .data_out = R_SYNC_SERIAL3_TR_DATA, | ||
227 | .data_in = R_SYNC_SERIAL3_REC_DATA, | ||
228 | .data_avail_bit = IO_BITNR(R_IRQ_MASK1_RD, ser3_data), | ||
229 | .transmitter_ready_bit = IO_BITNR(R_IRQ_MASK1_RD, ser3_ready), | ||
230 | .input_dma_descr_bit = IO_BITNR(R_IRQ_MASK2_RD, dma5_descr), | ||
231 | .output_dma_bit = IO_BITNR(R_IRQ_MASK2_RD, dma4_eop), | ||
232 | .init_irqs = 1, | ||
233 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA) | ||
234 | .use_dma = 1, | ||
235 | #else | ||
236 | .use_dma = 0, | ||
237 | #endif | ||
238 | } | ||
239 | }; | ||
240 | |||
241 | /* Register shadows */ | ||
242 | static unsigned sync_serial_prescale_shadow; | ||
243 | |||
244 | #define NUMBER_OF_PORTS 2 | ||
245 | |||
246 | static struct file_operations sync_serial_fops = { | ||
247 | .owner = THIS_MODULE, | ||
248 | .write = sync_serial_write, | ||
249 | .read = sync_serial_read, | ||
250 | .poll = sync_serial_poll, | ||
251 | .ioctl = sync_serial_ioctl, | ||
252 | .open = sync_serial_open, | ||
253 | .release = sync_serial_release | ||
254 | }; | ||
255 | |||
256 | static int __init etrax_sync_serial_init(void) | ||
257 | { | ||
258 | ports[0].enabled = 0; | ||
259 | ports[1].enabled = 0; | ||
260 | |||
261 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) | ||
262 | if (cris_request_io_interface(if_sync_serial_1, "sync_ser1")) { | ||
263 | printk(KERN_CRIT "ETRAX100LX sync_serial: " | ||
264 | "Could not allocate IO group for port %d\n", 0); | ||
265 | return -EBUSY; | ||
266 | } | ||
267 | #endif | ||
268 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) | ||
269 | if (cris_request_io_interface(if_sync_serial_3, "sync_ser3")) { | ||
270 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) | ||
271 | cris_free_io_interface(if_sync_serial_1); | ||
272 | #endif | ||
273 | printk(KERN_CRIT "ETRAX100LX sync_serial: " | ||
274 | "Could not allocate IO group for port %d\n", 1); | ||
275 | return -EBUSY; | ||
276 | } | ||
277 | #endif | ||
278 | |||
279 | if (register_chrdev(SYNC_SERIAL_MAJOR, "sync serial", | ||
280 | &sync_serial_fops) < 0) { | ||
281 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) | ||
282 | cris_free_io_interface(if_sync_serial_3); | ||
283 | #endif | ||
284 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) | ||
285 | cris_free_io_interface(if_sync_serial_1); | ||
286 | #endif | ||
287 | printk("unable to get major for synchronous serial port\n"); | ||
288 | return -EBUSY; | ||
289 | } | ||
290 | |||
291 | /* Deselect synchronous serial ports while configuring. */ | ||
292 | SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async); | ||
293 | SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async); | ||
294 | *R_GEN_CONFIG_II = gen_config_ii_shadow; | ||
295 | |||
296 | /* Initialize Ports */ | ||
297 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) | ||
298 | ports[0].enabled = 1; | ||
299 | SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser1, ss1extra); | ||
300 | SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync); | ||
301 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA) | ||
302 | ports[0].use_dma = 1; | ||
303 | #else | ||
304 | ports[0].use_dma = 0; | ||
305 | #endif | ||
306 | initialize_port(0); | ||
307 | #endif | ||
308 | |||
309 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) | ||
310 | ports[1].enabled = 1; | ||
311 | SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser3, ss3extra); | ||
312 | SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync); | ||
313 | #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA) | ||
314 | ports[1].use_dma = 1; | ||
315 | #else | ||
316 | ports[1].use_dma = 0; | ||
317 | #endif | ||
318 | initialize_port(1); | ||
319 | #endif | ||
320 | |||
321 | *R_PORT_PB_I2C = port_pb_i2c_shadow; /* Use PB4/PB7 */ | ||
322 | |||
323 | /* Set up timing */ | ||
324 | *R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow = ( | ||
325 | IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec) | | ||
326 | IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u1, external) | | ||
327 | IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec) | | ||
328 | IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u3, external) | | ||
329 | IO_STATE(R_SYNC_SERIAL_PRESCALE, prescaler, div4) | | ||
330 | IO_FIELD(R_SYNC_SERIAL_PRESCALE, frame_rate, | ||
331 | DEFAULT_FRAME_RATE) | | ||
332 | IO_FIELD(R_SYNC_SERIAL_PRESCALE, word_rate, DEFAULT_WORD_RATE) | | ||
333 | IO_STATE(R_SYNC_SERIAL_PRESCALE, warp_mode, normal)); | ||
334 | |||
335 | /* Select synchronous ports */ | ||
336 | *R_GEN_CONFIG_II = gen_config_ii_shadow; | ||
337 | |||
338 | printk(KERN_INFO "ETRAX 100LX synchronous serial port driver\n"); | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static void __init initialize_port(int portnbr) | ||
343 | { | ||
344 | struct sync_port *port = &ports[portnbr]; | ||
345 | |||
346 | DEBUG(printk(KERN_DEBUG "Init sync serial port %d\n", portnbr)); | ||
347 | |||
348 | port->started = 0; | ||
349 | port->port_nbr = portnbr; | ||
350 | port->busy = 0; | ||
351 | port->tr_running = 0; | ||
352 | |||
353 | port->out_count = 0; | ||
354 | port->outp = port->out_buffer; | ||
355 | |||
356 | port->readp = port->flip; | ||
357 | port->writep = port->flip; | ||
358 | port->in_buffer_size = IN_BUFFER_SIZE; | ||
359 | port->inbufchunk = IN_DESCR_SIZE; | ||
360 | port->next_rx_desc = &port->in_descr[0]; | ||
361 | port->prev_rx_desc = &port->in_descr[NUM_IN_DESCR-1]; | ||
362 | port->prev_rx_desc->ctrl = d_eol; | ||
363 | |||
364 | init_waitqueue_head(&port->out_wait_q); | ||
365 | init_waitqueue_head(&port->in_wait_q); | ||
366 | |||
367 | port->ctrl_data_shadow = | ||
368 | IO_STATE(R_SYNC_SERIAL1_CTRL, tr_baud, c115k2Hz) | | ||
369 | IO_STATE(R_SYNC_SERIAL1_CTRL, mode, master_output) | | ||
370 | IO_STATE(R_SYNC_SERIAL1_CTRL, error, ignore) | | ||
371 | IO_STATE(R_SYNC_SERIAL1_CTRL, rec_enable, disable) | | ||
372 | IO_STATE(R_SYNC_SERIAL1_CTRL, f_synctype, normal) | | ||
373 | IO_STATE(R_SYNC_SERIAL1_CTRL, f_syncsize, word) | | ||
374 | IO_STATE(R_SYNC_SERIAL1_CTRL, f_sync, on) | | ||
375 | IO_STATE(R_SYNC_SERIAL1_CTRL, clk_mode, normal) | | ||
376 | IO_STATE(R_SYNC_SERIAL1_CTRL, clk_halt, stopped) | | ||
377 | IO_STATE(R_SYNC_SERIAL1_CTRL, bitorder, msb) | | ||
378 | IO_STATE(R_SYNC_SERIAL1_CTRL, tr_enable, disable) | | ||
379 | IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit) | | ||
380 | IO_STATE(R_SYNC_SERIAL1_CTRL, buf_empty, lmt_8) | | ||
381 | IO_STATE(R_SYNC_SERIAL1_CTRL, buf_full, lmt_8) | | ||
382 | IO_STATE(R_SYNC_SERIAL1_CTRL, flow_ctrl, enabled) | | ||
383 | IO_STATE(R_SYNC_SERIAL1_CTRL, clk_polarity, neg) | | ||
384 | IO_STATE(R_SYNC_SERIAL1_CTRL, frame_polarity, normal)| | ||
385 | IO_STATE(R_SYNC_SERIAL1_CTRL, status_polarity, inverted)| | ||
386 | IO_STATE(R_SYNC_SERIAL1_CTRL, clk_driver, normal) | | ||
387 | IO_STATE(R_SYNC_SERIAL1_CTRL, frame_driver, normal) | | ||
388 | IO_STATE(R_SYNC_SERIAL1_CTRL, status_driver, normal)| | ||
389 | IO_STATE(R_SYNC_SERIAL1_CTRL, def_out0, high); | ||
390 | |||
391 | if (port->use_dma) | ||
392 | port->ctrl_data_shadow |= IO_STATE(R_SYNC_SERIAL1_CTRL, | ||
393 | dma_enable, on); | ||
394 | else | ||
395 | port->ctrl_data_shadow |= IO_STATE(R_SYNC_SERIAL1_CTRL, | ||
396 | dma_enable, off); | ||
397 | |||
398 | *port->ctrl_data = port->ctrl_data_shadow; | ||
399 | } | ||
400 | |||
401 | static inline int sync_data_avail(struct sync_port *port) | ||
402 | { | ||
403 | int avail; | ||
404 | unsigned char *start; | ||
405 | unsigned char *end; | ||
406 | |||
407 | start = (unsigned char *)port->readp; /* cast away volatile */ | ||
408 | end = (unsigned char *)port->writep; /* cast away volatile */ | ||
409 | /* 0123456789 0123456789 | ||
410 | * ----- - ----- | ||
411 | * ^rp ^wp ^wp ^rp | ||
412 | */ | ||
413 | if (end >= start) | ||
414 | avail = end - start; | ||
415 | else | ||
416 | avail = port->in_buffer_size - (start - end); | ||
417 | return avail; | ||
418 | } | ||
419 | |||
420 | static inline int sync_data_avail_to_end(struct sync_port *port) | ||
421 | { | ||
422 | int avail; | ||
423 | unsigned char *start; | ||
424 | unsigned char *end; | ||
425 | |||
426 | start = (unsigned char *)port->readp; /* cast away volatile */ | ||
427 | end = (unsigned char *)port->writep; /* cast away volatile */ | ||
428 | /* 0123456789 0123456789 | ||
429 | * ----- ----- | ||
430 | * ^rp ^wp ^wp ^rp | ||
431 | */ | ||
432 | |||
433 | if (end >= start) | ||
434 | avail = end - start; | ||
435 | else | ||
436 | avail = port->flip + port->in_buffer_size - start; | ||
437 | return avail; | ||
438 | } | ||
439 | |||
440 | |||
441 | static int sync_serial_open(struct inode *inode, struct file *file) | ||
442 | { | ||
443 | int dev = MINOR(inode->i_rdev); | ||
444 | struct sync_port *port; | ||
445 | int mode; | ||
446 | |||
447 | DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev)); | ||
448 | |||
449 | if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) { | ||
450 | DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); | ||
451 | return -ENODEV; | ||
452 | } | ||
453 | port = &ports[dev]; | ||
454 | /* Allow open this device twice (assuming one reader and one writer) */ | ||
455 | if (port->busy == 2) { | ||
456 | DEBUG(printk(KERN_DEBUG "Device is busy.. \n")); | ||
457 | return -EBUSY; | ||
458 | } | ||
459 | if (port->init_irqs) { | ||
460 | if (port->use_dma) { | ||
461 | if (port == &ports[0]) { | ||
462 | #ifdef SYNC_SER_DMA | ||
463 | if (request_irq(24, tr_interrupt, 0, | ||
464 | "synchronous serial 1 dma tr", | ||
465 | &ports[0])) { | ||
466 | printk(KERN_CRIT "Can't alloc " | ||
467 | "sync serial port 1 IRQ"); | ||
468 | return -EBUSY; | ||
469 | } else if (request_irq(25, rx_interrupt, 0, | ||
470 | "synchronous serial 1 dma rx", | ||
471 | &ports[0])) { | ||
472 | free_irq(24, &port[0]); | ||
473 | printk(KERN_CRIT "Can't alloc " | ||
474 | "sync serial port 1 IRQ"); | ||
475 | return -EBUSY; | ||
476 | } else if (cris_request_dma(8, | ||
477 | "synchronous serial 1 dma tr", | ||
478 | DMA_VERBOSE_ON_ERROR, | ||
479 | dma_ser1)) { | ||
480 | free_irq(24, &port[0]); | ||
481 | free_irq(25, &port[0]); | ||
482 | printk(KERN_CRIT "Can't alloc " | ||
483 | "sync serial port 1 " | ||
484 | "TX DMA channel"); | ||
485 | return -EBUSY; | ||
486 | } else if (cris_request_dma(9, | ||
487 | "synchronous serial 1 dma rec", | ||
488 | DMA_VERBOSE_ON_ERROR, | ||
489 | dma_ser1)) { | ||
490 | cris_free_dma(8, NULL); | ||
491 | free_irq(24, &port[0]); | ||
492 | free_irq(25, &port[0]); | ||
493 | printk(KERN_CRIT "Can't alloc " | ||
494 | "sync serial port 1 " | ||
495 | "RX DMA channel"); | ||
496 | return -EBUSY; | ||
497 | } | ||
498 | #endif | ||
499 | RESET_DMA(8); WAIT_DMA(8); | ||
500 | RESET_DMA(9); WAIT_DMA(9); | ||
501 | *R_DMA_CH8_CLR_INTR = | ||
502 | IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, | ||
503 | do) | | ||
504 | IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, | ||
505 | do); | ||
506 | *R_DMA_CH9_CLR_INTR = | ||
507 | IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, | ||
508 | do) | | ||
509 | IO_STATE(R_DMA_CH9_CLR_INTR, clr_descr, | ||
510 | do); | ||
511 | *R_IRQ_MASK2_SET = | ||
512 | IO_STATE(R_IRQ_MASK2_SET, dma8_eop, | ||
513 | set) | | ||
514 | IO_STATE(R_IRQ_MASK2_SET, dma9_descr, | ||
515 | set); | ||
516 | } else if (port == &ports[1]) { | ||
517 | #ifdef SYNC_SER_DMA | ||
518 | if (request_irq(20, tr_interrupt, 0, | ||
519 | "synchronous serial 3 dma tr", | ||
520 | &ports[1])) { | ||
521 | printk(KERN_CRIT "Can't alloc " | ||
522 | "sync serial port 3 IRQ"); | ||
523 | return -EBUSY; | ||
524 | } else if (request_irq(21, rx_interrupt, 0, | ||
525 | "synchronous serial 3 dma rx", | ||
526 | &ports[1])) { | ||
527 | free_irq(20, &ports[1]); | ||
528 | printk(KERN_CRIT "Can't alloc " | ||
529 | "sync serial port 3 IRQ"); | ||
530 | return -EBUSY; | ||
531 | } else if (cris_request_dma(4, | ||
532 | "synchronous serial 3 dma tr", | ||
533 | DMA_VERBOSE_ON_ERROR, | ||
534 | dma_ser3)) { | ||
535 | free_irq(21, &ports[1]); | ||
536 | free_irq(20, &ports[1]); | ||
537 | printk(KERN_CRIT "Can't alloc " | ||
538 | "sync serial port 3 " | ||
539 | "TX DMA channel"); | ||
540 | return -EBUSY; | ||
541 | } else if (cris_request_dma(5, | ||
542 | "synchronous serial 3 dma rec", | ||
543 | DMA_VERBOSE_ON_ERROR, | ||
544 | dma_ser3)) { | ||
545 | cris_free_dma(4, NULL); | ||
546 | free_irq(21, &ports[1]); | ||
547 | free_irq(20, &ports[1]); | ||
548 | printk(KERN_CRIT "Can't alloc " | ||
549 | "sync serial port 3 " | ||
550 | "RX DMA channel"); | ||
551 | return -EBUSY; | ||
552 | } | ||
553 | #endif | ||
554 | RESET_DMA(4); WAIT_DMA(4); | ||
555 | RESET_DMA(5); WAIT_DMA(5); | ||
556 | *R_DMA_CH4_CLR_INTR = | ||
557 | IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, | ||
558 | do) | | ||
559 | IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, | ||
560 | do); | ||
561 | *R_DMA_CH5_CLR_INTR = | ||
562 | IO_STATE(R_DMA_CH5_CLR_INTR, clr_eop, | ||
563 | do) | | ||
564 | IO_STATE(R_DMA_CH5_CLR_INTR, clr_descr, | ||
565 | do); | ||
566 | *R_IRQ_MASK2_SET = | ||
567 | IO_STATE(R_IRQ_MASK2_SET, dma4_eop, | ||
568 | set) | | ||
569 | IO_STATE(R_IRQ_MASK2_SET, dma5_descr, | ||
570 | set); | ||
571 | } | ||
572 | start_dma_in(port); | ||
573 | port->init_irqs = 0; | ||
574 | } else { /* !port->use_dma */ | ||
575 | #ifdef SYNC_SER_MANUAL | ||
576 | if (port == &ports[0]) { | ||
577 | if (request_irq(8, | ||
578 | manual_interrupt, | ||
579 | IRQF_SHARED | IRQF_DISABLED, | ||
580 | "synchronous serial manual irq", | ||
581 | &ports[0])) { | ||
582 | printk(KERN_CRIT "Can't alloc " | ||
583 | "sync serial manual irq"); | ||
584 | return -EBUSY; | ||
585 | } | ||
586 | } else if (port == &ports[1]) { | ||
587 | if (request_irq(8, | ||
588 | manual_interrupt, | ||
589 | IRQF_SHARED | IRQF_DISABLED, | ||
590 | "synchronous serial manual irq", | ||
591 | &ports[1])) { | ||
592 | printk(KERN_CRIT "Can't alloc " | ||
593 | "sync serial manual irq"); | ||
594 | return -EBUSY; | ||
595 | } | ||
596 | } | ||
597 | port->init_irqs = 0; | ||
598 | #else | ||
599 | panic("sync_serial: Manual mode not supported.\n"); | ||
600 | #endif /* SYNC_SER_MANUAL */ | ||
601 | } | ||
602 | } /* port->init_irqs */ | ||
603 | |||
604 | port->busy++; | ||
605 | /* Start port if we use it as input */ | ||
606 | mode = IO_EXTRACT(R_SYNC_SERIAL1_CTRL, mode, port->ctrl_data_shadow); | ||
607 | if (mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, master_input) || | ||
608 | mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, slave_input) || | ||
609 | mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, master_bidir) || | ||
610 | mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, slave_bidir)) { | ||
611 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, | ||
612 | running); | ||
613 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, | ||
614 | enable); | ||
615 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, | ||
616 | enable); | ||
617 | port->started = 1; | ||
618 | *port->ctrl_data = port->ctrl_data_shadow; | ||
619 | if (!port->use_dma) | ||
620 | *R_IRQ_MASK1_SET = 1 << port->data_avail_bit; | ||
621 | DEBUG(printk(KERN_DEBUG "sser%d rec started\n", dev)); | ||
622 | } | ||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static int sync_serial_release(struct inode *inode, struct file *file) | ||
627 | { | ||
628 | int dev = MINOR(inode->i_rdev); | ||
629 | struct sync_port *port; | ||
630 | |||
631 | if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) { | ||
632 | DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); | ||
633 | return -ENODEV; | ||
634 | } | ||
635 | port = &ports[dev]; | ||
636 | if (port->busy) | ||
637 | port->busy--; | ||
638 | if (!port->busy) | ||
639 | *R_IRQ_MASK1_CLR = ((1 << port->data_avail_bit) | | ||
640 | (1 << port->transmitter_ready_bit)); | ||
641 | |||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | |||
646 | |||
647 | static unsigned int sync_serial_poll(struct file *file, poll_table *wait) | ||
648 | { | ||
649 | int dev = MINOR(file->f_dentry->d_inode->i_rdev); | ||
650 | unsigned int mask = 0; | ||
651 | struct sync_port *port; | ||
652 | DEBUGPOLL(static unsigned int prev_mask = 0); | ||
653 | |||
654 | port = &ports[dev]; | ||
655 | poll_wait(file, &port->out_wait_q, wait); | ||
656 | poll_wait(file, &port->in_wait_q, wait); | ||
657 | /* Some room to write */ | ||
658 | if (port->out_count < OUT_BUFFER_SIZE) | ||
659 | mask |= POLLOUT | POLLWRNORM; | ||
660 | /* At least an inbufchunk of data */ | ||
661 | if (sync_data_avail(port) >= port->inbufchunk) | ||
662 | mask |= POLLIN | POLLRDNORM; | ||
663 | |||
664 | DEBUGPOLL(if (mask != prev_mask) | ||
665 | printk(KERN_DEBUG "sync_serial_poll: mask 0x%08X %s %s\n", | ||
666 | mask, | ||
667 | mask & POLLOUT ? "POLLOUT" : "", | ||
668 | mask & POLLIN ? "POLLIN" : ""); | ||
669 | prev_mask = mask; | ||
670 | ); | ||
671 | return mask; | ||
672 | } | ||
673 | |||
674 | static int sync_serial_ioctl(struct inode *inode, struct file *file, | ||
675 | unsigned int cmd, unsigned long arg) | ||
676 | { | ||
677 | int return_val = 0; | ||
678 | unsigned long flags; | ||
679 | |||
680 | int dev = MINOR(file->f_dentry->d_inode->i_rdev); | ||
681 | struct sync_port *port; | ||
682 | |||
683 | if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) { | ||
684 | DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); | ||
685 | return -1; | ||
686 | } | ||
687 | port = &ports[dev]; | ||
688 | |||
689 | local_irq_save(flags); | ||
690 | /* Disable port while changing config */ | ||
691 | if (dev) { | ||
692 | if (port->use_dma) { | ||
693 | RESET_DMA(4); WAIT_DMA(4); | ||
694 | port->tr_running = 0; | ||
695 | port->out_count = 0; | ||
696 | port->outp = port->out_buffer; | ||
697 | *R_DMA_CH4_CLR_INTR = | ||
698 | IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, do) | | ||
699 | IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do); | ||
700 | } | ||
701 | SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async); | ||
702 | } else { | ||
703 | if (port->use_dma) { | ||
704 | RESET_DMA(8); WAIT_DMA(8); | ||
705 | port->tr_running = 0; | ||
706 | port->out_count = 0; | ||
707 | port->outp = port->out_buffer; | ||
708 | *R_DMA_CH8_CLR_INTR = | ||
709 | IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, do) | | ||
710 | IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, do); | ||
711 | } | ||
712 | SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async); | ||
713 | } | ||
714 | *R_GEN_CONFIG_II = gen_config_ii_shadow; | ||
715 | local_irq_restore(flags); | ||
716 | |||
717 | switch (cmd) { | ||
718 | case SSP_SPEED: | ||
719 | if (GET_SPEED(arg) == CODEC) { | ||
720 | if (dev) | ||
721 | SETS(sync_serial_prescale_shadow, | ||
722 | R_SYNC_SERIAL_PRESCALE, clk_sel_u3, | ||
723 | codec); | ||
724 | else | ||
725 | SETS(sync_serial_prescale_shadow, | ||
726 | R_SYNC_SERIAL_PRESCALE, clk_sel_u1, | ||
727 | codec); | ||
728 | |||
729 | SETF(sync_serial_prescale_shadow, | ||
730 | R_SYNC_SERIAL_PRESCALE, prescaler, | ||
731 | GET_FREQ(arg)); | ||
732 | SETF(sync_serial_prescale_shadow, | ||
733 | R_SYNC_SERIAL_PRESCALE, frame_rate, | ||
734 | GET_FRAME_RATE(arg)); | ||
735 | SETF(sync_serial_prescale_shadow, | ||
736 | R_SYNC_SERIAL_PRESCALE, word_rate, | ||
737 | GET_WORD_RATE(arg)); | ||
738 | } else { | ||
739 | SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
740 | tr_baud, GET_SPEED(arg)); | ||
741 | if (dev) | ||
742 | SETS(sync_serial_prescale_shadow, | ||
743 | R_SYNC_SERIAL_PRESCALE, clk_sel_u3, | ||
744 | baudrate); | ||
745 | else | ||
746 | SETS(sync_serial_prescale_shadow, | ||
747 | R_SYNC_SERIAL_PRESCALE, clk_sel_u1, | ||
748 | baudrate); | ||
749 | } | ||
750 | break; | ||
751 | case SSP_MODE: | ||
752 | if (arg > 5) | ||
753 | return -EINVAL; | ||
754 | if (arg == MASTER_OUTPUT || arg == SLAVE_OUTPUT) | ||
755 | *R_IRQ_MASK1_CLR = 1 << port->data_avail_bit; | ||
756 | else if (!port->use_dma) | ||
757 | *R_IRQ_MASK1_SET = 1 << port->data_avail_bit; | ||
758 | SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, arg); | ||
759 | break; | ||
760 | case SSP_FRAME_SYNC: | ||
761 | if (arg & NORMAL_SYNC) | ||
762 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
763 | f_synctype, normal); | ||
764 | else if (arg & EARLY_SYNC) | ||
765 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
766 | f_synctype, early); | ||
767 | |||
768 | if (arg & BIT_SYNC) | ||
769 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
770 | f_syncsize, bit); | ||
771 | else if (arg & WORD_SYNC) | ||
772 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
773 | f_syncsize, word); | ||
774 | else if (arg & EXTENDED_SYNC) | ||
775 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
776 | f_syncsize, extended); | ||
777 | |||
778 | if (arg & SYNC_ON) | ||
779 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
780 | f_sync, on); | ||
781 | else if (arg & SYNC_OFF) | ||
782 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
783 | f_sync, off); | ||
784 | |||
785 | if (arg & WORD_SIZE_8) | ||
786 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
787 | wordsize, size8bit); | ||
788 | else if (arg & WORD_SIZE_12) | ||
789 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
790 | wordsize, size12bit); | ||
791 | else if (arg & WORD_SIZE_16) | ||
792 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
793 | wordsize, size16bit); | ||
794 | else if (arg & WORD_SIZE_24) | ||
795 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
796 | wordsize, size24bit); | ||
797 | else if (arg & WORD_SIZE_32) | ||
798 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
799 | wordsize, size32bit); | ||
800 | |||
801 | if (arg & BIT_ORDER_MSB) | ||
802 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
803 | bitorder, msb); | ||
804 | else if (arg & BIT_ORDER_LSB) | ||
805 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
806 | bitorder, lsb); | ||
807 | |||
808 | if (arg & FLOW_CONTROL_ENABLE) | ||
809 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
810 | flow_ctrl, enabled); | ||
811 | else if (arg & FLOW_CONTROL_DISABLE) | ||
812 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
813 | flow_ctrl, disabled); | ||
814 | |||
815 | if (arg & CLOCK_NOT_GATED) | ||
816 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
817 | clk_mode, normal); | ||
818 | else if (arg & CLOCK_GATED) | ||
819 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
820 | clk_mode, gated); | ||
821 | |||
822 | break; | ||
823 | case SSP_IPOLARITY: | ||
824 | /* NOTE!! negedge is considered NORMAL */ | ||
825 | if (arg & CLOCK_NORMAL) | ||
826 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
827 | clk_polarity, neg); | ||
828 | else if (arg & CLOCK_INVERT) | ||
829 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
830 | clk_polarity, pos); | ||
831 | |||
832 | if (arg & FRAME_NORMAL) | ||
833 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
834 | frame_polarity, normal); | ||
835 | else if (arg & FRAME_INVERT) | ||
836 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
837 | frame_polarity, inverted); | ||
838 | |||
839 | if (arg & STATUS_NORMAL) | ||
840 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
841 | status_polarity, normal); | ||
842 | else if (arg & STATUS_INVERT) | ||
843 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
844 | status_polarity, inverted); | ||
845 | break; | ||
846 | case SSP_OPOLARITY: | ||
847 | if (arg & CLOCK_NORMAL) | ||
848 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
849 | clk_driver, normal); | ||
850 | else if (arg & CLOCK_INVERT) | ||
851 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
852 | clk_driver, inverted); | ||
853 | |||
854 | if (arg & FRAME_NORMAL) | ||
855 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
856 | frame_driver, normal); | ||
857 | else if (arg & FRAME_INVERT) | ||
858 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
859 | frame_driver, inverted); | ||
860 | |||
861 | if (arg & STATUS_NORMAL) | ||
862 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
863 | status_driver, normal); | ||
864 | else if (arg & STATUS_INVERT) | ||
865 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
866 | status_driver, inverted); | ||
867 | break; | ||
868 | case SSP_SPI: | ||
869 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, | ||
870 | disabled); | ||
871 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, | ||
872 | msb); | ||
873 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, | ||
874 | size8bit); | ||
875 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on); | ||
876 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, | ||
877 | word); | ||
878 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, | ||
879 | normal); | ||
880 | if (arg & SPI_SLAVE) { | ||
881 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
882 | frame_polarity, inverted); | ||
883 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
884 | clk_polarity, neg); | ||
885 | SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
886 | mode, SLAVE_INPUT); | ||
887 | } else { | ||
888 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
889 | frame_driver, inverted); | ||
890 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
891 | clk_driver, inverted); | ||
892 | SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, | ||
893 | mode, MASTER_OUTPUT); | ||
894 | } | ||
895 | break; | ||
896 | case SSP_INBUFCHUNK: | ||
897 | #if 0 | ||
898 | if (arg > port->in_buffer_size/NUM_IN_DESCR) | ||
899 | return -EINVAL; | ||
900 | port->inbufchunk = arg; | ||
901 | /* Make sure in_buffer_size is a multiple of inbufchunk */ | ||
902 | port->in_buffer_size = | ||
903 | (port->in_buffer_size/port->inbufchunk) * | ||
904 | port->inbufchunk; | ||
905 | DEBUG(printk(KERN_DEBUG "inbufchunk %i in_buffer_size: %i\n", | ||
906 | port->inbufchunk, port->in_buffer_size)); | ||
907 | if (port->use_dma) { | ||
908 | if (port->port_nbr == 0) { | ||
909 | RESET_DMA(9); | ||
910 | WAIT_DMA(9); | ||
911 | } else { | ||
912 | RESET_DMA(5); | ||
913 | WAIT_DMA(5); | ||
914 | } | ||
915 | start_dma_in(port); | ||
916 | } | ||
917 | #endif | ||
918 | break; | ||
919 | default: | ||
920 | return_val = -1; | ||
921 | } | ||
922 | /* Make sure we write the config without interruption */ | ||
923 | local_irq_save(flags); | ||
924 | /* Set config and enable port */ | ||
925 | *port->ctrl_data = port->ctrl_data_shadow; | ||
926 | nop(); nop(); nop(); nop(); | ||
927 | *R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow; | ||
928 | nop(); nop(); nop(); nop(); | ||
929 | if (dev) | ||
930 | SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync); | ||
931 | else | ||
932 | SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync); | ||
933 | |||
934 | *R_GEN_CONFIG_II = gen_config_ii_shadow; | ||
935 | /* Reset DMA. At readout from serial port the data could be shifted | ||
936 | * one byte if not resetting DMA. | ||
937 | */ | ||
938 | if (port->use_dma) { | ||
939 | if (port->port_nbr == 0) { | ||
940 | RESET_DMA(9); | ||
941 | WAIT_DMA(9); | ||
942 | } else { | ||
943 | RESET_DMA(5); | ||
944 | WAIT_DMA(5); | ||
945 | } | ||
946 | start_dma_in(port); | ||
947 | } | ||
948 | local_irq_restore(flags); | ||
949 | return return_val; | ||
950 | } | ||
951 | |||
952 | |||
953 | static ssize_t sync_serial_write(struct file *file, const char *buf, | ||
954 | size_t count, loff_t *ppos) | ||
955 | { | ||
956 | int dev = MINOR(file->f_dentry->d_inode->i_rdev); | ||
957 | DECLARE_WAITQUEUE(wait, current); | ||
958 | struct sync_port *port; | ||
959 | unsigned long flags; | ||
960 | unsigned long c, c1; | ||
961 | unsigned long free_outp; | ||
962 | unsigned long outp; | ||
963 | unsigned long out_buffer; | ||
964 | |||
965 | if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) { | ||
966 | DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); | ||
967 | return -ENODEV; | ||
968 | } | ||
969 | port = &ports[dev]; | ||
970 | |||
971 | DEBUGWRITE(printk(KERN_DEBUG "W d%d c %lu (%d/%d)\n", | ||
972 | port->port_nbr, count, port->out_count, OUT_BUFFER_SIZE)); | ||
973 | /* Space to end of buffer */ | ||
974 | /* | ||
975 | * out_buffer <c1>012345<- c ->OUT_BUFFER_SIZE | ||
976 | * outp^ +out_count | ||
977 | * ^free_outp | ||
978 | * out_buffer 45<- c ->0123OUT_BUFFER_SIZE | ||
979 | * +out_count outp^ | ||
980 | * free_outp | ||
981 | * | ||
982 | */ | ||
983 | |||
984 | /* Read variables that may be updated by interrupts */ | ||
985 | local_irq_save(flags); | ||
986 | if (count > OUT_BUFFER_SIZE - port->out_count) | ||
987 | count = OUT_BUFFER_SIZE - port->out_count; | ||
988 | |||
989 | outp = (unsigned long)port->outp; | ||
990 | free_outp = outp + port->out_count; | ||
991 | local_irq_restore(flags); | ||
992 | out_buffer = (unsigned long)port->out_buffer; | ||
993 | |||
994 | /* Find out where and how much to write */ | ||
995 | if (free_outp >= out_buffer + OUT_BUFFER_SIZE) | ||
996 | free_outp -= OUT_BUFFER_SIZE; | ||
997 | if (free_outp >= outp) | ||
998 | c = out_buffer + OUT_BUFFER_SIZE - free_outp; | ||
999 | else | ||
1000 | c = outp - free_outp; | ||
1001 | if (c > count) | ||
1002 | c = count; | ||
1003 | |||
1004 | DEBUGWRITE(printk(KERN_DEBUG "w op %08lX fop %08lX c %lu\n", | ||
1005 | outp, free_outp, c)); | ||
1006 | if (copy_from_user((void *)free_outp, buf, c)) | ||
1007 | return -EFAULT; | ||
1008 | |||
1009 | if (c != count) { | ||
1010 | buf += c; | ||
1011 | c1 = count - c; | ||
1012 | DEBUGWRITE(printk(KERN_DEBUG "w2 fi %lu c %lu c1 %lu\n", | ||
1013 | free_outp-out_buffer, c, c1)); | ||
1014 | if (copy_from_user((void *)out_buffer, buf, c1)) | ||
1015 | return -EFAULT; | ||
1016 | } | ||
1017 | local_irq_save(flags); | ||
1018 | port->out_count += count; | ||
1019 | local_irq_restore(flags); | ||
1020 | |||
1021 | /* Make sure transmitter/receiver is running */ | ||
1022 | if (!port->started) { | ||
1023 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, | ||
1024 | running); | ||
1025 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, | ||
1026 | enable); | ||
1027 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, | ||
1028 | enable); | ||
1029 | port->started = 1; | ||
1030 | } | ||
1031 | |||
1032 | *port->ctrl_data = port->ctrl_data_shadow; | ||
1033 | |||
1034 | if (file->f_flags & O_NONBLOCK) { | ||
1035 | local_irq_save(flags); | ||
1036 | if (!port->tr_running) { | ||
1037 | if (!port->use_dma) { | ||
1038 | /* Start sender by writing data */ | ||
1039 | send_word(port); | ||
1040 | /* and enable transmitter ready IRQ */ | ||
1041 | *R_IRQ_MASK1_SET = 1 << | ||
1042 | port->transmitter_ready_bit; | ||
1043 | } else | ||
1044 | start_dma(port, | ||
1045 | (unsigned char *volatile)port->outp, c); | ||
1046 | } | ||
1047 | local_irq_restore(flags); | ||
1048 | DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu NB\n", | ||
1049 | port->port_nbr, count)); | ||
1050 | return count; | ||
1051 | } | ||
1052 | |||
1053 | /* Sleep until all sent */ | ||
1054 | add_wait_queue(&port->out_wait_q, &wait); | ||
1055 | set_current_state(TASK_INTERRUPTIBLE); | ||
1056 | local_irq_save(flags); | ||
1057 | if (!port->tr_running) { | ||
1058 | if (!port->use_dma) { | ||
1059 | /* Start sender by writing data */ | ||
1060 | send_word(port); | ||
1061 | /* and enable transmitter ready IRQ */ | ||
1062 | *R_IRQ_MASK1_SET = 1 << port->transmitter_ready_bit; | ||
1063 | } else | ||
1064 | start_dma(port, port->outp, c); | ||
1065 | } | ||
1066 | local_irq_restore(flags); | ||
1067 | schedule(); | ||
1068 | set_current_state(TASK_RUNNING); | ||
1069 | remove_wait_queue(&port->out_wait_q, &wait); | ||
1070 | if (signal_pending(current)) | ||
1071 | return -EINTR; | ||
1072 | |||
1073 | DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu\n", port->port_nbr, count)); | ||
1074 | return count; | ||
1075 | } | ||
1076 | |||
1077 | static ssize_t sync_serial_read(struct file *file, char *buf, | ||
1078 | size_t count, loff_t *ppos) | ||
1079 | { | ||
1080 | int dev = MINOR(file->f_dentry->d_inode->i_rdev); | ||
1081 | int avail; | ||
1082 | struct sync_port *port; | ||
1083 | unsigned char *start; | ||
1084 | unsigned char *end; | ||
1085 | unsigned long flags; | ||
1086 | |||
1087 | if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) { | ||
1088 | DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); | ||
1089 | return -ENODEV; | ||
1090 | } | ||
1091 | port = &ports[dev]; | ||
1092 | |||
1093 | DEBUGREAD(printk(KERN_DEBUG "R%d c %d ri %lu wi %lu /%lu\n", | ||
1094 | dev, count, port->readp - port->flip, | ||
1095 | port->writep - port->flip, port->in_buffer_size)); | ||
1096 | |||
1097 | if (!port->started) { | ||
1098 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, | ||
1099 | running); | ||
1100 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, | ||
1101 | enable); | ||
1102 | SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, | ||
1103 | enable); | ||
1104 | port->started = 1; | ||
1105 | } | ||
1106 | *port->ctrl_data = port->ctrl_data_shadow; | ||
1107 | |||
1108 | /* Calculate number of available bytes */ | ||
1109 | /* Save pointers to avoid that they are modified by interrupt */ | ||
1110 | local_irq_save(flags); | ||
1111 | start = (unsigned char *)port->readp; /* cast away volatile */ | ||
1112 | end = (unsigned char *)port->writep; /* cast away volatile */ | ||
1113 | local_irq_restore(flags); | ||
1114 | while (start == end && !port->full) { | ||
1115 | /* No data */ | ||
1116 | if (file->f_flags & O_NONBLOCK) | ||
1117 | return -EAGAIN; | ||
1118 | |||
1119 | interruptible_sleep_on(&port->in_wait_q); | ||
1120 | if (signal_pending(current)) | ||
1121 | return -EINTR; | ||
1122 | |||
1123 | local_irq_save(flags); | ||
1124 | start = (unsigned char *)port->readp; /* cast away volatile */ | ||
1125 | end = (unsigned char *)port->writep; /* cast away volatile */ | ||
1126 | local_irq_restore(flags); | ||
1127 | } | ||
1128 | |||
1129 | /* Lazy read, never return wrapped data. */ | ||
1130 | if (port->full) | ||
1131 | avail = port->in_buffer_size; | ||
1132 | else if (end > start) | ||
1133 | avail = end - start; | ||
1134 | else | ||
1135 | avail = port->flip + port->in_buffer_size - start; | ||
1136 | |||
1137 | count = count > avail ? avail : count; | ||
1138 | if (copy_to_user(buf, start, count)) | ||
1139 | return -EFAULT; | ||
1140 | /* Disable interrupts while updating readp */ | ||
1141 | local_irq_save(flags); | ||
1142 | port->readp += count; | ||
1143 | if (port->readp >= port->flip + port->in_buffer_size) /* Wrap? */ | ||
1144 | port->readp = port->flip; | ||
1145 | port->full = 0; | ||
1146 | local_irq_restore(flags); | ||
1147 | DEBUGREAD(printk(KERN_DEBUG "r %d\n", count)); | ||
1148 | return count; | ||
1149 | } | ||
1150 | |||
1151 | static void send_word(struct sync_port *port) | ||
1152 | { | ||
1153 | switch (IO_EXTRACT(R_SYNC_SERIAL1_CTRL, wordsize, | ||
1154 | port->ctrl_data_shadow)) { | ||
1155 | case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit): | ||
1156 | port->out_count--; | ||
1157 | *port->data_out = *port->outp++; | ||
1158 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | ||
1159 | port->outp = port->out_buffer; | ||
1160 | break; | ||
1161 | case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit): | ||
1162 | { | ||
1163 | int data = (*port->outp++) << 8; | ||
1164 | data |= *port->outp++; | ||
1165 | port->out_count -= 2; | ||
1166 | *port->data_out = data; | ||
1167 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | ||
1168 | port->outp = port->out_buffer; | ||
1169 | break; | ||
1170 | } | ||
1171 | case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit): | ||
1172 | port->out_count -= 2; | ||
1173 | *port->data_out = *(unsigned short *)port->outp; | ||
1174 | port->outp += 2; | ||
1175 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | ||
1176 | port->outp = port->out_buffer; | ||
1177 | break; | ||
1178 | case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit): | ||
1179 | port->out_count -= 3; | ||
1180 | *port->data_out = *(unsigned int *)port->outp; | ||
1181 | port->outp += 3; | ||
1182 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | ||
1183 | port->outp = port->out_buffer; | ||
1184 | break; | ||
1185 | case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit): | ||
1186 | port->out_count -= 4; | ||
1187 | *port->data_out = *(unsigned int *)port->outp; | ||
1188 | port->outp += 4; | ||
1189 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | ||
1190 | port->outp = port->out_buffer; | ||
1191 | break; | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | |||
1196 | static void start_dma(struct sync_port *port, const char *data, int count) | ||
1197 | { | ||
1198 | port->tr_running = 1; | ||
1199 | port->out_descr.hw_len = 0; | ||
1200 | port->out_descr.next = 0; | ||
1201 | port->out_descr.ctrl = d_eol | d_eop; /* No d_wait to avoid glitches */ | ||
1202 | port->out_descr.sw_len = count; | ||
1203 | port->out_descr.buf = virt_to_phys(data); | ||
1204 | port->out_descr.status = 0; | ||
1205 | |||
1206 | *port->output_dma_first = virt_to_phys(&port->out_descr); | ||
1207 | *port->output_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start); | ||
1208 | DEBUGTXINT(printk(KERN_DEBUG "dma %08lX c %d\n", | ||
1209 | (unsigned long)data, count)); | ||
1210 | } | ||
1211 | |||
1212 | static void start_dma_in(struct sync_port *port) | ||
1213 | { | ||
1214 | int i; | ||
1215 | unsigned long buf; | ||
1216 | port->writep = port->flip; | ||
1217 | |||
1218 | if (port->writep > port->flip + port->in_buffer_size) { | ||
1219 | panic("Offset too large in sync serial driver\n"); | ||
1220 | return; | ||
1221 | } | ||
1222 | buf = virt_to_phys(port->in_buffer); | ||
1223 | for (i = 0; i < NUM_IN_DESCR; i++) { | ||
1224 | port->in_descr[i].sw_len = port->inbufchunk; | ||
1225 | port->in_descr[i].ctrl = d_int; | ||
1226 | port->in_descr[i].next = virt_to_phys(&port->in_descr[i+1]); | ||
1227 | port->in_descr[i].buf = buf; | ||
1228 | port->in_descr[i].hw_len = 0; | ||
1229 | port->in_descr[i].status = 0; | ||
1230 | port->in_descr[i].fifo_len = 0; | ||
1231 | buf += port->inbufchunk; | ||
1232 | prepare_rx_descriptor(&port->in_descr[i]); | ||
1233 | } | ||
1234 | /* Link the last descriptor to the first */ | ||
1235 | port->in_descr[i-1].next = virt_to_phys(&port->in_descr[0]); | ||
1236 | port->in_descr[i-1].ctrl |= d_eol; | ||
1237 | port->next_rx_desc = &port->in_descr[0]; | ||
1238 | port->prev_rx_desc = &port->in_descr[NUM_IN_DESCR - 1]; | ||
1239 | *port->input_dma_first = virt_to_phys(port->next_rx_desc); | ||
1240 | *port->input_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start); | ||
1241 | } | ||
1242 | |||
1243 | #ifdef SYNC_SER_DMA | ||
1244 | static irqreturn_t tr_interrupt(int irq, void *dev_id) | ||
1245 | { | ||
1246 | unsigned long ireg = *R_IRQ_MASK2_RD; | ||
1247 | struct etrax_dma_descr *descr; | ||
1248 | unsigned int sentl; | ||
1249 | int handled = 0; | ||
1250 | int i; | ||
1251 | |||
1252 | for (i = 0; i < NUMBER_OF_PORTS; i++) { | ||
1253 | struct sync_port *port = &ports[i]; | ||
1254 | if (!port->enabled || !port->use_dma) | ||
1255 | continue; | ||
1256 | |||
1257 | /* IRQ active for the port? */ | ||
1258 | if (!(ireg & (1 << port->output_dma_bit))) | ||
1259 | continue; | ||
1260 | |||
1261 | handled = 1; | ||
1262 | |||
1263 | /* Clear IRQ */ | ||
1264 | *port->output_dma_clr_irq = | ||
1265 | IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do) | | ||
1266 | IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do); | ||
1267 | |||
1268 | descr = &port->out_descr; | ||
1269 | if (!(descr->status & d_stop)) | ||
1270 | sentl = descr->sw_len; | ||
1271 | else | ||
1272 | /* Otherwise find amount of data sent here */ | ||
1273 | sentl = descr->hw_len; | ||
1274 | |||
1275 | port->out_count -= sentl; | ||
1276 | port->outp += sentl; | ||
1277 | if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) | ||
1278 | port->outp = port->out_buffer; | ||
1279 | if (port->out_count) { | ||
1280 | int c = port->out_buffer + OUT_BUFFER_SIZE - port->outp; | ||
1281 | if (c > port->out_count) | ||
1282 | c = port->out_count; | ||
1283 | DEBUGTXINT(printk(KERN_DEBUG | ||
1284 | "tx_int DMAWRITE %i %i\n", sentl, c)); | ||
1285 | start_dma(port, port->outp, c); | ||
1286 | } else { | ||
1287 | DEBUGTXINT(printk(KERN_DEBUG | ||
1288 | "tx_int DMA stop %i\n", sentl)); | ||
1289 | port->tr_running = 0; | ||
1290 | } | ||
1291 | /* wake up the waiting process */ | ||
1292 | wake_up_interruptible(&port->out_wait_q); | ||
1293 | } | ||
1294 | return IRQ_RETVAL(handled); | ||
1295 | } /* tr_interrupt */ | ||
1296 | |||
1297 | static irqreturn_t rx_interrupt(int irq, void *dev_id) | ||
1298 | { | ||
1299 | unsigned long ireg = *R_IRQ_MASK2_RD; | ||
1300 | int i; | ||
1301 | int handled = 0; | ||
1302 | |||
1303 | for (i = 0; i < NUMBER_OF_PORTS; i++) { | ||
1304 | struct sync_port *port = &ports[i]; | ||
1305 | |||
1306 | if (!port->enabled || !port->use_dma) | ||
1307 | continue; | ||
1308 | |||
1309 | if (!(ireg & (1 << port->input_dma_descr_bit))) | ||
1310 | continue; | ||
1311 | |||
1312 | /* Descriptor interrupt */ | ||
1313 | handled = 1; | ||
1314 | while (*port->input_dma_descr != | ||
1315 | virt_to_phys(port->next_rx_desc)) { | ||
1316 | if (port->writep + port->inbufchunk > port->flip + | ||
1317 | port->in_buffer_size) { | ||
1318 | int first_size = port->flip + | ||
1319 | port->in_buffer_size - port->writep; | ||
1320 | memcpy(port->writep, | ||
1321 | phys_to_virt(port->next_rx_desc->buf), | ||
1322 | first_size); | ||
1323 | memcpy(port->flip, | ||
1324 | phys_to_virt(port->next_rx_desc->buf + | ||
1325 | first_size), | ||
1326 | port->inbufchunk - first_size); | ||
1327 | port->writep = port->flip + | ||
1328 | port->inbufchunk - first_size; | ||
1329 | } else { | ||
1330 | memcpy(port->writep, | ||
1331 | phys_to_virt(port->next_rx_desc->buf), | ||
1332 | port->inbufchunk); | ||
1333 | port->writep += port->inbufchunk; | ||
1334 | if (port->writep >= port->flip | ||
1335 | + port->in_buffer_size) | ||
1336 | port->writep = port->flip; | ||
1337 | } | ||
1338 | if (port->writep == port->readp) | ||
1339 | port->full = 1; | ||
1340 | prepare_rx_descriptor(port->next_rx_desc); | ||
1341 | port->next_rx_desc->ctrl |= d_eol; | ||
1342 | port->prev_rx_desc->ctrl &= ~d_eol; | ||
1343 | port->prev_rx_desc = phys_to_virt((unsigned) | ||
1344 | port->next_rx_desc); | ||
1345 | port->next_rx_desc = phys_to_virt((unsigned) | ||
1346 | port->next_rx_desc->next); | ||
1347 | /* Wake up the waiting process */ | ||
1348 | wake_up_interruptible(&port->in_wait_q); | ||
1349 | *port->input_dma_cmd = IO_STATE(R_DMA_CH1_CMD, | ||
1350 | cmd, restart); | ||
1351 | /* DMA has reached end of descriptor */ | ||
1352 | *port->input_dma_clr_irq = IO_STATE(R_DMA_CH0_CLR_INTR, | ||
1353 | clr_descr, do); | ||
1354 | } | ||
1355 | } | ||
1356 | return IRQ_RETVAL(handled); | ||
1357 | } /* rx_interrupt */ | ||
1358 | #endif /* SYNC_SER_DMA */ | ||
1359 | |||
1360 | #ifdef SYNC_SER_MANUAL | ||
1361 | static irqreturn_t manual_interrupt(int irq, void *dev_id) | ||
1362 | { | ||
1363 | int i; | ||
1364 | int handled = 0; | ||
1365 | |||
1366 | for (i = 0; i < NUMBER_OF_PORTS; i++) { | ||
1367 | struct sync_port *port = &ports[i]; | ||
1368 | |||
1369 | if (!port->enabled || port->use_dma) | ||
1370 | continue; | ||
1371 | |||
1372 | /* Data received? */ | ||
1373 | if (*R_IRQ_MASK1_RD & (1 << port->data_avail_bit)) { | ||
1374 | handled = 1; | ||
1375 | /* Read data */ | ||
1376 | switch (port->ctrl_data_shadow & | ||
1377 | IO_MASK(R_SYNC_SERIAL1_CTRL, wordsize)) { | ||
1378 | case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit): | ||
1379 | *port->writep++ = | ||
1380 | *(volatile char *)port->data_in; | ||
1381 | break; | ||
1382 | case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit): | ||
1383 | { | ||
1384 | int data = *(unsigned short *)port->data_in; | ||
1385 | *port->writep = (data & 0x0ff0) >> 4; | ||
1386 | *(port->writep + 1) = data & 0x0f; | ||
1387 | port->writep += 2; | ||
1388 | break; | ||
1389 | } | ||
1390 | case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit): | ||
1391 | *(unsigned short *)port->writep = | ||
1392 | *(volatile unsigned short *)port->data_in; | ||
1393 | port->writep += 2; | ||
1394 | break; | ||
1395 | case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit): | ||
1396 | *(unsigned int *)port->writep = *port->data_in; | ||
1397 | port->writep += 3; | ||
1398 | break; | ||
1399 | case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit): | ||
1400 | *(unsigned int *)port->writep = *port->data_in; | ||
1401 | port->writep += 4; | ||
1402 | break; | ||
1403 | } | ||
1404 | |||
1405 | /* Wrap? */ | ||
1406 | if (port->writep >= port->flip + port->in_buffer_size) | ||
1407 | port->writep = port->flip; | ||
1408 | if (port->writep == port->readp) { | ||
1409 | /* Receive buffer overrun, discard oldest */ | ||
1410 | port->readp++; | ||
1411 | /* Wrap? */ | ||
1412 | if (port->readp >= port->flip + | ||
1413 | port->in_buffer_size) | ||
1414 | port->readp = port->flip; | ||
1415 | } | ||
1416 | if (sync_data_avail(port) >= port->inbufchunk) { | ||
1417 | /* Wake up application */ | ||
1418 | wake_up_interruptible(&port->in_wait_q); | ||
1419 | } | ||
1420 | } | ||
1421 | |||
1422 | /* Transmitter ready? */ | ||
1423 | if (*R_IRQ_MASK1_RD & (1 << port->transmitter_ready_bit)) { | ||
1424 | if (port->out_count > 0) { | ||
1425 | /* More data to send */ | ||
1426 | send_word(port); | ||
1427 | } else { | ||
1428 | /* Transmission finished */ | ||
1429 | /* Turn off IRQ */ | ||
1430 | *R_IRQ_MASK1_CLR = 1 << | ||
1431 | port->transmitter_ready_bit; | ||
1432 | /* Wake up application */ | ||
1433 | wake_up_interruptible(&port->out_wait_q); | ||
1434 | } | ||
1435 | } | ||
1436 | } | ||
1437 | return IRQ_RETVAL(handled); | ||
1438 | } | ||
1439 | #endif | ||
1440 | |||
1441 | module_init(etrax_sync_serial_init); | ||