summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2012-09-25 14:40:15 +0800
committerGerrit <chrome-bot@google.com>2012-09-26 08:58:57 -0700
commitcfcd1412eae4f9f14076d357106709372ca6dc0b (patch)
tree1db52d56e5e94c58eb467dcca505e3dfd78c20c1
parentc51a8982ff742fa710887608b038e4e4dd9621e9 (diff)
downloadchrome-ec-cfcd1412eae4f9f14076d357106709372ca6dc0b.tar.gz
stm32: Export DMA memory size option
We need different memory size configuration in different application. Let's export the memory size option to DMA function parameters. BUG=chrome-os-partner:14316 TEST=Boot on snow. Check I2C host command works. BRANCH=none Change-Id: I30481ddf86a1526d517961e009898642ecdd649a Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/33981 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--chip/stm32/dma.c19
-rw-r--r--chip/stm32/dma.h29
-rw-r--r--chip/stm32/i2c.c29
-rw-r--r--chip/stm32/registers.h8
-rw-r--r--chip/stm32/spi.c20
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);
}
/**