diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-04-26 14:36:38 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-04-30 11:45:52 -0700 |
commit | 0a6b7620d6b4ba1a50500a75db3e76162eac5ce0 (patch) | |
tree | 8f55cf2a2ee6469981bd27924349bf80de0f295e /chip/stm32 | |
parent | c08e0ade765bf69fb9ab3f62305a84a4d3d34c1d (diff) | |
download | chrome-ec-0a6b7620d6b4ba1a50500a75db3e76162eac5ce0.tar.gz |
Move i2cread and i2cwrite functions to i2c_common
Also moves the handy i2cscan command to i2c_common. The
platform-dependent interface is now i2c_xfer().
Still more to do in follow-up CLs; for example, i2c_read_string() has
platform-dependent implementation, and the i2c/i2cread console
commands aren't common yet.
BUG=chrome-os-partner:18969
BRANCH=none
TEST=i2cscan on link, spring
Change-Id: Ia53d57beaa157bece293a4262257e20b4107589e
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/49492
Reviewed-by: Simon Glass <sjg@chromium.org>
Commit-Queue: Daniel Erat <derat@chromium.org>
Commit-Queue: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'chip/stm32')
-rw-r--r-- | chip/stm32/config.h | 5 | ||||
-rw-r--r-- | chip/stm32/i2c.c | 124 |
2 files changed, 46 insertions, 83 deletions
diff --git a/chip/stm32/config.h b/chip/stm32/config.h index 989cafa087..ef97180ebd 100644 --- a/chip/stm32/config.h +++ b/chip/stm32/config.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -34,6 +34,9 @@ /* Maximum number of deferrable functions */ #define DEFERRABLE_MAX_COUNT 8 +/* Number of I2C ports */ +#define I2C_PORT_COUNT 2 + /* support programming on-chip flash */ #define CONFIG_FLASH diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c index 2b968b0dd2..8680f59521 100644 --- a/chip/stm32/i2c.c +++ b/chip/stm32/i2c.c @@ -57,7 +57,6 @@ */ #define I2C_BITBANG_DELAY_US 5 -#define NUM_PORTS 2 #define I2C1 STM32_I2C1_PORT #define I2C2 STM32_I2C2_PORT @@ -80,22 +79,21 @@ enum { STOP_SENT_RETRY_US = 150, }; -static const struct dma_option dma_tx_option[NUM_PORTS] = { +static const struct dma_option dma_tx_option[I2C_PORT_COUNT] = { {DMAC_I2C1_TX, (void *)&STM32_I2C_DR(I2C1), DMA_MSIZE_BYTE | DMA_PSIZE_HALF_WORD}, {DMAC_I2C2_TX, (void *)&STM32_I2C_DR(I2C2), DMA_MSIZE_BYTE | DMA_PSIZE_HALF_WORD}, }; -static const struct dma_option dma_rx_option[NUM_PORTS] = { +static const struct dma_option dma_rx_option[I2C_PORT_COUNT] = { {DMAC_I2C1_RX, (void *)&STM32_I2C_DR(I2C1), DMA_MSIZE_BYTE | DMA_PSIZE_HALF_WORD}, {DMAC_I2C2_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; +static uint16_t i2c_sr1[I2C_PORT_COUNT]; /* Buffer for host commands (including version, error code and checksum) */ static uint8_t host_buffer[EC_HOST_PARAM_SIZE + 4]; @@ -710,7 +708,7 @@ cr_cleanup: STM32_I2C_CR1(port) = (1 << 10) | (1 << 0); } -static int i2c_master_transmit(int port, int slave_addr, uint8_t *data, +static int i2c_master_transmit(int port, int slave_addr, const uint8_t *data, int size, int stop) { int rv, rv_start; @@ -804,32 +802,18 @@ static int i2c_master_receive(int port, int slave_addr, uint8_t *data, return wait_until_stop_sent(port); } -/** - * Perform an I2C transaction, involve a write, and optional read. - * - * @param port I2C port to use (e.g. I2C_PORT_HOST) - * @param slave_addr Slave address of chip to access on I2C bus - * @param out Buffer containing bytes to output - * @param out_bytes Number of bytes to send (must be >0) - * @param in Buffer to place input bytes - * @param in_bytes Number of bytse to receive - * @return 0 if ok, else ER_ERROR... - */ -static int i2c_xfer(int port, int slave_addr, uint8_t *out, int out_bytes, - uint8_t *in, int in_bytes) +int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_bytes, + uint8_t *in, int in_bytes, int flags) { int rv; - ASSERT(out && out_bytes); - ASSERT(in || !in_bytes); + /* TODO: support start/stop flags */ - disable_sleep(SLEEP_MASK_I2C); - mutex_lock(&i2c_mutex); + ASSERT(out || !out_bytes); + ASSERT(in || !in_bytes); - if (i2c_claim(port)) { - rv = EC_ERROR_BUSY; - goto err_claim; - } + if (i2c_claim(port)) + return EC_ERROR_BUSY; disable_i2c_interrupt(port); @@ -843,58 +827,25 @@ static int i2c_xfer(int port, int slave_addr, uint8_t *out, int out_bytes, i2c_release(port); -err_claim: - mutex_unlock(&i2c_mutex); - enable_sleep(SLEEP_MASK_I2C); - - return rv; -} - -int i2c_read16(int port, int slave_addr, int offset, int *data) -{ - uint8_t reg, buf[2]; - int rv; - - reg = offset & 0xff; - rv = i2c_xfer(port, slave_addr, ®, 1, buf, 2); - - *data = (buf[1] << 8) | buf[0]; - return rv; } -int i2c_write16(int port, int slave_addr, int offset, int data) -{ - uint8_t buf[3]; - - buf[0] = offset & 0xff; - buf[1] = data & 0xff; - buf[2] = (data >> 8) & 0xff; - - return i2c_xfer(port, slave_addr, buf, sizeof(buf), NULL, 0); -} - -int i2c_read8(int port, int slave_addr, int offset, int *data) +int i2c_get_line_levels(int port) { - uint8_t reg, buf[1]; - int rv; - - reg = offset & 0xff; - rv = i2c_xfer(port, slave_addr, ®, 1, buf, 1); - - *data = buf[0]; - - return rv; -} + enum gpio_signal sda, scl; -int i2c_write8(int port, int slave_addr, int offset, int data) -{ - uint8_t buf[2]; + ASSERT(port == I2C1 || port == I2C2); - buf[0] = offset & 0xff; - buf[1] = data & 0xff; + if (port == I2C1) { + sda = GPIO_I2C1_SDA; + scl = GPIO_I2C1_SCL; + } else { + sda = GPIO_I2C2_SDA; + scl = GPIO_I2C2_SCL; + } - return i2c_xfer(port, slave_addr, buf, sizeof(buf), NULL, 0); + return (gpio_get_level(sda) ? I2C_LINE_SDA_HIGH : 0) | + (gpio_get_level(scl) ? I2C_LINE_SCL_HIGH : 0); } int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data, @@ -902,23 +853,32 @@ int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data, { int rv; uint8_t reg, block_length; + + /* + * TODO: when i2c_xfer() supports start/stop bits, won't need a temp + * buffer, and this code can merge with the LM4 implementation and + * move to i2c_common.c. + */ uint8_t buffer[SMBUS_MAX_BLOCK + 1]; if ((len <= 0) || (len > SMBUS_MAX_BLOCK)) return EC_ERROR_INVAL; - reg = offset; - rv = i2c_xfer(port, slave_addr, ®, 1, buffer, SMBUS_MAX_BLOCK + 1); - if (rv) - return rv; + i2c_lock(port, 1); - /* the length of the block is the first byte of the returned buffer */ - block_length = MIN(buffer[0], len - 1); - buffer[block_length + 1] = 0; - - memcpy(data, buffer+1, block_length + 1); + reg = offset; + rv = i2c_xfer(port, slave_addr, ®, 1, buffer, SMBUS_MAX_BLOCK + 1, + I2C_XFER_SINGLE); + if (rv == EC_SUCCESS) { + /* Block length is the first byte of the returned buffer */ + block_length = MIN(buffer[0], len - 1); + buffer[block_length + 1] = 0; + + memcpy(data, buffer+1, block_length + 1); + } - return EC_SUCCESS; + i2c_lock(port, 0); + return rv; } /*****************************************************************************/ |