X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Flpc%2Fao_spi_lpc.c;h=a8d4cda9229b32d176c480916ff39c55988af6ed;hp=e7edca4c1a165e7a090339c20e7354d4ec75601c;hb=1085ec5d57e0ed5d132f2bbdac1a0b6a32c0ab4a;hpb=e383d7a28d01729c50f933ceda77ea767d1b8087 diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index e7edca4c..a8d4cda9 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,36 +22,27 @@ static uint8_t ao_spi_mutex[LPC_NUM_SPI]; static struct lpc_ssp * const ao_lpc_ssp[LPC_NUM_SPI] = { &lpc_ssp0, &lpc_ssp1 }; -static uint8_t spi_dev_null; - -#define tx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_TNF))) != (1 << LPC_SSP_SR_TNF) -#define rx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_RNE))) != (1 << LPC_SSP_SR_RNE) - #define spi_loop(len, put, get) do { \ while (len--) { \ - /* Wait for space in the fifo */ \ - while (tx_busy(lpc_ssp)) \ - ; \ - \ /* send a byte */ \ lpc_ssp->dr = put; \ - \ - /* Wait for byte to appear in the fifo */ \ - while (rx_busy(lpc_ssp)) \ + /* wait for the received byte to appear */ \ + while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) == 0) \ ; \ - \ - /* recv a byte */ \ + /* receive a byte */ \ get lpc_ssp->dr; \ } \ - } while (0); + /* Wait for the SSP to go idle (it already should be) */ \ + while (lpc_ssp->sr & (1 << LPC_SSP_SR_BSY)); \ + } while (0) void -ao_spi_send(void *block, uint16_t len, uint8_t id) +ao_spi_send(const void *block, uint16_t len, uint8_t id) { - uint8_t *b = block; struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + const uint8_t *o = block; - spi_loop(len, *b++, (void)); + spi_loop(len, *o++, (void)); } void @@ -64,18 +56,18 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t id) void ao_spi_recv(void *block, uint16_t len, uint8_t id) { - uint8_t *b = block; struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + uint8_t *i = block; - spi_loop(len, 0xff, *b++ =); + spi_loop(len, 0xff, *i++ =); } void -ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t id) +ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t id) { - uint8_t *o = out; - uint8_t *i = in; struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + const uint8_t *o = out; + uint8_t *i = in; spi_loop(len, *o++, *i++ =); } @@ -86,27 +78,14 @@ ao_spi_get(uint8_t id, uint32_t speed) struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; ao_mutex_get(&ao_spi_mutex[id]); - + /* Set the clock prescale */ lpc_ssp->cpsr = speed; - - /* Enable the device */ - lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | - (1 << LPC_SSP_CR1_SSE) | - (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | - (0 << LPC_SSP_CR1_SOD)); } void ao_spi_put(uint8_t id) { - struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; - - /* Disable the device */ - lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | - (0 << LPC_SSP_CR1_SSE) | - (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | - (0 << LPC_SSP_CR1_SOD)); ao_mutex_put(&ao_spi_mutex[id]); } @@ -116,11 +95,23 @@ ao_spi_channel_init(uint8_t id) struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; uint8_t d; + /* Clear interrupt registers */ + lpc_ssp->imsc = 0; + lpc_ssp->ris = 0; + lpc_ssp->mis = 0; + lpc_ssp->cr0 = ((LPC_SSP_CR0_DSS_8 << LPC_SSP_CR0_DSS) | (LPC_SSP_CR0_FRF_SPI << LPC_SSP_CR0_FRF) | (0 << LPC_SSP_CR0_CPOL) | (0 << LPC_SSP_CR0_CPHA) | (0 << LPC_SSP_CR0_SCR)); + + /* Enable the device */ + lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | + (1 << LPC_SSP_CR1_SSE) | + (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | + (0 << LPC_SSP_CR1_SOD)); + /* Drain the receive fifo */ for (d = 0; d < LPC_SSP_FIFOSIZE; d++) (void) lpc_ssp->dr; @@ -131,7 +122,21 @@ ao_spi_init(void) { #if HAS_SPI_0 /* Configure pins */ - lpc_ioconf.pio0_6 = ao_lpc_alternate(LPC_IOCONF_FUNC_SCK0); +#if SPI_SCK0_P0_6 + lpc_ioconf.pio0_6 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_6_SCK0); +#define HAS_SCK0 +#endif +#if SPI_SCK0_P0_10 + lpc_ioconf.pio0_10 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_10_SCK0); +#define HAS_SCK0 +#endif +#if SPI_SCK0_P1_29 + lpc_ioconf.pio1_29 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO1_29_SCK0); +#define HAS_SCK0 +#endif +#ifndef HAS_SCK0 +#error "No pin specified for SCK0" +#endif lpc_ioconf.pio0_8 = ao_lpc_alternate(LPC_IOCONF_FUNC_MISO0); lpc_ioconf.pio0_9 = ao_lpc_alternate(LPC_IOCONF_FUNC_MOSI0); @@ -145,7 +150,7 @@ ao_spi_init(void) lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP0_RST_N); lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP0_RST_N); ao_spi_channel_init(0); -#endif +#endif #if HAS_SPI_1 @@ -174,7 +179,7 @@ ao_spi_init(void) #endif #if SPI_MOSI1_P0_21 - lpc_ioconf.pio1_21 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_21_MOSI1); + lpc_ioconf.pio0_21 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_21_MOSI1); #define HAS_MOSI1 #endif #if SPI_MOSI1_P1_22 @@ -184,14 +189,15 @@ ao_spi_init(void) #ifndef HAS_MOSI1 #error "No pin specified for MOSI1" #endif - + /* Enable the device */ lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_SSP1); /* Turn on the clock */ lpc_scb.ssp1clkdiv = 1; - /* De-assert reset */ + /* Reset the device */ + lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); ao_spi_channel_init(1); #endif /* HAS_SPI_1 */