From f533c61e1921b93aa247d72d39c3fbe045340a9a Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Oct 2011 17:33:00 -0700 Subject: [PATCH 1/4] i2c-tegra: __iomem annotation fix drivers/i2c/busses/i2c-tegra.c:585:7: warning: incorrect type in assignment (different address spaces) drivers/i2c/busses/i2c-tegra.c:585:7: expected void *base drivers/i2c/busses/i2c-tegra.c:585:7: got void [noderef] * drivers/i2c/busses/i2c-tegra.c:619:16: warning: incorrect type in assignment (different address spaces) drivers/i2c/busses/i2c-tegra.c:619:16: expected void [noderef] *base drivers/i2c/busses/i2c-tegra.c:619:16: got void *base drivers/i2c/busses/i2c-tegra.c:689:10: warning: incorrect type in argument 1 (different address spaces) drivers/i2c/busses/i2c-tegra.c:689:10: expected void volatile [noderef] *addr drivers/i2c/busses/i2c-tegra.c:689:10: got void *base Signed-off-by: Olof Johansson Acked-by; Stephen Warren Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 3c94c4a81a55..b0505309faa7 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -566,7 +566,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) struct clk *clk; struct clk *i2c_clk; const unsigned int *prop; - void *base; + void __iomem *base; int irq; int ret = 0; From 8abf6fbbd22bc777fd4027cbc55e99cdfb7a8324 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Thu, 20 Oct 2011 18:23:01 +0200 Subject: [PATCH 2/4] i2c-nomadik: cosmetic coding style corrections This fixes a number of whitespace and punctuation problems around the Nomadik I2C driver. Signed-off-by: Jonas Aaberg Signed-off-by: Linus Walleij Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-nomadik.c | 89 +++++++++++++++++--------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index b228e09c5d05..ce4fd801a8c2 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -63,11 +63,11 @@ /* Master controller (MCR) register */ #define I2C_MCR_OP (0x1 << 0) /* Operation */ #define I2C_MCR_A7 (0x7f << 1) /* 7-bit address */ -#define I2C_MCR_EA10 (0x7 << 8) /* 10-bit Extended address */ +#define I2C_MCR_EA10 (0x7 << 8) /* 10-bit Extended address */ #define I2C_MCR_SB (0x1 << 11) /* Extended address */ #define I2C_MCR_AM (0x3 << 12) /* Address type */ -#define I2C_MCR_STOP (0x1 << 14) /* Stop condition */ -#define I2C_MCR_LENGTH (0x7ff << 15) /* Transaction length */ +#define I2C_MCR_STOP (0x1 << 14) /* Stop condition */ +#define I2C_MCR_LENGTH (0x7ff << 15) /* Transaction length */ /* Status register (SR) */ #define I2C_SR_OP (0x3 << 0) /* Operation */ @@ -77,7 +77,7 @@ #define I2C_SR_LENGTH (0x7ff << 9) /* Transfer length */ /* Interrupt mask set/clear (IMSCR) bits */ -#define I2C_IT_TXFE (0x1 << 0) +#define I2C_IT_TXFE (0x1 << 0) #define I2C_IT_TXFNE (0x1 << 1) #define I2C_IT_TXFF (0x1 << 2) #define I2C_IT_TXFOVR (0x1 << 3) @@ -135,31 +135,31 @@ struct i2c_nmk_client { }; /** - * struct nmk_i2c_dev - private data structure of the controller - * @pdev: parent platform device - * @adap: corresponding I2C adapter - * @irq: interrupt line for the controller - * @virtbase: virtual io memory area - * @clk: hardware i2c block clock - * @cfg: machine provided controller configuration - * @cli: holder of client specific data - * @stop: stop condition - * @xfer_complete: acknowledge completion for a I2C message - * @result: controller propogated result - * @regulator: pointer to i2c regulator - * @busy: Busy doing transfer + * struct nmk_i2c_dev - private data structure of the controller. + * @pdev: parent platform device. + * @adap: corresponding I2C adapter. + * @irq: interrupt line for the controller. + * @virtbase: virtual io memory area. + * @clk: hardware i2c block clock. + * @cfg: machine provided controller configuration. + * @cli: holder of client specific data. + * @stop: stop condition. + * @xfer_complete: acknowledge completion for a I2C message. + * @result: controller propogated result. + * @regulator: pointer to i2c regulator. + * @busy: Busy doing transfer. */ struct nmk_i2c_dev { struct platform_device *pdev; - struct i2c_adapter adap; - int irq; + struct i2c_adapter adap; + int irq; void __iomem *virtbase; struct clk *clk; struct nmk_i2c_controller cfg; struct i2c_nmk_client cli; - int stop; + int stop; struct completion xfer_complete; - int result; + int result; struct regulator *regulator; bool busy; }; @@ -217,8 +217,9 @@ static int flush_i2c_fifo(struct nmk_i2c_dev *dev) } } - dev_err(&dev->pdev->dev, "flushing operation timed out " - "giving up after %d attempts", LOOP_ATTEMPTS); + dev_err(&dev->pdev->dev, + "flushing operation timed out giving up after %d attempts", + LOOP_ATTEMPTS); return -ETIMEDOUT; } @@ -270,7 +271,7 @@ exit: } /* enable peripheral, master mode operation */ -#define DEFAULT_I2C_REG_CR ((1 << 1) | I2C_CR_PE) +#define DEFAULT_I2C_REG_CR ((1 << 1) | I2C_CR_PE) /** * load_i2c_mcr_reg() - load the MCR register @@ -363,8 +364,8 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) * and high speed (up to 3.4 Mb/s) */ if (dev->cfg.sm > I2C_FREQ_MODE_FAST) { - dev_err(&dev->pdev->dev, "do not support this mode " - "defaulting to std. mode\n"); + dev_err(&dev->pdev->dev, + "do not support this mode defaulting to std. mode\n"); brcr2 = i2c_clk/(100000 * 2) & 0xffff; writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR); writel(I2C_FREQ_MODE_STANDARD << 4, @@ -423,7 +424,7 @@ static int read_i2c(struct nmk_i2c_dev *dev) if (timeout < 0) { dev_err(&dev->pdev->dev, - "wait_for_completion_timeout" + "wait_for_completion_timeout " "returned %d waiting for event\n", timeout); status = timeout; } @@ -556,8 +557,8 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags) if (((i2c_sr >> 2) & 0x3) == 0x3) { /* get the abort cause */ cause = (i2c_sr >> 4) & 0x7; - dev_err(&dev->pdev->dev, "%s\n", cause - >= ARRAY_SIZE(abort_causes) ? + dev_err(&dev->pdev->dev, "%s\n", + cause >= ARRAY_SIZE(abort_causes) ? "unknown reason" : abort_causes[cause]); } @@ -582,13 +583,13 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags) * * NOTE: * READ TRANSFER : We impose a restriction of the first message to be the - * index message for any read transaction. - * - a no index is coded as '0', - * - 2byte big endian index is coded as '3' - * !!! msg[0].buf holds the actual index. - * This is compatible with generic messages of smbus emulator - * that send a one byte index. - * eg. a I2C transation to read 2 bytes from index 0 + * index message for any read transaction. + * - a no index is coded as '0', + * - 2byte big endian index is coded as '3' + * !!! msg[0].buf holds the actual index. + * This is compatible with generic messages of smbus emulator + * that send a one byte index. + * eg. a I2C transation to read 2 bytes from index 0 * idx = 0; * msg[0].addr = client->addr; * msg[0].flags = 0x0; @@ -644,8 +645,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, for (i = 0; i < num_msgs; i++) { if (unlikely(msgs[i].flags & I2C_M_TEN)) { - dev_err(&dev->pdev->dev, "10 bit addressing" - "not supported\n"); + dev_err(&dev->pdev->dev, + "10 bit addressing not supported\n"); status = -EINVAL; goto out; @@ -789,8 +790,9 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) if (dev->cli.count) { dev->result = -EIO; - dev_err(&dev->pdev->dev, "%lu bytes still remain to be" - "xfered\n", dev->cli.count); + dev_err(&dev->pdev->dev, + "%lu bytes still remain to be xfered\n", + dev->cli.count); (void) init_hw(dev); } complete(&dev->xfer_complete); @@ -923,7 +925,7 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) } if (request_mem_region(res->start, resource_size(res), - DRIVER_NAME "I/O region") == NULL) { + DRIVER_NAME "I/O region") == NULL) { ret = -EBUSY; goto err_no_region; } @@ -980,8 +982,9 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(adap, dev); - dev_info(&pdev->dev, "initialize %s on virtual " - "base %p\n", adap->name, dev->virtbase); + dev_info(&pdev->dev, + "initialize %s on virtual base %p\n", + adap->name, dev->virtbase); ret = i2c_add_numbered_adapter(adap); if (ret) { From 4fd81eb2d64295ab038a3ea9d44e0eac85a6648c Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Tue, 13 Sep 2011 09:46:04 +0530 Subject: [PATCH 3/4] i2c-s3c2410: Keep a copy of platform data and use it The platform data is copied into driver's private data and the copy is used for all access to the platform data. This simpifies the addition of device tree support for the i2c-s3c2410 driver. Cc: Ben Dooks Signed-off-by: Thomas Abraham Acked-by: Grant Likely Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-s3c2410.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index f84a63c6dd97..266dd83a3ec2 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -78,6 +78,7 @@ struct s3c24xx_i2c { struct resource *ioarea; struct i2c_adapter adap; + struct s3c2410_platform_i2c *pdata; #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; #endif @@ -625,7 +626,7 @@ static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted, static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) { - struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data; + struct s3c2410_platform_i2c *pdata = i2c->pdata; unsigned long clkin = clk_get_rate(i2c->clk); unsigned int divs, div1; unsigned long target_frequency; @@ -754,7 +755,7 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) /* get the plafrom data */ - pdata = i2c->dev->platform_data; + pdata = i2c->pdata; /* inititalise the gpio */ @@ -793,7 +794,7 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) static int s3c24xx_i2c_probe(struct platform_device *pdev) { struct s3c24xx_i2c *i2c; - struct s3c2410_platform_i2c *pdata; + struct s3c2410_platform_i2c *pdata = NULL; struct resource *res; int ret; @@ -809,6 +810,15 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) return -ENOMEM; } + i2c->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!i2c->pdata) { + ret = -ENOMEM; + goto err_noclk; + } + + if (pdata) + memcpy(i2c->pdata, pdata, sizeof(*pdata)); + strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name)); i2c->adap.owner = THIS_MODULE; i2c->adap.algo = &s3c24xx_i2c_algorithm; @@ -903,7 +913,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) * being bus 0. */ - i2c->adap.nr = pdata->bus_num; + i2c->adap.nr = i2c->pdata->bus_num; ret = i2c_add_numbered_adapter(&i2c->adap); if (ret < 0) { From 5a5f50802f5a31b9e15de8df40d5621af970a560 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Tue, 13 Sep 2011 09:46:05 +0530 Subject: [PATCH 4/4] i2c-s3c2410: Add device tree support Add device tree probe support for Samsung's s3c2410 i2c driver. Cc: Ben Dooks Signed-off-by: Thomas Abraham Acked-by: Grant Likely Signed-off-by: Ben Dooks --- .../devicetree/bindings/i2c/samsung-i2c.txt | 39 +++++++ drivers/i2c/busses/i2c-s3c2410.c | 110 +++++++++++++++++- 2 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/i2c/samsung-i2c.txt diff --git a/Documentation/devicetree/bindings/i2c/samsung-i2c.txt b/Documentation/devicetree/bindings/i2c/samsung-i2c.txt new file mode 100644 index 000000000000..38832c712919 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/samsung-i2c.txt @@ -0,0 +1,39 @@ +* Samsung's I2C controller + +The Samsung's I2C controller is used to interface with I2C devices. + +Required properties: + - compatible: value should be either of the following. + (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c. + (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c. + - reg: physical base address of the controller and length of memory mapped + region. + - interrupts: interrupt number to the cpu. + - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges. + - gpios: The order of the gpios should be the following: . + The gpio specifier depends on the gpio controller. + +Optional properties: + - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not + specified, default value is 0. + - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not + specified, the default value in Hz is 100000. + +Example: + + i2c@13870000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x13870000 0x100>; + interrupts = <345>; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <100000>; + gpios = <&gpd1 2 0 /* SDA */ + &gpd1 3 0 /* SCL */>; + #address-cells = <1>; + #size-cells = <0>; + + wm8994@1a { + compatible = "wlf,wm8994"; + reg = <0x1a>; + }; + }; diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 266dd83a3ec2..9c00ad1f50a2 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include @@ -79,6 +81,7 @@ struct s3c24xx_i2c { struct i2c_adapter adap; struct s3c2410_platform_i2c *pdata; + int gpios[2]; #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; #endif @@ -96,6 +99,12 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c) struct platform_device *pdev = to_platform_device(i2c->dev); enum s3c24xx_i2c_type type; +#ifdef CONFIG_OF + if (i2c->dev->of_node) + return of_device_is_compatible(i2c->dev->of_node, + "samsung,s3c2440-i2c"); +#endif + type = platform_get_device_id(pdev)->driver_data; return type == TYPE_S3C2440; } @@ -742,6 +751,49 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) } #endif +#ifdef CONFIG_OF +static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) +{ + int idx, gpio, ret; + + for (idx = 0; idx < 2; idx++) { + gpio = of_get_gpio(i2c->dev->of_node, idx); + if (!gpio_is_valid(gpio)) { + dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio); + goto free_gpio; + } + + ret = gpio_request(gpio, "i2c-bus"); + if (ret) { + dev_err(i2c->dev, "gpio [%d] request failed\n", gpio); + goto free_gpio; + } + } + return 0; + +free_gpio: + while (--idx >= 0) + gpio_free(i2c->gpios[idx]); + return -EINVAL; +} + +static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) +{ + unsigned int idx; + for (idx = 0; idx < 2; idx++) + gpio_free(i2c->gpios[idx]); +} +#else +static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) +{ + return -EINVAL; +} + +static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) +{ +} +#endif + /* s3c24xx_i2c_init * * initialise the controller, set the IO lines and frequency @@ -761,6 +813,9 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) if (pdata->cfg_gpio) pdata->cfg_gpio(to_platform_device(i2c->dev)); + else + if (s3c24xx_i2c_parse_dt_gpio(i2c)) + return -EINVAL; /* write slave address */ @@ -786,6 +841,34 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) return 0; } +#ifdef CONFIG_OF +/* s3c24xx_i2c_parse_dt + * + * Parse the device tree node and retreive the platform data. +*/ + +static void +s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) +{ + struct s3c2410_platform_i2c *pdata = i2c->pdata; + + if (!np) + return; + + pdata->bus_num = -1; /* i2c bus number is dynamically assigned */ + of_property_read_u32(np, "samsung,i2c-sda-delay", &pdata->sda_delay); + of_property_read_u32(np, "samsung,i2c-slave-addr", &pdata->slave_addr); + of_property_read_u32(np, "samsung,i2c-max-bus-freq", + (u32 *)&pdata->frequency); +} +#else +static void +s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) +{ + return; +} +#endif + /* s3c24xx_i2c_probe * * called by the bus driver when a suitable device is found @@ -798,10 +881,12 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) struct resource *res; int ret; - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "no platform data\n"); - return -EINVAL; + if (!pdev->dev.of_node) { + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "no platform data\n"); + return -EINVAL; + } } i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL); @@ -818,6 +903,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) if (pdata) memcpy(i2c->pdata, pdata, sizeof(*pdata)); + else + s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c); strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name)); i2c->adap.owner = THIS_MODULE; @@ -914,6 +1001,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) */ i2c->adap.nr = i2c->pdata->bus_num; + i2c->adap.dev.of_node = pdev->dev.of_node; ret = i2c_add_numbered_adapter(&i2c->adap); if (ret < 0) { @@ -921,6 +1009,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) goto err_cpufreq; } + of_i2c_register_devices(&i2c->adap); platform_set_drvdata(pdev, i2c); dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev)); @@ -969,6 +1058,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) iounmap(i2c->regs); release_resource(i2c->ioarea); + s3c24xx_i2c_dt_gpio_free(i2c); kfree(i2c->ioarea); kfree(i2c); @@ -1022,6 +1112,17 @@ static struct platform_device_id s3c24xx_driver_ids[] = { }; MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); +#ifdef CONFIG_OF +static const struct of_device_id s3c24xx_i2c_match[] = { + { .compatible = "samsung,s3c2410-i2c" }, + { .compatible = "samsung,s3c2440-i2c" }, + {}, +}; +MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); +#else +#define s3c24xx_i2c_match NULL +#endif + static struct platform_driver s3c24xx_i2c_driver = { .probe = s3c24xx_i2c_probe, .remove = s3c24xx_i2c_remove, @@ -1030,6 +1131,7 @@ static struct platform_driver s3c24xx_i2c_driver = { .owner = THIS_MODULE, .name = "s3c-i2c", .pm = S3C24XX_DEV_PM_OPS, + .of_match_table = s3c24xx_i2c_match, }, };