All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Andersson <bjorn.andersson@sonymobile.com>
To: Stephen Boyd <sboyd@codeaurora.org>
Cc: Mark Rutland <mark.rutland@arm.com>,
	Wolfram Sang <wsa@the-dreams.de>,
	"linux-i2c@vger.kernel.org" <linux-i2c@vger.kernel.org>,
	Matt Porter <matt.porter@linaro.org>,
	"linux-doc@vger.kernel.org" <linux-doc@vger.kernel.org>,
	Grant Likely <grant.likely@linaro.org>,
	James Ralston <james.d.ralston@intel.com>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	Rob Landley <rob@landley.net>, Pawel Moll <pawel.moll@arm.com>,
	Ian Campbell <ijc+devicetree@hellion.org.uk>,
	"linux-arm-msm@vger.kernel.org" <linux-arm-msm@vger.kernel.org>,
	Rob Herring <rob.herring@calxeda.com>,
	Martin Schwidefsky <schwidefsky@de.ibm.com>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	Bill Brown <bill.e.brown@intel.com>,
	Greg Kroah-Hartman
	<gregkh@linuxfoundation.org>"linux-kernel@vger.kernel.org"
	<linux->
Subject: Re: [PATCH v2 2/2] i2c: New bus driver for the QUP I2C controller
Date: Thu, 16 Jan 2014 16:18:33 -0800	[thread overview]
Message-ID: <20140117001833.GL30911@sonymobile.com> (raw)
In-Reply-To: <20140115164604.GI14405@codeaurora.org>

On Wed 15 Jan 08:46 PST 2014, Stephen Boyd wrote:

> On 01/13, Bjorn Andersson wrote:
> > +/*
> > + * QUP driver for Qualcomm MSM platforms
> > + *
> > + */
> 
> This comment seems redundant, we know what file we're looking at.
> 

Indeed.

> > +
> > +struct qup_i2c_dev {
> > +	struct device		*dev;
> > +	void __iomem		*base;
> > +	struct pinctrl		*pctrl;
> 
> This is unused.
> 

Removed.

> > +	int			irq;
> > +	struct clk		*clk;
> > +	struct clk		*pclk;
> > +	struct i2c_adapter	adap;
> > +
> > +	int			clk_freq;
> 
> This is only ever used in probe, so why do we need to store it
> away?
> 

Moved to probe()

> > +	int			clk_ctl;
> > +	int			one_bit_t;
> > +	int			out_fifo_sz;
> > +	int			in_fifo_sz;
> > +	int			out_blk_sz;
> > +	int			in_blk_sz;
> > +	unsigned long		xfer_time;
> > +	unsigned long		wait_idle;
> > +
> > +	struct i2c_msg		*msg;
> > +	/* Current possion in user message buffer */
> 
> s/possion/position/?
> 

Thanks.

> > +	int			pos;
> > +	/* Keep number of bytes left to be transmitted */
> > +	int			cnt;
> > +	/* I2C protocol errors */
> > +	u32			bus_err;
> > +	/* QUP core errors */
> > +	u32			qup_err;
> > +	/*
> > +	 * maximum bytes that could be send (per iterration). could be
> 
> s/iterration/iteration/?
> 

Thanks

> > +	 * equal of fifo size or block size (in block mode)
> > +	 */
> > +	int			chunk_sz;
> > +	struct completion	xfer;
> > +};
> > +
> > +static irqreturn_t qup_i2c_interrupt(int irq, void *dev)
> > +{
> > +	struct qup_i2c_dev *qup = dev;
> > +	u32 bus_err;
> > +	u32 qup_err;
> > +	u32 opflags;
> > +
> [...]
> > +
> > +	if (opflags & QUP_OUT_SVC_FLAG)
> > +		writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL);
> > +
> > +	if (!(qup->msg->flags == I2C_M_RD))
> 
> Should this be?
> 
> 	if (!(qup->msg->flags & I2C_M_RD))
> 
> Otherwise it should be
> 
> 	if (qup->msg->flags != I2C_M_RD)
> 

In the codeaurora implementation this seem to be:

if (qup->msg->flags == I2C_M_RD) {
	if ((opflags & QUP_MX_INPUT_DONE) || (opflags & QUP_IN_SVC_FLAG))
		writel(QUP_IN_SVC_FLAG, qup->base + QUP_OPERATIONAL);
	else
		return IRQ_HANDLED;
}

So, do not complete the xfer unless there's something for us.
I'll verify this and update the next version.

Thanks.

> > +		return IRQ_HANDLED;
> > +
> > +	if ((opflags & QUP_MX_INPUT_DONE) || (opflags & QUP_IN_SVC_FLAG))
> > +		writel(QUP_IN_SVC_FLAG, qup->base + QUP_OPERATIONAL);
> > +
> > +done:
> > +	qup->qup_err = qup_err;
> > +	qup->bus_err = bus_err;
> > +	complete(&qup->xfer);
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int
> > +qup_i2c_poll_state(struct qup_i2c_dev *qup, u32 req_state, bool only_valid)
> > +{
> > +	int retries = 0;
> > +	u32 state;
> > +
> > +	do {
> > +		state = readl(qup->base + QUP_STATE);
> > +
> > +		/*
> > +		 * If only valid bit needs to be checked, requested state is
> > +		 * 'don't care'
> > +		 */
> 
> It looks like req_state == 0 means only_valid == true. Can we
> drop the only_valid argument to this function?
> 

In all cases but the reset in the beginning of qup_i2c_xfer, so it seems that
it has to stay.

> > +		if (state & QUP_STATE_VALID) {
> > +			if (only_valid)
> > +				return 0;
> > +			if ((req_state & QUP_I2C_MAST_GEN)
> > +			    && (state & QUP_I2C_MAST_GEN))
> > +				return 0;
> > +			if ((state & QUP_STATE_MASK) == req_state)
> > +				return 0;
> > +		}
> > +
> > +		if (retries++ == 1000)
> > +			udelay(100);
> > +
> > +	} while (retries != 2000);
> 
> Please makes #defines for 1000 and 2000.
> 

This retry loop looks completely arbitrary to me now that you say it. I'll
revise this.

> > +
> > +	return -ETIMEDOUT;
> > +}
> > +
> [...]
> > +static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > +{
> > +	u32 addr = msg->addr << 1;
> > +	u32 val, qup_tag;
> > +	int idx, entries;
> > +
> > +	if (qup->pos == 0) {
> > +		val = QUP_OUT_START | addr;
> > +	} else {
> > +		/*
> > +		 * Avoid setup time issue by adding 1 NOP when number of bytes
> > +		 * are more than FIFO/BLOCK size. setup time issue can't appear
> > +		 * otherwise since next byte to be written will always be ready
> > +		 */
> > +		val = (QUP_OUT_NOP | 1);
> > +	}
> > +
> > +	entries = qup->cnt + 1;
> > +
> > +	if (entries > qup->chunk_sz)
> > +		entries = qup->chunk_sz;
> > +
> > +	qup_tag = QUP_OUT_DATA;
> > +
> > +	/* Reserve one entry for STOP */
> > +	for (idx = 1; idx < (entries - 1); idx++, qup->pos++) {
> 
> Unnecessary () here around entries.
> 

Sure.

> > +
> > +		if (idx & 1) {
> > +			val |= (qup_tag | msg->buf[qup->pos]) << QUP_MSW_SHIFT;
> > +			writel(val, qup->base + QUP_OUT_FIFO_BASE);
> > +		} else {
> > +			val = qup_tag | msg->buf[qup->pos];
> > +		}
> [...]
> > +
> > +#ifdef CONFIG_PM
> 
> This ifdef is probably wrong considering that you can disable
> CONFIG_PM_RUNTIME without disabling CONFIG_PM and then these
> runtime PM functions would be unused.
> 

Will fix.

> > +static int qup_i2c_pm_suspend_runtime(struct device *device)
> > +{
> > +	struct qup_i2c_dev *qup = dev_get_drvdata(device);
> > +
> > +	dev_dbg(device, "pm_runtime: suspending...\n");
> > +	qup_i2c_disable_clocks(qup);
> > +	return 0;
> > +}
> > +
> > +static int qup_i2c_pm_resume_runtime(struct device *device)
> > +{
> > +	struct qup_i2c_dev *qup = dev_get_drvdata(device);
> > +
> > +	dev_dbg(device, "pm_runtime: resuming...\n");
> > +	qup_i2c_enable_clocks(qup);
> > +	return 0;
> > +}
> > +
> > +static int qup_i2c_suspend(struct device *device)
> > +{
> > +	dev_dbg(device, "system suspend");
> > +	qup_i2c_pm_suspend_runtime(device);
> > +	return 0;
> > +}
> > +
> > +static int qup_i2c_resume(struct device *device)
> > +{
> > +	dev_dbg(device, "system resume");
> > +	qup_i2c_pm_resume_runtime(device);
> > +	pm_runtime_mark_last_busy(device);
> > +	pm_request_autosuspend(device);
> > +	return 0;
> > +}
> > +#endif /* CONFIG_PM */
> > +
> > +static const struct dev_pm_ops qup_i2c_qup_pm_ops = {
> > +	SET_SYSTEM_SLEEP_PM_OPS(
> > +		qup_i2c_suspend,
> > +		qup_i2c_resume)
> > +	SET_RUNTIME_PM_OPS(
> > +		qup_i2c_pm_suspend_runtime,
> > +		qup_i2c_pm_resume_runtime,
> > +		NULL)
> > +};
> > +
> > +static struct of_device_id qup_i2c_dt_match[] = {
> 
> const?
> 

Sure

> > +	{.compatible = "qcom,i2c-qup"},
> > +	{}
> > +};
> 
> MODULE_DEVICE_TABLE(of, qup_i2c_dt_match)?
> 

OK

Thanks Stephen!

// Bjorn

WARNING: multiple messages have this Message-ID (diff)
From: bjorn.andersson@sonymobile.com (Bjorn Andersson)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 2/2] i2c: New bus driver for the QUP I2C controller
Date: Thu, 16 Jan 2014 16:18:33 -0800	[thread overview]
Message-ID: <20140117001833.GL30911@sonymobile.com> (raw)
In-Reply-To: <20140115164604.GI14405@codeaurora.org>

On Wed 15 Jan 08:46 PST 2014, Stephen Boyd wrote:

> On 01/13, Bjorn Andersson wrote:
> > +/*
> > + * QUP driver for Qualcomm MSM platforms
> > + *
> > + */
> 
> This comment seems redundant, we know what file we're looking at.
> 

Indeed.

> > +
> > +struct qup_i2c_dev {
> > +	struct device		*dev;
> > +	void __iomem		*base;
> > +	struct pinctrl		*pctrl;
> 
> This is unused.
> 

Removed.

> > +	int			irq;
> > +	struct clk		*clk;
> > +	struct clk		*pclk;
> > +	struct i2c_adapter	adap;
> > +
> > +	int			clk_freq;
> 
> This is only ever used in probe, so why do we need to store it
> away?
> 

Moved to probe()

> > +	int			clk_ctl;
> > +	int			one_bit_t;
> > +	int			out_fifo_sz;
> > +	int			in_fifo_sz;
> > +	int			out_blk_sz;
> > +	int			in_blk_sz;
> > +	unsigned long		xfer_time;
> > +	unsigned long		wait_idle;
> > +
> > +	struct i2c_msg		*msg;
> > +	/* Current possion in user message buffer */
> 
> s/possion/position/?
> 

Thanks.

> > +	int			pos;
> > +	/* Keep number of bytes left to be transmitted */
> > +	int			cnt;
> > +	/* I2C protocol errors */
> > +	u32			bus_err;
> > +	/* QUP core errors */
> > +	u32			qup_err;
> > +	/*
> > +	 * maximum bytes that could be send (per iterration). could be
> 
> s/iterration/iteration/?
> 

Thanks

> > +	 * equal of fifo size or block size (in block mode)
> > +	 */
> > +	int			chunk_sz;
> > +	struct completion	xfer;
> > +};
> > +
> > +static irqreturn_t qup_i2c_interrupt(int irq, void *dev)
> > +{
> > +	struct qup_i2c_dev *qup = dev;
> > +	u32 bus_err;
> > +	u32 qup_err;
> > +	u32 opflags;
> > +
> [...]
> > +
> > +	if (opflags & QUP_OUT_SVC_FLAG)
> > +		writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL);
> > +
> > +	if (!(qup->msg->flags == I2C_M_RD))
> 
> Should this be?
> 
> 	if (!(qup->msg->flags & I2C_M_RD))
> 
> Otherwise it should be
> 
> 	if (qup->msg->flags != I2C_M_RD)
> 

In the codeaurora implementation this seem to be:

if (qup->msg->flags == I2C_M_RD) {
	if ((opflags & QUP_MX_INPUT_DONE) || (opflags & QUP_IN_SVC_FLAG))
		writel(QUP_IN_SVC_FLAG, qup->base + QUP_OPERATIONAL);
	else
		return IRQ_HANDLED;
}

So, do not complete the xfer unless there's something for us.
I'll verify this and update the next version.

Thanks.

> > +		return IRQ_HANDLED;
> > +
> > +	if ((opflags & QUP_MX_INPUT_DONE) || (opflags & QUP_IN_SVC_FLAG))
> > +		writel(QUP_IN_SVC_FLAG, qup->base + QUP_OPERATIONAL);
> > +
> > +done:
> > +	qup->qup_err = qup_err;
> > +	qup->bus_err = bus_err;
> > +	complete(&qup->xfer);
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int
> > +qup_i2c_poll_state(struct qup_i2c_dev *qup, u32 req_state, bool only_valid)
> > +{
> > +	int retries = 0;
> > +	u32 state;
> > +
> > +	do {
> > +		state = readl(qup->base + QUP_STATE);
> > +
> > +		/*
> > +		 * If only valid bit needs to be checked, requested state is
> > +		 * 'don't care'
> > +		 */
> 
> It looks like req_state == 0 means only_valid == true. Can we
> drop the only_valid argument to this function?
> 

In all cases but the reset in the beginning of qup_i2c_xfer, so it seems that
it has to stay.

> > +		if (state & QUP_STATE_VALID) {
> > +			if (only_valid)
> > +				return 0;
> > +			if ((req_state & QUP_I2C_MAST_GEN)
> > +			    && (state & QUP_I2C_MAST_GEN))
> > +				return 0;
> > +			if ((state & QUP_STATE_MASK) == req_state)
> > +				return 0;
> > +		}
> > +
> > +		if (retries++ == 1000)
> > +			udelay(100);
> > +
> > +	} while (retries != 2000);
> 
> Please makes #defines for 1000 and 2000.
> 

This retry loop looks completely arbitrary to me now that you say it. I'll
revise this.

> > +
> > +	return -ETIMEDOUT;
> > +}
> > +
> [...]
> > +static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > +{
> > +	u32 addr = msg->addr << 1;
> > +	u32 val, qup_tag;
> > +	int idx, entries;
> > +
> > +	if (qup->pos == 0) {
> > +		val = QUP_OUT_START | addr;
> > +	} else {
> > +		/*
> > +		 * Avoid setup time issue by adding 1 NOP when number of bytes
> > +		 * are more than FIFO/BLOCK size. setup time issue can't appear
> > +		 * otherwise since next byte to be written will always be ready
> > +		 */
> > +		val = (QUP_OUT_NOP | 1);
> > +	}
> > +
> > +	entries = qup->cnt + 1;
> > +
> > +	if (entries > qup->chunk_sz)
> > +		entries = qup->chunk_sz;
> > +
> > +	qup_tag = QUP_OUT_DATA;
> > +
> > +	/* Reserve one entry for STOP */
> > +	for (idx = 1; idx < (entries - 1); idx++, qup->pos++) {
> 
> Unnecessary () here around entries.
> 

Sure.

> > +
> > +		if (idx & 1) {
> > +			val |= (qup_tag | msg->buf[qup->pos]) << QUP_MSW_SHIFT;
> > +			writel(val, qup->base + QUP_OUT_FIFO_BASE);
> > +		} else {
> > +			val = qup_tag | msg->buf[qup->pos];
> > +		}
> [...]
> > +
> > +#ifdef CONFIG_PM
> 
> This ifdef is probably wrong considering that you can disable
> CONFIG_PM_RUNTIME without disabling CONFIG_PM and then these
> runtime PM functions would be unused.
> 

Will fix.

> > +static int qup_i2c_pm_suspend_runtime(struct device *device)
> > +{
> > +	struct qup_i2c_dev *qup = dev_get_drvdata(device);
> > +
> > +	dev_dbg(device, "pm_runtime: suspending...\n");
> > +	qup_i2c_disable_clocks(qup);
> > +	return 0;
> > +}
> > +
> > +static int qup_i2c_pm_resume_runtime(struct device *device)
> > +{
> > +	struct qup_i2c_dev *qup = dev_get_drvdata(device);
> > +
> > +	dev_dbg(device, "pm_runtime: resuming...\n");
> > +	qup_i2c_enable_clocks(qup);
> > +	return 0;
> > +}
> > +
> > +static int qup_i2c_suspend(struct device *device)
> > +{
> > +	dev_dbg(device, "system suspend");
> > +	qup_i2c_pm_suspend_runtime(device);
> > +	return 0;
> > +}
> > +
> > +static int qup_i2c_resume(struct device *device)
> > +{
> > +	dev_dbg(device, "system resume");
> > +	qup_i2c_pm_resume_runtime(device);
> > +	pm_runtime_mark_last_busy(device);
> > +	pm_request_autosuspend(device);
> > +	return 0;
> > +}
> > +#endif /* CONFIG_PM */
> > +
> > +static const struct dev_pm_ops qup_i2c_qup_pm_ops = {
> > +	SET_SYSTEM_SLEEP_PM_OPS(
> > +		qup_i2c_suspend,
> > +		qup_i2c_resume)
> > +	SET_RUNTIME_PM_OPS(
> > +		qup_i2c_pm_suspend_runtime,
> > +		qup_i2c_pm_resume_runtime,
> > +		NULL)
> > +};
> > +
> > +static struct of_device_id qup_i2c_dt_match[] = {
> 
> const?
> 

Sure

> > +	{.compatible = "qcom,i2c-qup"},
> > +	{}
> > +};
> 
> MODULE_DEVICE_TABLE(of, qup_i2c_dt_match)?
> 

OK

Thanks Stephen!

// Bjorn

  parent reply	other threads:[~2014-01-17  0:18 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-14  0:30 [PATCH v2 0/2] Qualcomm Universal Peripheral (QUP) I2C controller Bjorn Andersson
2014-01-14  0:30 ` Bjorn Andersson
2014-01-14  0:30 ` [PATCH v2 1/2] i2c: qup: Add device tree bindings information Bjorn Andersson
2014-01-14  0:30   ` Bjorn Andersson
2014-01-14  8:57   ` Ivan T. Ivanov
2014-01-14  8:57     ` Ivan T. Ivanov
2014-01-16 23:20     ` Bjorn Andersson
2014-01-16 23:20       ` Bjorn Andersson
2014-01-16 23:20       ` Bjorn Andersson
2014-01-17  7:40       ` Ivan T. Ivanov
2014-01-17  7:40         ` Ivan T. Ivanov
2014-01-17  7:40         ` Ivan T. Ivanov
2014-01-14  0:30 ` [PATCH v2 2/2] i2c: New bus driver for the QUP I2C controller Bjorn Andersson
2014-01-14  0:30   ` Bjorn Andersson
2014-01-14 13:03   ` Ivan T. Ivanov
2014-01-14 13:03     ` Ivan T. Ivanov
2014-01-15 16:46   ` Stephen Boyd
2014-01-15 16:46     ` Stephen Boyd
     [not found]     ` <20140115164604.GI14405-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2014-01-16 13:37       ` Ivan T. Ivanov
2014-01-16 13:37         ` Ivan T. Ivanov
2014-01-16 13:37         ` Ivan T. Ivanov
2014-01-17  0:18     ` Bjorn Andersson [this message]
2014-01-17  0:18       ` Bjorn Andersson
2014-01-17  0:33       ` Stephen Boyd
2014-01-17  0:33         ` Stephen Boyd
2014-01-17 22:19         ` Bjorn Andersson
2014-01-17 22:19           ` Bjorn Andersson

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=20140117001833.GL30911@sonymobile.com \
    --to=bjorn.andersson@sonymobile.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=bill.e.brown@intel.com \
    --cc=devicetree@vger.kernel.org \
    --cc=grant.likely@linaro.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=ijc+devicetree@hellion.org.uk \
    --cc=james.d.ralston@intel.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-i2c@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=matt.porter@linaro.org \
    --cc=pawel.moll@arm.com \
    --cc=rob.herring@calxeda.com \
    --cc=rob@landley.net \
    --cc=sboyd@codeaurora.org \
    --cc=schwidefsky@de.ibm.com \
    --cc=wsa@the-dreams.de \
    /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.