From 9d3dda5c0d092d6bc9911bf24de81350d47c6be6 Mon Sep 17 00:00:00 2001 From: Leilei Shang Date: Fri, 7 Jun 2013 14:38:17 +0800 Subject: i2c: pxa: enable high speed mode for i2c bus To enter high speed mode, following steps should be done: 1. When running in high speed mode, i2c clock rate is different from standard mode. Clock rate must be set according to specification first. 2. When i2c controller sends a master code and wins arbitration, high speed mode is entered. If you want to enable high speed mode, the following members of platform data should be set to proper value: 1. "high_mode" should be set to "1". 2. "master_code" should be set to "8'b 0000_1xxx"(x is 0 or 1). If no master_code is set, set to default value 0xe. 3. "rate" should be set according to specification. Signed-off-by: Leilei Shang Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index fbafed2..a61d906 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -110,6 +110,8 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table); #define ICR_SADIE (1 << 13) /* slave address detected int enable */ #define ICR_UR (1 << 14) /* unit reset */ #define ICR_FM (1 << 15) /* fast mode */ +#define ICR_HS (1 << 16) /* High Speed mode */ +#define ICR_GPIOEN (1 << 19) /* enable GPIO mode for SCL in HS */ #define ISR_RWM (1 << 0) /* read/write mode */ #define ISR_ACKNAK (1 << 1) /* ack/nak status */ @@ -155,6 +157,10 @@ struct pxa_i2c { int irq; unsigned int use_pio :1; unsigned int fast_mode :1; + unsigned int high_mode:1; + unsigned char master_code; + unsigned long rate; + bool highmode_enter; }; #define _IBMR(i2c) ((i2c)->reg_ibmr) @@ -459,6 +465,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c) /* set control register values */ writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c)); + writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c)); #ifdef CONFIG_I2C_PXA_SLAVE dev_info(&i2c->adap.dev, "Enabling slave mode\n"); @@ -680,6 +687,34 @@ static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c) return 0; } +/* + * PXA I2C send master code + * 1. Load master code to IDBR and send it. + * Note for HS mode, set ICR [GPIOEN]. + * 2. Wait until win arbitration. + */ +static int i2c_pxa_send_mastercode(struct pxa_i2c *i2c) +{ + u32 icr; + long timeout; + + spin_lock_irq(&i2c->lock); + i2c->highmode_enter = true; + writel(i2c->master_code, _IDBR(i2c)); + + icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE); + icr |= ICR_GPIOEN | ICR_START | ICR_TB | ICR_ITEIE; + writel(icr, _ICR(i2c)); + + spin_unlock_irq(&i2c->lock); + timeout = wait_event_timeout(i2c->wait, + i2c->highmode_enter == false, HZ * 1); + + i2c->highmode_enter = false; + + return (timeout == 0) ? I2C_RETRY : 0; +} + static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) { @@ -743,6 +778,14 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) goto out; } + if (i2c->high_mode) { + ret = i2c_pxa_send_mastercode(i2c); + if (ret) { + dev_err(&i2c->adap.dev, "i2c_pxa_send_mastercode timeout\n"); + goto out; + } + } + spin_lock_irq(&i2c->lock); i2c->msg = msg; @@ -990,11 +1033,14 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id) i2c_pxa_slave_txempty(i2c, isr); if (isr & ISR_IRF) i2c_pxa_slave_rxfull(i2c, isr); - } else if (i2c->msg) { + } else if (i2c->msg && (!i2c->highmode_enter)) { if (isr & ISR_ITE) i2c_pxa_irq_txempty(i2c, isr); if (isr & ISR_IRF) i2c_pxa_irq_rxfull(i2c, isr); + } else if ((isr & ISR_ITE) && i2c->highmode_enter) { + i2c->highmode_enter = false; + wake_up(&i2c->wait); } else { i2c_pxa_scream_blue_murder(i2c, "spurious irq"); } @@ -1079,6 +1125,11 @@ static int i2c_pxa_probe_pdata(struct platform_device *pdev, if (plat) { i2c->use_pio = plat->use_pio; i2c->fast_mode = plat->fast_mode; + i2c->high_mode = plat->high_mode; + i2c->master_code = plat->master_code; + if (!i2c->master_code) + i2c->master_code = 0xe; + i2c->rate = plat->rate; } return 0; } @@ -1151,6 +1202,7 @@ static int i2c_pxa_probe(struct platform_device *dev) i2c->irq = irq; i2c->slave_addr = I2C_PXA_SLAVE_ADDR; + i2c->highmode_enter = false; if (plat) { #ifdef CONFIG_I2C_PXA_SLAVE @@ -1160,6 +1212,16 @@ static int i2c_pxa_probe(struct platform_device *dev) i2c->adap.class = plat->class; } + if (i2c->high_mode) { + if (i2c->rate) { + clk_set_rate(i2c->clk, i2c->rate); + pr_info("i2c: <%s> set rate to %ld\n", + i2c->adap.name, clk_get_rate(i2c->clk)); + } else + pr_warn("i2c: <%s> clock rate not set\n", + i2c->adap.name); + } + clk_prepare_enable(i2c->clk); if (i2c->use_pio) { diff --git a/include/linux/i2c/pxa-i2c.h b/include/linux/i2c/pxa-i2c.h index 1a9f65e..53aab24 100644 --- a/include/linux/i2c/pxa-i2c.h +++ b/include/linux/i2c/pxa-i2c.h @@ -67,6 +67,9 @@ struct i2c_pxa_platform_data { unsigned int class; unsigned int use_pio :1; unsigned int fast_mode :1; + unsigned int high_mode:1; + unsigned char master_code; + unsigned long rate; }; extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info); -- cgit v0.10.2 From 825642455367e5498da82a8044dd345ac7869c8d Mon Sep 17 00:00:00 2001 From: "Chew, Chiau Ee" Date: Fri, 21 Jun 2013 15:05:28 +0800 Subject: i2c: designware: Manually set RESTART bit between messages If both IC_EMPTYFIFO_HOLD_MASTER_EN and IC_RESTART_EN are set to 1, the Designware I2C controller doesn't generate RESTART unless user specifically requests it by setting RESTART bit in IC_DATA_CMD register. Since IC_EMPTYFIFO_HOLD_MASTER_EN setting can't be detected from hardware register, we must always manually set the restart bit between messages. Signed-off-by: Chew, Chiau Ee Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index ad46616..f325ec7 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -416,6 +416,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) u32 addr = msgs[dev->msg_write_idx].addr; u32 buf_len = dev->tx_buf_len; u8 *buf = dev->tx_buf; + bool need_restart = false; intr_mask = DW_IC_INTR_DEFAULT_MASK; @@ -443,6 +444,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) /* new i2c_msg */ buf = msgs[dev->msg_write_idx].buf; buf_len = msgs[dev->msg_write_idx].len; + + /* If both IC_EMPTYFIFO_HOLD_MASTER_EN and + * IC_RESTART_EN are set, we must manually + * set restart bit between messages. + */ + if ((dev->master_cfg & DW_IC_CON_RESTART_EN) && + (dev->msg_write_idx > 0)) + need_restart = true; } tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR); @@ -461,6 +470,11 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) buf_len == 1) cmd |= BIT(9); + if (need_restart) { + cmd |= BIT(10); + need_restart = false; + } + if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { /* avoid rx buffer overrun */ -- cgit v0.10.2 From 3923172b3d700486c1ca24df9c4c5405a83e2309 Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Wed, 26 Jun 2013 10:56:35 +0300 Subject: i2c: reduce parent checking to a NOOP in non-I2C_MUX case In 0826374 - i2c: Multiplexed I2C bus core support core i2c code increased in size and complexity even when I2C_MUX wasn't selected. Turning this check into a constant NULL in the n case lets the client functions in be simplified too, not needing to include never-called calls to the mux-specific helpers. Signed-off-by: Phil Carmody Signed-off-by: Wolfram Sang diff --git a/include/linux/i2c.h b/include/linux/i2c.h index e988fa9..b3c4b8d 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -447,11 +447,13 @@ static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data) static inline struct i2c_adapter * i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter) { +#if IS_ENABLED(I2C_MUX) struct device *parent = adapter->dev.parent; if (parent != NULL && parent->type == &i2c_adapter_type) return to_i2c_adapter(parent); else +#endif return NULL; } -- cgit v0.10.2 From c66c4cc087eb1f5307f6391e467797227aed758a Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Thu, 1 Aug 2013 14:10:46 +0200 Subject: i2c: add sanity check to i2c_put_adapter i2c_put_adapter dereferences i2c_adapter pointer passed without check for NULL. This adds a check for non-NULL pointer to allow i2c_put_adapter called with NULL and behave the same way i2c_release_client does already. It allows to simplify drivers where you need to release the adapter during probe failures. Signed-off-by: Sebastian Hesselbarth Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index f32ca29..d075df6 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1825,7 +1825,8 @@ EXPORT_SYMBOL(i2c_get_adapter); void i2c_put_adapter(struct i2c_adapter *adap) { - module_put(adap->owner); + if (adap) + module_put(adap->owner); } EXPORT_SYMBOL(i2c_put_adapter); -- cgit v0.10.2 From 421476aeed56a8d19c890ae6729e3c43b740da7a Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 10 Jul 2013 12:03:21 -0700 Subject: i2c: mpc: Define unique I2C adapter names The I2C adapters on Freescale MPC107/824x/85xx/512x/52xx/83xx/86xx all have the same name "MPC adapter". Since I2C adapter numbers can change across reboots and even after loading/unloading an I2C bus master driver, adapter names have to be used to identify adapters and thus should be unique and well defined. Since this is not the case with this driver, it is difficult if not impossible to identify a specific adapter from user space on affected platforms. To remedy the problem, use the adapter memory address as part of the adapter name. With this patch, adapter names are: On P2020: MPC adapter at 0xfff703000 MPC adapter at 0xfff703100 On P5040: MPC adapter at 0xffe118000 MPC adapter at 0xffe118100 MPC adapter at 0xffe119000 MPC adapter at 0xffe119100 Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 7607dc0..99acf63 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -609,7 +609,6 @@ static const struct i2c_algorithm mpc_algo = { static struct i2c_adapter mpc_ops = { .owner = THIS_MODULE, - .name = "MPC adapter", .algo = &mpc_algo, .timeout = HZ, }; @@ -623,6 +622,7 @@ static int fsl_i2c_probe(struct platform_device *op) u32 clock = MPC_I2C_CLOCK_LEGACY; int result = 0; int plen; + struct resource res; match = of_match_device(mpc_i2c_of_match, &op->dev); if (!match) @@ -682,6 +682,9 @@ static int fsl_i2c_probe(struct platform_device *op) platform_set_drvdata(op, i2c); i2c->adap = mpc_ops; + of_address_to_resource(op->dev.of_node, 0, &res); + scnprintf(i2c->adap.name, sizeof(i2c->adap.name), + "MPC adapter at 0x%llx", (unsigned long long)res.start); i2c_set_adapdata(&i2c->adap, i2c); i2c->adap.dev.parent = &op->dev; i2c->adap.dev.of_node = of_node_get(op->dev.of_node); -- cgit v0.10.2 From 3f97b62faba952baca59307ef38e8e5594405fb9 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 10 Jul 2013 16:57:37 +0100 Subject: drivers/i2c/busses: don't use devm_pinctrl_get_select_default() in probe Since commit ab78029 (drivers/pinctrl: grab default handles from device core), we can rely on device core for setting the default pins. Compile tested only. Acked-by: Linus Walleij (personally at LCE13) Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 142b694d..d09512e 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -43,7 +43,6 @@ #include #include #include -#include /* I2C controller revisions */ #define OMAP_I2C_OMAP1_REV_2 0x20 @@ -216,8 +215,6 @@ struct omap_i2c_dev { u16 syscstate; u16 westate; u16 errata; - - struct pinctrl *pins; }; static const u8 reg_map_ip_v1[] = { @@ -1120,16 +1117,6 @@ omap_i2c_probe(struct platform_device *pdev) dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; } - dev->pins = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(dev->pins)) { - if (PTR_ERR(dev->pins) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - dev_warn(&pdev->dev, "did not get pins for i2c error: %li\n", - PTR_ERR(dev->pins)); - dev->pins = NULL; - } - dev->dev = &pdev->dev; dev->irq = irq; -- cgit v0.10.2 From 2806914f5d027c225c7562a0f2dd7e20c3ba8beb Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 23 Jul 2013 20:01:39 +0200 Subject: drivers/i2c/busses: don't check resource with devm_ioremap_resource devm_ioremap_resource does sanity checks on the given resource. No need to duplicate this in the driver. Signed-off-by: Wolfram Sang Acked-by: Linus Walleij diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index d1a6b20..ded21cf 100644 --- a/drivers/i2c/busses/i2c-stu300.c +++ b/drivers/i2c/busses/i2c-stu300.c @@ -884,9 +884,6 @@ stu300_probe(struct platform_device *pdev) dev->pdev = pdev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENOENT; - dev->virtbase = devm_ioremap_resource(&pdev->dev, res); dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual " "base %p\n", bus_nr, dev->virtbase); -- cgit v0.10.2 From 63151c539d790732f22d59d4c89766dd9b5284d2 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 10 Jul 2013 22:19:28 -0300 Subject: i2c: mxs: Check the return value from stmp_reset_block() stmp_reset_block() may fail, so let's check its return value and propagate it in the case of error. Signed-off-by: Fabio Estevam Acked-by: Marek Vasut Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index e2e9a0d..43e2273 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -123,9 +123,11 @@ struct mxs_i2c_dev { bool dma_read; }; -static void mxs_i2c_reset(struct mxs_i2c_dev *i2c) +static int mxs_i2c_reset(struct mxs_i2c_dev *i2c) { - stmp_reset_block(i2c->regs); + int ret = stmp_reset_block(i2c->regs); + if (ret) + return ret; /* * Configure timing for the I2C block. The I2C TIMING2 register has to @@ -139,6 +141,8 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c) writel(0x00300030, i2c->regs + MXS_I2C_TIMING2); writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); + + return 0; } static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c) @@ -475,7 +479,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) { struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap); - int ret; + int ret, err; int flags; flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0; @@ -495,8 +499,11 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, i2c->cmd_err = 0; if (0) { /* disable PIO mode until a proper fix is made */ ret = mxs_i2c_pio_setup_xfer(adap, msg, flags); - if (ret) - mxs_i2c_reset(i2c); + if (ret) { + err = mxs_i2c_reset(i2c); + if (err) + return err; + } } else { INIT_COMPLETION(i2c->cmd_complete); ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); @@ -527,7 +534,10 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, timeout: dev_dbg(i2c->dev, "Timeout!\n"); mxs_i2c_dma_finish(i2c); - mxs_i2c_reset(i2c); + ret = mxs_i2c_reset(i2c); + if (ret) + return ret; + return -ETIMEDOUT; } @@ -683,7 +693,9 @@ static int mxs_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, i2c); /* Do reset to enforce correct startup after pinmuxing */ - mxs_i2c_reset(i2c); + err = mxs_i2c_reset(i2c); + if (err) + return err; adap = &i2c->adapter; strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name)); -- cgit v0.10.2 From 0a488c49eac0ad851b1afbf12b345e2adaf3775c Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 15 Jul 2013 11:28:23 +0900 Subject: i2c: i2c-mpc: add CONFIG_PM_SLEEP to suspend/resume functions Add CONFIG_PM_SLEEP to suspend/resume functions to fix the following build warning when CONFIG_PM_SLEEP is not selected. This is because sleep PM callbacks defined by SIMPLE_DEV_PM_OPS are only used when the CONFIG_PM_SLEEP is enabled. drivers/i2c/busses/i2c-mpc.c:724:12: warning: 'mpc_i2c_suspend' defined but not used [-Wunused-function] drivers/i2c/busses/i2c-mpc.c:734:12: warning: 'mpc_i2c_resume' defined but not used [-Wunused-function] Also, this patch makes mpc_i2c_pm_ops static, because mpc_i2c_pm_ops is not exported. Signed-off-by: Jingoo Han Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 99acf63..ffac214 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -64,7 +64,7 @@ struct mpc_i2c { struct i2c_adapter adap; int irq; u32 real_clk; -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP u8 fdr, dfsrr; #endif }; @@ -723,7 +723,7 @@ static int fsl_i2c_remove(struct platform_device *op) return 0; }; -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int mpc_i2c_suspend(struct device *dev) { struct mpc_i2c *i2c = dev_get_drvdata(dev); @@ -744,7 +744,10 @@ static int mpc_i2c_resume(struct device *dev) return 0; } -SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume); +static SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume); +#define MPC_I2C_PM_OPS (&mpc_i2c_pm_ops) +#else +#define MPC_I2C_PM_OPS NULL #endif static const struct mpc_i2c_data mpc_i2c_data_512x = { @@ -791,9 +794,7 @@ static struct platform_driver mpc_i2c_driver = { .owner = THIS_MODULE, .name = DRV_NAME, .of_match_table = mpc_i2c_of_match, -#ifdef CONFIG_PM - .pm = &mpc_i2c_pm_ops, -#endif + .pm = MPC_I2C_PM_OPS, }, }; -- cgit v0.10.2 From dfb03fb246dc893743a28d00966b1862ae836f2d Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 15 Jul 2013 11:28:59 +0900 Subject: i2c: designware: add CONFIG_PM_SLEEP to suspend/resume functions Add CONFIG_PM_SLEEP to suspend/resume functions to fix the following build warning when CONFIG_PM_SLEEP is not selected. This is because sleep PM callbacks defined by SIMPLE_DEV_PM_OPS are only used when the CONFIG_PM_SLEEP is enabled. drivers/i2c/busses/i2c-designware-platdrv.c:211:12: warning: 'dw_i2c_suspend' defined but not used [-Wunused-function] drivers/i2c/busses/i2c-designware-platdrv.c:221:12: warning: 'dw_i2c_resume' defined but not used [-Wunused-function] Signed-off-by: Jingoo Han Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 4c5fada..64ffb90 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -207,7 +207,7 @@ static const struct of_device_id dw_i2c_of_match[] = { MODULE_DEVICE_TABLE(of, dw_i2c_of_match); #endif -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int dw_i2c_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -228,9 +228,12 @@ static int dw_i2c_resume(struct device *dev) return 0; } -#endif static SIMPLE_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, dw_i2c_resume); +#define DW_I2C_DEV_PM_OPS (&dw_i2c_dev_pm_ops) +#else +#define DW_I2C_DEV_PM_OPS NULL +#endif /* work with hotplug and coldplug */ MODULE_ALIAS("platform:i2c_designware"); @@ -242,7 +245,7 @@ static struct platform_driver dw_i2c_driver = { .owner = THIS_MODULE, .of_match_table = of_match_ptr(dw_i2c_of_match), .acpi_match_table = ACPI_PTR(dw_i2c_acpi_match), - .pm = &dw_i2c_dev_pm_ops, + .pm = DW_I2C_DEV_PM_OPS, }, }; -- cgit v0.10.2 From f076e91635dc519352110497d50a5104194702e5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 15 Jul 2013 11:29:35 +0900 Subject: i2c: ocores: add CONFIG_PM_SLEEP to suspend/resume functions Add CONFIG_PM_SLEEP to suspend/resume functions to fix the following build warning when CONFIG_PM_SLEEP is not selected. This is because sleep PM callbacks defined by SIMPLE_DEV_PM_OPS are only used when the CONFIG_PM_SLEEP is enabled. drivers/i2c/busses/i2c-ocores.c:460:12: warning: 'ocores_i2c_suspend' defined but not used [-Wunused-function] drivers/i2c/busses/i2c-ocores.c:471:12: warning: 'ocores_i2c_resume' defined but not used [-Wunused-function] Signed-off-by: Jingoo Han Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 0e1f824..bdae4ca 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -456,7 +456,7 @@ static int ocores_i2c_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int ocores_i2c_suspend(struct device *dev) { struct ocores_i2c *i2c = dev_get_drvdata(dev); -- cgit v0.10.2 From 71f1260e713bc663ade4b200bfff7cfc97bf34a1 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 15 Jul 2013 11:29:56 +0900 Subject: i2c: stu300: add CONFIG_PM_SLEEP to suspend/resume functions Add CONFIG_PM_SLEEP to suspend/resume functions to fix the following build warning when CONFIG_PM_SLEEP is not selected. This is because sleep PM callbacks defined by SIMPLE_DEV_PM_OPS are only used when the CONFIG_PM_SLEEP is enabled. drivers/i2c/busses/i2c-stu300.c:945:12: warning: 'stu300_suspend' defined but not used [-Wunused-function] drivers/i2c/busses/i2c-stu300.c:954:12: warning: 'stu300_resume' defined but not used [-Wunused-function] Signed-off-by: Jingoo Han Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index ded21cf..19a40af 100644 --- a/drivers/i2c/busses/i2c-stu300.c +++ b/drivers/i2c/busses/i2c-stu300.c @@ -938,7 +938,7 @@ stu300_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int stu300_suspend(struct device *device) { struct stu300_dev *dev = dev_get_drvdata(device); -- cgit v0.10.2 From d2f185343d22a4cc8432d74dba641607cd91e8e5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 15 Jul 2013 11:30:17 +0900 Subject: i2c: pnx: add CONFIG_PM_SLEEP to suspend/resume functions Add CONFIG_PM_SLEEP to suspend/resume functions to fix the following build warning when CONFIG_PM_SLEEP is not selected. This is because sleep PM callbacks defined by SIMPLE_DEV_PM_OPS are only used when the CONFIG_PM_SLEEP is enabled. drivers/i2c/busses/i2c-pnx.c:599:12: warning: 'i2c_pnx_controller_suspend' defined but not used [-Wunused-function] drivers/i2c/busses/i2c-pnx.c:608:12: warning: 'i2c_pnx_controller_resume' defined but not used [-Wunused-function] Signed-off-by: Jingoo Han Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 5f39c6d..1713b3e 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -595,7 +595,7 @@ static struct i2c_algorithm pnx_algorithm = { .functionality = i2c_pnx_func, }; -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int i2c_pnx_controller_suspend(struct device *dev) { struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev); -- cgit v0.10.2 From c6a88fa60c7cd500f8368345ee98e472daf4ed04 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 15 Jul 2013 11:30:36 +0900 Subject: i2c: puv3: add CONFIG_PM_SLEEP to suspend function Add CONFIG_PM_SLEEP to suspend function to fix the following build warning when CONFIG_PM_SLEEP is not selected. This is because sleep PM callbacks defined by SIMPLE_DEV_PM_OPS are only used when the CONFIG_PM_SLEEP is enabled. drivers/i2c/busses/i2c-puv3.c:249:12: warning: 'puv3_i2c_suspend' defined but not used [-Wunused-function] Signed-off-by: Jingoo Han Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c index 37a84c8..ac80199 100644 --- a/drivers/i2c/busses/i2c-puv3.c +++ b/drivers/i2c/busses/i2c-puv3.c @@ -245,7 +245,7 @@ static int puv3_i2c_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int puv3_i2c_suspend(struct device *dev) { int poll_count; -- cgit v0.10.2 From 2fb9ac0cb446ab6ae8add7d9987b42bbfccd94b9 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 15 Jul 2013 11:30:57 +0900 Subject: i2c: i2c-bfin-twi: add CONFIG_PM_SLEEP to suspend/resume functions Add CONFIG_PM_SLEEP to suspend/resume functions to fix the following build warning when CONFIG_PM_SLEEP is not selected. This is because sleep PM callbacks defined by SIMPLE_DEV_PM_OPS are only used when the CONFIG_PM_SLEEP is enabled. drivers/i2c/busses/i2c-bfin-twi.c:585:12: warning: 'i2c_bfin_twi_suspend' defined but not used [-Wunused-function] drivers/i2c/busses/i2c-bfin-twi.c:600:12: warning: 'i2c_bfin_twi_resume' defined but not used [-Wunused-function] Signed-off-by: Jingoo Han Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index 13ea1c2..37d4239 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -582,6 +582,7 @@ static struct i2c_algorithm bfin_twi_algorithm = { .functionality = bfin_twi_functionality, }; +#ifdef CONFIG_PM_SLEEP static int i2c_bfin_twi_suspend(struct device *dev) { struct bfin_twi_iface *iface = dev_get_drvdata(dev); @@ -619,6 +620,10 @@ static int i2c_bfin_twi_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(i2c_bfin_twi_pm, i2c_bfin_twi_suspend, i2c_bfin_twi_resume); +#define I2C_BFIN_TWI_PM_OPS (&i2c_bfin_twi_pm) +#else +#define I2C_BFIN_TWI_PM_OPS NULL +#endif static int i2c_bfin_twi_probe(struct platform_device *pdev) { @@ -746,7 +751,7 @@ static struct platform_driver i2c_bfin_twi_driver = { .driver = { .name = "i2c-bfin-twi", .owner = THIS_MODULE, - .pm = &i2c_bfin_twi_pm, + .pm = I2C_BFIN_TWI_PM_OPS, }, }; -- cgit v0.10.2 From 9adad4dfd121bb529ef028d3785310275ccbcc47 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 25 Jul 2013 16:59:25 -0400 Subject: i2c: davinci: remove useless mach/hardware include This driver no longer uses definitions from mach/hardware.h. On the other hand, including this header breaks this driver on non-davinci platforms which don't have such a header. Acked-by: Sekhar Nori Signed-off-by: Santosh Shilimkar Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index fa55605..5898df3 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -40,8 +40,6 @@ #include #include #include - -#include #include /* ----- global defines ----------------------------------------------- */ -- cgit v0.10.2 From d654b5489eb4950cddf6d72a5c3a2fb1cab4f15b Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Wed, 24 Jul 2013 20:28:19 -0400 Subject: i2c: davinci: Allow i2c driver available for keystone platforms Keystone SOCs uses the same I2C IP as available on DaVinci SOCs. Update the config so that ARCH_KEYSTONE can use it. Signed-off-by: Santosh Shilimkar Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index dc6dea6..fcdd321 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -385,7 +385,7 @@ config I2C_CPM config I2C_DAVINCI tristate "DaVinci I2C driver" - depends on ARCH_DAVINCI + depends on ARCH_DAVINCI || ARCH_KEYSTONE help Support for TI DaVinci I2C controller driver. -- cgit v0.10.2 From d63a9e851c2c007d9129b8dbfc1af24722bd18bd Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 17 Jul 2013 13:27:59 -0700 Subject: i2c: Improve logging on failure to probe for ->class devices While writing the i2c-imc driver, I noticed that the warning message when the i2c core can't figure out how to probe is mostly useless. This trivial patch improves it. Signed-off-by: Andy Lutomirski Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index d075df6..3d9ca2d 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1665,7 +1665,8 @@ static int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr) err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &dummy); else { - dev_warn(&adap->dev, "No suitable probing method supported\n"); + dev_warn(&adap->dev, "No suitable probing method supported for address 0x%02X\n", + addr); err = -EOPNOTSUPP; } -- cgit v0.10.2 From a94dd00f2e1c20deacffadaaa6eebf73b217c907 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Sun, 14 Jul 2013 23:17:26 +0200 Subject: i2c: piix4: Add support for secondary SMBus on AMD SB800 and AMD FCH chipsets Add support for the secondary SMBus controller on the AMD SB800 and AMD FCH chipsets. Signed-off-by: Rudolf Marek Tested-by: Paul Menzel Signed-off-by: Wolfram Sang diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index a370b20..c097e0f 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -73,9 +73,10 @@ this driver on those mainboards. The ServerWorks Southbridges, the Intel 440MX, and the Victory66 are identical to the PIIX4 in I2C/SMBus support. -The AMD SB700 and SP5100 chipsets implement two PIIX4-compatible SMBus -controllers. If your BIOS initializes the secondary controller, it will -be detected by this driver as an "Auxiliary SMBus Host Controller". +The AMD SB700, SB800, SP5100 and Hudson-2 chipsets implement two +PIIX4-compatible SMBus controllers. If your BIOS initializes the +secondary controller, it will be detected by this driver as +an "Auxiliary SMBus Host Controller". If you own Force CPCI735 motherboard or other OSB4 based systems you may need to change the SMBus Interrupt Select register so the SMBus controller uses diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index d05ad59..a028617 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -231,11 +231,11 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, } static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, - const struct pci_device_id *id) + const struct pci_device_id *id, u8 aux) { unsigned short piix4_smba; unsigned short smba_idx = 0xcd6; - u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en = 0x2c; + u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en; /* SB800 and later SMBus does not support forcing address */ if (force || force_addr) { @@ -245,6 +245,8 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, } /* Determine the address of the SMBus areas */ + smb_en = (aux) ? 0x28 : 0x2c; + if (!request_region(smba_idx, 2, "smba_idx")) { dev_err(&PIIX4_dev->dev, "SMBus base address index region " "0x%x already in use!\n", smba_idx); @@ -272,6 +274,13 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, return -EBUSY; } + /* Aux SMBus does not support IRQ information */ + if (aux) { + dev_info(&PIIX4_dev->dev, + "SMBus Host Controller at 0x%x\n", piix4_smba); + return piix4_smba; + } + /* Request the SMBus I2C bus config region */ if (!request_region(piix4_smba + i2ccfg_offset, 1, "i2ccfg")) { dev_err(&PIIX4_dev->dev, "SMBus I2C bus config region " @@ -597,7 +606,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) dev->revision >= 0x40) || dev->vendor == PCI_VENDOR_ID_AMD) /* base address location etc changed in SB800 */ - retval = piix4_setup_sb800(dev, id); + retval = piix4_setup_sb800(dev, id, 0); else retval = piix4_setup(dev, id); @@ -611,17 +620,29 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) return retval; /* Check for auxiliary SMBus on some AMD chipsets */ + retval = -ENODEV; + if (dev->vendor == PCI_VENDOR_ID_ATI && - dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && - dev->revision < 0x40) { - retval = piix4_setup_aux(dev, id, 0x58); - if (retval > 0) { - /* Try to add the aux adapter if it exists, - * piix4_add_adapter will clean up if this fails */ - piix4_add_adapter(dev, retval, &piix4_aux_adapter); + dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS) { + if (dev->revision < 0x40) { + retval = piix4_setup_aux(dev, id, 0x58); + } else { + /* SB800 added aux bus too */ + retval = piix4_setup_sb800(dev, id, 1); } } + if (dev->vendor == PCI_VENDOR_ID_AMD && + dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) { + retval = piix4_setup_sb800(dev, id, 1); + } + + if (retval > 0) { + /* Try to add the aux adapter if it exists, + * piix4_add_adapter will clean up if this fails */ + piix4_add_adapter(dev, retval, &piix4_aux_adapter); + } + return 0; } -- cgit v0.10.2 From d533f0492b6371025a4f88506c7f1828a7a48e81 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Wed, 7 Aug 2013 17:05:36 +0800 Subject: i2c: imx: use struct representing i2c clk{div, val} pair using struct representing the i2c clk{div, val} pair would make the i2c_clk_div array more clear. Signed-off-by: Jingchang Lu Reviewed-by: Sascha Hauer Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index e242797..9167d43 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -30,6 +30,8 @@ * Copyright (C) 2007 RightHand Technologies, Inc. * Copyright (C) 2008 Darius Augulis * + * Copyright 2013 Freescale Semiconductor, Inc. + * */ /** Includes ******************************************************************* @@ -95,8 +97,12 @@ * * Duplicated divider values removed from list */ +struct imx_i2c_clk_pair { + u16 div; + u16 val; +}; -static u16 __initdata i2c_clk_div[50][2] = { +static struct imx_i2c_clk_pair __initdata i2c_clk_div[] = { { 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 }, { 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 }, { 40, 0x26 }, { 42, 0x03 }, { 44, 0x27 }, { 48, 0x28 }, { 52, 0x05 }, @@ -274,15 +280,15 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, /* Divider value calculation */ i2c_clk_rate = clk_get_rate(i2c_imx->clk); div = (i2c_clk_rate + rate - 1) / rate; - if (div < i2c_clk_div[0][0]) + if (div < i2c_clk_div[0].div) i = 0; - else if (div > i2c_clk_div[ARRAY_SIZE(i2c_clk_div) - 1][0]) + else if (div > i2c_clk_div[ARRAY_SIZE(i2c_clk_div) - 1].div) i = ARRAY_SIZE(i2c_clk_div) - 1; else - for (i = 0; i2c_clk_div[i][0] < div; i++); + for (i = 0; i2c_clk_div[i].div < div; i++); /* Store divider value */ - i2c_imx->ifdr = i2c_clk_div[i][1]; + i2c_imx->ifdr = i2c_clk_div[i].val; /* * There dummy delay is calculated. @@ -290,7 +296,7 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, * This delay is used in I2C bus disable function * to fix chip hardware bug. */ - i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] + i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); /* dev_dbg() can't be used, because adapter is not yet registered */ @@ -298,7 +304,7 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n", __func__, i2c_clk_rate, div); dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n", - __func__, i2c_clk_div[i][1], i2c_clk_div[i][0]); + __func__, i2c_clk_div[i].val, i2c_clk_div[i].div); #endif } -- cgit v0.10.2 From 46f2832b9f66b008fb813fe153f27794412fbc4f Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Wed, 7 Aug 2013 17:05:37 +0800 Subject: i2c: imx: enable clk before write to registers The module clk should be enabled before write to its register in probe(), and the clk can be disabled after. Signed-off-by: Jingchang Lu Reviewed-by: Sascha Hauer Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 9167d43..7adb351 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -543,6 +543,11 @@ static int __init i2c_imx_probe(struct platform_device *pdev) return PTR_ERR(i2c_imx->clk); } + ret = clk_prepare_enable(i2c_imx->clk); + if (ret) { + dev_err(&pdev->dev, "can't enable I2C clock\n"); + return ret; + } /* Request IRQ */ ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0, pdev->name, i2c_imx); @@ -580,6 +585,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) /* Set up platform driver data */ platform_set_drvdata(pdev, i2c_imx); + clk_disable_unprepare(i2c_imx->clk); dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq); dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n", -- cgit v0.10.2 From 0fc1347a7fdbcc25204f737998b824fc46662afd Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Wed, 7 Aug 2013 17:05:38 +0800 Subject: i2c: imx: don't change platform device id_entry directly The id_entry field should be changed by platform driver core, driver should prevent changing it derectly. Use local variable to save and extract platform_device_id info of the dts devices instead. Signed-off-by: Jingchang Lu Reviewed-by: Sascha Hauer Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 7adb351..cbea84b 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -499,6 +499,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) struct imx_i2c_struct *i2c_imx; struct resource *res; struct imxi2c_platform_data *pdata = pdev->dev.platform_data; + const struct platform_device_id *imx_id; void __iomem *base; int irq, ret; u32 bitrate; @@ -524,8 +525,11 @@ static int __init i2c_imx_probe(struct platform_device *pdev) } if (of_id) - pdev->id_entry = of_id->data; - i2c_imx->devtype = pdev->id_entry->driver_data; + imx_id = of_id->data; + else + imx_id = platform_get_device_id(pdev); + + i2c_imx->devtype = imx_id->driver_data; /* Setup i2c_imx driver structure */ strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name)); -- cgit v0.10.2 From 1d5ef2a83e3097408924b5eea8d7750bbde21e45 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Wed, 7 Aug 2013 17:05:39 +0800 Subject: i2c: imx: wrap registers read/write to inline function wrap the readb(), writeb() into inline function calls. It would make the driver more clearer to support platform with different register offset. Signed-off-by: Jingchang Lu Reviewed-by: Sascha Hauer Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index cbea84b..1a3c608 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -160,6 +160,18 @@ static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx) return i2c_imx->devtype == IMX1_I2C; } +static inline void imx_i2c_write_reg(unsigned int val, + struct imx_i2c_struct *i2c_imx, unsigned int reg) +{ + writeb(val, i2c_imx->base + reg); +} + +static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx, + unsigned int reg) +{ + return readb(i2c_imx->base + reg); +} + /** Functions for IMX I2C adapter driver *************************************** *******************************************************************************/ @@ -171,7 +183,7 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); while (1) { - temp = readb(i2c_imx->base + IMX_I2C_I2SR); + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); if (for_busy && (temp & I2SR_IBB)) break; if (!for_busy && !(temp & I2SR_IBB)) @@ -202,7 +214,7 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx) { - if (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_RXAK) { + if (imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR) & I2SR_RXAK) { dev_dbg(&i2c_imx->adapter.dev, "<%s> No ACK\n", __func__); return -EIO; /* No ACK */ } @@ -219,25 +231,25 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); clk_prepare_enable(i2c_imx->clk); - writeb(i2c_imx->ifdr, i2c_imx->base + IMX_I2C_IFDR); + imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR); /* Enable I2C controller */ - writeb(0, i2c_imx->base + IMX_I2C_I2SR); - writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR); + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); + imx_i2c_write_reg(I2CR_IEN, i2c_imx, IMX_I2C_I2CR); /* Wait controller to be stable */ udelay(50); /* Start I2C transaction */ - temp = readb(i2c_imx->base + IMX_I2C_I2CR); + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp |= I2CR_MSTA; - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); result = i2c_imx_bus_busy(i2c_imx, 1); if (result) return result; i2c_imx->stopped = 0; temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK; - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); return result; } @@ -248,9 +260,9 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) if (!i2c_imx->stopped) { /* Stop I2C transaction */ dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - temp = readb(i2c_imx->base + IMX_I2C_I2CR); + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); } if (is_imx1_i2c(i2c_imx)) { /* @@ -266,7 +278,7 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) } /* Disable I2C controller */ - writeb(0, i2c_imx->base + IMX_I2C_I2CR); + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR); clk_disable_unprepare(i2c_imx->clk); } @@ -313,12 +325,12 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) struct imx_i2c_struct *i2c_imx = dev_id; unsigned int temp; - temp = readb(i2c_imx->base + IMX_I2C_I2SR); + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); if (temp & I2SR_IIF) { /* save status register */ i2c_imx->i2csr = temp; temp &= ~I2SR_IIF; - writeb(temp, i2c_imx->base + IMX_I2C_I2SR); + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); wake_up(&i2c_imx->queue); return IRQ_HANDLED; } @@ -334,7 +346,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) __func__, msgs->addr << 1); /* write slave address */ - writeb(msgs->addr << 1, i2c_imx->base + IMX_I2C_I2DR); + imx_i2c_write_reg(msgs->addr << 1, i2c_imx, IMX_I2C_I2DR); result = i2c_imx_trx_complete(i2c_imx); if (result) return result; @@ -348,7 +360,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) dev_dbg(&i2c_imx->adapter.dev, "<%s> write byte: B%d=0x%X\n", __func__, i, msgs->buf[i]); - writeb(msgs->buf[i], i2c_imx->base + IMX_I2C_I2DR); + imx_i2c_write_reg(msgs->buf[i], i2c_imx, IMX_I2C_I2DR); result = i2c_imx_trx_complete(i2c_imx); if (result) return result; @@ -369,7 +381,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) __func__, (msgs->addr << 1) | 0x01); /* write slave address */ - writeb((msgs->addr << 1) | 0x01, i2c_imx->base + IMX_I2C_I2DR); + imx_i2c_write_reg((msgs->addr << 1) | 0x01, i2c_imx, IMX_I2C_I2DR); result = i2c_imx_trx_complete(i2c_imx); if (result) return result; @@ -380,12 +392,12 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) dev_dbg(&i2c_imx->adapter.dev, "<%s> setup bus\n", __func__); /* setup bus to read data */ - temp = readb(i2c_imx->base + IMX_I2C_I2CR); + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp &= ~I2CR_MTX; if (msgs->len - 1) temp &= ~I2CR_TXAK; - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); - readb(i2c_imx->base + IMX_I2C_I2DR); /* dummy read */ + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); + imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */ dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__); @@ -399,19 +411,19 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) controller from generating another clock cycle */ dev_dbg(&i2c_imx->adapter.dev, "<%s> clear MSTA\n", __func__); - temp = readb(i2c_imx->base + IMX_I2C_I2CR); + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); i2c_imx_bus_busy(i2c_imx, 0); i2c_imx->stopped = 1; } else if (i == (msgs->len - 2)) { dev_dbg(&i2c_imx->adapter.dev, "<%s> set TXAK\n", __func__); - temp = readb(i2c_imx->base + IMX_I2C_I2CR); + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp |= I2CR_TXAK; - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); } - msgs->buf[i] = readb(i2c_imx->base + IMX_I2C_I2DR); + msgs->buf[i] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); dev_dbg(&i2c_imx->adapter.dev, "<%s> read byte: B%d=0x%X\n", __func__, i, msgs->buf[i]); @@ -438,9 +450,9 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, if (i) { dev_dbg(&i2c_imx->adapter.dev, "<%s> repeated start\n", __func__); - temp = readb(i2c_imx->base + IMX_I2C_I2CR); + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp |= I2CR_RSTA; - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); result = i2c_imx_bus_busy(i2c_imx, 1); if (result) goto fail0; @@ -449,13 +461,13 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, "<%s> transfer message: %d\n", __func__, i); /* write/read data */ #ifdef CONFIG_I2C_DEBUG_BUS - temp = readb(i2c_imx->base + IMX_I2C_I2CR); + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); dev_dbg(&i2c_imx->adapter.dev, "<%s> CONTROL: IEN=%d, IIEN=%d, " "MSTA=%d, MTX=%d, TXAK=%d, RSTA=%d\n", __func__, (temp & I2CR_IEN ? 1 : 0), (temp & I2CR_IIEN ? 1 : 0), (temp & I2CR_MSTA ? 1 : 0), (temp & I2CR_MTX ? 1 : 0), (temp & I2CR_TXAK ? 1 : 0), (temp & I2CR_RSTA ? 1 : 0)); - temp = readb(i2c_imx->base + IMX_I2C_I2SR); + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); dev_dbg(&i2c_imx->adapter.dev, "<%s> STATUS: ICF=%d, IAAS=%d, IBB=%d, " "IAL=%d, SRW=%d, IIF=%d, RXAK=%d\n", __func__, @@ -575,8 +587,8 @@ static int __init i2c_imx_probe(struct platform_device *pdev) i2c_imx_set_clk(i2c_imx, bitrate); /* Set up chip registers to defaults */ - writeb(0, i2c_imx->base + IMX_I2C_I2CR); - writeb(0, i2c_imx->base + IMX_I2C_I2SR); + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR); + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); /* Add I2C adapter */ ret = i2c_add_numbered_adapter(&i2c_imx->adapter); @@ -612,10 +624,10 @@ static int __exit i2c_imx_remove(struct platform_device *pdev) i2c_del_adapter(&i2c_imx->adapter); /* setup chip registers to defaults */ - writeb(0, i2c_imx->base + IMX_I2C_IADR); - writeb(0, i2c_imx->base + IMX_I2C_IFDR); - writeb(0, i2c_imx->base + IMX_I2C_I2CR); - writeb(0, i2c_imx->base + IMX_I2C_I2SR); + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR); + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IFDR); + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR); + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); return 0; } -- cgit v0.10.2 From 8cc7331ff372b9d03f8b2eb1422052bd99430611 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Wed, 7 Aug 2013 17:05:40 +0800 Subject: i2c: imx: change register offset representation the I2C register offset may different between SoCs, to provid support for all these chips, split the register offset into a fixed base address and a variable shift value, then the full register offset will be calculated by reg_off = ( reg_base_addr << reg_shift) Signed-off-by: Jingchang Lu Reviewed-by: Sascha Hauer Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 1a3c608..8a292a9 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -64,12 +64,21 @@ /* Default value */ #define IMX_I2C_BIT_RATE 100000 /* 100kHz */ -/* IMX I2C registers */ +/* IMX I2C registers: + * the I2C register offset is different between SoCs, + * to provid support for all these chips, split the + * register offset into a fixed base address and a + * variable shift value, then the full register offset + * will be calculated by + * reg_off = ( reg_base_addr << reg_shift) + */ #define IMX_I2C_IADR 0x00 /* i2c slave address */ -#define IMX_I2C_IFDR 0x04 /* i2c frequency divider */ -#define IMX_I2C_I2CR 0x08 /* i2c control */ -#define IMX_I2C_I2SR 0x0C /* i2c status */ -#define IMX_I2C_I2DR 0x10 /* i2c transfer data */ +#define IMX_I2C_IFDR 0x01 /* i2c frequency divider */ +#define IMX_I2C_I2CR 0x02 /* i2c control */ +#define IMX_I2C_I2SR 0x03 /* i2c status */ +#define IMX_I2C_I2DR 0x04 /* i2c transfer data */ + +#define IMX_I2C_REGSHIFT 2 /* Bits of IMX I2C registers */ #define I2SR_RXAK 0x01 @@ -163,13 +172,13 @@ static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx) static inline void imx_i2c_write_reg(unsigned int val, struct imx_i2c_struct *i2c_imx, unsigned int reg) { - writeb(val, i2c_imx->base + reg); + writeb(val, i2c_imx->base + (reg << IMX_I2C_REGSHIFT)); } static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx, unsigned int reg) { - return readb(i2c_imx->base + reg); + return readb(i2c_imx->base + (reg << IMX_I2C_REGSHIFT)); } /** Functions for IMX I2C adapter driver *************************************** -- cgit v0.10.2 From 171408c21149dd3fd2ed33f19afe2cd558269253 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Wed, 7 Aug 2013 17:05:41 +0800 Subject: i2c: imx: add INT flag and IEN bit operatation codes This add bits operation macro that differ between SoCs. Interrupt flags clear operation in I2SR differ between SoCs: write zero to clear(w0c) INT flag on i.MX, but write one to clear(w1c) INT flag on Vybrid. I2C module enable operation in I2CR also differ between SoCs: set I2CR_IEN bit enable the module on i.MX, but clear I2CR_IEN bit enable the module on Vybrid. Signed-off-by: Jingchang Lu Reviewed-by: Sascha Hauer Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 8a292a9..dc9f2ec 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -95,6 +95,22 @@ #define I2CR_IIEN 0x40 #define I2CR_IEN 0x80 +/* register bits different operating codes definition: + * 1) I2SR: Interrupt flags clear operation differ between SoCs: + * - write zero to clear(w0c) INT flag on i.MX, + * - but write one to clear(w1c) INT flag on Vybrid. + * 2) I2CR: I2C module enable operation also differ between SoCs: + * - set I2CR_IEN bit enable the module on i.MX, + * - but clear I2CR_IEN bit enable the module on Vybrid. + */ +#define I2SR_CLR_OPCODE_W0C 0x0 +#define I2SR_CLR_OPCODE_W1C (I2SR_IAL | I2SR_IIF) +#define I2CR_IEN_OPCODE_0 0x0 +#define I2CR_IEN_OPCODE_1 I2CR_IEN + +#define IMX_I2SR_CLR_OPCODE I2SR_CLR_OPCODE_W0C +#define IMX_I2CR_IEN_OPCODE I2CR_IEN_OPCODE_1 + /** Variables ****************************************************************** *******************************************************************************/ @@ -242,8 +258,8 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) clk_prepare_enable(i2c_imx->clk); imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR); /* Enable I2C controller */ - imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); - imx_i2c_write_reg(I2CR_IEN, i2c_imx, IMX_I2C_I2CR); + imx_i2c_write_reg(IMX_I2SR_CLR_OPCODE, i2c_imx, IMX_I2C_I2SR); + imx_i2c_write_reg(IMX_I2CR_IEN_OPCODE, i2c_imx, IMX_I2C_I2CR); /* Wait controller to be stable */ udelay(50); @@ -287,7 +303,7 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) } /* Disable I2C controller */ - imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR); + imx_i2c_write_reg(IMX_I2CR_IEN_OPCODE ^ I2CR_IEN, i2c_imx, IMX_I2C_I2CR); clk_disable_unprepare(i2c_imx->clk); } @@ -339,6 +355,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) /* save status register */ i2c_imx->i2csr = temp; temp &= ~I2SR_IIF; + temp |= (IMX_I2SR_CLR_OPCODE & I2SR_IIF); imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); wake_up(&i2c_imx->queue); return IRQ_HANDLED; @@ -596,8 +613,8 @@ static int __init i2c_imx_probe(struct platform_device *pdev) i2c_imx_set_clk(i2c_imx, bitrate); /* Set up chip registers to defaults */ - imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR); - imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); + imx_i2c_write_reg(IMX_I2CR_IEN_OPCODE ^ I2CR_IEN, i2c_imx, IMX_I2C_I2CR); + imx_i2c_write_reg(IMX_I2SR_CLR_OPCODE, i2c_imx, IMX_I2C_I2SR); /* Add I2C adapter */ ret = i2c_add_numbered_adapter(&i2c_imx->adapter); -- cgit v0.10.2 From 4b775022f6fdcfba6d219f46b2606e77a0dc38d9 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Wed, 7 Aug 2013 17:05:42 +0800 Subject: i2c: imx: add struct to hold more configurable quirks This add struct imx_i2c_hwdata to hold more quirks data which may vary between SoCs, thus the driver can operate on more differences to support more SoCs. Signed-off-by: Jingchang Lu Reviewed-by: Sascha Hauer Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index dc9f2ec..ce31196 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -108,9 +108,6 @@ #define I2CR_IEN_OPCODE_0 0x0 #define I2CR_IEN_OPCODE_1 I2CR_IEN -#define IMX_I2SR_CLR_OPCODE I2SR_CLR_OPCODE_W0C -#define IMX_I2CR_IEN_OPCODE I2CR_IEN_OPCODE_1 - /** Variables ****************************************************************** *******************************************************************************/ @@ -127,7 +124,7 @@ struct imx_i2c_clk_pair { u16 val; }; -static struct imx_i2c_clk_pair __initdata i2c_clk_div[] = { +static struct imx_i2c_clk_pair imx_i2c_clk_div[] = { { 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 }, { 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 }, { 40, 0x26 }, { 42, 0x03 }, { 44, 0x27 }, { 48, 0x28 }, { 52, 0x05 }, @@ -148,6 +145,15 @@ enum imx_i2c_type { IMX21_I2C, }; +struct imx_i2c_hwdata { + enum imx_i2c_type devtype; + unsigned regshift; + struct imx_i2c_clk_pair *clk_div; + unsigned ndivs; + unsigned i2sr_clr_opcode; + unsigned i2cr_ien_opcode; +}; + struct imx_i2c_struct { struct i2c_adapter adapter; struct clk *clk; @@ -157,16 +163,36 @@ struct imx_i2c_struct { unsigned int disable_delay; int stopped; unsigned int ifdr; /* IMX_I2C_IFDR */ - enum imx_i2c_type devtype; + const struct imx_i2c_hwdata *hwdata; +}; + +static const struct imx_i2c_hwdata imx1_i2c_hwdata = { + .devtype = IMX1_I2C, + .regshift = IMX_I2C_REGSHIFT, + .clk_div = imx_i2c_clk_div, + .ndivs = ARRAY_SIZE(imx_i2c_clk_div), + .i2sr_clr_opcode = I2SR_CLR_OPCODE_W0C, + .i2cr_ien_opcode = I2CR_IEN_OPCODE_1, + +}; + +static const struct imx_i2c_hwdata imx21_i2c_hwdata = { + .devtype = IMX21_I2C, + .regshift = IMX_I2C_REGSHIFT, + .clk_div = imx_i2c_clk_div, + .ndivs = ARRAY_SIZE(imx_i2c_clk_div), + .i2sr_clr_opcode = I2SR_CLR_OPCODE_W0C, + .i2cr_ien_opcode = I2CR_IEN_OPCODE_1, + }; static struct platform_device_id imx_i2c_devtype[] = { { .name = "imx1-i2c", - .driver_data = IMX1_I2C, + .driver_data = (kernel_ulong_t)&imx1_i2c_hwdata, }, { .name = "imx21-i2c", - .driver_data = IMX21_I2C, + .driver_data = (kernel_ulong_t)&imx21_i2c_hwdata, }, { /* sentinel */ } @@ -174,27 +200,27 @@ static struct platform_device_id imx_i2c_devtype[] = { MODULE_DEVICE_TABLE(platform, imx_i2c_devtype); static const struct of_device_id i2c_imx_dt_ids[] = { - { .compatible = "fsl,imx1-i2c", .data = &imx_i2c_devtype[IMX1_I2C], }, - { .compatible = "fsl,imx21-i2c", .data = &imx_i2c_devtype[IMX21_I2C], }, + { .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, }, + { .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, i2c_imx_dt_ids); static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx) { - return i2c_imx->devtype == IMX1_I2C; + return i2c_imx->hwdata->devtype == IMX1_I2C; } static inline void imx_i2c_write_reg(unsigned int val, struct imx_i2c_struct *i2c_imx, unsigned int reg) { - writeb(val, i2c_imx->base + (reg << IMX_I2C_REGSHIFT)); + writeb(val, i2c_imx->base + (reg << i2c_imx->hwdata->regshift)); } static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx, unsigned int reg) { - return readb(i2c_imx->base + (reg << IMX_I2C_REGSHIFT)); + return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift)); } /** Functions for IMX I2C adapter driver *************************************** @@ -258,8 +284,8 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) clk_prepare_enable(i2c_imx->clk); imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR); /* Enable I2C controller */ - imx_i2c_write_reg(IMX_I2SR_CLR_OPCODE, i2c_imx, IMX_I2C_I2SR); - imx_i2c_write_reg(IMX_I2CR_IEN_OPCODE, i2c_imx, IMX_I2C_I2CR); + imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); + imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode, i2c_imx, IMX_I2C_I2CR); /* Wait controller to be stable */ udelay(50); @@ -303,13 +329,15 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) } /* Disable I2C controller */ - imx_i2c_write_reg(IMX_I2CR_IEN_OPCODE ^ I2CR_IEN, i2c_imx, IMX_I2C_I2CR); + temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); clk_disable_unprepare(i2c_imx->clk); } static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, unsigned int rate) { + struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div; unsigned int i2c_clk_rate; unsigned int div; int i; @@ -319,8 +347,8 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, div = (i2c_clk_rate + rate - 1) / rate; if (div < i2c_clk_div[0].div) i = 0; - else if (div > i2c_clk_div[ARRAY_SIZE(i2c_clk_div) - 1].div) - i = ARRAY_SIZE(i2c_clk_div) - 1; + else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div) + i = i2c_imx->hwdata->ndivs - 1; else for (i = 0; i2c_clk_div[i].div < div; i++); @@ -355,7 +383,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) /* save status register */ i2c_imx->i2csr = temp; temp &= ~I2SR_IIF; - temp |= (IMX_I2SR_CLR_OPCODE & I2SR_IIF); + temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF); imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); wake_up(&i2c_imx->queue); return IRQ_HANDLED; @@ -537,7 +565,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev) struct imx_i2c_struct *i2c_imx; struct resource *res; struct imxi2c_platform_data *pdata = pdev->dev.platform_data; - const struct platform_device_id *imx_id; void __iomem *base; int irq, ret; u32 bitrate; @@ -563,11 +590,10 @@ static int __init i2c_imx_probe(struct platform_device *pdev) } if (of_id) - imx_id = of_id->data; + i2c_imx->hwdata = of_id->data; else - imx_id = platform_get_device_id(pdev); - - i2c_imx->devtype = imx_id->driver_data; + i2c_imx->hwdata = (struct imx_i2c_hwdata *) + platform_get_device_id(pdev)->driver_data; /* Setup i2c_imx driver structure */ strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name)); @@ -613,8 +639,9 @@ static int __init i2c_imx_probe(struct platform_device *pdev) i2c_imx_set_clk(i2c_imx, bitrate); /* Set up chip registers to defaults */ - imx_i2c_write_reg(IMX_I2CR_IEN_OPCODE ^ I2CR_IEN, i2c_imx, IMX_I2C_I2CR); - imx_i2c_write_reg(IMX_I2SR_CLR_OPCODE, i2c_imx, IMX_I2C_I2SR); + imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, + i2c_imx, IMX_I2C_I2CR); + imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); /* Add I2C adapter */ ret = i2c_add_numbered_adapter(&i2c_imx->adapter); -- cgit v0.10.2 From ad90efae1b9203baeb0f6fd668e6c61c2377bd5f Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Wed, 7 Aug 2013 17:05:43 +0800 Subject: i2c: imx: Add Vybrid VF610 I2C controller support Add Freescale Vybrid VF610 I2C controller support to imx I2C driver framework. Signed-off-by: Jason Jin Signed-off-by: Jingchang Lu Reviewed-by: Sascha Hauer Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index ce31196..9c0f8bd 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -79,6 +79,7 @@ #define IMX_I2C_I2DR 0x04 /* i2c transfer data */ #define IMX_I2C_REGSHIFT 2 +#define VF610_I2C_REGSHIFT 0 /* Bits of IMX I2C registers */ #define I2SR_RXAK 0x01 @@ -140,9 +141,29 @@ static struct imx_i2c_clk_pair imx_i2c_clk_div[] = { { 3072, 0x1E }, { 3840, 0x1F } }; +/* Vybrid VF610 clock divider, register value pairs */ +static struct imx_i2c_clk_pair vf610_i2c_clk_div[] = { + { 20, 0x00 }, { 22, 0x01 }, { 24, 0x02 }, { 26, 0x03 }, + { 28, 0x04 }, { 30, 0x05 }, { 32, 0x09 }, { 34, 0x06 }, + { 36, 0x0A }, { 40, 0x07 }, { 44, 0x0C }, { 48, 0x0D }, + { 52, 0x43 }, { 56, 0x0E }, { 60, 0x45 }, { 64, 0x12 }, + { 68, 0x0F }, { 72, 0x13 }, { 80, 0x14 }, { 88, 0x15 }, + { 96, 0x19 }, { 104, 0x16 }, { 112, 0x1A }, { 128, 0x17 }, + { 136, 0x4F }, { 144, 0x1C }, { 160, 0x1D }, { 176, 0x55 }, + { 192, 0x1E }, { 208, 0x56 }, { 224, 0x22 }, { 228, 0x24 }, + { 240, 0x1F }, { 256, 0x23 }, { 288, 0x5C }, { 320, 0x25 }, + { 384, 0x26 }, { 448, 0x2A }, { 480, 0x27 }, { 512, 0x2B }, + { 576, 0x2C }, { 640, 0x2D }, { 768, 0x31 }, { 896, 0x32 }, + { 960, 0x2F }, { 1024, 0x33 }, { 1152, 0x34 }, { 1280, 0x35 }, + { 1536, 0x36 }, { 1792, 0x3A }, { 1920, 0x37 }, { 2048, 0x3B }, + { 2304, 0x3C }, { 2560, 0x3D }, { 3072, 0x3E }, { 3584, 0x7A }, + { 3840, 0x3F }, { 4096, 0x7B }, { 5120, 0x7D }, { 6144, 0x7E }, +}; + enum imx_i2c_type { IMX1_I2C, IMX21_I2C, + VF610_I2C, }; struct imx_i2c_hwdata { @@ -186,6 +207,16 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata = { }; +static struct imx_i2c_hwdata vf610_i2c_hwdata = { + .devtype = VF610_I2C, + .regshift = VF610_I2C_REGSHIFT, + .clk_div = vf610_i2c_clk_div, + .ndivs = ARRAY_SIZE(vf610_i2c_clk_div), + .i2sr_clr_opcode = I2SR_CLR_OPCODE_W1C, + .i2cr_ien_opcode = I2CR_IEN_OPCODE_0, + +}; + static struct platform_device_id imx_i2c_devtype[] = { { .name = "imx1-i2c", @@ -202,6 +233,7 @@ MODULE_DEVICE_TABLE(platform, imx_i2c_devtype); static const struct of_device_id i2c_imx_dt_ids[] = { { .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, }, { .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, }, + { .compatible = "fsl,vf610-i2c", .data = &vf610_i2c_hwdata, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, i2c_imx_dt_ids); -- cgit v0.10.2 From b7d12a8667d78ba340829280da8ff62d3b733664 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 14 Aug 2013 11:11:27 +0200 Subject: drivers/i2c/busses/i2c-ocores.c: simplify use of devm_ioremap_resource Remove unneeded error handling on the result of a call to platform_get_resource when the value is passed to devm_ioremap_resource. Move the call to platform_get_resource adjacent to the call to devm_ioremap_resource to make the connection between them more clear. A simplified version of the semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression pdev,res,n,e,e1; expression ret != 0; identifier l; @@ - res = platform_get_resource(pdev, IORESOURCE_MEM, n); ... when != res - if (res == NULL) { ... \(goto l;\|return ret;\) } ... when != res + res = platform_get_resource(pdev, IORESOURCE_MEM, n); e = devm_ioremap_resource(e1, res); // Signed-off-by: Julia Lawall Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index bdae4ca..7ac8b9c 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -353,10 +353,6 @@ static int ocores_i2c_probe(struct platform_device *pdev) int ret; int i; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -365,6 +361,7 @@ static int ocores_i2c_probe(struct platform_device *pdev) if (!i2c) return -ENOMEM; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); i2c->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); -- cgit v0.10.2 From 869c6a3ededbb108b03a11a7c9d4c8a4fb607063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Fri, 5 Jul 2013 18:28:00 +0200 Subject: i2c: mxs: fix broken timing calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The timing calculation is rather bogus and gives extremely wrong results for higher frequencies (on an i.MX28). E.g. instead of 400 kHz I measured 770 kHz. Implement a calculation that adheres to the I2C spec and gives exact results for I2C frequencies from 12.56 kHz to 960 kHz. Also the bus_free and leadin parameters are programmed according to the I2C spec for standard and fast mode. This was tested on a Ka-Ro TX28 module with a DS1339, TSC2007, PCA9554 and SGTL5000 client. Signed-off-by: Lothar Waßmann Acked-by: Marek Vasut [wsa: patch fixes whitespace issue, too] Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 43e2273..46cda0b 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -114,9 +114,10 @@ struct mxs_i2c_dev { uint32_t timing0; uint32_t timing1; + uint32_t timing2; /* DMA support components */ - struct dma_chan *dmach; + struct dma_chan *dmach; uint32_t pio_data[2]; uint32_t addr_data; struct scatterlist sg_io[2]; @@ -138,7 +139,7 @@ static int mxs_i2c_reset(struct mxs_i2c_dev *i2c) */ writel(i2c->timing0, i2c->regs + MXS_I2C_TIMING0); writel(i2c->timing1, i2c->regs + MXS_I2C_TIMING1); - writel(0x00300030, i2c->regs + MXS_I2C_TIMING2); + writel(i2c->timing2, i2c->regs + MXS_I2C_TIMING2); writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); @@ -587,41 +588,79 @@ static const struct i2c_algorithm mxs_i2c_algo = { .functionality = mxs_i2c_func, }; -static void mxs_i2c_derive_timing(struct mxs_i2c_dev *i2c, int speed) +static void mxs_i2c_derive_timing(struct mxs_i2c_dev *i2c, uint32_t speed) { - /* The I2C block clock run at 24MHz */ + /* The I2C block clock runs at 24MHz */ const uint32_t clk = 24000000; - uint32_t base; + uint32_t divider; uint16_t high_count, low_count, rcv_count, xmit_count; + uint32_t bus_free, leadin; struct device *dev = i2c->dev; - if (speed > 540000) { - dev_warn(dev, "Speed too high (%d Hz), using 540 kHz\n", speed); - speed = 540000; - } else if (speed < 12000) { - dev_warn(dev, "Speed too low (%d Hz), using 12 kHz\n", speed); - speed = 12000; + divider = DIV_ROUND_UP(clk, speed); + + if (divider < 25) { + /* + * limit the divider, so that min(low_count, high_count) + * is >= 1 + */ + divider = 25; + dev_warn(dev, + "Speed too high (%u.%03u kHz), using %u.%03u kHz\n", + speed / 1000, speed % 1000, + clk / divider / 1000, clk / divider % 1000); + } else if (divider > 1897) { + /* + * limit the divider, so that max(low_count, high_count) + * cannot exceed 1023 + */ + divider = 1897; + dev_warn(dev, + "Speed too low (%u.%03u kHz), using %u.%03u kHz\n", + speed / 1000, speed % 1000, + clk / divider / 1000, clk / divider % 1000); } /* - * The timing derivation algorithm. There is no documentation for this - * algorithm available, it was derived by using the scope and fiddling - * with constants until the result observed on the scope was good enough - * for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be - * possible to assume the algorithm works for other frequencies as well. + * The I2C spec specifies the following timing data: + * standard mode fast mode Bitfield name + * tLOW (SCL LOW period) 4700 ns 1300 ns + * tHIGH (SCL HIGH period) 4000 ns 600 ns + * tSU;DAT (data setup time) 250 ns 100 ns + * tHD;STA (START hold time) 4000 ns 600 ns + * tBUF (bus free time) 4700 ns 1300 ns * - * Note it was necessary to cap the frequency on both ends as it's not - * possible to configure completely arbitrary frequency for the I2C bus - * clock. + * The hardware (of the i.MX28 at least) seems to add 2 additional + * clock cycles to the low_count and 7 cycles to the high_count. + * This is compensated for by subtracting the respective constants + * from the values written to the timing registers. */ - base = ((clk / speed) - 38) / 2; - high_count = base + 3; - low_count = base - 3; - rcv_count = (high_count * 3) / 4; - xmit_count = low_count / 4; + if (speed > 100000) { + /* fast mode */ + low_count = DIV_ROUND_CLOSEST(divider * 13, (13 + 6)); + high_count = DIV_ROUND_CLOSEST(divider * 6, (13 + 6)); + leadin = DIV_ROUND_UP(600 * (clk / 1000000), 1000); + bus_free = DIV_ROUND_UP(1300 * (clk / 1000000), 1000); + } else { + /* normal mode */ + low_count = DIV_ROUND_CLOSEST(divider * 47, (47 + 40)); + high_count = DIV_ROUND_CLOSEST(divider * 40, (47 + 40)); + leadin = DIV_ROUND_UP(4700 * (clk / 1000000), 1000); + bus_free = DIV_ROUND_UP(4700 * (clk / 1000000), 1000); + } + rcv_count = high_count * 3 / 8; + xmit_count = low_count * 3 / 8; + + dev_dbg(dev, + "speed=%u(actual %u) divider=%u low=%u high=%u xmit=%u rcv=%u leadin=%u bus_free=%u\n", + speed, clk / divider, divider, low_count, high_count, + xmit_count, rcv_count, leadin, bus_free); + low_count -= 2; + high_count -= 7; i2c->timing0 = (high_count << 16) | rcv_count; i2c->timing1 = (low_count << 16) | xmit_count; + i2c->timing2 = (bus_free << 16 | leadin); } static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) -- cgit v0.10.2 From cda2109a26eb6fa58acfeae878eed87492480eae Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 7 Jun 2013 21:46:07 +0300 Subject: i2c: omap: query STP always when NACK is received According to I2C specification the NACK should be handled as folowing: "When SDA remains HIGH during this ninth clock pulse, this is defined as the Not Acknowledge signal. The master can then gene rate either a STOP condition to abort the transfer, or a repeated START condition to start a new transfer." [http://www.nxp.com/documents/user_manual/UM10204.pdf] The same is recomened by TI I2C wiki: http://processors.wiki.ti.com/index.php/I2C_Tips Currently, the OMAP I2C driver interrupts I2C trunsfer in case of NACK, but It queries Stop condition OMAP_I2C_CON_REG.STP=1 only if NACK has been received during the last message transmitting/recieving. This may lead to stuck Bus in "Bus Busy" until I2C IP reset (idle/enable). Hence, fix it by querying Stop condition (STP) always when NACK is received. Signed-off-by: Grygorii Strashko Acked-by: Hein Tibosch Acked-by: Felipe Balbi Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index d09512e..c6db76e 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -615,11 +615,10 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, if (dev->cmd_err & OMAP_I2C_STAT_NACK) { if (msg->flags & I2C_M_IGNORE_NAK) return 0; - if (stop) { - w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG); - w |= OMAP_I2C_CON_STP; - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w); - } + + w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG); + w |= OMAP_I2C_CON_STP; + omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w); return -EREMOTEIO; } return -EIO; -- cgit v0.10.2 From 6d4028c644edc0a2e4a8c948ebf81e8f2f09726e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 16:59:33 +0900 Subject: i2c: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index 37d4239..35a473b 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -674,8 +674,9 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) p_adap->timeout = 5 * HZ; p_adap->retries = 3; - rc = peripheral_request_list((unsigned short *)pdev->dev.platform_data, - "i2c-bfin-twi"); + rc = peripheral_request_list( + (unsigned short *)dev_get_platdata(&pdev->dev), + "i2c-bfin-twi"); if (rc) { dev_err(&pdev->dev, "Can't setup pin mux!\n"); goto out_error_pin_mux; @@ -722,7 +723,7 @@ out_error_add_adapter: free_irq(iface->irq, iface); out_error_req_irq: out_error_no_irq: - peripheral_free_list((unsigned short *)pdev->dev.platform_data); + peripheral_free_list((unsigned short *)dev_get_platdata(&pdev->dev)); out_error_pin_mux: iounmap(iface->regs_base); out_error_ioremap: @@ -738,7 +739,7 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev) i2c_del_adapter(&(iface->adap)); free_irq(iface->irq, iface); - peripheral_free_list((unsigned short *)pdev->dev.platform_data); + peripheral_free_list((unsigned short *)dev_get_platdata(&pdev->dev)); iounmap(iface->regs_base); kfree(iface); diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c index 1be13ac..2d46f13 100644 --- a/drivers/i2c/busses/i2c-cbus-gpio.c +++ b/drivers/i2c/busses/i2c-cbus-gpio.c @@ -233,8 +233,9 @@ static int cbus_i2c_probe(struct platform_device *pdev) chost->clk_gpio = of_get_gpio(dnode, 0); chost->dat_gpio = of_get_gpio(dnode, 1); chost->sel_gpio = of_get_gpio(dnode, 2); - } else if (pdev->dev.platform_data) { - struct i2c_cbus_platform_data *pdata = pdev->dev.platform_data; + } else if (dev_get_platdata(&pdev->dev)) { + struct i2c_cbus_platform_data *pdata = + dev_get_platdata(&pdev->dev); chost->clk_gpio = pdata->clk_gpio; chost->dat_gpio = pdata->dat_gpio; chost->sel_gpio = pdata->sel_gpio; diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 5898df3..cf90bff 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -663,7 +663,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) #endif dev->dev = &pdev->dev; dev->irq = irq->start; - dev->pdata = dev->dev->platform_data; + dev->pdata = dev_get_platdata(&dev->dev); platform_set_drvdata(pdev, dev); if (!dev->pdata && pdev->dev.of_node) { diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index bc6e139..8cdb4f7 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -137,9 +137,9 @@ static int i2c_gpio_probe(struct platform_device *pdev) if (ret) return ret; } else { - if (!pdev->dev.platform_data) + if (!dev_get_platdata(&pdev->dev)) return -ENXIO; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); sda_pin = pdata->sda_pin; scl_pin = pdata->scl_pin; } @@ -171,7 +171,7 @@ static int i2c_gpio_probe(struct platform_device *pdev) pdata->scl_pin = scl_pin; of_i2c_gpio_get_props(pdev->dev.of_node, pdata); } else { - memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); + memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata)); } if (pdata->sda_is_open_drain) { diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 9c0f8bd..a231d2f 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -596,7 +596,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) &pdev->dev); struct imx_i2c_struct *i2c_imx; struct resource *res; - struct imxi2c_platform_data *pdata = pdev->dev.platform_data; + struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev); void __iomem *base; int irq, ret; u32 bitrate; diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index b1f42bf..9cc361d 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -618,7 +618,7 @@ static int mv64xxx_i2c_probe(struct platform_device *pd) { struct mv64xxx_i2c_data *drv_data; - struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data; + struct mv64xxx_i2c_pdata *pdata = dev_get_platdata(&pd->dev); struct resource *r; int rc; diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 512dfe6..1909e80 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -943,7 +943,7 @@ static void nmk_i2c_of_probe(struct device_node *np, static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) { int ret = 0; - struct nmk_i2c_controller *pdata = adev->dev.platform_data; + struct nmk_i2c_controller *pdata = dev_get_platdata(&adev->dev); struct device_node *np = adev->dev.of_node; struct nmk_i2c_dev *dev; struct i2c_adapter *adap; diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c index 865ee35..36394d7 100644 --- a/drivers/i2c/busses/i2c-nuc900.c +++ b/drivers/i2c/busses/i2c-nuc900.c @@ -525,7 +525,7 @@ static int nuc900_i2c_probe(struct platform_device *pdev) struct resource *res; int ret; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "no platform data\n"); return -EINVAL; diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 7ac8b9c..e14182c 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -366,7 +366,7 @@ static int ocores_i2c_probe(struct platform_device *pdev) if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (pdata) { i2c->reg_shift = pdata->reg_shift; i2c->reg_io_width = pdata->reg_io_width; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index c6db76e..9ccb7b9 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1075,7 +1075,7 @@ omap_i2c_probe(struct platform_device *pdev) struct i2c_adapter *adap; struct resource *mem; const struct omap_i2c_bus_platform_data *pdata = - pdev->dev.platform_data; + dev_get_platdata(&pdev->dev); struct device_node *node = pdev->dev.of_node; const struct of_device_id *match; int irq; diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index aa00df1..39e2755 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -136,7 +136,7 @@ static int i2c_pca_pf_probe(struct platform_device *pdev) struct i2c_pca_pf_data *i2c; struct resource *res; struct i2c_pca9564_pf_platform_data *platform_data = - pdev->dev.platform_data; + dev_get_platdata(&pdev->dev); int ret = 0; int irq; diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 8dc90da..5a88364 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -398,7 +398,7 @@ static void i2c_powermac_register_devices(struct i2c_adapter *adap, static int i2c_powermac_probe(struct platform_device *dev) { - struct pmac_i2c_bus *bus = dev->dev.platform_data; + struct pmac_i2c_bus *bus = dev_get_platdata(&dev->dev); struct device_node *parent = NULL; struct i2c_adapter *adapter; const char *basename; diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index a61d906..3dbc1ac 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1118,7 +1118,7 @@ static int i2c_pxa_probe_pdata(struct platform_device *pdev, struct pxa_i2c *i2c, enum pxa_i2c_types *i2c_types) { - struct i2c_pxa_platform_data *plat = pdev->dev.platform_data; + struct i2c_pxa_platform_data *plat = dev_get_platdata(&pdev->dev); const struct platform_device_id *id = platform_get_device_id(pdev); *i2c_types = id->driver_data; @@ -1136,7 +1136,7 @@ static int i2c_pxa_probe_pdata(struct platform_device *pdev, static int i2c_pxa_probe(struct platform_device *dev) { - struct i2c_pxa_platform_data *plat = dev->dev.platform_data; + struct i2c_pxa_platform_data *plat = dev_get_platdata(&dev->dev); enum pxa_i2c_types i2c_type; struct pxa_i2c *i2c; struct resource *res = NULL; diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 0fc5858..e59c3f6 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -615,7 +615,7 @@ static const struct i2c_algorithm rcar_i2c_algo = { static int rcar_i2c_probe(struct platform_device *pdev) { - struct i2c_rcar_platform_data *pdata = pdev->dev.platform_data; + struct i2c_rcar_platform_data *pdata = dev_get_platdata(&pdev->dev); struct rcar_i2c_priv *priv; struct i2c_adapter *adap; struct resource *res; diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index cab1c91..0a077b1 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -1033,7 +1033,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) int ret; if (!pdev->dev.of_node) { - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "no platform data\n"); return -EINVAL; diff --git a/drivers/i2c/busses/i2c-s6000.c b/drivers/i2c/busses/i2c-s6000.c index 7c1ca5a..dd186a0 100644 --- a/drivers/i2c/busses/i2c-s6000.c +++ b/drivers/i2c/busses/i2c-s6000.c @@ -290,8 +290,9 @@ static int s6i2c_probe(struct platform_device *dev) clock = 0; bus_num = -1; - if (dev->dev.platform_data) { - struct s6_i2c_platform_data *pdata = dev->dev.platform_data; + if (dev_get_platdata(&dev->dev)) { + struct s6_i2c_platform_data *pdata = + dev_get_platdata(&dev->dev); bus_num = pdata->bus_num; clock = pdata->clock; } diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index 5351a2f..5e8f136 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c @@ -437,7 +437,7 @@ static int sh7760_i2c_probe(struct platform_device *pdev) struct cami2c *id; int ret; - pd = pdev->dev.platform_data; + pd = dev_get_platdata(&pdev->dev); if (!pd) { dev_err(&pdev->dev, "no platform_data!\n"); ret = -ENODEV; diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index debf745..4e86a31 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -658,7 +658,7 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook) static int sh_mobile_i2c_probe(struct platform_device *dev) { - struct i2c_sh_mobile_platform_data *pdata = dev->dev.platform_data; + struct i2c_sh_mobile_platform_data *pdata = dev_get_platdata(&dev->dev); struct sh_mobile_i2c_data *pd; struct i2c_adapter *adap; struct resource *res; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 3d0f052..433f377 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -703,7 +703,7 @@ static int xiic_i2c_probe(struct platform_device *pdev) if (irq < 0) goto resource_missing; - pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data; + pdata = (struct xiic_i2c_platform_data *)dev_get_platdata(&pdev->dev); i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); if (!i2c) diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index 92cdd23..44d4c60 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -137,7 +137,7 @@ static irqreturn_t smbalert_irq(int irq, void *d) static int smbalert_probe(struct i2c_client *ara, const struct i2c_device_id *id) { - struct i2c_smbus_alert_setup *setup = ara->dev.platform_data; + struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev); struct i2c_smbus_alert *alert; struct i2c_adapter *adapter = ara->adapter; int res; diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c index 210b6f7..f7bf243 100644 --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c @@ -131,7 +131,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) dev_err(dev, "Cannot find device tree node\n"); return -ENODEV; } - if (dev->platform_data) { + if (dev_get_platdata(dev)) { dev_err(dev, "Platform data is not supported\n"); return -EINVAL; } diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 5a0ce00..6a206e8 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -148,12 +148,14 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mux); - if (!pdev->dev.platform_data) { + if (!dev_get_platdata(&pdev->dev)) { ret = i2c_mux_gpio_probe_dt(mux, pdev); if (ret < 0) return ret; - } else - memcpy(&mux->data, pdev->dev.platform_data, sizeof(mux->data)); + } else { + memcpy(&mux->data, dev_get_platdata(&pdev->dev), + sizeof(mux->data)); + } /* * If a GPIO chip name is provided, the GPIO pin numbers provided are diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index 966a18a..c4f08ad 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -324,7 +324,7 @@ static int pca9541_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adap = client->adapter; - struct pca954x_platform_data *pdata = client->dev.platform_data; + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); struct pca9541 *data; int force; int ret = -ENODEV; diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index a531d80..bad5b84 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -185,7 +185,7 @@ static int pca954x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); - struct pca954x_platform_data *pdata = client->dev.platform_data; + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); int num, force, class; struct pca954x *data; int ret = -ENODEV; diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index a43c0ce..0d08202 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -145,7 +145,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) mux->dev = &pdev->dev; - mux->pdata = pdev->dev.platform_data; + mux->pdata = dev_get_platdata(&pdev->dev); if (!mux->pdata) { ret = i2c_mux_pinctrl_parse_dt(mux, pdev); if (ret < 0) -- cgit v0.10.2 From 243ec0909af052d3f420dd6a4d4376e68346d95c Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 6 Aug 2013 14:17:42 +0300 Subject: i2c: tiny-usb: do not use stack as URB transfer_buffer Patch fixes i2c-tiny-usb not to use stack as URB transfer_buffer. URB buffers need to be DMA-able, which stack is not. Patch is only compile tested. Signed-off-by: Jussi Kivilinna Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index 0510636..e7d3b75 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -54,12 +54,16 @@ static int usb_write(struct i2c_adapter *adapter, int cmd, static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { - unsigned char status; + unsigned char *pstatus; struct i2c_msg *pmsg; - int i; + int i, ret; dev_dbg(&adapter->dev, "master xfer %d messages:\n", num); + pstatus = kmalloc(sizeof(*pstatus), GFP_KERNEL); + if (!pstatus) + return -ENOMEM; + for (i = 0 ; i < num ; i++) { int cmd = CMD_I2C_IO; @@ -84,7 +88,8 @@ static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) pmsg->buf, pmsg->len) != pmsg->len) { dev_err(&adapter->dev, "failure reading data\n"); - return -EREMOTEIO; + ret = -EREMOTEIO; + goto out; } } else { /* write data */ @@ -93,36 +98,50 @@ static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) pmsg->buf, pmsg->len) != pmsg->len) { dev_err(&adapter->dev, "failure writing data\n"); - return -EREMOTEIO; + ret = -EREMOTEIO; + goto out; } } /* read status */ - if (usb_read(adapter, CMD_GET_STATUS, 0, 0, &status, 1) != 1) { + if (usb_read(adapter, CMD_GET_STATUS, 0, 0, pstatus, 1) != 1) { dev_err(&adapter->dev, "failure reading status\n"); - return -EREMOTEIO; + ret = -EREMOTEIO; + goto out; } - dev_dbg(&adapter->dev, " status = %d\n", status); - if (status == STATUS_ADDRESS_NAK) - return -EREMOTEIO; + dev_dbg(&adapter->dev, " status = %d\n", *pstatus); + if (*pstatus == STATUS_ADDRESS_NAK) { + ret = -EREMOTEIO; + goto out; + } } - return i; + ret = i; +out: + kfree(pstatus); + return ret; } static u32 usb_func(struct i2c_adapter *adapter) { - __le32 func; + __le32 *pfunc; + u32 ret; + + pfunc = kmalloc(sizeof(*pfunc), GFP_KERNEL); /* get functionality from adapter */ - if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) != - sizeof(func)) { + if (!pfunc || usb_read(adapter, CMD_GET_FUNC, 0, 0, pfunc, + sizeof(*pfunc)) != sizeof(*pfunc)) { dev_err(&adapter->dev, "failure reading functionality\n"); - return 0; + ret = 0; + goto out; } - return le32_to_cpu(func); + ret = le32_to_cpup(pfunc); +out: + kfree(pfunc); + return ret; } /* This is the actual algorithm we define */ -- cgit v0.10.2 From 42fa278d70e7caee728f6f3e563d1aaaf9c521aa Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 8 Aug 2013 10:55:11 +0530 Subject: Documentation: i2c: Fix example in instantiating-devices __initdata should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Signed-off-by: Wolfram Sang diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices index 2218266..c70e7a7 100644 --- a/Documentation/i2c/instantiating-devices +++ b/Documentation/i2c/instantiating-devices @@ -19,7 +19,7 @@ i2c_board_info which is registered by calling i2c_register_board_info(). Example (from omap2 h4): -static struct i2c_board_info __initdata h4_i2c_board_info[] = { +static struct i2c_board_info h4_i2c_board_info[] __initdata = { { I2C_BOARD_INFO("isp1301_omap", 0x2d), .irq = OMAP_GPIO_IRQ(125), -- cgit v0.10.2 From 874e955b171f0505e2371c1ca80a2188efdc217d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 11 Jul 2013 22:02:03 +0100 Subject: i2c: powermac: fix return path on error We want to bail out immediately if i2c_add_adapter failed and not try to register child nodes with a nilled adapter structure. Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 5a88364..06858d5 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -446,6 +446,7 @@ static int i2c_powermac_probe(struct platform_device *dev) printk(KERN_ERR "i2c-powermac: Adapter %s registration " "failed\n", adapter->name); memset(adapter, 0, sizeof(*adapter)); + return rc; } printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name); @@ -455,7 +456,7 @@ static int i2c_powermac_probe(struct platform_device *dev) */ i2c_powermac_register_devices(adapter, bus); - return rc; + return 0; } static struct platform_driver i2c_powermac_driver = { -- cgit v0.10.2 From 930ab3d403ae43f19d7e6d972139e02c9b8a5ec6 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 22 Aug 2013 16:19:05 +0200 Subject: i2c: mv64xxx: Add I2C Transaction Generator support The I2C Transaction Generator offloads CPU from managing I2C transfer step by step. This feature is currently only available on Armada XP, so usage of this mechanism is activated through device tree. Based on the work of Piotr Ziecik and rewrote to use the new way of handling multiples i2c messages. Signed-off-by: Piotr Ziecik Signed-off-by: Gregory CLEMENT Signed-off-by: Wolfram Sang diff --git a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt index 6113f92..73cdc03 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt @@ -5,6 +5,7 @@ Required properties : - reg : Offset and length of the register set for the device - compatible : Should be "marvell,mv64xxx-i2c" or "allwinner,sun4i-i2c" + or "marvell,mv7230-i2c" - interrupts : The interrupt number Optional properties : @@ -20,3 +21,12 @@ Examples: interrupts = <29>; clock-frequency = <100000>; }; + +For the Armada XP: + + i2c@11000 { + compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; + reg = <0x11000 0x100>; + interrupts = <29>; + clock-frequency = <100000>; + }; diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 9cc361d..2404c4e 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -55,6 +55,32 @@ #define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8 #define MV64XXX_I2C_STATUS_NO_STATUS 0xf8 +/* Register defines (I2C bridge) */ +#define MV64XXX_I2C_REG_TX_DATA_LO 0xc0 +#define MV64XXX_I2C_REG_TX_DATA_HI 0xc4 +#define MV64XXX_I2C_REG_RX_DATA_LO 0xc8 +#define MV64XXX_I2C_REG_RX_DATA_HI 0xcc +#define MV64XXX_I2C_REG_BRIDGE_CONTROL 0xd0 +#define MV64XXX_I2C_REG_BRIDGE_STATUS 0xd4 +#define MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE 0xd8 +#define MV64XXX_I2C_REG_BRIDGE_INTR_MASK 0xdC +#define MV64XXX_I2C_REG_BRIDGE_TIMING 0xe0 + +/* Bridge Control values */ +#define MV64XXX_I2C_BRIDGE_CONTROL_WR 0x00000001 +#define MV64XXX_I2C_BRIDGE_CONTROL_RD 0x00000002 +#define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT 2 +#define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT 0x00001000 +#define MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT 13 +#define MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT 16 +#define MV64XXX_I2C_BRIDGE_CONTROL_ENABLE 0x00080000 + +/* Bridge Status values */ +#define MV64XXX_I2C_BRIDGE_STATUS_ERROR 0x00000001 +#define MV64XXX_I2C_STATUS_OFFLOAD_ERROR 0xf0000001 +#define MV64XXX_I2C_STATUS_OFFLOAD_OK 0xf0000000 + + /* Driver states */ enum { MV64XXX_I2C_STATE_INVALID, @@ -71,14 +97,17 @@ enum { enum { MV64XXX_I2C_ACTION_INVALID, MV64XXX_I2C_ACTION_CONTINUE, + MV64XXX_I2C_ACTION_OFFLOAD_SEND_START, MV64XXX_I2C_ACTION_SEND_START, MV64XXX_I2C_ACTION_SEND_RESTART, + MV64XXX_I2C_ACTION_OFFLOAD_RESTART, MV64XXX_I2C_ACTION_SEND_ADDR_1, MV64XXX_I2C_ACTION_SEND_ADDR_2, MV64XXX_I2C_ACTION_SEND_DATA, MV64XXX_I2C_ACTION_RCV_DATA, MV64XXX_I2C_ACTION_RCV_DATA_STOP, MV64XXX_I2C_ACTION_SEND_STOP, + MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP, }; struct mv64xxx_i2c_regs { @@ -117,6 +146,7 @@ struct mv64xxx_i2c_data { spinlock_t lock; struct i2c_msg *msg; struct i2c_adapter adapter; + bool offload_enabled; }; static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { @@ -165,6 +195,77 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, } } +static int mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data) +{ + unsigned long data_reg_hi = 0; + unsigned long data_reg_lo = 0; + unsigned long ctrl_reg; + struct i2c_msg *msg = drv_data->msgs; + + drv_data->msg = msg; + drv_data->byte_posn = 0; + drv_data->bytes_left = msg->len; + drv_data->aborting = 0; + drv_data->rc = 0; + /* Only regular transactions can be offloaded */ + if ((msg->flags & ~(I2C_M_TEN | I2C_M_RD)) != 0) + return -EINVAL; + + /* Only 1-8 byte transfers can be offloaded */ + if (msg->len < 1 || msg->len > 8) + return -EINVAL; + + /* Build transaction */ + ctrl_reg = MV64XXX_I2C_BRIDGE_CONTROL_ENABLE | + (msg->addr << MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT); + + if ((msg->flags & I2C_M_TEN) != 0) + ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT; + + if ((msg->flags & I2C_M_RD) == 0) { + u8 local_buf[8] = { 0 }; + + memcpy(local_buf, msg->buf, msg->len); + data_reg_lo = cpu_to_le32(*((u32 *)local_buf)); + data_reg_hi = cpu_to_le32(*((u32 *)(local_buf+4))); + + ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_WR | + (msg->len - 1) << MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT; + + writel_relaxed(data_reg_lo, + drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_LO); + writel_relaxed(data_reg_hi, + drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_HI); + + } else { + ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_RD | + (msg->len - 1) << MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT; + } + + /* Execute transaction */ + writel(ctrl_reg, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); + + return 0; +} + +static void +mv64xxx_i2c_update_offload_data(struct mv64xxx_i2c_data *drv_data) +{ + struct i2c_msg *msg = drv_data->msg; + + if (msg->flags & I2C_M_RD) { + u32 data_reg_lo = readl(drv_data->reg_base + + MV64XXX_I2C_REG_RX_DATA_LO); + u32 data_reg_hi = readl(drv_data->reg_base + + MV64XXX_I2C_REG_RX_DATA_HI); + u8 local_buf[8] = { 0 }; + + *((u32 *)local_buf) = le32_to_cpu(data_reg_lo); + *((u32 *)(local_buf+4)) = le32_to_cpu(data_reg_hi); + memcpy(msg->buf, local_buf, msg->len); + } + +} /* ***************************************************************************** * @@ -177,6 +278,15 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, static void mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) { + if (drv_data->offload_enabled) { + writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); + writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_TIMING); + writel(0, drv_data->reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); + writel(0, drv_data->reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_MASK); + } + writel(0, drv_data->reg_base + drv_data->reg_offsets.soft_reset); writel(MV64XXX_I2C_BAUD_DIV_M(drv_data->freq_m) | MV64XXX_I2C_BAUD_DIV_N(drv_data->freq_n), drv_data->reg_base + drv_data->reg_offsets.clock); @@ -283,6 +393,16 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) drv_data->rc = -ENXIO; break; + case MV64XXX_I2C_STATUS_OFFLOAD_OK: + if (drv_data->send_stop || drv_data->aborting) { + drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP; + drv_data->state = MV64XXX_I2C_STATE_IDLE; + } else { + drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_RESTART; + drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_RESTART; + } + break; + default: dev_err(&drv_data->adapter.dev, "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, " @@ -299,20 +419,27 @@ static void mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) { switch(drv_data->action) { + case MV64XXX_I2C_ACTION_OFFLOAD_RESTART: + mv64xxx_i2c_update_offload_data(drv_data); + writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); + writel(0, drv_data->reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); + /* FALLTHRU */ case MV64XXX_I2C_ACTION_SEND_RESTART: /* We should only get here if we have further messages */ BUG_ON(drv_data->num_msgs == 0); - drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; - writel(drv_data->cntl_bits, - drv_data->reg_base + drv_data->reg_offsets.control); - drv_data->msgs++; drv_data->num_msgs--; + if (!(drv_data->offload_enabled && + mv64xxx_i2c_offload_msg(drv_data))) { + drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; + writel(drv_data->cntl_bits, + drv_data->reg_base + drv_data->reg_offsets.control); - /* Setup for the next message */ - mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); - + /* Setup for the next message */ + mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); + } /* * We're never at the start of the message here, and by this * time it's already too late to do any protocol mangling. @@ -326,6 +453,12 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) drv_data->reg_base + drv_data->reg_offsets.control); break; + case MV64XXX_I2C_ACTION_OFFLOAD_SEND_START: + if (!mv64xxx_i2c_offload_msg(drv_data)) + break; + else + drv_data->action = MV64XXX_I2C_ACTION_SEND_START; + /* FALLTHRU */ case MV64XXX_I2C_ACTION_SEND_START: writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, drv_data->reg_base + drv_data->reg_offsets.control); @@ -375,6 +508,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) "mv64xxx_i2c_do_action: Invalid action: %d\n", drv_data->action); drv_data->rc = -EIO; + /* FALLTHRU */ case MV64XXX_I2C_ACTION_SEND_STOP: drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; @@ -383,6 +517,15 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) drv_data->block = 0; wake_up(&drv_data->waitq); break; + + case MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP: + mv64xxx_i2c_update_offload_data(drv_data); + writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); + writel(0, drv_data->reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); + drv_data->block = 0; + wake_up(&drv_data->waitq); + break; } } @@ -395,6 +538,21 @@ mv64xxx_i2c_intr(int irq, void *dev_id) irqreturn_t rc = IRQ_NONE; spin_lock_irqsave(&drv_data->lock, flags); + + if (drv_data->offload_enabled) { + while (readl(drv_data->reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE)) { + int reg_status = readl(drv_data->reg_base + + MV64XXX_I2C_REG_BRIDGE_STATUS); + if (reg_status & MV64XXX_I2C_BRIDGE_STATUS_ERROR) + status = MV64XXX_I2C_STATUS_OFFLOAD_ERROR; + else + status = MV64XXX_I2C_STATUS_OFFLOAD_OK; + mv64xxx_i2c_fsm(drv_data, status); + mv64xxx_i2c_do_action(drv_data); + rc = IRQ_HANDLED; + } + } while (readl(drv_data->reg_base + drv_data->reg_offsets.control) & MV64XXX_I2C_REG_CONTROL_IFLG) { status = readl(drv_data->reg_base + drv_data->reg_offsets.status); @@ -459,11 +617,15 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, unsigned long flags; spin_lock_irqsave(&drv_data->lock, flags); - mv64xxx_i2c_prepare_for_io(drv_data, msg); - - drv_data->action = MV64XXX_I2C_ACTION_SEND_START; - drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; + if (drv_data->offload_enabled) { + drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_START; + drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; + } else { + mv64xxx_i2c_prepare_for_io(drv_data, msg); + drv_data->action = MV64XXX_I2C_ACTION_SEND_START; + drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; + } drv_data->send_stop = is_last; drv_data->block = 1; mv64xxx_i2c_do_action(drv_data); @@ -521,6 +683,7 @@ static const struct i2c_algorithm mv64xxx_i2c_algo = { static const struct of_device_id mv64xxx_i2c_of_match_table[] = { { .compatible = "allwinner,sun4i-i2c", .data = &mv64xxx_i2c_regs_sun4i}, { .compatible = "marvell,mv64xxx-i2c", .data = &mv64xxx_i2c_regs_mv64xxx}, + { .compatible = "marvell,mv78230-i2c", .data = &mv64xxx_i2c_regs_mv64xxx}, {} }; MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table); @@ -601,6 +764,13 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, memcpy(&drv_data->reg_offsets, device->data, sizeof(drv_data->reg_offsets)); + /* + * For controllers embedded in new SoCs activate the + * Transaction Generator support. + */ + if (of_device_is_compatible(np, "marvell,mv78230-i2c")) + drv_data->offload_enabled = true; + out: return rc; #endif @@ -654,6 +824,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) drv_data->freq_n = pdata->freq_n; drv_data->irq = platform_get_irq(pd, 0); drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout); + drv_data->offload_enabled = false; memcpy(&drv_data->reg_offsets, &mv64xxx_i2c_regs_mv64xxx, sizeof(drv_data->reg_offsets)); } else if (pd->dev.of_node) { rc = mv64xxx_of_config(drv_data, &pd->dev); -- cgit v0.10.2 From c1d15b68aab86f1f3b602fa65e7618c0065d46e6 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 22 Aug 2013 16:19:06 +0200 Subject: i2c: mv64xxx: Fix timing issue on Armada XP (errata FE-8471889) All the Armada XP (mv78230, mv78260 and mv78460) have a silicon issue in the I2C controller which violate the i2c repeated start timing. The I2C standard requires a minimum of 4.7us for the repeated start condition whereas the I2C controller of the Armada XP this time is 2.9us. So this patch adds a 5us delay for the start case only if the the compatible i2c-mv78230 is set. Based on the initals patches from Zbigniew Bodek Signed-off-by: Gregory CLEMENT Signed-off-by: Zbigniew Bodek Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 2404c4e..bc60f9a 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -24,6 +24,7 @@ #include #include #include +#include #define MV64XXX_I2C_ADDR_ADDR(val) ((val & 0x7f) << 1) #define MV64XXX_I2C_BAUD_DIV_N(val) (val & 0x7) @@ -147,6 +148,8 @@ struct mv64xxx_i2c_data { struct i2c_msg *msg; struct i2c_adapter adapter; bool offload_enabled; +/* 5us delay in order to avoid repeated start timing violation */ + bool errata_delay; }; static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { @@ -440,6 +443,9 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) /* Setup for the next message */ mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); } + if (drv_data->errata_delay) + udelay(5); + /* * We're never at the start of the message here, and by this * time it's already too late to do any protocol mangling. @@ -499,6 +505,9 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, drv_data->reg_base + drv_data->reg_offsets.control); drv_data->block = 0; + if (drv_data->errata_delay) + udelay(5); + wake_up(&drv_data->waitq); break; @@ -766,10 +775,12 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, /* * For controllers embedded in new SoCs activate the - * Transaction Generator support. + * Transaction Generator support and the errata fix. */ - if (of_device_is_compatible(np, "marvell,mv78230-i2c")) + if (of_device_is_compatible(np, "marvell,mv78230-i2c")) { drv_data->offload_enabled = true; + drv_data->errata_delay = true; + } out: return rc; -- cgit v0.10.2 From 687b81d083c082bc1e853032e3a2a54f8c251d27 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 11 Jul 2013 12:56:15 +0100 Subject: i2c: move OF helpers into the core I2C of helpers used to live in of_i2c.c but experience (from SPI) shows that it is much cleaner to have this in the core. This also removes a circular dependency between the helpers and the core, and so we can finally register child nodes in the core instead of doing this manually in each driver. So, fix the drivers and documentation, too. Signed-off-by: Wolfram Sang diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt index d9be7a9..958266e 100644 --- a/Documentation/acpi/enumeration.txt +++ b/Documentation/acpi/enumeration.txt @@ -238,7 +238,6 @@ An I2C bus (controller) driver does: if (ret) /* handle error */ - of_i2c_register_devices(adapter); /* Enumerate the slave devices behind this bus via ACPI */ acpi_i2c_register_devices(adapter); diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 4cfa499..534574a 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index dfffaf0..a19f657 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index 925c7cd..c38b56b 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/drivers/gpu/host1x/drm/output.c b/drivers/gpu/host1x/drm/output.c index 8140fc6..137ae81 100644 --- a/drivers/gpu/host1x/drm/output.c +++ b/drivers/gpu/host1x/drm/output.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include "drm.h" diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 6bb839b..fd05930 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -775,8 +774,6 @@ static int at91_twi_probe(struct platform_device *pdev) return rc; } - of_i2c_register_devices(&dev->adapter); - dev_info(dev->dev, "AT91 i2c bus driver.\n"); return 0; } diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 2e1f7eb..b2b8aa9 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -681,11 +680,6 @@ static int cpm_i2c_probe(struct platform_device *ofdev) dev_dbg(&ofdev->dev, "hw routines for %s registered.\n", cpm->adap.name); - /* - * register OF I2C devices - */ - of_i2c_register_devices(&cpm->adap); - return 0; out_shut: cpm_i2c_shutdown(cpm); diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index cf90bff..5747341 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -726,7 +725,6 @@ static int davinci_i2c_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failure adding adapter\n"); goto err_unuse_clocks; } - of_i2c_register_devices(adap); return 0; diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 64ffb90..ded77c3 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -172,7 +171,6 @@ static int dw_i2c_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failure adding adapter\n"); return r; } - of_i2c_register_devices(adap); acpi_i2c_register_devices(adap); pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 8cdb4f7..bfa02c6 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -16,7 +16,6 @@ #include #include #include -#include struct i2c_gpio_private_data { struct i2c_adapter adap; @@ -224,8 +223,6 @@ static int i2c_gpio_probe(struct platform_device *pdev) if (ret) goto err_add_bus; - of_i2c_register_devices(adap); - platform_set_drvdata(pdev, priv); dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 4ebceed..4296d17 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -87,7 +87,6 @@ #include #include #include -#include #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ defined CONFIG_DMI @@ -1230,7 +1229,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) goto exit_free_irq; } - of_i2c_register_devices(&priv->adapter); i801_probe_optional_slaves(priv); /* We ignore errors - multiplexing is optional */ i801_add_mux(priv); diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 973f516..ff3caa0 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -42,7 +42,6 @@ #include #include #include -#include #include "i2c-ibm_iic.h" @@ -759,9 +758,6 @@ static int iic_probe(struct platform_device *ofdev) dev_info(&ofdev->dev, "using %s mode\n", dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); - /* Now register all the child nodes */ - of_i2c_register_devices(adap); - return 0; error_cleanup: diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index a231d2f..ccf4665 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -52,7 +52,6 @@ #include #include #include -#include #include /** Defines ******************************************************************** @@ -682,8 +681,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev) return ret; } - of_i2c_register_devices(&i2c_imx->adapter); - /* Set up platform driver data */ platform_set_drvdata(pdev, i2c_imx); clk_disable_unprepare(i2c_imx->clk); diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index ffac214..f406093 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -694,7 +693,6 @@ static int fsl_i2c_probe(struct platform_device *op) dev_err(i2c->dev, "failed to add adapter\n"); goto fail_add; } - of_i2c_register_devices(&i2c->adap); return result; diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index bc60f9a..7f3a474 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -871,8 +870,6 @@ mv64xxx_i2c_probe(struct platform_device *pd) goto exit_free_irq; } - of_i2c_register_devices(&drv_data->adapter); - return 0; exit_free_irq: diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 46cda0b..f4a0167 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -752,8 +751,6 @@ static int mxs_i2c_probe(struct platform_device *pdev) return err; } - of_i2c_register_devices(adap); - return 0; } diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 1909e80..8bf9ac0 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #define DRIVER_NAME "nmk-i2c" @@ -1045,8 +1044,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) goto err_add_adap; } - of_i2c_register_devices(adap); - pm_runtime_put(&adev->dev); return 0; diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index e14182c..c61f37a 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -24,7 +24,6 @@ #include #include #include -#include #include struct ocores_i2c { @@ -432,8 +431,6 @@ static int ocores_i2c_probe(struct platform_device *pdev) if (pdata) { for (i = 0; i < pdata->num_devices; i++) i2c_new_device(&i2c->adap, pdata->devices + i); - } else { - of_i2c_register_devices(&i2c->adap); } return 0; diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 956fe32..b929ba2 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -599,8 +598,6 @@ static int octeon_i2c_probe(struct platform_device *pdev) } dev_info(i2c->dev, "version %s\n", DRV_VERSION); - of_i2c_register_devices(&i2c->adap); - return 0; out: diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 9ccb7b9..6d8308d 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -1231,8 +1230,6 @@ omap_i2c_probe(struct platform_device *pdev) dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr, major, minor, dev->speed); - of_i2c_register_devices(adap); - pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 1713b3e..d09577a 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -23,7 +23,6 @@ #include #include #include -#include #define I2C_PNX_TIMEOUT_DEFAULT 10 /* msec */ #define I2C_PNX_SPEED_KHZ_DEFAULT 100 @@ -741,8 +740,6 @@ static int i2c_pnx_probe(struct platform_device *pdev) goto out_irq; } - of_i2c_register_devices(&alg_data->adapter); - dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", alg_data->adapter.name, res->start, alg_data->irq); diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 06858d5..37e8cfa 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -440,7 +440,9 @@ static int i2c_powermac_probe(struct platform_device *dev) adapter->algo = &i2c_powermac_algorithm; i2c_set_adapdata(adapter, bus); adapter->dev.parent = &dev->dev; - adapter->dev.of_node = dev->dev.of_node; + + /* Clear of_node to skip automatic registration of i2c child nodes */ + adapter->dev.of_node = NULL; rc = i2c_add_adapter(adapter); if (rc) { printk(KERN_ERR "i2c-powermac: Adapter %s registration " @@ -451,9 +453,8 @@ static int i2c_powermac_probe(struct platform_device *dev) printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name); - /* Cannot use of_i2c_register_devices() due to Apple device-tree - * funkyness - */ + /* Use custom child registration due to Apple device-tree funkyness */ + adapter->dev.of_node = dev->dev.of_node; i2c_powermac_register_devices(adapter, bus); return 0; diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 3dbc1ac..bbe6dfb 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -1247,7 +1246,6 @@ static int i2c_pxa_probe(struct platform_device *dev) printk(KERN_INFO "I2C: Failed to add bus\n"); goto eadapt; } - of_i2c_register_devices(&i2c->adap); platform_set_drvdata(dev, i2c); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 0a077b1..3535f3c 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include @@ -1154,7 +1153,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) return ret; } - of_i2c_register_devices(&i2c->adap); platform_set_drvdata(pdev, i2c); pm_runtime_enable(&pdev->dev); diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 4e86a31..55110dd 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -758,7 +757,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) "I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n", adap->nr, pd->bus_speed, pd->iccl, pd->icch); - of_i2c_register_devices(adap); return 0; err_all: diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index a63c7d5..0ff22e2 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -366,8 +365,6 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) clk_disable(clk); - of_i2c_register_devices(adap); - dev_info(&pdev->dev, " I2C adapter ready to operate\n"); return 0; diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index 19a40af..f8f6f2e 100644 --- a/drivers/i2c/busses/i2c-stu300.c +++ b/drivers/i2c/busses/i2c-stu300.c @@ -17,7 +17,6 @@ #include #include #include -#include /* the name of this kernel module */ #define NAME "stu300" @@ -933,7 +932,6 @@ stu300_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n", dev->virtbase, dev->irq); - of_i2c_register_devices(adap); return 0; } diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 9aa1b60..c457cb4 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -802,8 +801,6 @@ static int tegra_i2c_probe(struct platform_device *pdev) return ret; } - of_i2c_register_devices(&i2c_dev->adapter); - return 0; } diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c index f3a8790..6bb3a89 100644 --- a/drivers/i2c/busses/i2c-versatile.c +++ b/drivers/i2c/busses/i2c-versatile.c @@ -16,7 +16,6 @@ #include #include #include -#include #define I2C_CONTROL 0x00 #define I2C_CONTROLS 0x00 @@ -108,7 +107,6 @@ static int i2c_versatile_probe(struct platform_device *dev) ret = i2c_bit_add_numbered_bus(&i2c->adap); if (ret >= 0) { platform_set_drvdata(dev, i2c); - of_i2c_register_devices(&i2c->adap); return 0; } diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c index baaa7d1..c65da3d 100644 --- a/drivers/i2c/busses/i2c-wmt.c +++ b/drivers/i2c/busses/i2c-wmt.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -439,8 +438,6 @@ static int wmt_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, i2c_dev); - of_i2c_register_devices(adap); - return 0; } diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 433f377..4c8b368 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -40,7 +40,6 @@ #include #include #include -#include #define DRIVER_NAME "xiic-i2c" @@ -752,8 +751,6 @@ static int xiic_i2c_probe(struct platform_device *pdev) i2c_new_device(&i2c->adap, pdata->devices + i); } - of_i2c_register_devices(&i2c->adap); - return 0; add_adapter_failed: diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 3d9ca2d..e874b05 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -23,7 +23,11 @@ SMBus 2.0 support by Mark Studebaker and Jean Delvare Mux support by Rodolfo Giometti and - Michael Lawnick */ + Michael Lawnick + OF support is copyright (c) 2008 Jochen Friedrich + (based on a previous patch from Jon Smirl ) and + (c) 2013 Wolfram Sang + */ #include #include @@ -35,7 +39,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -954,6 +960,104 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter) up_read(&__i2c_board_lock); } +/* OF support code */ + +#if IS_ENABLED(CONFIG_OF) +static void of_i2c_register_devices(struct i2c_adapter *adap) +{ + void *result; + struct device_node *node; + + /* Only register child devices if the adapter has a node pointer set */ + if (!adap->dev.of_node) + return; + + dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); + + for_each_available_child_of_node(adap->dev.of_node, node) { + struct i2c_board_info info = {}; + struct dev_archdata dev_ad = {}; + const __be32 *addr; + int len; + + dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name); + + if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { + dev_err(&adap->dev, "of_i2c: modalias failure on %s\n", + node->full_name); + continue; + } + + addr = of_get_property(node, "reg", &len); + if (!addr || (len < sizeof(int))) { + dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", + node->full_name); + continue; + } + + info.addr = be32_to_cpup(addr); + if (info.addr > (1 << 10) - 1) { + dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", + info.addr, node->full_name); + continue; + } + + info.irq = irq_of_parse_and_map(node, 0); + info.of_node = of_node_get(node); + info.archdata = &dev_ad; + + if (of_get_property(node, "wakeup-source", NULL)) + info.flags |= I2C_CLIENT_WAKE; + + request_module("%s%s", I2C_MODULE_PREFIX, info.type); + + result = i2c_new_device(adap, &info); + if (result == NULL) { + dev_err(&adap->dev, "of_i2c: Failure registering %s\n", + node->full_name); + of_node_put(node); + irq_dispose_mapping(info.irq); + continue; + } + } +} + +static int of_dev_node_match(struct device *dev, void *data) +{ + return dev->of_node == data; +} + +/* must call put_device() when done with returned i2c_client device */ +struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) +{ + struct device *dev; + + dev = bus_find_device(&i2c_bus_type, NULL, node, + of_dev_node_match); + if (!dev) + return NULL; + + return i2c_verify_client(dev); +} +EXPORT_SYMBOL(of_find_i2c_device_by_node); + +/* must call put_device() when done with returned i2c_adapter device */ +struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) +{ + struct device *dev; + + dev = bus_find_device(&i2c_bus_type, NULL, node, + of_dev_node_match); + if (!dev) + return NULL; + + return i2c_verify_adapter(dev); +} +EXPORT_SYMBOL(of_find_i2c_adapter_by_node); +#else +static void of_i2c_register_devices(struct i2c_adapter *adap) { } +#endif /* CONFIG_OF */ + static int i2c_do_add_adapter(struct i2c_driver *driver, struct i2c_adapter *adap) { @@ -1058,6 +1162,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap) exit_recovery: /* create pre-declared device nodes */ + of_i2c_register_devices(adap); + if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); @@ -1282,7 +1388,6 @@ void i2c_del_adapter(struct i2c_adapter *adap) } EXPORT_SYMBOL(i2c_del_adapter); - /* ------------------------------------------------------------------------- */ int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *)) diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 7409ebb..797e311 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -25,7 +25,6 @@ #include #include #include -#include /* multiplexer per channel data */ struct i2c_mux_priv { @@ -185,8 +184,6 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", i2c_adapter_id(&priv->adap)); - of_i2c_register_devices(&priv->adap); - return &priv->adap; } EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c index f7bf243..74b41ae 100644 --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 6a206e8..5d4a99b 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -16,7 +16,6 @@ #include #include #include -#include #include struct gpiomux { diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 0d08202..69a9173 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c index 617a798..9930556 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c +++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include @@ -67,8 +67,6 @@ static int fimc_is_i2c_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_enable(&i2c_adap->dev); - of_i2c_register_devices(i2c_adap); - return 0; } diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 967f6a9..2276fdc 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 19f556c..f8c66b4 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 80e5c13..78cc760 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -48,12 +48,6 @@ config OF_IRQ def_bool y depends on !SPARC -config OF_I2C - def_tristate I2C - depends on I2C - help - OpenFirmware I2C accessors - config OF_NET depends on NETDEVICES def_bool y diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 1f9c0c4..efd0510 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -3,7 +3,6 @@ obj-$(CONFIG_OF_FLATTREE) += fdt.o obj-$(CONFIG_OF_PROMTREE) += pdt.o obj-$(CONFIG_OF_ADDRESS) += address.o obj-$(CONFIG_OF_IRQ) += irq.o -obj-$(CONFIG_OF_I2C) += of_i2c.o obj-$(CONFIG_OF_NET) += of_net.o obj-$(CONFIG_OF_SELFTEST) += selftest.o obj-$(CONFIG_OF_MDIO) += of_mdio.o diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c deleted file mode 100644 index b667264..0000000 --- a/drivers/of/of_i2c.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * OF helpers for the I2C API - * - * Copyright (c) 2008 Jochen Friedrich - * - * Based on a previous patch from Jon Smirl - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include - -void of_i2c_register_devices(struct i2c_adapter *adap) -{ - void *result; - struct device_node *node; - - /* Only register child devices if the adapter has a node pointer set */ - if (!adap->dev.of_node) - return; - - dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); - - for_each_available_child_of_node(adap->dev.of_node, node) { - struct i2c_board_info info = {}; - struct dev_archdata dev_ad = {}; - const __be32 *addr; - int len; - - dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name); - - if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { - dev_err(&adap->dev, "of_i2c: modalias failure on %s\n", - node->full_name); - continue; - } - - addr = of_get_property(node, "reg", &len); - if (!addr || (len < sizeof(int))) { - dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", - node->full_name); - continue; - } - - info.addr = be32_to_cpup(addr); - if (info.addr > (1 << 10) - 1) { - dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", - info.addr, node->full_name); - continue; - } - - info.irq = irq_of_parse_and_map(node, 0); - info.of_node = of_node_get(node); - info.archdata = &dev_ad; - - if (of_get_property(node, "wakeup-source", NULL)) - info.flags |= I2C_CLIENT_WAKE; - - request_module("%s%s", I2C_MODULE_PREFIX, info.type); - - result = i2c_new_device(adap, &info); - if (result == NULL) { - dev_err(&adap->dev, "of_i2c: Failure registering %s\n", - node->full_name); - of_node_put(node); - irq_dispose_mapping(info.irq); - continue; - } - } -} -EXPORT_SYMBOL(of_i2c_register_devices); - -static int of_dev_node_match(struct device *dev, void *data) -{ - return dev->of_node == data; -} - -/* must call put_device() when done with returned i2c_client device */ -struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) -{ - struct device *dev; - - dev = bus_find_device(&i2c_bus_type, NULL, node, - of_dev_node_match); - if (!dev) - return NULL; - - return i2c_verify_client(dev); -} -EXPORT_SYMBOL(of_find_i2c_device_by_node); - -/* must call put_device() when done with returned i2c_adapter device */ -struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) -{ - struct device *dev; - - dev = bus_find_device(&i2c_bus_type, NULL, node, - of_dev_node_match); - if (!dev) - return NULL; - - return i2c_verify_adapter(dev); -} -EXPORT_SYMBOL(of_find_i2c_adapter_by_node); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c index a56797d..2d76fd4 100644 --- a/drivers/staging/imx-drm/imx-tve.c +++ b/drivers/staging/imx-drm/imx-tve.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/linux/i2c.h b/include/linux/i2c.h index b3c4b8d..ed53696 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -544,6 +544,26 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap) #endif /* I2C */ +#if IS_ENABLED(CONFIG_OF) +/* must call put_device() when done with returned i2c_client device */ +extern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node); + +/* must call put_device() when done with returned i2c_adapter device */ +extern struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node); + +#else + +static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) +{ + return NULL; +} + +static inline struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) +{ + return NULL; +} +#endif /* CONFIG_OF */ + #if IS_ENABLED(CONFIG_ACPI_I2C) extern void acpi_i2c_register_devices(struct i2c_adapter *adap); #else diff --git a/include/linux/of_i2c.h b/include/linux/of_i2c.h deleted file mode 100644 index cfb545c..0000000 --- a/include/linux/of_i2c.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Generic I2C API implementation for PowerPC. - * - * Copyright (c) 2008 Jochen Friedrich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef __LINUX_OF_I2C_H -#define __LINUX_OF_I2C_H - -#if defined(CONFIG_OF_I2C) || defined(CONFIG_OF_I2C_MODULE) -#include - -extern void of_i2c_register_devices(struct i2c_adapter *adap); - -/* must call put_device() when done with returned i2c_client device */ -extern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node); - -/* must call put_device() when done with returned i2c_adapter device */ -extern struct i2c_adapter *of_find_i2c_adapter_by_node( - struct device_node *node); - -#else -static inline void of_i2c_register_devices(struct i2c_adapter *adap) -{ - return; -} - -static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) -{ - return NULL; -} - -/* must call put_device() when done with returned i2c_adapter device */ -static inline struct i2c_adapter *of_find_i2c_adapter_by_node( - struct device_node *node) -{ - return NULL; -} -#endif /* CONFIG_OF_I2C */ - -#endif /* __LINUX_OF_I2C_H */ diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 3f726e4..f2fbde9 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index 52a36a9..9fd7a65 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include -- cgit v0.10.2 From 55e71edb81b2b45273e7b284cce13ff24bde846f Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 21 Aug 2013 17:28:23 +0300 Subject: i2c: move ACPI helpers into the core This follows what has already been done for the DeviceTree helpers. Move the ACPI helpers from drivers/acpi/acpi_i2c.c to the I2C core and update documentation accordingly. This also solves a problem reported by Jerry Snitselaar that we can't build the ACPI I2C helpers as a module. Signed-off-by: Mika Westerberg Acked-by: Rafael J. Wysocki Signed-off-by: Wolfram Sang diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt index 958266e..d977778 100644 --- a/Documentation/acpi/enumeration.txt +++ b/Documentation/acpi/enumeration.txt @@ -228,18 +228,9 @@ ACPI handle like: I2C serial bus support ~~~~~~~~~~~~~~~~~~~~~~ The slaves behind I2C bus controller only need to add the ACPI IDs like -with the platform and SPI drivers. However the I2C bus controller driver -needs to call acpi_i2c_register_devices() after it has added the adapter. - -An I2C bus (controller) driver does: - - ... - ret = i2c_add_numbered_adapter(adapter); - if (ret) - /* handle error */ - - /* Enumerate the slave devices behind this bus via ACPI */ - acpi_i2c_register_devices(adapter); +with the platform and SPI drivers. The I2C core automatically enumerates +any slave devices behind the controller device once the adapter is +registered. Below is an example of how to add ACPI support to the existing mpu3050 input driver: diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 100bd72..4e0162f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -180,12 +180,6 @@ config ACPI_DOCK This driver supports ACPI-controlled docking stations and removable drive bays such as the IBM Ultrabay and the Dell Module Bay. -config ACPI_I2C - def_tristate I2C - depends on I2C - help - ACPI I2C enumeration support. - config ACPI_PROCESSOR tristate "Processor" select THERMAL diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 81dbeb8..cdaf68b 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -73,7 +73,6 @@ obj-$(CONFIG_ACPI_HED) += hed.o obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o obj-$(CONFIG_ACPI_BGRT) += bgrt.o -obj-$(CONFIG_ACPI_I2C) += acpi_i2c.o # processor has its own "processor." module_param namespace processor-y := processor_driver.o processor_throttling.o diff --git a/drivers/acpi/acpi_i2c.c b/drivers/acpi/acpi_i2c.c deleted file mode 100644 index a82c762..0000000 --- a/drivers/acpi/acpi_i2c.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ACPI I2C enumeration support - * - * Copyright (C) 2012, Intel Corporation - * Author: Mika Westerberg - * - * 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 -#include -#include -#include -#include - -ACPI_MODULE_NAME("i2c"); - -static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) -{ - struct i2c_board_info *info = data; - - if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { - struct acpi_resource_i2c_serialbus *sb; - - sb = &ares->data.i2c_serial_bus; - if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { - info->addr = sb->slave_address; - if (sb->access_mode == ACPI_I2C_10BIT_MODE) - info->flags |= I2C_CLIENT_TEN; - } - } else if (info->irq < 0) { - struct resource r; - - if (acpi_dev_resource_interrupt(ares, 0, &r)) - info->irq = r.start; - } - - /* Tell the ACPI core to skip this resource */ - return 1; -} - -static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, - void *data, void **return_value) -{ - struct i2c_adapter *adapter = data; - struct list_head resource_list; - struct i2c_board_info info; - struct acpi_device *adev; - int ret; - - if (acpi_bus_get_device(handle, &adev)) - return AE_OK; - if (acpi_bus_get_status(adev) || !adev->status.present) - return AE_OK; - - memset(&info, 0, sizeof(info)); - info.acpi_node.handle = handle; - info.irq = -1; - - INIT_LIST_HEAD(&resource_list); - ret = acpi_dev_get_resources(adev, &resource_list, - acpi_i2c_add_resource, &info); - acpi_dev_free_resource_list(&resource_list); - - if (ret < 0 || !info.addr) - return AE_OK; - - strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); - if (!i2c_new_device(adapter, &info)) { - dev_err(&adapter->dev, - "failed to add I2C device %s from ACPI\n", - dev_name(&adev->dev)); - } - - return AE_OK; -} - -/** - * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter - * @adapter: pointer to adapter - * - * Enumerate all I2C slave devices behind this adapter by walking the ACPI - * namespace. When a device is found it will be added to the Linux device - * model and bound to the corresponding ACPI handle. - */ -void acpi_i2c_register_devices(struct i2c_adapter *adapter) -{ - acpi_handle handle; - acpi_status status; - - handle = ACPI_HANDLE(adapter->dev.parent); - if (!handle) - return; - - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, - acpi_i2c_add_device, NULL, - adapter, NULL); - if (ACPI_FAILURE(status)) - dev_warn(&adapter->dev, "failed to enumerate I2C slaves\n"); -} -EXPORT_SYMBOL_GPL(acpi_i2c_register_devices); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index ded77c3..6e99d9f 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -171,7 +171,6 @@ static int dw_i2c_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failure adding adapter\n"); return r; } - acpi_i2c_register_devices(adap); pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); pm_runtime_use_autosuspend(&pdev->dev); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e874b05..29d3f04 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1058,6 +1058,96 @@ EXPORT_SYMBOL(of_find_i2c_adapter_by_node); static void of_i2c_register_devices(struct i2c_adapter *adap) { } #endif /* CONFIG_OF */ +/* ACPI support code */ + +#if IS_ENABLED(CONFIG_ACPI) +static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) +{ + struct i2c_board_info *info = data; + + if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { + struct acpi_resource_i2c_serialbus *sb; + + sb = &ares->data.i2c_serial_bus; + if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { + info->addr = sb->slave_address; + if (sb->access_mode == ACPI_I2C_10BIT_MODE) + info->flags |= I2C_CLIENT_TEN; + } + } else if (info->irq < 0) { + struct resource r; + + if (acpi_dev_resource_interrupt(ares, 0, &r)) + info->irq = r.start; + } + + /* Tell the ACPI core to skip this resource */ + return 1; +} + +static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, + void *data, void **return_value) +{ + struct i2c_adapter *adapter = data; + struct list_head resource_list; + struct i2c_board_info info; + struct acpi_device *adev; + int ret; + + if (acpi_bus_get_device(handle, &adev)) + return AE_OK; + if (acpi_bus_get_status(adev) || !adev->status.present) + return AE_OK; + + memset(&info, 0, sizeof(info)); + info.acpi_node.handle = handle; + info.irq = -1; + + INIT_LIST_HEAD(&resource_list); + ret = acpi_dev_get_resources(adev, &resource_list, + acpi_i2c_add_resource, &info); + acpi_dev_free_resource_list(&resource_list); + + if (ret < 0 || !info.addr) + return AE_OK; + + strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); + if (!i2c_new_device(adapter, &info)) { + dev_err(&adapter->dev, + "failed to add I2C device %s from ACPI\n", + dev_name(&adev->dev)); + } + + return AE_OK; +} + +/** + * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter + * @adap: pointer to adapter + * + * Enumerate all I2C slave devices behind this adapter by walking the ACPI + * namespace. When a device is found it will be added to the Linux device + * model and bound to the corresponding ACPI handle. + */ +static void acpi_i2c_register_devices(struct i2c_adapter *adap) +{ + acpi_handle handle; + acpi_status status; + + handle = ACPI_HANDLE(adap->dev.parent); + if (!handle) + return; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, + acpi_i2c_add_device, NULL, + adap, NULL); + if (ACPI_FAILURE(status)) + dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); +} +#else +static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {} +#endif /* CONFIG_ACPI */ + static int i2c_do_add_adapter(struct i2c_driver *driver, struct i2c_adapter *adap) { @@ -1163,6 +1253,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) exit_recovery: /* create pre-declared device nodes */ of_i2c_register_devices(adap); + acpi_i2c_register_devices(adap); if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index ed53696..2ab11dc 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -564,10 +564,4 @@ static inline struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node } #endif /* CONFIG_OF */ -#if IS_ENABLED(CONFIG_ACPI_I2C) -extern void acpi_i2c_register_devices(struct i2c_adapter *adap); -#else -static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {} -#endif - #endif /* _LINUX_I2C_H */ -- cgit v0.10.2 From e66ff0a921eebd46b339c4548dc7f49592b91f99 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Wed, 21 Aug 2013 10:11:59 +0800 Subject: i2c: imx: use exact SoC revision to document binding use exact SoC revision instead of wildcard describing the compatible property requirement in the binding document. This will make the binding more clearer. Signed-off-by: Jingchang Lu Acked-by: Shawn Guo Signed-off-by: Wolfram Sang diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx.txt b/Documentation/devicetree/bindings/i2c/i2c-imx.txt index 3614242..4a8513e 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-imx.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-imx.txt @@ -1,7 +1,10 @@ * Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX Required properties: -- compatible : Should be "fsl,-i2c" +- compatible : + - "fsl,imx1-i2c" for I2C compatible with the one integrated on i.MX1 SoC + - "fsl,imx21-i2c" for I2C compatible with the one integrated on i.MX21 SoC + - "fsl,vf610-i2c" for I2C compatible with the one integrated on Vybrid vf610 SoC - reg : Should contain I2C/HS-I2C registers location and length - interrupts : Should contain I2C/HS-I2C interrupt -- cgit v0.10.2 From 7be60f2bfdd6c2c2c6273d2ff3ab6c81eec4a863 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 23 Aug 2013 20:10:04 +0200 Subject: i2c: mv64xxx: fix typo in binding documentation Reported-by: Mark Rutland Signed-off-by: Wolfram Sang diff --git a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt index 73cdc03..82e8f6f 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt @@ -5,7 +5,7 @@ Required properties : - reg : Offset and length of the register set for the device - compatible : Should be "marvell,mv64xxx-i2c" or "allwinner,sun4i-i2c" - or "marvell,mv7230-i2c" + or "marvell,mv78230-i2c" - interrupts : The interrupt number Optional properties : -- cgit v0.10.2 From 370257b287a3959f1d12398b51fb0c50063b4ca8 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 23 Aug 2013 11:23:50 +0200 Subject: i2c: ismt: add error return code in probe() Return error code in the error case, and not success. Acked-by: Neil Horman Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index cd82eb4..8ed79a0 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -879,6 +879,7 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id) DMA_BIT_MASK(32)) != 0)) { dev_err(&pdev->dev, "pci_set_dma_mask fail %p\n", pdev); + err = -ENODEV; goto fail; } } -- cgit v0.10.2 From 498c0146213aa5fbca3b63a6525e91c606c20c5e Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 23 Aug 2013 10:55:51 +0800 Subject: i2c: pnx: fix error return code in i2c_pnx_probe() Fix to return a negative error code in the irq get error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun [wsa: fixed wrong exit point, too] Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index d09577a..1a9ea25 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -726,7 +726,8 @@ static int i2c_pnx_probe(struct platform_device *pdev) alg_data->irq = platform_get_irq(pdev, 0); if (alg_data->irq < 0) { dev_err(&pdev->dev, "Failed to get IRQ from platform resource\n"); - goto out_irq; + ret = alg_data->irq; + goto out_clock; } ret = request_irq(alg_data->irq, i2c_pnx_interrupt, 0, pdev->name, alg_data); -- cgit v0.10.2 From b3bfce2bc205ff4fdb4ec0b048513557cef459cf Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Fri, 23 Aug 2013 18:01:44 +0200 Subject: i2c: mpc: cleanup clock API use make the MPC I2C driver get, prepare and enable the gated clock item for register access during probe; disable and unprepare the clock upon remove(), put is done by the devm approach; hold a reference to the clock over the period of use clock lookup is non-fatal in this implementation as not all platforms may provide clock specs in their device tree, but failure to enable a clock when specified is considered fatal Signed-off-by: Gerhard Sittig Signed-off-by: Anatolij Gustschin Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index f406093..b80c768 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -66,6 +67,7 @@ struct mpc_i2c { #ifdef CONFIG_PM_SLEEP u8 fdr, dfsrr; #endif + struct clk *clk_per; }; struct mpc_i2c_divider { @@ -622,6 +624,8 @@ static int fsl_i2c_probe(struct platform_device *op) int result = 0; int plen; struct resource res; + struct clk *clk; + int err; match = of_match_device(mpc_i2c_of_match, &op->dev); if (!match) @@ -652,6 +656,21 @@ static int fsl_i2c_probe(struct platform_device *op) } } + /* + * enable clock for the I2C peripheral (non fatal), + * keep a reference upon successful allocation + */ + clk = devm_clk_get(&op->dev, NULL); + if (!IS_ERR(clk)) { + err = clk_prepare_enable(clk); + if (err) { + dev_err(&op->dev, "failed to enable clock\n"); + goto fail_request; + } else { + i2c->clk_per = clk; + } + } + if (of_get_property(op->dev.of_node, "fsl,preserve-clocking", NULL)) { clock = MPC_I2C_CLOCK_PRESERVE; } else { @@ -697,6 +716,8 @@ static int fsl_i2c_probe(struct platform_device *op) return result; fail_add: + if (i2c->clk_per) + clk_disable_unprepare(i2c->clk_per); free_irq(i2c->irq, i2c); fail_request: irq_dispose_mapping(i2c->irq); @@ -712,6 +733,9 @@ static int fsl_i2c_remove(struct platform_device *op) i2c_del_adapter(&i2c->adap); + if (i2c->clk_per) + clk_disable_unprepare(i2c->clk_per); + if (i2c->irq) free_irq(i2c->irq, i2c); -- cgit v0.10.2 From defc0b2fb5221bca847a9adb8159b88bc3c93904 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 19 Aug 2013 15:07:53 +0300 Subject: i2c: designware: make HCNT/LCNT values configurable The DesignWare I2C controller has high count (HCNT) and low count (LCNT) registers for each of the I2C speed modes (standard and fast). These registers are programmed based on the input clock speed in the driver. The current code calculates these values based on the input clock speed and tries hard to meet the I2C bus timing requirements. This could result non-optimal values with regarding to the bus speed. For example on Intel BayTrail we get bus speed of 315.41kHz which is ~20% slower than we would expect (400kHz) in fast mode (even though the timing requirements are met). This patch makes it possible for the platform code to pass more optimal HCNT/LCNT values to the core driver if they are known beforehand. If these are not set we use the calculated and more conservative values. Signed-off-by: Mika Westerberg Acked-by: Shinya Kuribayashi Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index f325ec7..dbecf08 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -317,6 +317,12 @@ int i2c_dw_init(struct dw_i2c_dev *dev) 47, /* tLOW = 4.7 us */ 3, /* tf = 0.3 us */ 0); /* No offset */ + + /* Allow platforms to specify the ideal HCNT and LCNT values */ + if (dev->ss_hcnt && dev->ss_lcnt) { + hcnt = dev->ss_hcnt; + lcnt = dev->ss_lcnt; + } dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT); dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT); dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); @@ -331,6 +337,11 @@ int i2c_dw_init(struct dw_i2c_dev *dev) 13, /* tLOW = 1.3 us */ 3, /* tf = 0.3 us */ 0); /* No offset */ + + if (dev->fs_hcnt && dev->fs_lcnt) { + hcnt = dev->fs_hcnt; + lcnt = dev->fs_lcnt; + } dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT); dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT); dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 912aa22..e8a7565 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -61,6 +61,14 @@ * @tx_fifo_depth: depth of the hardware tx fifo * @rx_fifo_depth: depth of the hardware rx fifo * @rx_outstanding: current master-rx elements in tx fifo + * @ss_hcnt: standard speed HCNT value + * @ss_lcnt: standard speed LCNT value + * @fs_hcnt: fast speed HCNT value + * @fs_lcnt: fast speed LCNT value + * + * HCNT and LCNT parameters can be used if the platform knows more accurate + * values than the one computed based only on the input clock frequency. + * Leave them to be %0 if not used. */ struct dw_i2c_dev { struct device *dev; @@ -91,6 +99,10 @@ struct dw_i2c_dev { unsigned int rx_fifo_depth; int rx_outstanding; u32 sda_hold_time; + u16 ss_hcnt; + u16 ss_lcnt; + u16 fs_hcnt; + u16 fs_lcnt; }; #define ACCESS_SWAP 0x00000001 -- cgit v0.10.2 From 57cd1e3029e5fb4d238ad11fd0d7ad917179fdf2 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 19 Aug 2013 15:07:54 +0300 Subject: i2c: designware: get SDA hold time, HCNT and LCNT configuration from ACPI Some Intel LPSS I2C devices make the SDA hold time and *CNT parameters available via SSCN (standard mode) and FMCN (fast mode) ACPI methods. Implement support for this so that we check whether an ACPI method exists and if it does, fill in the SDA hold time and *CNT values to the device private structure for core to use. Signed-off-by: Mika Westerberg Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 6e99d9f..4c1b605 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -53,9 +53,33 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) } #ifdef CONFIG_ACPI +static void dw_i2c_acpi_params(struct platform_device *pdev, char method[], + u16 *hcnt, u16 *lcnt, u32 *sda_hold) +{ + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; + acpi_handle handle = ACPI_HANDLE(&pdev->dev); + union acpi_object *obj; + + if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf))) + return; + + obj = (union acpi_object *)buf.pointer; + if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 3) { + const union acpi_object *objs = obj->package.elements; + + *hcnt = (u16)objs[0].integer.value; + *lcnt = (u16)objs[1].integer.value; + if (sda_hold) + *sda_hold = (u32)objs[2].integer.value; + } + + kfree(buf.pointer); +} + static int dw_i2c_acpi_configure(struct platform_device *pdev) { struct dw_i2c_dev *dev = platform_get_drvdata(pdev); + bool fs_mode = dev->master_cfg & DW_IC_CON_SPEED_FAST; if (!ACPI_HANDLE(&pdev->dev)) return -ENODEV; @@ -63,6 +87,16 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev) dev->adapter.nr = -1; dev->tx_fifo_depth = 32; dev->rx_fifo_depth = 32; + + /* + * Try to get SDA hold time and *CNT values from an ACPI method if + * it exists for both supported speed modes. + */ + dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, + fs_mode ? NULL : &dev->sda_hold_time); + dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, + fs_mode ? &dev->sda_hold_time : NULL); + return 0; } -- cgit v0.10.2 From c984319ad9c54c269493b6bc0517e8c2dfca4456 Mon Sep 17 00:00:00 2001 From: Zhiwu Song Date: Tue, 13 Aug 2013 17:11:27 +0800 Subject: i2c: sirf: reset i2c controller early after we get a noack Due to hardware ANOMALY, we need to reset I2C earlier after we get NOACK while accessing non-existing clients, otherwise we will get errors even we access existing clients later Signed-off-by: Zhiwu Song Signed-off-by: Barry Song Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 0ff22e2..ff47a76 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -64,6 +64,8 @@ #define SIRFSOC_I2C_START BIT(7) #define SIRFSOC_I2C_DEFAULT_SPEED 100000 +#define SIRFSOC_I2C_ERR_NOACK 1 +#define SIRFSOC_I2C_ERR_TIMEOUT 2 struct sirfsoc_i2c { void __iomem *base; @@ -142,14 +144,24 @@ static irqreturn_t i2c_sirfsoc_irq(int irq, void *dev_id) if (i2c_stat & SIRFSOC_I2C_STAT_ERR) { /* Error conditions */ - siic->err_status = 1; + siic->err_status = SIRFSOC_I2C_ERR_NOACK; writel(SIRFSOC_I2C_STAT_ERR, siic->base + SIRFSOC_I2C_STATUS); if (i2c_stat & SIRFSOC_I2C_STAT_NACK) - dev_err(&siic->adapter.dev, "ACK not received\n"); + dev_dbg(&siic->adapter.dev, "ACK not received\n"); else dev_err(&siic->adapter.dev, "I2C error\n"); + /* + * Due to hardware ANOMALY, we need to reset I2C earlier after + * we get NOACK while accessing non-existing clients, otherwise + * we will get errors even we access existing clients later + */ + writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET, + siic->base + SIRFSOC_I2C_CTRL); + while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) + cpu_relax(); + complete(&siic->done); } else if (i2c_stat & SIRFSOC_I2C_STAT_CMD_DONE) { /* CMD buffer execution complete */ @@ -190,7 +202,6 @@ static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg) u32 regval = readl(siic->base + SIRFSOC_I2C_CTRL); /* timeout waiting for the xfer to finish or fail */ int timeout = msecs_to_jiffies((msg->len + 1) * 50); - int ret = 0; i2c_sirfsoc_set_address(siic, msg); @@ -199,7 +210,7 @@ static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg) i2c_sirfsoc_queue_cmd(siic); if (wait_for_completion_timeout(&siic->done, timeout) == 0) { - siic->err_status = 1; + siic->err_status = SIRFSOC_I2C_ERR_TIMEOUT; dev_err(&siic->adapter.dev, "Transfer timeout\n"); } @@ -207,16 +218,14 @@ static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg) siic->base + SIRFSOC_I2C_CTRL); writel(0, siic->base + SIRFSOC_I2C_CMD_START); - if (siic->err_status) { + /* i2c control doesn't response, reset it */ + if (siic->err_status == SIRFSOC_I2C_ERR_TIMEOUT) { writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) cpu_relax(); - - ret = -EIO; } - - return ret; + return siic->err_status ? -EIO : 0; } static u32 i2c_sirfsoc_func(struct i2c_adapter *adap) -- cgit v0.10.2 From ebae7dfab001890bc85d473275cc46611501664a Mon Sep 17 00:00:00 2001 From: Zhiwu Song Date: Tue, 13 Aug 2013 17:11:28 +0800 Subject: i2c: sirf: we need to wait I2C_RESET status in resume this fixes the issue that we lost to wait the i2c reset finished. Signed-off-by: Zhiwu Song Signed-off-by: Barry Song Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index ff47a76..efb51a1 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -422,6 +422,8 @@ static int i2c_sirfsoc_resume(struct device *dev) clk_enable(siic->clk); writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); + while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) + cpu_relax(); writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE, siic->base + SIRFSOC_I2C_CTRL); writel(siic->clk_div, siic->base + SIRFSOC_I2C_CLK_CTRL); -- cgit v0.10.2 From 4602bf1642dbf8b573fc6c224850114565652b4d Mon Sep 17 00:00:00 2001 From: Zhiwu Song Date: Tue, 13 Aug 2013 17:11:29 +0800 Subject: i2c: sirf: fix the typo for setting bitrate to less than 100k there is a typo before, it makes the final bitrate wrong, this patch fixes it. Signed-off-by: Zhiwu Song Signed-off-by: Barry Song Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index efb51a1..3b5fd38 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -356,7 +356,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) if (bitrate < 100000) regval = - (2 * ctrl_speed) / (2 * bitrate * 11); + (2 * ctrl_speed) / (bitrate * 11); else regval = ctrl_speed / (bitrate * 5); -- cgit v0.10.2 From 5ebffa6b5e0c43edbdd41e5bc53137547a1378cb Mon Sep 17 00:00:00 2001 From: Zhiwu Song Date: Tue, 13 Aug 2013 17:11:30 +0800 Subject: i2c: sirf: support reverse direction of address if users set I2C_M_REV_DIR_ADDR, revert the direction of address. Signed-off-by: Zhiwu Song Signed-off-by: Rongjun Ying Signed-off-by: Barry Song Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 3b5fd38..30ae378 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -194,6 +194,10 @@ static void i2c_sirfsoc_set_address(struct sirfsoc_i2c *siic, if (msg->flags & I2C_M_RD) addr |= 1; + /* Reverse direction bit */ + if (msg->flags & I2C_M_REV_DIR_ADDR) + addr ^= 1; + writel(addr, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); } -- cgit v0.10.2 From 617da00cb11b75a17a271147e616296f754f591b Mon Sep 17 00:00:00 2001 From: Zhiwu Song Date: Tue, 13 Aug 2013 17:11:31 +0800 Subject: i2c: sirf: retry 3 times as sometimes we get random noack and timeout let i2c core retry 3 times as sometimes we get random noack and timeout even when we access an existing i2c client. Signed-off-by: Zhiwu Song Signed-off-by: Barry Song Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 30ae378..6784f7f 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -229,7 +229,7 @@ static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg) while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) cpu_relax(); } - return siic->err_status ? -EIO : 0; + return siic->err_status ? -EAGAIN : 0; } static u32 i2c_sirfsoc_func(struct i2c_adapter *adap) @@ -333,6 +333,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) adap->algo = &i2c_sirfsoc_algo; adap->algo_data = siic; + adap->retries = 3; adap->dev.of_node = pdev->dev.of_node; adap->dev.parent = &pdev->dev; -- cgit v0.10.2 From b720423a2627f045133bec39a31fe2bc0dab86f3 Mon Sep 17 00:00:00 2001 From: Nguyen Viet Dung Date: Tue, 3 Sep 2013 09:09:25 +0900 Subject: i2c: rcar: add rcar-H2 support This patch modify I2C driver of rcar-H1 to usable on both rcar-H1 and rcar-H2. Signed-off-by: Nguyen Viet Dung Signed-off-by: Wolfram Sang diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index e59c3f6..d2fe11d 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -101,6 +101,11 @@ enum { #define ID_ARBLOST (1 << 3) #define ID_NACK (1 << 4) +enum rcar_i2c_type { + I2C_RCAR_H1, + I2C_RCAR_H2, +}; + struct rcar_i2c_priv { void __iomem *io; struct i2c_adapter adap; @@ -113,6 +118,7 @@ struct rcar_i2c_priv { int irq; u32 icccr; u32 flags; + enum rcar_i2c_type devtype; }; #define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent) @@ -224,12 +230,25 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, u32 scgd, cdf; u32 round, ick; u32 scl; + u32 cdf_width; if (!clkp) { dev_err(dev, "there is no peripheral_clk\n"); return -EIO; } + switch (priv->devtype) { + case I2C_RCAR_H1: + cdf_width = 2; + break; + case I2C_RCAR_H2: + cdf_width = 3; + break; + default: + dev_err(dev, "device type error\n"); + return -EIO; + } + /* * calculate SCL clock * see @@ -245,7 +264,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, * clkp : peripheral_clk * F[] : integer up-valuation */ - for (cdf = 0; cdf < 4; cdf++) { + for (cdf = 0; cdf < (1 << cdf_width); cdf++) { ick = clk_get_rate(clkp) / (1 + cdf); if (ick < 20000000) goto ick_find; @@ -287,7 +306,7 @@ scgd_find: /* * keep icccr value */ - priv->icccr = (scgd << 2 | cdf); + priv->icccr = (scgd << (cdf_width) | cdf); return 0; } @@ -632,6 +651,9 @@ static int rcar_i2c_probe(struct platform_device *pdev) bus_speed = 100000; /* default 100 kHz */ if (pdata && pdata->bus_speed) bus_speed = pdata->bus_speed; + + priv->devtype = platform_get_device_id(pdev)->driver_data; + ret = rcar_i2c_clock_calculate(priv, bus_speed, dev); if (ret < 0) return ret; @@ -686,6 +708,14 @@ static int rcar_i2c_remove(struct platform_device *pdev) return 0; } +static struct platform_device_id rcar_i2c_id_table[] = { + { "i2c-rcar", I2C_RCAR_H1 }, + { "i2c-rcar_h1", I2C_RCAR_H1 }, + { "i2c-rcar_h2", I2C_RCAR_H2 }, + {}, +}; +MODULE_DEVICE_TABLE(platform, rcar_i2c_id_table); + static struct platform_driver rcar_i2c_driver = { .driver = { .name = "i2c-rcar", @@ -693,6 +723,7 @@ static struct platform_driver rcar_i2c_driver = { }, .probe = rcar_i2c_probe, .remove = rcar_i2c_remove, + .id_table = rcar_i2c_id_table, }; module_platform_driver(rcar_i2c_driver); -- cgit v0.10.2