// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2009 ST-Ericsson SA * Copyright (C) 2009 STMicroelectronics * * I2C master mode controller driver, used in Nomadik 8815 * and Ux500 platforms. * * The Mobileye EyeQ5 and EyeQ6H platforms are also supported; they use * the same Ux500/DB8500 IP block with two quirks: * - The memory bus only supports 32-bit accesses. * - (only EyeQ5) A register must be configured for the I2C speed mode; * it is located in a shared register region called OLB. * * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> * Author: Sachin Verma <sachin.verma@st.com>
*/ #include <linux/amba/bus.h> #include <linux/bitfield.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/slab.h>
/* some bits in ICR are reserved */ #define I2C_CLEAR_ALL_INTS 0x131f007f
/* maximum threshold value */ #define MAX_I2C_FIFO_THRESHOLD 15
enum i2c_freq_mode {
I2C_FREQ_MODE_STANDARD, /* up to 100 Kb/s */
I2C_FREQ_MODE_FAST, /* up to 400 Kb/s */
I2C_FREQ_MODE_HIGH_SPEED, /* up to 3.4 Mb/s */
I2C_FREQ_MODE_FAST_PLUS, /* up to 1 Mb/s */
};
/* Mobileye EyeQ5 offset into a shared register region (called OLB) */ #define NMK_I2C_EYEQ5_OLB_IOCR2 0x0B8
/** * struct i2c_nmk_client - client specific data * @slave_adr: 7-bit slave address * @count: no. bytes to be transferred * @buffer: client data buffer * @xfer_bytes: bytes transferred till now * @operation: current I2C operation
*/ struct i2c_nmk_client { unsignedshort slave_adr; unsignedlong count; unsignedchar *buffer; unsignedlong xfer_bytes; enum i2c_operation operation;
};
/** * struct nmk_i2c_dev - private data structure of the controller. * @vendor: vendor data for this variant. * @adev: parent amba device. * @adap: corresponding I2C adapter. * @irq: interrupt line for the controller. * @virtbase: virtual io memory area. * @clk: hardware i2c block clock. * @cli: holder of client specific data. * @clk_freq: clock frequency for the operation mode * @tft: Tx FIFO Threshold in bytes * @rft: Rx FIFO Threshold in bytes * @timeout_usecs: Slave response timeout * @sm: speed mode * @stop: stop condition. * @xfer_wq: xfer done wait queue. * @xfer_done: xfer done boolean. * @result: controller propogated result. * @has_32b_bus: controller is on a bus that only supports 32-bit accesses.
*/ struct nmk_i2c_dev { struct i2c_vendor_data *vendor; struct amba_device *adev; struct i2c_adapter adap; int irq; void __iomem *virtbase; struct clk *clk; struct i2c_nmk_client cli;
u32 clk_freq; unsignedchar tft; unsignedchar rft;
u32 timeout_usecs; enum i2c_freq_mode sm; int stop; struct wait_queue_head xfer_wq; bool xfer_done; int result; bool has_32b_bus;
};
/* controller's abort causes */ staticconstchar *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",
};
/** * flush_i2c_fifo() - This function flushes the I2C FIFO * @priv: private data of I2C Driver * * This function flushes the I2C Tx and Rx FIFOs. It returns * 0 on successful flushing of FIFO
*/ staticint flush_i2c_fifo(struct nmk_i2c_dev *priv)
{ #define LOOP_ATTEMPTS 10
ktime_t timeout; int i;
/* * 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), priv->virtbase + I2C_CR);
for (i = 0; i < LOOP_ATTEMPTS; i++) {
timeout = ktime_add_us(ktime_get(), priv->timeout_usecs);
while (ktime_after(timeout, ktime_get())) { if ((readl(priv->virtbase + I2C_CR) &
(I2C_CR_FTX | I2C_CR_FRX)) == 0) return 0;
}
}
dev_err(&priv->adev->dev, "flushing operation timed out giving up after %d attempts",
LOOP_ATTEMPTS);
return -ETIMEDOUT;
}
/** * disable_all_interrupts() - Disable all interrupts of this I2c Bus * @priv: private data of I2C Driver
*/ staticvoid disable_all_interrupts(struct nmk_i2c_dev *priv)
{
writel(0, priv->virtbase + I2C_IMSCR);
}
/** * clear_all_interrupts() - Clear all interrupts of I2C Controller * @priv: private data of I2C Driver
*/ staticvoid clear_all_interrupts(struct nmk_i2c_dev *priv)
{
writel(I2C_CLEAR_ALL_INTS, priv->virtbase + I2C_ICR);
}
/** * init_hw() - initialize the I2C hardware * @priv: private data of I2C Driver
*/ staticint init_hw(struct nmk_i2c_dev *priv)
{ int stat;
stat = flush_i2c_fifo(priv); if (stat) gotoexit;
/* disable the controller */
i2c_clr_bit(priv->virtbase + I2C_CR, I2C_CR_PE);
if (unlikely(flags & I2C_M_TEN)) { /* 10-bit address transaction */
mcr |= FIELD_PREP(I2C_MCR_AM, 2); /* * Get the top 3 bits. * EA10 represents extended address in MCR. This includes * the extension (MSB bits) of the 7 bit address loaded * in A7
*/
slave_adr_3msb_bits = FIELD_GET(ADR_3MSB_BITS,
priv->cli.slave_adr);
/* * set the slsu: * * slsu defines the data setup time after SCL clock * stretching in terms of i2c clk cycles + 1 (zero means * "wait one cycle"), the needed setup time for the three * modes are 250ns, 100ns, 10ns respectively. * * As the time for one cycle T in nanoseconds is * T = (1/f) * 1000000000 => * slsu = cycles / (1000000000 / f) + 1
*/
ns = DIV_ROUND_UP_ULL(1000000000ULL, i2c_clk); switch (priv->sm) { case I2C_FREQ_MODE_FAST: case I2C_FREQ_MODE_FAST_PLUS:
slsu = DIV_ROUND_UP(100, ns); /* Fast */ break; case I2C_FREQ_MODE_HIGH_SPEED:
slsu = DIV_ROUND_UP(10, ns); /* High */ break; case I2C_FREQ_MODE_STANDARD: default:
slsu = DIV_ROUND_UP(250, ns); /* Standard */ break;
}
slsu += 1;
/* * The spec says, in case of std. mode the divider is * 2 whereas it is 3 for fast and fastplus mode of * operation.
*/
div = (priv->clk_freq > I2C_MAX_STANDARD_MODE_FREQ) ? 3 : 2;
/* * generate the mask for baud rate counters. The controller * has two baud rate counters. One is used for High speed * operation, and the other is for std, fast mode, fast mode * plus operation. * * BRCR is a clock divider amount. Pick highest value that * leads to rate strictly below target. Eg when asking for * 400kHz you want a bus rate <=400kHz (and not >=400kHz).
*/
brcr = DIV_ROUND_UP(i2c_clk, priv->clk_freq * div);
/** * read_i2c() - Read from I2C client device * @priv: private data of I2C Driver * @flags: message flags * * This function reads from i2c client device when controller is in * master mode. There is a completion timeout. If there is no transfer * before timeout error is returned.
*/ staticint read_i2c(struct nmk_i2c_dev *priv, u16 flags)
{
u32 mcr, irq_mask; int status = 0; bool xfer_done;
/* enable interrupts by settings the masks */
irq_mask = (I2C_IT_TXFOVR | I2C_IT_MAL | I2C_IT_BERR);
/* Fill the TX FIFO with transmit data */
fill_tx_fifo(priv, MAX_I2C_FIFO_THRESHOLD);
if (priv->cli.count != 0)
irq_mask |= I2C_IT_TXFNE;
/* * check if we want to transfer a single or multiple bytes, if so * set the MTDWS bit (Master Transaction Done Without Stop) * to start repeated start operation
*/ if (priv->stop || !priv->vendor->has_mtdws)
irq_mask |= I2C_IT_MTD; else
irq_mask |= I2C_IT_MTDWS;
if (!xfer_done) { /* Controller timed out */
dev_err(&priv->adev->dev, "write to slave 0x%x timed out\n",
priv->cli.slave_adr);
status = -ETIMEDOUT;
}
return status;
}
/** * nmk_i2c_xfer_one() - transmit a single I2C message * @priv: device with a message encoded into it * @flags: message flags
*/ staticint nmk_i2c_xfer_one(struct nmk_i2c_dev *priv, u16 flags)
{ int status;
if (status || priv->result) {
u32 i2c_sr;
u32 cause;
i2c_sr = readl(priv->virtbase + I2C_SR); if (FIELD_GET(I2C_SR_STATUS, i2c_sr) == I2C_ABORT) {
cause = FIELD_GET(I2C_SR_CAUSE, i2c_sr);
dev_err(&priv->adev->dev, "%s\n",
cause >= ARRAY_SIZE(abort_causes) ? "unknown reason" :
abort_causes[cause]);
}
init_hw(priv);
status = status ? status : priv->result;
}
return status;
}
/** * nmk_i2c_xfer() - I2C transfer function used by kernel framework * @i2c_adap: Adapter pointer to the controller * @msgs: Pointer to data to be written. * @num_msgs: Number of messages to be executed * * This is the function called by the generic kernel i2c_transfer() * or i2c_smbus...() API calls. Note that this code is protected by the * semaphore set in the kernel i2c_transfer() function. * * NOTE: * READ TRANSFER : We impose a restriction of the first message to be the * index message for any read transaction. * - a no index is coded as '0', * - 2byte big endian index is coded as '3' * !!! msg[0].buf holds the actual index. * This is compatible with generic messages of smbus emulator * that send a one byte index. * eg. a I2C transation to read 2 bytes from index 0 * idx = 0; * msg[0].addr = client->addr; * msg[0].flags = 0x0; * msg[0].len = 1; * msg[0].buf = &idx; * * msg[1].addr = client->addr; * msg[1].flags = I2C_M_RD; * msg[1].len = 2; * msg[1].buf = rd_buff * i2c_transfer(adap, msg, 2); * * WRITE TRANSFER : The I2C standard interface interprets all data as payload. * If you want to emulate an SMBUS write transaction put the * index as first byte(or first and second) in the payload. * eg. a I2C transation to write 2 bytes from index 1 * wr_buff[0] = 0x1; * wr_buff[1] = 0x23; * wr_buff[2] = 0x46; * msg[0].flags = 0x0; * msg[0].len = 3; * msg[0].buf = wr_buff; * i2c_transfer(adap, msg, 1); * * To read or write a block of data (multiple bytes) using SMBUS emulation * please use the i2c_smbus_read_i2c_block_data() * or i2c_smbus_write_i2c_block_data() API
*/ staticint nmk_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num_msgs)
{ int status = 0; int i; struct nmk_i2c_dev *priv = i2c_get_adapdata(i2c_adap); int j;
pm_runtime_get_sync(&priv->adev->dev);
/* Attempt three times to send the message queue */ for (j = 0; j < 3; j++) { /* setup the i2c controller */
setup_i2c_controller(priv);
for (i = 0; i < num_msgs; i++) {
priv->cli.slave_adr = msgs[i].addr;
priv->cli.buffer = msgs[i].buf;
priv->cli.count = msgs[i].len;
priv->stop = (i < (num_msgs - 1)) ? 0 : 1;
priv->result = 0;
status = nmk_i2c_xfer_one(priv, msgs[i].flags); if (status != 0) break;
} if (status == 0) break;
}
pm_runtime_put_sync(&priv->adev->dev);
/* return the no. messages processed */ if (status) return status; else return num_msgs;
}
/** * disable_interrupts() - disable the interrupts * @priv: private data of controller * @irq: interrupt number
*/ staticint disable_interrupts(struct nmk_i2c_dev *priv, u32 irq)
{
irq &= I2C_CLEAR_ALL_INTS;
writel(readl(priv->virtbase + I2C_IMSCR) & ~irq,
priv->virtbase + I2C_IMSCR); return 0;
}
/** * i2c_irq_handler() - interrupt routine * @irq: interrupt number * @arg: data passed to the handler * * This is the interrupt handler for the i2c driver. Currently * it handles the major interrupts like Rx & Tx FIFO management * interrupts, master transaction interrupts, arbitration and * bus error interrupts. The rest of the interrupts are treated as * unhandled.
*/ static irqreturn_t i2c_irq_handler(int irq, void *arg)
{ struct nmk_i2c_dev *priv = arg; struct device *dev = &priv->adev->dev;
u32 tft, rft;
u32 count;
u32 misr, src;
/* read interrupt status register */
misr = readl(priv->virtbase + I2C_MISR);
src = __ffs(misr); switch (BIT(src)) {
/* Transmit FIFO nearly empty interrupt */ case I2C_IT_TXFNE:
{ if (priv->cli.operation == I2C_READ) { /* * in read operation why do we care for writing? * so disable the Transmit FIFO interrupt
*/
disable_interrupts(priv, I2C_IT_TXFNE);
} else {
fill_tx_fifo(priv, (MAX_I2C_FIFO_THRESHOLD - tft)); /* * if done, close the transfer by disabling the * corresponding TXFNE interrupt
*/ if (priv->cli.count == 0)
disable_interrupts(priv, I2C_IT_TXFNE);
}
} break;
/* * Rx FIFO nearly full interrupt. * This is set when the numer of entries in Rx FIFO is * greater or equal than the threshold value programmed * in RFT
*/ case I2C_IT_RXFNF: for (count = rft; count > 0; count--) { /* Read the Rx FIFO */
*priv->cli.buffer = nmk_i2c_readb(priv, I2C_RFR);
priv->cli.buffer++;
}
priv->cli.count -= rft;
priv->cli.xfer_bytes += rft; break;
/* Rx FIFO full */ case I2C_IT_RXFF: for (count = MAX_I2C_FIFO_THRESHOLD; count > 0; count--) {
*priv->cli.buffer = nmk_i2c_readb(priv, I2C_RFR);
priv->cli.buffer++;
}
priv->cli.count -= MAX_I2C_FIFO_THRESHOLD;
priv->cli.xfer_bytes += MAX_I2C_FIFO_THRESHOLD; break;
/* Master Transaction Done with/without stop */ case I2C_IT_MTD: case I2C_IT_MTDWS: if (priv->cli.operation == I2C_READ) { while (!(readl(priv->virtbase + I2C_RISR)
& I2C_IT_RXFE)) { if (priv->cli.count == 0) break;
*priv->cli.buffer =
nmk_i2c_readb(priv, I2C_RFR);
priv->cli.buffer++;
priv->cli.count--;
priv->cli.xfer_bytes++;
}
}
/* * Tx FIFO overrun interrupt. * This is set when a write operation in Tx FIFO is performed and * the Tx FIFO is full.
*/ case I2C_IT_TXFOVR:
priv->result = -EIO;
init_hw(priv);
dev_err(dev, "Tx Fifo Over run\n");
priv->xfer_done = true;
wake_up(&priv->xfer_wq);
break;
/* unhandled interrupts by this driver - TODO*/ case I2C_IT_TXFE: case I2C_IT_TXFF: case I2C_IT_RXFE: case I2C_IT_RFSR: case I2C_IT_RFSE: case I2C_IT_WTSR: case I2C_IT_STD:
dev_err(dev, "unhandled Interrupt\n"); break; default:
dev_err(dev, "spurious Interrupt..\n"); break;
}
return IRQ_HANDLED;
}
staticint nmk_i2c_suspend_late(struct device *dev)
{ int ret;
ret = pm_runtime_force_suspend(dev); if (ret) return ret;
/* Default to 100 kHz if no frequency is given in the node */ if (of_property_read_u32(np, "clock-frequency", &priv->clk_freq))
priv->clk_freq = I2C_MAX_STANDARD_MODE_FREQ;
/* * We do not want to attach a .of_match_table to our amba driver. * Do not convert to device_get_match_data().
*/
match = of_match_device(nmk_i2c_eyeq_match_table, dev); if (match)
match_flags = (unsignedlong)match->data;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.