From: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
To: Roland Stigge <stigge-uj/7R2tJ6VmzQB+pC5nmwQ@public.gmane.org>,
Rob Herring <robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: vitalywool-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org,
ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org,
grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org,
rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org,
linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
arm-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
kevin.wells-3arQi8VN3Tc@public.gmane.org,
srinivas.bakki-3arQi8VN3Tc@public.gmane.org
Subject: Re: [PATCH v4] i2c: Add device tree support to i2c-pnx.c
Date: Thu, 19 Apr 2012 18:07:15 +0200 [thread overview]
Message-ID: <20120419160715.GD24987@pengutronix.de> (raw)
In-Reply-To: <1334850612-24151-1-git-send-email-stigge-uj/7R2tJ6VmzQB+pC5nmwQ@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 10522 bytes --]
On Thu, Apr 19, 2012 at 05:50:12PM +0200, Roland Stigge wrote:
> This patch adds device tree support to the pnx-i2c driver by using platform
> resources for memory region and irq and removing dependency on mach includes.
>
> The following platforms are affected:
>
> * PNX
> * LPC31xx (WIP)
> * LPC32xx
>
> The patch is based on a patch by Jon Smirl, working on lpc31xx integration
>
> Signed-off-by: Roland Stigge <stigge-uj/7R2tJ6VmzQB+pC5nmwQ@public.gmane.org>
> Reviewed-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
>
> ---
>
> Applies to v3.4-rc3 + already applied i2c-pnx.c patches from this series
>
> NOTE: I separated out this patch from the first patch series of the LPC32xx
> device tree conversion because most of those patches are already applied to
> -next. This is the last patch of this first series, a precondition for the
> LPC32xx device tree switch.
>
> Changes since v3:
> * Documentation/devicetree/bindings/i2c/pnx.txt:
> - Documented interrupt-parent as required
> - Documented slave-addr default in hex
>
> Documentation/devicetree/bindings/i2c/pnx.txt | 40 ++++++++++++++++
> drivers/i2c/busses/i2c-pnx.c | 65 +++++++++++++++++++-------
> include/linux/i2c-pnx.h | 1
> 3 files changed, 89 insertions(+), 17 deletions(-)
>
> --- /dev/null
> +++ linux-2.6/Documentation/devicetree/bindings/i2c/pnx.txt
> @@ -0,0 +1,40 @@
> +* NXP PNX I2C Controller
> +
> +Required properties:
> +
> + - reg: Offset and length of the register set for the device
> + - compatible: should be "nxp,pnx-i2c"
> + - interrupts: configure one interrupt line
> + - #address-cells: always 1 (for i2c addresses)
> + - #size-cells: always 0
> + - interrupt-parent: the phandle for the interrupt controller that
> + services interrupts for this device.
> +
> +Optional properties:
> +
> + - clock-frequency: desired I2C bus clock frequency in Hz, Default: 100000 Hz
> + - pnx,timeout: I2C bus timeout in milliseconds, Default: 10 ms
I'd like to repeat my question to the devicetree folks here: Can we have
timeout generic? It doesn't make sense to me to have that per vendor
again and again. I searched devicetree.org and EPAPR but couldn't find a
hint.
> + - slave-addr: Address used by the controller, Hardware default: 0x6e
> +
> +Examples:
> +
> + i2c1: i2c@400a0000 {
> + compatible = "nxp,pnx-i2c";
> + reg = <0x400a0000 0x100>;
> + interrupt-parent = <&mic>;
> + interrupts = <51 0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + };
> +
> + i2c2: i2c@400a8000 {
> + compatible = "nxp,pnx-i2c";
> + reg = <0x400a8000 0x100>;
> + interrupt-parent = <&mic>;
> + interrupts = <50 0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + clock-frequency = <0x186a0>;
> + pnx,timeout = <0x64>;
Did you change this, too? Timeouts are better readable in dec :)
> + slave-addr = <0x11>;
> + };
> --- linux-2.6.orig/drivers/i2c/busses/i2c-pnx.c
> +++ linux-2.6/drivers/i2c/busses/i2c-pnx.c
> @@ -23,10 +23,11 @@
> #include <linux/err.h>
> #include <linux/clk.h>
> #include <linux/slab.h>
> +#include <linux/of_i2c.h>
>
> -#define I2C_PNX_TIMEOUT 10 /* msec */
> -#define I2C_PNX_SPEED_KHZ 100
> -#define I2C_PNX_REGION_SIZE 0x100
> +#define I2C_PNX_TIMEOUT_DEFAULT 10 /* msec */
> +#define I2C_PNX_SPEED_KHZ_DEFAULT 100
> +#define I2C_PNX_REGION_SIZE 0x100
>
> enum {
> mstatus_tdi = 0x00000001,
> @@ -74,8 +75,9 @@ enum {
> #define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */
> #define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */
>
> -static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
> +static inline int wait_timeout(struct i2c_pnx_algo_data *data)
> {
> + long timeout = data->timeout;
> while (timeout > 0 &&
> (ioread32(I2C_REG_STS(data)) & mstatus_active)) {
> mdelay(1);
> @@ -84,8 +86,9 @@ static inline int wait_timeout(long time
> return (timeout <= 0);
> }
>
> -static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
> +static inline int wait_reset(struct i2c_pnx_algo_data *data)
> {
> + long timeout = data->timeout;
> while (timeout > 0 &&
> (ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
> mdelay(1);
> @@ -97,7 +100,7 @@ static inline int wait_reset(long timeou
> static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
> {
> struct timer_list *timer = &alg_data->mif.timer;
> - unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT);
> + unsigned long expires = msecs_to_jiffies(alg_data->timeout);
>
> if (expires <= 1)
> expires = 2;
> @@ -135,7 +138,7 @@ static int i2c_pnx_start(unsigned char s
> }
>
> /* First, make sure bus is idle */
> - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
> + if (wait_timeout(alg_data)) {
> /* Somebody else is monopolizing the bus */
> dev_err(&alg_data->adapter.dev,
> "%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
> @@ -228,7 +231,7 @@ static int i2c_pnx_master_xmit(struct i2
> if (alg_data->mif.len == 0) {
> if (alg_data->last) {
> /* Wait until the STOP is seen. */
> - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
> + if (wait_timeout(alg_data))
> dev_err(&alg_data->adapter.dev,
> "The bus is still active after timeout\n");
> }
> @@ -326,7 +329,7 @@ static int i2c_pnx_master_rcv(struct i2c
> if (alg_data->mif.len == 0) {
> if (alg_data->last)
> /* Wait until the STOP is seen. */
> - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
> + if (wait_timeout(alg_data))
> dev_err(&alg_data->adapter.dev,
> "The bus is still active after timeout\n");
>
> @@ -442,7 +445,7 @@ static void i2c_pnx_timeout(unsigned lon
>
> ctl |= mcntrl_reset;
> iowrite32(ctl, I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> alg_data->mif.ret = -EIO;
> complete(&alg_data->mif.complete);
> }
> @@ -457,18 +460,18 @@ static inline void bus_reset_if_active(s
> alg_data->adapter.name);
> iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
> I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> } else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
> /* If there is data in the fifo's after transfer,
> * flush fifo's by reset.
> */
> iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
> I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> } else if (stat & mstatus_nai) {
> iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
> I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> }
> }
>
> @@ -612,6 +615,8 @@ static int __devinit i2c_pnx_probe(struc
> struct i2c_pnx_algo_data *alg_data;
> unsigned long freq;
> struct resource *res;
> + u32 speed = I2C_PNX_SPEED_KHZ_DEFAULT * 1000;
> + u32 slave_addr = ~0;
>
> alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL);
> if (!alg_data) {
> @@ -626,6 +631,18 @@ static int __devinit i2c_pnx_probe(struc
> alg_data->adapter.algo_data = alg_data;
> alg_data->adapter.nr = pdev->id;
>
> + alg_data->timeout = I2C_PNX_TIMEOUT_DEFAULT;
> +#ifdef CONFIG_OF
> + alg_data->adapter.dev.of_node = of_node_get(pdev->dev.of_node);
> + if (pdev->dev.of_node) {
> + of_property_read_u32(pdev->dev.of_node, "pnx,timeout",
> + &alg_data->timeout);
> + of_property_read_u32(pdev->dev.of_node, "clock-frequency",
> + &speed);
> + of_property_read_u32(pdev->dev.of_node, "slave-addr",
> + &slave_addr);
> + }
> +#endif
> alg_data->clk = clk_get(&pdev->dev, NULL);
> if (IS_ERR(alg_data->clk)) {
> ret = PTR_ERR(alg_data->clk);
> @@ -651,7 +668,7 @@ static int __devinit i2c_pnx_probe(struc
> dev_err(&pdev->dev,
> "I/O region 0x%08x for I2C already in use.\n",
> res->start);
> - ret = -ENODEV;
> + ret = -ENOMEM;
> goto out_clkget;
> }
>
> @@ -667,6 +684,9 @@ static int __devinit i2c_pnx_probe(struc
> if (ret)
> goto out_unmap;
>
> + if (slave_addr != ~0)
> + iowrite32(slave_addr, I2C_REG_ADR(alg_data));
> +
> freq = clk_get_rate(alg_data->clk);
>
> /*
> @@ -680,14 +700,14 @@ static int __devinit i2c_pnx_probe(struc
> * the deglitching filter length.
> */
>
> - tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
> + tmp = (freq / speed) / 2 - 2;
> if (tmp > 0x3FF)
> tmp = 0x3FF;
> iowrite32(tmp, I2C_REG_CKH(alg_data));
> iowrite32(tmp, I2C_REG_CKL(alg_data));
>
> iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
> - if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
> + if (wait_reset(alg_data)) {
> ret = -ENODEV;
> goto out_clock;
> }
> @@ -699,7 +719,7 @@ static int __devinit i2c_pnx_probe(struc
> goto out_irq;
> }
> ret = request_irq(alg_data->irq, i2c_pnx_interrupt,
> - 0, pdev->name, alg_data);
> + 0, pdev->name, alg_data);
> if (ret)
> goto out_clock;
>
> @@ -710,6 +730,8 @@ static int __devinit i2c_pnx_probe(struc
> 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);
>
> @@ -748,10 +770,19 @@ static int __devexit i2c_pnx_remove(stru
> return 0;
> }
>
> +#ifdef CONFIG_OF
> +static const struct of_device_id i2c_pnx_of_match[] = {
> + { .compatible = "nxp,pnx-i2c" },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, i2c_pnx_of_match);
> +#endif
> +
> static struct platform_driver i2c_pnx_driver = {
> .driver = {
> .name = "pnx-i2c",
> .owner = THIS_MODULE,
> + .of_match_table = of_match_ptr(i2c_pnx_of_match),
> },
> .probe = i2c_pnx_probe,
> .remove = __devexit_p(i2c_pnx_remove),
> --- linux-2.6.orig/include/linux/i2c-pnx.h
> +++ linux-2.6/include/linux/i2c-pnx.h
> @@ -32,6 +32,7 @@ struct i2c_pnx_algo_data {
> struct i2c_adapter adapter;
> phys_addr_t base;
> int irq;
> + u32 timeout;
> };
>
> #endif /* __I2C_PNX_H__ */
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
WARNING: multiple messages have this Message-ID (diff)
From: w.sang@pengutronix.de (Wolfram Sang)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v4] i2c: Add device tree support to i2c-pnx.c
Date: Thu, 19 Apr 2012 18:07:15 +0200 [thread overview]
Message-ID: <20120419160715.GD24987@pengutronix.de> (raw)
In-Reply-To: <1334850612-24151-1-git-send-email-stigge@antcom.de>
On Thu, Apr 19, 2012 at 05:50:12PM +0200, Roland Stigge wrote:
> This patch adds device tree support to the pnx-i2c driver by using platform
> resources for memory region and irq and removing dependency on mach includes.
>
> The following platforms are affected:
>
> * PNX
> * LPC31xx (WIP)
> * LPC32xx
>
> The patch is based on a patch by Jon Smirl, working on lpc31xx integration
>
> Signed-off-by: Roland Stigge <stigge@antcom.de>
> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
>
> ---
>
> Applies to v3.4-rc3 + already applied i2c-pnx.c patches from this series
>
> NOTE: I separated out this patch from the first patch series of the LPC32xx
> device tree conversion because most of those patches are already applied to
> -next. This is the last patch of this first series, a precondition for the
> LPC32xx device tree switch.
>
> Changes since v3:
> * Documentation/devicetree/bindings/i2c/pnx.txt:
> - Documented interrupt-parent as required
> - Documented slave-addr default in hex
>
> Documentation/devicetree/bindings/i2c/pnx.txt | 40 ++++++++++++++++
> drivers/i2c/busses/i2c-pnx.c | 65 +++++++++++++++++++-------
> include/linux/i2c-pnx.h | 1
> 3 files changed, 89 insertions(+), 17 deletions(-)
>
> --- /dev/null
> +++ linux-2.6/Documentation/devicetree/bindings/i2c/pnx.txt
> @@ -0,0 +1,40 @@
> +* NXP PNX I2C Controller
> +
> +Required properties:
> +
> + - reg: Offset and length of the register set for the device
> + - compatible: should be "nxp,pnx-i2c"
> + - interrupts: configure one interrupt line
> + - #address-cells: always 1 (for i2c addresses)
> + - #size-cells: always 0
> + - interrupt-parent: the phandle for the interrupt controller that
> + services interrupts for this device.
> +
> +Optional properties:
> +
> + - clock-frequency: desired I2C bus clock frequency in Hz, Default: 100000 Hz
> + - pnx,timeout: I2C bus timeout in milliseconds, Default: 10 ms
I'd like to repeat my question to the devicetree folks here: Can we have
timeout generic? It doesn't make sense to me to have that per vendor
again and again. I searched devicetree.org and EPAPR but couldn't find a
hint.
> + - slave-addr: Address used by the controller, Hardware default: 0x6e
> +
> +Examples:
> +
> + i2c1: i2c at 400a0000 {
> + compatible = "nxp,pnx-i2c";
> + reg = <0x400a0000 0x100>;
> + interrupt-parent = <&mic>;
> + interrupts = <51 0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + };
> +
> + i2c2: i2c at 400a8000 {
> + compatible = "nxp,pnx-i2c";
> + reg = <0x400a8000 0x100>;
> + interrupt-parent = <&mic>;
> + interrupts = <50 0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + clock-frequency = <0x186a0>;
> + pnx,timeout = <0x64>;
Did you change this, too? Timeouts are better readable in dec :)
> + slave-addr = <0x11>;
> + };
> --- linux-2.6.orig/drivers/i2c/busses/i2c-pnx.c
> +++ linux-2.6/drivers/i2c/busses/i2c-pnx.c
> @@ -23,10 +23,11 @@
> #include <linux/err.h>
> #include <linux/clk.h>
> #include <linux/slab.h>
> +#include <linux/of_i2c.h>
>
> -#define I2C_PNX_TIMEOUT 10 /* msec */
> -#define I2C_PNX_SPEED_KHZ 100
> -#define I2C_PNX_REGION_SIZE 0x100
> +#define I2C_PNX_TIMEOUT_DEFAULT 10 /* msec */
> +#define I2C_PNX_SPEED_KHZ_DEFAULT 100
> +#define I2C_PNX_REGION_SIZE 0x100
>
> enum {
> mstatus_tdi = 0x00000001,
> @@ -74,8 +75,9 @@ enum {
> #define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */
> #define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */
>
> -static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
> +static inline int wait_timeout(struct i2c_pnx_algo_data *data)
> {
> + long timeout = data->timeout;
> while (timeout > 0 &&
> (ioread32(I2C_REG_STS(data)) & mstatus_active)) {
> mdelay(1);
> @@ -84,8 +86,9 @@ static inline int wait_timeout(long time
> return (timeout <= 0);
> }
>
> -static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
> +static inline int wait_reset(struct i2c_pnx_algo_data *data)
> {
> + long timeout = data->timeout;
> while (timeout > 0 &&
> (ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
> mdelay(1);
> @@ -97,7 +100,7 @@ static inline int wait_reset(long timeou
> static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
> {
> struct timer_list *timer = &alg_data->mif.timer;
> - unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT);
> + unsigned long expires = msecs_to_jiffies(alg_data->timeout);
>
> if (expires <= 1)
> expires = 2;
> @@ -135,7 +138,7 @@ static int i2c_pnx_start(unsigned char s
> }
>
> /* First, make sure bus is idle */
> - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
> + if (wait_timeout(alg_data)) {
> /* Somebody else is monopolizing the bus */
> dev_err(&alg_data->adapter.dev,
> "%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
> @@ -228,7 +231,7 @@ static int i2c_pnx_master_xmit(struct i2
> if (alg_data->mif.len == 0) {
> if (alg_data->last) {
> /* Wait until the STOP is seen. */
> - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
> + if (wait_timeout(alg_data))
> dev_err(&alg_data->adapter.dev,
> "The bus is still active after timeout\n");
> }
> @@ -326,7 +329,7 @@ static int i2c_pnx_master_rcv(struct i2c
> if (alg_data->mif.len == 0) {
> if (alg_data->last)
> /* Wait until the STOP is seen. */
> - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
> + if (wait_timeout(alg_data))
> dev_err(&alg_data->adapter.dev,
> "The bus is still active after timeout\n");
>
> @@ -442,7 +445,7 @@ static void i2c_pnx_timeout(unsigned lon
>
> ctl |= mcntrl_reset;
> iowrite32(ctl, I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> alg_data->mif.ret = -EIO;
> complete(&alg_data->mif.complete);
> }
> @@ -457,18 +460,18 @@ static inline void bus_reset_if_active(s
> alg_data->adapter.name);
> iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
> I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> } else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
> /* If there is data in the fifo's after transfer,
> * flush fifo's by reset.
> */
> iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
> I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> } else if (stat & mstatus_nai) {
> iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
> I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> }
> }
>
> @@ -612,6 +615,8 @@ static int __devinit i2c_pnx_probe(struc
> struct i2c_pnx_algo_data *alg_data;
> unsigned long freq;
> struct resource *res;
> + u32 speed = I2C_PNX_SPEED_KHZ_DEFAULT * 1000;
> + u32 slave_addr = ~0;
>
> alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL);
> if (!alg_data) {
> @@ -626,6 +631,18 @@ static int __devinit i2c_pnx_probe(struc
> alg_data->adapter.algo_data = alg_data;
> alg_data->adapter.nr = pdev->id;
>
> + alg_data->timeout = I2C_PNX_TIMEOUT_DEFAULT;
> +#ifdef CONFIG_OF
> + alg_data->adapter.dev.of_node = of_node_get(pdev->dev.of_node);
> + if (pdev->dev.of_node) {
> + of_property_read_u32(pdev->dev.of_node, "pnx,timeout",
> + &alg_data->timeout);
> + of_property_read_u32(pdev->dev.of_node, "clock-frequency",
> + &speed);
> + of_property_read_u32(pdev->dev.of_node, "slave-addr",
> + &slave_addr);
> + }
> +#endif
> alg_data->clk = clk_get(&pdev->dev, NULL);
> if (IS_ERR(alg_data->clk)) {
> ret = PTR_ERR(alg_data->clk);
> @@ -651,7 +668,7 @@ static int __devinit i2c_pnx_probe(struc
> dev_err(&pdev->dev,
> "I/O region 0x%08x for I2C already in use.\n",
> res->start);
> - ret = -ENODEV;
> + ret = -ENOMEM;
> goto out_clkget;
> }
>
> @@ -667,6 +684,9 @@ static int __devinit i2c_pnx_probe(struc
> if (ret)
> goto out_unmap;
>
> + if (slave_addr != ~0)
> + iowrite32(slave_addr, I2C_REG_ADR(alg_data));
> +
> freq = clk_get_rate(alg_data->clk);
>
> /*
> @@ -680,14 +700,14 @@ static int __devinit i2c_pnx_probe(struc
> * the deglitching filter length.
> */
>
> - tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
> + tmp = (freq / speed) / 2 - 2;
> if (tmp > 0x3FF)
> tmp = 0x3FF;
> iowrite32(tmp, I2C_REG_CKH(alg_data));
> iowrite32(tmp, I2C_REG_CKL(alg_data));
>
> iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
> - if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
> + if (wait_reset(alg_data)) {
> ret = -ENODEV;
> goto out_clock;
> }
> @@ -699,7 +719,7 @@ static int __devinit i2c_pnx_probe(struc
> goto out_irq;
> }
> ret = request_irq(alg_data->irq, i2c_pnx_interrupt,
> - 0, pdev->name, alg_data);
> + 0, pdev->name, alg_data);
> if (ret)
> goto out_clock;
>
> @@ -710,6 +730,8 @@ static int __devinit i2c_pnx_probe(struc
> 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);
>
> @@ -748,10 +770,19 @@ static int __devexit i2c_pnx_remove(stru
> return 0;
> }
>
> +#ifdef CONFIG_OF
> +static const struct of_device_id i2c_pnx_of_match[] = {
> + { .compatible = "nxp,pnx-i2c" },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, i2c_pnx_of_match);
> +#endif
> +
> static struct platform_driver i2c_pnx_driver = {
> .driver = {
> .name = "pnx-i2c",
> .owner = THIS_MODULE,
> + .of_match_table = of_match_ptr(i2c_pnx_of_match),
> },
> .probe = i2c_pnx_probe,
> .remove = __devexit_p(i2c_pnx_remove),
> --- linux-2.6.orig/include/linux/i2c-pnx.h
> +++ linux-2.6/include/linux/i2c-pnx.h
> @@ -32,6 +32,7 @@ struct i2c_pnx_algo_data {
> struct i2c_adapter adapter;
> phys_addr_t base;
> int irq;
> + u32 timeout;
> };
>
> #endif /* __I2C_PNX_H__ */
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120419/3888eeab/attachment.sig>
WARNING: multiple messages have this Message-ID (diff)
From: Wolfram Sang <w.sang@pengutronix.de>
To: Roland Stigge <stigge@antcom.de>,
Grant Likely <grant.likely@secretlab.ca>,
Rob Herring <robherring2@gmail.com>
Cc: vitalywool@gmail.com, khali@linux-fr.org, ben-linux@fluff.org,
grant.likely@secretlab.ca, rob.herring@calxeda.com,
linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree-discuss@lists.ozlabs.org, arm@kernel.org,
linux-arm-kernel@lists.infradead.org, kevin.wells@nxp.com,
srinivas.bakki@nxp.com
Subject: Re: [PATCH v4] i2c: Add device tree support to i2c-pnx.c
Date: Thu, 19 Apr 2012 18:07:15 +0200 [thread overview]
Message-ID: <20120419160715.GD24987@pengutronix.de> (raw)
In-Reply-To: <1334850612-24151-1-git-send-email-stigge@antcom.de>
[-- Attachment #1: Type: text/plain, Size: 10472 bytes --]
On Thu, Apr 19, 2012 at 05:50:12PM +0200, Roland Stigge wrote:
> This patch adds device tree support to the pnx-i2c driver by using platform
> resources for memory region and irq and removing dependency on mach includes.
>
> The following platforms are affected:
>
> * PNX
> * LPC31xx (WIP)
> * LPC32xx
>
> The patch is based on a patch by Jon Smirl, working on lpc31xx integration
>
> Signed-off-by: Roland Stigge <stigge@antcom.de>
> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
>
> ---
>
> Applies to v3.4-rc3 + already applied i2c-pnx.c patches from this series
>
> NOTE: I separated out this patch from the first patch series of the LPC32xx
> device tree conversion because most of those patches are already applied to
> -next. This is the last patch of this first series, a precondition for the
> LPC32xx device tree switch.
>
> Changes since v3:
> * Documentation/devicetree/bindings/i2c/pnx.txt:
> - Documented interrupt-parent as required
> - Documented slave-addr default in hex
>
> Documentation/devicetree/bindings/i2c/pnx.txt | 40 ++++++++++++++++
> drivers/i2c/busses/i2c-pnx.c | 65 +++++++++++++++++++-------
> include/linux/i2c-pnx.h | 1
> 3 files changed, 89 insertions(+), 17 deletions(-)
>
> --- /dev/null
> +++ linux-2.6/Documentation/devicetree/bindings/i2c/pnx.txt
> @@ -0,0 +1,40 @@
> +* NXP PNX I2C Controller
> +
> +Required properties:
> +
> + - reg: Offset and length of the register set for the device
> + - compatible: should be "nxp,pnx-i2c"
> + - interrupts: configure one interrupt line
> + - #address-cells: always 1 (for i2c addresses)
> + - #size-cells: always 0
> + - interrupt-parent: the phandle for the interrupt controller that
> + services interrupts for this device.
> +
> +Optional properties:
> +
> + - clock-frequency: desired I2C bus clock frequency in Hz, Default: 100000 Hz
> + - pnx,timeout: I2C bus timeout in milliseconds, Default: 10 ms
I'd like to repeat my question to the devicetree folks here: Can we have
timeout generic? It doesn't make sense to me to have that per vendor
again and again. I searched devicetree.org and EPAPR but couldn't find a
hint.
> + - slave-addr: Address used by the controller, Hardware default: 0x6e
> +
> +Examples:
> +
> + i2c1: i2c@400a0000 {
> + compatible = "nxp,pnx-i2c";
> + reg = <0x400a0000 0x100>;
> + interrupt-parent = <&mic>;
> + interrupts = <51 0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + };
> +
> + i2c2: i2c@400a8000 {
> + compatible = "nxp,pnx-i2c";
> + reg = <0x400a8000 0x100>;
> + interrupt-parent = <&mic>;
> + interrupts = <50 0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + clock-frequency = <0x186a0>;
> + pnx,timeout = <0x64>;
Did you change this, too? Timeouts are better readable in dec :)
> + slave-addr = <0x11>;
> + };
> --- linux-2.6.orig/drivers/i2c/busses/i2c-pnx.c
> +++ linux-2.6/drivers/i2c/busses/i2c-pnx.c
> @@ -23,10 +23,11 @@
> #include <linux/err.h>
> #include <linux/clk.h>
> #include <linux/slab.h>
> +#include <linux/of_i2c.h>
>
> -#define I2C_PNX_TIMEOUT 10 /* msec */
> -#define I2C_PNX_SPEED_KHZ 100
> -#define I2C_PNX_REGION_SIZE 0x100
> +#define I2C_PNX_TIMEOUT_DEFAULT 10 /* msec */
> +#define I2C_PNX_SPEED_KHZ_DEFAULT 100
> +#define I2C_PNX_REGION_SIZE 0x100
>
> enum {
> mstatus_tdi = 0x00000001,
> @@ -74,8 +75,9 @@ enum {
> #define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */
> #define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */
>
> -static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
> +static inline int wait_timeout(struct i2c_pnx_algo_data *data)
> {
> + long timeout = data->timeout;
> while (timeout > 0 &&
> (ioread32(I2C_REG_STS(data)) & mstatus_active)) {
> mdelay(1);
> @@ -84,8 +86,9 @@ static inline int wait_timeout(long time
> return (timeout <= 0);
> }
>
> -static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
> +static inline int wait_reset(struct i2c_pnx_algo_data *data)
> {
> + long timeout = data->timeout;
> while (timeout > 0 &&
> (ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
> mdelay(1);
> @@ -97,7 +100,7 @@ static inline int wait_reset(long timeou
> static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
> {
> struct timer_list *timer = &alg_data->mif.timer;
> - unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT);
> + unsigned long expires = msecs_to_jiffies(alg_data->timeout);
>
> if (expires <= 1)
> expires = 2;
> @@ -135,7 +138,7 @@ static int i2c_pnx_start(unsigned char s
> }
>
> /* First, make sure bus is idle */
> - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
> + if (wait_timeout(alg_data)) {
> /* Somebody else is monopolizing the bus */
> dev_err(&alg_data->adapter.dev,
> "%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
> @@ -228,7 +231,7 @@ static int i2c_pnx_master_xmit(struct i2
> if (alg_data->mif.len == 0) {
> if (alg_data->last) {
> /* Wait until the STOP is seen. */
> - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
> + if (wait_timeout(alg_data))
> dev_err(&alg_data->adapter.dev,
> "The bus is still active after timeout\n");
> }
> @@ -326,7 +329,7 @@ static int i2c_pnx_master_rcv(struct i2c
> if (alg_data->mif.len == 0) {
> if (alg_data->last)
> /* Wait until the STOP is seen. */
> - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
> + if (wait_timeout(alg_data))
> dev_err(&alg_data->adapter.dev,
> "The bus is still active after timeout\n");
>
> @@ -442,7 +445,7 @@ static void i2c_pnx_timeout(unsigned lon
>
> ctl |= mcntrl_reset;
> iowrite32(ctl, I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> alg_data->mif.ret = -EIO;
> complete(&alg_data->mif.complete);
> }
> @@ -457,18 +460,18 @@ static inline void bus_reset_if_active(s
> alg_data->adapter.name);
> iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
> I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> } else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
> /* If there is data in the fifo's after transfer,
> * flush fifo's by reset.
> */
> iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
> I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> } else if (stat & mstatus_nai) {
> iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
> I2C_REG_CTL(alg_data));
> - wait_reset(I2C_PNX_TIMEOUT, alg_data);
> + wait_reset(alg_data);
> }
> }
>
> @@ -612,6 +615,8 @@ static int __devinit i2c_pnx_probe(struc
> struct i2c_pnx_algo_data *alg_data;
> unsigned long freq;
> struct resource *res;
> + u32 speed = I2C_PNX_SPEED_KHZ_DEFAULT * 1000;
> + u32 slave_addr = ~0;
>
> alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL);
> if (!alg_data) {
> @@ -626,6 +631,18 @@ static int __devinit i2c_pnx_probe(struc
> alg_data->adapter.algo_data = alg_data;
> alg_data->adapter.nr = pdev->id;
>
> + alg_data->timeout = I2C_PNX_TIMEOUT_DEFAULT;
> +#ifdef CONFIG_OF
> + alg_data->adapter.dev.of_node = of_node_get(pdev->dev.of_node);
> + if (pdev->dev.of_node) {
> + of_property_read_u32(pdev->dev.of_node, "pnx,timeout",
> + &alg_data->timeout);
> + of_property_read_u32(pdev->dev.of_node, "clock-frequency",
> + &speed);
> + of_property_read_u32(pdev->dev.of_node, "slave-addr",
> + &slave_addr);
> + }
> +#endif
> alg_data->clk = clk_get(&pdev->dev, NULL);
> if (IS_ERR(alg_data->clk)) {
> ret = PTR_ERR(alg_data->clk);
> @@ -651,7 +668,7 @@ static int __devinit i2c_pnx_probe(struc
> dev_err(&pdev->dev,
> "I/O region 0x%08x for I2C already in use.\n",
> res->start);
> - ret = -ENODEV;
> + ret = -ENOMEM;
> goto out_clkget;
> }
>
> @@ -667,6 +684,9 @@ static int __devinit i2c_pnx_probe(struc
> if (ret)
> goto out_unmap;
>
> + if (slave_addr != ~0)
> + iowrite32(slave_addr, I2C_REG_ADR(alg_data));
> +
> freq = clk_get_rate(alg_data->clk);
>
> /*
> @@ -680,14 +700,14 @@ static int __devinit i2c_pnx_probe(struc
> * the deglitching filter length.
> */
>
> - tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
> + tmp = (freq / speed) / 2 - 2;
> if (tmp > 0x3FF)
> tmp = 0x3FF;
> iowrite32(tmp, I2C_REG_CKH(alg_data));
> iowrite32(tmp, I2C_REG_CKL(alg_data));
>
> iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
> - if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
> + if (wait_reset(alg_data)) {
> ret = -ENODEV;
> goto out_clock;
> }
> @@ -699,7 +719,7 @@ static int __devinit i2c_pnx_probe(struc
> goto out_irq;
> }
> ret = request_irq(alg_data->irq, i2c_pnx_interrupt,
> - 0, pdev->name, alg_data);
> + 0, pdev->name, alg_data);
> if (ret)
> goto out_clock;
>
> @@ -710,6 +730,8 @@ static int __devinit i2c_pnx_probe(struc
> 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);
>
> @@ -748,10 +770,19 @@ static int __devexit i2c_pnx_remove(stru
> return 0;
> }
>
> +#ifdef CONFIG_OF
> +static const struct of_device_id i2c_pnx_of_match[] = {
> + { .compatible = "nxp,pnx-i2c" },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, i2c_pnx_of_match);
> +#endif
> +
> static struct platform_driver i2c_pnx_driver = {
> .driver = {
> .name = "pnx-i2c",
> .owner = THIS_MODULE,
> + .of_match_table = of_match_ptr(i2c_pnx_of_match),
> },
> .probe = i2c_pnx_probe,
> .remove = __devexit_p(i2c_pnx_remove),
> --- linux-2.6.orig/include/linux/i2c-pnx.h
> +++ linux-2.6/include/linux/i2c-pnx.h
> @@ -32,6 +32,7 @@ struct i2c_pnx_algo_data {
> struct i2c_adapter adapter;
> phys_addr_t base;
> int irq;
> + u32 timeout;
> };
>
> #endif /* __I2C_PNX_H__ */
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
next prev parent reply other threads:[~2012-04-19 16:07 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-04-19 15:50 [PATCH v4] i2c: Add device tree support to i2c-pnx.c Roland Stigge
2012-04-19 15:50 ` Roland Stigge
[not found] ` <1334850612-24151-1-git-send-email-stigge-uj/7R2tJ6VmzQB+pC5nmwQ@public.gmane.org>
2012-04-19 16:07 ` Wolfram Sang [this message]
2012-04-19 16:07 ` Wolfram Sang
2012-04-19 16:07 ` Wolfram Sang
[not found] ` <20120419160715.GD24987-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2012-04-19 16:32 ` Roland Stigge
2012-04-19 16:32 ` Roland Stigge
2012-04-19 16:32 ` Roland Stigge
[not found] ` <4F903E0C.6010604-uj/7R2tJ6VmzQB+pC5nmwQ@public.gmane.org>
2012-04-19 20:39 ` Wolfram Sang
2012-04-19 20:39 ` Wolfram Sang
2012-04-19 20:39 ` Wolfram Sang
2012-04-19 21:18 ` Roland Stigge
2012-04-19 21:18 ` Roland Stigge
2012-04-19 21:18 ` Roland Stigge
[not found] ` <4F90812F.5090106-uj/7R2tJ6VmzQB+pC5nmwQ@public.gmane.org>
2012-04-20 7:28 ` Wolfram Sang
2012-04-20 7:28 ` Wolfram Sang
2012-04-20 7:28 ` Wolfram Sang
[not found] ` <20120420072811.GA9769-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2012-04-20 7:53 ` Roland Stigge
2012-04-20 7:53 ` Roland Stigge
2012-04-20 7:53 ` Roland Stigge
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120419160715.GD24987@pengutronix.de \
--to=w.sang-bicnvbalz9megne8c9+irq@public.gmane.org \
--cc=arm-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org \
--cc=devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org \
--cc=grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org \
--cc=kevin.wells-3arQi8VN3Tc@public.gmane.org \
--cc=khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org \
--cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org \
--cc=robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=srinivas.bakki-3arQi8VN3Tc@public.gmane.org \
--cc=stigge-uj/7R2tJ6VmzQB+pC5nmwQ@public.gmane.org \
--cc=vitalywool-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.