diff options
-rw-r--r-- | chip/stm32/dma.c | 19 | ||||
-rw-r--r-- | chip/stm32/dma.h | 29 | ||||
-rw-r--r-- | chip/stm32/i2c.c | 29 | ||||
-rw-r--r-- | chip/stm32/registers.h | 8 | ||||
-rw-r--r-- | chip/stm32/spi.c | 20 |
5 files changed, 74 insertions, 31 deletions
diff --git a/chip/stm32/dma.c b/chip/stm32/dma.c index 935ffed038..ab8e8f2d58 100644 --- a/chip/stm32/dma.c +++ b/chip/stm32/dma.c @@ -78,8 +78,6 @@ static void prepare_channel(struct dma_channel *chan, unsigned count, REG32(&chan->ccr) = ctrl; ctrl |= flags; - ctrl |= 0 << 10; /* MSIZE (memory size in bytes) */ - ctrl |= 1 << 8; /* PSIZE (16-bits for now) */ REG32(&chan->ccr) = ctrl; } @@ -89,19 +87,22 @@ void dma_go(struct dma_channel *chan) REG32(&chan->ccr) |= DMA_EN; } -void dma_prepare_tx(struct dma_channel *chan, unsigned count, void *periph, - const void *memory) +void dma_prepare_tx(const struct dma_option *option, unsigned count, + const void *memory) { - prepare_channel(chan, count, periph, memory, - DMA_MINC_MASK | DMA_DIR_FROM_MEM_MASK); + struct dma_channel *chan = dma_get_channel(option->channel); + + prepare_channel(chan, count, option->periph, memory, + DMA_MINC_MASK | DMA_DIR_FROM_MEM_MASK | option->flags); } -int dma_start_rx(unsigned channel, unsigned count, void *periph, +int dma_start_rx(const struct dma_option *option, unsigned count, const void *memory) { - struct dma_channel *chan = dma_get_channel(channel); + struct dma_channel *chan = dma_get_channel(option->channel); - prepare_channel(chan, count, periph, memory, DMA_MINC_MASK); + prepare_channel(chan, count, option->periph, memory, + DMA_MINC_MASK | option->flags); dma_go(chan); return 0; } diff --git a/chip/stm32/dma.h b/chip/stm32/dma.h index c1d69a7c07..76380de6f7 100644 --- a/chip/stm32/dma.h +++ b/chip/stm32/dma.h @@ -54,6 +54,14 @@ struct dma_ctlr { struct dma_channel chan[DMA_NUM_CHANNELS]; }; +/* DMA channel options */ +struct dma_option { + unsigned channel; /* DMA channel */ + void *periph; /* Pointer to peripheral data register */ + unsigned flags; /* DMA flags for the control register. Normally + used to select memory size. */ +}; + /* Defines for accessing DMA ccr */ #define DMA_PL_SHIFT 12 #define DMA_PL_MASK (3 << DMA_PL_SHIFT) @@ -72,6 +80,14 @@ enum { #define DMA_MINC_MASK (1 << 7) #define DMA_TCIF(channel) (1 << (1 + 4 * channel)) +#define DMA_MSIZE_BYTE (0 << 10) +#define DMA_MSIZE_HALF_WORD (1 << 10) +#define DMA_MSIZE_WORD (2 << 10) + +#define DMA_PSIZE_BYTE (0 << 8) +#define DMA_PSIZE_HALF_WORD (1 << 8) +#define DMA_PSIZE_WORD (2 << 8) + #define DMA_POLLING_INTERVAL_US 100 /* us */ #define DMA_TRANSFER_TIMEOUT_US 100000 /* us */ @@ -103,24 +119,23 @@ struct dma_channel *dma_get_channel(int channel); * * Call dma_go() afterwards to actually start the transfer. * - * @param chan Channel to prepare (use dma_get_channel()) + * @param option DMA channel options * @param count Number of bytes to transfer - * @param periph Pointer to peripheral data register * @param memory Pointer to memory address + * * @return pointer to prepared channel */ -void dma_prepare_tx(struct dma_channel *chan, unsigned count, - void *periph, const void *memory); +void dma_prepare_tx(const struct dma_option *option, unsigned count, + const void *memory); /** * Start a DMA transfer to receive data to memory from a peripheral * - * @param channel Channel number to read (DMAC_...) + * @param option DMA channel options * @param count Number of bytes to transfer - * @param periph Pointer to peripheral data register * @param memory Pointer to memory address */ -int dma_start_rx(unsigned channel, unsigned count, void *periph, +int dma_start_rx(const struct dma_option *option, unsigned count, const void *memory); /** diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c index 2bc072f266..a591e82709 100644 --- a/chip/stm32/i2c.c +++ b/chip/stm32/i2c.c @@ -72,6 +72,20 @@ enum { STOP_SENT_RETRY_US = 150, }; +static const struct dma_option dma_tx_option[NUM_PORTS] = { + {DMAC_I2C_TX, (void *)&STM32_I2C_DR(I2C1), + DMA_MSIZE_BYTE | DMA_PSIZE_HALF_WORD}, + {DMAC_I2C_TX, (void *)&STM32_I2C_DR(I2C2), + DMA_MSIZE_BYTE | DMA_PSIZE_HALF_WORD}, +}; + +static const struct dma_option dma_rx_option[NUM_PORTS] = { + {DMAC_I2C_RX, (void *)&STM32_I2C_DR(I2C1), + DMA_MSIZE_BYTE | DMA_PSIZE_HALF_WORD}, + {DMAC_I2C_RX, (void *)&STM32_I2C_DR(I2C2), + DMA_MSIZE_BYTE | DMA_PSIZE_HALF_WORD}, +}; + static uint16_t i2c_sr1[NUM_PORTS]; static struct mutex i2c_mutex; @@ -128,7 +142,7 @@ static int i2c_write_raw_slave(int port, void *buf, int len) /* Configuring DMA1 channel DMAC_I2X_TX */ enable_ack(port); chan = dma_get_channel(DMAC_I2C_TX); - dma_prepare_tx(chan, len, (void *)&STM32_I2C_DR(port), buf); + dma_prepare_tx(dma_tx_option + port, len, buf); /* Start the DMA */ dma_go(chan); @@ -237,8 +251,8 @@ static void i2c_event_handler(int port) if (i2c_sr1[port] & (1 << 1)) { /* If it's a receiver slave */ if (!(STM32_I2C_SR2(port) & (1 << 2))) { - dma_start_rx(DMAC_I2C_RX, sizeof(host_buffer), - (void *)&STM32_I2C_DR(port), host_buffer); + dma_start_rx(dma_rx_option + port, sizeof(host_buffer), + host_buffer); STM32_I2C_CR2(port) |= (1 << 11); rx_pending = 1; @@ -714,17 +728,15 @@ static int i2c_master_transmit(int port, int slave_addr, uint8_t *data, int size, int stop) { int rv, rv_start; - struct dma_channel *chan; disable_ack(port); /* Configuring DMA1 channel DMAC_I2X_TX */ - chan = dma_get_channel(DMAC_I2C_TX); - dma_prepare_tx(chan, size, (void *)&STM32_I2C_DR(port), data); + dma_prepare_tx(dma_tx_option + port, size, data); dma_enable_tc_interrupt(DMAC_I2C_TX); /* Start the DMA */ - dma_go(chan); + dma_go(dma_get_channel(DMAC_I2C_TX)); /* Configuring i2c2 to use DMA */ STM32_I2C_CR2(port) |= CR2_DMAEN; @@ -768,8 +780,7 @@ static int i2c_master_receive(int port, int slave_addr, uint8_t *data, /* Master receive only supports DMA for payloads > 1 byte */ if (size > 1) { enable_ack(port); - dma_start_rx(DMAC_I2C_RX, size, (void *)&STM32_I2C_DR(port), - data); + dma_start_rx(dma_rx_option + port, size, data); dma_enable_tc_interrupt(DMAC_I2C_RX); diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h index 612dce10f9..4831916a9e 100644 --- a/chip/stm32/registers.h +++ b/chip/stm32/registers.h @@ -253,10 +253,8 @@ #define STM32_I2C1_PORT 0 #define STM32_I2C2_PORT 1 -static inline uint16_t *stm32_i2c_reg(int port, int offset) -{ - return (uint16_t *)((STM32_I2C1_BASE + (port * 0x400)) + offset); -} +#define stm32_i2c_reg(port, offset) \ + ((uint16_t *)((STM32_I2C1_BASE + ((port) * 0x400)) + (offset))) #define STM32_I2C_CR1(n) REG16(stm32_i2c_reg(n, 0x00)) #define STM32_I2C_CR2(n) REG16(stm32_i2c_reg(n, 0x04)) @@ -417,6 +415,8 @@ struct spi_ctlr { */ #define stm32_spi_addr(port) \ ((struct spi_ctlr *)(port == 0 ? STM32_SPI1_BASE : STM32_SPI2_BASE)) +#define stm32_spi_port(addr) \ + ((addr) == STM32_SPI1_BASE ? 0 : 1) /* --- Debug --- */ diff --git a/chip/stm32/spi.c b/chip/stm32/spi.c index 6e518e7d1e..ec8e078c73 100644 --- a/chip/stm32/spi.c +++ b/chip/stm32/spi.c @@ -22,6 +22,21 @@ #define CPUTS(outstr) cputs(CC_SPI, outstr) #define CPRINTF(format, args...) cprintf(CC_SPI, format, ## args) +/* DMA channel option */ +static const struct dma_option dma_tx_option[2] = { + {DMA_SPI1_TX, (void *)&stm32_spi_addr(STM32_SPI1_PORT)->data, + DMA_MSIZE_BYTE | DMA_PSIZE_HALF_WORD}, + {DMA_SPI2_TX, (void *)&stm32_spi_addr(STM32_SPI2_PORT)->data, + DMA_MSIZE_BYTE | DMA_PSIZE_HALF_WORD}, +}; + +static const struct dma_option dma_rx_option[2] = { + {DMA_SPI1_RX, (void *)&stm32_spi_addr(STM32_SPI1_PORT)->data, + DMA_MSIZE_BYTE | DMA_PSIZE_HALF_WORD}, + {DMA_SPI2_RX, (void *)&stm32_spi_addr(STM32_SPI2_PORT)->data, + DMA_MSIZE_BYTE | DMA_PSIZE_HALF_WORD}, +}; + /* Status register flags that we use */ enum { SR_RXNE = 1 << 0, @@ -179,7 +194,7 @@ static void reply(struct spi_ctlr *spi, struct dma_channel *txdma, /* Add the checksum and get ready to send */ msg[msg_len - 2] = sum & 0xff; msg[msg_len - 1] = SPI_MSG_PREAMBLE_BYTE; - dma_prepare_tx(txdma, msg_len, (void *)&spi->data, msg); + dma_prepare_tx(dma_tx_option[stm32_spi_port(spi)], msg_len, msg); /* Kick off the DMA to send the data */ dma_go(txdma); @@ -206,7 +221,8 @@ static void setup_for_transaction(struct spi_ctlr *spi) /* read a byte in case there is one, and the rx dma gets it */ dmac = REG16(&spi->data); dmac = DMA_CHANNEL_FOR_SPI_RX(spi); - dma_start_rx(dmac, sizeof(in_msg), (void *)&spi->data, in_msg); + dma_start_rx(dma_rx_option[stm32_spi_port(spi)], + sizeof(in_msg), in_msg); } /** |