diff options
author | Charlie Mooney <charliemooney@chromium.org> | 2012-08-07 09:43:44 -0700 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-08-13 12:33:32 -0700 |
commit | 397a7aa33633b912cc08eabe125b88a6648efb10 (patch) | |
tree | b76b64eaa8f7b4c9191dfb5f1f000a98c731e3a3 /chip/stm32/dma.c | |
parent | 03d4ed278de2a27a9c2c580ad4d68e30dbcc7630 (diff) | |
download | chrome-ec-397a7aa33633b912cc08eabe125b88a6648efb10.tar.gz |
Lucas: Switching the i2c transmit code over to dma
There was an errata issues for the i2c on STMF100xx. It specified that
not all guarantees apply to i2c on these chips if you are not using DMA
to load the data. To prevent problems, I am converting the i2c code on
the EC for Lucas over to DMA.
Here the i2c's master functionality is retrofitted to use DMA
instead of polling to fill the i2c buffer. The slave functionality
is still left in the old style for the time being, but will also be
converted soon.
BUG=chrome-os-partner:10901
TEST=From EC console, make sure that "battery" and "pmu" commands work.
They both use i2c, so if i2c had been broken they would fail.
Change-Id: I2fb80dcb68632938df1c9165ebd5a67cb5194451
Signed-off-by: Charlie Mooney <charliemooney@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/29811
Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'chip/stm32/dma.c')
-rw-r--r-- | chip/stm32/dma.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/chip/stm32/dma.c b/chip/stm32/dma.c index 2f0f868e47..14058bfaa8 100644 --- a/chip/stm32/dma.c +++ b/chip/stm32/dma.c @@ -14,7 +14,10 @@ #define CPUTS(outstr) cputs(CC_DMA, outstr) #define CPRINTF(format, args...) cprintf(CC_DMA, format, ## args) - +/* + * Note, you must decrement the channel value by 1 from what is specified + * in the datasheets, as they index from 1 and this indexes from 0! + */ struct dma_channel *dma_get_channel(int channel) { struct dma_channel *chan; @@ -189,3 +192,43 @@ void dma_init(void) /* Enable DMA1, we don't support DMA2 yet */ STM32_RCC_AHBENR |= RCC_AHBENR_DMA1EN; } + +int dma_wait(int channel) +{ + struct dma_ctlr *dma; + uint32_t mask; + timestamp_t deadline; + + dma = dma_get_ctlr(channel); + mask = DMA_TCIF(channel); + + deadline.val = get_time().val + DMA_TRANSFER_TIMEOUT_US; + while ((REG32(&dma->isr) & mask) != mask) { + if (deadline.val <= get_time().val) + return -1; + else + usleep(DMA_POLLING_INTERVAL_US); + } + return 0; +} + +void dma_clear_isr(int channel) +{ + struct dma_ctlr *dma; + + dma = dma_get_ctlr(channel); + /* Adjusting the channel number if it's from the second DMA */ + if (channel > DMA1_NUM_CHANNELS) + channel -= DMA1_NUM_CHANNELS; + + REG32(&dma->ifcr) |= 0xff << (4 * channel); +} + +struct dma_ctlr *dma_get_ctlr(int channel) +{ + ASSERT(channel < DMA_NUM_CHANNELS); + if (channel < DMA1_NUM_CHANNELS) + return (struct dma_ctlr *)STM32_DMA1_BASE; + else + return (struct dma_ctlr *)STM32_DMA2_BASE; +} |