From: "Heiko Stübner" <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>
To: Max Schwarz <max.schwarz-BGeptl67XyCzQB+pC5nmwQ@public.gmane.org>
Cc: Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org>,
Grant Likely
<grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH] i2c: add driver for Rockchip RK3xxx SoC I2C adapter
Date: Sun, 27 Apr 2014 22:23:13 +0200 [thread overview]
Message-ID: <2533407.kJCGHuX10p@diego> (raw)
In-Reply-To: <1840959.yqLj3D6H4q@typ>
Hi Max,
first of all, thanks for working on this :-)
I saw some general things inlined below, but I guess Wolfram is the better
person to check the i2c-specifics.
Am Sonntag, 27. April 2014, 21:38:49 schrieb Max Schwarz:
> Driver for the native I2C adapter found in Rockchip RK3xxx SoCs.
[...]
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt new file mode 100644
> index 0000000..6778985
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> @@ -0,0 +1,33 @@
> +* Rockchip RK3xxx I2C controller
> +
> +This driver interfaces with the native I2C controller present in Rockchip
> +RK3xxx SoCs.
> +
> +Required properties :
> +
> + - reg : Offset and length of the register set for the device
> + - compatible : should be "rockchip,rk3x-i2c"
> + - interrupts : interrupt number
> + - clocks : parent clock
> + - grf : the phandle of the syscon node for the general register file (GRF)
> + - bus-idx : index of the bus in the GRF
both the grf as well as the bus-idx are rockchip specific, so they should be
prefixed (rockchip,grf, etc) and from my personal taste I would hope we could
invest in an "n" and "e", to make it a full bus-index ;-)
> +
> +Optional properties :
> +
> + - frequency : SCL frequency to use (in Hz). If omitted, 100kHz is used.
the convention seems to be "clock-frequency" for the desired bus speed
(checked i2c-sirf, i2c-exynos, i2c-at91and i2c-qup).
> +
> +Example:
> +
> +i2c0: i2c@2002d000 {
> + compatible = "rockchip,rk3x-i2c";
> + reg = <0x2002d000 0x1000>;
> + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + grf = <&grf>;
> + bus-idx = <0>;
> +
> + clock-names = "i2c";
> + clocks = <&cru PCLK_I2C0>;
> +};
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index c94db1c..f973632 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -663,6 +663,16 @@ config I2C_PXA_SLAVE
> is necessary for systems where the PXA may be a target on the
> I2C bus.
>
> +config I2C_RK3X
> + tristate "Rockchip RK3xxx I2C adapter"
> + depends on OF
> + help
> + Say Y here to include support for the I2C adapter in Rockchip RK3xxx
> + SoCs.
> +
> + This driver can also be built as a module. If so, the module will
> + be called i2c-rk3x.
> +
> config I2C_QUP
> tristate "Qualcomm QUP based I2C controller"
> depends on ARCH_QCOM
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 18d18ff..39b6851 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -65,6 +65,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
> obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o
> obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
> obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
> +obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o
> obj-$(CONFIG_I2C_QUP) += i2c-qup.o
> obj-$(CONFIG_I2C_RIIC) += i2c-riic.o
> obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> new file mode 100644
> index 0000000..00491b0
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -0,0 +1,728 @@
> +/*
> + * Driver for I2C unit in Rockchip RK3188 SoC
RK3188 -> RK3xxx?
> + *
> + * Max Schwarz <max.schwarz-BGeptl67XyCzQB+pC5nmwQ@public.gmane.org>
> + * based on the patches by Rockchip Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +
> +#include <linux/i2c.h>
> +#include <linux/time.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/spinlock.h>
> +#include <linux/clk.h>
> +#include <linux/wait.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +
> +
> +/* Register Map */
> +#define REG_CON 0x00 /* control register */
> +#define REG_CLKDIV 0x04 /* clock divisor register */
> +#define REG_MRXADDR 0x08 /* slave address for REGISTER_TX */
> +#define REG_MRXRADDR 0x0c /* slave register address for REGISTER_TX */
> +#define REG_MTXCNT 0x10 /* number of bytes to be transmitted */
> +#define REG_MRXCNT 0x14 /* number of bytes to be received */
> +#define REG_IEN 0x18 /* interrupt enable */
> +#define REG_IPD 0x1c /* interrupt pending */
> +#define REG_FCNT 0x20 /* finished count */
> +
> +/* Data buffer offsets */
> +#define TXBUFFER_BASE 0x100
> +#define RXBUFFER_BASE 0x200
> +
> +/* REG_CON bits */
> +#define REG_CON_EN (1 << 0)
> +enum {
> + REG_CON_MOD_TX = 0, /* transmit data */
> + REG_CON_MOD_REGISTER_TX, /* select register and restart */
> + REG_CON_MOD_RX, /* receive data */
> + REG_CON_MOD_REGISTER_RX, /* broken: transmits read addr AND writes
> + * register addr */
> +};
> +#define REG_CON_MOD(mod) ((mod) << 1)
> +#define REG_CON_MOD_MASK (3 << 1)
> +#define REG_CON_START (1 << 3)
> +#define REG_CON_STOP (1 << 4)
> +#define REG_CON_LASTACK (1 << 5) /* 1: do not send ACK after last receive
> */ +#define REG_CON_ACTACK (1 << 6) /* 1: stop if NACK is received */ +
> +/* REG_MRXADDR bits */
> +#define REG_MRXADDR_LOW (1 << 24) /* bits [7:0] of MRX[R]ADDR are valid
> */ +#define REG_MRXADDR_MID (1 << 25) /* bits [15:8] of MRX[R]ADDR are
> valid */ +#define REG_MRXADDR_HIGH (1 << 26) /* bits [23:16] of MRX[R]ADDR
> are valid */ +
> +/* REG_IEN/REG_IPD bits */
> +#define REG_INT_BTF (1 << 0) /* a byte was transmitted */
> +#define REG_INT_BRF (1 << 1) /* a byte was received */
> +#define REG_INT_MBTF (1 << 2) /* master data transmit finished */
> +#define REG_INT_MBRF (1 << 3) /* master data receive finished */
> +#define REG_INT_START (1 << 4) /* START condition generated */
> +#define REG_INT_STOP (1 << 5) /* STOP condition generated */
> +#define REG_INT_NAKRCV (1 << 6) /* NACK received */
> +#define REG_INT_ALL 0x7f
> +
> +/* Registers in the GRF (General Register File) */
> +#define GRF_SOC_CON1 4
> +
> +/* Constants */
> +#define WAIT_TIMEOUT 200 /* ms */
> +
> +enum rk3x_i2c_state {
> + STATE_IDLE,
> + STATE_START,
> + STATE_READ,
> + STATE_WRITE,
> + STATE_STOP
> +};
> +
> +struct rk3x_i2c {
> + struct i2c_adapter adap;
> + struct device *dev;
> +
> + /* Hardware resources */
> + void __iomem *regs;
> + struct regmap *grf;
> + unsigned int bus_idx;
> + struct clk *clk;
> + int irq;
> +
> + /* Settings */
> + unsigned int scl_frequency;
> +
> + /* Synchronization & notification */
> + spinlock_t lock;
> + wait_queue_head_t wait;
> + bool busy;
> +
> + /* Current message */
> + struct i2c_msg *msg;
> + u8 addr;
> + unsigned int mode;
> +
> + /* I2C state machine */
> + enum rk3x_i2c_state state;
> + unsigned int processed; /* sent/received bytes */
> + int error;
> +};
> +
> +static inline void i2c_writel(struct rk3x_i2c *i2c, u32 value,
> + unsigned int offset)
> +{
> + writel(value, i2c->regs + offset);
> +}
> +
> +static inline u32 i2c_readl(struct rk3x_i2c *i2c, unsigned int offset)
> +{
> + return readl(i2c->regs + offset);
> +}
I'm not sure what the policy here is, but is this indirection really necessary
when it's only doing a normal readl/writel?
Heiko
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: "Heiko Stübner" <heiko@sntech.de>
To: Max Schwarz <max.schwarz@online.de>
Cc: Wolfram Sang <wsa@the-dreams.de>,
Grant Likely <grant.likely@linaro.org>,
Rob Herring <robh+dt@kernel.org>,
linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org
Subject: Re: [PATCH] i2c: add driver for Rockchip RK3xxx SoC I2C adapter
Date: Sun, 27 Apr 2014 22:23:13 +0200 [thread overview]
Message-ID: <2533407.kJCGHuX10p@diego> (raw)
In-Reply-To: <1840959.yqLj3D6H4q@typ>
Hi Max,
first of all, thanks for working on this :-)
I saw some general things inlined below, but I guess Wolfram is the better
person to check the i2c-specifics.
Am Sonntag, 27. April 2014, 21:38:49 schrieb Max Schwarz:
> Driver for the native I2C adapter found in Rockchip RK3xxx SoCs.
[...]
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt new file mode 100644
> index 0000000..6778985
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> @@ -0,0 +1,33 @@
> +* Rockchip RK3xxx I2C controller
> +
> +This driver interfaces with the native I2C controller present in Rockchip
> +RK3xxx SoCs.
> +
> +Required properties :
> +
> + - reg : Offset and length of the register set for the device
> + - compatible : should be "rockchip,rk3x-i2c"
> + - interrupts : interrupt number
> + - clocks : parent clock
> + - grf : the phandle of the syscon node for the general register file (GRF)
> + - bus-idx : index of the bus in the GRF
both the grf as well as the bus-idx are rockchip specific, so they should be
prefixed (rockchip,grf, etc) and from my personal taste I would hope we could
invest in an "n" and "e", to make it a full bus-index ;-)
> +
> +Optional properties :
> +
> + - frequency : SCL frequency to use (in Hz). If omitted, 100kHz is used.
the convention seems to be "clock-frequency" for the desired bus speed
(checked i2c-sirf, i2c-exynos, i2c-at91and i2c-qup).
> +
> +Example:
> +
> +i2c0: i2c@2002d000 {
> + compatible = "rockchip,rk3x-i2c";
> + reg = <0x2002d000 0x1000>;
> + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + grf = <&grf>;
> + bus-idx = <0>;
> +
> + clock-names = "i2c";
> + clocks = <&cru PCLK_I2C0>;
> +};
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index c94db1c..f973632 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -663,6 +663,16 @@ config I2C_PXA_SLAVE
> is necessary for systems where the PXA may be a target on the
> I2C bus.
>
> +config I2C_RK3X
> + tristate "Rockchip RK3xxx I2C adapter"
> + depends on OF
> + help
> + Say Y here to include support for the I2C adapter in Rockchip RK3xxx
> + SoCs.
> +
> + This driver can also be built as a module. If so, the module will
> + be called i2c-rk3x.
> +
> config I2C_QUP
> tristate "Qualcomm QUP based I2C controller"
> depends on ARCH_QCOM
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 18d18ff..39b6851 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -65,6 +65,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
> obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o
> obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
> obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
> +obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o
> obj-$(CONFIG_I2C_QUP) += i2c-qup.o
> obj-$(CONFIG_I2C_RIIC) += i2c-riic.o
> obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> new file mode 100644
> index 0000000..00491b0
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -0,0 +1,728 @@
> +/*
> + * Driver for I2C unit in Rockchip RK3188 SoC
RK3188 -> RK3xxx?
> + *
> + * Max Schwarz <max.schwarz@online.de>
> + * based on the patches by Rockchip Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +
> +#include <linux/i2c.h>
> +#include <linux/time.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/spinlock.h>
> +#include <linux/clk.h>
> +#include <linux/wait.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +
> +
> +/* Register Map */
> +#define REG_CON 0x00 /* control register */
> +#define REG_CLKDIV 0x04 /* clock divisor register */
> +#define REG_MRXADDR 0x08 /* slave address for REGISTER_TX */
> +#define REG_MRXRADDR 0x0c /* slave register address for REGISTER_TX */
> +#define REG_MTXCNT 0x10 /* number of bytes to be transmitted */
> +#define REG_MRXCNT 0x14 /* number of bytes to be received */
> +#define REG_IEN 0x18 /* interrupt enable */
> +#define REG_IPD 0x1c /* interrupt pending */
> +#define REG_FCNT 0x20 /* finished count */
> +
> +/* Data buffer offsets */
> +#define TXBUFFER_BASE 0x100
> +#define RXBUFFER_BASE 0x200
> +
> +/* REG_CON bits */
> +#define REG_CON_EN (1 << 0)
> +enum {
> + REG_CON_MOD_TX = 0, /* transmit data */
> + REG_CON_MOD_REGISTER_TX, /* select register and restart */
> + REG_CON_MOD_RX, /* receive data */
> + REG_CON_MOD_REGISTER_RX, /* broken: transmits read addr AND writes
> + * register addr */
> +};
> +#define REG_CON_MOD(mod) ((mod) << 1)
> +#define REG_CON_MOD_MASK (3 << 1)
> +#define REG_CON_START (1 << 3)
> +#define REG_CON_STOP (1 << 4)
> +#define REG_CON_LASTACK (1 << 5) /* 1: do not send ACK after last receive
> */ +#define REG_CON_ACTACK (1 << 6) /* 1: stop if NACK is received */ +
> +/* REG_MRXADDR bits */
> +#define REG_MRXADDR_LOW (1 << 24) /* bits [7:0] of MRX[R]ADDR are valid
> */ +#define REG_MRXADDR_MID (1 << 25) /* bits [15:8] of MRX[R]ADDR are
> valid */ +#define REG_MRXADDR_HIGH (1 << 26) /* bits [23:16] of MRX[R]ADDR
> are valid */ +
> +/* REG_IEN/REG_IPD bits */
> +#define REG_INT_BTF (1 << 0) /* a byte was transmitted */
> +#define REG_INT_BRF (1 << 1) /* a byte was received */
> +#define REG_INT_MBTF (1 << 2) /* master data transmit finished */
> +#define REG_INT_MBRF (1 << 3) /* master data receive finished */
> +#define REG_INT_START (1 << 4) /* START condition generated */
> +#define REG_INT_STOP (1 << 5) /* STOP condition generated */
> +#define REG_INT_NAKRCV (1 << 6) /* NACK received */
> +#define REG_INT_ALL 0x7f
> +
> +/* Registers in the GRF (General Register File) */
> +#define GRF_SOC_CON1 4
> +
> +/* Constants */
> +#define WAIT_TIMEOUT 200 /* ms */
> +
> +enum rk3x_i2c_state {
> + STATE_IDLE,
> + STATE_START,
> + STATE_READ,
> + STATE_WRITE,
> + STATE_STOP
> +};
> +
> +struct rk3x_i2c {
> + struct i2c_adapter adap;
> + struct device *dev;
> +
> + /* Hardware resources */
> + void __iomem *regs;
> + struct regmap *grf;
> + unsigned int bus_idx;
> + struct clk *clk;
> + int irq;
> +
> + /* Settings */
> + unsigned int scl_frequency;
> +
> + /* Synchronization & notification */
> + spinlock_t lock;
> + wait_queue_head_t wait;
> + bool busy;
> +
> + /* Current message */
> + struct i2c_msg *msg;
> + u8 addr;
> + unsigned int mode;
> +
> + /* I2C state machine */
> + enum rk3x_i2c_state state;
> + unsigned int processed; /* sent/received bytes */
> + int error;
> +};
> +
> +static inline void i2c_writel(struct rk3x_i2c *i2c, u32 value,
> + unsigned int offset)
> +{
> + writel(value, i2c->regs + offset);
> +}
> +
> +static inline u32 i2c_readl(struct rk3x_i2c *i2c, unsigned int offset)
> +{
> + return readl(i2c->regs + offset);
> +}
I'm not sure what the policy here is, but is this indirection really necessary
when it's only doing a normal readl/writel?
Heiko
next prev parent reply other threads:[~2014-04-27 20:23 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-27 19:38 [PATCH] i2c: add driver for Rockchip RK3xxx SoC I2C adapter Max Schwarz
2014-04-27 19:38 ` Max Schwarz
2014-04-27 20:23 ` Heiko Stübner [this message]
2014-04-27 20:23 ` Heiko Stübner
2014-04-27 22:39 ` Max Schwarz
2014-04-27 22:39 ` Max Schwarz
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=2533407.kJCGHuX10p@diego \
--to=heiko-4mtyjxux2i+zqb+pc5nmwq@public.gmane.org \
--cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
--cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=max.schwarz-BGeptl67XyCzQB+pC5nmwQ@public.gmane.org \
--cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=wsa-z923LK4zBo2bacvFa/9K2g@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.