summaryrefslogtreecommitdiff
path: root/chip/stm32/dma.c
diff options
context:
space:
mode:
authorCharlie Mooney <charliemooney@chromium.org>2012-08-07 09:43:44 -0700
committerGerrit <chrome-bot@google.com>2012-08-13 12:33:32 -0700
commit397a7aa33633b912cc08eabe125b88a6648efb10 (patch)
treeb76b64eaa8f7b4c9191dfb5f1f000a98c731e3a3 /chip/stm32/dma.c
parent03d4ed278de2a27a9c2c580ad4d68e30dbcc7630 (diff)
downloadchrome-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.c45
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;
+}