From: Shawn Guo <shawnguo@kernel.org>
To: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-i2c@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Baoyou Xie <xie.baoyou@sanechips.com.cn>,
Xin Zhou <zhou.xin8@sanechips.com.cn>,
Baoyou Xie <baoyou.xie@linaro.org>
Subject: Re: [PATCH 2/2] i2c: zx2967: add i2c controller driver for ZTE's zx2967 family
Date: Tue, 20 Jun 2017 10:58:17 +0800 [thread overview]
Message-ID: <20170620025815.GA4818@x250> (raw)
In-Reply-To: <20170619193130.velebm7p3r5ggaos@ninjato>
Hi Wolfram,
Thanks for taking time help review.
On Mon, Jun 19, 2017 at 09:31:30PM +0200, Wolfram Sang wrote:
> Hi Shawn,
>
> On Sun, May 28, 2017 at 12:59:36PM +0800, Shawn Guo wrote:
> > From: Baoyou Xie <baoyou.xie@linaro.org>
> >
> > This patch adds i2c controller driver for ZTE's zx2967 family.
> >
> > Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> > Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> > Reviewed-by: Jun Nie <jun.nie@linaro.org>
> > Signed-off-by: Shawn Guo <shawnguo@kernel.org>
>
> What about this patch from the old series updating the MAINTAINERS entry?
> I think it is a good idea?
>
> http://patchwork.ozlabs.org/patch/731006/
Oh, yes, I should have mentioned it in the cover-letter. Instead of
changing MAINTAINERS file in different subsystem patch series, which may
introduce merge conflicts, we plan to update it with a separate patch
adding all driver entries that lands on mainline, and get it in through
arm-soc tree. Are you okay with that?
>
> > ---
> > drivers/i2c/busses/Kconfig | 9 +
> > drivers/i2c/busses/Makefile | 1 +
> > drivers/i2c/busses/i2c-zx2967.c | 610 ++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 620 insertions(+)
> > create mode 100644 drivers/i2c/busses/i2c-zx2967.c
> >
> > diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> > index 144cbadc7c72..f9f0ed61df2e 100644
> > --- a/drivers/i2c/busses/Kconfig
> > +++ b/drivers/i2c/busses/Kconfig
> > @@ -1258,4 +1258,13 @@ config I2C_OPAL
> > This driver can also be built as a module. If so, the module will be
> > called as i2c-opal.
> >
> > +config I2C_ZX2967
> > + tristate "ZTE ZX2967 I2C support"
> > + depends on ARCH_ZX
>
> || COMPILE_TEST?
Yeah, good suggestion.
>
> > + default y
> > + help
> > + Selecting this option will add ZX2967 I2C driver.
> > + This driver can also be built as a module. If so, the module will be
> > + called i2c-zx2967.
> > +
> > endmenu
>
> ...
>
> > +static int zx2967_i2c_reset_hardware(struct zx2967_i2c_info *zx_i2c)
> > +{
> > + u32 val;
> > + u32 clk_div;
> > + u32 status;
> > +
> > + val = I2C_MASTER | I2C_IRQ_MSK_ENABLE;
> > + zx2967_i2c_writel(zx_i2c, val, REG_CMD);
> > +
> > + clk_div = clk_get_rate(zx_i2c->clk) / zx_i2c->clk_freq - 1;
> > + zx2967_i2c_writel(zx_i2c, clk_div, REG_CLK_DIV_FS);
> > + zx2967_i2c_writel(zx_i2c, clk_div, REG_CLK_DIV_HS);
> > +
> > + zx2967_i2c_writel(zx_i2c, I2C_FIFO_MAX - 1, REG_WRCONF);
> > + zx2967_i2c_writel(zx_i2c, I2C_FIFO_MAX - 1, REG_RDCONF);
> > + zx2967_i2c_writel(zx_i2c, 1, REG_RDCONF);
> > +
> > + zx2967_i2c_flush_fifos(zx_i2c);
> > +
> > + status = zx2967_i2c_readl(zx_i2c, REG_STAT);
> > + if (status & I2C_SR_BUSY)
> > + return -EBUSY;
> > + if (status & (I2C_SR_EDEVICE | I2C_SR_EDATA))
> > + return -EIO;
>
> Is this the error handling (NACK, etc)? Then, it got lost now since we
> don't reset the hardware anymore after timeouts. But that would have
> meant that errors are only detected after the timeout was reached
> instead of instantly? If so, no good design. But maybe I misunderstand.
Hmm, this doesn't make too much sense now, since this reset function is
only being called at probe time to ensure the device is in a sane
initial state. There is no data transfer happening at this point at
all. I will drop these error bits checking from here, and add the error
handling in irq handler.
>
> > +
> > + enable_irq(zx_i2c->irq);
> > +
> > + return 0;
> > +}
> > +
> > +static void zx2967_i2c_isr_clr(struct zx2967_i2c_info *zx_i2c)
> > +{
> > + u32 status;
> > +
> > + status = zx2967_i2c_readl(zx_i2c, REG_STAT);
> > + status |= I2C_IRQ_ACK_CLEAR;
> > + zx2967_i2c_writel(zx_i2c, status, REG_STAT);
> > +}
> > +
> > +static irqreturn_t zx2967_i2c_isr(int irq, void *dev_id)
> > +{
> > + u32 status;
> > + struct zx2967_i2c_info *zx_i2c = (struct zx2967_i2c_info *)dev_id;
> > +
> > + status = zx2967_i2c_readl(zx_i2c, REG_STAT) & I2C_INT_MASK;
> > + zx2967_i2c_isr_clr(zx_i2c);
> > +
> > + if (status & I2C_ERROR_MASK)
> > + return IRQ_HANDLED;
>
> I would have expected the error handling here.
Yes, we should check error status here.
>
> > +
> > + if (status & I2C_TRANS_DONE)
> > + complete(&zx_i2c->complete);
> > +
> > + return IRQ_HANDLED;
> > +}
>
> ...
>
> > +static int zx2967_smbus_xfer_read(struct zx2967_i2c_info *zx_i2c, int size,
> > + union i2c_smbus_data *data)
> > +{
> > + unsigned long time_left;
> > + u8 buf[2];
> > + u32 val;
> > +
> > + reinit_completion(&zx_i2c->complete);
> > +
> > + val = zx2967_i2c_readl(zx_i2c, REG_CMD);
> > + val |= I2C_CMB_RW_EN;
> > + zx2967_i2c_writel(zx_i2c, val, REG_CMD);
> > +
> > + val = zx2967_i2c_readl(zx_i2c, REG_CMD);
> > + val |= I2C_START;
> > + zx2967_i2c_writel(zx_i2c, val, REG_CMD);
> > +
> > + time_left = wait_for_completion_timeout(&zx_i2c->complete,
> > + I2C_TIMEOUT);
> > + if (time_left == 0)
> > + return -ETIMEDOUT;
> > +
> > + switch (size) {
> > + case I2C_SMBUS_BYTE:
> > + case I2C_SMBUS_BYTE_DATA:
> > + val = zx2967_i2c_readl(zx_i2c, REG_DATA);
> > + data->byte = val;
> > + break;
> > + case I2C_SMBUS_WORD_DATA:
> > + case I2C_SMBUS_PROC_CALL:
> > + buf[0] = zx2967_i2c_readl(zx_i2c, REG_DATA);
> > + buf[1] = zx2967_i2c_readl(zx_i2c, REG_DATA);
> > + data->word = (buf[0] << 8) | buf[1];
> > + break;
> > + default:
> > + dev_warn(DEV(zx_i2c), "Unsupported transaction %d\n", size);
>
> I wouldn't print something here. If an unsupported SMBus transfer is
> used, your driver will fall back to emulate them via I2C. No need to
> print a warning then.
Okay, will drop it.
>
> > + return -EOPNOTSUPP;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +#define ZX2967_I2C_FUNCS (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
> > + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
> > + I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL | \
> > + I2C_FUNC_I2C | I2C_FUNC_SMBUS_I2C_BLOCK)
> > +
> > +static u32 zx2967_i2c_func(struct i2c_adapter *adap)
> > +{
> > + return ZX2967_I2C_FUNCS;
> > +}
>
> No strong opinion but I think we can return that value directly without
> a define.
I do not have a strong opinion either, but since you ask, I will do what
you are asking here.
>
> ...
>
> > + ret = i2c_add_numbered_adapter(&zx_i2c->adap);
> > + if (ret) {
> > + dev_err(&pdev->dev, "failed to add zx2967 i2c adapter\n");
>
> Drop the message, the core will do the reporting.
Okay, will do.
>
> > + goto err_clk_unprepare;
> > + }
>
> How was this driver tested BTW?
The driver is being used to access an Audio codec on the I2C bus.
Shawn
WARNING: multiple messages have this Message-ID (diff)
From: shawnguo@kernel.org (Shawn Guo)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/2] i2c: zx2967: add i2c controller driver for ZTE's zx2967 family
Date: Tue, 20 Jun 2017 10:58:17 +0800 [thread overview]
Message-ID: <20170620025815.GA4818@x250> (raw)
In-Reply-To: <20170619193130.velebm7p3r5ggaos@ninjato>
Hi Wolfram,
Thanks for taking time help review.
On Mon, Jun 19, 2017 at 09:31:30PM +0200, Wolfram Sang wrote:
> Hi Shawn,
>
> On Sun, May 28, 2017 at 12:59:36PM +0800, Shawn Guo wrote:
> > From: Baoyou Xie <baoyou.xie@linaro.org>
> >
> > This patch adds i2c controller driver for ZTE's zx2967 family.
> >
> > Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> > Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> > Reviewed-by: Jun Nie <jun.nie@linaro.org>
> > Signed-off-by: Shawn Guo <shawnguo@kernel.org>
>
> What about this patch from the old series updating the MAINTAINERS entry?
> I think it is a good idea?
>
> http://patchwork.ozlabs.org/patch/731006/
Oh, yes, I should have mentioned it in the cover-letter. Instead of
changing MAINTAINERS file in different subsystem patch series, which may
introduce merge conflicts, we plan to update it with a separate patch
adding all driver entries that lands on mainline, and get it in through
arm-soc tree. Are you okay with that?
>
> > ---
> > drivers/i2c/busses/Kconfig | 9 +
> > drivers/i2c/busses/Makefile | 1 +
> > drivers/i2c/busses/i2c-zx2967.c | 610 ++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 620 insertions(+)
> > create mode 100644 drivers/i2c/busses/i2c-zx2967.c
> >
> > diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> > index 144cbadc7c72..f9f0ed61df2e 100644
> > --- a/drivers/i2c/busses/Kconfig
> > +++ b/drivers/i2c/busses/Kconfig
> > @@ -1258,4 +1258,13 @@ config I2C_OPAL
> > This driver can also be built as a module. If so, the module will be
> > called as i2c-opal.
> >
> > +config I2C_ZX2967
> > + tristate "ZTE ZX2967 I2C support"
> > + depends on ARCH_ZX
>
> || COMPILE_TEST?
Yeah, good suggestion.
>
> > + default y
> > + help
> > + Selecting this option will add ZX2967 I2C driver.
> > + This driver can also be built as a module. If so, the module will be
> > + called i2c-zx2967.
> > +
> > endmenu
>
> ...
>
> > +static int zx2967_i2c_reset_hardware(struct zx2967_i2c_info *zx_i2c)
> > +{
> > + u32 val;
> > + u32 clk_div;
> > + u32 status;
> > +
> > + val = I2C_MASTER | I2C_IRQ_MSK_ENABLE;
> > + zx2967_i2c_writel(zx_i2c, val, REG_CMD);
> > +
> > + clk_div = clk_get_rate(zx_i2c->clk) / zx_i2c->clk_freq - 1;
> > + zx2967_i2c_writel(zx_i2c, clk_div, REG_CLK_DIV_FS);
> > + zx2967_i2c_writel(zx_i2c, clk_div, REG_CLK_DIV_HS);
> > +
> > + zx2967_i2c_writel(zx_i2c, I2C_FIFO_MAX - 1, REG_WRCONF);
> > + zx2967_i2c_writel(zx_i2c, I2C_FIFO_MAX - 1, REG_RDCONF);
> > + zx2967_i2c_writel(zx_i2c, 1, REG_RDCONF);
> > +
> > + zx2967_i2c_flush_fifos(zx_i2c);
> > +
> > + status = zx2967_i2c_readl(zx_i2c, REG_STAT);
> > + if (status & I2C_SR_BUSY)
> > + return -EBUSY;
> > + if (status & (I2C_SR_EDEVICE | I2C_SR_EDATA))
> > + return -EIO;
>
> Is this the error handling (NACK, etc)? Then, it got lost now since we
> don't reset the hardware anymore after timeouts. But that would have
> meant that errors are only detected after the timeout was reached
> instead of instantly? If so, no good design. But maybe I misunderstand.
Hmm, this doesn't make too much sense now, since this reset function is
only being called at probe time to ensure the device is in a sane
initial state. There is no data transfer happening at this point at
all. I will drop these error bits checking from here, and add the error
handling in irq handler.
>
> > +
> > + enable_irq(zx_i2c->irq);
> > +
> > + return 0;
> > +}
> > +
> > +static void zx2967_i2c_isr_clr(struct zx2967_i2c_info *zx_i2c)
> > +{
> > + u32 status;
> > +
> > + status = zx2967_i2c_readl(zx_i2c, REG_STAT);
> > + status |= I2C_IRQ_ACK_CLEAR;
> > + zx2967_i2c_writel(zx_i2c, status, REG_STAT);
> > +}
> > +
> > +static irqreturn_t zx2967_i2c_isr(int irq, void *dev_id)
> > +{
> > + u32 status;
> > + struct zx2967_i2c_info *zx_i2c = (struct zx2967_i2c_info *)dev_id;
> > +
> > + status = zx2967_i2c_readl(zx_i2c, REG_STAT) & I2C_INT_MASK;
> > + zx2967_i2c_isr_clr(zx_i2c);
> > +
> > + if (status & I2C_ERROR_MASK)
> > + return IRQ_HANDLED;
>
> I would have expected the error handling here.
Yes, we should check error status here.
>
> > +
> > + if (status & I2C_TRANS_DONE)
> > + complete(&zx_i2c->complete);
> > +
> > + return IRQ_HANDLED;
> > +}
>
> ...
>
> > +static int zx2967_smbus_xfer_read(struct zx2967_i2c_info *zx_i2c, int size,
> > + union i2c_smbus_data *data)
> > +{
> > + unsigned long time_left;
> > + u8 buf[2];
> > + u32 val;
> > +
> > + reinit_completion(&zx_i2c->complete);
> > +
> > + val = zx2967_i2c_readl(zx_i2c, REG_CMD);
> > + val |= I2C_CMB_RW_EN;
> > + zx2967_i2c_writel(zx_i2c, val, REG_CMD);
> > +
> > + val = zx2967_i2c_readl(zx_i2c, REG_CMD);
> > + val |= I2C_START;
> > + zx2967_i2c_writel(zx_i2c, val, REG_CMD);
> > +
> > + time_left = wait_for_completion_timeout(&zx_i2c->complete,
> > + I2C_TIMEOUT);
> > + if (time_left == 0)
> > + return -ETIMEDOUT;
> > +
> > + switch (size) {
> > + case I2C_SMBUS_BYTE:
> > + case I2C_SMBUS_BYTE_DATA:
> > + val = zx2967_i2c_readl(zx_i2c, REG_DATA);
> > + data->byte = val;
> > + break;
> > + case I2C_SMBUS_WORD_DATA:
> > + case I2C_SMBUS_PROC_CALL:
> > + buf[0] = zx2967_i2c_readl(zx_i2c, REG_DATA);
> > + buf[1] = zx2967_i2c_readl(zx_i2c, REG_DATA);
> > + data->word = (buf[0] << 8) | buf[1];
> > + break;
> > + default:
> > + dev_warn(DEV(zx_i2c), "Unsupported transaction %d\n", size);
>
> I wouldn't print something here. If an unsupported SMBus transfer is
> used, your driver will fall back to emulate them via I2C. No need to
> print a warning then.
Okay, will drop it.
>
> > + return -EOPNOTSUPP;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +#define ZX2967_I2C_FUNCS (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
> > + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
> > + I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL | \
> > + I2C_FUNC_I2C | I2C_FUNC_SMBUS_I2C_BLOCK)
> > +
> > +static u32 zx2967_i2c_func(struct i2c_adapter *adap)
> > +{
> > + return ZX2967_I2C_FUNCS;
> > +}
>
> No strong opinion but I think we can return that value directly without
> a define.
I do not have a strong opinion either, but since you ask, I will do what
you are asking here.
>
> ...
>
> > + ret = i2c_add_numbered_adapter(&zx_i2c->adap);
> > + if (ret) {
> > + dev_err(&pdev->dev, "failed to add zx2967 i2c adapter\n");
>
> Drop the message, the core will do the reporting.
Okay, will do.
>
> > + goto err_clk_unprepare;
> > + }
>
> How was this driver tested BTW?
The driver is being used to access an Audio codec on the I2C bus.
Shawn
next prev parent reply other threads:[~2017-06-20 2:58 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-28 4:59 [PATCH 0/2] Add I2C driver for ZTE ZX2967 family SoCs Shawn Guo
2017-05-28 4:59 ` Shawn Guo
2017-05-28 4:59 ` [PATCH 1/2] dt: bindings: add documentation for zx2967 family i2c controller Shawn Guo
2017-05-28 4:59 ` Shawn Guo
2017-05-28 4:59 ` [PATCH 2/2] i2c: zx2967: add i2c controller driver for ZTE's zx2967 family Shawn Guo
2017-05-28 4:59 ` Shawn Guo
2017-06-19 19:31 ` Wolfram Sang
2017-06-19 19:31 ` Wolfram Sang
2017-06-20 2:58 ` Shawn Guo [this message]
2017-06-20 2:58 ` Shawn Guo
2017-06-20 7:41 ` Wolfram Sang
2017-06-20 7:41 ` Wolfram Sang
2017-06-21 16:06 ` Shawn Guo
2017-06-21 16:06 ` Shawn Guo
2017-06-22 7:48 ` Shawn Guo
2017-06-22 7:48 ` Shawn Guo
2017-06-22 8:07 ` Wolfram Sang
2017-06-22 8:07 ` Wolfram Sang
2017-06-22 12:25 ` Shawn Guo
2017-06-22 12:25 ` Shawn Guo
2017-06-22 13:22 ` Wolfram Sang
2017-06-22 13:22 ` Wolfram Sang
2017-06-10 14:32 ` [PATCH 0/2] Add I2C driver for ZTE ZX2967 family SoCs Shawn Guo
2017-06-10 14:32 ` Shawn Guo
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=20170620025815.GA4818@x250 \
--to=shawnguo@kernel.org \
--cc=baoyou.xie@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-i2c@vger.kernel.org \
--cc=wsa@the-dreams.de \
--cc=xie.baoyou@sanechips.com.cn \
--cc=zhou.xin8@sanechips.com.cn \
/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.