mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-30 10:31:02 +00:00
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>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 --- */
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user