Refactor BeRTOS to be in his own directory.
[bertos.git] / cpu / arm / drv / ser_at91.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
30  * Copyright 2000 Bernardo Innocenti <bernie@codewiz.org>
31  *
32  * -->
33  *
34  * \brief ARM UART and SPI I/O driver
35  *
36  *
37  * \version $Id: ser_at91.c 20881 2008-03-04 14:07:02Z batt $
38  * \author Daniele Basile <asterix@develer.com>
39  */
40
41 #include <io/arm.h>
42
43 #include <cpu/attr.h>
44 #include <drv/ser.h>
45 #include <drv/ser_p.h>
46
47 #include <hw/hw_ser.h>  /* Required for bus macros overrides */
48 #include <hw/hw_cpu.h>  /* CLOCK_FREQ */
49
50 #include <mware/fifobuf.h>
51 #include <cfg/debug.h>
52
53 #include <appconfig.h>
54
55 #define SERIRQ_PRIORITY 4 ///< default priority for serial irqs.
56
57 /**
58  * \name Overridable serial bus hooks
59  *
60  * These can be redefined in hw.h to implement
61  * special bus policies such as half-duplex, 485, etc.
62  *
63  *
64  * \code
65  *  TXBEGIN      TXCHAR      TXEND  TXOFF
66  *    |   __________|__________ |     |
67  *    |   |   |   |   |   |   | |     |
68  *    v   v   v   v   v   v   v v     v
69  * ______  __  __  __  __  __  __  ________________
70  *       \/  \/  \/  \/  \/  \/  \/
71  * ______/\__/\__/\__/\__/\__/\__/
72  *
73  * \endcode
74  *
75  * \{
76  */
77
78 #ifndef SER_UART0_BUS_TXINIT
79         /**
80          * Default TXINIT macro - invoked in uart0_init()
81          *
82          * - Disable GPIO on USART0 tx/rx pins
83          */
84         #if !CPU_ARM_AT91SAM7S256 && !CPU_ARM_AT91SAM7X256 && !CPU_ARM_AT91SAM7X128
85                 #warning Check USART0 pins!
86         #endif
87         #define SER_UART0_BUS_TXINIT do { \
88                 PIOA_PDR = BV(RXD0) | BV(TXD0); \
89         } while (0)
90
91 #endif
92
93 #ifndef SER_UART0_BUS_TXBEGIN
94         /**
95          * Invoked before starting a transmission
96          */
97         #define SER_UART0_BUS_TXBEGIN
98 #endif
99
100 #ifndef SER_UART0_BUS_TXCHAR
101         /**
102          * Invoked to send one character.
103          */
104         #define SER_UART0_BUS_TXCHAR(c) do { \
105                 US0_THR = (c); \
106         } while (0)
107 #endif
108
109 #ifndef SER_UART0_BUS_TXEND
110         /**
111          * Invoked as soon as the txfifo becomes empty
112          */
113         #define SER_UART0_BUS_TXEND
114 #endif
115
116 /* End USART0 macros */
117
118 #ifndef SER_UART1_BUS_TXINIT
119         /**
120          * Default TXINIT macro - invoked in uart1_init()
121          *
122          * - Disable GPIO on USART1 tx/rx pins
123          */
124         #if !CPU_ARM_AT91SAM7S256 && !CPU_ARM_AT91SAM7X256 && !CPU_ARM_AT91SAM7X128
125                 #warning Check USART1 pins!
126         #endif
127         #define SER_UART1_BUS_TXINIT do { \
128                 PIOA_PDR = BV(RXD1) | BV(TXD1); \
129         } while (0)
130
131 #endif
132
133 #ifndef SER_UART1_BUS_TXBEGIN
134         /**
135          * Invoked before starting a transmission
136          */
137         #define SER_UART1_BUS_TXBEGIN
138 #endif
139
140 #ifndef SER_UART1_BUS_TXCHAR
141         /**
142          * Invoked to send one character.
143          */
144         #define SER_UART1_BUS_TXCHAR(c) do { \
145                 US1_THR = (c); \
146         } while (0)
147 #endif
148
149 #ifndef SER_UART1_BUS_TXEND
150         /**
151          * Invoked as soon as the txfifo becomes empty
152          */
153         #define SER_UART1_BUS_TXEND
154 #endif
155
156 /**
157 * \name Overridable SPI hooks
158 *
159 * These can be redefined in hw.h to implement
160 * special bus policies such as slave select pin handling, etc.
161 *
162 * \{
163 */
164
165 #ifndef SER_SPI0_BUS_TXINIT
166         /**
167         * Default TXINIT macro - invoked in spi_init()
168         * The default is no action.
169         */
170         #define SER_SPI0_BUS_TXINIT
171 #endif
172
173 #ifndef SER_SPI0_BUS_TXCLOSE
174         /**
175         * Invoked after the last character has been transmitted.
176         * The default is no action.
177         */
178         #define SER_SPI0_BUS_TXCLOSE
179 #endif
180
181 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
182
183         #ifndef SER_SPI1_BUS_TXINIT
184                 /**
185                 * Default TXINIT macro - invoked in spi_init()
186                 * The default is no action.
187                 */
188                 #define SER_SPI1_BUS_TXINIT
189         #endif
190
191         #ifndef SER_SPI1_BUS_TXCLOSE
192                 /**
193                 * Invoked after the last character has been transmitted.
194                 * The default is no action.
195                 */
196                 #define SER_SPI1_BUS_TXCLOSE
197         #endif
198 #endif
199 /*\}*/
200
201
202 /**
203  * \def CONFIG_SER_STROBE
204  *
205  * This is a debug facility that can be used to
206  * monitor SER interrupt activity on an external pin.
207  *
208  * To use strobes, redefine the macros SER_STROBE_ON,
209  * SER_STROBE_OFF and SER_STROBE_INIT and set
210  * CONFIG_SER_STROBE to 1.
211  */
212 #if !defined(CONFIG_SER_STROBE) || !CONFIG_SER_STROBE
213         #define SER_STROBE_ON    do {/*nop*/} while(0)
214         #define SER_STROBE_OFF   do {/*nop*/} while(0)
215         #define SER_STROBE_INIT  do {/*nop*/} while(0)
216 #endif
217
218
219 /* From the high-level serial driver */
220 extern struct Serial ser_handles[SER_CNT];
221
222 /* TX and RX buffers */
223 static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE];
224 static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE];
225
226 static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE];
227 static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE];
228
229 static unsigned char spi0_txbuffer[CONFIG_SPI0_TXBUFSIZE];
230 static unsigned char spi0_rxbuffer[CONFIG_SPI0_RXBUFSIZE];
231 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
232 static unsigned char spi1_txbuffer[CONFIG_SPI1_TXBUFSIZE];
233 static unsigned char spi1_rxbuffer[CONFIG_SPI1_RXBUFSIZE];
234 #endif
235
236 /**
237  * Internal hardware state structure
238  *
239  * The \a sending variable is true while the transmission
240  * interrupt is retriggering itself.
241  *
242  * For the USARTs the \a sending flag is useful for taking specific
243  * actions before sending a burst of data, at the start of a trasmission
244  * but not before every char sent.
245  *
246  * For the SPI, this flag is necessary because the SPI sends and receives
247  * bytes at the same time and the SPI IRQ is unique for send/receive.
248  * The only way to start transmission is to write data in SPDR (this
249  * is done by spi_starttx()). We do this *only* if a transfer is
250  * not already started.
251  */
252 struct ArmSerial
253 {
254         struct SerialHardware hw;
255         volatile bool sending;
256 };
257
258
259 /*
260  * These are to trick GCC into *not* using absolute addressing mode
261  * when accessing ser_handles, which is very expensive.
262  *
263  * Accessing through these pointers generates much shorter
264  * (and hopefully faster) code.
265  */
266 struct Serial *ser_uart0 = &ser_handles[SER_UART0];
267 struct Serial *ser_uart1 = &ser_handles[SER_UART1];
268
269 struct Serial *ser_spi0 = &ser_handles[SER_SPI0];
270 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
271 struct Serial *ser_spi1 = &ser_handles[SER_SPI1];
272 #endif
273
274 static void uart0_irq_dispatcher(void);
275 static void uart1_irq_dispatcher(void);
276 static void spi0_irq_handler(void);
277 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
278 static void spi1_irq_handler(void);
279 #endif
280 /*
281  * Callbacks for USART0
282  */
283 static void uart0_init(
284         UNUSED_ARG(struct SerialHardware *, _hw),
285         UNUSED_ARG(struct Serial *, ser))
286 {
287         US0_IDR = 0xFFFFFFFF;
288         /* Set the vector. */
289         AIC_SVR(US0_ID) = uart0_irq_dispatcher;
290         /* Initialize to edge triggered with defined priority. */
291         AIC_SMR(US0_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED | SERIRQ_PRIORITY;
292         PMC_PCER = BV(US0_ID);
293
294         /*
295          * - Reset USART0
296          * - Set serial param: mode Normal, 8bit data, 1bit stop, parity none
297          * - Enable both the receiver and the transmitter
298          * - Enable only the RX complete interrupt
299          */
300         US0_CR = BV(US_RSTRX) | BV(US_RSTTX);
301         US0_MR = US_CHMODE_NORMAL | US_CHRL_8 | US_NBSTOP_1 | US_PAR_NO;
302         US0_CR = BV(US_RXEN) | BV(US_TXEN);
303         US0_IER = BV(US_RXRDY);
304
305         SER_UART0_BUS_TXINIT;
306
307         /* Enable the USART IRQ */
308         AIC_IECR = BV(US0_ID);
309
310         SER_STROBE_INIT;
311 }
312
313 static void uart0_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
314 {
315         US0_CR = BV(US_RSTRX) | BV(US_RSTTX) | BV(US_RXDIS) | BV(US_TXDIS) | BV(US_RSTSTA);
316 }
317
318 static void uart0_enabletxirq(struct SerialHardware *_hw)
319 {
320         struct ArmSerial *hw = (struct ArmSerial *)_hw;
321
322         /*
323          * WARNING: racy code here!  The tx interrupt sets hw->sending to false
324          * when it runs with an empty fifo.  The order of statements in the
325          * if-block matters.
326          */
327         if (!hw->sending)
328         {
329                 hw->sending = true;
330                 /*
331                  * - Enable the transmitter
332                  * - Enable TX empty interrupt
333                  */
334                 SER_UART0_BUS_TXBEGIN;
335                 US0_IER = BV(US_TXEMPTY);
336         }
337 }
338
339 static void uart0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
340 {
341         /* Compute baud-rate period */
342         US0_BRGR = CLOCK_FREQ / (16 * rate);
343         //DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
344 }
345
346 static void uart0_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
347 {
348         US0_MR &= ~US_PAR_MASK;
349         /* Set UART parity */
350         switch(parity)
351         {
352                 case SER_PARITY_NONE:
353                 {
354                         /* Parity none. */
355                         US0_MR |= US_PAR_NO;
356                         break;
357                 }
358                 case SER_PARITY_EVEN:
359                 {
360                         /* Even parity. */
361                         US0_MR |= US_PAR_EVEN;
362                         break;
363                 }
364                 case SER_PARITY_ODD:
365                 {
366                         /* Odd parity. */
367                         US0_MR |= US_PAR_ODD;
368                         break;
369                 }
370                 default:
371                         ASSERT(0);
372         }
373
374 }
375 /*
376  * Callbacks for USART1
377  */
378 static void uart1_init(
379         UNUSED_ARG(struct SerialHardware *, _hw),
380         UNUSED_ARG(struct Serial *, ser))
381 {
382         US1_IDR = 0xFFFFFFFF;
383         /* Set the vector. */
384         AIC_SVR(US1_ID) = uart1_irq_dispatcher;
385         /* Initialize to edge triggered with defined priority. */
386         AIC_SMR(US1_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED | SERIRQ_PRIORITY;
387         PMC_PCER = BV(US1_ID);
388
389         /*
390          * - Reset USART1
391          * - Set serial param: mode Normal, 8bit data, 1bit stop, parity none
392          * - Enable both the receiver and the transmitter
393          * - Enable only the RX complete interrupt
394          */
395         US1_CR = BV(US_RSTRX) | BV(US_RSTTX);
396         US1_MR = US_CHMODE_NORMAL | US_CHRL_8 | US_NBSTOP_1 | US_PAR_NO;
397         US1_CR = BV(US_RXEN) | BV(US_TXEN);
398         US1_IER = BV(US_RXRDY);
399
400         SER_UART1_BUS_TXINIT;
401
402         /* Enable the USART IRQ */
403         AIC_IECR = BV(US1_ID);
404
405         SER_STROBE_INIT;
406 }
407
408 static void uart1_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
409 {
410         US1_CR = BV(US_RSTRX) | BV(US_RSTTX) | BV(US_RXDIS) | BV(US_TXDIS) | BV(US_RSTSTA);
411 }
412
413 static void uart1_enabletxirq(struct SerialHardware *_hw)
414 {
415         struct ArmSerial *hw = (struct ArmSerial *)_hw;
416
417         /*
418          * WARNING: racy code here!  The tx interrupt sets hw->sending to false
419          * when it runs with an empty fifo.  The order of statements in the
420          * if-block matters.
421          */
422         if (!hw->sending)
423         {
424                 hw->sending = true;
425                 /*
426                  * - Enable the transmitter
427                  * - Enable TX empty interrupt
428                  */
429                 SER_UART1_BUS_TXBEGIN;
430                 US1_IER = BV(US_TXEMPTY);
431         }
432 }
433
434 static void uart1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
435 {
436         /* Compute baud-rate period */
437         US1_BRGR = CLOCK_FREQ / (16 * rate);
438         //DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
439 }
440
441 static void uart1_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
442 {
443         US1_MR &= ~US_PAR_MASK;
444         /* Set UART parity */
445         switch(parity)
446         {
447                 case SER_PARITY_NONE:
448                 {
449                         /* Parity none. */
450                         US1_MR |= US_PAR_NO;
451                         break;
452                 }
453                 case SER_PARITY_EVEN:
454                 {
455                         /* Even parity. */
456                         US1_MR |= US_PAR_EVEN;
457                         break;
458                 }
459                 case SER_PARITY_ODD:
460                 {
461                         /* Odd parity. */
462                         US1_MR |= US_PAR_ODD;
463                         break;
464                 }
465                 default:
466                         ASSERT(0);
467         }
468
469 }
470
471 /* SPI driver */
472 static void spi0_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struct Serial *, ser))
473 {
474         /* Disable PIO on SPI pins */
475         PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO);
476
477         /* Reset device */
478         SPI0_CR = BV(SPI_SWRST);
479
480         /*
481          * Set SPI to master mode, fixed peripheral select, chip select directly connected to a peripheral device,
482          * SPI clock set to MCK, mode fault detection disabled, loopback disable, NPCS0 active, Delay between CS = 0
483          */
484         SPI0_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS);
485
486         /*
487          * Set SPI mode.
488          * At reset clock division factor is set to 0, that is
489          * *forbidden*. Set SPI clock to minimum to keep it valid.
490          */
491         SPI0_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
492
493         /* Disable all irqs */
494         SPI0_IDR = 0xFFFFFFFF;
495         /* Set the vector. */
496         AIC_SVR(SPI0_ID) = spi0_irq_handler;
497         /* Initialize to edge triggered with defined priority. */
498         AIC_SMR(SPI0_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED | SERIRQ_PRIORITY;
499         /* Enable the USART IRQ */
500         AIC_IECR = BV(SPI0_ID);
501         PMC_PCER = BV(SPI0_ID);
502
503         /* Enable interrupt on tx buffer empty */
504         SPI0_IER = BV(SPI_TXEMPTY);
505
506         /* Enable SPI */
507         SPI0_CR = BV(SPI_SPIEN);
508
509
510         SER_SPI0_BUS_TXINIT;
511
512         SER_STROBE_INIT;
513 }
514
515 static void spi0_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
516 {
517         /* Disable SPI */
518         SPI0_CR = BV(SPI_SPIDIS);
519
520         /* Disable all irqs */
521         SPI0_IDR = 0xFFFFFFFF;
522
523         SER_SPI0_BUS_TXCLOSE;
524
525         /* Enable PIO on SPI pins */
526         PIOA_PER = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO);
527 }
528
529 static void spi0_starttx(struct SerialHardware *_hw)
530 {
531         struct ArmSerial *hw = (struct ArmSerial *)_hw;
532
533         cpuflags_t flags;
534         IRQ_SAVE_DISABLE(flags);
535
536         /* Send data only if the SPI is not already transmitting */
537         if (!hw->sending && !fifo_isempty(&ser_spi0->txfifo))
538         {
539                 hw->sending = true;
540                 SPI0_TDR = fifo_pop(&ser_spi0->txfifo);
541         }
542
543         IRQ_RESTORE(flags);
544 }
545
546 static void spi0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
547 {
548         SPI0_CSR0 &= ~SPI_SCBR;
549
550         ASSERT((uint8_t)DIV_ROUND(CLOCK_FREQ, rate));
551         SPI0_CSR0 |= DIV_ROUND(CLOCK_FREQ, rate) << SPI_SCBR_SHIFT;
552 }
553
554 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
555 /* SPI driver */
556 static void spi1_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struct Serial *, ser))
557 {
558         /* Disable PIO on SPI pins */
559         PIOA_PDR = BV(SPI1_SPCK) | BV(SPI1_MOSI) | BV(SPI1_MISO);
560
561         /* Reset device */
562         SPI1_CR = BV(SPI_SWRST);
563
564 /*
565          * Set SPI to master mode, fixed peripheral select, chip select directly connected to a peripheral device,
566          * SPI clock set to MCK, mode fault detection disabled, loopback disable, NPCS0 active, Delay between CS = 0
567          */
568         SPI1_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS);
569
570         /*
571          * Set SPI mode.
572          * At reset clock division factor is set to 0, that is
573          * *forbidden*. Set SPI clock to minimum to keep it valid.
574          */
575         SPI1_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
576
577         /* Disable all irqs */
578         SPI1_IDR = 0xFFFFFFFF;
579         /* Set the vector. */
580         AIC_SVR(SPI1_ID) = spi1_irq_handler;
581         /* Initialize to edge triggered with defined priority. */
582         AIC_SMR(SPI1_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED | SERIRQ_PRIORITY;
583         /* Enable the USART IRQ */
584         AIC_IECR = BV(SPI1_ID);
585         PMC_PCER = BV(SPI1_ID);
586
587         /* Enable interrupt on tx buffer empty */
588         SPI1_IER = BV(SPI_TXEMPTY);
589
590         /* Enable SPI */
591         SPI1_CR = BV(SPI_SPIEN);
592
593
594         SER_SPI1_BUS_TXINIT;
595
596         SER_STROBE_INIT;
597 }
598
599 static void spi1_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
600 {
601         /* Disable SPI */
602         SPI1_CR = BV(SPI_SPIDIS);
603
604         /* Disable all irqs */
605         SPI1_IDR = 0xFFFFFFFF;
606
607         SER_SPI1_BUS_TXCLOSE;
608
609         /* Enable PIO on SPI pins */
610         PIOA_PER = BV(SPI1_SPCK) | BV(SPI1_MOSI) | BV(SPI1_MISO);
611 }
612
613 static void spi1_starttx(struct SerialHardware *_hw)
614 {
615         struct ArmSerial *hw = (struct ArmSerial *)_hw;
616
617         cpuflags_t flags;
618         IRQ_SAVE_DISABLE(flags);
619
620         /* Send data only if the SPI is not already transmitting */
621         if (!hw->sending && !fifo_isempty(&ser_spi1->txfifo))
622         {
623                 hw->sending = true;
624                 SPI1_TDR = fifo_pop(&ser_spi1->txfifo);
625         }
626
627         IRQ_RESTORE(flags);
628 }
629
630 static void spi1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
631 {
632         SPI1_CSR0 &= ~SPI_SCBR;
633
634         ASSERT((uint8_t)DIV_ROUND(CLOCK_FREQ, rate));
635         SPI1_CSR0 |= DIV_ROUND(CLOCK_FREQ, rate) << SPI_SCBR_SHIFT;
636 }
637 #endif
638
639 static void spi_setparity(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(int, parity))
640 {
641         // nop
642 }
643
644
645 static bool tx_sending(struct SerialHardware* _hw)
646 {
647         struct ArmSerial *hw = (struct ArmSerial *)_hw;
648         return hw->sending;
649 }
650
651 // FIXME: move into compiler.h?  Ditch?
652 #if COMPILER_C99
653         #define C99INIT(name,val) .name = val
654 #elif defined(__GNUC__)
655         #define C99INIT(name,val) name: val
656 #else
657         #warning No designated initializers, double check your code
658         #define C99INIT(name,val) (val)
659 #endif
660
661 /*
662  * High-level interface data structures
663  */
664 static const struct SerialHardwareVT UART0_VT =
665 {
666         C99INIT(init, uart0_init),
667         C99INIT(cleanup, uart0_cleanup),
668         C99INIT(setBaudrate, uart0_setbaudrate),
669         C99INIT(setParity, uart0_setparity),
670         C99INIT(txStart, uart0_enabletxirq),
671         C99INIT(txSending, tx_sending),
672 };
673
674 static const struct SerialHardwareVT UART1_VT =
675 {
676         C99INIT(init, uart1_init),
677         C99INIT(cleanup, uart1_cleanup),
678         C99INIT(setBaudrate, uart1_setbaudrate),
679         C99INIT(setParity, uart1_setparity),
680         C99INIT(txStart, uart1_enabletxirq),
681         C99INIT(txSending, tx_sending),
682 };
683
684 static const struct SerialHardwareVT SPI0_VT =
685 {
686         C99INIT(init, spi0_init),
687         C99INIT(cleanup, spi0_cleanup),
688         C99INIT(setBaudrate, spi0_setbaudrate),
689         C99INIT(setParity, spi_setparity),
690         C99INIT(txStart, spi0_starttx),
691         C99INIT(txSending, tx_sending),
692 };
693 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
694 static const struct SerialHardwareVT SPI1_VT =
695 {
696         C99INIT(init, spi1_init),
697         C99INIT(cleanup, spi1_cleanup),
698         C99INIT(setBaudrate, spi1_setbaudrate),
699         C99INIT(setParity, spi_setparity),
700         C99INIT(txStart, spi1_starttx),
701         C99INIT(txSending, tx_sending),
702 };
703 #endif
704
705 static struct ArmSerial UARTDescs[SER_CNT] =
706 {
707         {
708                 C99INIT(hw, /**/) {
709                         C99INIT(table, &UART0_VT),
710                         C99INIT(txbuffer, uart0_txbuffer),
711                         C99INIT(rxbuffer, uart0_rxbuffer),
712                         C99INIT(txbuffer_size, sizeof(uart0_txbuffer)),
713                         C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)),
714                 },
715                 C99INIT(sending, false),
716         },
717         {
718                 C99INIT(hw, /**/) {
719                         C99INIT(table, &UART1_VT),
720                         C99INIT(txbuffer, uart1_txbuffer),
721                         C99INIT(rxbuffer, uart1_rxbuffer),
722                         C99INIT(txbuffer_size, sizeof(uart1_txbuffer)),
723                         C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)),
724                 },
725                 C99INIT(sending, false),
726         },
727
728         {
729                 C99INIT(hw, /**/) {
730                         C99INIT(table, &SPI0_VT),
731                         C99INIT(txbuffer, spi0_txbuffer),
732                         C99INIT(rxbuffer, spi0_rxbuffer),
733                         C99INIT(txbuffer_size, sizeof(spi0_txbuffer)),
734                         C99INIT(rxbuffer_size, sizeof(spi0_rxbuffer)),
735                 },
736                 C99INIT(sending, false),
737         },
738         #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
739         {
740                 C99INIT(hw, /**/) {
741                         C99INIT(table, &SPI1_VT),
742                         C99INIT(txbuffer, spi1_txbuffer),
743                         C99INIT(rxbuffer, spi1_rxbuffer),
744                         C99INIT(txbuffer_size, sizeof(spi1_txbuffer)),
745                         C99INIT(rxbuffer_size, sizeof(spi1_rxbuffer)),
746                 },
747                 C99INIT(sending, false),
748         }
749
750         #endif
751 };
752
753 struct SerialHardware *ser_hw_getdesc(int unit)
754 {
755         ASSERT(unit < SER_CNT);
756         return &UARTDescs[unit].hw;
757 }
758
759 /**
760  * Serial 0 TX interrupt handler
761  */
762 static void uart0_irq_tx(void)
763 {
764         SER_STROBE_ON;
765
766         struct FIFOBuffer * const txfifo = &ser_uart0->txfifo;
767
768         if (fifo_isempty(txfifo))
769         {
770                 /*
771                  * - Disable the TX empty interrupts
772                  */
773                 US0_IDR = BV(US_TXEMPTY);
774                 SER_UART0_BUS_TXEND;
775                 UARTDescs[SER_UART0].sending = false;
776         }
777         else
778         {
779                 char c = fifo_pop(txfifo);
780                 SER_UART0_BUS_TXCHAR(c);
781         }
782
783         SER_STROBE_OFF;
784 }
785
786 /**
787  * Serial 0 RX complete interrupt handler.
788  */
789 static void uart0_irq_rx(void)
790 {
791         SER_STROBE_ON;
792
793         /* Should be read before US_CRS */
794         ser_uart0->status |= US0_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
795
796         char c = US0_RHR;
797         struct FIFOBuffer * const rxfifo = &ser_uart0->rxfifo;
798
799         if (fifo_isfull(rxfifo))
800                 ser_uart0->status |= SERRF_RXFIFOOVERRUN;
801         else
802                 fifo_push(rxfifo, c);
803
804         SER_STROBE_OFF;
805 }
806
807 /**
808  * Serial IRQ dispatcher for USART0.
809  */
810 static void uart0_irq_dispatcher(void) __attribute__ ((interrupt));
811 static void uart0_irq_dispatcher(void)
812 {
813         if (US0_CSR & BV(US_RXRDY))
814                 uart0_irq_rx();
815
816         if (US0_CSR & BV(US_TXEMPTY))
817                 uart0_irq_tx();
818
819         /* Inform hw that we have served the IRQ */
820         AIC_EOICR = 0;
821 }
822
823 /**
824  * Serial 1 TX interrupt handler
825  */
826 static void uart1_irq_tx(void)
827 {
828         SER_STROBE_ON;
829
830         struct FIFOBuffer * const txfifo = &ser_uart1->txfifo;
831
832         if (fifo_isempty(txfifo))
833         {
834                 /*
835                  * - Disable the TX empty interrupts
836                  */
837                 US1_IDR = BV(US_TXEMPTY);
838                 SER_UART1_BUS_TXEND;
839                 UARTDescs[SER_UART1].sending = false;
840         }
841         else
842         {
843                 char c = fifo_pop(txfifo);
844                 SER_UART1_BUS_TXCHAR(c);
845         }
846
847         SER_STROBE_OFF;
848 }
849
850 /**
851  * Serial 1 RX complete interrupt handler.
852  */
853 static void uart1_irq_rx(void)
854 {
855         SER_STROBE_ON;
856
857         /* Should be read before US_CRS */
858         ser_uart1->status |= US1_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
859
860         char c = US1_RHR;
861         struct FIFOBuffer * const rxfifo = &ser_uart1->rxfifo;
862
863         if (fifo_isfull(rxfifo))
864                 ser_uart1->status |= SERRF_RXFIFOOVERRUN;
865         else
866                 fifo_push(rxfifo, c);
867
868         SER_STROBE_OFF;
869 }
870
871 /**
872  * Serial IRQ dispatcher for USART1.
873  */
874 static void uart1_irq_dispatcher(void) __attribute__ ((interrupt));
875 static void uart1_irq_dispatcher(void)
876 {
877         if (US1_CSR & BV(US_RXRDY))
878                 uart1_irq_rx();
879
880         if (US1_CSR & BV(US_TXEMPTY))
881                 uart1_irq_tx();
882
883         /* Inform hw that we have served the IRQ */
884         AIC_EOICR = 0;
885 }
886
887 /**
888  * SPI0 interrupt handler
889  */
890 static void spi0_irq_handler(void) __attribute__ ((interrupt));
891 static void spi0_irq_handler(void)
892 {
893         SER_STROBE_ON;
894
895         char c = SPI0_RDR;
896         /* Read incoming byte. */
897         if (!fifo_isfull(&ser_spi0->rxfifo))
898                 fifo_push(&ser_spi0->rxfifo, c);
899         /*
900          * FIXME
901         else
902                 ser_spi0->status |= SERRF_RXFIFOOVERRUN;
903         */
904
905         /* Send */
906         if (!fifo_isempty(&ser_spi0->txfifo))
907                 SPI0_TDR = fifo_pop(&ser_spi0->txfifo);
908         else
909                 UARTDescs[SER_SPI0].sending = false;
910
911         /* Inform hw that we have served the IRQ */
912         AIC_EOICR = 0;
913         SER_STROBE_OFF;
914 }
915
916
917 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
918 /**
919  * SPI1 interrupt handler
920  */
921 static void spi1_irq_handler(void) __attribute__ ((interrupt));
922 static void spi1_irq_handler(void)
923 {
924         SER_STROBE_ON;
925
926         char c = SPI1_RDR;
927         /* Read incoming byte. */
928         if (!fifo_isfull(&ser_spi1->rxfifo))
929                 fifo_push(&ser_spi1->rxfifo, c);
930         /*
931          * FIXME
932         else
933                 ser_spi1->status |= SERRF_RXFIFOOVERRUN;
934         */
935
936         /* Send */
937         if (!fifo_isempty(&ser_spi1->txfifo))
938                 SPI1_TDR = fifo_pop(&ser_spi1->txfifo);
939         else
940                 UARTDescs[SER_SPI1].sending = false;
941
942         /* Inform hw that we have served the IRQ */
943         AIC_EOICR = 0;
944         SER_STROBE_OFF;
945 }
946 #endif