diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-14 18:10:45 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-14 18:10:45 -0700 |
commit | c3a416a669eb83cfa9ccb52db030e72d654bd105 (patch) | |
tree | 518d00dc803fbb7d3772fc26a78b6bf3b797baf3 /drivers/i2c | |
parent | 8c194f3bd322a8bd44d079092d870549b8ae62d1 (diff) | |
parent | 2bbd681ba2bfa0f3805fb541b0840b96893c5727 (diff) |
Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
"Most notable:
- introducing the i2c_quirk infrastructure. Now, flaws of I2C
controllers can be described and the core will check if the flaws
collide with the messages to be sent
- wait_for_completion return type cleanup series
- new drivers for Digicolor, Netlogic XLP, Ingenic JZ4780
- updates to the I2C slave framework which include API changes. Its
only user was updated, too. Documentation was finally added
- changed dynamic bus numbering for the DT case. This could change
bus numbers for users. However, it fixes a collision where dynamic
and static busses request the same id.
- driver bugfixes, cleanups"
* 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (52 commits)
i2c: xlp9xx: Driver for Netlogic XLP9XX/5XX I2C controller
of: Add vendor prefix 'netlogic'
i2c: davinci: use ICPFUNC to toggle I2C as gpio for bus recovery
i2c: davinci: use bus recovery infrastructure
i2c: change input parameter to i2c_adapter for prepare/unprepare_recovery
i2c: i2c-mux-gpio: remove error messages for probe deferrals
i2c: jz4780: Add i2c bus controller driver for Ingenic JZ4780
i2c: dln2: set the device tree node of the adapter
i2c: davinci: fixup wait_for_completion_timeout handling
i2c: mpc: Fix ISR return value
i2c: slave-eeprom: add more info when to increase the pointer
i2c: slave: add documentation for i2c-slave-eeprom
Documentation: i2c: describe the new slave mode
i2c: slave: rework the slave API
i2c: add support for the Digicolor I2C controller
i2c: busses with dynamic ids should start after fixed ids for DT
of: base: add function to get highest id of an alias stem
i2c: designware: Suppress error message if platform_get_irq() < 0
i2c: mpc: assign the correct prescaler from SVR
i2c: img-scb: fixup of wait_for_completion_timeout return handling
...
Diffstat (limited to 'drivers/i2c')
34 files changed, 2122 insertions, 266 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 22da9c2ffa22..2255af23b9c7 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -485,6 +485,15 @@ config I2C_DESIGNWARE_BAYTRAIL the platform firmware controlling it. You should say Y if running on a BayTrail system using the AXP288. +config I2C_DIGICOLOR + tristate "Conexant Digicolor I2C driver" + depends on ARCH_DIGICOLOR + help + Support for Conexant Digicolor SoCs (CX92755) I2C controller driver. + + This driver can also be built as a module. If so, the module + will be called i2c-digicolor. + config I2C_EFM32 tristate "EFM32 I2C controller" depends on ARCH_EFM32 || COMPILE_TEST @@ -574,6 +583,15 @@ config I2C_IOP3XX This driver can also be built as a module. If so, the module will be called i2c-iop3xx. +config I2C_JZ4780 + tristate "JZ4780 I2C controller interface support" + depends on MACH_JZ4780 || COMPILE_TEST + help + If you say yes to this option, support will be included for the + Ingenic JZ4780 I2C controller. + + If you don't know what to do here, say N. + config I2C_KEMPLD tristate "Kontron COM I2C Controller" depends on MFD_KEMPLD @@ -898,6 +916,16 @@ config I2C_XLR This driver can also be built as a module. If so, the module will be called i2c-xlr. +config I2C_XLP9XX + tristate "XLP9XX I2C support" + depends on CPU_XLP || COMPILE_TEST + help + This driver enables support for the on-chip I2C interface of + the Broadcom XLP9xx/XLP5xx MIPS processors. + + This driver can also be built as a module. If so, the module will + be called i2c-xlp9xx. + config I2C_RCAR tristate "Renesas R-Car I2C Controller" depends on ARCH_SHMOBILE || COMPILE_TEST diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 3638feb6677e..cdf941da91c6 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -45,6 +45,7 @@ i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-platform-$(CONFIG_I2C_DESIGNWARE_BAYTRAIL) += i2c-designware-baytrail.o obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o i2c-designware-pci-objs := i2c-designware-pcidrv.o +obj-$(CONFIG_I2C_DIGICOLOR) += i2c-digicolor.o obj-$(CONFIG_I2C_EFM32) += i2c-efm32.o obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o obj-$(CONFIG_I2C_EXYNOS5) += i2c-exynos5.o @@ -55,6 +56,7 @@ obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o obj-$(CONFIG_I2C_IMG) += i2c-img-scb.o obj-$(CONFIG_I2C_IMX) += i2c-imx.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o +obj-$(CONFIG_I2C_JZ4780) += i2c-jz4780.o obj-$(CONFIG_I2C_KEMPLD) += i2c-kempld.o obj-$(CONFIG_I2C_MESON) += i2c-meson.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o @@ -87,6 +89,7 @@ obj-$(CONFIG_I2C_WMT) += i2c-wmt.o obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o obj-$(CONFIG_I2C_XLR) += i2c-xlr.o +obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o # External I2C/SMBus adapter drivers diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 636fd2efad88..ff23d1bdd230 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -381,6 +381,7 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id) static int at91_do_twi_transfer(struct at91_twi_dev *dev) { int ret; + unsigned long time_left; bool has_unre_flag = dev->pdata->has_unre_flag; dev_dbg(dev->dev, "transfer: %s %d bytes.\n", @@ -436,9 +437,9 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) } } - ret = wait_for_completion_timeout(&dev->cmd_complete, - dev->adapter.timeout); - if (ret == 0) { + time_left = wait_for_completion_timeout(&dev->cmd_complete, + dev->adapter.timeout); + if (time_left == 0) { dev_err(dev->dev, "controller timed out\n"); at91_init_twi_bus(dev); ret = -ETIMEDOUT; @@ -487,30 +488,10 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) if (ret < 0) goto out; - /* - * The hardware can handle at most two messages concatenated by a - * repeated start via it's internal address feature. - */ - if (num > 2) { - dev_err(dev->dev, - "cannot handle more than two concatenated messages.\n"); - ret = 0; - goto out; - } else if (num == 2) { + if (num == 2) { int internal_address = 0; int i; - if (msg->flags & I2C_M_RD) { - dev_err(dev->dev, "first transfer must be write.\n"); - ret = -EINVAL; - goto out; - } - if (msg->len > 3) { - dev_err(dev->dev, "first message size must be <= 3.\n"); - ret = -EINVAL; - goto out; - } - /* 1st msg is put into the internal address, start with 2nd */ m_start = &msg[1]; for (i = 0; i < msg->len; ++i) { @@ -540,6 +521,15 @@ out: return ret; } +/* + * The hardware can handle at most two messages concatenated by a + * repeated start via it's internal address feature. + */ +static struct i2c_adapter_quirks at91_twi_quirks = { + .flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | I2C_AQ_COMB_SAME_ADDR, + .max_comb_1st_msg_len = 3, +}; + static u32 at91_twi_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL @@ -777,6 +767,7 @@ static int at91_twi_probe(struct platform_device *pdev) dev->adapter.owner = THIS_MODULE; dev->adapter.class = I2C_CLASS_DEPRECATED; dev->adapter.algo = &at91_twi_algorithm; + dev->adapter.quirks = &at91_twi_quirks; dev->adapter.dev.parent = dev->dev; dev->adapter.nr = pdev->id; dev->adapter.timeout = AT91_I2C_TIMEOUT; diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index 768a598d8d03..32d883490863 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -334,12 +334,7 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg) u32 int_mask = MST_STATUS_ERR | MST_STATUS_SNS; u32 rx_xfer, tx_xfer; u32 addr_1, addr_2; - int ret; - - if (msg->len > 255) { - dev_warn(idev->dev, "unsupported length %u\n", msg->len); - return -EINVAL; - } + unsigned long time_left; idev->msg = msg; idev->msg_xfrd = 0; @@ -388,15 +383,15 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg) i2c_int_enable(idev, int_mask); - ret = wait_for_completion_timeout(&idev->msg_complete, - I2C_XFER_TIMEOUT); + time_left = wait_for_completion_timeout(&idev->msg_complete, + I2C_XFER_TIMEOUT); i2c_int_disable(idev, int_mask); if (readl(idev->base + MST_COMMAND) & CMD_BUSY) dev_warn(idev->dev, "busy after xfer\n"); - if (ret == 0) + if (time_left == 0) idev->msg_err = -ETIMEDOUT; if (unlikely(idev->msg_err) && idev->msg_err != -ENXIO) @@ -408,17 +403,17 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg) static int axxia_i2c_stop(struct axxia_i2c_dev *idev) { u32 int_mask = MST_STATUS_ERR | MST_STATUS_SCC; - int ret; + unsigned long time_left; reinit_completion(&idev->msg_complete); /* Issue stop */ writel(0xb, idev->base + MST_COMMAND); i2c_int_enable(idev, int_mask); - ret = wait_for_completion_timeout(&idev->msg_complete, - I2C_STOP_TIMEOUT); + time_left = wait_for_completion_timeout(&idev->msg_complete, + I2C_STOP_TIMEOUT); i2c_int_disable(idev, int_mask); - if (ret == 0) + if (time_left == 0) return -ETIMEDOUT; if (readl(idev->base + MST_COMMAND) & CMD_BUSY) @@ -454,6 +449,11 @@ static const struct i2c_algorithm axxia_i2c_algo = { .functionality = axxia_i2c_func, }; +static struct i2c_adapter_quirks axxia_i2c_quirks = { + .max_read_len = 255, + .max_write_len = 255, +}; + static int axxia_i2c_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -511,6 +511,7 @@ static int axxia_i2c_probe(struct platform_device *pdev) strlcpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name)); idev->adapter.owner = THIS_MODULE; idev->adapter.algo = &axxia_i2c_algo; + idev->adapter.quirks = &axxia_i2c_quirks; idev->adapter.dev.parent = &pdev->dev; idev->adapter.dev.of_node = pdev->dev.of_node; diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index d3c89157b337..f9f2c2082151 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -160,14 +160,6 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, u32 val; unsigned long time_left = msecs_to_jiffies(I2C_TIMEOUT_MESC); - /* need to reserve one byte in the FIFO for the slave address */ - if (msg->len > M_TX_RX_FIFO_SIZE - 1) { - dev_err(iproc_i2c->device, - "only support data length up to %u bytes\n", - M_TX_RX_FIFO_SIZE - 1); - return -EOPNOTSUPP; - } - /* check if bus is busy */ if (!!(readl(iproc_i2c->base + M_CMD_OFFSET) & BIT(M_CMD_START_BUSY_SHIFT))) { @@ -287,6 +279,12 @@ static const struct i2c_algorithm bcm_iproc_algo = { .functionality = bcm_iproc_i2c_functionality, }; +static struct i2c_adapter_quirks bcm_iproc_i2c_quirks = { + /* need to reserve one byte in the FIFO for the slave address */ + .max_read_len = M_TX_RX_FIFO_SIZE - 1, + .max_write_len = M_TX_RX_FIFO_SIZE - 1, +}; + static int bcm_iproc_i2c_cfg_speed(struct bcm_iproc_i2c_dev *iproc_i2c) { unsigned int bus_speed; @@ -413,6 +411,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(adap, iproc_i2c); strlcpy(adap->name, "Broadcom iProc I2C adapter", sizeof(adap->name)); adap->algo = &bcm_iproc_algo; + adap->quirks = &bcm_iproc_i2c_quirks; adap->dev.parent = &pdev->dev; adap->dev.of_node = pdev->dev.of_node; diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 5d6feb937b9d..c9336a3202d5 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -147,7 +147,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, struct i2c_msg *msg) { u32 c; - int time_left; + unsigned long time_left; i2c_dev->msg_buf = msg->buf; i2c_dev->msg_buf_remaining = msg->len; diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 7d7a14cdadfb..2ee78e099d30 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -475,7 +475,7 @@ static void cdns_i2c_master_reset(struct i2c_adapter *adap) static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg, struct i2c_adapter *adap) { - int ret; + unsigned long time_left; u32 reg; id->p_msg = msg; @@ -501,8 +501,8 @@ static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg, cdns_i2c_msend(id); /* Wait for the signal of completion */ - ret = wait_for_completion_timeout(&id->xfer_done, adap->timeout); - if (!ret) { + time_left = wait_for_completion_timeout(&id->xfer_done, adap->timeout); + if (time_left == 0) { cdns_i2c_master_reset(adap); dev_err(id->adap.dev.parent, "timeout waiting on completion\n"); diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 2d466538b2e2..714bdc837769 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -308,22 +308,12 @@ static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg; struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram; struct i2c_msg *pmsg; - int ret, i; + int ret; int tptr; int rptr; cbd_t __iomem *tbdf; cbd_t __iomem *rbdf; - if (num > CPM_MAXBD) - return -EINVAL; - - /* Check if we have any oversized READ requests */ - for (i = 0; i < num; i++) { - pmsg = &msgs[i]; - if (pmsg->len >= CPM_MAX_READ) - return -EINVAL; - } - /* Reset to use first buffer */ out_be16(&i2c_ram->rbptr, in_be16(&i2c_ram->rbase)); out_be16(&i2c_ram->tbptr, in_be16(&i2c_ram->tbase)); @@ -424,10 +414,18 @@ static const struct i2c_algorithm cpm_i2c_algo = { .functionality = cpm_i2c_func, }; +/* CPM_MAX_READ is also limiting writes according to the code! */ +static struct i2c_adapter_quirks cpm_i2c_quirks = { + .max_num_msgs = CPM_MAXBD, + .max_read_len = CPM_MAX_READ, + .max_write_len = CPM_MAX_READ, +}; + static const struct i2c_adapter cpm_ops = { .owner = THIS_MODULE, .name = "i2c-cpm", .algo = &cpm_i2c_algo, + .quirks = &cpm_i2c_quirks, }; static int cpm_i2c_setup(struct cpm_i2c *cpm) diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 6dc7ff5d3d9a..4788a32afb86 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -60,6 +60,12 @@ #define DAVINCI_I2C_IVR_REG 0x28 #define DAVINCI_I2C_EMDR_REG 0x2c #define DAVINCI_I2C_PSC_REG 0x30 +#define DAVINCI_I2C_FUNC_REG 0x48 +#define DAVINCI_I2C_DIR_REG 0x4c +#define DAVINCI_I2C_DIN_REG 0x50 +#define DAVINCI_I2C_DOUT_REG 0x54 +#define DAVINCI_I2C_DSET_REG 0x58 +#define DAVINCI_I2C_DCLR_REG 0x5c #define DAVINCI_I2C_IVR_AAS 0x07 #define DAVINCI_I2C_IVR_SCD 0x06 @@ -93,6 +99,29 @@ #define DAVINCI_I2C_IMR_NACK BIT(1) #define DAVINCI_I2C_IMR_AL BIT(0) +/* set SDA and SCL as GPIO */ +#define DAVINCI_I2C_FUNC_PFUNC0 BIT(0) + +/* set SCL as output when used as GPIO*/ +#define DAVINCI_I2C_DIR_PDIR0 BIT(0) +/* set SDA as output when used as GPIO*/ +#define DAVINCI_I2C_DIR_PDIR1 BIT(1) + +/* read SCL GPIO level */ +#define DAVINCI_I2C_DIN_PDIN0 BIT(0) +/* read SDA GPIO level */ +#define DAVINCI_I2C_DIN_PDIN1 BIT(1) + +/*set the SCL GPIO high */ +#define DAVINCI_I2C_DSET_PDSET0 BIT(0) +/*set the SDA GPIO high */ +#define DAVINCI_I2C_DSET_PDSET1 BIT(1) + +/* set the SCL GPIO low */ +#define DAVINCI_I2C_DCLR_PDCLR0 BIT(0) +/* set the SDA GPIO low */ +#define DAVINCI_I2C_DCLR_PDCLR1 BIT(1) + struct davinci_i2c_dev { struct device *dev; void __iomem *base; @@ -129,43 +158,6 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg) return readw_relaxed(i2c_dev->base + reg); } -/* Generate a pulse on the i2c clock pin. */ -static void davinci_i2c_clock_pulse(unsigned int scl_pin) -{ - u16 i; - - if (scl_pin) { - /* Send high and low on the SCL line */ - for (i = 0; i < 9; i++) { - gpio_set_value(scl_pin, 0); - udelay(20); - gpio_set_value(scl_pin, 1); - udelay(20); - } - } -} - -/* This routine does i2c bus recovery as specified in the - * i2c protocol Rev. 03 section 3.16 titled "Bus clear" - */ -static void davinci_i2c_recover_bus(struct davinci_i2c_dev *dev) -{ - u32 flag = 0; - struct davinci_i2c_platform_data *pdata = dev->pdata; - - dev_err(dev->dev, "initiating i2c bus recovery\n"); - /* Send NACK to the slave */ - flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); - flag |= DAVINCI_I2C_MDR_NACK; - /* write the data into mode register */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); - davinci_i2c_clock_pulse(pdata->scl_pin); - /* Send STOP */ - flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); - flag |= DAVINCI_I2C_MDR_STP; - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); -} - static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev, int val) { @@ -263,6 +255,99 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) } /* + * This routine does i2c bus recovery by using i2c_generic_gpio_recovery + * which is provided by I2C Bus recovery infrastructure. + */ +static void davinci_i2c_prepare_recovery(struct i2c_adapter *adap) +{ + struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); + + /* Disable interrupts */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, 0); + + /* put I2C into reset */ + davinci_i2c_reset_ctrl(dev, 0); +} + +static void davinci_i2c_unprepare_recovery(struct i2c_adapter *adap) +{ + struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); + + i2c_davinci_init(dev); +} + +static struct i2c_bus_recovery_info davinci_i2c_gpio_recovery_info = { + .recover_bus = i2c_generic_gpio_recovery, + .prepare_recovery = davinci_i2c_prepare_recovery, + .unprepare_recovery = davinci_i2c_unprepare_recovery, +}; + +static void davinci_i2c_set_scl(struct i2c_adapter *adap, int val) +{ + struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); + + if (val) + davinci_i2c_write_reg(dev, DAVINCI_I2C_DSET_REG, + DAVINCI_I2C_DSET_PDSET0); + else + davinci_i2c_write_reg(dev, DAVINCI_I2C_DCLR_REG, + DAVINCI_I2C_DCLR_PDCLR0); +} + +static int davinci_i2c_get_scl(struct i2c_adapter *adap) +{ + struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); + int val; + + /* read the state of SCL */ + val = davinci_i2c_read_reg(dev, DAVINCI_I2C_DIN_REG); + return val & DAVINCI_I2C_DIN_PDIN0; +} + +static int davinci_i2c_get_sda(struct i2c_adapter *adap) +{ + struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); + int val; + + /* read the state of SDA */ + val = davinci_i2c_read_reg(dev, DAVINCI_I2C_DIN_REG); + return val & DAVINCI_I2C_DIN_PDIN1; +} + +static void davinci_i2c_scl_prepare_recovery(struct i2c_adapter *adap) +{ + struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); + + davinci_i2c_prepare_recovery(adap); + + /* SCL output, SDA input */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_DIR_REG, DAVINCI_I2C_DIR_PDIR0); + + /* change to GPIO mode */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_FUNC_REG, + DAVINCI_I2C_FUNC_PFUNC0); +} + +static void davinci_i2c_scl_unprepare_recovery(struct i2c_adapter *adap) +{ + struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); + + /* change back to I2C mode */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_FUNC_REG, 0); + + davinci_i2c_unprepare_recovery(adap); +} + +static struct i2c_bus_recovery_info davinci_i2c_scl_recovery_info = { + .recover_bus = i2c_generic_scl_recovery, + .set_scl = davinci_i2c_set_scl, + .get_scl = davinci_i2c_get_scl, + .get_sda = davinci_i2c_get_sda, + .prepare_recovery = davinci_i2c_scl_prepare_recovery, + .unprepare_recovery = davinci_i2c_scl_unprepare_recovery, +}; + +/* * Waiting for bus not busy */ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev, @@ -282,8 +367,7 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev, return -ETIMEDOUT; } else { to_cnt = 0; - davinci_i2c_recover_bus(dev); - i2c_davinci_init(dev); + i2c_recover_bus(&dev->adapter); } } if (allow_sleep) @@ -304,7 +388,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) struct davinci_i2c_platform_data *pdata = dev->pdata; u32 flag; u16 w; - int r; + unsigned long time_left; /* Introduce a delay, required for some boards (e.g Davinci EVM) */ if (pdata->bus_delay) @@ -368,11 +452,11 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) flag |= DAVINCI_I2C_MDR_STP; davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); - r = wait_for_completion_timeout(&dev->cmd_complete, dev->adapter.timeout); - if (r == 0) { + time_left = wait_for_completion_timeout(&dev->cmd_complete, + dev->adapter.timeout); + if (!time_left) { dev_err(dev->dev, "controller timed out\n"); - davinci_i2c_recover_bus(dev); - i2c_davinci_init(dev); + i2c_recover_bus(adap); dev->buf_len = 0; return -ETIMEDOUT; } @@ -380,17 +464,13 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) /* This should be 0 if all bytes were transferred * or dev->cmd_err denotes an error. */ - if (r >= 0) { - dev_err(dev->dev, "abnormal termination buf_len=%i\n", - dev->buf_len); - r = -EREMOTEIO; - } + dev_err(dev->dev, "abnormal termination buf_len=%i\n", + dev->buf_len); dev->terminate = 1; wmb(); dev->buf_len = 0; + return -EREMOTEIO; } - if (r < 0) - return r; /* no error */ if (likely(!dev->cmd_err)) @@ -674,6 +754,10 @@ static int davinci_i2c_probe(struct platform_device *pdev) if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency", &prop)) dev->pdata->bus_freq = prop / 1000; + + dev->pdata->has_pfunc = + of_property_read_bool(pdev->dev.of_node, + "ti,has-pfunc"); } else if (!dev->pdata) { dev->pdata = &davinci_i2c_platform_data_default; } @@ -715,6 +799,14 @@ static int davinci_i2c_probe(struct platform_device *pdev) adap->timeout = DAVINCI_I2C_TIMEOUT; adap->dev.of_node = pdev->dev.of_node; + if (dev->pdata->has_pfunc) + adap->bus_recovery_info = &davinci_i2c_scl_recovery_info; + else if (dev->pdata->scl_pin) { + adap->bus_recovery_info = &davinci_i2c_gpio_recovery_info; + adap->bus_recovery_info->scl_gpio = dev->pdata->scl_pin; + adap->bus_recovery_info->sda_gpio = dev->pdata->sda_pin; + } + adap->nr = pdev->id; r = i2c_add_numbered_adapter(adap); if (r) { diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 6e25c010e690..6f19a33773fe 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -656,8 +656,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) i2c_dw_xfer_init(dev); /* wait for tx to complete */ - ret = wait_for_completion_timeout(&dev->cmd_complete, HZ); - if (ret == 0) { + if (!wait_for_completion_timeout(&dev->cmd_complete, HZ)) { dev_err(dev->dev, "controller timed out\n"); /* i2c_dw_init implicitly disables the adapter */ i2c_dw_init(dev); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index c270f5f9a8f9..fa4e2b521f0d 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -143,10 +143,8 @@ static int dw_i2c_probe(struct platform_device *pdev) u32 clk_freq, ht = 0; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); - return irq; /* -ENXIO */ - } + if (irq < 0) + return irq; dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL); if (!dev) diff --git a/drivers/i2c/busses/i2c-digicolor.c b/drivers/i2c/busses/i2c-digicolor.c new file mode 100644 index 000000000000..03f1e5549896 --- /dev/null +++ b/drivers/i2c/busses/i2c-digicolor.c @@ -0,0 +1,385 @@ +/* + * I2C bus driver for Conexant Digicolor SoCs + * + * Author: Baruch Siach <baruch@tkos.co.il> + * + * Copyright (C) 2015 Paradox Innovation Ltd. + * + * 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/clk.h> +#include <linux/completion.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +#define DEFAULT_FREQ 100000 +#define TIMEOUT_MS 100 + +#define II_CONTROL 0x0 +#define II_CONTROL_LOCAL_RESET BIT(0) + +#define II_CLOCKTIME 0x1 + +#define II_COMMAND 0x2 +#define II_CMD_START 1 +#define II_CMD_RESTART 2 +#define II_CMD_SEND_ACK 3 +#define II_CMD_GET_ACK 6 +#define II_CMD_GET_NOACK 7 +#define II_CMD_STOP 10 +#define II_COMMAND_GO BIT(7) +#define II_COMMAND_COMPLETION_STATUS(r) (((r) >> 5) & 3) +#define II_CMD_STATUS_NORMAL 0 +#define II_CMD_STATUS_ACK_GOOD 1 +#define II_CMD_STATUS_ACK_BAD 2 +#define II_CMD_STATUS_ABORT 3 + +#define II_DATA 0x3 +#define II_INTFLAG_CLEAR 0x8 +#define II_INTENABLE 0xa + +struct dc_i2c { + struct i2c_adapter adap; + struct device *dev; + void __iomem *regs; + struct clk *clk; + unsigned int frequency; + + struct i2c_msg *msg; + unsigned int msgbuf_ptr; + int last; + spinlock_t lock; + struct completion done; + int state; + int error; +}; + +enum { + STATE_IDLE, + STATE_START, + STATE_ADDR, + STATE_WRITE, + STATE_READ, + STATE_STOP, +}; + +static void dc_i2c_cmd(struct dc_i2c *i2c, u8 cmd) +{ + writeb_relaxed(cmd | II_COMMAND_GO, i2c->regs + II_COMMAND); +} + +static u8 dc_i2c_addr_cmd(struct i2c_msg *msg) +{ + u8 addr = (msg->addr & 0x |