/drivers/i2c/busses/i2c-nomadik.c
C | 960 lines | 576 code | 137 blank | 247 comment | 55 complexity | 203c125b8f021734c24331389126f355 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * Copyright (C) 2009 ST-Ericsson
- * Copyright (C) 2009 STMicroelectronics
- *
- * I2C master mode controller driver, used in Nomadik 8815
- * and Ux500 platforms.
- *
- * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
- * Author: Sachin Verma <sachin.verma@st.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- */
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/delay.h>
- #include <linux/slab.h>
- #include <linux/interrupt.h>
- #include <linux/i2c.h>
- #include <linux/err.h>
- #include <linux/clk.h>
- #include <linux/io.h>
- #include <plat/i2c.h>
- #define DRIVER_NAME "nmk-i2c"
- /* I2C Controller register offsets */
- #define I2C_CR (0x000)
- #define I2C_SCR (0x004)
- #define I2C_HSMCR (0x008)
- #define I2C_MCR (0x00C)
- #define I2C_TFR (0x010)
- #define I2C_SR (0x014)
- #define I2C_RFR (0x018)
- #define I2C_TFTR (0x01C)
- #define I2C_RFTR (0x020)
- #define I2C_DMAR (0x024)
- #define I2C_BRCR (0x028)
- #define I2C_IMSCR (0x02C)
- #define I2C_RISR (0x030)
- #define I2C_MISR (0x034)
- #define I2C_ICR (0x038)
- /* Control registers */
- #define I2C_CR_PE (0x1 << 0) /* Peripheral Enable */
- #define I2C_CR_OM (0x3 << 1) /* Operating mode */
- #define I2C_CR_SAM (0x1 << 3) /* Slave addressing mode */
- #define I2C_CR_SM (0x3 << 4) /* Speed mode */
- #define I2C_CR_SGCM (0x1 << 6) /* Slave general call mode */
- #define I2C_CR_FTX (0x1 << 7) /* Flush Transmit */
- #define I2C_CR_FRX (0x1 << 8) /* Flush Receive */
- #define I2C_CR_DMA_TX_EN (0x1 << 9) /* DMA Tx enable */
- #define I2C_CR_DMA_RX_EN (0x1 << 10) /* DMA Rx Enable */
- #define I2C_CR_DMA_SLE (0x1 << 11) /* DMA sync. logic enable */
- #define I2C_CR_LM (0x1 << 12) /* Loopback mode */
- #define I2C_CR_FON (0x3 << 13) /* Filtering on */
- #define I2C_CR_FS (0x3 << 15) /* Force stop enable */
- /* Master controller (MCR) register */
- #define I2C_MCR_OP (0x1 << 0) /* Operation */
- #define I2C_MCR_A7 (0x7f << 1) /* 7-bit address */
- #define I2C_MCR_EA10 (0x7 << 8) /* 10-bit Extended address */
- #define I2C_MCR_SB (0x1 << 11) /* Extended address */
- #define I2C_MCR_AM (0x3 << 12) /* Address type */
- #define I2C_MCR_STOP (0x1 << 14) /* Stop condition */
- #define I2C_MCR_LENGTH (0x7ff << 15) /* Transaction length */
- /* Status register (SR) */
- #define I2C_SR_OP (0x3 << 0) /* Operation */
- #define I2C_SR_STATUS (0x3 << 2) /* controller status */
- #define I2C_SR_CAUSE (0x7 << 4) /* Abort cause */
- #define I2C_SR_TYPE (0x3 << 7) /* Receive type */
- #define I2C_SR_LENGTH (0x7ff << 9) /* Transfer length */
- /* Interrupt mask set/clear (IMSCR) bits */
- #define I2C_IT_TXFE (0x1 << 0)
- #define I2C_IT_TXFNE (0x1 << 1)
- #define I2C_IT_TXFF (0x1 << 2)
- #define I2C_IT_TXFOVR (0x1 << 3)
- #define I2C_IT_RXFE (0x1 << 4)
- #define I2C_IT_RXFNF (0x1 << 5)
- #define I2C_IT_RXFF (0x1 << 6)
- #define I2C_IT_RFSR (0x1 << 16)
- #define I2C_IT_RFSE (0x1 << 17)
- #define I2C_IT_WTSR (0x1 << 18)
- #define I2C_IT_MTD (0x1 << 19)
- #define I2C_IT_STD (0x1 << 20)
- #define I2C_IT_MAL (0x1 << 24)
- #define I2C_IT_BERR (0x1 << 25)
- #define I2C_IT_MTDWS (0x1 << 28)
- #define GEN_MASK(val, mask, sb) (((val) << (sb)) & (mask))
- /* some bits in ICR are reserved */
- #define I2C_CLEAR_ALL_INTS 0x131f007f
- /* first three msb bits are reserved */
- #define IRQ_MASK(mask) (mask & 0x1fffffff)
- /* maximum threshold value */
- #define MAX_I2C_FIFO_THRESHOLD 15
- enum i2c_status {
- I2C_NOP,
- I2C_ON_GOING,
- I2C_OK,
- I2C_ABORT
- };
- /* operation */
- enum i2c_operation {
- I2C_NO_OPERATION = 0xff,
- I2C_WRITE = 0x00,
- I2C_READ = 0x01
- };
- /* controller response timeout in ms */
- #define I2C_TIMEOUT_MS 500
- /**
- * struct i2c_nmk_client - client specific data
- * @slave_adr: 7-bit slave address
- * @count: no. bytes to be transfered
- * @buffer: client data buffer
- * @xfer_bytes: bytes transfered till now
- * @operation: current I2C operation
- */
- struct i2c_nmk_client {
- unsigned short slave_adr;
- unsigned long count;
- unsigned char *buffer;
- unsigned long xfer_bytes;
- enum i2c_operation operation;
- };
- /**
- * struct nmk_i2c_dev - private data structure of the controller
- * @pdev: parent platform device
- * @adap: corresponding I2C adapter
- * @irq: interrupt line for the controller
- * @virtbase: virtual io memory area
- * @clk: hardware i2c block clock
- * @cfg: machine provided controller configuration
- * @cli: holder of client specific data
- * @stop: stop condition
- * @xfer_complete: acknowledge completion for a I2C message
- * @result: controller propogated result
- */
- struct nmk_i2c_dev {
- struct platform_device *pdev;
- struct i2c_adapter adap;
- int irq;
- void __iomem *virtbase;
- struct clk *clk;
- struct nmk_i2c_controller cfg;
- struct i2c_nmk_client cli;
- int stop;
- struct completion xfer_complete;
- int result;
- };
- /* controller's abort causes */
- static const char *abort_causes[] = {
- "no ack received after address transmission",
- "no ack received during data phase",
- "ack received after xmission of master code",
- "master lost arbitration",
- "slave restarts",
- "slave reset",
- "overflow, maxsize is 2047 bytes",
- };
- static inline void i2c_set_bit(void __iomem *reg, u32 mask)
- {
- writel(readl(reg) | mask, reg);
- }
- static inline void i2c_clr_bit(void __iomem *reg, u32 mask)
- {
- writel(readl(reg) & ~mask, reg);
- }
- /**
- * flush_i2c_fifo() - This function flushes the I2C FIFO
- * @dev: private data of I2C Driver
- *
- * This function flushes the I2C Tx and Rx FIFOs. It returns
- * 0 on successful flushing of FIFO
- */
- static int flush_i2c_fifo(struct nmk_i2c_dev *dev)
- {
- #define LOOP_ATTEMPTS 10
- int i;
- unsigned long timeout;
- /*
- * flush the transmit and receive FIFO. The flushing
- * operation takes several cycles before to be completed.
- * On the completion, the I2C internal logic clears these
- * bits, until then no one must access Tx, Rx FIFO and
- * should poll on these bits waiting for the completion.
- */
- writel((I2C_CR_FTX | I2C_CR_FRX), dev->virtbase + I2C_CR);
- for (i = 0; i < LOOP_ATTEMPTS; i++) {
- timeout = jiffies + msecs_to_jiffies(I2C_TIMEOUT_MS);
- while (!time_after(jiffies, timeout)) {
- if ((readl(dev->virtbase + I2C_CR) &
- (I2C_CR_FTX | I2C_CR_FRX)) == 0)
- return 0;
- }
- }
- dev_err(&dev->pdev->dev, "flushing operation timed out "
- "giving up after %d attempts", LOOP_ATTEMPTS);
- return -ETIMEDOUT;
- }
- /**
- * disable_all_interrupts() - Disable all interrupts of this I2c Bus
- * @dev: private data of I2C Driver
- */
- static void disable_all_interrupts(struct nmk_i2c_dev *dev)
- {
- u32 mask = IRQ_MASK(0);
- writel(mask, dev->virtbase + I2C_IMSCR);
- }
- /**
- * clear_all_interrupts() - Clear all interrupts of I2C Controller
- * @dev: private data of I2C Driver
- */
- static void clear_all_interrupts(struct nmk_i2c_dev *dev)
- {
- u32 mask;
- mask = IRQ_MASK(I2C_CLEAR_ALL_INTS);
- writel(mask, dev->virtbase + I2C_ICR);
- }
- /**
- * init_hw() - initialize the I2C hardware
- * @dev: private data of I2C Driver