From: Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org>
To: Brendan Higgins <brendanhiggins-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
mark.rutland-5wv7dgnIgG8@public.gmane.org,
tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org,
jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org,
marc.zyngier-5wv7dgnIgG8@public.gmane.org,
joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org,
vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org,
mouse-Pma6HLj0uuo@public.gmane.org,
clg-Bxea+6Xhats@public.gmane.org,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org,
ryan_chen-SAlXDmAnmOAqDJ6do+/SaQ@public.gmane.org,
linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
openbmc-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Subject: Re: [PATCH v10 4/5] i2c: aspeed: added driver for Aspeed I2C
Date: Mon, 19 Jun 2017 16:13:22 +0200 [thread overview]
Message-ID: <20170619141322.devvmcbjaeq4jnv5@ninjato> (raw)
In-Reply-To: <20170603012952.2192-5-brendanhiggins-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 5152 bytes --]
Hi Brendan,
here is my review. Only minor stuff, no real show-stopper.
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index 144cbadc7c72..280f84a0d7d1 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -326,6 +326,16 @@ config I2C_POWERMAC
>
> comment "I2C system bus drivers (mostly embedded / system-on-chip)"
>
> +config I2C_ASPEED
> + tristate "Aspeed I2C Controller"
> + depends on ARCH_ASPEED
|| COMPILE_TEST?
> + help
> + If you say yes to this option, support will be included for the
> + Aspeed I2C controller.
> +
> + This driver can also be built as a module. If so, the module
> + will be called i2c-aspeed.
> +
> config I2C_AT91
> tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
> depends on ARCH_AT91
> +struct aspeed_i2c_bus {
> + struct i2c_adapter adap;
> + struct device *dev;
> + void __iomem *base;
> + /* Synchronizes I/O mem access to base. */
> + spinlock_t lock;
> + struct completion cmd_complete;
> + int irq;
'irq' not really needed, I'd think.
> + unsigned long parent_clk_frequency;
> + u32 bus_frequency;
> + /* Transaction state. */
> + enum aspeed_i2c_master_state master_state;
> + struct i2c_msg *msgs;
> + size_t buf_index;
> + size_t msgs_index;
> + size_t msgs_count;
> + bool send_stop;
> + int cmd_err;
> + /* Protected only by i2c_lock_bus */
> + int master_xfer_result;
> +};
...
> +static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> +{
> + unsigned long time_left, flags;
> + int ret = 0;
> + u32 command;
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + command = readl(bus->base + ASPEED_I2C_CMD_REG);
> +
> + if (command & ASPEED_I2CD_SDA_LINE_STS) {
> + /* Bus is idle: no recovery needed. */
> + if (command & ASPEED_I2CD_SCL_LINE_STS)
> + goto out;
> + dev_dbg(bus->dev, "bus hung (state %x), attempting recovery\n",
> + command);
> +
> + reinit_completion(&bus->cmd_complete);
> + writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + time_left = wait_for_completion_timeout(
> + &bus->cmd_complete, bus->adap.timeout);
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + if (time_left == 0)
> + goto reset_out;
> + else if (bus->cmd_err)
> + goto reset_out;
> + /* Recovery failed. */
> + else if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
> + ASPEED_I2CD_SCL_LINE_STS))
> + goto reset_out;
> + /* Bus error. */
> + } else {
> + dev_dbg(bus->dev, "bus hung (state %x), attempting recovery\n",
> + command);
Same dbg message as in the condition? Move it out of the 'if'?
> +
> + reinit_completion(&bus->cmd_complete);
> + writel(ASPEED_I2CD_BUS_RECOVER_CMD,
> + bus->base + ASPEED_I2C_CMD_REG);
Out of interest: What does the RECOVER_CMD do?
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + time_left = wait_for_completion_timeout(
> + &bus->cmd_complete, bus->adap.timeout);
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + if (time_left == 0)
> + goto reset_out;
> + else if (bus->cmd_err)
> + goto reset_out;
> + /* Recovery failed. */
> + else if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
> + ASPEED_I2CD_SDA_LINE_STS))
> + goto reset_out;
> + }
> +
> +out:
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + return ret;
> +
> +reset_out:
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + return aspeed_i2c_reset(bus);
> +}
...
> + case ASPEED_I2C_MASTER_INACTIVE:
> + dev_err(bus->dev,
> + "master received interrupt 0x%08x, but is inactive",
> + irq_status);
> + bus->cmd_err = -EIO;
> + /* Do not STOP as we should be inactive. */
> + goto out_complete;
> + default:
> + WARN(1, "unknown master state\n");
> + bus->master_state = ASPEED_I2C_MASTER_INACTIVE;
> + bus->cmd_err = -EIO;
> + goto out_complete;
> + }
> +error_and_stop:
> + bus->cmd_err = -EIO;
> + aspeed_i2c_do_stop(bus);
> + goto out_no_complete;
> +out_complete:
> + bus->msgs = NULL;
> + if (bus->cmd_err)
> + bus->master_xfer_result = bus->cmd_err;
> + else
> + bus->master_xfer_result = bus->msgs_index + 1;
> + complete(&bus->cmd_complete);
> +out_no_complete:
> + if (irq_status != status_ack)
> + dev_err(bus->dev,
> + "irq handled != irq. expected 0x%08x, but was 0x%08x\n",
> + irq_status, status_ack);
> + spin_unlock(&bus->lock);
> + return !!irq_status;
> +}
You return in the interrupt handler -EIO always in case of errors. Can
you check Documentation/i2c/fault-codes and see if you can follow those
guidelines? Especially ENXIO on NACK and EAGAIN...
> +
> +static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
> +{
> + struct aspeed_i2c_bus *bus = dev_id;
> +
> + if (aspeed_i2c_master_irq(bus))
> + return IRQ_HANDLED;
> + else
> + return IRQ_NONE;
Ternary operator? Your choice, though...
And one more question: Why do you use adapter->algo_data instead of
i2c_{get|set}_adapdata?
Kind regards,
Wolfram
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
WARNING: multiple messages have this Message-ID (diff)
From: Wolfram Sang <wsa@the-dreams.de>
To: Brendan Higgins <brendanhiggins@google.com>
Cc: robh+dt@kernel.org, mark.rutland@arm.com, tglx@linutronix.de,
jason@lakedaemon.net, marc.zyngier@arm.com, joel@jms.id.au,
vz@mleia.com, mouse@mayc.ru, clg@kaod.org,
benh@kernel.crashing.org, ryan_chen@aspeedtech.com,
linux-i2c@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, openbmc@lists.ozlabs.org
Subject: Re: [PATCH v10 4/5] i2c: aspeed: added driver for Aspeed I2C
Date: Mon, 19 Jun 2017 16:13:22 +0200 [thread overview]
Message-ID: <20170619141322.devvmcbjaeq4jnv5@ninjato> (raw)
In-Reply-To: <20170603012952.2192-5-brendanhiggins@google.com>
[-- Attachment #1: Type: text/plain, Size: 5152 bytes --]
Hi Brendan,
here is my review. Only minor stuff, no real show-stopper.
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index 144cbadc7c72..280f84a0d7d1 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -326,6 +326,16 @@ config I2C_POWERMAC
>
> comment "I2C system bus drivers (mostly embedded / system-on-chip)"
>
> +config I2C_ASPEED
> + tristate "Aspeed I2C Controller"
> + depends on ARCH_ASPEED
|| COMPILE_TEST?
> + help
> + If you say yes to this option, support will be included for the
> + Aspeed I2C controller.
> +
> + This driver can also be built as a module. If so, the module
> + will be called i2c-aspeed.
> +
> config I2C_AT91
> tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
> depends on ARCH_AT91
> +struct aspeed_i2c_bus {
> + struct i2c_adapter adap;
> + struct device *dev;
> + void __iomem *base;
> + /* Synchronizes I/O mem access to base. */
> + spinlock_t lock;
> + struct completion cmd_complete;
> + int irq;
'irq' not really needed, I'd think.
> + unsigned long parent_clk_frequency;
> + u32 bus_frequency;
> + /* Transaction state. */
> + enum aspeed_i2c_master_state master_state;
> + struct i2c_msg *msgs;
> + size_t buf_index;
> + size_t msgs_index;
> + size_t msgs_count;
> + bool send_stop;
> + int cmd_err;
> + /* Protected only by i2c_lock_bus */
> + int master_xfer_result;
> +};
...
> +static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> +{
> + unsigned long time_left, flags;
> + int ret = 0;
> + u32 command;
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + command = readl(bus->base + ASPEED_I2C_CMD_REG);
> +
> + if (command & ASPEED_I2CD_SDA_LINE_STS) {
> + /* Bus is idle: no recovery needed. */
> + if (command & ASPEED_I2CD_SCL_LINE_STS)
> + goto out;
> + dev_dbg(bus->dev, "bus hung (state %x), attempting recovery\n",
> + command);
> +
> + reinit_completion(&bus->cmd_complete);
> + writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + time_left = wait_for_completion_timeout(
> + &bus->cmd_complete, bus->adap.timeout);
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + if (time_left == 0)
> + goto reset_out;
> + else if (bus->cmd_err)
> + goto reset_out;
> + /* Recovery failed. */
> + else if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
> + ASPEED_I2CD_SCL_LINE_STS))
> + goto reset_out;
> + /* Bus error. */
> + } else {
> + dev_dbg(bus->dev, "bus hung (state %x), attempting recovery\n",
> + command);
Same dbg message as in the condition? Move it out of the 'if'?
> +
> + reinit_completion(&bus->cmd_complete);
> + writel(ASPEED_I2CD_BUS_RECOVER_CMD,
> + bus->base + ASPEED_I2C_CMD_REG);
Out of interest: What does the RECOVER_CMD do?
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + time_left = wait_for_completion_timeout(
> + &bus->cmd_complete, bus->adap.timeout);
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + if (time_left == 0)
> + goto reset_out;
> + else if (bus->cmd_err)
> + goto reset_out;
> + /* Recovery failed. */
> + else if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
> + ASPEED_I2CD_SDA_LINE_STS))
> + goto reset_out;
> + }
> +
> +out:
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + return ret;
> +
> +reset_out:
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + return aspeed_i2c_reset(bus);
> +}
...
> + case ASPEED_I2C_MASTER_INACTIVE:
> + dev_err(bus->dev,
> + "master received interrupt 0x%08x, but is inactive",
> + irq_status);
> + bus->cmd_err = -EIO;
> + /* Do not STOP as we should be inactive. */
> + goto out_complete;
> + default:
> + WARN(1, "unknown master state\n");
> + bus->master_state = ASPEED_I2C_MASTER_INACTIVE;
> + bus->cmd_err = -EIO;
> + goto out_complete;
> + }
> +error_and_stop:
> + bus->cmd_err = -EIO;
> + aspeed_i2c_do_stop(bus);
> + goto out_no_complete;
> +out_complete:
> + bus->msgs = NULL;
> + if (bus->cmd_err)
> + bus->master_xfer_result = bus->cmd_err;
> + else
> + bus->master_xfer_result = bus->msgs_index + 1;
> + complete(&bus->cmd_complete);
> +out_no_complete:
> + if (irq_status != status_ack)
> + dev_err(bus->dev,
> + "irq handled != irq. expected 0x%08x, but was 0x%08x\n",
> + irq_status, status_ack);
> + spin_unlock(&bus->lock);
> + return !!irq_status;
> +}
You return in the interrupt handler -EIO always in case of errors. Can
you check Documentation/i2c/fault-codes and see if you can follow those
guidelines? Especially ENXIO on NACK and EAGAIN...
> +
> +static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
> +{
> + struct aspeed_i2c_bus *bus = dev_id;
> +
> + if (aspeed_i2c_master_irq(bus))
> + return IRQ_HANDLED;
> + else
> + return IRQ_NONE;
Ternary operator? Your choice, though...
And one more question: Why do you use adapter->algo_data instead of
i2c_{get|set}_adapdata?
Kind regards,
Wolfram
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2017-06-19 14:13 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-03 1:29 [PATCH v10 0/5] i2c: aspeed: added driver for Aspeed I2C Brendan Higgins
2017-06-03 1:29 ` [PATCH v10 1/5] irqchip/aspeed-i2c-ic: binding docs for Aspeed I2C Interrupt Controller Brendan Higgins
2017-06-05 6:25 ` Joel Stanley
2017-06-07 11:31 ` Marc Zyngier
2017-06-03 1:29 ` [PATCH v10 2/5] irqchip/aspeed-i2c-ic: Add I2C IRQ controller for Aspeed Brendan Higgins
2017-06-05 4:56 ` Andrew Jeffery
2017-06-03 1:29 ` [PATCH v10 3/5] i2c: aspeed: added documentation for Aspeed I2C driver Brendan Higgins
2017-06-05 4:40 ` Joel Stanley
2017-06-03 1:29 ` [PATCH v10 4/5] i2c: aspeed: added driver for Aspeed I2C Brendan Higgins
[not found] ` <20170603012952.2192-5-brendanhiggins-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
2017-06-05 4:40 ` Joel Stanley
2017-06-05 4:40 ` Joel Stanley
2017-06-19 14:13 ` Wolfram Sang [this message]
2017-06-19 14:13 ` Wolfram Sang
2017-06-19 14:21 ` Wolfram Sang
2017-06-20 0:58 ` Brendan Higgins
2017-06-20 0:58 ` Brendan Higgins
2017-06-20 7:49 ` Wolfram Sang
2017-06-20 4:02 ` Brendan Higgins
2017-06-20 4:02 ` Brendan Higgins
2017-06-05 5:02 ` Andrew Jeffery
[not found] ` <1496638941.8159.20.camel-zrmu5oMJ5Fs@public.gmane.org>
2017-06-15 23:42 ` Brendan Higgins
2017-06-15 23:42 ` Brendan Higgins
2017-06-03 1:29 ` [PATCH v10 5/5] i2c: aspeed: added slave support for Aspeed I2C driver Brendan Higgins
2017-06-07 6:57 ` Joel Stanley
2017-06-19 14:14 ` Wolfram Sang
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=20170619141322.devvmcbjaeq4jnv5@ninjato \
--to=wsa-z923lk4zbo2bacvfa/9k2g@public.gmane.org \
--cc=benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org \
--cc=brendanhiggins-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
--cc=clg-Bxea+6Xhats@public.gmane.org \
--cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org \
--cc=joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org \
--cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=marc.zyngier-5wv7dgnIgG8@public.gmane.org \
--cc=mark.rutland-5wv7dgnIgG8@public.gmane.org \
--cc=mouse-Pma6HLj0uuo@public.gmane.org \
--cc=openbmc-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org \
--cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=ryan_chen-SAlXDmAnmOAqDJ6do+/SaQ@public.gmane.org \
--cc=tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org \
--cc=vz-ChpfBGZJDbMAvxtiuMwx3w@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.