All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org>
To: Zhangfei Gao <zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>,
	haifeng.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
	jchxue-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Wei Yan <sledge.yanwei-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Subject: Re: [PATCH resend 2/2] i2c: hix5hd2: add i2c controller driver
Date: Fri, 19 Sep 2014 19:18:30 +0200	[thread overview]
Message-ID: <20140919171829.GB2874@katana> (raw)
In-Reply-To: <1409030722-30709-3-git-send-email-zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Hi,

thanks for the submission.

> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-hix5hd2.c
> @@ -0,0 +1,573 @@
> +/*
> + * Copyright (c) 2014 Linaro Ltd.
> + * Copyright (c) 2014 Hisilicon Limited.
> + *
> + * 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
> + * publishhed by the Free Software Foundation.

"publishhed"

> + *
> + * Now only support 7 bit address.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>

I think there should be at least of.h, too.

> +struct hix5hd2_i2c {
> +	struct i2c_adapter adap;
> +	struct i2c_msg	*msg;
> +	unsigned int msg_ptr;	/* msg index */

Comment seems wrong. It looks to me as the msg buffer index. If so, the
variable name is also confusing.

> +	unsigned int len;	/* msg length */
> +	int stop;
> +	struct completion msg_complete;
> +
> +	unsigned int irq;

That can be a local variable.

> +	void __iomem *regs;
> +	struct clk *clk;
> +	struct device *dev;
> +	spinlock_t lock;	/* IRQ synchronization */
> +
> +	int err;
> +	enum hix5hd2_i2c_state state;
> +	enum hix5hd2_i2c_speed speed_mode;

Where is this needed?

> +
> +	/* Controller frequency */
> +	unsigned int s_clock;
> +};
> +
> +static void hix5hd2_i2c_drv_setrate(struct hix5hd2_i2c *i2c)
> +{
> +	u32 rate, val;
> +	u32 sclh, scll, sysclock;
> +
> +	/* close all i2c interrupt */
> +	val = readl_relaxed(i2c->regs + HIX5I2C_CTRL);
> +	writel_relaxed(val & (~I2C_UNMASK_TOTAL), i2c->regs + HIX5I2C_CTRL);
> +
> +	rate = i2c->s_clock;
> +	sysclock = clk_get_rate(i2c->clk);
> +	sclh = (sysclock / (rate * 2)) / 2 - 1;
> +	writel_relaxed(sclh, i2c->regs + HIX5I2C_SCL_H);
> +	scll = (sysclock / (rate * 2)) / 2 - 1;

scll and sclh use the same formula? Have you measured the setup
frequency with a scope?

> +	writel_relaxed(scll, i2c->regs + HIX5I2C_SCL_L);
> +
> +	/* restore original interrupt*/
> +	writel_relaxed(val, i2c->regs + HIX5I2C_CTRL);
> +
> +	dev_dbg(i2c->dev, "%s: sysclock=%d, rate=%d, sclh=%d, scll=%d\n",
> +		__func__, sysclock, rate, sclh, scll);
> +}
> +
> +static void hix5hd2_rw_over(struct hix5hd2_i2c *i2c)
> +{
> +	if (HIX5I2C_STAT_SND_STOP == i2c->state)

To be honest, I don't like having the constant on the left side. It
is far easier to read if they are on the right side. Plus, we have gcc
warnings to prevent the "=" and "==" mistake. Please switch them around
in this driver.

> +		dev_dbg(i2c->dev, "%s: rw and send stop over\n", __func__);
> +	else
> +		dev_dbg(i2c->dev, "%s: have not data to send\n", __func__);
> +
> +	i2c->state = HIX5I2C_STAT_RW_SUCCESS;
> +	i2c->err = 0;
> +}
> +

...

> +	/* handle error */
> +	if (int_status & I2C_ARBITRATE_INTR) {
> +		/*Bus error */

Space missing in front of "Bus". If this is an arbitration lost error,
then please use -EAGAIN. Check Documentation/i2c/fault-codes for the
convention.

> +		dev_dbg(i2c->dev, "ARB bus loss\n");
> +		i2c->err = -ENXIO;
> +		i2c->state = HIX5I2C_STAT_RW_ERR;
> +		goto stop;
> +	} else if (int_status & I2C_ACK_INTR) {
> +		/* ack error */
> +		dev_dbg(i2c->dev, "No ACK from device\n");
> +		i2c->err = -ENXIO;
> +		i2c->state = HIX5I2C_STAT_RW_ERR;
> +		goto stop;
> +	}
> +
> +static void hix5hd2_i2c_message_start(struct hix5hd2_i2c *i2c, int stop)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&i2c->lock, flags);
> +	hix5hd2_i2c_clr_all_irq(i2c);
> +	hix5hd2_i2c_enable_irq(i2c);
> +
> +	if (i2c->msg->flags & I2C_M_RD)
> +		writel_relaxed(i2c->msg->addr | HIX5I2C_READ_OPERATION,
> +			       i2c->regs + HIX5I2C_TXR);
> +	else
> +		writel_relaxed(i2c->msg->addr & HIX5I2C_WRITE_OPERATION,
> +			       i2c->regs + HIX5I2C_TXR);

??? Does this really work? i2c->msg->addr should be left shifted by 1?

> +
> +	writel_relaxed(I2C_WRITE | I2C_START, i2c->regs + HIX5I2C_COM);
> +	spin_unlock_irqrestore(&i2c->lock, flags);
> +}
> +
> +static int hix5hd2_i2c_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct hix5hd2_i2c *i2c;
> +	struct resource *mem;
> +	unsigned int op_clock;
> +	int ret;
> +
> +	i2c = devm_kzalloc(&pdev->dev, sizeof(struct hix5hd2_i2c), GFP_KERNEL);
> +	if (!i2c)
> +		return -ENOMEM;
> +
> +	if (of_property_read_u32(np, "clock-frequency", &op_clock)) {
> +		/* use default value */
> +		i2c->speed_mode = HIX5I2C_HIG_SPD;
> +		i2c->s_clock = HIX5I2C_HS_TX_CLOCK;

Please use 100kHz as the default. This is the speed devices should
support. 400kHz is optional. And I think 100000 is easier to read than a
define.

> +	} else {
> +		if (op_clock >= HIX5I2C_HS_TX_CLOCK) {
> +			i2c->speed_mode = HIX5I2C_HIG_SPD;
> +			i2c->s_clock = HIX5I2C_HS_TX_CLOCK;

So, if the speed is bigger than 400kHz, it will be capped down to
400kHz? Is that true? Then, the user should be informed about that.

> +		} else {
> +			i2c->speed_mode = HIX5I2C_NORMAL_SPD;
> +			i2c->s_clock = op_clock;
> +		}
> +	}
> +

...

> +	i2c->adap.owner   = THIS_MODULE;
> +	i2c->adap.algo	  = &hix5hd2_i2c_algorithm;

Single space as indentation.

Thanks,

   Wolfram

WARNING: multiple messages have this Message-ID (diff)
From: wsa@the-dreams.de (Wolfram Sang)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH resend 2/2] i2c: hix5hd2: add i2c controller driver
Date: Fri, 19 Sep 2014 19:18:30 +0200	[thread overview]
Message-ID: <20140919171829.GB2874@katana> (raw)
In-Reply-To: <1409030722-30709-3-git-send-email-zhangfei.gao@linaro.org>

Hi,

thanks for the submission.

> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-hix5hd2.c
> @@ -0,0 +1,573 @@
> +/*
> + * Copyright (c) 2014 Linaro Ltd.
> + * Copyright (c) 2014 Hisilicon Limited.
> + *
> + * 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
> + * publishhed by the Free Software Foundation.

"publishhed"

> + *
> + * Now only support 7 bit address.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>

I think there should be at least of.h, too.

> +struct hix5hd2_i2c {
> +	struct i2c_adapter adap;
> +	struct i2c_msg	*msg;
> +	unsigned int msg_ptr;	/* msg index */

Comment seems wrong. It looks to me as the msg buffer index. If so, the
variable name is also confusing.

> +	unsigned int len;	/* msg length */
> +	int stop;
> +	struct completion msg_complete;
> +
> +	unsigned int irq;

That can be a local variable.

> +	void __iomem *regs;
> +	struct clk *clk;
> +	struct device *dev;
> +	spinlock_t lock;	/* IRQ synchronization */
> +
> +	int err;
> +	enum hix5hd2_i2c_state state;
> +	enum hix5hd2_i2c_speed speed_mode;

Where is this needed?

> +
> +	/* Controller frequency */
> +	unsigned int s_clock;
> +};
> +
> +static void hix5hd2_i2c_drv_setrate(struct hix5hd2_i2c *i2c)
> +{
> +	u32 rate, val;
> +	u32 sclh, scll, sysclock;
> +
> +	/* close all i2c interrupt */
> +	val = readl_relaxed(i2c->regs + HIX5I2C_CTRL);
> +	writel_relaxed(val & (~I2C_UNMASK_TOTAL), i2c->regs + HIX5I2C_CTRL);
> +
> +	rate = i2c->s_clock;
> +	sysclock = clk_get_rate(i2c->clk);
> +	sclh = (sysclock / (rate * 2)) / 2 - 1;
> +	writel_relaxed(sclh, i2c->regs + HIX5I2C_SCL_H);
> +	scll = (sysclock / (rate * 2)) / 2 - 1;

scll and sclh use the same formula? Have you measured the setup
frequency with a scope?

> +	writel_relaxed(scll, i2c->regs + HIX5I2C_SCL_L);
> +
> +	/* restore original interrupt*/
> +	writel_relaxed(val, i2c->regs + HIX5I2C_CTRL);
> +
> +	dev_dbg(i2c->dev, "%s: sysclock=%d, rate=%d, sclh=%d, scll=%d\n",
> +		__func__, sysclock, rate, sclh, scll);
> +}
> +
> +static void hix5hd2_rw_over(struct hix5hd2_i2c *i2c)
> +{
> +	if (HIX5I2C_STAT_SND_STOP == i2c->state)

To be honest, I don't like having the constant on the left side. It
is far easier to read if they are on the right side. Plus, we have gcc
warnings to prevent the "=" and "==" mistake. Please switch them around
in this driver.

> +		dev_dbg(i2c->dev, "%s: rw and send stop over\n", __func__);
> +	else
> +		dev_dbg(i2c->dev, "%s: have not data to send\n", __func__);
> +
> +	i2c->state = HIX5I2C_STAT_RW_SUCCESS;
> +	i2c->err = 0;
> +}
> +

...

> +	/* handle error */
> +	if (int_status & I2C_ARBITRATE_INTR) {
> +		/*Bus error */

Space missing in front of "Bus". If this is an arbitration lost error,
then please use -EAGAIN. Check Documentation/i2c/fault-codes for the
convention.

> +		dev_dbg(i2c->dev, "ARB bus loss\n");
> +		i2c->err = -ENXIO;
> +		i2c->state = HIX5I2C_STAT_RW_ERR;
> +		goto stop;
> +	} else if (int_status & I2C_ACK_INTR) {
> +		/* ack error */
> +		dev_dbg(i2c->dev, "No ACK from device\n");
> +		i2c->err = -ENXIO;
> +		i2c->state = HIX5I2C_STAT_RW_ERR;
> +		goto stop;
> +	}
> +
> +static void hix5hd2_i2c_message_start(struct hix5hd2_i2c *i2c, int stop)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&i2c->lock, flags);
> +	hix5hd2_i2c_clr_all_irq(i2c);
> +	hix5hd2_i2c_enable_irq(i2c);
> +
> +	if (i2c->msg->flags & I2C_M_RD)
> +		writel_relaxed(i2c->msg->addr | HIX5I2C_READ_OPERATION,
> +			       i2c->regs + HIX5I2C_TXR);
> +	else
> +		writel_relaxed(i2c->msg->addr & HIX5I2C_WRITE_OPERATION,
> +			       i2c->regs + HIX5I2C_TXR);

??? Does this really work? i2c->msg->addr should be left shifted by 1?

> +
> +	writel_relaxed(I2C_WRITE | I2C_START, i2c->regs + HIX5I2C_COM);
> +	spin_unlock_irqrestore(&i2c->lock, flags);
> +}
> +
> +static int hix5hd2_i2c_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct hix5hd2_i2c *i2c;
> +	struct resource *mem;
> +	unsigned int op_clock;
> +	int ret;
> +
> +	i2c = devm_kzalloc(&pdev->dev, sizeof(struct hix5hd2_i2c), GFP_KERNEL);
> +	if (!i2c)
> +		return -ENOMEM;
> +
> +	if (of_property_read_u32(np, "clock-frequency", &op_clock)) {
> +		/* use default value */
> +		i2c->speed_mode = HIX5I2C_HIG_SPD;
> +		i2c->s_clock = HIX5I2C_HS_TX_CLOCK;

Please use 100kHz as the default. This is the speed devices should
support. 400kHz is optional. And I think 100000 is easier to read than a
define.

> +	} else {
> +		if (op_clock >= HIX5I2C_HS_TX_CLOCK) {
> +			i2c->speed_mode = HIX5I2C_HIG_SPD;
> +			i2c->s_clock = HIX5I2C_HS_TX_CLOCK;

So, if the speed is bigger than 400kHz, it will be capped down to
400kHz? Is that true? Then, the user should be informed about that.

> +		} else {
> +			i2c->speed_mode = HIX5I2C_NORMAL_SPD;
> +			i2c->s_clock = op_clock;
> +		}
> +	}
> +

...

> +	i2c->adap.owner   = THIS_MODULE;
> +	i2c->adap.algo	  = &hix5hd2_i2c_algorithm;

Single space as indentation.

Thanks,

   Wolfram

  parent reply	other threads:[~2014-09-19 17:18 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-26  5:25 [PATCH resend 0/2] i2c: hix5hd2: add i2c controller driver Zhangfei Gao
2014-08-26  5:25 ` Zhangfei Gao
     [not found] ` <1409030722-30709-1-git-send-email-zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-08-26  5:25   ` [PATCH resend 1/2] i2c: hix5hd2: add devicetree documentation Zhangfei Gao
2014-08-26  5:25     ` Zhangfei Gao
2014-08-26  5:25   ` [PATCH resend 2/2] i2c: hix5hd2: add i2c controller driver Zhangfei Gao
2014-08-26  5:25     ` Zhangfei Gao
     [not found]     ` <1409030722-30709-3-git-send-email-zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-09-19 17:18       ` Wolfram Sang [this message]
2014-09-19 17:18         ` Wolfram Sang
2014-09-26  3:30         ` zhangfei
2014-09-26  3:30           ` zhangfei
     [not found]           ` <5424DDD5.1020706-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-09-26  6:55             ` Wolfram Sang
2014-09-26  6:55               ` Wolfram Sang
2014-09-15 19:56   ` [PATCH resend 0/2] " Zhangfei Gao
2014-09-15 19:56     ` Zhangfei Gao

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=20140919171829.GB2874@katana \
    --to=wsa-z923lk4zbo2bacvfa/9k2g@public.gmane.org \
    --cc=arnd-r2nGTMty4D4@public.gmane.org \
    --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=haifeng.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
    --cc=jchxue-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=sledge.yanwei-hv44wF8Li93QT0dZR+AlfA@public.gmane.org \
    --cc=zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@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.