* [PATCH v3 0/3] i2c: add driver for Amlogic Meson I2C controller @ 2014-11-13 19:32 ` Beniamino Galvani 0 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-13 19:32 UTC (permalink / raw) To: Wolfram Sang Cc: Carlo Caione, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Jerry Cao, Victor Wan, Beniamino Galvani Hi, this patchset adds a driver for the I2C controller available in Amlogic Meson SoCs. It has been tested on a Meson8 based board with the following devices: - Ricoh RN5T618 PMIC - NXP PCF8564 RTC Changes since v2: - fixed token generation for split reads - simplified meson_i2c_prepare_xfer() - added DTS patch Changes since v1: - factored common code for token list setup Beniamino Galvani (3): i2c: meson: add device tree bindings documentation i2c: add support for Amlogic Meson I2C controller ARM: dts: meson: add I2C controller nodes .../devicetree/bindings/i2c/i2c-meson.txt | 24 + arch/arm/boot/dts/meson.dtsi | 30 ++ drivers/i2c/busses/Kconfig | 7 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-meson.c | 492 +++++++++++++++++++++ 5 files changed, 554 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/i2c-meson.txt create mode 100644 drivers/i2c/busses/i2c-meson.c -- 1.9.1 ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 0/3] i2c: add driver for Amlogic Meson I2C controller @ 2014-11-13 19:32 ` Beniamino Galvani 0 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-13 19:32 UTC (permalink / raw) To: Wolfram Sang Cc: Carlo Caione, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, linux-i2c, linux-kernel, devicetree, linux-arm-kernel, Jerry Cao, Victor Wan, Beniamino Galvani Hi, this patchset adds a driver for the I2C controller available in Amlogic Meson SoCs. It has been tested on a Meson8 based board with the following devices: - Ricoh RN5T618 PMIC - NXP PCF8564 RTC Changes since v2: - fixed token generation for split reads - simplified meson_i2c_prepare_xfer() - added DTS patch Changes since v1: - factored common code for token list setup Beniamino Galvani (3): i2c: meson: add device tree bindings documentation i2c: add support for Amlogic Meson I2C controller ARM: dts: meson: add I2C controller nodes .../devicetree/bindings/i2c/i2c-meson.txt | 24 + arch/arm/boot/dts/meson.dtsi | 30 ++ drivers/i2c/busses/Kconfig | 7 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-meson.c | 492 +++++++++++++++++++++ 5 files changed, 554 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/i2c-meson.txt create mode 100644 drivers/i2c/busses/i2c-meson.c -- 1.9.1 ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 0/3] i2c: add driver for Amlogic Meson I2C controller @ 2014-11-13 19:32 ` Beniamino Galvani 0 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-13 19:32 UTC (permalink / raw) To: linux-arm-kernel Hi, this patchset adds a driver for the I2C controller available in Amlogic Meson SoCs. It has been tested on a Meson8 based board with the following devices: - Ricoh RN5T618 PMIC - NXP PCF8564 RTC Changes since v2: - fixed token generation for split reads - simplified meson_i2c_prepare_xfer() - added DTS patch Changes since v1: - factored common code for token list setup Beniamino Galvani (3): i2c: meson: add device tree bindings documentation i2c: add support for Amlogic Meson I2C controller ARM: dts: meson: add I2C controller nodes .../devicetree/bindings/i2c/i2c-meson.txt | 24 + arch/arm/boot/dts/meson.dtsi | 30 ++ drivers/i2c/busses/Kconfig | 7 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-meson.c | 492 +++++++++++++++++++++ 5 files changed, 554 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/i2c-meson.txt create mode 100644 drivers/i2c/busses/i2c-meson.c -- 1.9.1 ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 1/3] i2c: meson: add device tree bindings documentation 2014-11-13 19:32 ` Beniamino Galvani @ 2014-11-13 19:32 ` Beniamino Galvani -1 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-13 19:32 UTC (permalink / raw) To: Wolfram Sang Cc: Carlo Caione, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, linux-i2c, linux-kernel, devicetree, linux-arm-kernel, Jerry Cao, Victor Wan, Beniamino Galvani This commit adds device tree bindings documentation for the I2C bus controller found on Amlogic Meson SoCs. Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> --- .../devicetree/bindings/i2c/i2c-meson.txt | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/i2c-meson.txt diff --git a/Documentation/devicetree/bindings/i2c/i2c-meson.txt b/Documentation/devicetree/bindings/i2c/i2c-meson.txt new file mode 100644 index 0000000..682f9a6 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-meson.txt @@ -0,0 +1,24 @@ +Amlogic Meson I2C controller + +Required properties: + - compatible: must be "amlogic,meson6-i2c" + - reg: physical address and length of the device registers + - interrupts: a single interrupt specifier + - clocks: clock for the device + - #address-cells: should be <1> + - #size-cells: should be <0> + +Optional properties: +- clock-frequency: the desired I2C bus clock frequency in Hz; in + absence of this property the default value is used (100 kHz). + +Examples: + + i2c@c8100500 { + compatible = "amlogic,meson6-i2c"; + reg = <0xc8100500 0x20>; + interrupts = <0 92 1>; + clocks = <&clk81>; + #address-cells = <1>; + #size-cells = <0>; + }; -- 1.9.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 1/3] i2c: meson: add device tree bindings documentation @ 2014-11-13 19:32 ` Beniamino Galvani 0 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-13 19:32 UTC (permalink / raw) To: linux-arm-kernel This commit adds device tree bindings documentation for the I2C bus controller found on Amlogic Meson SoCs. Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> --- .../devicetree/bindings/i2c/i2c-meson.txt | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/i2c-meson.txt diff --git a/Documentation/devicetree/bindings/i2c/i2c-meson.txt b/Documentation/devicetree/bindings/i2c/i2c-meson.txt new file mode 100644 index 0000000..682f9a6 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-meson.txt @@ -0,0 +1,24 @@ +Amlogic Meson I2C controller + +Required properties: + - compatible: must be "amlogic,meson6-i2c" + - reg: physical address and length of the device registers + - interrupts: a single interrupt specifier + - clocks: clock for the device + - #address-cells: should be <1> + - #size-cells: should be <0> + +Optional properties: +- clock-frequency: the desired I2C bus clock frequency in Hz; in + absence of this property the default value is used (100 kHz). + +Examples: + + i2c at c8100500 { + compatible = "amlogic,meson6-i2c"; + reg = <0xc8100500 0x20>; + interrupts = <0 92 1>; + clocks = <&clk81>; + #address-cells = <1>; + #size-cells = <0>; + }; -- 1.9.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v3 1/3] i2c: meson: add device tree bindings documentation 2014-11-13 19:32 ` Beniamino Galvani @ 2014-11-18 15:17 ` Wolfram Sang -1 siblings, 0 replies; 20+ messages in thread From: Wolfram Sang @ 2014-11-18 15:17 UTC (permalink / raw) To: Beniamino Galvani Cc: Carlo Caione, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, linux-i2c, linux-kernel, devicetree, linux-arm-kernel, Jerry Cao, Victor Wan [-- Attachment #1: Type: text/plain, Size: 278 bytes --] On Thu, Nov 13, 2014 at 08:32:01PM +0100, Beniamino Galvani wrote: > This commit adds device tree bindings documentation for the I2C bus > controller found on Amlogic Meson SoCs. > > Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> Applied to for-next, thanks! [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 1/3] i2c: meson: add device tree bindings documentation @ 2014-11-18 15:17 ` Wolfram Sang 0 siblings, 0 replies; 20+ messages in thread From: Wolfram Sang @ 2014-11-18 15:17 UTC (permalink / raw) To: linux-arm-kernel On Thu, Nov 13, 2014 at 08:32:01PM +0100, Beniamino Galvani wrote: > This commit adds device tree bindings documentation for the I2C bus > controller found on Amlogic Meson SoCs. > > Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> Applied to for-next, thanks! -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141118/e5469475/attachment-0001.sig> ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 2/3] i2c: add support for Amlogic Meson I2C controller 2014-11-13 19:32 ` Beniamino Galvani @ 2014-11-13 19:32 ` Beniamino Galvani -1 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-13 19:32 UTC (permalink / raw) To: Wolfram Sang Cc: Carlo Caione, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, linux-i2c, linux-kernel, devicetree, linux-arm-kernel, Jerry Cao, Victor Wan, Beniamino Galvani This is a driver for the I2C controller found in Amlogic Meson SoCs. Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> --- drivers/i2c/busses/Kconfig | 7 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-meson.c | 492 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 500 insertions(+) create mode 100644 drivers/i2c/busses/i2c-meson.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 917c358..b76fd31 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -553,6 +553,13 @@ config I2C_KEMPLD This driver can also be built as a module. If so, the module will be called i2c-kempld. +config I2C_MESON + tristate "Amlogic Meson I2C controller" + depends on ARCH_MESON + help + If you say yes to this option, support will be included for the + I2C interface on the Amlogic Meson family of SoCs. + config I2C_MPC tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx" depends on PPC diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 78d56c5..a3f2de9 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o obj-$(CONFIG_I2C_IMX) += i2c-imx.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_KEMPLD) += i2c-kempld.o +obj-$(CONFIG_I2C_MESON) += i2c-meson.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_MXS) += i2c-mxs.o diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c new file mode 100644 index 0000000..5e176ad --- /dev/null +++ b/drivers/i2c/busses/i2c-meson.c @@ -0,0 +1,492 @@ +/* + * I2C bus driver for Amlogic Meson SoCs + * + * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/clk.h> +#include <linux/completion.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/types.h> + +/* Meson I2C register map */ +#define REG_CTRL 0x00 +#define REG_SLAVE_ADDR 0x04 +#define REG_TOK_LIST0 0x08 +#define REG_TOK_LIST1 0x0c +#define REG_TOK_WDATA0 0x10 +#define REG_TOK_WDATA1 0x14 +#define REG_TOK_RDATA0 0x18 +#define REG_TOK_RDATA1 0x1c + +/* Control register fields */ +#define REG_CTRL_START BIT(0) +#define REG_CTRL_ACK_IGNORE BIT(1) +#define REG_CTRL_STATUS BIT(2) +#define REG_CTRL_ERROR BIT(3) +#define REG_CTRL_CLKDIV_SHIFT 12 +#define REG_CTRL_CLKDIV_MASK ((BIT(10) - 1) << REG_CTRL_CLKDIV_SHIFT) + +#define I2C_TIMEOUT_MS 500 +#define DEFAULT_FREQ 100000 + +enum { + TOKEN_END = 0, + TOKEN_START, + TOKEN_SLAVE_ADDR_WRITE, + TOKEN_SLAVE_ADDR_READ, + TOKEN_DATA, + TOKEN_DATA_LAST, + TOKEN_STOP, +}; + +enum { + STATE_IDLE, + STATE_READ, + STATE_WRITE, + STATE_STOP, +}; + +/** + * struct meson_i2c - Meson I2C device private data + * + * @adap: I2C adapter instance + * @dev: Pointer to device structure + * @regs: Base address of the device memory mapped registers + * @clk: Pointer to clock structure + * @irq: IRQ number + * @msg: Pointer to the current I2C message + * @state: Current state in the driver state machine + * @last: Flag set for the last message in the transfer + * @count: Number of bytes to be sent/received in current transfer + * @pos: Current position in the send/receive buffer + * @error: Flag set when an error is received + * @lock: To avoid race conditions between irq handler and xfer code + * @done: Completion used to wait for transfer termination + * @frequency: Operating frequency of I2C bus clock + * @tokens: Sequence of tokens to be written to the device + * @num_tokens: Number of tokens + */ +struct meson_i2c { + struct i2c_adapter adap; + struct device *dev; + void __iomem *regs; + struct clk *clk; + int irq; + + struct i2c_msg *msg; + int state; + bool last; + int count; + int pos; + int error; + + spinlock_t lock; + struct completion done; + unsigned int frequency; + u32 tokens[2]; + int num_tokens; +}; + +static void meson_i2c_set_mask(struct meson_i2c *i2c, int reg, u32 mask, + u32 val) +{ + u32 data; + + data = readl(i2c->regs + reg); + data &= ~mask; + data |= val & mask; + writel(data, i2c->regs + reg); +} + +static void meson_i2c_reset_tokens(struct meson_i2c *i2c) +{ + i2c->tokens[0] = 0; + i2c->tokens[1] = 0; + i2c->num_tokens = 0; +} + +static void meson_i2c_add_token(struct meson_i2c *i2c, int token) +{ + if (i2c->num_tokens < 8) + i2c->tokens[0] |= (token & 0xf) << (i2c->num_tokens * 4); + else + i2c->tokens[1] |= (token & 0xf) << ((i2c->num_tokens % 8) * 4); + + i2c->num_tokens++; +} + +static void meson_i2c_write_tokens(struct meson_i2c *i2c) +{ + writel(i2c->tokens[0], i2c->regs + REG_TOK_LIST0); + writel(i2c->tokens[1], i2c->regs + REG_TOK_LIST1); +} + +static void meson_i2c_set_clk_div(struct meson_i2c *i2c) +{ + unsigned long clk_rate = clk_get_rate(i2c->clk); + unsigned int div; + + div = DIV_ROUND_UP(clk_rate, i2c->frequency * 4); + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK, + div << REG_CTRL_CLKDIV_SHIFT); + + dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__, + clk_rate, i2c->frequency, div); +} + +static void meson_i2c_get_data(struct meson_i2c *i2c, char *buf, int len) +{ + u32 rdata0, rdata1; + int i; + + rdata0 = readl(i2c->regs + REG_TOK_RDATA0); + rdata1 = readl(i2c->regs + REG_TOK_RDATA1); + + dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__, + rdata0, rdata1, len); + + for (i = 0; i < min_t(int, 4, len); i++) + *buf++ = (rdata0 >> i * 8) & 0xff; + + for (i = 4; i < min_t(int, 8, len); i++) + *buf++ = (rdata1 >> (i - 4) * 8) & 0xff; +} + +static void meson_i2c_put_data(struct meson_i2c *i2c, char *buf, int len) +{ + u32 wdata0 = 0, wdata1 = 0; + int i; + + for (i = 0; i < min_t(int, 4, len); i++) + wdata0 |= *buf++ << (i * 8); + + for (i = 4; i < min_t(int, 8, len); i++) + wdata1 |= *buf++ << ((i - 4) * 8); + + writel(wdata0, i2c->regs + REG_TOK_WDATA0); + writel(wdata0, i2c->regs + REG_TOK_WDATA1); + + dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__, + wdata0, wdata1, len); +} + +static void meson_i2c_prepare_xfer(struct meson_i2c *i2c) +{ + bool write = !(i2c->msg->flags & I2C_M_RD); + int i; + + i2c->count = min_t(int, i2c->msg->len - i2c->pos, 8); + + for (i = 0; i < i2c->count - 1; i++) + meson_i2c_add_token(i2c, TOKEN_DATA); + + if (i2c->count) { + if (write || i2c->pos + i2c->count < i2c->msg->len) + meson_i2c_add_token(i2c, TOKEN_DATA); + else + meson_i2c_add_token(i2c, TOKEN_DATA_LAST); + } + + if (write) + meson_i2c_put_data(i2c, i2c->msg->buf + i2c->pos, i2c->count); +} + +static void meson_i2c_stop(struct meson_i2c *i2c) +{ + dev_dbg(i2c->dev, "%s: last %d\n", __func__, i2c->last); + + if (i2c->last) { + i2c->state = STATE_STOP; + meson_i2c_add_token(i2c, TOKEN_STOP); + } else { + i2c->state = STATE_IDLE; + complete_all(&i2c->done); + } +} + +static irqreturn_t meson_i2c_irq(int irqno, void *dev_id) +{ + struct meson_i2c *i2c = dev_id; + unsigned int ctrl; + + spin_lock(&i2c->lock); + + meson_i2c_reset_tokens(i2c); + ctrl = readl(i2c->regs + REG_CTRL); + + dev_dbg(i2c->dev, "irq: state %d, pos %d, count %d, ctrl %08x\n", + i2c->state, i2c->pos, i2c->count, ctrl); + + if (ctrl & REG_CTRL_ERROR && i2c->state != STATE_IDLE) { + /* + * The bit is set when the IGNORE_NAK bit is cleared + * and the device didn't respond. In this case, the + * I2C controller automatically generates a STOP + * condition. + */ + dev_dbg(i2c->dev, "error bit set\n"); + i2c->error = -ENXIO; + i2c->state = STATE_IDLE; + complete_all(&i2c->done); + goto out; + } + + switch (i2c->state) { + case STATE_READ: + if (i2c->count > 0) { + meson_i2c_get_data(i2c, i2c->msg->buf + i2c->pos, + i2c->count); + i2c->pos += i2c->count; + } + + if (i2c->pos >= i2c->msg->len) { + meson_i2c_stop(i2c); + break; + } + + meson_i2c_prepare_xfer(i2c); + break; + case STATE_WRITE: + i2c->pos += i2c->count; + + if (i2c->pos >= i2c->msg->len) { + meson_i2c_stop(i2c); + break; + } + + meson_i2c_prepare_xfer(i2c); + break; + case STATE_STOP: + i2c->state = STATE_IDLE; + complete_all(&i2c->done); + break; + case STATE_IDLE: + break; + } + +out: + if (i2c->state != STATE_IDLE) { + /* Restart the processing */ + meson_i2c_write_tokens(i2c); + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0); + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, + REG_CTRL_START); + } + + spin_unlock(&i2c->lock); + + return IRQ_HANDLED; +} + +static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg) +{ + int token; + + token = (msg->flags & I2C_M_RD) ? TOKEN_SLAVE_ADDR_READ : + TOKEN_SLAVE_ADDR_WRITE; + + writel(msg->addr << 1, i2c->regs + REG_SLAVE_ADDR); + meson_i2c_add_token(i2c, TOKEN_START); + meson_i2c_add_token(i2c, token); +} + +static int meson_i2c_xfer_msg(struct meson_i2c *i2c, struct i2c_msg *msg, + int last) +{ + unsigned long time_left, flags; + int ret = 0; + + i2c->msg = msg; + i2c->last = last; + i2c->pos = 0; + i2c->count = 0; + i2c->error = 0; + + meson_i2c_reset_tokens(i2c); + + flags = (msg->flags & I2C_M_IGNORE_NAK) ? REG_CTRL_ACK_IGNORE : 0; + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_ACK_IGNORE, flags); + + if (!(msg->flags & I2C_M_NOSTART)) + meson_i2c_do_start(i2c, msg); + + i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + meson_i2c_prepare_xfer(i2c); + meson_i2c_write_tokens(i2c); + reinit_completion(&i2c->done); + + /* Start the transfer */ + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, REG_CTRL_START); + + time_left = msecs_to_jiffies(I2C_TIMEOUT_MS); + time_left = wait_for_completion_timeout(&i2c->done, time_left); + + /* + * Protect access to i2c struct and registers from interrupt + * handlers triggered by a transfer terminated after the + * timeout period + */ + spin_lock_irqsave(&i2c->lock, flags); + + /* Abort any active operation */ + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0); + + if (!time_left) { + i2c->state = STATE_IDLE; + ret = -ETIMEDOUT; + } + + if (i2c->error) + ret = i2c->error; + + spin_unlock_irqrestore(&i2c->lock, flags); + + return ret; +} + +static int meson_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) +{ + struct meson_i2c *i2c = adap->algo_data; + int i, ret = 0, count = 0; + + clk_enable(i2c->clk); + meson_i2c_set_clk_div(i2c); + + for (i = 0; i < num; i++) { + ret = meson_i2c_xfer_msg(i2c, msgs + i, i == num - 1); + if (ret) + break; + count++; + } + + clk_disable(i2c->clk); + + return ret ? ret : count; +} + +static u32 meson_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm meson_i2c_algorithm = { + .master_xfer = meson_i2c_xfer, + .functionality = meson_i2c_func, +}; + +static int meson_i2c_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct meson_i2c *i2c; + struct resource *mem; + int ret = 0; + + i2c = devm_kzalloc(&pdev->dev, sizeof(struct meson_i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &i2c->frequency)) + i2c->frequency = DEFAULT_FREQ; + + i2c->dev = &pdev->dev; + platform_set_drvdata(pdev, i2c); + + spin_lock_init(&i2c->lock); + init_completion(&i2c->done); + + i2c->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(i2c->clk)) { + dev_err(&pdev->dev, "can't get device clock\n"); + return PTR_ERR(i2c->clk); + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + i2c->regs = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(i2c->regs)) + return PTR_ERR(i2c->regs); + + i2c->irq = platform_get_irq(pdev, 0); + if (i2c->irq < 0) { + dev_err(&pdev->dev, "can't find IRQ\n"); + return i2c->irq; + } + + ret = devm_request_irq(&pdev->dev, i2c->irq, meson_i2c_irq, + 0, dev_name(&pdev->dev), i2c); + if (ret < 0) { + dev_err(&pdev->dev, "can't request IRQ\n"); + return ret; + } + + ret = clk_prepare(i2c->clk); + if (ret < 0) { + dev_err(&pdev->dev, "can't prepare clock\n"); + return ret; + } + + strlcpy(i2c->adap.name, "Meson I2C adapter", + sizeof(i2c->adap.name)); + i2c->adap.owner = THIS_MODULE; + i2c->adap.algo = &meson_i2c_algorithm; + i2c->adap.dev.parent = &pdev->dev; + i2c->adap.dev.of_node = np; + i2c->adap.algo_data = i2c; + + /* + * A transfer is triggered when START bit changes from 0 to 1. + * Ensure that the bit is set to 0 after probe + */ + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0); + + ret = i2c_add_adapter(&i2c->adap); + if (ret < 0) { + dev_err(&pdev->dev, "can't register adapter\n"); + clk_unprepare(i2c->clk); + return ret; + } + + return 0; +} + +static int meson_i2c_remove(struct platform_device *pdev) +{ + struct meson_i2c *i2c = platform_get_drvdata(pdev); + + i2c_del_adapter(&i2c->adap); + clk_unprepare(i2c->clk); + + return 0; +} + +static const struct of_device_id meson_i2c_match[] = { + { .compatible = "amlogic,meson6-i2c" }, + { }, +}; + +static struct platform_driver meson_i2c_driver = { + .probe = meson_i2c_probe, + .remove = meson_i2c_remove, + .driver = { + .name = "meson-i2c", + .of_match_table = meson_i2c_match, + }, +}; + +module_platform_driver(meson_i2c_driver); + +MODULE_DESCRIPTION("Amlogic Meson I2C Bus driver"); +MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); +MODULE_LICENSE("GPL v2"); -- 1.9.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 2/3] i2c: add support for Amlogic Meson I2C controller @ 2014-11-13 19:32 ` Beniamino Galvani 0 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-13 19:32 UTC (permalink / raw) To: linux-arm-kernel This is a driver for the I2C controller found in Amlogic Meson SoCs. Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> --- drivers/i2c/busses/Kconfig | 7 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-meson.c | 492 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 500 insertions(+) create mode 100644 drivers/i2c/busses/i2c-meson.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 917c358..b76fd31 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -553,6 +553,13 @@ config I2C_KEMPLD This driver can also be built as a module. If so, the module will be called i2c-kempld. +config I2C_MESON + tristate "Amlogic Meson I2C controller" + depends on ARCH_MESON + help + If you say yes to this option, support will be included for the + I2C interface on the Amlogic Meson family of SoCs. + config I2C_MPC tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx" depends on PPC diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 78d56c5..a3f2de9 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o obj-$(CONFIG_I2C_IMX) += i2c-imx.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_KEMPLD) += i2c-kempld.o +obj-$(CONFIG_I2C_MESON) += i2c-meson.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_MXS) += i2c-mxs.o diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c new file mode 100644 index 0000000..5e176ad --- /dev/null +++ b/drivers/i2c/busses/i2c-meson.c @@ -0,0 +1,492 @@ +/* + * I2C bus driver for Amlogic Meson SoCs + * + * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/clk.h> +#include <linux/completion.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/types.h> + +/* Meson I2C register map */ +#define REG_CTRL 0x00 +#define REG_SLAVE_ADDR 0x04 +#define REG_TOK_LIST0 0x08 +#define REG_TOK_LIST1 0x0c +#define REG_TOK_WDATA0 0x10 +#define REG_TOK_WDATA1 0x14 +#define REG_TOK_RDATA0 0x18 +#define REG_TOK_RDATA1 0x1c + +/* Control register fields */ +#define REG_CTRL_START BIT(0) +#define REG_CTRL_ACK_IGNORE BIT(1) +#define REG_CTRL_STATUS BIT(2) +#define REG_CTRL_ERROR BIT(3) +#define REG_CTRL_CLKDIV_SHIFT 12 +#define REG_CTRL_CLKDIV_MASK ((BIT(10) - 1) << REG_CTRL_CLKDIV_SHIFT) + +#define I2C_TIMEOUT_MS 500 +#define DEFAULT_FREQ 100000 + +enum { + TOKEN_END = 0, + TOKEN_START, + TOKEN_SLAVE_ADDR_WRITE, + TOKEN_SLAVE_ADDR_READ, + TOKEN_DATA, + TOKEN_DATA_LAST, + TOKEN_STOP, +}; + +enum { + STATE_IDLE, + STATE_READ, + STATE_WRITE, + STATE_STOP, +}; + +/** + * struct meson_i2c - Meson I2C device private data + * + * @adap: I2C adapter instance + * @dev: Pointer to device structure + * @regs: Base address of the device memory mapped registers + * @clk: Pointer to clock structure + * @irq: IRQ number + * @msg: Pointer to the current I2C message + * @state: Current state in the driver state machine + * @last: Flag set for the last message in the transfer + * @count: Number of bytes to be sent/received in current transfer + * @pos: Current position in the send/receive buffer + * @error: Flag set when an error is received + * @lock: To avoid race conditions between irq handler and xfer code + * @done: Completion used to wait for transfer termination + * @frequency: Operating frequency of I2C bus clock + * @tokens: Sequence of tokens to be written to the device + * @num_tokens: Number of tokens + */ +struct meson_i2c { + struct i2c_adapter adap; + struct device *dev; + void __iomem *regs; + struct clk *clk; + int irq; + + struct i2c_msg *msg; + int state; + bool last; + int count; + int pos; + int error; + + spinlock_t lock; + struct completion done; + unsigned int frequency; + u32 tokens[2]; + int num_tokens; +}; + +static void meson_i2c_set_mask(struct meson_i2c *i2c, int reg, u32 mask, + u32 val) +{ + u32 data; + + data = readl(i2c->regs + reg); + data &= ~mask; + data |= val & mask; + writel(data, i2c->regs + reg); +} + +static void meson_i2c_reset_tokens(struct meson_i2c *i2c) +{ + i2c->tokens[0] = 0; + i2c->tokens[1] = 0; + i2c->num_tokens = 0; +} + +static void meson_i2c_add_token(struct meson_i2c *i2c, int token) +{ + if (i2c->num_tokens < 8) + i2c->tokens[0] |= (token & 0xf) << (i2c->num_tokens * 4); + else + i2c->tokens[1] |= (token & 0xf) << ((i2c->num_tokens % 8) * 4); + + i2c->num_tokens++; +} + +static void meson_i2c_write_tokens(struct meson_i2c *i2c) +{ + writel(i2c->tokens[0], i2c->regs + REG_TOK_LIST0); + writel(i2c->tokens[1], i2c->regs + REG_TOK_LIST1); +} + +static void meson_i2c_set_clk_div(struct meson_i2c *i2c) +{ + unsigned long clk_rate = clk_get_rate(i2c->clk); + unsigned int div; + + div = DIV_ROUND_UP(clk_rate, i2c->frequency * 4); + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK, + div << REG_CTRL_CLKDIV_SHIFT); + + dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__, + clk_rate, i2c->frequency, div); +} + +static void meson_i2c_get_data(struct meson_i2c *i2c, char *buf, int len) +{ + u32 rdata0, rdata1; + int i; + + rdata0 = readl(i2c->regs + REG_TOK_RDATA0); + rdata1 = readl(i2c->regs + REG_TOK_RDATA1); + + dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__, + rdata0, rdata1, len); + + for (i = 0; i < min_t(int, 4, len); i++) + *buf++ = (rdata0 >> i * 8) & 0xff; + + for (i = 4; i < min_t(int, 8, len); i++) + *buf++ = (rdata1 >> (i - 4) * 8) & 0xff; +} + +static void meson_i2c_put_data(struct meson_i2c *i2c, char *buf, int len) +{ + u32 wdata0 = 0, wdata1 = 0; + int i; + + for (i = 0; i < min_t(int, 4, len); i++) + wdata0 |= *buf++ << (i * 8); + + for (i = 4; i < min_t(int, 8, len); i++) + wdata1 |= *buf++ << ((i - 4) * 8); + + writel(wdata0, i2c->regs + REG_TOK_WDATA0); + writel(wdata0, i2c->regs + REG_TOK_WDATA1); + + dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__, + wdata0, wdata1, len); +} + +static void meson_i2c_prepare_xfer(struct meson_i2c *i2c) +{ + bool write = !(i2c->msg->flags & I2C_M_RD); + int i; + + i2c->count = min_t(int, i2c->msg->len - i2c->pos, 8); + + for (i = 0; i < i2c->count - 1; i++) + meson_i2c_add_token(i2c, TOKEN_DATA); + + if (i2c->count) { + if (write || i2c->pos + i2c->count < i2c->msg->len) + meson_i2c_add_token(i2c, TOKEN_DATA); + else + meson_i2c_add_token(i2c, TOKEN_DATA_LAST); + } + + if (write) + meson_i2c_put_data(i2c, i2c->msg->buf + i2c->pos, i2c->count); +} + +static void meson_i2c_stop(struct meson_i2c *i2c) +{ + dev_dbg(i2c->dev, "%s: last %d\n", __func__, i2c->last); + + if (i2c->last) { + i2c->state = STATE_STOP; + meson_i2c_add_token(i2c, TOKEN_STOP); + } else { + i2c->state = STATE_IDLE; + complete_all(&i2c->done); + } +} + +static irqreturn_t meson_i2c_irq(int irqno, void *dev_id) +{ + struct meson_i2c *i2c = dev_id; + unsigned int ctrl; + + spin_lock(&i2c->lock); + + meson_i2c_reset_tokens(i2c); + ctrl = readl(i2c->regs + REG_CTRL); + + dev_dbg(i2c->dev, "irq: state %d, pos %d, count %d, ctrl %08x\n", + i2c->state, i2c->pos, i2c->count, ctrl); + + if (ctrl & REG_CTRL_ERROR && i2c->state != STATE_IDLE) { + /* + * The bit is set when the IGNORE_NAK bit is cleared + * and the device didn't respond. In this case, the + * I2C controller automatically generates a STOP + * condition. + */ + dev_dbg(i2c->dev, "error bit set\n"); + i2c->error = -ENXIO; + i2c->state = STATE_IDLE; + complete_all(&i2c->done); + goto out; + } + + switch (i2c->state) { + case STATE_READ: + if (i2c->count > 0) { + meson_i2c_get_data(i2c, i2c->msg->buf + i2c->pos, + i2c->count); + i2c->pos += i2c->count; + } + + if (i2c->pos >= i2c->msg->len) { + meson_i2c_stop(i2c); + break; + } + + meson_i2c_prepare_xfer(i2c); + break; + case STATE_WRITE: + i2c->pos += i2c->count; + + if (i2c->pos >= i2c->msg->len) { + meson_i2c_stop(i2c); + break; + } + + meson_i2c_prepare_xfer(i2c); + break; + case STATE_STOP: + i2c->state = STATE_IDLE; + complete_all(&i2c->done); + break; + case STATE_IDLE: + break; + } + +out: + if (i2c->state != STATE_IDLE) { + /* Restart the processing */ + meson_i2c_write_tokens(i2c); + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0); + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, + REG_CTRL_START); + } + + spin_unlock(&i2c->lock); + + return IRQ_HANDLED; +} + +static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg) +{ + int token; + + token = (msg->flags & I2C_M_RD) ? TOKEN_SLAVE_ADDR_READ : + TOKEN_SLAVE_ADDR_WRITE; + + writel(msg->addr << 1, i2c->regs + REG_SLAVE_ADDR); + meson_i2c_add_token(i2c, TOKEN_START); + meson_i2c_add_token(i2c, token); +} + +static int meson_i2c_xfer_msg(struct meson_i2c *i2c, struct i2c_msg *msg, + int last) +{ + unsigned long time_left, flags; + int ret = 0; + + i2c->msg = msg; + i2c->last = last; + i2c->pos = 0; + i2c->count = 0; + i2c->error = 0; + + meson_i2c_reset_tokens(i2c); + + flags = (msg->flags & I2C_M_IGNORE_NAK) ? REG_CTRL_ACK_IGNORE : 0; + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_ACK_IGNORE, flags); + + if (!(msg->flags & I2C_M_NOSTART)) + meson_i2c_do_start(i2c, msg); + + i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + meson_i2c_prepare_xfer(i2c); + meson_i2c_write_tokens(i2c); + reinit_completion(&i2c->done); + + /* Start the transfer */ + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, REG_CTRL_START); + + time_left = msecs_to_jiffies(I2C_TIMEOUT_MS); + time_left = wait_for_completion_timeout(&i2c->done, time_left); + + /* + * Protect access to i2c struct and registers from interrupt + * handlers triggered by a transfer terminated after the + * timeout period + */ + spin_lock_irqsave(&i2c->lock, flags); + + /* Abort any active operation */ + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0); + + if (!time_left) { + i2c->state = STATE_IDLE; + ret = -ETIMEDOUT; + } + + if (i2c->error) + ret = i2c->error; + + spin_unlock_irqrestore(&i2c->lock, flags); + + return ret; +} + +static int meson_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) +{ + struct meson_i2c *i2c = adap->algo_data; + int i, ret = 0, count = 0; + + clk_enable(i2c->clk); + meson_i2c_set_clk_div(i2c); + + for (i = 0; i < num; i++) { + ret = meson_i2c_xfer_msg(i2c, msgs + i, i == num - 1); + if (ret) + break; + count++; + } + + clk_disable(i2c->clk); + + return ret ? ret : count; +} + +static u32 meson_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm meson_i2c_algorithm = { + .master_xfer = meson_i2c_xfer, + .functionality = meson_i2c_func, +}; + +static int meson_i2c_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct meson_i2c *i2c; + struct resource *mem; + int ret = 0; + + i2c = devm_kzalloc(&pdev->dev, sizeof(struct meson_i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &i2c->frequency)) + i2c->frequency = DEFAULT_FREQ; + + i2c->dev = &pdev->dev; + platform_set_drvdata(pdev, i2c); + + spin_lock_init(&i2c->lock); + init_completion(&i2c->done); + + i2c->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(i2c->clk)) { + dev_err(&pdev->dev, "can't get device clock\n"); + return PTR_ERR(i2c->clk); + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + i2c->regs = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(i2c->regs)) + return PTR_ERR(i2c->regs); + + i2c->irq = platform_get_irq(pdev, 0); + if (i2c->irq < 0) { + dev_err(&pdev->dev, "can't find IRQ\n"); + return i2c->irq; + } + + ret = devm_request_irq(&pdev->dev, i2c->irq, meson_i2c_irq, + 0, dev_name(&pdev->dev), i2c); + if (ret < 0) { + dev_err(&pdev->dev, "can't request IRQ\n"); + return ret; + } + + ret = clk_prepare(i2c->clk); + if (ret < 0) { + dev_err(&pdev->dev, "can't prepare clock\n"); + return ret; + } + + strlcpy(i2c->adap.name, "Meson I2C adapter", + sizeof(i2c->adap.name)); + i2c->adap.owner = THIS_MODULE; + i2c->adap.algo = &meson_i2c_algorithm; + i2c->adap.dev.parent = &pdev->dev; + i2c->adap.dev.of_node = np; + i2c->adap.algo_data = i2c; + + /* + * A transfer is triggered when START bit changes from 0 to 1. + * Ensure that the bit is set to 0 after probe + */ + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0); + + ret = i2c_add_adapter(&i2c->adap); + if (ret < 0) { + dev_err(&pdev->dev, "can't register adapter\n"); + clk_unprepare(i2c->clk); + return ret; + } + + return 0; +} + +static int meson_i2c_remove(struct platform_device *pdev) +{ + struct meson_i2c *i2c = platform_get_drvdata(pdev); + + i2c_del_adapter(&i2c->adap); + clk_unprepare(i2c->clk); + + return 0; +} + +static const struct of_device_id meson_i2c_match[] = { + { .compatible = "amlogic,meson6-i2c" }, + { }, +}; + +static struct platform_driver meson_i2c_driver = { + .probe = meson_i2c_probe, + .remove = meson_i2c_remove, + .driver = { + .name = "meson-i2c", + .of_match_table = meson_i2c_match, + }, +}; + +module_platform_driver(meson_i2c_driver); + +MODULE_DESCRIPTION("Amlogic Meson I2C Bus driver"); +MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); +MODULE_LICENSE("GPL v2"); -- 1.9.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v3 2/3] i2c: add support for Amlogic Meson I2C controller 2014-11-13 19:32 ` Beniamino Galvani @ 2014-11-18 15:17 ` Wolfram Sang -1 siblings, 0 replies; 20+ messages in thread From: Wolfram Sang @ 2014-11-18 15:17 UTC (permalink / raw) To: Beniamino Galvani Cc: Carlo Caione, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, linux-i2c, linux-kernel, devicetree, linux-arm-kernel, Jerry Cao, Victor Wan [-- Attachment #1: Type: text/plain, Size: 236 bytes --] On Thu, Nov 13, 2014 at 08:32:02PM +0100, Beniamino Galvani wrote: > This is a driver for the I2C controller found in Amlogic Meson SoCs. > > Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> Applied to for-next, thanks! [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 2/3] i2c: add support for Amlogic Meson I2C controller @ 2014-11-18 15:17 ` Wolfram Sang 0 siblings, 0 replies; 20+ messages in thread From: Wolfram Sang @ 2014-11-18 15:17 UTC (permalink / raw) To: linux-arm-kernel On Thu, Nov 13, 2014 at 08:32:02PM +0100, Beniamino Galvani wrote: > This is a driver for the I2C controller found in Amlogic Meson SoCs. > > Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> Applied to for-next, thanks! -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141118/9fd16625/attachment.sig> ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 3/3] ARM: dts: meson: add I2C controller nodes 2014-11-13 19:32 ` Beniamino Galvani @ 2014-11-13 19:32 ` Beniamino Galvani -1 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-13 19:32 UTC (permalink / raw) To: Wolfram Sang Cc: Carlo Caione, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, linux-i2c, linux-kernel, devicetree, linux-arm-kernel, Jerry Cao, Victor Wan, Beniamino Galvani Add nodes for I2C controllers A,B,AO, which are available in both Meson6 and Meson8. Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> --- arch/arm/boot/dts/meson.dtsi | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm/boot/dts/meson.dtsi b/arch/arm/boot/dts/meson.dtsi index e6539ea..4f16aee 100644 --- a/arch/arm/boot/dts/meson.dtsi +++ b/arch/arm/boot/dts/meson.dtsi @@ -106,5 +106,35 @@ clocks = <&clk81>; status = "disabled"; }; + + i2c_AO: i2c@c8100500 { + compatible = "amlogic,meson6-i2c"; + reg = <0xc8100500 0x20>; + interrupts = <0 92 1>; + clocks = <&clk81>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c_A: i2c@c1108500 { + compatible = "amlogic,meson6-i2c"; + reg = <0xc1108500 0x20>; + interrupts = <0 21 1>; + clocks = <&clk81>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c_B: i2c@c11087c0 { + compatible = "amlogic,meson6-i2c"; + reg = <0xc11087c0 0x20>; + interrupts = <0 128 1>; + clocks = <&clk81>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; }; /* end of / */ -- 1.9.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 3/3] ARM: dts: meson: add I2C controller nodes @ 2014-11-13 19:32 ` Beniamino Galvani 0 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-13 19:32 UTC (permalink / raw) To: linux-arm-kernel Add nodes for I2C controllers A,B,AO, which are available in both Meson6 and Meson8. Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> --- arch/arm/boot/dts/meson.dtsi | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm/boot/dts/meson.dtsi b/arch/arm/boot/dts/meson.dtsi index e6539ea..4f16aee 100644 --- a/arch/arm/boot/dts/meson.dtsi +++ b/arch/arm/boot/dts/meson.dtsi @@ -106,5 +106,35 @@ clocks = <&clk81>; status = "disabled"; }; + + i2c_AO: i2c at c8100500 { + compatible = "amlogic,meson6-i2c"; + reg = <0xc8100500 0x20>; + interrupts = <0 92 1>; + clocks = <&clk81>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c_A: i2c at c1108500 { + compatible = "amlogic,meson6-i2c"; + reg = <0xc1108500 0x20>; + interrupts = <0 21 1>; + clocks = <&clk81>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c_B: i2c at c11087c0 { + compatible = "amlogic,meson6-i2c"; + reg = <0xc11087c0 0x20>; + interrupts = <0 128 1>; + clocks = <&clk81>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; }; /* end of / */ -- 1.9.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v3 3/3] ARM: dts: meson: add I2C controller nodes 2014-11-13 19:32 ` Beniamino Galvani @ 2014-11-18 15:19 ` Wolfram Sang -1 siblings, 0 replies; 20+ messages in thread From: Wolfram Sang @ 2014-11-18 15:19 UTC (permalink / raw) To: Beniamino Galvani Cc: Carlo Caione, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, linux-i2c, linux-kernel, devicetree, linux-arm-kernel, Jerry Cao, Victor Wan [-- Attachment #1: Type: text/plain, Size: 349 bytes --] On Thu, Nov 13, 2014 at 08:32:03PM +0100, Beniamino Galvani wrote: > Add nodes for I2C controllers A,B,AO, which are available in both > Meson6 and Meson8. > > Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> > --- I usually don't take DTS patches. They should go via arm-soc. Please say so if there are reasons I should take it. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 3/3] ARM: dts: meson: add I2C controller nodes @ 2014-11-18 15:19 ` Wolfram Sang 0 siblings, 0 replies; 20+ messages in thread From: Wolfram Sang @ 2014-11-18 15:19 UTC (permalink / raw) To: linux-arm-kernel On Thu, Nov 13, 2014 at 08:32:03PM +0100, Beniamino Galvani wrote: > Add nodes for I2C controllers A,B,AO, which are available in both > Meson6 and Meson8. > > Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> > --- I usually don't take DTS patches. They should go via arm-soc. Please say so if there are reasons I should take it. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141118/09cfab71/attachment.sig> ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v3 3/3] ARM: dts: meson: add I2C controller nodes 2014-11-18 15:19 ` Wolfram Sang @ 2014-11-18 15:29 ` Carlo Caione -1 siblings, 0 replies; 20+ messages in thread From: Carlo Caione @ 2014-11-18 15:29 UTC (permalink / raw) To: Wolfram Sang Cc: Beniamino Galvani, Carlo Caione, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, linux-i2c, linux-kernel, devicetree, linux-arm-kernel, Jerry Cao, Victor Wan On Tue, Nov 18, 2014 at 4:19 PM, Wolfram Sang <wsa@the-dreams.de> wrote: > On Thu, Nov 13, 2014 at 08:32:03PM +0100, Beniamino Galvani wrote: >> Add nodes for I2C controllers A,B,AO, which are available in both >> Meson6 and Meson8. >> >> Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> >> --- > > I usually don't take DTS patches. They should go via arm-soc. Please say > so if there are reasons I should take it. I'll take them. -- Carlo Caione ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 3/3] ARM: dts: meson: add I2C controller nodes @ 2014-11-18 15:29 ` Carlo Caione 0 siblings, 0 replies; 20+ messages in thread From: Carlo Caione @ 2014-11-18 15:29 UTC (permalink / raw) To: linux-arm-kernel On Tue, Nov 18, 2014 at 4:19 PM, Wolfram Sang <wsa@the-dreams.de> wrote: > On Thu, Nov 13, 2014 at 08:32:03PM +0100, Beniamino Galvani wrote: >> Add nodes for I2C controllers A,B,AO, which are available in both >> Meson6 and Meson8. >> >> Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> >> --- > > I usually don't take DTS patches. They should go via arm-soc. Please say > so if there are reasons I should take it. I'll take them. -- Carlo Caione ^ permalink raw reply [flat|nested] 20+ messages in thread
[parent not found: <CAOQ7t2Yw5h61xWf2MW11Zsz5_gnv==ihB7Swj=yqcYc=J166gw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [PATCH v3 3/3] ARM: dts: meson: add I2C controller nodes 2014-11-18 15:29 ` Carlo Caione (?) @ 2014-11-18 20:32 ` Beniamino Galvani -1 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-18 20:32 UTC (permalink / raw) To: Carlo Caione Cc: Wolfram Sang, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, devicetree, linux-arm-kernel, Jerry Cao, Victor Wan On Tue, Nov 18, 2014 at 04:29:13PM +0100, Carlo Caione wrote: > On Tue, Nov 18, 2014 at 4:19 PM, Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org> wrote: > > On Thu, Nov 13, 2014 at 08:32:03PM +0100, Beniamino Galvani wrote: > >> Add nodes for I2C controllers A,B,AO, which are available in both > >> Meson6 and Meson8. > >> > >> Signed-off-by: Beniamino Galvani <b.galvani-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > >> --- > > > > I usually don't take DTS patches. They should go via arm-soc. Please say > > so if there are reasons I should take it. > > I'll take them. Thanks! Beniamino ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v3 3/3] ARM: dts: meson: add I2C controller nodes @ 2014-11-18 20:32 ` Beniamino Galvani 0 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-18 20:32 UTC (permalink / raw) To: Carlo Caione Cc: Wolfram Sang, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely, linux-i2c, linux-kernel, devicetree, linux-arm-kernel, Jerry Cao, Victor Wan On Tue, Nov 18, 2014 at 04:29:13PM +0100, Carlo Caione wrote: > On Tue, Nov 18, 2014 at 4:19 PM, Wolfram Sang <wsa@the-dreams.de> wrote: > > On Thu, Nov 13, 2014 at 08:32:03PM +0100, Beniamino Galvani wrote: > >> Add nodes for I2C controllers A,B,AO, which are available in both > >> Meson6 and Meson8. > >> > >> Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> > >> --- > > > > I usually don't take DTS patches. They should go via arm-soc. Please say > > so if there are reasons I should take it. > > I'll take them. Thanks! Beniamino ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 3/3] ARM: dts: meson: add I2C controller nodes @ 2014-11-18 20:32 ` Beniamino Galvani 0 siblings, 0 replies; 20+ messages in thread From: Beniamino Galvani @ 2014-11-18 20:32 UTC (permalink / raw) To: linux-arm-kernel On Tue, Nov 18, 2014 at 04:29:13PM +0100, Carlo Caione wrote: > On Tue, Nov 18, 2014 at 4:19 PM, Wolfram Sang <wsa@the-dreams.de> wrote: > > On Thu, Nov 13, 2014 at 08:32:03PM +0100, Beniamino Galvani wrote: > >> Add nodes for I2C controllers A,B,AO, which are available in both > >> Meson6 and Meson8. > >> > >> Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> > >> --- > > > > I usually don't take DTS patches. They should go via arm-soc. Please say > > so if there are reasons I should take it. > > I'll take them. Thanks! Beniamino ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2014-11-18 20:34 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-13 19:32 [PATCH v3 0/3] i2c: add driver for Amlogic Meson I2C controller Beniamino Galvani
2014-11-13 19:32 ` Beniamino Galvani
2014-11-13 19:32 ` Beniamino Galvani
2014-11-13 19:32 ` [PATCH v3 1/3] i2c: meson: add device tree bindings documentation Beniamino Galvani
2014-11-13 19:32 ` Beniamino Galvani
2014-11-18 15:17 ` Wolfram Sang
2014-11-18 15:17 ` Wolfram Sang
2014-11-13 19:32 ` [PATCH v3 2/3] i2c: add support for Amlogic Meson I2C controller Beniamino Galvani
2014-11-13 19:32 ` Beniamino Galvani
2014-11-18 15:17 ` Wolfram Sang
2014-11-18 15:17 ` Wolfram Sang
2014-11-13 19:32 ` [PATCH v3 3/3] ARM: dts: meson: add I2C controller nodes Beniamino Galvani
2014-11-13 19:32 ` Beniamino Galvani
2014-11-18 15:19 ` Wolfram Sang
2014-11-18 15:19 ` Wolfram Sang
2014-11-18 15:29 ` Carlo Caione
2014-11-18 15:29 ` Carlo Caione
[not found] ` <CAOQ7t2Yw5h61xWf2MW11Zsz5_gnv==ihB7Swj=yqcYc=J166gw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-18 20:32 ` Beniamino Galvani
2014-11-18 20:32 ` Beniamino Galvani
2014-11-18 20:32 ` Beniamino Galvani
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.