Skip to contentSkip to conversation

i2c: core/pxa: Add support for hardware lock

PATCH New Vaibhav Hiremath 7 participants 51 messages Jun 2, 2015 – Oct 25, 2015

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover i2c: core/pxa: Add support for hardware lock

To justify the need for hardware lock, lets take a real usecase scenario -

In case of Marvell SoC, PXA910 silicon, both AP and CP are present and these two ARM cores are sharing one pair of I2C pins.

In order to keep I2C transaction operated with atomic, hardware lock (RIPC) is required.

This patch extends support for atomic operation by adding hardware lock support to the i2c-core.

PATCH[1/3] : Core changes for hardware lock
PATCH[2/3 & 3/3] : hardware lock support to i2c-pxa bus driver.

Link to previous post:
http://lkml.iu.edu/hypermail/linux/kernel/1104.3/02352.html
http://lkml.iu.edu/hypermail/linux/kernel/1104.3/02353.html
http://lkml.iu.edu/hypermail/linux/kernel/1104.3/02354.html

TODO:
- DT node addition
I am using PXA1928 based platform which is still not available in Mainline, so it is based on, below patch-series Link to Rob's patches:
https://lkml.org/lkml/2015/5/1/14
https://lkml.org/lkml/2015/5/19/1206
PMIC 88pm860 support
http://www.spinics.net/lists/arm-kernel/msg422554.html

Vaibhav Hiremath (3):
i2c: core: append hardware lock with bus lock
i2c: pxa: Add support for hardware lock
i2c: pxa: Add pin ctrl support for CP core access

 drivers/i2c/busses/i2c-pxa.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/i2c-core.c       | 22 +++++++++--
 include/linux/i2c.h          |  5 +++
 include/linux/i2c/pxa-i2c.h  |  4 ++
 4 files changed, 119 insertions(+), 4 deletions(-)
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/3 i2c: core: append hardware lock with bus lock

To justify the need for hardware lock, lets take a real usecase scenario -

In case of Marvell SoC, PXA910 silicon, both AP and CP are present and
these two ARM cores are sharing one pair of I2C pins.

In order to keep I2C transaction operated with atomic, hardware lock (RIPC) is required.

This patch extends support for atomic operation by adding hardware lock.

History:
The attempt has been made to push this patch-sets upstream sometime back in 2011, but not sure what happened later. I am making another attempt, hopefully will conclude it now.

Link to previous patch:
http://marc.info/?l=linux-i2c&m=130432846300735&w=2

---
 drivers/i2c/i2c-core.c | 22 ++++++++++++++++++----
 include/linux/i2c.h    |  5 +++++
 2 files changed, 23 insertions(+), 4 deletions(-)
drivers/i2c/i2c-core.c +18 -4
index 987c124..daea523 100644
@@ -868,8 +868,11 @@ void i2c_lock_adapter(struct i2c_adapter *adapter)
 
 	if (parent)
 		i2c_lock_adapter(parent);
-	else
+	else {
 		rt_mutex_lock(&adapter->bus_lock);
+		if (adapter->hardware_lock)
+			adapter->hardware_lock(adapter);
+	}
 }
 EXPORT_SYMBOL_GPL(i2c_lock_adapter);
 
@@ -880,11 +883,19 @@ EXPORT_SYMBOL_GPL(i2c_lock_adapter);
 static int i2c_trylock_adapter(struct i2c_adapter *adapter)
 {
 	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
+	int ret = 0;
 
 	if (parent)
 		return i2c_trylock_adapter(parent);
-	else
-		return rt_mutex_trylock(&adapter->bus_lock);
+	else {
+		ret = rt_mutex_trylock(&adapter->bus_lock);
+		if (ret && adapter->hardware_trylock) {
+			ret = adapter->hardware_trylock(adapter);
+			if (!ret)
+				i2c_unlock_adapter(adapter);
+		}
+		return ret;
+	}
 }
 
 /**
@@ -897,8 +908,11 @@ void i2c_unlock_adapter(struct i2c_adapter *adapter)
 
 	if (parent)
 		i2c_unlock_adapter(parent);
-	else
+	else {
+		if (adapter->hardware_unlock)
+			adapter->hardware_unlock(adapter);
 		rt_mutex_unlock(&adapter->bus_lock);
+	}
 }
 EXPORT_SYMBOL_GPL(i2c_unlock_adapter);
 
include/linux/i2c.h +5 -0
index e83a738..0758fb3 100644
@@ -504,6 +504,11 @@ struct i2c_adapter {
 	/* data fields that are valid for all devices	*/
 	struct rt_mutex bus_lock;
 
+	/* if hardware lock feature provided */
+	void (*hardware_lock)(struct i2c_adapter *);
+	void (*hardware_unlock)(struct i2c_adapter *);
+	int (*hardware_trylock)(struct i2c_adapter *);
+
 	int timeout;			/* in jiffies */
 	int retries;
 	struct device dev;		/* the adapter device */
Signature · 1 line
1.9.1
#2 lore raw

PATCH 2/3 i2c: pxa: Add support for hardware lock

In reply to Vaibhav Hiremath

In case of PXA910 silicon, both AP and CP are present and these two ARM cores are sharing one pair of I2C pins.

In order to keep I2C transaction operated with atomic, hardware lock (RIPC) is required.

This patch extends support for atomic operation by adding hardware lock.

---
 drivers/i2c/busses/i2c-pxa.c | 75 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c/pxa-i2c.h  |  4 +++
 2 files changed, 79 insertions(+)
drivers/i2c/busses/i2c-pxa.c +75 -0
index f51d512..eb26eb1 100644
@@ -167,6 +167,7 @@ struct pxa_i2c {
 	void __iomem		*reg_isar;
 	void __iomem		*reg_ilcr;
 	void __iomem		*reg_iwcr;
+	void __iomem		*hwlock_addr;
 
 	unsigned long		iobase;
 	unsigned long		iosize;
@@ -368,6 +369,9 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
 static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
 static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id);
 
+spinlock_t lock_for_ripc;
+static int ripc_status;
+
 /* enable/disable i2c unit */
 static inline void i2c_pxa_enable(struct pxa_i2c *i2c, bool enable)
 {
@@ -378,6 +382,57 @@ static inline void i2c_pxa_enable(struct pxa_i2c *i2c, bool enable)
 	udelay(100);
 }
 
+void mmp_hwlock_lock(struct i2c_adapter *adap)
+{
+	int cnt = 0;
+	unsigned long flags;
+
+	struct pxa_i2c *i2c = adap->algo_data;
+
+	spin_lock_irqsave(&lock_for_ripc, flags);
+	while(__raw_readl(i2c->hwlock_addr)) {
+		ripc_status = false;
+		spin_unlock_irqrestore(&lock_for_ripc, flags);
+		cpu_relax();
+		udelay(50);
+		cnt++;
+		if (cnt >= 10000) {
+			pr_warn("AP: fail to lock ripc!\n");
+			cnt = 0;
+		}
+	}
+	/* sure to hold ripc */
+	ripc_status = true;
+
+	spin_unlock_irqrestore(&lock_for_ripc, flags);
+}
+
+void mmp_hwlock_unlock(struct i2c_adapter *adap)
+{
+	unsigned long flags;
+
+	struct pxa_i2c *i2c = adap->algo_data;
+
+	spin_lock_irqsave(&lock_for_ripc, flags);
+	__raw_writel(1, i2c->hwlock_addr);
+	ripc_status = false;
+
+	spin_unlock_irqrestore(&lock_for_ripc, flags);
+}
+
+int mmp_hwlock_trylock(struct i2c_adapter *adap)
+{
+	unsigned long flags;
+
+	struct pxa_i2c *i2c = adap->algo_data;
+
+	spin_lock_irqsave(&lock_for_ripc, flags);
+	ripc_status = !__raw_readl(i2c->hwlock_addr);
+	spin_unlock_irqrestore(&lock_for_ripc, flags);
+
+	return ripc_status;
+}
+
 static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
 {
 	return !(readl(_ICR(i2c)) & ICR_SCLE);
@@ -1347,6 +1402,14 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	i2c->iobase = res->start;
 	i2c->iosize = resource_size(res);
 
+	res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+	if (res) {
+		i2c->hwlock_addr = ioremap(res->start, resource_size(res));
+		dev_info(&dev->dev, "hardware lock address: 0x%p\n",
+			 i2c->hwlock_addr);
+	} else
+		dev_dbg(&dev->dev, "no hardware lock used\n");
+
 	i2c->irq = irq;
 
 	i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
@@ -1360,6 +1423,18 @@ static int i2c_pxa_probe(struct platform_device *dev)
 		i2c->ilcr = plat->ilcr;
 		i2c->iwcr = plat->iwcr;
 		i2c->adap.class = plat->class;
+
+		i2c->adap.hardware_lock = plat->hardware_lock;
+		i2c->adap.hardware_unlock = plat->hardware_unlock;
+		i2c->adap.hardware_trylock = plat->hardware_trylock;
+	} else {
+		if (i2c->hwlock_addr) {
+			spin_lock_init(&lock_for_ripc);
+
+			i2c->adap.hardware_lock = mmp_hwlock_lock;
+			i2c->adap.hardware_unlock = mmp_hwlock_unlock;
+			i2c->adap.hardware_trylock = mmp_hwlock_trylock;
+		}
 	}
 
 	if (i2c->high_mode) {
include/linux/i2c/pxa-i2c.h +4 -0
index d1a44e8..e6f5981 100644
@@ -72,6 +72,10 @@ struct i2c_pxa_platform_data {
 	unsigned long		rate;
 	unsigned int		ilcr;
 	unsigned int		iwcr;
+	void			(*hardware_lock)(struct i2c_adapter *);
+	void			(*hardware_unlock)(struct i2c_adapter *);
+	int			(*hardware_trylock)(struct i2c_adapter *);
+
 };
 
 extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info);
Signature · 1 line
1.9.1
#3 lore raw

PATCH 3/3 i2c: pxa: Add pin ctrl support for CP core access

In reply to Vaibhav Hiremath

PMIC TWSI pins configuration for AP and CP is different on eden, it need to be set to function 0 when AP get RIPC lock. When AP release RIPC lock, it also need configure twsi pins to other state, otherwise pinctrl will assume pins configration is not changed even if it is changed by CP, so it will not change twsi pins configuration to AP state when AP get RIPC next time.

---
 drivers/i2c/busses/i2c-pxa.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
drivers/i2c/busses/i2c-pxa.c +17 -0
index eb26eb1..1340de1 100644
@@ -184,6 +184,7 @@ struct pxa_i2c {
 	struct pinctrl		*pinctrl;
 	struct pinctrl_state	*pin_i2c;
 	struct pinctrl_state	*pin_gpio;
+	struct pinctrl_state	*pin_i2c_cp;
 };
 
 #define _IBMR(i2c)	((i2c)->reg_ibmr)
@@ -405,6 +406,10 @@ void mmp_hwlock_lock(struct i2c_adapter *adap)
 	ripc_status = true;
 
 	spin_unlock_irqrestore(&lock_for_ripc, flags);
+
+	if (pinctrl_select_state(i2c->pinctrl, i2c->pin_i2c) < 0)
+		dev_err(&i2c->adap.dev, "could not set i2c AP pins\n");
+
 }
 
 void mmp_hwlock_unlock(struct i2c_adapter *adap)
@@ -413,6 +418,9 @@ void mmp_hwlock_unlock(struct i2c_adapter *adap)
 
 	struct pxa_i2c *i2c = adap->algo_data;
 
+	if (pinctrl_select_state(i2c->pinctrl, i2c->pin_i2c_cp) < 0)
+		dev_err(&i2c->adap.dev, "could not set i2c CP pins\n");
+
 	spin_lock_irqsave(&lock_for_ripc, flags);
 	__raw_writel(1, i2c->hwlock_addr);
 	ripc_status = false;
@@ -430,6 +438,9 @@ int mmp_hwlock_trylock(struct i2c_adapter *adap)
 	ripc_status = !__raw_readl(i2c->hwlock_addr);
 	spin_unlock_irqrestore(&lock_for_ripc, flags);
 
+	if (ripc_status && (pinctrl_select_state(i2c->pinctrl, i2c->pin_i2c) < 0))
+		dev_err(&i2c->adap.dev, "could not set i2c AP pins\n");
+
 	return ripc_status;
 }
 
@@ -1497,8 +1508,14 @@ static int i2c_pxa_probe(struct platform_device *dev)
 			ret = IS_ERR(i2c->pin_gpio);
 		}
 
+		/* pin ctrl for CP - optional */
+		i2c->pin_i2c_cp = pinctrl_lookup_state(i2c->pinctrl, "i2c_cp");
+		if (IS_ERR(i2c->pin_i2c_cp))
+			dev_err(&dev->dev, "could not get i2c_cp pinstate\n");
+
 		if (ret) {
 			i2c->pin_i2c = NULL;
+			i2c->pin_i2c_cp = NULL;
 			i2c->pin_gpio = NULL;
 			i2c->pinctrl = NULL;
 			ret = 0;
Signature · 1 line
1.9.1
#4 lore raw

cover i2c: core/pxa: Add support for hardware lock

In reply to Vaibhav Hiremath
Quoted 29 lines · Vaibhav Hiremath

To justify the need for hardware lock, lets take a real usecase scenario -

In case of Marvell SoC, PXA910 silicon, both AP and CP are present and these two ARM cores are sharing one pair of I2C pins.

In order to keep I2C transaction operated with atomic, hardware lock (RIPC) is required.

This patch extends support for atomic operation by adding hardware lock support to the i2c-core.

PATCH[1/3] : Core changes for hardware lock
PATCH[2/3 & 3/3] : hardware lock support to i2c-pxa bus driver.

Link to previous post:
http://lkml.iu.edu/hypermail/linux/kernel/1104.3/02352.html
http://lkml.iu.edu/hypermail/linux/kernel/1104.3/02353.html
http://lkml.iu.edu/hypermail/linux/kernel/1104.3/02354.html

TODO:
- DT node addition
I am using PXA1928 based platform which is still not available in Mainline, so it is based on, below patch-series Link to Rob's patches:
https://lkml.org/lkml/2015/5/1/14
https://lkml.org/lkml/2015/5/19/1206
PMIC 88pm860 support
http://www.spinics.net/lists/arm-kernel/msg422554.html

Quoted 5 lines

Vaibhav Hiremath (3):
i2c: core: append hardware lock with bus lock
i2c: pxa: Add support for hardware lock
i2c: pxa: Add pin ctrl support for CP core access

Wolfram,

Any update on this patch-series?

Thanks,
Vaibhav

#5 lore raw

cover i2c: core/pxa: Add support for hardware lock

Quoted 40 lines · Vaibhav Hiremath
Quoted 31 lines · Vaibhav Hiremath

To justify the need for hardware lock, lets take a real usecase scenario -

In case of Marvell SoC, PXA910 silicon, both AP and CP are present and these two ARM cores are sharing one pair of I2C pins.

In order to keep I2C transaction operated with atomic, hardware lock (RIPC) is required.

This patch extends support for atomic operation by adding hardware lock support
to the i2c-core.

PATCH[1/3] : Core changes for hardware lock
PATCH[2/3 & 3/3] : hardware lock support to i2c-pxa bus driver.

Link to previous post:
http://lkml.iu.edu/hypermail/linux/kernel/1104.3/02352.html
http://lkml.iu.edu/hypermail/linux/kernel/1104.3/02353.html
http://lkml.iu.edu/hypermail/linux/kernel/1104.3/02354.html

TODO:
- DT node addition
I am using PXA1928 based platform which is still not available in Mainline, so it is based on, below patch-series Link to Rob's patches:
https://lkml.org/lkml/2015/5/1/14
https://lkml.org/lkml/2015/5/19/1206
PMIC 88pm860 support
http://www.spinics.net/lists/arm-kernel/msg422554.html

Quoted 5 lines

Vaibhav Hiremath (3):
i2c: core: append hardware lock with bus lock
i2c: pxa: Add support for hardware lock
i2c: pxa: Add pin ctrl support for CP core access

Quoted 4 lines

Wolfram,

Any update on this patch-series?

Any update? Its long time since this patch is pending for review.

Thanks,
Vaibhav

#6 lore raw

cover i2c: core/pxa: Add support for hardware lock

In reply to Vaibhav Hiremath
Quoted 5 lines · Vaibhav Hiremath

To justify the need for hardware lock, lets take a real usecase scenario -

In case of Marvell SoC, PXA910 silicon, both AP and CP are present and these two ARM cores are sharing one pair of I2C pins.

Quoted 8 lines

In order to keep I2C transaction operated with atomic, hardware lock (RIPC) is required.

This patch extends support for atomic operation by adding hardware lock support to the i2c-core.

PATCH[1/3] : Core changes for hardware lock
PATCH[2/3 & 3/3] : hardware lock support to i2c-pxa bus driver.

Why don't you use the hwspinlock subsystem?

-------------- 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/20151025/c8731197/attachment.sig>

#7 lore raw

v2 cover i2c: pxa: Fixes, cleanup and support for pxa910 family

This patch series fixes bugs/warnings, cleans up the code and adds support for PXA910 family of devices to PXA I2C bus driver.

There has been one attempt made sometime back in 2012 to upstream some of the patches from below list, but did not get follow up later. I have consolidated all the patches, cleaned them up, splited into logical changes, added new patches and submitting it now.

I tried to maintain authorship & Signoff except where I did some significant changes to the code/logic.

Link to previous post:
http://permalink.gmane.org/gmane.linux.drivers.i2c/13557

Testing:
- Basic testing on PMIC device on I2C-0 interface
- Boot tested on platform based on PXA1928
- Probe is successfully passing
- Read few registers of PMIC (RTC, ID, etc...) during boot

V1 => V2:
========
Link to V1 - http://lists.infradead.org/pipermail/linux-arm-kernel/2015-May/347012.html

- Fixed all comments from "Robert Jarzmik" and "Wolfram Sang"
- Dropped Patch
05/12: using core bus reset implementation - under work.
Will submit shortly.
08/12: NAKed and dropped
- Seperated DT binding patch from driver changes, for easy merge

Leilei Shang (1):
i2c: pxa: keep i2c irq ON in suspend

Shouming Wang (1):
i2c: pxa: Return I2C_RETRY when timeout in pio mode

Vaibhav Hiremath (8):
i2c: pxa: No need to set slave addr for i2c master mode reset
i2c: pxa: Reset i2c controller on timeout in interrupt and pio mode
i2c: pxa: Update debug function to dump more info on error i2c:pxa: Use devm_ variants in probe function
Documentation: binding: add new property 'disable_after_xfer' to

    i2c-pxa

i2c: pxa: Add support for pxa910/988 & new configuration features
i2c: pxa: Add ILCR (tLow & tHigh) configuration support
Documentation: binding: add sclk adjustment properties to i2c-pxa

Yi Zhang (1):
i2c: pxa: enable/disable i2c module across msg xfer

Yipeng Yao (1):
i2c: pxa: Remove compile warnning in 64bit mode

 Documentation/devicetree/bindings/i2c/i2c-pxa.txt |  18 ++
 drivers/i2c/busses/i2c-pxa.c                      | 267 ++++++++++++++++------
 2 files changed, 220 insertions(+), 65 deletions(-)
Signature · 1 line
1.9.1
#8 lore raw

PATCH v2 1/12 i2c: pxa: keep i2c irq ON in suspend

From: Leilei Shang <[email protected]>

During suspend there may still be some i2c access happening, as the interrupt is shared between multiple drivers.
And if we don't keep i2c irq ON, there may be i2c access timeout if i2c is in irq mode of operation.

[vaibhav.hiremath at linaro.org: updated Changelog]
Cc Wolfram Sang <[email protected]>
---
 drivers/i2c/busses/i2c-pxa.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-pxa.c +3 -2
index d9c0d6a..f4ac8c5 100644
@@ -1232,8 +1232,9 @@ static int i2c_pxa_probe(struct platform_device *dev)
 		i2c->adap.algo = &i2c_pxa_pio_algorithm;
 	} else {
 		i2c->adap.algo = &i2c_pxa_algorithm;
-		ret = request_irq(irq, i2c_pxa_handler, IRQF_SHARED,
-				  dev_name(&dev->dev), i2c);
+		ret = request_irq(irq, i2c_pxa_handler,
+				IRQF_SHARED | IRQF_NO_SUSPEND,
+				dev_name(&dev->dev), i2c);
 		if (ret)
 			goto ereqirq;
 	}
Signature · 1 line
1.9.1
#9 lore raw

PATCH v2 2/12 i2c: pxa: No need to set slave addr for i2c master mode reset

In reply to Vaibhav Hiremath

Normally i2c controller works as master, so slave addr is not needed, or it will impact some slave device (eg. ST NFC chip) i2c accesses, because it has the same i2c address with controller.

---
 drivers/i2c/busses/i2c-pxa.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-pxa.c +1 -1
index f4ac8c5..023e59f 100644
@@ -459,7 +459,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
 	writel(I2C_ISR_INIT, _ISR(i2c));
 	writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c));
 
-	if (i2c->reg_isar)
+	if (i2c->reg_isar && IS_ENABLED(CONFIG_I2C_PXA_SLAVE))
 		writel(i2c->slave_addr, _ISAR(i2c));
 
 	/* set control register values */
Signature · 1 line
1.9.1
#10 lore raw

PATCH v2 2/12 i2c: pxa: No need to set slave addr for i2c master mode reset

Quoted 7 lines · Vaibhav Hiremath

Normally i2c controller works as master, so slave addr is not needed, or it will impact some slave device (eg. ST NFC chip) i2c accesses, because it has the same i2c address with controller.

Cheers.

Signature · 1 line
Robert
#11 lore raw

PATCH v2 3/12 i2c: pxa: Return I2C_RETRY when timeout in pio mode

In reply to Vaibhav Hiremath

From: Shouming Wang <[email protected]>

In case of timeout in pio mode of operation return I2C_RETRY. This behavior will be same as interrupt mode of operation.

[vaibhav.hiremath at linaro.org: Updated changelog]
---
 drivers/i2c/busses/i2c-pxa.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-pxa.c +3 -1
index 023e59f..632008f 100644
@@ -745,8 +745,10 @@ static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
 	ret = i2c->msg_idx;
 
 out:
-	if (timeout == 0)
+	if (timeout == 0) {
 		i2c_pxa_scream_blue_murder(i2c, "timeout");
+		ret = I2C_RETRY;
+	}
 
 	return ret;
 }
Signature · 1 line
1.9.1
#12 lore raw

PATCH v2 3/12 i2c: pxa: Return I2C_RETRY when timeout in pio mode

Quoted 17 lines · Vaibhav Hiremath

From: Shouming Wang <[email protected]>

In case of timeout in pio mode of operation return I2C_RETRY. This behavior will be same as interrupt mode of operation.

[vaibhav.hiremath at linaro.org: Updated changelog]
---
 drivers/i2c/busses/i2c-pxa.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-pxa.c +0 -0
index 023e59f..632008f 100644

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, · line 750

Quoted 7 lines
drivers/i2c/busses/i2c-pxa.c +2 -1
@@ -745,8 +745,10 @@ static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
        ret = i2c->msg_idx;
 
 out:
-       if (timeout == 0)
+       if (timeout == 0) {
                i2c_pxa_scream_blue_murder(i2c, "timeout");
+               ret = I2C_RETRY;

Can we use standard return types.

Quoted 12 lines
drivers/i2c/busses/i2c-pxa.c +1 -1
+       }
 
        return ret;
 }
--

1.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#13 lore raw

PATCH v2 3/12 i2c: pxa: Return I2C_RETRY when timeout in pio mode

Quoted 21 lines · Shubhrajyoti Datta
Quoted 19 lines · Vaibhav Hiremath

From: Shouming Wang <[email protected]>

In case of timeout in pio mode of operation return I2C_RETRY. This behavior will be same as interrupt mode of operation.

[vaibhav.hiremath at linaro.org: Updated changelog]
---
  drivers/i2c/busses/i2c-pxa.c | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-pxa.c +0 -0
index 023e59f..632008f 100644
@@ -745,8 +745,10 @@ static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
         ret = i2c->msg_idx;
 
Quoted 8 lines

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, · line 750

Quoted 5 lines
drivers/i2c/busses/i2c-pxa.c +2 -1
  out:
-       if (timeout == 0)
+       if (timeout == 0) {
                 i2c_pxa_scream_blue_murder(i2c, "timeout");
+               ret = I2C_RETRY;

Can we use standard return types.

Unfortunately NO.

I2C_RETRY is used in many places, internal to the i2c-pcxa driver. This return value is internal only and used internally to the driver.

Thanks,
Vaibhav

#14 lore raw

PATCH v2 3/12 i2c: pxa: Return I2C_RETRY when timeout in pio mode

In reply to Vaibhav Hiremath
Quoted 8 lines · Vaibhav Hiremath

From: Shouming Wang <[email protected]>

In case of timeout in pio mode of operation return I2C_RETRY. This behavior will be same as interrupt mode of operation.

[vaibhav.hiremath at linaro.org: Updated changelog]

Cheers.

Signature · 1 line
Robert
#15 lore raw

PATCH v2 4/12 i2c: pxa: Reset i2c controller on timeout in interrupt and pio mode

In reply to Vaibhav Hiremath

In case of timeout during msg xfer assert reset to i2c controller for both interrupt and PIO mode of operation.

[vaibhav.hiremath at linaro.org: Split & merge patches into logical changes and update the Changelog]

---
 drivers/i2c/busses/i2c-pxa.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/i2c/busses/i2c-pxa.c +8 -0
index 632008f..edacfeb3 100644
@@ -173,6 +173,8 @@ struct pxa_i2c {
  */
 #define I2C_PXA_SLAVE_ADDR      0x1
 
+static void i2c_pxa_reset(struct pxa_i2c *i2c);
+
 #ifdef DEBUG
 
 struct bits {
@@ -750,6 +752,9 @@ out:
 		ret = I2C_RETRY;
 	}
 
+	if (ret < 0)
+		i2c_pxa_reset(i2c);
+
 	return ret;
 }
 
@@ -816,6 +821,9 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
 	}
 
  out:
+	if (ret < 0)
+		i2c_pxa_reset(i2c);
+
 	return ret;
 }
 
Signature · 1 line
1.9.1
#16 lore raw

PATCH v2 4/12 i2c: pxa: Reset i2c controller on timeout in interrupt and pio mode

Quoted 7 lines · Vaibhav Hiremath

In case of timeout during msg xfer assert reset to i2c controller for both interrupt and PIO mode of operation.

[vaibhav.hiremath at linaro.org: Split & merge patches into logical changes and update the Changelog]

I already said it previously, I'm against an unconditional reset in a timeout path. Make it a quirk or whatever, but in the current status, I'm against.

The previous behavior looks correct to me : upon timeout, retry, no need to reset.

--
Robert

#17 lore raw

PATCH v2 4/12 i2c: pxa: Reset i2c controller on timeout in interrupt and pio mode

Quoted 10 lines · Robert Jarzmik
Quoted 7 lines · Vaibhav Hiremath

In case of timeout during msg xfer assert reset to i2c controller for both interrupt and PIO mode of operation.

[vaibhav.hiremath at linaro.org: Split & merge patches into logical changes and update the Changelog]

Quoted 6 lines

I already said it previously, I'm against an unconditional reset in a timeout path. Make it a quirk or whatever, but in the current status, I'm against.

The previous behavior looks correct to me : upon timeout, retry, no need to reset.

We still do return RETRY here, but also assert reset to I2C.

Anyway, lets revisit this again later. I will remove it in my next version.

Thanks,
Vaibhav

#18 lore raw

PATCH v2 5/12 i2c: pxa: Remove compile warnning in 64bit mode

In reply to Vaibhav Hiremath

From: Yipeng Yao <[email protected]>

Fix below warning message, coming from 64 bit toolchain.

drivers/i2c/busses/i2c-pxa.c:1237:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

[vaibhav.hiremath at linaro.org: Updated Changelog]
Cc Wolfram Sang <[email protected]>
---
 drivers/i2c/busses/i2c-pxa.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-pxa.c +3 -1
index edacfeb3..810e9d0 100644
@@ -1124,7 +1124,9 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
 		i2c->use_pio = 1;
 	if (of_get_property(np, "mrvl,i2c-fast-mode", NULL))
 		i2c->fast_mode = 1;
-	*i2c_types = (u32)(of_id->data);
+
+	*i2c_types = (long)(of_id->data);
+
 	return 0;
 }
 
Signature · 1 line
1.9.1
#19 lore raw

PATCH v2 6/12 i2c: pxa: Update debug function to dump more info on error

In reply to Vaibhav Hiremath

Update i2c_pxa_scream_blue_murder() fn to print more information in case of error.
Also, use dev_err variants instead of printk.

---
 drivers/i2c/busses/i2c-pxa.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)
drivers/i2c/busses/i2c-pxa.c +15 -7
index 810e9d0..b8b3856 100644
@@ -132,6 +132,7 @@ struct pxa_i2c {
 	unsigned int		msg_idx;
 	unsigned int		msg_ptr;
 	unsigned int		slave_addr;
+	unsigned int		req_slave_addr;
 
 	struct i2c_adapter	adap;
 	struct clk		*clk;
@@ -255,15 +256,20 @@ static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
 static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
 {
 	unsigned int i;
-	printk(KERN_ERR "i2c: error: %s\n", why);
-	printk(KERN_ERR "i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n",
+	struct device *dev = &i2c->adap.dev;
+
+	dev_err(dev, "slave_0x%x error: %s\n",
+		i2c->req_slave_addr >> 1, why);
+	dev_err(dev, "msg_num: %d msg_idx: %d msg_ptr: %d\n",
 		i2c->msg_num, i2c->msg_idx, i2c->msg_ptr);
-	printk(KERN_ERR "i2c: ICR: %08x ISR: %08x\n",
-	       readl(_ICR(i2c)), readl(_ISR(i2c)));
-	printk(KERN_DEBUG "i2c: log: ");
+	dev_err(dev, "IBMR: %08x IDBR: %08x ICR: %08x ISR: %08x\n",
+		readl(_IBMR(i2c)), readl(_IDBR(i2c)), readl(_ICR(i2c)),
+		readl(_ISR(i2c)));
+	dev_dbg(dev, "log: ");
 	for (i = 0; i < i2c->irqlogidx; i++)
-		printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]);
-	printk("\n");
+		pr_debug("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]);
+
+	pr_debug("\n");
 }
 
 #else /* ifdef DEBUG */
@@ -640,6 +646,7 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
 	 * Step 1: target slave address into IDBR
 	 */
 	writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c));
+	i2c->req_slave_addr = i2c_pxa_addr_byte(i2c->msg);
 
 	/*
 	 * Step 2: initiate the write.
@@ -959,6 +966,7 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
 		 * Write the next address.
 		 */
 		writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c));
+		i2c->req_slave_addr = i2c_pxa_addr_byte(i2c->msg);
 
 		/*
 		 * And trigger a repeated start, and send the byte.
Signature · 1 line
1.9.1
#20 lore raw

PATCH v2 7/12 i2c:pxa: Use devm_ variants in probe function

In reply to Vaibhav Hiremath

This patch cleans up i2c_pxa_probe() function,

- Use devm_ variants wherever
This will clean both probe exit and i2c_pxa_remove() functions

- Check platform resource before parsing any other data from DT/platform

- Use dev_err on failure from i2c_add_numbered_adapter()

- Use pr_info instead of printk for KERN_INFO

---
 drivers/i2c/busses/i2c-pxa.c | 81 ++++++++++++++++++--------------------------
 1 file changed, 33 insertions(+), 48 deletions(-)
drivers/i2c/busses/i2c-pxa.c +33 -48
index b8b3856..0a8b3bb 100644
@@ -1166,10 +1166,22 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	struct resource *res = NULL;
 	int ret, irq;
 
-	i2c = kzalloc(sizeof(struct pxa_i2c), GFP_KERNEL);
+	i2c = devm_kzalloc(&dev->dev, sizeof(struct pxa_i2c), GFP_KERNEL);
 	if (!i2c) {
-		ret = -ENOMEM;
-		goto emalloc;
+		dev_err(&dev->dev, "memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&dev->dev, "no mem resource\n");
+		return -ENODEV;
+	}
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		dev_err(&dev->dev, "no irq resource: %d\n", irq);
+		return irq;
 	}
 
 	/* Default adapter num to device id; i2c_pxa_probe_dt can override. */
@@ -1179,19 +1191,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	if (ret > 0)
 		ret = i2c_pxa_probe_pdata(dev, i2c, &i2c_type);
 	if (ret < 0)
-		goto eclk;
-
-	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	irq = platform_get_irq(dev, 0);
-	if (res == NULL || irq < 0) {
-		ret = -ENODEV;
-		goto eclk;
-	}
-
-	if (!request_mem_region(res->start, resource_size(res), res->name)) {
-		ret = -ENOMEM;
-		goto eclk;
-	}
+		return ret;
 
 	i2c->adap.owner   = THIS_MODULE;
 	i2c->adap.retries = 5;
@@ -1201,16 +1201,17 @@ static int i2c_pxa_probe(struct platform_device *dev)
 
 	strlcpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name));
 
-	i2c->clk = clk_get(&dev->dev, NULL);
+	i2c->clk = devm_clk_get(&dev->dev, NULL);
 	if (IS_ERR(i2c->clk)) {
-		ret = PTR_ERR(i2c->clk);
-		goto eclk;
+		dev_err(&dev->dev, "failed to get the clk\n");
+		return PTR_ERR(i2c->clk);
 	}
 
-	i2c->reg_base = ioremap(res->start, resource_size(res));
-	if (!i2c->reg_base) {
-		ret = -EIO;
-		goto eremap;
+	i2c->reg_base = devm_ioremap_resource(&dev->dev, res);
+	if (IS_ERR(i2c->reg_base)) {
+		dev_err(&dev->dev, "failed to map resource: %ld\n",
+			PTR_ERR(i2c->reg_base));
+		return PTR_ERR(i2c->reg_base);
 	}
 
 	i2c->reg_ibmr = i2c->reg_base + pxa_reg_layout[i2c_type].ibmr;
@@ -1252,11 +1253,13 @@ static int i2c_pxa_probe(struct platform_device *dev)
 		i2c->adap.algo = &i2c_pxa_pio_algorithm;
 	} else {
 		i2c->adap.algo = &i2c_pxa_algorithm;
-		ret = request_irq(irq, i2c_pxa_handler,
+		ret = devm_request_irq(&dev->dev, irq, i2c_pxa_handler,
 				IRQF_SHARED | IRQF_NO_SUSPEND,
 				dev_name(&dev->dev), i2c);
-		if (ret)
+		if (ret) {
+			dev_err(&dev->dev, "failed to request irq: %d\n", ret);
 			goto ereqirq;
+		}
 	}
 
 	i2c_pxa_reset(i2c);
@@ -1269,33 +1272,22 @@ static int i2c_pxa_probe(struct platform_device *dev)
 
 	ret = i2c_add_numbered_adapter(&i2c->adap);
 	if (ret < 0) {
-		printk(KERN_INFO "I2C: Failed to add bus\n");
-		goto eadapt;
+		dev_err(&dev->dev, "failed to add bus: %d\n", ret);
+		goto ereqirq;
 	}
 
 	platform_set_drvdata(dev, i2c);
 
 #ifdef CONFIG_I2C_PXA_SLAVE
-	printk(KERN_INFO "I2C: %s: PXA I2C adapter, slave address %d\n",
-	       dev_name(&i2c->adap.dev), i2c->slave_addr);
+	dev_info(&i2c->adap.dev, " PXA I2C adapter, slave address %d\n",
+		i2c->slave_addr);
 #else
-	printk(KERN_INFO "I2C: %s: PXA I2C adapter\n",
-	       dev_name(&i2c->adap.dev));
+	dev_info(&i2c->adap.dev, " PXA I2C adapter\n");
 #endif
 	return 0;
 
-eadapt:
-	if (!i2c->use_pio)
-		free_irq(irq, i2c);
 ereqirq:
 	clk_disable_unprepare(i2c->clk);
-	iounmap(i2c->reg_base);
-eremap:
-	clk_put(i2c->clk);
-eclk:
-	kfree(i2c);
-emalloc:
-	release_mem_region(res->start, resource_size(res));
 	return ret;
 }
 
@@ -1304,15 +1296,8 @@ static int i2c_pxa_remove(struct platform_device *dev)
 	struct pxa_i2c *i2c = platform_get_drvdata(dev);
 
 	i2c_del_adapter(&i2c->adap);
-	if (!i2c->use_pio)
-		free_irq(i2c->irq, i2c);
 
 	clk_disable_unprepare(i2c->clk);
-	clk_put(i2c->clk);
-
-	iounmap(i2c->reg_base);
-	release_mem_region(i2c->iobase, i2c->iosize);
-	kfree(i2c);
 
 	return 0;
 }
Signature · 1 line
1.9.1
#21 lore raw

PATCH v2 7/12 i2c:pxa: Use devm_ variants in probe function

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1206

Quoted 10 lines · Vaibhav Hiremath
drivers/i2c/busses/i2c-pxa.c +2 -3
@@ -1201,16 +1201,17 @@ static int i2c_pxa_probe(struct platform_device *dev)
 
 	strlcpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name));
 
-	i2c->clk = clk_get(&dev->dev, NULL);
+	i2c->clk = devm_clk_get(&dev->dev, NULL);
 	if (IS_ERR(i2c->clk)) {
-		ret = PTR_ERR(i2c->clk);
-		goto eclk;
+		dev_err(&dev->dev, "failed to get the clk\n");

For consistency's sake, please use :

		dev_err(&dev->dev, "failed to get the clk: %ld\n", PTR_ERR(i2c->clk));

Once that is done, you can add my :

Signature · 1 line
Robert
#22 lore raw

PATCH v2 7/12 i2c:pxa: Use devm_ variants in probe function

Quoted 6 lines · Robert Jarzmik
Quoted 4 lines · Vaibhav Hiremath
drivers/i2c/busses/i2c-pxa.c +0 -0
@@ -1201,16 +1201,17 @@ static int i2c_pxa_probe(struct platform_device *dev)
 
  	strlcpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name));
 
Quoted 9 lines

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1206

Quoted 6 lines
drivers/i2c/busses/i2c-pxa.c +2 -3
-	i2c->clk = clk_get(&dev->dev, NULL);
+	i2c->clk = devm_clk_get(&dev->dev, NULL);
  	if (IS_ERR(i2c->clk)) {
-		ret = PTR_ERR(i2c->clk);
-		goto eclk;
+		dev_err(&dev->dev, "failed to get the clk\n");

For consistency's sake, please use :

		dev_err(&dev->dev, "failed to get the clk: %ld\n", PTR_ERR(i2c->clk));

Will include it in next version.

Quoted 3 lines

Once that is done, you can add my :

Thanks for your ack

Thanks,
Vaibhav

#23 lore raw

PATCH v2 8/12 i2c: pxa: enable/disable i2c module across msg xfer

In reply to Vaibhav Hiremath

From: Yi Zhang <[email protected]>

Enable i2c module/unit before transmission and disable when it finishes.

why?
It's because the i2c bus may be distrubed if the slave device, typically a touch, powers on.

As we do not want to break slave mode support, this patch introduces DT property to control disable of the I2C module after xfer in master mode of operation.

i2c-disable-after-xfer : If set, driver will disable I2C module after msg xfer

---
 drivers/i2c/busses/i2c-pxa.c | 41 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 39 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-pxa.c +39 -2
index 0a8b3bb..c753411 100644
@@ -161,6 +161,7 @@ struct pxa_i2c {
 	unsigned char		master_code;
 	unsigned long		rate;
 	bool			highmode_enter;
+	bool			disable_after_xfer;
 };
 
 #define _IBMR(i2c)	((i2c)->reg_ibmr)
@@ -286,6 +287,22 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
 static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
 static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id);
 
+/* enable/disable i2c unit */
+static inline int i2c_pxa_is_enabled(struct pxa_i2c *i2c)
+{
+	return (readl(_ICR(i2c)) & ICR_IUE);
+}
+
+static inline void i2c_pxa_enable(struct pxa_i2c *i2c, bool enable)
+{
+	if (enable && !i2c_pxa_is_enabled(i2c)) {
+		writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
+		udelay(100);
+	} else {
+		writel(readl(_ICR(i2c)) & ~ICR_IUE, _ICR(i2c));
+	}
+}
+
 static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
 {
 	return !(readl(_ICR(i2c)) & ICR_SCLE);
@@ -482,8 +499,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
 	i2c_pxa_set_slave(i2c, 0);
 
 	/* enable unit */
-	writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
-	udelay(100);
+	i2c_pxa_enable(i2c, true);
 }
 
 
@@ -840,6 +856,9 @@ static int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
 	struct pxa_i2c *i2c = adap->algo_data;
 	int ret, i;
 
+	/* Enable i2c unit */
+	i2c_pxa_enable(i2c, true);
+
 	/* If the I2C controller is disabled we need to reset it
 	  (probably due to a suspend/resume destroying state). We do
 	  this here as we can then avoid worrying about resuming the
@@ -860,6 +879,11 @@ static int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
 	ret = -EREMOTEIO;
  out:
 	i2c_pxa_set_slave(i2c, ret);
+
+	/* disable i2c unit */
+	if (i2c->disable_after_xfer)
+		i2c_pxa_enable(i2c, false);
+
 	return ret;
 }
 
@@ -1075,6 +1099,9 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num
 	struct pxa_i2c *i2c = adap->algo_data;
 	int ret, i;
 
+	/* Enable i2c unit */
+	i2c_pxa_enable(i2c, true);
+
 	for (i = adap->retries; i >= 0; i--) {
 		ret = i2c_pxa_do_xfer(i2c, msgs, num);
 		if (ret != I2C_RETRY)
@@ -1088,6 +1115,10 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num
 	ret = -EREMOTEIO;
  out:
 	i2c_pxa_set_slave(i2c, ret);
+	/* disable i2c unit */
+	if (i2c->disable_after_xfer)
+		i2c_pxa_enable(i2c, false);
+
 	return ret;
 }
 
@@ -1128,6 +1159,9 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
 	/* For device tree we always use the dynamic or alias-assigned ID */
 	i2c->adap.nr = -1;
 
+	i2c->disable_after_xfer = of_property_read_bool(np,
+				"i2c-disable-after-xfer");
+
 	if (of_get_property(np, "mrvl,i2c-polling", NULL))
 		i2c->use_pio = 1;
 	if (of_get_property(np, "mrvl,i2c-fast-mode", NULL))
@@ -1278,6 +1312,9 @@ static int i2c_pxa_probe(struct platform_device *dev)
 
 	platform_set_drvdata(dev, i2c);
 
+	if (i2c->disable_after_xfer)
+		i2c_pxa_enable(i2c, false);
+
 #ifdef CONFIG_I2C_PXA_SLAVE
 	dev_info(&i2c->adap.dev, " PXA I2C adapter, slave address %d\n",
 		i2c->slave_addr);
Signature · 1 line
1.9.1
#24 lore raw

PATCH v2 8/12 i2c: pxa: enable/disable i2c module across msg xfer

Quoted 57 lines · Vaibhav Hiremath

#define _IBMR(i2c) ((i2c)->reg_ibmr)

drivers/i2c/busses/i2c-pxa.c +25 -2
@@ -286,6 +287,22 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
 static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
 static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id);
 
+/* enable/disable i2c unit */
+static inline int i2c_pxa_is_enabled(struct pxa_i2c *i2c)
+{
+	return (readl(_ICR(i2c)) & ICR_IUE);
+}
+
+static inline void i2c_pxa_enable(struct pxa_i2c *i2c, bool enable)
+{
+	if (enable && !i2c_pxa_is_enabled(i2c)) {
+		writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
+		udelay(100);
+	} else {
+		writel(readl(_ICR(i2c)) & ~ICR_IUE, _ICR(i2c));
+	}
+}
+
 static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
 {
 	return !(readl(_ICR(i2c)) & ICR_SCLE);
@@ -482,8 +499,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
 	i2c_pxa_set_slave(i2c, 0);
 
 	/* enable unit */
-	writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
-	udelay(100);
+	i2c_pxa_enable(i2c, true);
 }
 
 
@@ -840,6 +856,9 @@ static int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
 	struct pxa_i2c *i2c = adap->algo_data;
 	int ret, i;
 
+	/* Enable i2c unit */
+	i2c_pxa_enable(i2c, true);
+
 	/* If the I2C controller is disabled we need to reset it
 	  (probably due to a suspend/resume destroying state). We do
 	  this here as we can then avoid worrying about resuming the
@@ -860,6 +879,11 @@ static int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
 	ret = -EREMOTEIO;
  out:
 	i2c_pxa_set_slave(i2c, ret);
+
+	/* disable i2c unit */
+	if (i2c->disable_after_xfer)
+		i2c_pxa_enable(i2c, false);
+
 	return ret;
 }
 

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num · line 1103

Quoted 5 lines
drivers/i2c/busses/i2c-pxa.c +2 -0
@@ -1075,6 +1099,9 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num
 	struct pxa_i2c *i2c = adap->algo_data;
 	int ret, i;
 
+	/* Enable i2c unit */
+	i2c_pxa_enable(i2c, true);

Okay, what happens in master mode when we get there on the 2nd xfer :
- i2c is enabled AFAIU.
- as a consequence i2c_pxa_is_enabled() returns true
- as a consequence, i2c_pxa_enable() _disables_ the i2c, right ?
- as a consequence i2c is broken

Is this correct, because if it is the patch needs a rework ?

Cheers.

--
Robert

#25 lore raw

PATCH v2 8/12 i2c: pxa: enable/disable i2c module across msg xfer

Quoted 70 lines · Robert Jarzmik
Quoted 57 lines · Vaibhav Hiremath
  #define _IBMR(i2c)	((i2c)->reg_ibmr)
drivers/i2c/busses/i2c-pxa.c +25 -2
@@ -286,6 +287,22 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
  static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
  static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id);
 
+/* enable/disable i2c unit */
+static inline int i2c_pxa_is_enabled(struct pxa_i2c *i2c)
+{
+	return (readl(_ICR(i2c)) & ICR_IUE);
+}
+
+static inline void i2c_pxa_enable(struct pxa_i2c *i2c, bool enable)
+{
+	if (enable && !i2c_pxa_is_enabled(i2c)) {
+		writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
+		udelay(100);
+	} else {
+		writel(readl(_ICR(i2c)) & ~ICR_IUE, _ICR(i2c));
+	}
+}
+
  static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
  {
  	return !(readl(_ICR(i2c)) & ICR_SCLE);
@@ -482,8 +499,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
  	i2c_pxa_set_slave(i2c, 0);
 
  	/* enable unit */
-	writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
-	udelay(100);
+	i2c_pxa_enable(i2c, true);
  }
 
 
@@ -840,6 +856,9 @@ static int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
  	struct pxa_i2c *i2c = adap->algo_data;
  	int ret, i;
 
+	/* Enable i2c unit */
+	i2c_pxa_enable(i2c, true);
+
  	/* If the I2C controller is disabled we need to reset it
  	  (probably due to a suspend/resume destroying state). We do
  	  this here as we can then avoid worrying about resuming the
@@ -860,6 +879,11 @@ static int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
  	ret = -EREMOTEIO;
   out:
  	i2c_pxa_set_slave(i2c, ret);
+
+	/* disable i2c unit */
+	if (i2c->disable_after_xfer)
+		i2c_pxa_enable(i2c, false);
+
  	return ret;
  }
 

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num · line 1103

Quoted 5 lines
drivers/i2c/busses/i2c-pxa.c +2 -0
@@ -1075,6 +1099,9 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num
  	struct pxa_i2c *i2c = adap->algo_data;
  	int ret, i;
 
+	/* Enable i2c unit */
+	i2c_pxa_enable(i2c, true);

Okay, what happens in master mode when we get there on the 2nd xfer :
- i2c is enabled AFAIU.
- as a consequence i2c_pxa_is_enabled() returns true
- as a consequence, i2c_pxa_enable() _disables_ the i2c, right ?
- as a consequence i2c is broken

Quoted 2 lines

Is this correct, because if it is the patch needs a rework ?

Good catch :)

I will fix this in next version.

Thanks,
Vaibhav

#26 lore raw

PATCH v2 8/12 i2c: pxa: enable/disable i2c module across msg xfer

Quoted 77 lines · Vaibhav Hiremath
Quoted 74 lines · Robert Jarzmik
Quoted 60 lines · Vaibhav Hiremath
  #define _IBMR(i2c)    ((i2c)->reg_ibmr)
drivers/i2c/busses/i2c-pxa.c +16 -0
@@ -286,6 +287,22 @@ static void i2c_pxa_scream_blue_murder(struct
 pxa_i2c *i2c, const char *why)
  static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
  static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id);
 
+/* enable/disable i2c unit */
+static inline int i2c_pxa_is_enabled(struct pxa_i2c *i2c)
+{
+    return (readl(_ICR(i2c)) & ICR_IUE);
+}
+
+static inline void i2c_pxa_enable(struct pxa_i2c *i2c, bool enable)
+{
+    if (enable && !i2c_pxa_is_enabled(i2c)) {
+        writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
+        udelay(100);
+    } else {
+        writel(readl(_ICR(i2c)) & ~ICR_IUE, _ICR(i2c));
+    }
+}
+
  static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
  {
      return !(readl(_ICR(i2c)) & ICR_SCLE);
drivers/i2c/busses/i2c-pxa.c +4 -2
@@ -482,8 +499,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
      i2c_pxa_set_slave(i2c, 0);
 
      /* enable unit */
-    writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
-    udelay(100);
+    i2c_pxa_enable(i2c, true);
  }
 
 
@@ -840,6 +856,9 @@ static int i2c_pxa_pio_xfer(struct i2c_adapter
 *adap,
      struct pxa_i2c *i2c = adap->algo_data;
      int ret, i;
 
+    /* Enable i2c unit */
+    i2c_pxa_enable(i2c, true);
+
      /* If the I2C controller is disabled we need to reset it
        (probably due to a suspend/resume destroying state). We do

this here as we can then avoid worrying about resuming the

drivers/i2c/busses/i2c-pxa.c +5 -0
@@ -860,6 +879,11 @@ static int i2c_pxa_pio_xfer(struct i2c_adapter
 *adap,
      ret = -EREMOTEIO;
   out:
      i2c_pxa_set_slave(i2c, ret);
+
+    /* disable i2c unit */
+    if (i2c->disable_after_xfer)
+        i2c_pxa_enable(i2c, false);
+
      return ret;
  }

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_xfer(struct i2c_adapter · line 1104

Quoted 6 lines
drivers/i2c/busses/i2c-pxa.c +2 -0
@@ -1075,6 +1099,9 @@ static int i2c_pxa_xfer(struct i2c_adapter
 *adap, struct i2c_msg msgs[], int num
      struct pxa_i2c *i2c = adap->algo_data;
      int ret, i;
 
+    /* Enable i2c unit */
+    i2c_pxa_enable(i2c, true);

Okay, what happens in master mode when we get there on the 2nd xfer :
- i2c is enabled AFAIU.
- as a consequence i2c_pxa_is_enabled() returns true
- as a consequence, i2c_pxa_enable() _disables_ the i2c, right ?
- as a consequence i2c is broken

Quoted 7 lines
Quoted 2 lines

Is this correct, because if it is the patch needs a rework ?

Good catch :)

I will fix this in next version.

I have taken care of all comments on the 3 patches.

Just in case if you have any comments on other patches in series, I will wait for a day before pushing next version.

Thanks,
Vaibhav

#27 lore raw

PATCH v2 8/12 i2c: pxa: enable/disable i2c module across msg xfer

Quoted 4 lines · Vaibhav Hiremath

I have taken care of all comments on the 3 patches.

Just in case if you have any comments on other patches in series, I will wait for a day before pushing next version.

That would be great, yeah. I'll make another pass tomorrow. If that works for you, and if you release your next version before Sunday morning (french local time), I'll make another review for Sunday evening of all the patches.

Cheers.

Signature · 1 line
Robert
#28 lore raw

PATCH v2 9/12 Documentation: binding: add new property 'disable_after_xfer' to i2c-pxa

In reply to Vaibhav Hiremath

Driver now supports enable/disable across msg xfer, which user can control it by new DT property -

i2c-disable-after-xfer : If set, driver will disable I2C module after msg
xfer and enable it back before xfer.

---
 Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 5 +++++
 1 file changed, 5 insertions(+)
Documentation/devicetree/bindings/i2c/i2c-pxa.txt +5 -0
index 12b78ac..9657db5 100644
@@ -18,6 +18,11 @@ Recommended properties :
    status register of i2c controller instead.
  - mrvl,i2c-fast-mode : Enable fast mode of i2c controller.
 
+Optional properties :
+
+ - i2c-disable-after-xfer : If set, driver will disable I2C module
+   after msg xfer and enable it again before xfer.
+
 Examples:
 	twsi1: i2c at d4011000 {
 		compatible = "mrvl,mmp-twsi";
Signature · 1 line
1.9.1
#29 lore raw

PATCH v2 10/12 i2c: pxa: Add support for pxa910/988 & new configuration features

In reply to Vaibhav Hiremath

PXA910 family of devices supports SCLK adjustment through TWSI_ILCR & TWSI_IWCR registers (for all supported modes). This patch also adds these two new register entries to "struct pxa_reg_layout" and "struct pxa_i2c".

As discussed in the previous patch-series, the idea here is to add standard DT properties for ilcr and iwcr configuration fields.
In case of Master ilcr is used for low/high time and in case of slave mode of operation iwcr is used for setup/hold time.

---
 drivers/i2c/busses/i2c-pxa.c | 42 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-pxa.c +41 -1
index c753411..97f9c7c 100644
@@ -46,12 +46,15 @@ struct pxa_reg_layout {
 	u32 icr;
 	u32 isr;
 	u32 isar;
+	u32 ilcr;
+	u32 iwcr;
 };
 
 enum pxa_i2c_types {
 	REGS_PXA2XX,
 	REGS_PXA3XX,
 	REGS_CE4100,
+	REGS_PXA910,
 };
 
 /*
@@ -79,12 +82,22 @@ static struct pxa_reg_layout pxa_reg_layout[] = {
 		.isr =	0x04,
 		/* no isar register */
 	},
+	[REGS_PXA910] = {
+		.ibmr = 0x00,
+		.idbr = 0x08,
+		.icr =	0x10,
+		.isr =	0x18,
+		.isar = 0x20,
+		.ilcr = 0x28,
+		.iwcr = 0x30,
+	},
 };
 
 static const struct platform_device_id i2c_pxa_id_table[] = {
 	{ "pxa2xx-i2c",		REGS_PXA2XX },
 	{ "pxa3xx-pwri2c",	REGS_PXA3XX },
 	{ "ce4100-i2c",		REGS_CE4100 },
+	{ "pxa910-i2c",		REGS_PXA910 },
 	{ },
 };
 MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
@@ -124,6 +137,24 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
 #define ISR_SAD		(1 << 9)	   /* slave address detected */
 #define ISR_BED		(1 << 10)	   /* bus error no ACK/NAK */
 
+/* bit field shift & mask */
+#define ILCR_SLV_SHIFT		0
+#define ILCR_SLV_MASK		(0x1FF << ILCR_SLV_SHIFT)
+#define ILCR_FLV_SHIFT		9
+#define ILCR_FLV_MASK		(0x1FF << ILCR_FLV_SHIFT)
+#define ILCR_HLVL_SHIFT		18
+#define ILCR_HLVL_MASK		(0x1FF << ILCR_HLVL_SHIFT)
+#define ILCR_HLVH_SHIFT		27
+#define ILCR_HLVH_MASK		(0x1F << ILCR_HLVH_SHIFT)
+
+#define IWCR_CNT_SHIFT		0
+#define IWCR_CNT_MASK		(0x1F << IWCR_CNT_SHIFT)
+#define IWCR_HS_CNT1_SHIFT	5
+#define IWCR_HS_CNT1_MASK	(0x1F << IWCR_HS_CNT1_SHIFT)
+#define IWCR_HS_CNT2_SHIFT	10
+#define IWCR_HS_CNT2_MASK	(0x1F << IWCR_HS_CNT2_SHIFT)
+
+
 struct pxa_i2c {
 	spinlock_t		lock;
 	wait_queue_head_t	wait;
@@ -150,6 +181,8 @@ struct pxa_i2c {
 	void __iomem		*reg_icr;
 	void __iomem		*reg_isr;
 	void __iomem		*reg_isar;
+	void __iomem		*reg_ilcr;
+	void __iomem		*reg_iwcr;
 
 	unsigned long		iobase;
 	unsigned long		iosize;
@@ -169,6 +202,8 @@ struct pxa_i2c {
 #define _ICR(i2c)	((i2c)->reg_icr)
 #define _ISR(i2c)	((i2c)->reg_isr)
 #define _ISAR(i2c)	((i2c)->reg_isar)
+#define _ILCR(i2c)	((i2c)->reg_ilcr)
+#define _IWCR(i2c)	((i2c)->reg_iwcr)
 
 /*
  * I2C Slave mode address
@@ -1141,7 +1176,7 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = {
 static const struct of_device_id i2c_pxa_dt_ids[] = {
 	{ .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX },
 	{ .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX },
-	{ .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA2XX },
+	{ .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA910 },
 	{}
 };
 MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
@@ -1255,6 +1290,11 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	if (i2c_type != REGS_CE4100)
 		i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
 
+	if (i2c_type == REGS_PXA910) {
+		i2c->reg_ilcr = i2c->reg_base + pxa_reg_layout[i2c_type].ilcr;
+		i2c->reg_iwcr = i2c->reg_base + pxa_reg_layout[i2c_type].iwcr;
+	}
+
 	i2c->iobase = res->start;
 	i2c->iosize = resource_size(res);
 
Signature · 1 line
1.9.1
#30 lore raw

PATCH v2 11/12 i2c: pxa: Add ILCR (tLow & tHigh) configuration support

In reply to Vaibhav Hiremath

With addition of PXA910 family of devices, the TWSI module supports SCL clock adjustment using ILCR register.

This patch enables the control and configuration of ICLR through DT properties,

i2c-sclk-high-time-ns:
SCLK high time (tHigh), for standard/fast/high speed mode
i2c-sclk-low-time-ns:
SCLK low time (tLow), for standard/fast/high speed mode

Note that in case of standard and fast mod, the tLow and tHigh counters are same, and software will use tLow value.

---
 drivers/i2c/busses/i2c-pxa.c | 66 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 60 insertions(+), 6 deletions(-)
drivers/i2c/busses/i2c-pxa.c +60 -6
index 97f9c7c..03b70f8 100644
@@ -195,6 +195,9 @@ struct pxa_i2c {
 	unsigned long		rate;
 	bool			highmode_enter;
 	bool			disable_after_xfer;
+
+	unsigned int		sclk_thigh_load_cnt;
+	unsigned int		sclk_tlow_load_cnt;
 };
 
 #define _IBMR(i2c)	((i2c)->reg_ibmr)
@@ -507,6 +510,33 @@ static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode)
 #define i2c_pxa_set_slave(i2c, err)	do { } while (0)
 #endif
 
+static void i2c_pxa_do_sclk_adj(struct pxa_i2c *i2c)
+{
+	unsigned int reg_ilcr;
+
+	reg_ilcr = readl(_ILCR(i2c));
+
+	/* For standard/fast mode tlow and thigh counters are same */
+	if (i2c->sclk_tlow_load_cnt) {
+		unsigned int mask, shift;
+
+		mask = i2c->high_mode ? ILCR_HLVL_MASK :
+			i2c->fast_mode ? ILCR_FLV_MASK : ILCR_SLV_MASK;
+		shift = i2c->high_mode ? ILCR_HLVL_SHIFT :
+			i2c->fast_mode ? ILCR_FLV_SHIFT : ILCR_SLV_SHIFT;
+
+		reg_ilcr &= ~mask;
+		reg_ilcr |= i2c->sclk_tlow_load_cnt << shift;
+	}
+
+	if (i2c->high_mode && i2c->sclk_thigh_load_cnt) {
+		reg_ilcr &= ~ILCR_HLVH_MASK;
+		reg_ilcr |= i2c->sclk_thigh_load_cnt << ILCR_HLVH_SHIFT;
+	}
+
+	writel(reg_ilcr, _ILCR(i2c));
+}
+
 static void i2c_pxa_reset(struct pxa_i2c *i2c)
 {
 	pr_debug("Resetting I2C Controller Unit\n");
@@ -526,6 +556,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
 	writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
 	writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c));
 
+	i2c_pxa_do_sclk_adj(i2c);
+
 #ifdef CONFIG_I2C_PXA_SLAVE
 	dev_info(&i2c->adap.dev, "Enabling slave mode\n");
 	writel(readl(_ICR(i2c)) | ICR_SADIE | ICR_ALDIE | ICR_SSDIE, _ICR(i2c));
@@ -1204,6 +1236,26 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
 
 	*i2c_types = (long)(of_id->data);
 
+	/* optional properties */
+	if (of_device_is_compatible(np, "mrvl,mmp-twsi")) {
+		unsigned int tlow = 0, thigh = 0;
+		unsigned int clk_ns;
+
+		/* clock time in nsec */
+		clk_ns = 1000000 / (i2c->rate / 1000);
+
+		of_property_read_u32(np, "i2c-sclk-high-time-ns", &thigh);
+		i2c->sclk_thigh_load_cnt = thigh / clk_ns;
+
+		of_property_read_u32(np, "i2c-sclk-low-time-ns", &tlow);
+		i2c->sclk_tlow_load_cnt = tlow / clk_ns;
+
+		/* For std/fast mode tlow & thigh have same bit-fields */
+		if (!i2c->high_mode &&
+			(i2c->sclk_tlow_load_cnt != i2c->sclk_thigh_load_cnt))
+			dev_warn(&i2c->adap.dev,
+				"mismatch of tLow & tHigh values, using tLow\n");
+	}
 	return 0;
 }
 
@@ -1253,6 +1305,14 @@ static int i2c_pxa_probe(struct platform_device *dev)
 		return irq;
 	}
 
+	i2c->clk = devm_clk_get(&dev->dev, NULL);
+	if (IS_ERR(i2c->clk)) {
+		dev_err(&dev->dev, "failed to get the clk\n");
+		return PTR_ERR(i2c->clk);
+	}
+
+	i2c->rate = clk_get_rate(i2c->clk);
+
 	/* Default adapter num to device id; i2c_pxa_probe_dt can override. */
 	i2c->adap.nr = dev->id;
 
@@ -1270,12 +1330,6 @@ static int i2c_pxa_probe(struct platform_device *dev)
 
 	strlcpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name));
 
-	i2c->clk = devm_clk_get(&dev->dev, NULL);
-	if (IS_ERR(i2c->clk)) {
-		dev_err(&dev->dev, "failed to get the clk\n");
-		return PTR_ERR(i2c->clk);
-	}
-
 	i2c->reg_base = devm_ioremap_resource(&dev->dev, res);
 	if (IS_ERR(i2c->reg_base)) {
 		dev_err(&dev->dev, "failed to map resource: %ld\n",
Signature · 1 line
1.9.1
#31 lore raw

PATCH v2 11/12 i2c: pxa: Add ILCR (tLow & tHigh) configuration support

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev)

Quoted 7 lines · Vaibhav Hiremath
drivers/i2c/busses/i2c-pxa.c +6 -0
+	i2c->clk = devm_clk_get(&dev->dev, NULL);
+	if (IS_ERR(i2c->clk)) {
+		dev_err(&dev->dev, "failed to get the clk\n");
+		dev_err(&dev->dev, "failed to get the clk: %ld\n", PTR_ERR(i2c->clk));
 
+		return PTR_ERR(i2c->clk);
+	}

Why is this block moving up ? I can't find the reason in the commit message or in the code.

Cheers.

Signature · 1 line
Robert
#32 lore raw

PATCH v2 11/12 i2c: pxa: Add ILCR (tLow & tHigh) configuration support

Quoted 7 lines · Robert Jarzmik
Quoted 4 lines · Vaibhav Hiremath
drivers/i2c/busses/i2c-pxa.c +4 -0
+	i2c->clk = devm_clk_get(&dev->dev, NULL);
+	if (IS_ERR(i2c->clk)) {
+		dev_err(&dev->dev, "failed to get the clk\n");
+		dev_err(&dev->dev, "failed to get the clk: %ld\n", PTR_ERR(i2c->clk));
Quoted 5 lines

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1312

Quoted 2 lines
drivers/i2c/busses/i2c-pxa.c +2 -0
+		return PTR_ERR(i2c->clk);
+	}

Why is this block moving up ? I can't find the reason in the commit message or in the code.

Because of obvious reason :)

The clk_rate is being used in i2c_pxa_probe_dt() function.

Although I did not mention in commit description as I felt it is evident from the patch.
Probably should have been more descriptive here, sorry for that. I will take care of it in next version.

Thanks,
Vaibhav

#33 lore raw

PATCH v2 12/12 Documentation: binding: add sclk adjustment properties to i2c-pxa

In reply to Vaibhav Hiremath

With addition of PXA910 family of devices, the TWSI module supports new feature which allows us to adjust SCLK.
With DT properties i2c-pxa driver takes input configuration in nsec and converts it to respective bit-fields,

- i2c-sclk-low-time-ns : SCLK low time (tlow) This property is used along with mode selection.
- i2c-sclk-high-time-ns : SCLK high time (thigh)

---
 Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 13 +++++++++++++
 1 file changed, 13 insertions(+)
Documentation/devicetree/bindings/i2c/i2c-pxa.txt +13 -0
index 9657db5..0fafd91 100644
@@ -23,12 +23,25 @@ Optional properties :
  - i2c-disable-after-xfer : If set, driver will disable I2C module
    after msg xfer and enable it again before xfer.
 
+   (Applicable to PXA910 family):
+
+ - i2c-sclk-low-time-ns : SCLK low time (tlow), for standard/fast/high
+   speed mode.
+   This property is used along with mode selection. Driver uses this property
+   to set low/high time for standard and fast speed mode, as counter bit-field
+   is same for both.
+ - i2c-sclk-high-time-ns : SCLK high time (thigh), Used in case of high speed
+   mode.
+
 Examples:
 	twsi1: i2c at d4011000 {
 		compatible = "mrvl,mmp-twsi";
 		reg = <0xd4011000 0x1000>;
 		interrupts = <7>;
 		mrvl,i2c-fast-mode;
+
+		i2c-sclk-low-time-ns = <988>;
+		i2c-sclk-high-time-ns = <988>;
 	};
 	
 	twsi2: i2c at d4025000 {
Signature · 1 line
1.9.1
#34 lore raw

PATCH v2 12/12 Documentation: binding: add sclk adjustment properties to i2c-pxa

Quoted 19 lines · Vaibhav Hiremath

With addition of PXA910 family of devices, the TWSI module supports new feature which allows us to adjust SCLK.
With DT properties i2c-pxa driver takes input configuration in nsec and converts it to respective bit-fields,

- i2c-sclk-low-time-ns : SCLK low time (tlow) This property is used along with mode selection.
- i2c-sclk-high-time-ns : SCLK high time (thigh)

---
 Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 13 +++++++++++++
 1 file changed, 13 insertions(+)
Documentation/devicetree/bindings/i2c/i2c-pxa.txt +0 -0
index 9657db5..0fafd91 100644

Documentation/devicetree/bindings/i2c/i2c-pxa.txt Optional properties : · line 32

Quoted 10 lines
Documentation/devicetree/bindings/i2c/i2c-pxa.txt +7 -0
@@ -23,12 +23,25 @@ Optional properties :
  - i2c-disable-after-xfer : If set, driver will disable I2C module
    after msg xfer and enable it again before xfer.
 
+   (Applicable to PXA910 family):
+
+ - i2c-sclk-low-time-ns : SCLK low time (tlow), for standard/fast/high
+   speed mode.
+   This property is used along with mode selection. Driver uses this property
+   to set low/high time for standard and fast speed mode, as counter bit-field
+   is same for both.

This belongs below both properties, and it should be clear that both properties are required if present.

Documentation/devicetree/bindings/i2c/i2c-pxa.txt Optional properties : · line 34

Quoted 2 lines
Documentation/devicetree/bindings/i2c/i2c-pxa.txt +2 -0
+ - i2c-sclk-high-time-ns : SCLK high time (thigh), Used in case of high speed
+   mode.

Rob

#35 lore raw

PATCH v2 12/12 Documentation: binding: add sclk adjustment properties to i2c-pxa

Quoted 24 lines · Rob Herring
Quoted 22 lines · Vaibhav Hiremath

With addition of PXA910 family of devices, the TWSI module supports new feature which allows us to adjust SCLK.
With DT properties i2c-pxa driver takes input configuration in nsec and converts it to respective bit-fields,

- i2c-sclk-low-time-ns : SCLK low time (tlow) This property is used along with mode selection.
- i2c-sclk-high-time-ns : SCLK high time (thigh)

---
  Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 13 +++++++++++++
  1 file changed, 13 insertions(+)
Documentation/devicetree/bindings/i2c/i2c-pxa.txt +0 -0
index 9657db5..0fafd91 100644
@@ -23,12 +23,25 @@ Optional properties :
   - i2c-disable-after-xfer : If set, driver will disable I2C module
     after msg xfer and enable it again before xfer.
 
Quoted 11 lines

Documentation/devicetree/bindings/i2c/i2c-pxa.txt Optional properties : · line 32

Quoted 7 lines
Documentation/devicetree/bindings/i2c/i2c-pxa.txt +7 -0
+   (Applicable to PXA910 family):
+
+ - i2c-sclk-low-time-ns : SCLK low time (tlow), for standard/fast/high
+   speed mode.
+   This property is used along with mode selection. Driver uses this property
+   to set low/high time for standard and fast speed mode, as counter bit-field
+   is same for both.

This belongs below both properties, and it should be clear that both properties are required if present.

Technically, both properties are required only in case of high_mode.

As mentioned above, in case of standard and fast mode we use tLow value.

Thanks,
Vaibhav

#36 lore raw

v2 cover i2c: pxa: Fixes, cleanup and support for pxa910 family

In reply to Vaibhav Hiremath
Quoted 21 lines · Vaibhav Hiremath

This patch series fixes bugs/warnings, cleans up the code and adds support for PXA910 family of devices to PXA I2C bus driver.

There has been one attempt made sometime back in 2012 to upstream some of the patches from below list, but did not get follow up later. I have consolidated all the patches, cleaned them up, splited into logical changes, added new patches and submitting it now.

I tried to maintain authorship & Signoff except where I did some significant changes to the code/logic.

Link to previous post:
http://permalink.gmane.org/gmane.linux.drivers.i2c/13557

Testing:
- Basic testing on PMIC device on I2C-0 interface
- Boot tested on platform based on PXA1928
- Probe is successfully passing
- Read few registers of PMIC (RTC, ID, etc...) during boot

Quoted 2 lines

V1 => V2:
========

Ping !!!

Thanks,
Vaibhav

Quoted 37 lines

Link to V1 - http://lists.infradead.org/pipermail/linux-arm-kernel/2015-May/347012.html

- Fixed all comments from "Robert Jarzmik" and "Wolfram Sang"
- Dropped Patch
05/12: using core bus reset implementation - under work.
Will submit shortly.
08/12: NAKed and dropped
- Seperated DT binding patch from driver changes, for easy merge

Leilei Shang (1):
i2c: pxa: keep i2c irq ON in suspend

Shouming Wang (1):
i2c: pxa: Return I2C_RETRY when timeout in pio mode

Vaibhav Hiremath (8):
i2c: pxa: No need to set slave addr for i2c master mode reset
i2c: pxa: Reset i2c controller on timeout in interrupt and pio mode
i2c: pxa: Update debug function to dump more info on error i2c:pxa: Use devm_ variants in probe function
Documentation: binding: add new property 'disable_after_xfer' to

     i2c-pxa

i2c: pxa: Add support for pxa910/988 & new configuration features
i2c: pxa: Add ILCR (tLow & tHigh) configuration support
Documentation: binding: add sclk adjustment properties to i2c-pxa

Yi Zhang (1):
i2c: pxa: enable/disable i2c module across msg xfer

Yipeng Yao (1):
i2c: pxa: Remove compile warnning in 64bit mode

  Documentation/devicetree/bindings/i2c/i2c-pxa.txt |  18 ++
  drivers/i2c/busses/i2c-pxa.c                      | 267 ++++++++++++++++------
  2 files changed, 220 insertions(+), 65 deletions(-)
#37 lore raw

v2 cover i2c: pxa: Fixes, cleanup and support for pxa910 family

Quoted 24 lines · Vaibhav Hiremath
Quoted 21 lines · Vaibhav Hiremath

This patch series fixes bugs/warnings, cleans up the code and adds support for PXA910 family of devices to PXA I2C bus driver.

There has been one attempt made sometime back in 2012 to upstream some of the patches from below list, but did not get follow up later. I have consolidated all the patches, cleaned them up, splited into logical changes, added new patches and submitting it now.

I tried to maintain authorship & Signoff except where I did some significant changes to the code/logic.

Link to previous post:
http://permalink.gmane.org/gmane.linux.drivers.i2c/13557

Testing:
- Basic testing on PMIC device on I2C-0 interface
- Boot tested on platform based on PXA1928
- Probe is successfully passing
- Read few registers of PMIC (RTC, ID, etc...) during boot

Quoted 5 lines
Quoted 2 lines

V1 => V2:
========

Ping !!!

If there are no review comments on this series, can it be merged?

Thanks,
Vaibhav

Quoted 46 lines

Thanks,
Vaibhav

Quoted 40 lines

Link to V1 -
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-May/347012.html

- Fixed all comments from "Robert Jarzmik" and "Wolfram Sang"
- Dropped Patch
05/12: using core bus reset implementation - under work.
Will submit shortly.
08/12: NAKed and dropped
- Seperated DT binding patch from driver changes, for easy merge

Leilei Shang (1):
i2c: pxa: keep i2c irq ON in suspend

Shouming Wang (1):
i2c: pxa: Return I2C_RETRY when timeout in pio mode

Vaibhav Hiremath (8):
i2c: pxa: No need to set slave addr for i2c master mode reset
i2c: pxa: Reset i2c controller on timeout in interrupt and pio mode
i2c: pxa: Update debug function to dump more info on error i2c:pxa: Use devm_ variants in probe function
Documentation: binding: add new property 'disable_after_xfer' to

     i2c-pxa

i2c: pxa: Add support for pxa910/988 & new configuration features
i2c: pxa: Add ILCR (tLow & tHigh) configuration support
Documentation: binding: add sclk adjustment properties to i2c-pxa

Yi Zhang (1):
i2c: pxa: enable/disable i2c module across msg xfer

Yipeng Yao (1):
i2c: pxa: Remove compile warnning in 64bit mode

  Documentation/devicetree/bindings/i2c/i2c-pxa.txt |  18 ++
  drivers/i2c/busses/i2c-pxa.c                      | 267
++++++++++++++++------
  2 files changed, 220 insertions(+), 65 deletions(-)
#38 lore raw

v2 cover mfd: 88pm800: Add Device tree support

This patch-series adds support for Device tree to 88PM800 mfd driver. It also enabled configuration of irq clear method through DT.

Testing::
- Boot tested on PXA1928 based platform.
- probe of mfd, rtc and regulator function passing successfully.
- Basic read operations on registers

V1 => V1
=======
Link to V1: http://lkml.iu.edu/hypermail/linux/kernel/1505.3/04386.html

- Split binding changes from original commit
- Updated binding info as per Rob's suggestion
- Dropped PATCH 4/4, as discussed during review
- Dropped PATCH 3/4, as it is independent RTC code change, so will submit it separately to ease merging.
- Fixed all other minor comments

Attempt has been made to push some of the patches to the list sometime back in 2013.

Link to previous patch submission:

        https://lkml.org/lkml/2013/8/14/86

Vaibhav Hiremath (3):
mfd: 88pm800: Add device tree support
mfd: 88pm800: Allow configuration of interrupt clear method
mfd: devicetree: bindings: Add new 88pm800 mfd binding

 Documentation/devicetree/bindings/mfd/88pm800.txt | 60 +++++++++++++++++++++++
 drivers/mfd/88pm800.c                             | 40 +++++++++++++--
 include/linux/mfd/88pm80x.h                       |  6 ++-
 3 files changed, 99 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm800.txt
Signature · 1 line
1.9.1
#39 lore raw

PATCH v2 1/3 mfd: 88pm800: Add device tree support

Add DT support to the 88pm800 driver, along with compatible field for it's sub-devices (rtc, onkey and regulator)

---
 drivers/mfd/88pm800.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
drivers/mfd/88pm800.c +25 -0
index 841717a..059f01a 100644
@@ -27,6 +27,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/88pm80x.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 
 /* Interrupt Registers */
 #define PM800_INT_STATUS1		(0x05)
@@ -121,6 +122,11 @@ static const struct i2c_device_id pm80x_id_table[] = {
 };
 MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
 
+static const struct of_device_id pm80x_of_match_table[] = {
+	{ .compatible = "marvell,88pm800", },
+	{},
+};
+
 static struct resource rtc_resources[] = {
 	{
 	 .name = "88pm80x-rtc",
@@ -133,6 +139,7 @@ static struct resource rtc_resources[] = {
 static struct mfd_cell rtc_devs[] = {
 	{
 	 .name = "88pm80x-rtc",
+	 .of_compatible = "marvell,88pm80x-rtc",
 	 .num_resources = ARRAY_SIZE(rtc_resources),
 	 .resources = &rtc_resources[0],
 	 .id = -1,
@@ -151,6 +158,7 @@ static struct resource onkey_resources[] = {
 static const struct mfd_cell onkey_devs[] = {
 	{
 	 .name = "88pm80x-onkey",
+	 .of_compatible = "marvell,88pm80x-onkey",
 	 .num_resources = 1,
 	 .resources = &onkey_resources[0],
 	 .id = -1,
@@ -160,6 +168,7 @@ static const struct mfd_cell onkey_devs[] = {
 static const struct mfd_cell regulator_devs[] = {
 	{
 	 .name = "88pm80x-regulator",
+	 .of_compatible = "marvell,88pm80x-regulator",
 	 .id = -1,
 	},
 };
@@ -544,8 +553,23 @@ static int pm800_probe(struct i2c_client *client,
 	int ret = 0;
 	struct pm80x_chip *chip;
 	struct pm80x_platform_data *pdata = dev_get_platdata(&client->dev);
+	struct device_node *np = client->dev.of_node;
 	struct pm80x_subchip *subchip;
 
+	if (!pdata && !np) {
+		dev_err(&client->dev,
+			"pm80x requires platform data or of_node\n");
+		return -EINVAL;
+	}
+
+	if (!pdata) {
+		pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&client->dev, "failed to allocaate memory\n");
+			return -ENOMEM;
+		}
+	}
+
 	ret = pm80x_init(client);
 	if (ret) {
 		dev_err(&client->dev, "pm800_init fail\n");
@@ -611,6 +635,7 @@ static struct i2c_driver pm800_driver = {
 		.name = "88PM800",
 		.owner = THIS_MODULE,
 		.pm = &pm80x_pm_ops,
+		.of_match_table	= pm80x_of_match_table,
 		},
 	.probe = pm800_probe,
 	.remove = pm800_remove,
Signature · 1 line
1.9.1
#40 lore raw

PATCH v2 1/1 rtc: 88pm80x: add device tree support

In reply to Vaibhav Hiremath

Along with DT support, this patch also cleans up the unnecessary code around 'rtc_wakeup' initialization.

---
Link to V1: https://lkml.org/lkml/2015/5/29/757

 drivers/rtc/rtc-88pm80x.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)
drivers/rtc/rtc-88pm80x.c +17 -11
index 7df0579..8f66519 100644
@@ -251,17 +251,26 @@ static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume);
 static int pm80x_rtc_probe(struct platform_device *pdev)
 {
 	struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct pm80x_platform_data *pm80x_pdata =
-				dev_get_platdata(pdev->dev.parent);
-	struct pm80x_rtc_pdata *pdata = NULL;
+	struct pm80x_rtc_pdata *pdata = dev_get_platdata(&pdev->dev);
 	struct pm80x_rtc_info *info;
+	struct device_node *node = pdev->dev.of_node;
 	struct rtc_time tm;
 	unsigned long ticks = 0;
 	int ret;
 
-	pdata = dev_get_platdata(&pdev->dev);
-	if (pdata == NULL)
-		dev_warn(&pdev->dev, "No platform data!\n");
+	if (!pdata && !node) {
+		dev_err(&pdev->dev,
+			"pm80x-rtc requires platform data or of_node\n");
+		return -EINVAL;
+	}
+
+	if (!pdata) {
+		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&pdev->dev, "failed to allocate memory\n");
+			return -ENOMEM;
+		}
+	}
 
 	info =
 	    devm_kzalloc(&pdev->dev, sizeof(struct pm80x_rtc_info), GFP_KERNEL);
@@ -327,11 +336,8 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
 	regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_RTC1_USE_XO,
 			   PM800_RTC1_USE_XO);
 
-	if (pm80x_pdata) {
-		pdata = pm80x_pdata->rtc;
-		if (pdata)
-			info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup;
-	}
+	/* remeber whether this power up is caused by PMIC RTC or not */
+	info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup;
 
 	device_init_wakeup(&pdev->dev, 1);
 
Signature · 1 line
1.9.1
#41 lore raw

Re: [rtc-linux] [PATCH-v2] rtc: 88pm80x: add device tree support

Hi,

drivers/rtc/rtc-88pm80x.c static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume); · line 268

Quoted 11 lines · Vaibhav Hiremath
drivers/rtc/rtc-88pm80x.c +8 -3
-	pdata = dev_get_platdata(&pdev->dev);
-	if (pdata == NULL)
-		dev_warn(&pdev->dev, "No platform data!\n");
+	if (!pdata && !node) {
+		dev_err(&pdev->dev,
+			"pm80x-rtc requires platform data or of_node\n");
+		return -EINVAL;
+	}
+
+	if (!pdata) {
+		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);

I had troubles to follow the rtc_wakeup initialization cleanup but it seems OK. However, I'm wondering why you are adding DT support as this will always be probed from the MFD driver which pass the platform_data and avoids that allocation.

Quoted 9 lines
drivers/rtc/rtc-88pm80x.c +5 -0
+		if (!pdata) {
+			dev_err(&pdev->dev, "failed to allocate memory\n");
+			return -ENOMEM;
+		}
+	}
 
 	info =
 	    devm_kzalloc(&pdev->dev, sizeof(struct pm80x_rtc_info), GFP_KERNEL);

drivers/rtc/rtc-88pm80x.c static int pm80x_rtc_probe(struct platform_device *pdev) · line 339

Quoted 9 lines
drivers/rtc/rtc-88pm80x.c +1 -5
@@ -327,11 +336,8 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
 	regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_RTC1_USE_XO,
 			   PM800_RTC1_USE_XO);
 
-	if (pm80x_pdata) {
-		pdata = pm80x_pdata->rtc;
-		if (pdata)
-			info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup;
-	}
+	/* remeber whether this power up is caused by PMIC RTC or not */

remember -^

Signature · 3 lines
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
#42 lore raw

Re: [rtc-linux] [PATCH-v2] rtc: 88pm80x: add device tree support

Quoted 2 lines · Alexandre Belloni

Hi,

Sorry I missed this email.
Just wanted to send reminder email and saw this :)

Quoted 7 lines · Vaibhav Hiremath
Quoted 6 lines
drivers/rtc/rtc-88pm80x.c +3 -3
-	pdata = dev_get_platdata(&pdev->dev);
-	if (pdata == NULL)
-		dev_warn(&pdev->dev, "No platform data!\n");
+	if (!pdata && !node) {
+		dev_err(&pdev->dev,
+			"pm80x-rtc requires platform data or of_node\n");
Quoted 8 lines

drivers/rtc/rtc-88pm80x.c static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume); · line 268

Quoted 5 lines
drivers/rtc/rtc-88pm80x.c +5 -0
+		return -EINVAL;
+	}
+
+	if (!pdata) {
+		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);

I had troubles to follow the rtc_wakeup initialization cleanup but it seems OK.

Probably, once we have complete PM support ready then it would be easier to understand. I think as of now lets have this minimal code for rtc_wakeup.

Quoted 4 lines

However, I'm wondering why you are adding DT support as this will always be probed from the MFD driver which pass the platform_data and avoids that allocation.

You are right.

Originally, it was cleanup patch,

- remove pm80x_pdata
- Add check for pdata and np
- and around rtc_wakeup

While doing that I added this nice to have allocation.

Thanks,
Vaibhav

#43 lore raw

Re: [rtc-linux] [PATCH-v2] rtc: 88pm80x: add device tree support

Quoted 36 lines · Vaibhav Hiremath
Quoted 2 lines · Alexandre Belloni

Hi,

Sorry I missed this email.
Just wanted to send reminder email and saw this :)

Quoted 13 lines · Vaibhav Hiremath

drivers/rtc/rtc-88pm80x.c static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume); · line 268

Quoted 11 lines
drivers/rtc/rtc-88pm80x.c +8 -3
-    pdata = dev_get_platdata(&pdev->dev);
-    if (pdata == NULL)
-        dev_warn(&pdev->dev, "No platform data!\n");
+    if (!pdata && !node) {
+        dev_err(&pdev->dev,
+            "pm80x-rtc requires platform data or of_node\n");
+        return -EINVAL;
+    }
+
+    if (!pdata) {
+        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
Quoted 2 lines

I had troubles to follow the rtc_wakeup initialization cleanup but it seems OK.

Probably, once we have complete PM support ready then it would be easier to understand. I think as of now lets have this minimal code for rtc_wakeup.

Quoted 4 lines

However, I'm wondering why you are adding DT support as this will always be probed from the MFD driver which pass the platform_data and avoids that allocation.

You are right.

Quoted 8 lines

Originally, it was cleanup patch,

- remove pm80x_pdata
- Add check for pdata and np
- and around rtc_wakeup

While doing that I added this nice to have allocation.

Any update/feedback on this?

Thanks,
Vaibhav

#44 lore raw

PATCH v2 2/3 mfd: 88pm800: Allow configuration of interrupt clear method

In reply to Vaibhav Hiremath

As per the spec, bit 1 (INT_CLEAR_MODE) of reg addr 0xe (page 0) controls the method of clearing interrupt status of 88pm800 family of devices;

0: clear on read
1: clear on write

This patch allows to configure this field, through DT.

Also, as suggested by "Lee Jones" renaming DT property and variable field to appropriate name.

---
 drivers/mfd/88pm800.c       | 15 ++++++++++-----
 include/linux/mfd/88pm80x.h |  6 ++++--
 2 files changed, 14 insertions(+), 7 deletions(-)
drivers/mfd/88pm800.c +10 -5
index 059f01a..c1a6306 100644
@@ -376,7 +376,7 @@ static int device_irq_init_800(struct pm80x_chip *chip)
 {
 	struct regmap *map = chip->regmap;
 	unsigned long flags = IRQF_ONESHOT;
-	int data, mask, ret = -EINVAL;
+	int irq_clr_mode, mask, ret = -EINVAL;
 
 	if (!map || !chip->irq) {
 		dev_err(chip->dev, "incorrect parameters\n");
@@ -384,15 +384,16 @@ static int device_irq_init_800(struct pm80x_chip *chip)
 	}
 
 	/*
-	 * irq_mode defines the way of clearing interrupt. it's read-clear by
-	 * default.
+	 * irq_clr_on_wr defines the way of clearing interrupt by
+	 * read/write(0/1).  It's read-clear by default.
 	 */
 	mask =
 	    PM800_WAKEUP2_INV_INT | PM800_WAKEUP2_INT_CLEAR |
 	    PM800_WAKEUP2_INT_MASK;
 
-	data = PM800_WAKEUP2_INT_CLEAR;
-	ret = regmap_update_bits(map, PM800_WAKEUP2, mask, data);
+	irq_clr_mode = (chip->irq_clr_on_wr) ?
+		PM800_WAKEUP2_INT_WRITE_CLEAR : PM800_WAKEUP2_INT_READ_CLEAR;
+	ret = regmap_update_bits(map, PM800_WAKEUP2, mask, irq_clr_mode);
 
 	if (ret < 0)
 		goto out;
@@ -514,6 +515,7 @@ static int device_800_init(struct pm80x_chip *chip,
 	}
 
 	chip->regmap_irq_chip = &pm800_irq_chip;
+	chip->irq_clr_on_wr = pdata->irq_clr_on_wr;
 
 	ret = device_irq_init_800(chip);
 	if (ret < 0) {
@@ -568,6 +570,9 @@ static int pm800_probe(struct i2c_client *client,
 			dev_err(&client->dev, "failed to allocaate memory\n");
 			return -ENOMEM;
 		}
+
+		pdata->irq_clr_on_wr = of_property_read_bool(np,
+					"marvell,irq-clr-on-write");
 	}
 
 	ret = pm80x_init(client);
include/linux/mfd/88pm80x.h +4 -2
index 97cb283..94b3dcd 100644
@@ -77,6 +77,8 @@ enum {
 #define PM800_WAKEUP2		(0x0E)
 #define PM800_WAKEUP2_INV_INT		(1 << 0)
 #define PM800_WAKEUP2_INT_CLEAR		(1 << 1)
+#define PM800_WAKEUP2_INT_READ_CLEAR		(0 << 1)
+#define PM800_WAKEUP2_INT_WRITE_CLEAR		(1 << 1)
 #define PM800_WAKEUP2_INT_MASK		(1 << 2)
 
 #define PM800_POWER_UP_LOG	(0x10)
@@ -300,7 +302,7 @@ struct pm80x_chip {
 	struct regmap_irq_chip_data *irq_data;
 	int type;
 	int irq;
-	int irq_mode;
+	int irq_clr_on_wr;	/* '1': Clear on write, '0': Clear on read*/
 	unsigned long wu_flag;
 	spinlock_t lock;
 };
@@ -315,7 +317,7 @@ struct pm80x_platform_data {
 	 */
 	struct regulator_init_data *regulators[PM800_ID_RG_MAX];
 	unsigned int num_regulators;
-	int irq_mode;		/* Clear interrupt by read/write(0/1) */
+	int irq_clr_on_wr;		/* Clear interrupt by read/write(0/1) */
 	int batt_det;		/* enable/disable */
 	int (*plat_config)(struct pm80x_chip *chip,
 				struct pm80x_platform_data *pdata);
Signature · 1 line
1.9.1
#45 lore raw

PATCH v2 3/3 mfd: devicetree: bindings: Add new 88pm800 mfd binding

In reply to Vaibhav Hiremath

With addition of DT support to 88pm800 mfd driver, this patch adds new DT binding documentation along with respective properties.

---
 Documentation/devicetree/bindings/mfd/88pm800.txt | 60 +++++++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm800.txt
Documentation/devicetree/bindings/mfd/88pm800.txt new file +60 -0
new file mode 100644
index 0000000..b8e72df
@@ -0,0 +1,60 @@
+* Marvell 88PM8xx Power Management IC
+
+Required parent device properties:
+- compatible : "marvell,88pm800", "marvell,88pm805", "marvell,88pm860"
+- reg : the I2C slave address for the 88pm8xx chip
+- interrupts : IRQ line for the 88pm8xx chip
+- interrupt-controller: describes the 88pm8xx as an interrupt controller
+- #interrupt-cells : should be 1.
+		- The cell is the 88pm8xx local IRQ number
+
+Optional parent device properties:
+- marvell,irq-clr-on-write: indicates whether interrupt status is cleared
+  by write or read.
+  If enabled, interrupt is cleared by write else just read would do.
+
+88pm8xx family of devices consists of varied group of sub-devices:
+
+Device		 	Supply Names	 Description
+------		 	------------	 -----------
+88pm80x-onkey		:		: On key
+88pm80x-rtc		:		: RTC
+88pm80x-regulator	:		: Regulators
+
+Note: More device list will follow
+
+Example:
+
+	pmic: 88pm800 at 30 {
+		compatible = "marvell,88pm800";
+		reg = <0x30>;
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-parent = <&gic>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+
+		marvell,irq-clr-on-write;
+
+		regulators {
+			compatible = "marvell,88pm80x-regulator";
+
+			buck1a: BUCK1A {
+				regulator-compatible = "88PM800-BUCK1A";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			ldo1: LDO1 {
+				regulator-compatible = "88PM800-LDO1";
+				regulator-min-microvolt = <1700000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+
+		rtc {
+			compatible = "marvell,88pm80x-rtc";
+		};
+	};
Signature · 1 line
1.9.1
Acked-by on v2 3/3
#46 lore raw

Re: [PATCH-v2 3/3] mfd: devicetree: bindings: Add new 88pm800 mfd binding

Quoted 4 lines · Vaibhav Hiremath

With addition of DT support to 88pm800 mfd driver, this patch adds new DT binding documentation along with respective properties.

Quoted 74 lines
---
 Documentation/devicetree/bindings/mfd/88pm800.txt | 60 +++++++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm800.txt
Documentation/devicetree/bindings/mfd/88pm800.txt new file +60 -1
new file mode 100644
index 0000000..b8e72df
@@ -0,0 +1,60 @@
+* Marvell 88PM8xx Power Management IC
+
+Required parent device properties:
+- compatible : "marvell,88pm800", "marvell,88pm805", "marvell,88pm860"
+- reg : the I2C slave address for the 88pm8xx chip
+- interrupts : IRQ line for the 88pm8xx chip
+- interrupt-controller: describes the 88pm8xx as an interrupt controller
+- #interrupt-cells : should be 1.
+               - The cell is the 88pm8xx local IRQ number
+
+Optional parent device properties:
+- marvell,irq-clr-on-write: indicates whether interrupt status is cleared
+  by write or read.
+  If enabled, interrupt is cleared by write else just read would do.
+
+88pm8xx family of devices consists of varied group of sub-devices:
+
+Device                 Supply Names     Description
+------                 ------------     -----------
+88pm80x-onkey          :               : On key
+88pm80x-rtc            :               : RTC
+88pm80x-regulator      :               : Regulators
+
+Note: More device list will follow
+
+Example:
+
+       pmic: 88pm800 at 30 {
+               compatible = "marvell,88pm800";
+               reg = <0x30>;
+               interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-parent = <&gic>;
+               interrupt-controller;
+               #interrupt-cells = <1>;
+
+               marvell,irq-clr-on-write;
+
+               regulators {
+                       compatible = "marvell,88pm80x-regulator";
+
+                       buck1a: BUCK1A {
+                               regulator-compatible = "88PM800-BUCK1A";
+                               regulator-min-microvolt = <600000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+                       ldo1: LDO1 {
+                               regulator-compatible = "88PM800-LDO1";
+                               regulator-min-microvolt = <1700000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+               };
+
+               rtc {
+                       compatible = "marvell,88pm80x-rtc";
+               };
+       };
--

1.9.1

#48 lore raw

Re: [PATCH-v2 3/3] mfd: devicetree: bindings: Add new 88pm800 mfd binding

In reply to Vaibhav Hiremath

2015-06-18 3:58 GMT+09:00 Vaibhav Hiremath <[email protected]>:

Quoted 47 lines

With addition of DT support to 88pm800 mfd driver, this patch adds new DT binding documentation along with respective properties.

---
 Documentation/devicetree/bindings/mfd/88pm800.txt | 60 +++++++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm800.txt
Documentation/devicetree/bindings/mfd/88pm800.txt new file +32 -0
new file mode 100644
index 0000000..b8e72df
@@ -0,0 +1,60 @@
+* Marvell 88PM8xx Power Management IC
+
+Required parent device properties:
+- compatible : "marvell,88pm800", "marvell,88pm805", "marvell,88pm860"
+- reg : the I2C slave address for the 88pm8xx chip
+- interrupts : IRQ line for the 88pm8xx chip
+- interrupt-controller: describes the 88pm8xx as an interrupt controller
+- #interrupt-cells : should be 1.
+               - The cell is the 88pm8xx local IRQ number
+
+Optional parent device properties:
+- marvell,irq-clr-on-write: indicates whether interrupt status is cleared
+  by write or read.
+  If enabled, interrupt is cleared by write else just read would do.
+
+88pm8xx family of devices consists of varied group of sub-devices:
+
+Device                 Supply Names     Description
+------                 ------------     -----------
+88pm80x-onkey          :               : On key
+88pm80x-rtc            :               : RTC
+88pm80x-regulator      :               : Regulators
+
+Note: More device list will follow
+
+Example:
+
+       pmic: 88pm800 at 30 {
+               compatible = "marvell,88pm800";
+               reg = <0x30>;
+               interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-parent = <&gic>;

Documentation/devicetree/bindings/mfd/88pm800.txt line 42

Quoted 10 lines
Documentation/devicetree/bindings/mfd/88pm800.txt new file +10 -0
+               interrupt-controller;
+               #interrupt-cells = <1>;
+
+               marvell,irq-clr-on-write;
+
+               regulators {
+                       compatible = "marvell,88pm80x-regulator";
+
+                       buck1a: BUCK1A {
+                               regulator-compatible = "88PM800-BUCK1A";

That's a deprecated property. Documentation/devicetree/bindings/regulator/regulator.txt

Best regards,
Krzysztof

#49 lore raw

Re: [PATCH-v2 3/3] mfd: devicetree: bindings: Add new 88pm800 mfd binding

Quoted 53 lines · Krzysztof Kozlowski

2015-06-18 3:58 GMT+09:00 Vaibhav Hiremath <[email protected]>:

Quoted 52 lines

With addition of DT support to 88pm800 mfd driver, this patch adds new DT binding documentation along with respective properties.

---
  Documentation/devicetree/bindings/mfd/88pm800.txt | 60 +++++++++++++++++++++++
  1 file changed, 60 insertions(+)

create mode 100644 Documentation/devicetree/bindings/mfd/88pm800.txt

Documentation/devicetree/bindings/mfd/88pm800.txt new file +37 -0
new file mode 100644
index 0000000..b8e72df
@@ -0,0 +1,60 @@
+* Marvell 88PM8xx Power Management IC
+
+Required parent device properties:
+- compatible : "marvell,88pm800", "marvell,88pm805", "marvell,88pm860"
+- reg : the I2C slave address for the 88pm8xx chip
+- interrupts : IRQ line for the 88pm8xx chip
+- interrupt-controller: describes the 88pm8xx as an interrupt controller
+- #interrupt-cells : should be 1.
+               - The cell is the 88pm8xx local IRQ number
+
+Optional parent device properties:
+- marvell,irq-clr-on-write: indicates whether interrupt status is cleared
+  by write or read.
+  If enabled, interrupt is cleared by write else just read would do.
+
+88pm8xx family of devices consists of varied group of sub-devices:
+
+Device                 Supply Names     Description
+------                 ------------     -----------
+88pm80x-onkey          :               : On key
+88pm80x-rtc            :               : RTC
+88pm80x-regulator      :               : Regulators
+
+Note: More device list will follow
+
+Example:
+
+       pmic: 88pm800 at 30 {
+               compatible = "marvell,88pm800";
+               reg = <0x30>;
+               interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-parent = <&gic>;
+               interrupt-controller;
+               #interrupt-cells = <1>;
+
+               marvell,irq-clr-on-write;
+
Quoted 9 lines

Documentation/devicetree/bindings/mfd/88pm800.txt line 42

Quoted 5 lines
Documentation/devicetree/bindings/mfd/88pm800.txt new file +5 -0
+               regulators {
+                       compatible = "marvell,88pm80x-regulator";
+
+                       buck1a: BUCK1A {
+                               regulator-compatible = "88PM800-BUCK1A";

That's a deprecated property. Documentation/devicetree/bindings/regulator/regulator.txt

Yes,

Will replace with regulator-name and resubmit shortly with Rob's Acked-by.

Thanks,
Vaibhav

#50 lore raw

Re: [PATCH-v2 0/3] mfd: 88pm800: Add Device tree support

In reply to Vaibhav Hiremath
Quoted 31 lines · Vaibhav Hiremath

This patch-series adds support for Device tree to 88PM800 mfd driver. It also enabled configuration of irq clear method through DT.

Testing::
- Boot tested on PXA1928 based platform.
- probe of mfd, rtc and regulator function passing successfully.
- Basic read operations on registers

V1 => V1
=======
Link to V1: http://lkml.iu.edu/hypermail/linux/kernel/1505.3/04386.html

- Split binding changes from original commit
- Updated binding info as per Rob's suggestion
- Dropped PATCH 4/4, as discussed during review
- Dropped PATCH 3/4, as it is independent RTC code change, so will submit it separately to ease merging.
- Fixed all other minor comments

Attempt has been made to push some of the patches to the list sometime back in 2013.

Link to previous patch submission:

         https://lkml.org/lkml/2013/8/14/86

Vaibhav Hiremath (3):
mfd: 88pm800: Add device tree support
mfd: 88pm800: Allow configuration of interrupt clear method
mfd: devicetree: bindings: Add new 88pm800 mfd binding

Quoted 6 lines
  Documentation/devicetree/bindings/mfd/88pm800.txt | 60 +++++++++++++++++++++++
  drivers/mfd/88pm800.c                             | 40 +++++++++++++--
  include/linux/mfd/88pm80x.h                       |  6 ++-
  3 files changed, 99 insertions(+), 7 deletions(-)

create mode 100644 Documentation/devicetree/bindings/mfd/88pm800.txt

Any update on this?

If there are no review comments, then can it be queued ?

Thanks,
Vaibhav