authorNathael Pajani <nathael.pajani@ed3l.fr>
Tue, 22 Sep 2015 01:02:58 +0000 (03:02 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Tue, 22 Sep 2015 01:02:58 +0000 (03:02 +0200)
drivers/ssp.c
include/core/lpc_regs_17xx.h
include/drivers/ssp.h

index 07373f1..d748406 100644 (file)
@@ -63,8 +63,8 @@ static struct ssp_device ssps[NUM_SSPS] = {
                .int_overrun_stats = 0,
                .int_rx_timeout_stats = 0,
                .irq = SSP0_IRQ,
-               .pclk_bit = (uint8_t)LPC_SSP0_POWER_ON,
-               .power_bit = LPC_SSP0_PCLK,
+               .pclk_bit = LPC_SSP0_PCLK,
+               .power_bit = LPC_SSP0_POWER_ON,
        },
        {
                .num = 0,
@@ -75,27 +75,35 @@ static struct ssp_device ssps[NUM_SSPS] = {
                .int_overrun_stats = 0,
                .int_rx_timeout_stats = 0,
                .irq = SSP1_IRQ,
-               .pclk_bit = (uint8_t)LPC_SSP1_POWER_ON,
-               .power_bit = LPC_SSP1_PCLK,
+               .pclk_bit = LPC_SSP1_PCLK,
+               .power_bit = LPC_SSP1_POWER_ON,
        },
 };
 
 
 
 /* Handlers */
-void SSP_0_Handler(void)
+void SSP_Handler(struct ssp_device* ssp)
 {
-       struct lpc_ssp* ssp = LPC_SSP0;
-       uint32_t intr_flags = ssp->masked_int_status;
+       uint32_t intr_flags = ssp->regs->masked_int_status;
 
        /* Clear the interrupts. Other bits are cleared by fifo access */
-       ssp->int_clear = (intr_flags & (LPC_SSP_INTR_RX_OVERRUN | LPC_SSP_INTR_RX_TIMEOUT));
+       ssp->regs->int_clear = (intr_flags & (LPC_SSP_INTR_RX_OVERRUN | LPC_SSP_INTR_RX_TIMEOUT));
        if (intr_flags & LPC_SSP_INTR_RX_OVERRUN) {
-               ssps[0].int_overrun_stats += 1;
+               ssp->int_overrun_stats += 1;
        }
        if (intr_flags & LPC_SSP_INTR_RX_TIMEOUT) {
-               ssps[0].int_rx_timeout_stats += 1;
+               ssp->int_rx_timeout_stats += 1;
        }
+       /* FIXME : implement handlers and call the right one if configured */
+}
+void SSP_0_Handler(void)
+{
+       SSP_Handler(&ssps[0]);
+}
+void SSP_1_Handler(void)
+{
+       SSP_Handler(&ssps[1]);
 }
 
 
@@ -281,12 +289,12 @@ uint32_t ssp_clk_on(uint8_t ssp_num, uint32_t rate)
 
        /* Set cclk divider for PCLK */
        set_subsystem_clk_divider(ssps[ssp_num].pclk_bit, LPC_PCLK_CCLK);
-
        pclk = get_main_clock();
 
        /* Make sure we can get this clock rate */
-       /* NOTE: We use only to divisors, so we could achieve lower clock rates by using
-        *   the third one. Any need for this though ?
+       /* NOTE: We use only to divisors.,We could achieve lower clock rates by using
+        *   half, a quarter or a eighth of the main clock as SSP peripheral clock.
+        *   Any need for this though ?
         */
        if ((pclk / rate) > 0xFFF0) {
                /* What should we do ? */
@@ -298,11 +306,17 @@ uint32_t ssp_clk_on(uint8_t ssp_num, uint32_t rate)
        do {
                prescale += 2; /* Minimum value is 2, and must be even */
                pclk_div = (div / prescale);
-       } while ((prescale > 0xFF) || (pclk_div > 0xFF));
-
+       } while (pclk_div > 0xFF);
+       /* This shoulf not happen due to the previous test (see above note) */
+       if (prescale > 0xFF) {
+               return 0;
+       }
 
        /* Set the prescaler */
        ssp_regs->clk_prescale = prescale;
+       /* Set the serial clock rate (SCR) part of the first control register */
+       ssp_regs->ctrl_0 &= ~LPC_SSP_SPI_CLK_RATE_MASK;
+       ssp_regs->ctrl_0 |= LPC_SSP_SPI_CLK_RATE_DIV(pclk_div); /* (minus one made by macro) */
 
        /* And return the achieved clock */
        return (pclk / (prescale * pclk_div));
@@ -321,7 +335,7 @@ void ssp_clk_update(void)
 
 /***************************************************************************** */
 /* SSP Setup as master */
-/* Returns 0 on success
+/* Returns configured clock rate on success
  * Parameters :
  *  frame_type is SPI, TI or MICROWIRE (use apropriate defines for this one):
  *     LPC_SSP_FRAME_SPI - LPC_SSP_FRAME_TI - LPC_SSP_FRAME_MICROWIRE).
@@ -357,7 +371,7 @@ int ssp_master_on(uint8_t ssp_num, uint8_t frame_type, uint8_t data_width, uint3
        ssp_regs->ctrl_1 |= LPC_SSP_ENABLE;
 
        NVIC_EnableIRQ(ssp->irq);
-       return 0; /* Config OK */
+       return ssp->current_clk; /* Config OK */
 }
 
 int ssp_slave_on(uint8_t ssp_num, uint8_t frame_type, uint8_t data_width, uint8_t out_en, uint32_t max_rate)
index db591ed..0949931 100644 (file)
@@ -734,7 +734,8 @@ struct lpc_ssp
 #define LPC_SSP_SPI_CLK_HIGH     (0x01 << 6)
 #define LPC_SSP_SPI_CLK_FIRST    (0x00 << 7)
 #define LPC_SSP_SPI_CLK_LAST     (0x01 << 7)
-#define LPC_SSP_SPI_CLK_RATE_DIV(x) (((x) & 0xFF) << 8)
+#define LPC_SSP_SPI_CLK_RATE_MASK   (0xFF << 8)
+#define LPC_SSP_SPI_CLK_RATE_DIV(x) ((((x) - 1) & 0xFF) << 8)
 /* SSP Control 1 register */
 #define LPC_SSP_LOOPBACK_MODE      (0x01 << 0)
 #define LPC_SSP_ENABLE             (0x01 << 1)
index 6014d8b..3c0bfe4 100644 (file)
@@ -95,7 +95,7 @@ void ssp_clk_update(void);
 
 /***************************************************************************** */
 /* SSP Setup as master */
-/* Returns 0 on success
+/* Returns configured clock rate on success
  * Parameters :
  *  frame_type is SPI, TI or MICROWIRE (use apropriate defines for this one).
  *     LPC_SSP_FRAME_SPI - LPC_SSP_FRAME_TI - LPC_SSP_FRAME_MICROWIRE).