sam3n spi: revert to "end of transmit" interrupt instead of "tx buffer empty",
[bertos.git] / bertos / cpu / cortex-m3 / drv / ser_sam3.c
index be0f9642bef5949f9c503f7a4961e227ed41da42..0c5f8c3988b5124767cb833a581859f2abf663c1 100644 (file)
@@ -35,6 +35,7 @@
  *
  *
  * \author Daniele Basile <asterix@develer.com>
+ * \author Stefano Fedrigo <aleph@develer.com>
  */
 
 #include "hw/hw_ser.h"  /* Required for bus macros overrides */
        * Default TXINIT macro - invoked in spi_init()
        * The default is no action.
        */
-       #define SER_SPI0_BUS_TXINIT do { \
-               /* Disable PIO on SPI pins */ \
-               PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO); \
-       } while (0)
+       #if CPU_CM3_AT91SAM3
+               #define SER_SPI0_BUS_TXINIT do { \
+                       /* Disable PIO on SPI pins */ \
+                       PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO); \
+                       /* PIO is peripheral A */ \
+                       PIOA_ABCDSR1 &= ~(BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO)); \
+                       PIOA_ABCDSR2 &= ~(BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO)); \
+               } while (0)
+       #else
+               #define SER_SPI0_BUS_TXINIT do { \
+                       /* Disable PIO on SPI pins */ \
+                       PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO); \
+               } while (0)
+       #endif
 #endif
 
 #ifndef SER_SPI0_BUS_TXCLOSE
@@ -349,8 +360,8 @@ static void uart0_init(
 
        SER_UART0_BUS_TXINIT;
 
-       sysirq_setPriority(US0_ID, SERIRQ_PRIORITY);
-       sysirq_setHandler(US0_ID, uart0_irq_dispatcher);
+       sysirq_setPriority(INT_US0, SERIRQ_PRIORITY);
+       sysirq_setHandler(INT_US0, uart0_irq_dispatcher);
 
        SER_STROBE_INIT;
 }
@@ -439,8 +450,8 @@ static void uart1_init(
 
        SER_UART1_BUS_TXINIT;
 
-       sysirq_setPriority(US1_ID, SERIRQ_PRIORITY);
-       sysirq_setHandler(US1_ID, uart1_irq_dispatcher);
+       sysirq_setPriority(INT_US1, SERIRQ_PRIORITY);
+       sysirq_setHandler(INT_US1, uart1_irq_dispatcher);
 
        SER_STROBE_INIT;
 }
@@ -525,19 +536,21 @@ static void spi0_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struc
         * Set SPI mode.
         * At reset clock division factor is set to 0, that is
         * *forbidden*. Set SPI clock to minimum to keep it valid.
+        * Set all possible chip select registers in case user manually
+        * change CPS field in SPI_MR.
         */
        SPI0_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI0_CSR1 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI0_CSR2 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI0_CSR3 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
 
        /* Disable all irqs */
        SPI0_IDR = 0xFFFFFFFF;
 
-       sysirq_setPriority(SPI0_ID, SERIRQ_PRIORITY);
-       sysirq_setHandler(SPI0_ID, spi0_irq_handler);
+       //sysirq_setPriority(INT_SPI0, SERIRQ_PRIORITY);
+       sysirq_setHandler(INT_SPI0, spi0_irq_handler);
        PMC_PCER = BV(SPI0_ID);
 
-       /* Enable interrupt on tx buffer empty */
-       SPI0_IER = BV(SPI_TXEMPTY);
-
        /* Enable SPI */
        SPI0_CR = BV(SPI_SPIEN);
 
@@ -567,6 +580,8 @@ static void spi0_starttx(struct SerialHardware *_hw)
        {
                hw->sending = true;
                SPI0_TDR = fifo_pop(&ser_handles[SER_SPI0]->txfifo);
+               /* Enable interrupt on tx buffer empty */
+               SPI0_IER = BV(SPI_TXEMPTY);
        }
 
        IRQ_RESTORE(flags);
@@ -599,19 +614,21 @@ static void spi1_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struc
         * Set SPI mode.
         * At reset clock division factor is set to 0, that is
         * *forbidden*. Set SPI clock to minimum to keep it valid.
+        * Set all possible chip select registers in case user manually
+        * change chip select.
         */
        SPI1_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI1_CSR1 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI1_CSR2 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
+       SPI1_CSR3 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
 
        /* Disable all SPI irqs */
        SPI1_IDR = 0xFFFFFFFF;
 
-       sysirq_setPriority(SPI1_ID, SERIRQ_PRIORITY);
-       sysirq_setHandler(SPI1_ID, spi1_irq_dispatcher);
+       sysirq_setPriority(INT_SPI1, SERIRQ_PRIORITY);
+       sysirq_setHandler(INT_SPI1, spi1_irq_dispatcher);
        PMC_PCER = BV(SPI1_ID);
 
-       /* Enable interrupt on tx buffer empty */
-       SPI1_IER = BV(SPI_TXEMPTY);
-
        /* Enable SPI */
        SPI1_CR = BV(SPI_SPIEN);
 
@@ -641,6 +658,8 @@ static void spi1_starttx(struct SerialHardware *_hw)
        {
                hw->sending = true;
                SPI1_TDR = fifo_pop(&ser_handles[SER_SPI1]->txfifo);
+               /* Enable interrupt on tx buffer empty */
+               SPI1_IER = BV(SPI_TXEMPTY);
        }
 
        IRQ_RESTORE(flags);
@@ -922,7 +941,11 @@ static DECLARE_ISR(spi0_irq_handler)
        if (!fifo_isempty(&ser_handles[SER_SPI0]->txfifo))
                SPI0_TDR = fifo_pop(&ser_handles[SER_SPI0]->txfifo);
        else
+       {
                UARTDescs[SER_SPI0].sending = false;
+               /* Disable interrupt on tx buffer empty */
+               SPI0_IDR = BV(SPI_TXEMPTY);
+       }
 
        SER_INT_ACK;
 
@@ -952,7 +975,11 @@ static DECLARE_ISR(spi1_irq_handler)
        if (!fifo_isempty(&ser_handles[SER_SPI1]->txfifo))
                SPI1_TDR = fifo_pop(&ser_handles[SER_SPI1]->txfifo);
        else
+       {
                UARTDescs[SER_SPI1].sending = false;
+               /* Disable interrupt on tx buffer empty */
+               SPI1_IDR = BV(SPI_TXEMPTY);
+       }
 
        SER_INT_ACK;