Remove duplicate define. Put all phy chip specific defines in its
[bertos.git] / bertos / cpu / cortex-m3 / drv / ser_sam3.c
index 6222ece5e9180fc3bd912b1473f929a9932445e0..c330ca80acc382b9c335c82c782e4658166dbe27 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 */
@@ -90,6 +91,7 @@
        #endif
        #define SER_UART0_BUS_TXINIT do { \
                PIOA_PDR = BV(RXD0) | BV(TXD0); \
+               PIO_PERIPH_SEL(PIOA_BASE, BV(RXD0) | BV(TXD0), USART0_PERIPH); \
        } while (0)
 #endif
 
 
 /* End USART0 macros */
 
-#if !CPU_CM3_AT91SAM3U
+#if USART_PORTS > 1
 
        #ifndef SER_UART1_BUS_TXINIT
                /**
                 *
                 * - Disable GPIO on USART1 tx/rx pins
                 */
-               #if CPU_ARM_AT91
-                       #if !CPU_ARM_SAM7S_LARGE && !CPU_ARM_SAM7X
-                               #warning Check USART1 pins!
-                       #endif
-                       #define SER_UART1_BUS_TXINIT do { \
-                               PIOA_PDR = BV(RXD1) | BV(TXD1); \
-                       } while (0)
-               #elif CPU_CM3_AT91SAM3
-                       #define SER_UART1_BUS_TXINIT do { \
-                               PIOB_PDR = BV(RXD1) | BV(TXD1); \
-                       } while (0)
-               #else
-                       #error Unknown CPU
+               #if CPU_ARM_AT91 && !CPU_ARM_SAM7S_LARGE && !CPU_ARM_SAM7X
+                       #warning Check USART1 pins!
                #endif
+               #define SER_UART1_BUS_TXINIT do { \
+                       PIOA_PDR = BV(RXD1) | BV(TXD1); \
+                       PIO_PERIPH_SEL(PIOA_BASE, BV(RXD1) | BV(TXD1), USART1_PERIPH); \
+               } while (0)
        #endif
 
        #ifndef SER_UART1_BUS_TXBEGIN
        * Default TXINIT macro - invoked in spi_init()
        * The default is no action.
        */
-       #if CPU_CM3_AT91SAM3
+       #if CPU_CM3_SAM3
                #define SER_SPI0_BUS_TXINIT do { \
                        /* Disable PIO on SPI pins */ \
-                       PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO) | BV(30); \
-                       /* 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)); \
-                       /* Peripheral B for chip select for display */ \
-                       PIOA_ABCDSR1 |= BV(30); \
-                       PIOA_ABCDSR2 &= ~BV(30); \
+                       PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO); \
+                       /* SPI is peripheral A on SAM3X,A,N,S,U */ \
+                       PIO_PERIPH_SEL(PIOA_BASE, BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO), PIO_PERIPH_A); \
                } while (0)
        #else
                #define SER_SPI0_BUS_TXINIT do { \
@@ -281,7 +272,7 @@ INLINE void sysirq_setPriority(sysirq_t irq, int prio)
        AIC_EOICR = 0; \
 } while (0)
 
-#elif CPU_CM3_AT91SAM3
+#elif CPU_CM3_SAM3
 
 /** Inform hw that we have served the IRQ */
 #define SER_INT_ACK do { /* nop */ } while (0)
@@ -298,7 +289,7 @@ extern struct Serial *ser_handles[SER_CNT];
 /* TX and RX buffers */
 static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE];
 static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE];
-#if !CPU_CM3_AT91SAM3U
+#if USART_PORTS > 1
 static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE];
 static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE];
 #endif
@@ -332,7 +323,7 @@ struct ArmSerial
 };
 
 static ISR_PROTO(uart0_irq_dispatcher);
-#if !CPU_CM3_AT91SAM3U
+#if USART_PORTS > 1
 static ISR_PROTO(uart1_irq_dispatcher);
 #endif
 static ISR_PROTO(spi0_irq_handler);
@@ -347,7 +338,7 @@ static void uart0_init(
        UNUSED_ARG(struct Serial *, ser))
 {
        US0_IDR = 0xFFFFFFFF;
-       PMC_PCER = BV(US0_ID);
+       pmc_periphEnable(US0_ID);
 
        /*
         * - Reset USART0
@@ -429,6 +420,9 @@ static void uart0_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity
                        ASSERT(0);
        }
 }
+
+#if USART_PORTS > 1
+
 /*
  * Callbacks for USART1
  */
@@ -437,7 +431,7 @@ static void uart1_init(
        UNUSED_ARG(struct Serial *, ser))
 {
        US1_IDR = 0xFFFFFFFF;
-       PMC_PCER = BV(US1_ID);
+       pmc_periphEnable(US1_ID);
 
        /*
         * - Reset USART1
@@ -520,6 +514,8 @@ static void uart1_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity
        }
 }
 
+#endif /* USART_PORTS > 1 */
+
 /* SPI driver */
 static void spi0_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struct Serial *, ser))
 {
@@ -532,24 +528,26 @@ static void spi0_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struc
         * Set SPI to master mode, fixed peripheral select, chip select directly connected to a peripheral device,
         * SPI clock set to MCK, mode fault detection disabled, loopback disable, NPCS0 active, Delay between CS = 0
         */
-       SPI0_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS); // | SPI_PCS_2;
+       SPI0_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS);
 
        /*
         * 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(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);
+       pmc_periphEnable(SPI0_ID);
 
        /* Enable SPI */
        SPI0_CR = BV(SPI_SPIEN);
@@ -580,6 +578,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);
@@ -612,18 +612,20 @@ 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(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);
+       pmc_periphEnable(SPI1_ID);
 
        /* Enable SPI */
        SPI1_CR = BV(SPI_SPIEN);
@@ -654,6 +656,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);
@@ -703,6 +707,8 @@ static const struct SerialHardwareVT UART0_VT =
        C99INIT(txSending, tx_sending),
 };
 
+#if USART_PORTS > 1
+
 static const struct SerialHardwareVT UART1_VT =
 {
        C99INIT(init, uart1_init),
@@ -713,6 +719,8 @@ static const struct SerialHardwareVT UART1_VT =
        C99INIT(txSending, tx_sending),
 };
 
+#endif /* USART_PORTS > 1 */
+
 static const struct SerialHardwareVT SPI0_VT =
 {
        C99INIT(init, spi0_init),
@@ -746,6 +754,7 @@ static struct ArmSerial UARTDescs[SER_CNT] =
                },
                C99INIT(sending, false),
        },
+#if USART_PORTS > 1
        {
                C99INIT(hw, /**/) {
                        C99INIT(table, &UART1_VT),
@@ -756,6 +765,7 @@ static struct ArmSerial UARTDescs[SER_CNT] =
                },
                C99INIT(sending, false),
        },
+#endif
 
        {
                C99INIT(hw, /**/) {
@@ -851,6 +861,8 @@ static DECLARE_ISR(uart0_irq_dispatcher)
        SER_INT_ACK;
 }
 
+#if USART_PORTS > 1
+
 /**
  * Serial 1 TX interrupt handler
  */
@@ -914,6 +926,8 @@ static DECLARE_ISR(uart1_irq_dispatcher)
        SER_INT_ACK;
 }
 
+#endif /* USART_PORTS > 1 */
+
 /**
  * SPI0 interrupt handler
  */
@@ -935,7 +949,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;
 
@@ -965,7 +983,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;