All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V1 00/15]: support for spmi_pmic_arb v3/v5 and bug fixes
@ 2017-05-30 12:38 ` Kiran Gunda
  0 siblings, 0 replies; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  Cc: linux-arm-msm, linux-kernel, adharmap, aghayal, sboyd, Kiran Gunda

This patch series add the support for pmic arbiter hardware v3 and v5
support along with the multiple bug fixes and code cleanup.
	spmi_pmic_arb v3: Added 512 channel support.
	spmi_pmic_arb v5: Register offset changes. 
			  Multiple EEs can write to a single PPID.


Abhijeet Dharmapurikar (12):
  spmi: pmic_arb: block access of invalid read and writes
  spmi: pmic-arb: rename spmi_pmic_arb_dev to spmi_pmic_arb
  spmi: pmic-arb: fix inconsistent use of apid and chan
  spmi: pmic-arb: optimize table lookups
  spmi: pmic-arb: cleanup unrequested irqs
  spmi: pmic-arb: fix missing interrupts
  spmi: pmic-arb: clear the latched status of the interrupt
  spmi: pmic_arb: use appropriate flow handler
  spmi: pmic-arb: check apid enabled before calling the handler
  spmi: pmic_arb: add support for PMIC bus arbiter v3
  spmi-pmic-arb: fix a possible null pointer dereference
  spmi: pmic-arb: instantiate spmi_devices at arch_initcall

David Collins (1):
  spmi: pmic-arb: add support for HW version 5

Kiran Gunda (1):
  spmi: spmi-pmic-arb: enable the SPMI interrupt as a wakeup source

Subbaraman Narayanamurthy (1):
  spmi: pmic-arb: do not ack and clear peripheral interrupts in
    cleanup_irq

 drivers/spmi/spmi-pmic-arb.c | 818 ++++++++++++++++++++++++++++++-------------
 1 file changed, 578 insertions(+), 240 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH V1 00/15]: support for spmi_pmic_arb v3/v5 and bug fixes
@ 2017-05-30 12:38 ` Kiran Gunda
  0 siblings, 0 replies; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  Cc: linux-arm-msm, linux-kernel, adharmap, aghayal, sboyd, Kiran Gunda

This patch series add the support for pmic arbiter hardware v3 and v5
support along with the multiple bug fixes and code cleanup.
	spmi_pmic_arb v3: Added 512 channel support.
	spmi_pmic_arb v5: Register offset changes. 
			  Multiple EEs can write to a single PPID.


Abhijeet Dharmapurikar (12):
  spmi: pmic_arb: block access of invalid read and writes
  spmi: pmic-arb: rename spmi_pmic_arb_dev to spmi_pmic_arb
  spmi: pmic-arb: fix inconsistent use of apid and chan
  spmi: pmic-arb: optimize table lookups
  spmi: pmic-arb: cleanup unrequested irqs
  spmi: pmic-arb: fix missing interrupts
  spmi: pmic-arb: clear the latched status of the interrupt
  spmi: pmic_arb: use appropriate flow handler
  spmi: pmic-arb: check apid enabled before calling the handler
  spmi: pmic_arb: add support for PMIC bus arbiter v3
  spmi-pmic-arb: fix a possible null pointer dereference
  spmi: pmic-arb: instantiate spmi_devices at arch_initcall

David Collins (1):
  spmi: pmic-arb: add support for HW version 5

Kiran Gunda (1):
  spmi: spmi-pmic-arb: enable the SPMI interrupt as a wakeup source

Subbaraman Narayanamurthy (1):
  spmi: pmic-arb: do not ack and clear peripheral interrupts in
    cleanup_irq

 drivers/spmi/spmi-pmic-arb.c | 818 ++++++++++++++++++++++++++++++-------------
 1 file changed, 578 insertions(+), 240 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH V1 01/15] spmi: pmic_arb: block access of invalid read and writes
  2017-05-30 12:38 ` Kiran Gunda
  (?)
@ 2017-05-30 12:38 ` Kiran Gunda
  2017-05-31  0:33   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Christophe JAILLET,
	Subbaraman Narayanamurthy, David Collins, linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

The system crashes due to bad access when reading from an non configured
peripheral and when writing to peripheral which is not owned by current
ee. This patch verifies ownership to avoid crashing on
write.
For reads, since the forward mapping table, data_channel->ppid, is
towards the end of the block, we use the core size to figure the
max number of ppids supported. The table starts at an offset of 0x800
within the block, so size - 0x800 will give us the area used by the
table. Since each table is 4 bytes long (core_size - 0x800) / 4 will
gives us the number of data_channel supported.
This new protection is functional on hw v2.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 84 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 5ec3a59..df463d4 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -111,6 +111,7 @@ enum pmic_arb_cmd_op_code {
  * @ee:			the current Execution Environment
  * @min_apid:		minimum APID (used for bounding IRQ search)
  * @max_apid:		maximum APID
+ * @max_periph:		maximum number of PMIC peripherals supported by HW.
  * @mapping_table:	in-memory copy of PPID -> APID mapping table.
  * @domain:		irq domain object for PMIC IRQ domain
  * @spmic:		SPMI controller object
@@ -132,6 +133,7 @@ struct spmi_pmic_arb_dev {
 	u8			ee;
 	u16			min_apid;
 	u16			max_apid;
+	u16			max_periph;
 	u32			*mapping_table;
 	DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS);
 	struct irq_domain	*domain;
@@ -140,11 +142,13 @@ struct spmi_pmic_arb_dev {
 	const struct pmic_arb_ver_ops *ver_ops;
 	u16			*ppid_to_chan;
 	u16			last_channel;
+	u8			*chan_to_owner;
 };
 
 /**
  * pmic_arb_ver: version dependent functionality.
  *
+ * @mode:	access rights to specified pmic peripheral.
  * @non_data_cmd:	on v1 issues an spmi non-data command.
  *			on v2 no HW support, returns -EOPNOTSUPP.
  * @offset:		on v1 offset of per-ee channel.
@@ -160,6 +164,8 @@ struct spmi_pmic_arb_dev {
  *			on v2 offset of SPMI_PIC_IRQ_CLEARn.
  */
 struct pmic_arb_ver_ops {
+	int (*mode)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
+			mode_t *mode);
 	/* spmi commands (read_cmd, write_cmd, cmd) functionality */
 	int (*offset)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
 		      u32 *offset);
@@ -313,11 +319,23 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	u32 cmd;
 	int rc;
 	u32 offset;
+	mode_t mode;
 
 	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
 	if (rc)
 		return rc;
 
+	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
+	if (rc)
+		return rc;
+
+	if (!(mode & S_IRUSR)) {
+		dev_err(&pmic_arb->spmic->dev,
+			"error: impermissible read from peripheral sid:%d addr:0x%x\n",
+			sid, addr);
+		return -EPERM;
+	}
+
 	if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
 		dev_err(&ctrl->dev,
 			"pmic-arb supports 1..%d bytes per trans, but:%zu requested",
@@ -364,11 +382,23 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	u32 cmd;
 	int rc;
 	u32 offset;
+	mode_t mode;
 
 	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
 	if (rc)
 		return rc;
 
+	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
+	if (rc)
+		return rc;
+
+	if (!(mode & S_IWUSR)) {
+		dev_err(&pmic_arb->spmic->dev,
+			"error: impermissible write to peripheral sid:%d addr:0x%x\n",
+			sid, addr);
+		return -EPERM;
+	}
+
 	if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
 		dev_err(&ctrl->dev,
 			"pmic-arb supports 1..%d bytes per trans, but:%zu requested",
@@ -727,6 +757,13 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
 	return 0;
 }
 
+static int
+pmic_arb_mode_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, mode_t *mode)
+{
+	*mode = S_IRUSR | S_IWUSR;
+	return 0;
+}
+
 /* v1 offset per ee */
 static int
 pmic_arb_offset_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, u32 *offset)
@@ -745,7 +782,11 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb_dev *pa, u16 ppid)
 	 * PMIC_ARB_REG_CHNL is a table in HW mapping channel to ppid.
 	 * ppid_to_chan is an in-memory invert of that table.
 	 */
-	for (chan = pa->last_channel; ; chan++) {
+	for (chan = pa->last_channel; chan < pa->max_periph; chan++) {
+		regval = readl_relaxed(pa->cnfg +
+				      SPMI_OWNERSHIP_TABLE_REG(chan));
+		pa->chan_to_owner[chan] = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
+
 		offset = PMIC_ARB_REG_CHNL(chan);
 		if (offset >= pa->core_size)
 			break;
@@ -767,6 +808,27 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb_dev *pa, u16 ppid)
 }
 
 
+static int
+pmic_arb_mode_v2(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, mode_t *mode)
+{
+	u16 ppid = (sid << 8) | (addr >> 8);
+	u16 chan;
+	u8 owner;
+
+	chan = pa->ppid_to_chan[ppid];
+	if (!(chan & PMIC_ARB_CHAN_VALID))
+		return -ENODEV;
+
+	*mode = 0;
+	*mode |= S_IRUSR;
+
+	chan &= ~PMIC_ARB_CHAN_VALID;
+	owner = pa->chan_to_owner[chan];
+	if (owner == pa->ee)
+		*mode |= S_IWUSR;
+	return 0;
+}
+
 /* v2 offset per ppid (chan) and per ee */
 static int
 pmic_arb_offset_v2(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, u32 *offset)
@@ -836,6 +898,7 @@ static u32 pmic_arb_irq_clear_v2(u8 n)
 }
 
 static const struct pmic_arb_ver_ops pmic_arb_v1 = {
+	.mode			= pmic_arb_mode_v1,
 	.non_data_cmd		= pmic_arb_non_data_cmd_v1,
 	.offset			= pmic_arb_offset_v1,
 	.fmt_cmd		= pmic_arb_fmt_cmd_v1,
@@ -846,6 +909,7 @@ static u32 pmic_arb_irq_clear_v2(u8 n)
 };
 
 static const struct pmic_arb_ver_ops pmic_arb_v2 = {
+	.mode			= pmic_arb_mode_v2,
 	.non_data_cmd		= pmic_arb_non_data_cmd_v2,
 	.offset			= pmic_arb_offset_v2,
 	.fmt_cmd		= pmic_arb_fmt_cmd_v2,
@@ -879,6 +943,12 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
 	pa->core_size = resource_size(res);
+	if (pa->core_size <= 0x800) {
+		dev_err(&pdev->dev, "core_size is smaller than 0x800. Failing Probe\n");
+		err = -EINVAL;
+		goto err_put_ctrl;
+	}
+
 	core = devm_ioremap_resource(&ctrl->dev, res);
 	if (IS_ERR(core)) {
 		err = PTR_ERR(core);
@@ -899,6 +969,9 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 		pa->core = core;
 		pa->ver_ops = &pmic_arb_v2;
 
+		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL(0) */
+		pa->max_periph =  (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;
+
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						   "obsrvr");
 		pa->rd_base = devm_ioremap_resource(&ctrl->dev, res);
@@ -923,6 +996,15 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 			err = -ENOMEM;
 			goto err_put_ctrl;
 		}
+
+		pa->chan_to_owner = devm_kcalloc(&ctrl->dev,
+						 pa->max_periph,
+						 sizeof(*pa->chan_to_owner),
+						 GFP_KERNEL);
+		if (!pa->chan_to_owner) {
+			err = -ENOMEM;
+			goto err_put_ctrl;
+		}
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 02/15] spmi: pmic-arb: rename spmi_pmic_arb_dev to spmi_pmic_arb
  2017-05-30 12:38 ` Kiran Gunda
  (?)
  (?)
@ 2017-05-30 12:38 ` Kiran Gunda
  2017-05-31  0:46   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Greg Kroah-Hartman,
	David Collins, Subbaraman Narayanamurthy, Christophe JAILLET,
	linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

Usually *_dev best used for structures that embed a struct device in
them. spmi_pmic_arb_dev doesn't embed one. It is simply a driver data
structure. Use an appropriate name for it.

Also there are many places in the driver that left shift the bit to
generate a bit mask. Replace it with the BIT() macro.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 164 +++++++++++++++++++++----------------------
 1 file changed, 82 insertions(+), 82 deletions(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index df463d4..7f918ea 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -58,10 +58,10 @@
 
 /* Channel Status fields */
 enum pmic_arb_chnl_status {
-	PMIC_ARB_STATUS_DONE	= (1 << 0),
-	PMIC_ARB_STATUS_FAILURE	= (1 << 1),
-	PMIC_ARB_STATUS_DENIED	= (1 << 2),
-	PMIC_ARB_STATUS_DROPPED	= (1 << 3),
+	PMIC_ARB_STATUS_DONE	= BIT(0),
+	PMIC_ARB_STATUS_FAILURE	= BIT(1),
+	PMIC_ARB_STATUS_DENIED	= BIT(2),
+	PMIC_ARB_STATUS_DROPPED	= BIT(3),
 };
 
 /* Command register fields */
@@ -99,7 +99,7 @@ enum pmic_arb_cmd_op_code {
 struct pmic_arb_ver_ops;
 
 /**
- * spmi_pmic_arb_dev - SPMI PMIC Arbiter object
+ * spmi_pmic_arb - SPMI PMIC Arbiter object
  *
  * @rd_base:		on v1 "core", on v2 "observer" register base off DT.
  * @wr_base:		on v1 "core", on v2 "chnls"    register base off DT.
@@ -120,7 +120,7 @@ enum pmic_arb_cmd_op_code {
  * @ppid_to_chan	in-memory copy of PPID -> channel (APID) mapping table.
  *			v2 only.
  */
-struct spmi_pmic_arb_dev {
+struct spmi_pmic_arb {
 	void __iomem		*rd_base;
 	void __iomem		*wr_base;
 	void __iomem		*intr;
@@ -164,10 +164,10 @@ struct spmi_pmic_arb_dev {
  *			on v2 offset of SPMI_PIC_IRQ_CLEARn.
  */
 struct pmic_arb_ver_ops {
-	int (*mode)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
+	int (*mode)(struct spmi_pmic_arb *dev, u8 sid, u16 addr,
 			mode_t *mode);
 	/* spmi commands (read_cmd, write_cmd, cmd) functionality */
-	int (*offset)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
+	int (*offset)(struct spmi_pmic_arb *dev, u8 sid, u16 addr,
 		      u32 *offset);
 	u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc);
 	int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid);
@@ -178,16 +178,16 @@ struct pmic_arb_ver_ops {
 	u32 (*irq_clear)(u8 n);
 };
 
-static inline void pmic_arb_base_write(struct spmi_pmic_arb_dev *dev,
+static inline void pmic_arb_base_write(struct spmi_pmic_arb *pa,
 				       u32 offset, u32 val)
 {
-	writel_relaxed(val, dev->wr_base + offset);
+	writel_relaxed(val, pa->wr_base + offset);
 }
 
-static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb_dev *dev,
+static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb *pa,
 				       u32 offset, u32 val)
 {
-	writel_relaxed(val, dev->rd_base + offset);
+	writel_relaxed(val, pa->rd_base + offset);
 }
 
 /**
@@ -196,9 +196,10 @@ static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb_dev *dev,
  * @reg:	register's address
  * @buf:	output parameter, length must be bc + 1
  */
-static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
+static void pa_read_data(struct spmi_pmic_arb *pa, u8 *buf, u32 reg, u8 bc)
 {
-	u32 data = __raw_readl(dev->rd_base + reg);
+	u32 data = __raw_readl(pa->rd_base + reg);
+
 	memcpy(buf, &data, (bc & 3) + 1);
 }
 
@@ -209,23 +210,24 @@ static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
  * @buf:	buffer to write. length must be bc + 1.
  */
 static void
-pa_write_data(struct spmi_pmic_arb_dev *dev, const u8 *buf, u32 reg, u8 bc)
+pa_write_data(struct spmi_pmic_arb *pa, const u8 *buf, u32 reg, u8 bc)
 {
 	u32 data = 0;
+
 	memcpy(&data, buf, (bc & 3) + 1);
-	__raw_writel(data, dev->wr_base + reg);
+	pmic_arb_base_write(pa, reg, data);
 }
 
 static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
 				  void __iomem *base, u8 sid, u16 addr)
 {
-	struct spmi_pmic_arb_dev *dev = spmi_controller_get_drvdata(ctrl);
+	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
 	u32 status = 0;
 	u32 timeout = PMIC_ARB_TIMEOUT_US;
 	u32 offset;
 	int rc;
 
-	rc = dev->ver_ops->offset(dev, sid, addr, &offset);
+	rc = pa->ver_ops->offset(pa, sid, addr, &offset);
 	if (rc)
 		return rc;
 
@@ -270,22 +272,22 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
 static int
 pmic_arb_non_data_cmd_v1(struct spmi_controller *ctrl, u8 opc, u8 sid)
 {
-	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
+	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
 	unsigned long flags;
 	u32 cmd;
 	int rc;
 	u32 offset;
 
-	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, 0, &offset);
+	rc = pa->ver_ops->offset(pa, sid, 0, &offset);
 	if (rc)
 		return rc;
 
 	cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20);
 
-	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
-	pmic_arb_base_write(pmic_arb, offset + PMIC_ARB_CMD, cmd);
-	rc = pmic_arb_wait_for_done(ctrl, pmic_arb->wr_base, sid, 0);
-	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
+	raw_spin_lock_irqsave(&pa->lock, flags);
+	pmic_arb_base_write(pa, offset + PMIC_ARB_CMD, cmd);
+	rc = pmic_arb_wait_for_done(ctrl, pa->wr_base, sid, 0);
+	raw_spin_unlock_irqrestore(&pa->lock, flags);
 
 	return rc;
 }
@@ -299,7 +301,7 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
 /* Non-data command */
 static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
 {
-	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
+	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
 
 	dev_dbg(&ctrl->dev, "cmd op:0x%x sid:%d\n", opc, sid);
 
@@ -307,13 +309,13 @@ static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
 	if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
 		return -EINVAL;
 
-	return pmic_arb->ver_ops->non_data_cmd(ctrl, opc, sid);
+	return pa->ver_ops->non_data_cmd(ctrl, opc, sid);
 }
 
 static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 			     u16 addr, u8 *buf, size_t len)
 {
-	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
+	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
 	unsigned long flags;
 	u8 bc = len - 1;
 	u32 cmd;
@@ -321,16 +323,16 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	u32 offset;
 	mode_t mode;
 
-	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
+	rc = pa->ver_ops->offset(pa, sid, addr, &offset);
 	if (rc)
 		return rc;
 
-	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
+	rc = pa->ver_ops->mode(pa, sid, addr, &mode);
 	if (rc)
 		return rc;
 
 	if (!(mode & S_IRUSR)) {
-		dev_err(&pmic_arb->spmic->dev,
+		dev_err(&pa->spmic->dev,
 			"error: impermissible read from peripheral sid:%d addr:0x%x\n",
 			sid, addr);
 		return -EPERM;
@@ -353,30 +355,29 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	else
 		return -EINVAL;
 
-	cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc);
+	cmd = pa->ver_ops->fmt_cmd(opc, sid, addr, bc);
 
-	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
-	pmic_arb_set_rd_cmd(pmic_arb, offset + PMIC_ARB_CMD, cmd);
-	rc = pmic_arb_wait_for_done(ctrl, pmic_arb->rd_base, sid, addr);
+	raw_spin_lock_irqsave(&pa->lock, flags);
+	pmic_arb_set_rd_cmd(pa, offset + PMIC_ARB_CMD, cmd);
+	rc = pmic_arb_wait_for_done(ctrl, pa->rd_base, sid, addr);
 	if (rc)
 		goto done;
 
-	pa_read_data(pmic_arb, buf, offset + PMIC_ARB_RDATA0,
+	pa_read_data(pa, buf, offset + PMIC_ARB_RDATA0,
 		     min_t(u8, bc, 3));
 
 	if (bc > 3)
-		pa_read_data(pmic_arb, buf + 4,
-				offset + PMIC_ARB_RDATA1, bc - 4);
+		pa_read_data(pa, buf + 4, offset + PMIC_ARB_RDATA1, bc - 4);
 
 done:
-	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
+	raw_spin_unlock_irqrestore(&pa->lock, flags);
 	return rc;
 }
 
 static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 			      u16 addr, const u8 *buf, size_t len)
 {
-	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
+	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
 	unsigned long flags;
 	u8 bc = len - 1;
 	u32 cmd;
@@ -384,16 +385,16 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	u32 offset;
 	mode_t mode;
 
-	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
+	rc = pa->ver_ops->offset(pa, sid, addr, &offset);
 	if (rc)
 		return rc;
 
-	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
+	rc = pa->ver_ops->mode(pa, sid, addr, &mode);
 	if (rc)
 		return rc;
 
 	if (!(mode & S_IWUSR)) {
-		dev_err(&pmic_arb->spmic->dev,
+		dev_err(&pa->spmic->dev,
 			"error: impermissible write to peripheral sid:%d addr:0x%x\n",
 			sid, addr);
 		return -EPERM;
@@ -418,20 +419,18 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	else
 		return -EINVAL;
 
-	cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc);
+	cmd = pa->ver_ops->fmt_cmd(opc, sid, addr, bc);
 
 	/* Write data to FIFOs */
-	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
-	pa_write_data(pmic_arb, buf, offset + PMIC_ARB_WDATA0,
-		      min_t(u8, bc, 3));
+	raw_spin_lock_irqsave(&pa->lock, flags);
+	pa_write_data(pa, buf, offset + PMIC_ARB_WDATA0, min_t(u8, bc, 3));
 	if (bc > 3)
-		pa_write_data(pmic_arb, buf + 4,
-				offset + PMIC_ARB_WDATA1, bc - 4);
+		pa_write_data(pa, buf + 4, offset + PMIC_ARB_WDATA1, bc - 4);
 
 	/* Start the transaction */
-	pmic_arb_base_write(pmic_arb, offset + PMIC_ARB_CMD, cmd);
-	rc = pmic_arb_wait_for_done(ctrl, pmic_arb->wr_base, sid, addr);
-	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
+	pmic_arb_base_write(pa, offset + PMIC_ARB_CMD, cmd);
+	rc = pmic_arb_wait_for_done(ctrl, pa->wr_base, sid, addr);
+	raw_spin_unlock_irqrestore(&pa->lock, flags);
 
 	return rc;
 }
@@ -457,7 +456,7 @@ struct spmi_pmic_arb_qpnpint_type {
 static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
 			       size_t len)
 {
-	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
 	u8 sid = d->hwirq >> 24;
 	u8 per = d->hwirq >> 16;
 
@@ -470,7 +469,7 @@ static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
 
 static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
 {
-	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
 	u8 sid = d->hwirq >> 24;
 	u8 per = d->hwirq >> 16;
 
@@ -481,7 +480,7 @@ static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
 				    d->irq);
 }
 
-static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
+static void periph_interrupt(struct spmi_pmic_arb *pa, u8 apid)
 {
 	unsigned int irq;
 	u32 status;
@@ -490,7 +489,7 @@ static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
 	status = readl_relaxed(pa->intr + pa->ver_ops->irq_status(apid));
 	while (status) {
 		id = ffs(status) - 1;
-		status &= ~(1 << id);
+		status &= ~BIT(id);
 		irq = irq_find_mapping(pa->domain,
 				       pa->apid_to_ppid[apid] << 16
 				     | id << 8
@@ -501,7 +500,7 @@ static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
 
 static void pmic_arb_chained_irq(struct irq_desc *desc)
 {
-	struct spmi_pmic_arb_dev *pa = irq_desc_get_handler_data(desc);
+	struct spmi_pmic_arb *pa = irq_desc_get_handler_data(desc);
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	void __iomem *intr = pa->intr;
 	int first = pa->min_apid >> 5;
@@ -516,7 +515,7 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
 				      pa->ver_ops->owner_acc_status(pa->ee, i));
 		while (status) {
 			id = ffs(status) - 1;
-			status &= ~(1 << id);
+			status &= ~BIT(id);
 			periph_interrupt(pa, id + i * 32);
 		}
 	}
@@ -526,23 +525,23 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
 
 static void qpnpint_irq_ack(struct irq_data *d)
 {
-	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
 	u8 irq  = d->hwirq >> 8;
 	u8 apid = d->hwirq;
 	unsigned long flags;
 	u8 data;
 
 	raw_spin_lock_irqsave(&pa->lock, flags);
-	writel_relaxed(1 << irq, pa->intr + pa->ver_ops->irq_clear(apid));
+	writel_relaxed(BIT(irq), pa->intr + pa->ver_ops->irq_clear(apid));
 	raw_spin_unlock_irqrestore(&pa->lock, flags);
 
-	data = 1 << irq;
+	data = BIT(irq);
 	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
 }
 
 static void qpnpint_irq_mask(struct irq_data *d)
 {
-	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
 	u8 irq  = d->hwirq >> 8;
 	u8 apid = d->hwirq;
 	unsigned long flags;
@@ -558,13 +557,13 @@ static void qpnpint_irq_mask(struct irq_data *d)
 	}
 	raw_spin_unlock_irqrestore(&pa->lock, flags);
 
-	data = 1 << irq;
+	data = BIT(irq);
 	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
 }
 
 static void qpnpint_irq_unmask(struct irq_data *d)
 {
-	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
 	u8 irq  = d->hwirq >> 8;
 	u8 apid = d->hwirq;
 	unsigned long flags;
@@ -579,7 +578,7 @@ static void qpnpint_irq_unmask(struct irq_data *d)
 	}
 	raw_spin_unlock_irqrestore(&pa->lock, flags);
 
-	data = 1 << irq;
+	data = BIT(irq);
 	qpnpint_spmi_write(d, QPNPINT_REG_EN_SET, &data, 1);
 }
 
@@ -590,7 +589,7 @@ static void qpnpint_irq_enable(struct irq_data *d)
 
 	qpnpint_irq_unmask(d);
 
-	data = 1 << irq;
+	data = BIT(irq);
 	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
 }
 
@@ -598,25 +597,26 @@ static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	struct spmi_pmic_arb_qpnpint_type type;
 	u8 irq = d->hwirq >> 8;
+	u8 bit_mask_irq = BIT(irq);
 
 	qpnpint_spmi_read(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
 
 	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-		type.type |= 1 << irq;
+		type.type |= bit_mask_irq;
 		if (flow_type & IRQF_TRIGGER_RISING)
-			type.polarity_high |= 1 << irq;
+			type.polarity_high |= bit_mask_irq;
 		if (flow_type & IRQF_TRIGGER_FALLING)
-			type.polarity_low  |= 1 << irq;
+			type.polarity_low  |= bit_mask_irq;
 	} else {
 		if ((flow_type & (IRQF_TRIGGER_HIGH)) &&
 		    (flow_type & (IRQF_TRIGGER_LOW)))
 			return -EINVAL;
 
-		type.type &= ~(1 << irq); /* level trig */
+		type.type &= ~bit_mask_irq; /* level trig */
 		if (flow_type & IRQF_TRIGGER_HIGH)
-			type.polarity_high |= 1 << irq;
+			type.polarity_high |= bit_mask_irq;
 		else
-			type.polarity_low  |= 1 << irq;
+			type.polarity_low  |= bit_mask_irq;
 	}
 
 	qpnpint_spmi_write(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
@@ -657,7 +657,7 @@ struct spmi_pmic_arb_irq_spec {
 	unsigned irq:3;
 };
 
-static int search_mapping_table(struct spmi_pmic_arb_dev *pa,
+static int search_mapping_table(struct spmi_pmic_arb *pa,
 				struct spmi_pmic_arb_irq_spec *spec,
 				u8 *apid)
 {
@@ -673,7 +673,7 @@ static int search_mapping_table(struct spmi_pmic_arb_dev *pa,
 
 		data = mapping_table[index];
 
-		if (ppid & (1 << SPMI_MAPPING_BIT_INDEX(data))) {
+		if (ppid & BIT(SPMI_MAPPING_BIT_INDEX(data))) {
 			if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) {
 				index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
 			} else {
@@ -700,7 +700,7 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 					   unsigned long *out_hwirq,
 					   unsigned int *out_type)
 {
-	struct spmi_pmic_arb_dev *pa = d->host_data;
+	struct spmi_pmic_arb *pa = d->host_data;
 	struct spmi_pmic_arb_irq_spec spec;
 	int err;
 	u8 apid;
@@ -747,7 +747,7 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
 				  unsigned int virq,
 				  irq_hw_number_t hwirq)
 {
-	struct spmi_pmic_arb_dev *pa = d->host_data;
+	struct spmi_pmic_arb *pa = d->host_data;
 
 	dev_dbg(&pa->spmic->dev, "virq = %u, hwirq = %lu\n", virq, hwirq);
 
@@ -758,7 +758,7 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
 }
 
 static int
-pmic_arb_mode_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, mode_t *mode)
+pmic_arb_mode_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
 {
 	*mode = S_IRUSR | S_IWUSR;
 	return 0;
@@ -766,13 +766,13 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
 
 /* v1 offset per ee */
 static int
-pmic_arb_offset_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, u32 *offset)
+pmic_arb_offset_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u32 *offset)
 {
 	*offset = 0x800 + 0x80 * pa->channel;
 	return 0;
 }
 
-static u16 pmic_arb_find_chan(struct spmi_pmic_arb_dev *pa, u16 ppid)
+static u16 pmic_arb_find_chan(struct spmi_pmic_arb *pa, u16 ppid)
 {
 	u32 regval, offset;
 	u16 chan;
@@ -809,7 +809,7 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb_dev *pa, u16 ppid)
 
 
 static int
-pmic_arb_mode_v2(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, mode_t *mode)
+pmic_arb_mode_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
 {
 	u16 ppid = (sid << 8) | (addr >> 8);
 	u16 chan;
@@ -831,7 +831,7 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb_dev *pa, u16 ppid)
 
 /* v2 offset per ppid (chan) and per ee */
 static int
-pmic_arb_offset_v2(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, u32 *offset)
+pmic_arb_offset_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u32 *offset)
 {
 	u16 ppid = (sid << 8) | (addr >> 8);
 	u16 chan;
@@ -926,7 +926,7 @@ static u32 pmic_arb_irq_clear_v2(u8 n)
 
 static int spmi_pmic_arb_probe(struct platform_device *pdev)
 {
-	struct spmi_pmic_arb_dev *pa;
+	struct spmi_pmic_arb *pa;
 	struct spmi_controller *ctrl;
 	struct resource *res;
 	void __iomem *core;
@@ -1111,7 +1111,7 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 static int spmi_pmic_arb_remove(struct platform_device *pdev)
 {
 	struct spmi_controller *ctrl = platform_get_drvdata(pdev);
-	struct spmi_pmic_arb_dev *pa = spmi_controller_get_drvdata(ctrl);
+	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
 	spmi_controller_remove(ctrl);
 	irq_set_chained_handler_and_data(pa->irq, NULL, NULL);
 	irq_domain_remove(pa->domain);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 03/15] spmi: pmic-arb: fix inconsistent use of apid and chan
  2017-05-30 12:38 ` Kiran Gunda
                   ` (2 preceding siblings ...)
  (?)
@ 2017-05-30 12:38 ` Kiran Gunda
  2017-05-31  1:31   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Greg Kroah-Hartman, David Collins, Christophe JAILLET,
	linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

The driver currently uses "apid" and "chan" to mean apid. Remove
the use of chan and use only apid.

On a SPMI bus there is allocation to manage up to 4K peripherals.
However, in practice only few peripherals are instantiated
and only few among the instantiated ones actually interrupt.

APID is CPU's way of keeping track of peripherals that could interrupt.
There is a table that maps the 256 interrupting peripherals to
a number between 0 and 255. This number is called APID. Information about
that interrupting peripheral is stored in registers offset by its
corresponding apid.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 68 ++++++++++++++++++++++----------------------
 1 file changed, 34 insertions(+), 34 deletions(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 7f918ea..7201611 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -117,7 +117,7 @@ enum pmic_arb_cmd_op_code {
  * @spmic:		SPMI controller object
  * @apid_to_ppid:	in-memory copy of APID -> PPID mapping table.
  * @ver_ops:		version dependent operations.
- * @ppid_to_chan	in-memory copy of PPID -> channel (APID) mapping table.
+ * @ppid_to_apid	in-memory copy of PPID -> channel (APID) mapping table.
  *			v2 only.
  */
 struct spmi_pmic_arb {
@@ -140,9 +140,9 @@ struct spmi_pmic_arb {
 	struct spmi_controller	*spmic;
 	u16			*apid_to_ppid;
 	const struct pmic_arb_ver_ops *ver_ops;
-	u16			*ppid_to_chan;
-	u16			last_channel;
-	u8			*chan_to_owner;
+	u16			*ppid_to_apid;
+	u16			last_apid;
+	u8			*apid_to_owner;
 };
 
 /**
@@ -772,22 +772,22 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
 	return 0;
 }
 
-static u16 pmic_arb_find_chan(struct spmi_pmic_arb *pa, u16 ppid)
+static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 {
 	u32 regval, offset;
-	u16 chan;
+	u16 apid;
 	u16 id;
 
 	/*
 	 * PMIC_ARB_REG_CHNL is a table in HW mapping channel to ppid.
-	 * ppid_to_chan is an in-memory invert of that table.
+	 * ppid_to_apid is an in-memory invert of that table.
 	 */
-	for (chan = pa->last_channel; chan < pa->max_periph; chan++) {
+	for (apid = pa->last_apid; apid < pa->max_periph; apid++) {
 		regval = readl_relaxed(pa->cnfg +
-				      SPMI_OWNERSHIP_TABLE_REG(chan));
-		pa->chan_to_owner[chan] = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
+				      SPMI_OWNERSHIP_TABLE_REG(apid));
+		pa->apid_to_owner[apid] = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
 
-		offset = PMIC_ARB_REG_CHNL(chan);
+		offset = PMIC_ARB_REG_CHNL(apid);
 		if (offset >= pa->core_size)
 			break;
 
@@ -796,15 +796,15 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb *pa, u16 ppid)
 			continue;
 
 		id = (regval >> 8) & PMIC_ARB_PPID_MASK;
-		pa->ppid_to_chan[id] = chan | PMIC_ARB_CHAN_VALID;
+		pa->ppid_to_apid[id] = apid | PMIC_ARB_CHAN_VALID;
 		if (id == ppid) {
-			chan |= PMIC_ARB_CHAN_VALID;
+			apid |= PMIC_ARB_CHAN_VALID;
 			break;
 		}
 	}
-	pa->last_channel = chan & ~PMIC_ARB_CHAN_VALID;
+	pa->last_apid = apid & ~PMIC_ARB_CHAN_VALID;
 
-	return chan;
+	return apid;
 }
 
 
@@ -812,38 +812,38 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb *pa, u16 ppid)
 pmic_arb_mode_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
 {
 	u16 ppid = (sid << 8) | (addr >> 8);
-	u16 chan;
+	u16 apid;
 	u8 owner;
 
-	chan = pa->ppid_to_chan[ppid];
-	if (!(chan & PMIC_ARB_CHAN_VALID))
+	apid = pa->ppid_to_apid[ppid];
+	if (!(apid & PMIC_ARB_CHAN_VALID))
 		return -ENODEV;
 
 	*mode = 0;
 	*mode |= S_IRUSR;
 
-	chan &= ~PMIC_ARB_CHAN_VALID;
-	owner = pa->chan_to_owner[chan];
+	apid &= ~PMIC_ARB_CHAN_VALID;
+	owner = pa->apid_to_owner[apid];
 	if (owner == pa->ee)
 		*mode |= S_IWUSR;
 	return 0;
 }
 
-/* v2 offset per ppid (chan) and per ee */
+/* v2 offset per ppid and per ee */
 static int
 pmic_arb_offset_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u32 *offset)
 {
 	u16 ppid = (sid << 8) | (addr >> 8);
-	u16 chan;
+	u16 apid;
 
-	chan = pa->ppid_to_chan[ppid];
-	if (!(chan & PMIC_ARB_CHAN_VALID))
-		chan = pmic_arb_find_chan(pa, ppid);
-	if (!(chan & PMIC_ARB_CHAN_VALID))
+	apid = pa->ppid_to_apid[ppid];
+	if (!(apid & PMIC_ARB_CHAN_VALID))
+		apid = pmic_arb_find_apid(pa, ppid);
+	if (!(apid & PMIC_ARB_CHAN_VALID))
 		return -ENODEV;
-	chan &= ~PMIC_ARB_CHAN_VALID;
+	apid &= ~PMIC_ARB_CHAN_VALID;
 
-	*offset = 0x1000 * pa->ee + 0x8000 * chan;
+	*offset = 0x1000 * pa->ee + 0x8000 * apid;
 	return 0;
 }
 
@@ -988,20 +988,20 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 			goto err_put_ctrl;
 		}
 
-		pa->ppid_to_chan = devm_kcalloc(&ctrl->dev,
+		pa->ppid_to_apid = devm_kcalloc(&ctrl->dev,
 						PMIC_ARB_MAX_PPID,
-						sizeof(*pa->ppid_to_chan),
+						sizeof(*pa->ppid_to_apid),
 						GFP_KERNEL);
-		if (!pa->ppid_to_chan) {
+		if (!pa->ppid_to_apid) {
 			err = -ENOMEM;
 			goto err_put_ctrl;
 		}
 
-		pa->chan_to_owner = devm_kcalloc(&ctrl->dev,
+		pa->apid_to_owner = devm_kcalloc(&ctrl->dev,
 						 pa->max_periph,
-						 sizeof(*pa->chan_to_owner),
+						 sizeof(*pa->apid_to_owner),
 						 GFP_KERNEL);
-		if (!pa->chan_to_owner) {
+		if (!pa->apid_to_owner) {
 			err = -ENOMEM;
 			goto err_put_ctrl;
 		}
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 04/15] spmi: pmic-arb: optimize table lookups
  2017-05-30 12:38 ` Kiran Gunda
                   ` (3 preceding siblings ...)
  (?)
@ 2017-05-30 12:38 ` Kiran Gunda
  2017-05-31  1:44   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Christophe JAILLET, David Collins, linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

The current driver uses a mix of radix tree and a fwd lookup
table to translate between apid and ppid. It is buggy and confusing.

Instead simply use a radix tree for v1 hardware and use the
forward lookup table for v2.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 144 ++++++++++++++++++++++++++-----------------
 1 file changed, 88 insertions(+), 56 deletions(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 7201611..6320f1f 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -164,6 +164,8 @@ struct spmi_pmic_arb {
  *			on v2 offset of SPMI_PIC_IRQ_CLEARn.
  */
 struct pmic_arb_ver_ops {
+	int (*ppid_to_apid)(struct spmi_pmic_arb *pa, u8 sid, u16 addr,
+			u8 *apid);
 	int (*mode)(struct spmi_pmic_arb *dev, u8 sid, u16 addr,
 			mode_t *mode);
 	/* spmi commands (read_cmd, write_cmd, cmd) functionality */
@@ -657,42 +659,6 @@ struct spmi_pmic_arb_irq_spec {
 	unsigned irq:3;
 };
 
-static int search_mapping_table(struct spmi_pmic_arb *pa,
-				struct spmi_pmic_arb_irq_spec *spec,
-				u8 *apid)
-{
-	u16 ppid = spec->slave << 8 | spec->per;
-	u32 *mapping_table = pa->mapping_table;
-	int index = 0, i;
-	u32 data;
-
-	for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
-		if (!test_and_set_bit(index, pa->mapping_table_valid))
-			mapping_table[index] = readl_relaxed(pa->cnfg +
-						SPMI_MAPPING_TABLE_REG(index));
-
-		data = mapping_table[index];
-
-		if (ppid & BIT(SPMI_MAPPING_BIT_INDEX(data))) {
-			if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) {
-				index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
-			} else {
-				*apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
-				return 0;
-			}
-		} else {
-			if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) {
-				index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
-			} else {
-				*apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
-				return 0;
-			}
-		}
-	}
-
-	return -ENODEV;
-}
-
 static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 					   struct device_node *controller,
 					   const u32 *intspec,
@@ -702,7 +668,7 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 {
 	struct spmi_pmic_arb *pa = d->host_data;
 	struct spmi_pmic_arb_irq_spec spec;
-	int err;
+	int rc;
 	u8 apid;
 
 	dev_dbg(&pa->spmic->dev,
@@ -720,11 +686,14 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 	spec.per   = intspec[1];
 	spec.irq   = intspec[2];
 
-	err = search_mapping_table(pa, &spec, &apid);
-	if (err)
-		return err;
-
-	pa->apid_to_ppid[apid] = spec.slave << 8 | spec.per;
+	rc = pa->ver_ops->ppid_to_apid(pa, intspec[0],
+			(intspec[1] << 8), &apid);
+	if (rc < 0) {
+		dev_err(&pa->spmic->dev,
+		"failed to xlate sid = 0x%x, periph = 0x%x, irq = %x rc = %d\n",
+		intspec[0], intspec[1], intspec[2], rc);
+		return rc;
+	}
 
 	/* Keep track of {max,min}_apid for bounding search during interrupt */
 	if (apid > pa->max_apid)
@@ -758,6 +727,54 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
 }
 
 static int
+pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u8 *apid)
+{
+	u16 ppid = sid << 8 | ((addr >> 8) & 0xFF);
+	u32 *mapping_table = pa->mapping_table;
+	int index = 0, i;
+	u16 apid_valid;
+	u32 data;
+
+	apid_valid = pa->ppid_to_apid[ppid];
+	if (apid_valid & PMIC_ARB_CHAN_VALID) {
+		*apid = (apid_valid & ~PMIC_ARB_CHAN_VALID);
+		return 0;
+	}
+
+	for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
+		if (!test_and_set_bit(index, pa->mapping_table_valid))
+			mapping_table[index] = readl_relaxed(pa->cnfg +
+						SPMI_MAPPING_TABLE_REG(index));
+
+		data = mapping_table[index];
+
+		if (ppid & BIT(SPMI_MAPPING_BIT_INDEX(data))) {
+			if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) {
+				index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
+			} else {
+				*apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
+				pa->ppid_to_apid[ppid]
+					= *apid | PMIC_ARB_CHAN_VALID;
+				pa->apid_to_ppid[*apid] = ppid;
+				return 0;
+			}
+		} else {
+			if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) {
+				index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
+			} else {
+				*apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
+				pa->ppid_to_apid[ppid]
+					= *apid | PMIC_ARB_CHAN_VALID;
+				pa->apid_to_ppid[*apid] = ppid;
+				return 0;
+			}
+		}
+	}
+
+	return -ENODEV;
+}
+
+static int
 pmic_arb_mode_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
 {
 	*mode = S_IRUSR | S_IWUSR;
@@ -797,6 +814,7 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 
 		id = (regval >> 8) & PMIC_ARB_PPID_MASK;
 		pa->ppid_to_apid[id] = apid | PMIC_ARB_CHAN_VALID;
+		pa->apid_to_ppid[apid] = id;
 		if (id == ppid) {
 			apid |= PMIC_ARB_CHAN_VALID;
 			break;
@@ -809,20 +827,35 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 
 
 static int
-pmic_arb_mode_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
+pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u8 *apid)
 {
 	u16 ppid = (sid << 8) | (addr >> 8);
-	u16 apid;
-	u8 owner;
+	u16 apid_valid;
 
-	apid = pa->ppid_to_apid[ppid];
-	if (!(apid & PMIC_ARB_CHAN_VALID))
+	apid_valid = pa->ppid_to_apid[ppid];
+	if (!(apid_valid & PMIC_ARB_CHAN_VALID))
+		apid_valid = pmic_arb_find_apid(pa, ppid);
+	if (!(apid_valid & PMIC_ARB_CHAN_VALID))
 		return -ENODEV;
 
+	*apid = (apid_valid & ~PMIC_ARB_CHAN_VALID);
+	return 0;
+}
+
+static int
+pmic_arb_mode_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
+{
+	u8 apid;
+	u8 owner;
+	int rc;
+
+	rc = pmic_arb_ppid_to_apid_v2(pa, sid, addr, &apid);
+	if (rc < 0)
+		return rc;
+
 	*mode = 0;
 	*mode |= S_IRUSR;
 
-	apid &= ~PMIC_ARB_CHAN_VALID;
 	owner = pa->apid_to_owner[apid];
 	if (owner == pa->ee)
 		*mode |= S_IWUSR;
@@ -833,15 +866,12 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 static int
 pmic_arb_offset_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u32 *offset)
 {
-	u16 ppid = (sid << 8) | (addr >> 8);
-	u16 apid;
+	u8 apid;
+	int rc;
 
-	apid = pa->ppid_to_apid[ppid];
-	if (!(apid & PMIC_ARB_CHAN_VALID))
-		apid = pmic_arb_find_apid(pa, ppid);
-	if (!(apid & PMIC_ARB_CHAN_VALID))
-		return -ENODEV;
-	apid &= ~PMIC_ARB_CHAN_VALID;
+	rc = pmic_arb_ppid_to_apid_v2(pa, sid, addr, &apid);
+	if (rc < 0)
+		return rc;
 
 	*offset = 0x1000 * pa->ee + 0x8000 * apid;
 	return 0;
@@ -898,6 +928,7 @@ static u32 pmic_arb_irq_clear_v2(u8 n)
 }
 
 static const struct pmic_arb_ver_ops pmic_arb_v1 = {
+	.ppid_to_apid		= pmic_arb_ppid_to_apid_v1,
 	.mode			= pmic_arb_mode_v1,
 	.non_data_cmd		= pmic_arb_non_data_cmd_v1,
 	.offset			= pmic_arb_offset_v1,
@@ -909,6 +940,7 @@ static u32 pmic_arb_irq_clear_v2(u8 n)
 };
 
 static const struct pmic_arb_ver_ops pmic_arb_v2 = {
+	.ppid_to_apid		= pmic_arb_ppid_to_apid_v2,
 	.mode			= pmic_arb_mode_v2,
 	.non_data_cmd		= pmic_arb_non_data_cmd_v2,
 	.offset			= pmic_arb_offset_v2,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 05/15] spmi: pmic-arb: cleanup unrequested irqs
  2017-05-30 12:38 ` Kiran Gunda
                   ` (4 preceding siblings ...)
  (?)
@ 2017-05-30 12:38 ` Kiran Gunda
  2017-05-31  1:57   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Christophe JAILLET, David Collins, linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

We see a unmapped irqs trigger right around bootup. This could
likely be because the bootloader exited leaving the interrupts
in an unknown or unhandled state.  Ack and mask the interrupt
if one is found. A request_irq later will unmask it and also
setup proper mapping structures.

Also the current driver ensures that no read/write transaction
is in progress while it makes changes to the interrupt regions.
This is not necessary because read/writes over spmi and arbiter
interrupt control are independent operations. Hence, remove the
synchronized accesses to interrupt region.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 101 ++++++++++++++++++-------------------------
 1 file changed, 43 insertions(+), 58 deletions(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 6320f1f..0a5728c 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -98,6 +98,11 @@ enum pmic_arb_cmd_op_code {
 
 struct pmic_arb_ver_ops;
 
+struct apid_data {
+	u16		ppid;
+	u8		owner;
+};
+
 /**
  * spmi_pmic_arb - SPMI PMIC Arbiter object
  *
@@ -115,7 +120,6 @@ enum pmic_arb_cmd_op_code {
  * @mapping_table:	in-memory copy of PPID -> APID mapping table.
  * @domain:		irq domain object for PMIC IRQ domain
  * @spmic:		SPMI controller object
- * @apid_to_ppid:	in-memory copy of APID -> PPID mapping table.
  * @ver_ops:		version dependent operations.
  * @ppid_to_apid	in-memory copy of PPID -> channel (APID) mapping table.
  *			v2 only.
@@ -138,11 +142,10 @@ struct spmi_pmic_arb {
 	DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS);
 	struct irq_domain	*domain;
 	struct spmi_controller	*spmic;
-	u16			*apid_to_ppid;
 	const struct pmic_arb_ver_ops *ver_ops;
 	u16			*ppid_to_apid;
 	u16			last_apid;
-	u8			*apid_to_owner;
+	struct apid_data	apid_data[PMIC_ARB_MAX_PERIPHS];
 };
 
 /**
@@ -482,6 +485,28 @@ static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
 				    d->irq);
 }
 
+static void cleanup_irq(struct spmi_pmic_arb *pa, u8 apid, int id)
+{
+	u16 ppid = pa->apid_data[apid].ppid;
+	u8 sid = ppid >> 8;
+	u8 per = ppid & 0xFF;
+	u8 irq_mask = BIT(id);
+
+	writel_relaxed(irq_mask, pa->intr + pa->ver_ops->irq_clear(apid));
+
+	if (pmic_arb_write_cmd(pa->spmic, SPMI_CMD_EXT_WRITEL, sid,
+			(per << 8) + QPNPINT_REG_LATCHED_CLR, &irq_mask, 1))
+		dev_err_ratelimited(&pa->spmic->dev,
+				"failed to ack irq_mask = 0x%x for ppid = %x\n",
+				irq_mask, ppid);
+
+	if (pmic_arb_write_cmd(pa->spmic, SPMI_CMD_EXT_WRITEL, sid,
+			       (per << 8) + QPNPINT_REG_EN_CLR, &irq_mask, 1))
+		dev_err_ratelimited(&pa->spmic->dev,
+				"failed to ack irq_mask = 0x%x for ppid = %x\n",
+				irq_mask, ppid);
+}
+
 static void periph_interrupt(struct spmi_pmic_arb *pa, u8 apid)
 {
 	unsigned int irq;
@@ -493,9 +518,13 @@ static void periph_interrupt(struct spmi_pmic_arb *pa, u8 apid)
 		id = ffs(status) - 1;
 		status &= ~BIT(id);
 		irq = irq_find_mapping(pa->domain,
-				       pa->apid_to_ppid[apid] << 16
+				       pa->apid_data[apid].ppid << 16
 				     | id << 8
 				     | apid);
+		if (irq == 0) {
+			cleanup_irq(pa, apid, id);
+			continue;
+		}
 		generic_handle_irq(irq);
 	}
 }
@@ -530,12 +559,9 @@ static void qpnpint_irq_ack(struct irq_data *d)
 	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
 	u8 irq  = d->hwirq >> 8;
 	u8 apid = d->hwirq;
-	unsigned long flags;
 	u8 data;
 
-	raw_spin_lock_irqsave(&pa->lock, flags);
 	writel_relaxed(BIT(irq), pa->intr + pa->ver_ops->irq_clear(apid));
-	raw_spin_unlock_irqrestore(&pa->lock, flags);
 
 	data = BIT(irq);
 	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
@@ -543,23 +569,9 @@ static void qpnpint_irq_ack(struct irq_data *d)
 
 static void qpnpint_irq_mask(struct irq_data *d)
 {
-	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
 	u8 irq  = d->hwirq >> 8;
-	u8 apid = d->hwirq;
-	unsigned long flags;
-	u32 status;
-	u8 data;
+	u8 data = BIT(irq);
 
-	raw_spin_lock_irqsave(&pa->lock, flags);
-	status = readl_relaxed(pa->intr + pa->ver_ops->acc_enable(apid));
-	if (status & SPMI_PIC_ACC_ENABLE_BIT) {
-		status = status & ~SPMI_PIC_ACC_ENABLE_BIT;
-		writel_relaxed(status, pa->intr +
-			       pa->ver_ops->acc_enable(apid));
-	}
-	raw_spin_unlock_irqrestore(&pa->lock, flags);
-
-	data = BIT(irq);
 	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
 }
 
@@ -568,20 +580,12 @@ static void qpnpint_irq_unmask(struct irq_data *d)
 	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
 	u8 irq  = d->hwirq >> 8;
 	u8 apid = d->hwirq;
-	unsigned long flags;
-	u32 status;
-	u8 data;
+	u8 data = BIT(irq);
 
-	raw_spin_lock_irqsave(&pa->lock, flags);
-	status = readl_relaxed(pa->intr + pa->ver_ops->acc_enable(apid));
-	if (!(status & SPMI_PIC_ACC_ENABLE_BIT)) {
-		writel_relaxed(status | SPMI_PIC_ACC_ENABLE_BIT,
-				pa->intr + pa->ver_ops->acc_enable(apid));
-	}
-	raw_spin_unlock_irqrestore(&pa->lock, flags);
+	writel_relaxed(SPMI_PIC_ACC_ENABLE_BIT,
+		pa->intr + pa->ver_ops->acc_enable(apid));
 
-	data = BIT(irq);
-	qpnpint_spmi_write(d, QPNPINT_REG_EN_SET, &data, 1);
+	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
 }
 
 static void qpnpint_irq_enable(struct irq_data *d)
@@ -755,7 +759,7 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
 				*apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
 				pa->ppid_to_apid[ppid]
 					= *apid | PMIC_ARB_CHAN_VALID;
-				pa->apid_to_ppid[*apid] = ppid;
+				pa->apid_data[*apid].ppid = ppid;
 				return 0;
 			}
 		} else {
@@ -765,7 +769,7 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
 				*apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
 				pa->ppid_to_apid[ppid]
 					= *apid | PMIC_ARB_CHAN_VALID;
-				pa->apid_to_ppid[*apid] = ppid;
+				pa->apid_data[*apid].ppid = ppid;
 				return 0;
 			}
 		}
@@ -802,7 +806,7 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 	for (apid = pa->last_apid; apid < pa->max_periph; apid++) {
 		regval = readl_relaxed(pa->cnfg +
 				      SPMI_OWNERSHIP_TABLE_REG(apid));
-		pa->apid_to_owner[apid] = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
+		pa->apid_data[apid].owner = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
 
 		offset = PMIC_ARB_REG_CHNL(apid);
 		if (offset >= pa->core_size)
@@ -814,7 +818,7 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 
 		id = (regval >> 8) & PMIC_ARB_PPID_MASK;
 		pa->ppid_to_apid[id] = apid | PMIC_ARB_CHAN_VALID;
-		pa->apid_to_ppid[apid] = id;
+		pa->apid_data[apid].ppid = id;
 		if (id == ppid) {
 			apid |= PMIC_ARB_CHAN_VALID;
 			break;
@@ -846,7 +850,6 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 pmic_arb_mode_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
 {
 	u8 apid;
-	u8 owner;
 	int rc;
 
 	rc = pmic_arb_ppid_to_apid_v2(pa, sid, addr, &apid);
@@ -856,8 +859,7 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 	*mode = 0;
 	*mode |= S_IRUSR;
 
-	owner = pa->apid_to_owner[apid];
-	if (owner == pa->ee)
+	if (pa->ee == pa->apid_data[apid].owner)
 		*mode |= S_IWUSR;
 	return 0;
 }
@@ -1028,15 +1030,6 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 			err = -ENOMEM;
 			goto err_put_ctrl;
 		}
-
-		pa->apid_to_owner = devm_kcalloc(&ctrl->dev,
-						 pa->max_periph,
-						 sizeof(*pa->apid_to_owner),
-						 GFP_KERNEL);
-		if (!pa->apid_to_owner) {
-			err = -ENOMEM;
-			goto err_put_ctrl;
-		}
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
@@ -1088,14 +1081,6 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 
 	pa->ee = ee;
 
-	pa->apid_to_ppid = devm_kcalloc(&ctrl->dev, PMIC_ARB_MAX_PERIPHS,
-					    sizeof(*pa->apid_to_ppid),
-					    GFP_KERNEL);
-	if (!pa->apid_to_ppid) {
-		err = -ENOMEM;
-		goto err_put_ctrl;
-	}
-
 	pa->mapping_table = devm_kcalloc(&ctrl->dev, PMIC_ARB_MAX_PERIPHS - 1,
 					sizeof(*pa->mapping_table), GFP_KERNEL);
 	if (!pa->mapping_table) {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 06/15] spmi: pmic-arb: fix missing interrupts
  2017-05-30 12:38 ` Kiran Gunda
                   ` (5 preceding siblings ...)
  (?)
@ 2017-05-30 12:38 ` Kiran Gunda
  2017-05-31  2:00   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Greg Kroah-Hartman,
	Christophe JAILLET, David Collins, Subbaraman Narayanamurthy,
	linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

irq_enable is called when the device resumes. Note that the
irq_enable is called regardless of whether the interrupt was
marked enabled/disabled in the descriptor or whether it was
masked/unmasked at the controller while resuming.

The current driver unconditionally clears the interrupt in its
irq_enable callback. This is dangerous as any interrupts that
happen right before the resume could be missed.
Remove the irq_enable callback and use mask/unmask instead.

Also remove struct pmic_arb_irq_spec as it serves no real purpose.
It is used only in the translate function and the code is much
cleaner without it.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 29 +++--------------------------
 1 file changed, 3 insertions(+), 26 deletions(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 0a5728c..bc03737 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -588,17 +588,6 @@ static void qpnpint_irq_unmask(struct irq_data *d)
 	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
 }
 
-static void qpnpint_irq_enable(struct irq_data *d)
-{
-	u8 irq  = d->hwirq >> 8;
-	u8 data;
-
-	qpnpint_irq_unmask(d);
-
-	data = BIT(irq);
-	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
-}
-
 static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	struct spmi_pmic_arb_qpnpint_type type;
@@ -647,7 +636,6 @@ static int qpnpint_get_irqchip_state(struct irq_data *d,
 
 static struct irq_chip pmic_arb_irqchip = {
 	.name		= "pmic_arb",
-	.irq_enable	= qpnpint_irq_enable,
 	.irq_ack	= qpnpint_irq_ack,
 	.irq_mask	= qpnpint_irq_mask,
 	.irq_unmask	= qpnpint_irq_unmask,
@@ -657,12 +645,6 @@ static int qpnpint_get_irqchip_state(struct irq_data *d,
 			| IRQCHIP_SKIP_SET_WAKE,
 };
 
-struct spmi_pmic_arb_irq_spec {
-	unsigned slave:4;
-	unsigned per:8;
-	unsigned irq:3;
-};
-
 static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 					   struct device_node *controller,
 					   const u32 *intspec,
@@ -671,7 +653,6 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 					   unsigned int *out_type)
 {
 	struct spmi_pmic_arb *pa = d->host_data;
-	struct spmi_pmic_arb_irq_spec spec;
 	int rc;
 	u8 apid;
 
@@ -686,10 +667,6 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 	if (intspec[0] > 0xF || intspec[1] > 0xFF || intspec[2] > 0x7)
 		return -EINVAL;
 
-	spec.slave = intspec[0];
-	spec.per   = intspec[1];
-	spec.irq   = intspec[2];
-
 	rc = pa->ver_ops->ppid_to_apid(pa, intspec[0],
 			(intspec[1] << 8), &apid);
 	if (rc < 0) {
@@ -705,9 +682,9 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 	if (apid < pa->min_apid)
 		pa->min_apid = apid;
 
-	*out_hwirq = spec.slave << 24
-		   | spec.per   << 16
-		   | spec.irq   << 8
+	*out_hwirq = (intspec[0] & 0xF) << 24
+		   | (intspec[1] & 0xFF) << 16
+		   | (intspec[2] & 0x7) << 8
 		   | apid;
 	*out_type  = intspec[3] & IRQ_TYPE_SENSE_MASK;
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 07/15] spmi: pmic-arb: clear the latched status of the interrupt
  2017-05-30 12:38 ` Kiran Gunda
                   ` (6 preceding siblings ...)
  (?)
@ 2017-05-30 12:38 ` Kiran Gunda
  2017-05-31 22:03   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Christophe JAILLET,
	Subbaraman Narayanamurthy, David Collins, linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

PMIC interrupts each have an internal latched status bit which is
not visible from any register.  This status bit is set as soon as
the conditions specified in the interrupt type and polarity
registers are met even if the interrupt is not enabled.  When it
is set, nothing else changes within the PMIC and no interrupt
notification packets are sent.  If the internal latched status
bit is set when an interrupt is enabled, then the value is
immediately propagated into the interrupt latched status register
and an interrupt notification packet is sent out from the PMIC
over SPMI.

This PMIC hardware behavior can lead to a situation where the
handler for a level triggered interrupt is called immediately
after enable_irq() is called even though the interrupt physically
triggered while it was disabled within the genirq framework.
This situation takes place if the the interrupt fires twice after
calling disable_irq().  The first time it fires, the level flow
handler will mask and disregard it.  Unfortunately, the second
time it fires, the internal latched status bit is set within the
PMIC and no further notification is received.  When enable_irq()
is called later, the interrupt is unmasked (enabled in the PMIC)
which results in the PMIC immediately sending an interrupt
notification packet out over SPMI.  This breaks the semantics
of level triggered interrupts within the genirq framework since
they should be completely ignored while disabled.

The PMIC internal latched status behavior also affects how
interrupts are treated during suspend.  While entering suspend,
all interrupts not specified as wakeup mode are masked.  Upon
resume, these interrupts are unmasked.  Thus if any of the
non-wakeup PMIC interrupts fired while the system was suspended,
then the PMIC will send interrupt notification packets out via
SPMI as soon as they are unmasked during resume.  This behavior
violates genirq semantics as well since non-wakeup interrupts
should be completely ignored during suspend.

Modify the qpnpint_irq_unmask() function so that the interrupt
latched status clear register is written immediately before the
interrupt enable register.  This clears the internal latched
status bit of the interrupt so that it cannot trigger spuriously
immediately upon being enabled.

Also, while resuming an irq, an unmask could be called even if it
was not previously masked.  So, before writing these registers,
check if the interrupt is already enabled within the PMIC. If it
is, then no further register writes are required.  This
condition check ensures that a valid latched status register bit
is not cleared until it is properly handled.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index bc03737..1d23df0 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -580,12 +580,22 @@ static void qpnpint_irq_unmask(struct irq_data *d)
 	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
 	u8 irq  = d->hwirq >> 8;
 	u8 apid = d->hwirq;
-	u8 data = BIT(irq);
+	u8 buf[2];
 
 	writel_relaxed(SPMI_PIC_ACC_ENABLE_BIT,
 		pa->intr + pa->ver_ops->acc_enable(apid));
 
-	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
+	qpnpint_spmi_read(d, QPNPINT_REG_EN_SET, &buf[0], 1);
+	if (!(buf[0] & BIT(irq))) {
+		/*
+		 * Since the interrupt is currently disabled, write to both the
+		 * LATCHED_CLR and EN_SET registers so that a spurious interrupt
+		 * cannot be triggered when the interrupt is enabled
+		 */
+		buf[0] = BIT(irq);
+		buf[1] = BIT(irq);
+		qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &buf, 2);
+	}
 }
 
 static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 08/15] spmi: pmic_arb: use appropriate flow handler
  2017-05-30 12:38 ` Kiran Gunda
                   ` (7 preceding siblings ...)
  (?)
@ 2017-05-30 12:38 ` Kiran Gunda
  2017-05-31 19:03   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Christophe JAILLET,
	David Collins, Subbaraman Narayanamurthy, linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

The current code uses handle_level_irq flow handler even if the
trigger type of the interrupt is edge. This can lead to missing
of an edge transition that happens when the interrupt is being
handled. The level flow handler masks the interrupt while it is
being handled, so if an edge transition happens at that time,
that edge is lost.

Use an edge flow handler for edge type interrupts which ensures
that the interrupt stays enabled while being handled - at least
until it triggers at which point the flow handler sets the
IRQF_PENDING flag and only then masks the interrupt. That
IRQF_PENDING state indicates an edge transition happened while
the interrupt was being handled and the handler is called again.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 1d23df0..ad34491 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -625,6 +625,12 @@ static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
 	}
 
 	qpnpint_spmi_write(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
+
+	if (flow_type & IRQ_TYPE_EDGE_BOTH)
+		irq_set_handler_locked(d, handle_edge_irq);
+	else
+		irq_set_handler_locked(d, handle_level_irq);
+
 	return 0;
 }
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 09/15] spmi: pmic-arb: check apid enabled before calling the handler
  2017-05-30 12:38 ` Kiran Gunda
                   ` (8 preceding siblings ...)
  (?)
@ 2017-05-30 12:38 ` Kiran Gunda
  2017-05-31 20:39   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, David Collins,
	Subbaraman Narayanamurthy, Christophe JAILLET, linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

The driver currently invokes the apid handler (periph_handler())
once it sees that the summary status bit for that apid is set.

However the hardware is designed to set that bit even if the apid
interrupts are disabled. The driver should check whether the apid
is indeed enabled before calling the apid handler.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index ad34491..f8638fa 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -536,8 +536,8 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
 	void __iomem *intr = pa->intr;
 	int first = pa->min_apid >> 5;
 	int last = pa->max_apid >> 5;
-	u32 status;
-	int i, id;
+	u32 status, enable;
+	int i, id, apid;
 
 	chained_irq_enter(chip, desc);
 
@@ -547,7 +547,11 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
 		while (status) {
 			id = ffs(status) - 1;
 			status &= ~BIT(id);
-			periph_interrupt(pa, id + i * 32);
+			apid = id + i * 32;
+			enable = readl_relaxed(intr +
+					pa->ver_ops->acc_enable(apid));
+			if (enable & SPMI_PIC_ACC_ENABLE_BIT)
+				periph_interrupt(pa, apid);
 		}
 	}
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 10/15] spmi: pmic_arb: add support for PMIC bus arbiter v3
  2017-05-30 12:38 ` Kiran Gunda
                   ` (9 preceding siblings ...)
  (?)
@ 2017-05-30 12:38 ` Kiran Gunda
  2017-05-31 22:18   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, David Collins,
	Christophe JAILLET, Subbaraman Narayanamurthy, linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

PMIC bus arbiter v3 supports 512 SPMI peripherals. Add the v3 operators to
support this new arbiter version.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 133 +++++++++++++++++++++++++++----------------
 1 file changed, 83 insertions(+), 50 deletions(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index f8638fa..0deac33 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -28,6 +28,7 @@
 /* PMIC Arbiter configuration registers */
 #define PMIC_ARB_VERSION		0x0000
 #define PMIC_ARB_VERSION_V2_MIN		0x20010000
+#define PMIC_ARB_VERSION_V3_MIN		0x30000000
 #define PMIC_ARB_INT_EN			0x0004
 
 /* PMIC Arbiter channel registers offsets */
@@ -96,6 +97,17 @@ enum pmic_arb_cmd_op_code {
 /* interrupt enable bit */
 #define SPMI_PIC_ACC_ENABLE_BIT		BIT(0)
 
+#define HWIRQ(slave_id, periph_id, irq_id, apid) \
+	((((slave_id) & 0xF)   << 28) | \
+	(((periph_id) & 0xFF)  << 20) | \
+	(((irq_id)    & 0x7)   << 16) | \
+	(((apid)      & 0x1FF) << 0))
+
+#define HWIRQ_SID(hwirq)  (((hwirq) >> 28) & 0xF)
+#define HWIRQ_PER(hwirq)  (((hwirq) >> 20) & 0xFF)
+#define HWIRQ_IRQ(hwirq)  (((hwirq) >> 16) & 0x7)
+#define HWIRQ_APID(hwirq) (((hwirq) >> 0)  & 0x1FF)
+
 struct pmic_arb_ver_ops;
 
 struct apid_data {
@@ -151,7 +163,9 @@ struct spmi_pmic_arb {
 /**
  * pmic_arb_ver: version dependent functionality.
  *
- * @mode:	access rights to specified pmic peripheral.
+ * @ver_str:		version string.
+ * @ppid_to_apid:	finds the apid for a given ppid.
+ * @mode:		access rights to specified pmic peripheral.
  * @non_data_cmd:	on v1 issues an spmi non-data command.
  *			on v2 no HW support, returns -EOPNOTSUPP.
  * @offset:		on v1 offset of per-ee channel.
@@ -167,8 +181,9 @@ struct spmi_pmic_arb {
  *			on v2 offset of SPMI_PIC_IRQ_CLEARn.
  */
 struct pmic_arb_ver_ops {
+	const char *ver_str;
 	int (*ppid_to_apid)(struct spmi_pmic_arb *pa, u8 sid, u16 addr,
-			u8 *apid);
+			u16 *apid);
 	int (*mode)(struct spmi_pmic_arb *dev, u8 sid, u16 addr,
 			mode_t *mode);
 	/* spmi commands (read_cmd, write_cmd, cmd) functionality */
@@ -177,10 +192,10 @@ struct pmic_arb_ver_ops {
 	u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc);
 	int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid);
 	/* Interrupts controller functionality (offset of PIC registers) */
-	u32 (*owner_acc_status)(u8 m, u8 n);
-	u32 (*acc_enable)(u8 n);
-	u32 (*irq_status)(u8 n);
-	u32 (*irq_clear)(u8 n);
+	u32 (*owner_acc_status)(u8 m, u16 n);
+	u32 (*acc_enable)(u16 n);
+	u32 (*irq_status)(u16 n);
+	u32 (*irq_clear)(u16 n);
 };
 
 static inline void pmic_arb_base_write(struct spmi_pmic_arb *pa,
@@ -462,8 +477,8 @@ static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
 			       size_t len)
 {
 	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
-	u8 sid = d->hwirq >> 24;
-	u8 per = d->hwirq >> 16;
+	u8 sid = HWIRQ_SID(d->hwirq);
+	u8 per = HWIRQ_PER(d->hwirq);
 
 	if (pmic_arb_write_cmd(pa->spmic, SPMI_CMD_EXT_WRITEL, sid,
 			       (per << 8) + reg, buf, len))
@@ -475,8 +490,8 @@ static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
 static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
 {
 	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
-	u8 sid = d->hwirq >> 24;
-	u8 per = d->hwirq >> 16;
+	u8 sid = HWIRQ_SID(d->hwirq);
+	u8 per = HWIRQ_PER(d->hwirq);
 
 	if (pmic_arb_read_cmd(pa->spmic, SPMI_CMD_EXT_READL, sid,
 			      (per << 8) + reg, buf, len))
@@ -485,7 +500,7 @@ static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
 				    d->irq);
 }
 
-static void cleanup_irq(struct spmi_pmic_arb *pa, u8 apid, int id)
+static void cleanup_irq(struct spmi_pmic_arb *pa, u16 apid, int id)
 {
 	u16 ppid = pa->apid_data[apid].ppid;
 	u8 sid = ppid >> 8;
@@ -507,20 +522,19 @@ static void cleanup_irq(struct spmi_pmic_arb *pa, u8 apid, int id)
 				irq_mask, ppid);
 }
 
-static void periph_interrupt(struct spmi_pmic_arb *pa, u8 apid)
+static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid)
 {
 	unsigned int irq;
 	u32 status;
 	int id;
+	u8 sid = (pa->apid_data[apid].ppid >> 8) & 0xF;
+	u8 per = pa->apid_data[apid].ppid & 0xFF;
 
 	status = readl_relaxed(pa->intr + pa->ver_ops->irq_status(apid));
 	while (status) {
 		id = ffs(status) - 1;
 		status &= ~BIT(id);
-		irq = irq_find_mapping(pa->domain,
-				       pa->apid_data[apid].ppid << 16
-				     | id << 8
-				     | apid);
+		irq = irq_find_mapping(pa->domain, HWIRQ(sid, per, id, apid));
 		if (irq == 0) {
 			cleanup_irq(pa, apid, id);
 			continue;
@@ -561,8 +575,8 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
 static void qpnpint_irq_ack(struct irq_data *d)
 {
 	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
-	u8 irq  = d->hwirq >> 8;
-	u8 apid = d->hwirq;
+	u8 irq = HWIRQ_IRQ(d->hwirq);
+	u16 apid = HWIRQ_APID(d->hwirq);
 	u8 data;
 
 	writel_relaxed(BIT(irq), pa->intr + pa->ver_ops->irq_clear(apid));
@@ -573,7 +587,7 @@ static void qpnpint_irq_ack(struct irq_data *d)
 
 static void qpnpint_irq_mask(struct irq_data *d)
 {
-	u8 irq  = d->hwirq >> 8;
+	u8 irq = HWIRQ_IRQ(d->hwirq);
 	u8 data = BIT(irq);
 
 	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
@@ -582,8 +596,8 @@ static void qpnpint_irq_mask(struct irq_data *d)
 static void qpnpint_irq_unmask(struct irq_data *d)
 {
 	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
-	u8 irq  = d->hwirq >> 8;
-	u8 apid = d->hwirq;
+	u8 irq = HWIRQ_IRQ(d->hwirq);
+	u16 apid = HWIRQ_APID(d->hwirq);
 	u8 buf[2];
 
 	writel_relaxed(SPMI_PIC_ACC_ENABLE_BIT,
@@ -605,7 +619,7 @@ static void qpnpint_irq_unmask(struct irq_data *d)
 static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	struct spmi_pmic_arb_qpnpint_type type;
-	u8 irq = d->hwirq >> 8;
+	u8 irq = HWIRQ_IRQ(d->hwirq);
 	u8 bit_mask_irq = BIT(irq);
 
 	qpnpint_spmi_read(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
@@ -642,7 +656,7 @@ static int qpnpint_get_irqchip_state(struct irq_data *d,
 				     enum irqchip_irq_state which,
 				     bool *state)
 {
-	u8 irq = d->hwirq >> 8;
+	u8 irq = HWIRQ_IRQ(d->hwirq);
 	u8 status = 0;
 
 	if (which != IRQCHIP_STATE_LINE_LEVEL)
@@ -674,7 +688,7 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 {
 	struct spmi_pmic_arb *pa = d->host_data;
 	int rc;
-	u8 apid;
+	u16 apid;
 
 	dev_dbg(&pa->spmic->dev,
 		"intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
@@ -702,10 +716,7 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 	if (apid < pa->min_apid)
 		pa->min_apid = apid;
 
-	*out_hwirq = (intspec[0] & 0xF) << 24
-		   | (intspec[1] & 0xFF) << 16
-		   | (intspec[2] & 0x7) << 8
-		   | apid;
+	*out_hwirq = HWIRQ(intspec[0], intspec[1], intspec[2], apid);
 	*out_type  = intspec[3] & IRQ_TYPE_SENSE_MASK;
 
 	dev_dbg(&pa->spmic->dev, "out_hwirq = %lu\n", *out_hwirq);
@@ -728,7 +739,7 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
 }
 
 static int
-pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u8 *apid)
+pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u16 *apid)
 {
 	u16 ppid = sid << 8 | ((addr >> 8) & 0xFF);
 	u32 *mapping_table = pa->mapping_table;
@@ -776,7 +787,7 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
 }
 
 static int
-pmic_arb_mode_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
+pmic_arb_mode_v1_v3(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
 {
 	*mode = S_IRUSR | S_IWUSR;
 	return 0;
@@ -828,7 +839,7 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 
 
 static int
-pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u8 *apid)
+pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u16 *apid)
 {
 	u16 ppid = (sid << 8) | (addr >> 8);
 	u16 apid_valid;
@@ -846,7 +857,7 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 static int
 pmic_arb_mode_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
 {
-	u8 apid;
+	u16 apid;
 	int rc;
 
 	rc = pmic_arb_ppid_to_apid_v2(pa, sid, addr, &apid);
@@ -865,7 +876,7 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 static int
 pmic_arb_offset_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u32 *offset)
 {
-	u8 apid;
+	u16 apid;
 	int rc;
 
 	rc = pmic_arb_ppid_to_apid_v2(pa, sid, addr, &apid);
@@ -886,49 +897,55 @@ static u32 pmic_arb_fmt_cmd_v2(u8 opc, u8 sid, u16 addr, u8 bc)
 	return (opc << 27) | ((addr & 0xff) << 4) | (bc & 0x7);
 }
 
-static u32 pmic_arb_owner_acc_status_v1(u8 m, u8 n)
+static u32 pmic_arb_owner_acc_status_v1(u8 m, u16 n)
 {
 	return 0x20 * m + 0x4 * n;
 }
 
-static u32 pmic_arb_owner_acc_status_v2(u8 m, u8 n)
+static u32 pmic_arb_owner_acc_status_v2(u8 m, u16 n)
 {
 	return 0x100000 + 0x1000 * m + 0x4 * n;
 }
 
-static u32 pmic_arb_acc_enable_v1(u8 n)
+static u32 pmic_arb_owner_acc_status_v3(u8 m, u16 n)
+{
+	return 0x200000 + 0x1000 * m + 0x4 * n;
+}
+
+static u32 pmic_arb_acc_enable_v1(u16 n)
 {
 	return 0x200 + 0x4 * n;
 }
 
-static u32 pmic_arb_acc_enable_v2(u8 n)
+static u32 pmic_arb_acc_enable_v2(u16 n)
 {
 	return 0x1000 * n;
 }
 
-static u32 pmic_arb_irq_status_v1(u8 n)
+static u32 pmic_arb_irq_status_v1(u16 n)
 {
 	return 0x600 + 0x4 * n;
 }
 
-static u32 pmic_arb_irq_status_v2(u8 n)
+static u32 pmic_arb_irq_status_v2(u16 n)
 {
 	return 0x4 + 0x1000 * n;
 }
 
-static u32 pmic_arb_irq_clear_v1(u8 n)
+static u32 pmic_arb_irq_clear_v1(u16 n)
 {
 	return 0xA00 + 0x4 * n;
 }
 
-static u32 pmic_arb_irq_clear_v2(u8 n)
+static u32 pmic_arb_irq_clear_v2(u16 n)
 {
 	return 0x8 + 0x1000 * n;
 }
 
 static const struct pmic_arb_ver_ops pmic_arb_v1 = {
+	.ver_str		= "v1",
 	.ppid_to_apid		= pmic_arb_ppid_to_apid_v1,
-	.mode			= pmic_arb_mode_v1,
+	.mode			= pmic_arb_mode_v1_v3,
 	.non_data_cmd		= pmic_arb_non_data_cmd_v1,
 	.offset			= pmic_arb_offset_v1,
 	.fmt_cmd		= pmic_arb_fmt_cmd_v1,
@@ -939,6 +956,7 @@ static u32 pmic_arb_irq_clear_v2(u8 n)
 };
 
 static const struct pmic_arb_ver_ops pmic_arb_v2 = {
+	.ver_str		= "v2",
 	.ppid_to_apid		= pmic_arb_ppid_to_apid_v2,
 	.mode			= pmic_arb_mode_v2,
 	.non_data_cmd		= pmic_arb_non_data_cmd_v2,
@@ -950,6 +968,19 @@ static u32 pmic_arb_irq_clear_v2(u8 n)
 	.irq_clear		= pmic_arb_irq_clear_v2,
 };
 
+static const struct pmic_arb_ver_ops pmic_arb_v3 = {
+	.ver_str		= "v3",
+	.ppid_to_apid		= pmic_arb_ppid_to_apid_v2,
+	.mode			= pmic_arb_mode_v1_v3,
+	.non_data_cmd		= pmic_arb_non_data_cmd_v2,
+	.offset			= pmic_arb_offset_v2,
+	.fmt_cmd		= pmic_arb_fmt_cmd_v2,
+	.owner_acc_status	= pmic_arb_owner_acc_status_v3,
+	.acc_enable		= pmic_arb_acc_enable_v2,
+	.irq_status		= pmic_arb_irq_status_v2,
+	.irq_clear		= pmic_arb_irq_clear_v2,
+};
+
 static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
 	.map	= qpnpint_irq_domain_map,
 	.xlate	= qpnpint_irq_domain_dt_translate,
@@ -963,7 +994,6 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 	void __iomem *core;
 	u32 channel, ee, hw_ver;
 	int err;
-	bool is_v1;
 
 	ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*pa));
 	if (!ctrl)
@@ -987,21 +1017,21 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 	}
 
 	hw_ver = readl_relaxed(core + PMIC_ARB_VERSION);
-	is_v1  = (hw_ver < PMIC_ARB_VERSION_V2_MIN);
-
-	dev_info(&ctrl->dev, "PMIC Arb Version-%d (0x%x)\n", (is_v1 ? 1 : 2),
-		hw_ver);
 
-	if (is_v1) {
+	if (hw_ver < PMIC_ARB_VERSION_V2_MIN) {
 		pa->ver_ops = &pmic_arb_v1;
 		pa->wr_base = core;
 		pa->rd_base = core;
 	} else {
 		pa->core = core;
-		pa->ver_ops = &pmic_arb_v2;
+
+		if (hw_ver < PMIC_ARB_VERSION_V3_MIN)
+			pa->ver_ops = &pmic_arb_v2;
+		else
+			pa->ver_ops = &pmic_arb_v3;
 
 		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL(0) */
-		pa->max_periph =  (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;
+		pa->max_periph = (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;
 
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						   "obsrvr");
@@ -1029,6 +1059,9 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 		}
 	}
 
+	dev_info(&ctrl->dev, "PMIC arbiter version %s (0x%x)\n",
+		 pa->ver_ops->ver_str, hw_ver);
+
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
 	pa->intr = devm_ioremap_resource(&ctrl->dev, res);
 	if (IS_ERR(pa->intr)) {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 11/15] spmi: spmi-pmic-arb: enable the SPMI interrupt as a wakeup source
  2017-05-30 12:38 ` Kiran Gunda
                   ` (10 preceding siblings ...)
  (?)
@ 2017-05-30 12:38 ` Kiran Gunda
  2017-05-31 17:13   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:38 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Christophe JAILLET,
	David Collins, Subbaraman Narayanamurthy, linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd, Nicholas Troast

Currently the SPMI interrupt will not wake the device. Enable this
interrupt as a wakeup source.

Signed-off-by: Nicholas Troast <ntroast@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 0deac33..2afe359 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -1140,6 +1140,7 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 	}
 
 	irq_set_chained_handler_and_data(pa->irq, pmic_arb_chained_irq, pa);
+	enable_irq_wake(pa->irq);
 
 	err = spmi_controller_add(ctrl);
 	if (err)
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 12/15] spmi-pmic-arb: fix a possible null pointer dereference
  2017-05-30 12:38 ` Kiran Gunda
                   ` (11 preceding siblings ...)
  (?)
@ 2017-05-30 12:39 ` Kiran Gunda
  2017-05-31 17:29   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:39 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Greg Kroah-Hartman,
	Subbaraman Narayanamurthy, Christophe JAILLET, David Collins,
	linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

If "core" memory resource is not specified, the driver could end up
dereferencing a null pointer.

Fix this by returning -EINVAL when core resource is missing.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 2afe359..412481d 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -1003,6 +1003,12 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 	pa->spmic = ctrl;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
+	if (!res) {
+		dev_err(&pdev->dev, "core resource not specified\n");
+		err = -EINVAL;
+		goto err_put_ctrl;
+	}
+
 	pa->core_size = resource_size(res);
 	if (pa->core_size <= 0x800) {
 		dev_err(&pdev->dev, "core_size is smaller than 0x800. Failing Probe\n");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 13/15] spmi: pmic-arb: add support for HW version 5
  2017-05-30 12:38 ` Kiran Gunda
                   ` (12 preceding siblings ...)
  (?)
@ 2017-05-30 12:39 ` Kiran Gunda
  2017-06-01  6:08   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:39 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Greg Kroah-Hartman,
	Subbaraman Narayanamurthy, David Collins, Christophe JAILLET,
	linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: David Collins <collinsd@codeaurora.org>

Add support for version 5 of the SPMI PMIC arbiter.  It utilizes
different offsets for registers than those found on version 3.
Also, the procedure to determine if writing and IRQ access is
allowed for a given PPID changes for version 5.

Signed-off-by: David Collins <collinsd@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 248 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 224 insertions(+), 24 deletions(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 412481d..b755c24 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -29,6 +29,7 @@
 #define PMIC_ARB_VERSION		0x0000
 #define PMIC_ARB_VERSION_V2_MIN		0x20010000
 #define PMIC_ARB_VERSION_V3_MIN		0x30000000
+#define PMIC_ARB_VERSION_V5_MIN		0x50000000
 #define PMIC_ARB_INT_EN			0x0004
 
 /* PMIC Arbiter channel registers offsets */
@@ -39,7 +40,6 @@
 #define PMIC_ARB_WDATA1			0x14
 #define PMIC_ARB_RDATA0			0x18
 #define PMIC_ARB_RDATA1			0x1C
-#define PMIC_ARB_REG_CHNL(N)		(0x800 + 0x4 * (N))
 
 /* Mapping Table */
 #define SPMI_MAPPING_TABLE_REG(N)	(0x0B00 + (4 * (N)))
@@ -52,6 +52,8 @@
 #define SPMI_MAPPING_TABLE_TREE_DEPTH	16	/* Maximum of 16-bits */
 #define PMIC_ARB_MAX_PPID		BIT(12) /* PPID is 12bit */
 #define PMIC_ARB_CHAN_VALID		BIT(15)
+#define PMIC_ARB_CHAN_IS_IRQ_OWNER(reg)	((reg) & BIT(24))
+#define INVALID_EE			(-1)
 
 /* Ownership Table */
 #define SPMI_OWNERSHIP_TABLE_REG(N)	(0x0700 + (4 * (N)))
@@ -86,6 +88,15 @@ enum pmic_arb_cmd_op_code {
 	PMIC_ARB_OP_ZERO_WRITE = 16,
 };
 
+/*
+ * PMIC arbiter version 5 uses different register offsets for read/write vs
+ * observer channels.
+ */
+enum pmic_arb_channel {
+	PMIC_ARB_CHANNEL_RW,
+	PMIC_ARB_CHANNEL_OBS,
+};
+
 /* Maximum number of support PMIC peripherals */
 #define PMIC_ARB_MAX_PERIPHS		512
 #define PMIC_ARB_TIMEOUT_US		100
@@ -112,7 +123,8 @@ enum pmic_arb_cmd_op_code {
 
 struct apid_data {
 	u16		ppid;
-	u8		owner;
+	u8		write_owner;
+	u8		irq_owner;
 };
 
 /**
@@ -121,6 +133,7 @@ struct apid_data {
  * @rd_base:		on v1 "core", on v2 "observer" register base off DT.
  * @wr_base:		on v1 "core", on v2 "chnls"    register base off DT.
  * @intr:		address of the SPMI interrupt control registers.
+ * @acc_status:		address of SPMI ACC interrupt status registers.
  * @cnfg:		address of the PMIC Arbiter configuration registers.
  * @lock:		lock to synchronize accesses.
  * @channel:		execution environment channel to use for accesses.
@@ -140,6 +153,7 @@ struct spmi_pmic_arb {
 	void __iomem		*rd_base;
 	void __iomem		*wr_base;
 	void __iomem		*intr;
+	void __iomem		*acc_status;
 	void __iomem		*cnfg;
 	void __iomem		*core;
 	resource_size_t		core_size;
@@ -179,6 +193,7 @@ struct spmi_pmic_arb {
  *			on v2 offset of SPMI_PIC_IRQ_STATUSn.
  * @irq_clear:		on v1 offset of PMIC_ARB_SPMI_PIC_IRQ_CLEARn
  *			on v2 offset of SPMI_PIC_IRQ_CLEARn.
+ * @channel_map_offset:	offset of PMIC_ARB_REG_CHNLn
  */
 struct pmic_arb_ver_ops {
 	const char *ver_str;
@@ -188,7 +203,7 @@ struct pmic_arb_ver_ops {
 			mode_t *mode);
 	/* spmi commands (read_cmd, write_cmd, cmd) functionality */
 	int (*offset)(struct spmi_pmic_arb *dev, u8 sid, u16 addr,
-		      u32 *offset);
+			enum pmic_arb_channel ch_type, u32 *offset);
 	u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc);
 	int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid);
 	/* Interrupts controller functionality (offset of PIC registers) */
@@ -196,6 +211,7 @@ struct pmic_arb_ver_ops {
 	u32 (*acc_enable)(u16 n);
 	u32 (*irq_status)(u16 n);
 	u32 (*irq_clear)(u16 n);
+	u32 (*channel_map_offset)(u16 n);
 };
 
 static inline void pmic_arb_base_write(struct spmi_pmic_arb *pa,
@@ -239,7 +255,8 @@ static void pa_read_data(struct spmi_pmic_arb *pa, u8 *buf, u32 reg, u8 bc)
 }
 
 static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
-				  void __iomem *base, u8 sid, u16 addr)
+				  void __iomem *base, u8 sid, u16 addr,
+				  enum pmic_arb_channel ch_type)
 {
 	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
 	u32 status = 0;
@@ -247,7 +264,7 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
 	u32 offset;
 	int rc;
 
-	rc = pa->ver_ops->offset(pa, sid, addr, &offset);
+	rc = pa->ver_ops->offset(pa, sid, addr, ch_type, &offset);
 	if (rc)
 		return rc;
 
@@ -298,7 +315,7 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
 	int rc;
 	u32 offset;
 
-	rc = pa->ver_ops->offset(pa, sid, 0, &offset);
+	rc = pa->ver_ops->offset(pa, sid, 0, PMIC_ARB_CHANNEL_RW, &offset);
 	if (rc)
 		return rc;
 
@@ -306,7 +323,8 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
 
 	raw_spin_lock_irqsave(&pa->lock, flags);
 	pmic_arb_base_write(pa, offset + PMIC_ARB_CMD, cmd);
-	rc = pmic_arb_wait_for_done(ctrl, pa->wr_base, sid, 0);
+	rc = pmic_arb_wait_for_done(ctrl, pa->wr_base, sid, 0,
+				    PMIC_ARB_CHANNEL_RW);
 	raw_spin_unlock_irqrestore(&pa->lock, flags);
 
 	return rc;
@@ -343,7 +361,7 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	u32 offset;
 	mode_t mode;
 
-	rc = pa->ver_ops->offset(pa, sid, addr, &offset);
+	rc = pa->ver_ops->offset(pa, sid, addr, PMIC_ARB_CHANNEL_OBS, &offset);
 	if (rc)
 		return rc;
 
@@ -379,7 +397,8 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 
 	raw_spin_lock_irqsave(&pa->lock, flags);
 	pmic_arb_set_rd_cmd(pa, offset + PMIC_ARB_CMD, cmd);
-	rc = pmic_arb_wait_for_done(ctrl, pa->rd_base, sid, addr);
+	rc = pmic_arb_wait_for_done(ctrl, pa->rd_base, sid, addr,
+				    PMIC_ARB_CHANNEL_OBS);
 	if (rc)
 		goto done;
 
@@ -405,7 +424,7 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 	u32 offset;
 	mode_t mode;
 
-	rc = pa->ver_ops->offset(pa, sid, addr, &offset);
+	rc = pa->ver_ops->offset(pa, sid, addr, PMIC_ARB_CHANNEL_RW, &offset);
 	if (rc)
 		return rc;
 
@@ -449,7 +468,8 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
 
 	/* Start the transaction */
 	pmic_arb_base_write(pa, offset + PMIC_ARB_CMD, cmd);
-	rc = pmic_arb_wait_for_done(ctrl, pa->wr_base, sid, addr);
+	rc = pmic_arb_wait_for_done(ctrl, pa->wr_base, sid, addr,
+				    PMIC_ARB_CHANNEL_RW);
 	raw_spin_unlock_irqrestore(&pa->lock, flags);
 
 	return rc;
@@ -547,7 +567,6 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
 {
 	struct spmi_pmic_arb *pa = irq_desc_get_handler_data(desc);
 	struct irq_chip *chip = irq_desc_get_chip(desc);
-	void __iomem *intr = pa->intr;
 	int first = pa->min_apid >> 5;
 	int last = pa->max_apid >> 5;
 	u32 status, enable;
@@ -556,13 +575,13 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
 	chained_irq_enter(chip, desc);
 
 	for (i = first; i <= last; ++i) {
-		status = readl_relaxed(intr +
+		status = readl_relaxed(pa->acc_status +
 				      pa->ver_ops->owner_acc_status(pa->ee, i));
 		while (status) {
 			id = ffs(status) - 1;
 			status &= ~BIT(id);
 			apid = id + i * 32;
-			enable = readl_relaxed(intr +
+			enable = readl_relaxed(pa->intr +
 					pa->ver_ops->acc_enable(apid));
 			if (enable & SPMI_PIC_ACC_ENABLE_BIT)
 				periph_interrupt(pa, apid);
@@ -705,11 +724,18 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 			(intspec[1] << 8), &apid);
 	if (rc < 0) {
 		dev_err(&pa->spmic->dev,
-		"failed to xlate sid = 0x%x, periph = 0x%x, irq = %x rc = %d\n",
+		"failed to xlate sid = 0x%x, periph = 0x%x, irq = %u rc = %d\n",
 		intspec[0], intspec[1], intspec[2], rc);
 		return rc;
 	}
 
+	if (pa->apid_data[apid].irq_owner != pa->ee) {
+		dev_err(&pa->spmic->dev, "failed to xlate sid = 0x%x, periph = 0x%x, irq = %u: ee=%u but owner=%u\n",
+			intspec[0], intspec[1], intspec[2], pa->ee,
+			pa->apid_data[apid].irq_owner);
+		return -ENODEV;
+	}
+
 	/* Keep track of {max,min}_apid for bounding search during interrupt */
 	if (apid > pa->max_apid)
 		pa->max_apid = apid;
@@ -795,7 +821,8 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
 
 /* v1 offset per ee */
 static int
-pmic_arb_offset_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u32 *offset)
+pmic_arb_offset_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr,
+		   enum pmic_arb_channel ch_type, u32 *offset)
 {
 	*offset = 0x800 + 0x80 * pa->channel;
 	return 0;
@@ -814,9 +841,11 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 	for (apid = pa->last_apid; apid < pa->max_periph; apid++) {
 		regval = readl_relaxed(pa->cnfg +
 				      SPMI_OWNERSHIP_TABLE_REG(apid));
-		pa->apid_data[apid].owner = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
+		pa->apid_data[apid].irq_owner
+			= SPMI_OWNERSHIP_PERIPH2OWNER(regval);
+		pa->apid_data[apid].write_owner = pa->apid_data[apid].irq_owner;
 
-		offset = PMIC_ARB_REG_CHNL(apid);
+		offset = pa->ver_ops->channel_map_offset(apid);
 		if (offset >= pa->core_size)
 			break;
 
@@ -854,27 +883,110 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 	return 0;
 }
 
+static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pa)
+{
+	u32 regval, offset;
+	u16 apid, prev_apid, ppid;
+	bool valid, is_irq_owner;
+
+	/*
+	 * PMIC_ARB_REG_CHNL is a table in HW mapping APID (channel) to PPID.
+	 * ppid_to_apid is an in-memory invert of that table.  In order to allow
+	 * multiple EE's to write to a single PPID in arbiter version 5, there
+	 * is more than one APID mapped to each PPID.  The owner field for each
+	 * of these mappings specifies the EE which is allowed to write to the
+	 * APID.  The owner of the last (highest) APID for a given PPID will
+	 * receive interrupts from the PPID.
+	 */
+	for (apid = 0; apid < pa->max_periph; apid++) {
+		offset = pa->ver_ops->channel_map_offset(apid);
+		if (offset >= pa->core_size)
+			break;
+
+		regval = readl_relaxed(pa->core + offset);
+		if (!regval)
+			continue;
+		ppid = (regval >> 8) & PMIC_ARB_PPID_MASK;
+		is_irq_owner = PMIC_ARB_CHAN_IS_IRQ_OWNER(regval);
+
+		regval = readl_relaxed(pa->cnfg +
+				      SPMI_OWNERSHIP_TABLE_REG(apid));
+		pa->apid_data[apid].write_owner
+			= SPMI_OWNERSHIP_PERIPH2OWNER(regval);
+
+		pa->apid_data[apid].irq_owner = is_irq_owner ?
+			pa->apid_data[apid].write_owner : INVALID_EE;
+
+		valid = pa->ppid_to_apid[ppid] & PMIC_ARB_CHAN_VALID;
+		prev_apid = pa->ppid_to_apid[ppid] & ~PMIC_ARB_CHAN_VALID;
+
+		if (valid && is_irq_owner &&
+		    pa->apid_data[prev_apid].write_owner == pa->ee) {
+			/*
+			 * Duplicate PPID mapping after the one for this EE;
+			 * override the irq owner
+			 */
+			pa->apid_data[prev_apid].irq_owner
+				= pa->apid_data[apid].irq_owner;
+		} else if (!valid || is_irq_owner) {
+			/* First PPID mapping or duplicate for another EE */
+			pa->ppid_to_apid[ppid] = apid | PMIC_ARB_CHAN_VALID;
+		}
+
+		pa->apid_data[apid].ppid = ppid;
+		pa->last_apid = apid;
+	}
+
+	/* Dump the mapping table for debug purposes. */
+	dev_dbg(&pa->spmic->dev, "PPID APID Write-EE IRQ-EE\n");
+	for (ppid = 0; ppid < PMIC_ARB_MAX_PPID; ppid++) {
+		valid = pa->ppid_to_apid[ppid] & PMIC_ARB_CHAN_VALID;
+		apid = pa->ppid_to_apid[ppid] & ~PMIC_ARB_CHAN_VALID;
+
+		if (valid)
+			dev_dbg(&pa->spmic->dev, "0x%03X %3u %2u %2u\n",
+				ppid, apid, pa->apid_data[apid].write_owner,
+				pa->apid_data[apid].irq_owner);
+	}
+
+	return 0;
+}
+
+static int
+pmic_arb_ppid_to_apid_v5(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u16 *apid)
+{
+	u16 ppid = (sid << 8) | (addr >> 8);
+
+	if (!(pa->ppid_to_apid[ppid] & PMIC_ARB_CHAN_VALID))
+		return -ENODEV;
+
+	*apid = pa->ppid_to_apid[ppid] & ~PMIC_ARB_CHAN_VALID;
+
+	return 0;
+}
+
 static int
 pmic_arb_mode_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
 {
 	u16 apid;
 	int rc;
 
-	rc = pmic_arb_ppid_to_apid_v2(pa, sid, addr, &apid);
+	rc = pa->ver_ops->ppid_to_apid(pa, sid, addr, &apid);
 	if (rc < 0)
 		return rc;
 
 	*mode = 0;
 	*mode |= S_IRUSR;
 
-	if (pa->ee == pa->apid_data[apid].owner)
+	if (pa->ee == pa->apid_data[apid].write_owner)
 		*mode |= S_IWUSR;
 	return 0;
 }
 
 /* v2 offset per ppid and per ee */
 static int
-pmic_arb_offset_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u32 *offset)
+pmic_arb_offset_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr,
+		   enum pmic_arb_channel ch_type, u32 *offset)
 {
 	u16 apid;
 	int rc;
@@ -887,6 +999,27 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
 	return 0;
 }
 
+/*
+ * v5 offset per ee and per apid for observer channels and per apid for
+ * read/write channels.
+ */
+static int
+pmic_arb_offset_v5(struct spmi_pmic_arb *pa, u8 sid, u16 addr,
+		   enum pmic_arb_channel ch_type, u32 *offset)
+{
+	u16 apid;
+	int rc;
+
+	rc = pmic_arb_ppid_to_apid_v5(pa, sid, addr, &apid);
+	if (rc < 0)
+		return rc;
+
+	*offset = (ch_type == PMIC_ARB_CHANNEL_OBS)
+			? 0x10000 * pa->ee + 0x80 * apid
+			: 0x10000 * apid;
+	return 0;
+}
+
 static u32 pmic_arb_fmt_cmd_v1(u8 opc, u8 sid, u16 addr, u8 bc)
 {
 	return (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
@@ -912,6 +1045,11 @@ static u32 pmic_arb_owner_acc_status_v3(u8 m, u16 n)
 	return 0x200000 + 0x1000 * m + 0x4 * n;
 }
 
+static u32 pmic_arb_owner_acc_status_v5(u8 m, u16 n)
+{
+	return 0x10000 * m + 0x4 * n;
+}
+
 static u32 pmic_arb_acc_enable_v1(u16 n)
 {
 	return 0x200 + 0x4 * n;
@@ -922,6 +1060,11 @@ static u32 pmic_arb_acc_enable_v2(u16 n)
 	return 0x1000 * n;
 }
 
+static u32 pmic_arb_acc_enable_v5(u16 n)
+{
+	return 0x100 + 0x10000 * n;
+}
+
 static u32 pmic_arb_irq_status_v1(u16 n)
 {
 	return 0x600 + 0x4 * n;
@@ -932,6 +1075,11 @@ static u32 pmic_arb_irq_status_v2(u16 n)
 	return 0x4 + 0x1000 * n;
 }
 
+static u32 pmic_arb_irq_status_v5(u16 n)
+{
+	return 0x104 + 0x10000 * n;
+}
+
 static u32 pmic_arb_irq_clear_v1(u16 n)
 {
 	return 0xA00 + 0x4 * n;
@@ -942,6 +1090,21 @@ static u32 pmic_arb_irq_clear_v2(u16 n)
 	return 0x8 + 0x1000 * n;
 }
 
+static u32 pmic_arb_irq_clear_v5(u16 n)
+{
+	return 0x108 + 0x10000 * n;
+}
+
+static u32 pmic_arb_channel_map_offset_v2(u16 n)
+{
+	return 0x800 + 0x4 * n;
+}
+
+static u32 pmic_arb_channel_map_offset_v5(u16 n)
+{
+	return 0x900 + 0x4 * n;
+}
+
 static const struct pmic_arb_ver_ops pmic_arb_v1 = {
 	.ver_str		= "v1",
 	.ppid_to_apid		= pmic_arb_ppid_to_apid_v1,
@@ -953,6 +1116,7 @@ static u32 pmic_arb_irq_clear_v2(u16 n)
 	.acc_enable		= pmic_arb_acc_enable_v1,
 	.irq_status		= pmic_arb_irq_status_v1,
 	.irq_clear		= pmic_arb_irq_clear_v1,
+	.channel_map_offset	= pmic_arb_channel_map_offset_v2,
 };
 
 static const struct pmic_arb_ver_ops pmic_arb_v2 = {
@@ -966,6 +1130,7 @@ static u32 pmic_arb_irq_clear_v2(u16 n)
 	.acc_enable		= pmic_arb_acc_enable_v2,
 	.irq_status		= pmic_arb_irq_status_v2,
 	.irq_clear		= pmic_arb_irq_clear_v2,
+	.channel_map_offset	= pmic_arb_channel_map_offset_v2,
 };
 
 static const struct pmic_arb_ver_ops pmic_arb_v3 = {
@@ -979,6 +1144,21 @@ static u32 pmic_arb_irq_clear_v2(u16 n)
 	.acc_enable		= pmic_arb_acc_enable_v2,
 	.irq_status		= pmic_arb_irq_status_v2,
 	.irq_clear		= pmic_arb_irq_clear_v2,
+	.channel_map_offset	= pmic_arb_channel_map_offset_v2,
+};
+
+static const struct pmic_arb_ver_ops pmic_arb_v5 = {
+	.ver_str		= "v5",
+	.ppid_to_apid		= pmic_arb_ppid_to_apid_v5,
+	.mode			= pmic_arb_mode_v2,
+	.non_data_cmd		= pmic_arb_non_data_cmd_v2,
+	.offset			= pmic_arb_offset_v5,
+	.fmt_cmd		= pmic_arb_fmt_cmd_v2,
+	.owner_acc_status	= pmic_arb_owner_acc_status_v5,
+	.acc_enable		= pmic_arb_acc_enable_v5,
+	.irq_status		= pmic_arb_irq_status_v5,
+	.irq_clear		= pmic_arb_irq_clear_v5,
+	.channel_map_offset	= pmic_arb_channel_map_offset_v5,
 };
 
 static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
@@ -1033,11 +1213,14 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 
 		if (hw_ver < PMIC_ARB_VERSION_V3_MIN)
 			pa->ver_ops = &pmic_arb_v2;
-		else
+		else if (hw_ver < PMIC_ARB_VERSION_V5_MIN)
 			pa->ver_ops = &pmic_arb_v3;
+		else
+			pa->ver_ops = &pmic_arb_v5;
 
-		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL(0) */
-		pa->max_periph = (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;
+		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL0 */
+		pa->max_periph
+		     = (pa->core_size - pa->ver_ops->channel_map_offset(0)) / 4;
 
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						   "obsrvr");
@@ -1074,6 +1257,14 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 		err = PTR_ERR(pa->intr);
 		goto err_put_ctrl;
 	}
+	pa->acc_status = pa->intr;
+
+	/*
+	 * PMIC arbiter v5 groups the IRQ control registers in the same hardware
+	 * module as the read/write channels.
+	 */
+	if (hw_ver >= PMIC_ARB_VERSION_V5_MIN)
+		pa->intr = pa->wr_base;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cnfg");
 	pa->cnfg = devm_ioremap_resource(&ctrl->dev, res);
@@ -1136,6 +1327,15 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 	ctrl->read_cmd = pmic_arb_read_cmd;
 	ctrl->write_cmd = pmic_arb_write_cmd;
 
+	if (hw_ver >= PMIC_ARB_VERSION_V5_MIN) {
+		err = pmic_arb_read_apid_map_v5(pa);
+		if (err) {
+			dev_err(&pdev->dev, "could not read APID->PPID mapping table, rc= %d\n",
+				err);
+			goto err_put_ctrl;
+		}
+	}
+
 	dev_dbg(&pdev->dev, "adding irq domain\n");
 	pa->domain = irq_domain_add_tree(pdev->dev.of_node,
 					 &pmic_arb_irq_domain_ops, pa);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 14/15] spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq
  2017-05-30 12:38 ` Kiran Gunda
                   ` (13 preceding siblings ...)
  (?)
@ 2017-05-30 12:39 ` Kiran Gunda
  2017-05-30 22:23     ` kbuild test robot
  2017-05-31 17:53   ` Stephen Boyd
  -1 siblings, 2 replies; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:39 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, David Collins,
	Christophe JAILLET, Subbaraman Narayanamurthy, linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Subbaraman Narayanamurthy <subbaram@codeaurora.org>

Currently, cleanup_irq() is invoked when a peripheral's interrupt
fires and there is no mapping present in the interrupt domain of
spmi interrupt controller.

The cleanup_irq clears the arbiter bit, clears the pmic interrupt
and disables it at the pmic in that order. The last disable in
cleanup_irq races with request_irq() in that it stomps over the
enable issued by request_irq. Fix this by not writing to the pmic
in cleanup_irq. The latched bit will be left set in the pmic,
which will not send us more interrupts even if the enable bit
stays enabled.

When a client wants to request an interrupt, use the activate
callback on the irq_domain to clear latched bit. This ensures
that the latched, if set due to the above changes in cleanup_irq
or when the bootloader leaves it set, gets cleaned up, paving way
for upcoming interrupts to trigger.

With this, there is a possibility of unwanted triggering of
interrupt right after the latched bit is cleared - the interrupt
may be left enabled too. To avoid that, clear the enable first
followed by clearing the latched bit in the activate callback.

Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 27 ++++++++++++---------------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index b755c24..767bd2c 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -522,24 +522,9 @@ static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
 
 static void cleanup_irq(struct spmi_pmic_arb *pa, u16 apid, int id)
 {
-	u16 ppid = pa->apid_data[apid].ppid;
-	u8 sid = ppid >> 8;
-	u8 per = ppid & 0xFF;
 	u8 irq_mask = BIT(id);
 
 	writel_relaxed(irq_mask, pa->intr + pa->ver_ops->irq_clear(apid));
-
-	if (pmic_arb_write_cmd(pa->spmic, SPMI_CMD_EXT_WRITEL, sid,
-			(per << 8) + QPNPINT_REG_LATCHED_CLR, &irq_mask, 1))
-		dev_err_ratelimited(&pa->spmic->dev,
-				"failed to ack irq_mask = 0x%x for ppid = %x\n",
-				irq_mask, ppid);
-
-	if (pmic_arb_write_cmd(pa->spmic, SPMI_CMD_EXT_WRITEL, sid,
-			       (per << 8) + QPNPINT_REG_EN_CLR, &irq_mask, 1))
-		dev_err_ratelimited(&pa->spmic->dev,
-				"failed to ack irq_mask = 0x%x for ppid = %x\n",
-				irq_mask, ppid);
 }
 
 static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid)
@@ -698,6 +683,17 @@ static int qpnpint_get_irqchip_state(struct irq_data *d,
 			| IRQCHIP_SKIP_SET_WAKE,
 };
 
+static void qpnpint_irq_domain_activate(struct irq_domain *domain,
+					struct irq_data *d)
+{
+	u8 irq = HWIRQ_IRQ(d->hwirq);
+	u8 buf;
+
+	buf = BIT(irq);
+	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &buf, 1);
+	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &buf, 1);
+}
+
 static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
 					   struct device_node *controller,
 					   const u32 *intspec,
@@ -1164,6 +1160,7 @@ static u32 pmic_arb_channel_map_offset_v5(u16 n)
 static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
 	.map	= qpnpint_irq_domain_map,
 	.xlate	= qpnpint_irq_domain_dt_translate,
+	.activate	= qpnpint_irq_domain_activate,
 };
 
 static int spmi_pmic_arb_probe(struct platform_device *pdev)
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH V1 15/15] spmi: pmic-arb: instantiate spmi_devices at arch_initcall
  2017-05-30 12:38 ` Kiran Gunda
                   ` (14 preceding siblings ...)
  (?)
@ 2017-05-30 12:39 ` Kiran Gunda
  2017-05-31 22:07   ` Stephen Boyd
  -1 siblings, 1 reply; 62+ messages in thread
From: Kiran Gunda @ 2017-05-30 12:39 UTC (permalink / raw)
  To: Kiran Gunda, Abhijeet Dharmapurikar, Christophe JAILLET,
	Greg Kroah-Hartman, Subbaraman Narayanamurthy, David Collins,
	linux-kernel
  Cc: linux-arm-msm, adharmap, aghayal, sboyd

From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>

The spmi arbiter device spawns spmi_devices which in turn spawn
platform_devices for pmic peripherals.

Move the arbiter's driver init to arch_initcall so that the subsequent
devices it spawns get instantiated earlier.

Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
---
 drivers/spmi/spmi-pmic-arb.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 767bd2c..069799c 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -1384,7 +1384,12 @@ static int spmi_pmic_arb_remove(struct platform_device *pdev)
 		.of_match_table = spmi_pmic_arb_match_table,
 	},
 };
-module_platform_driver(spmi_pmic_arb_driver);
+
+int __init spmi_pmic_arb_init(void)
+{
+	return platform_driver_register(&spmi_pmic_arb_driver);
+}
+arch_initcall(spmi_pmic_arb_init);
 
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:spmi_pmic_arb");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
--

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 14/15] spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq
  2017-05-30 12:39 ` [PATCH V1 14/15] spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq Kiran Gunda
@ 2017-05-30 22:23     ` kbuild test robot
  2017-05-31 17:53   ` Stephen Boyd
  1 sibling, 0 replies; 62+ messages in thread
From: kbuild test robot @ 2017-05-30 22:23 UTC (permalink / raw)
  Cc: kbuild-all, Kiran Gunda, Abhijeet Dharmapurikar, David Collins,
	Christophe JAILLET, Subbaraman Narayanamurthy, linux-kernel,
	linux-arm-msm, adharmap, aghayal, sboyd

[-- Attachment #1: Type: text/plain, Size: 2224 bytes --]

Hi Subbaraman,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc3 next-20170530]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Kiran-Gunda/spmi-pmic_arb-block-access-of-invalid-read-and-writes/20170531-034312
config: xtensa-allmodconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 4.9.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=xtensa 

All error/warnings (new ones prefixed by >>):

>> drivers//spmi/spmi-pmic-arb.c:1163:2: error: unknown field 'activate' specified in initializer
     .activate = qpnpint_irq_domain_activate,
     ^
>> drivers//spmi/spmi-pmic-arb.c:1163:2: warning: excess elements in struct initializer
   drivers//spmi/spmi-pmic-arb.c:1163:2: warning: (near initialization for 'pmic_arb_irq_domain_ops')

vim +/activate +1163 drivers//spmi/spmi-pmic-arb.c

  1147		.ver_str		= "v5",
  1148		.ppid_to_apid		= pmic_arb_ppid_to_apid_v5,
  1149		.mode			= pmic_arb_mode_v2,
  1150		.non_data_cmd		= pmic_arb_non_data_cmd_v2,
  1151		.offset			= pmic_arb_offset_v5,
  1152		.fmt_cmd		= pmic_arb_fmt_cmd_v2,
  1153		.owner_acc_status	= pmic_arb_owner_acc_status_v5,
  1154		.acc_enable		= pmic_arb_acc_enable_v5,
  1155		.irq_status		= pmic_arb_irq_status_v5,
  1156		.irq_clear		= pmic_arb_irq_clear_v5,
  1157		.channel_map_offset	= pmic_arb_channel_map_offset_v5,
  1158	};
  1159	
  1160	static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
  1161		.map	= qpnpint_irq_domain_map,
  1162		.xlate	= qpnpint_irq_domain_dt_translate,
> 1163		.activate	= qpnpint_irq_domain_activate,
  1164	};
  1165	
  1166	static int spmi_pmic_arb_probe(struct platform_device *pdev)
  1167	{
  1168		struct spmi_pmic_arb *pa;
  1169		struct spmi_controller *ctrl;
  1170		struct resource *res;
  1171		void __iomem *core;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 50141 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 14/15] spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq
@ 2017-05-30 22:23     ` kbuild test robot
  0 siblings, 0 replies; 62+ messages in thread
From: kbuild test robot @ 2017-05-30 22:23 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: kbuild-all, Kiran Gunda, Abhijeet Dharmapurikar, David Collins,
	Christophe JAILLET, Subbaraman Narayanamurthy, linux-kernel,
	linux-arm-msm, adharmap, aghayal, sboyd

[-- Attachment #1: Type: text/plain, Size: 2224 bytes --]

Hi Subbaraman,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc3 next-20170530]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Kiran-Gunda/spmi-pmic_arb-block-access-of-invalid-read-and-writes/20170531-034312
config: xtensa-allmodconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 4.9.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=xtensa 

All error/warnings (new ones prefixed by >>):

>> drivers//spmi/spmi-pmic-arb.c:1163:2: error: unknown field 'activate' specified in initializer
     .activate = qpnpint_irq_domain_activate,
     ^
>> drivers//spmi/spmi-pmic-arb.c:1163:2: warning: excess elements in struct initializer
   drivers//spmi/spmi-pmic-arb.c:1163:2: warning: (near initialization for 'pmic_arb_irq_domain_ops')

vim +/activate +1163 drivers//spmi/spmi-pmic-arb.c

  1147		.ver_str		= "v5",
  1148		.ppid_to_apid		= pmic_arb_ppid_to_apid_v5,
  1149		.mode			= pmic_arb_mode_v2,
  1150		.non_data_cmd		= pmic_arb_non_data_cmd_v2,
  1151		.offset			= pmic_arb_offset_v5,
  1152		.fmt_cmd		= pmic_arb_fmt_cmd_v2,
  1153		.owner_acc_status	= pmic_arb_owner_acc_status_v5,
  1154		.acc_enable		= pmic_arb_acc_enable_v5,
  1155		.irq_status		= pmic_arb_irq_status_v5,
  1156		.irq_clear		= pmic_arb_irq_clear_v5,
  1157		.channel_map_offset	= pmic_arb_channel_map_offset_v5,
  1158	};
  1159	
  1160	static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
  1161		.map	= qpnpint_irq_domain_map,
  1162		.xlate	= qpnpint_irq_domain_dt_translate,
> 1163		.activate	= qpnpint_irq_domain_activate,
  1164	};
  1165	
  1166	static int spmi_pmic_arb_probe(struct platform_device *pdev)
  1167	{
  1168		struct spmi_pmic_arb *pa;
  1169		struct spmi_controller *ctrl;
  1170		struct resource *res;
  1171		void __iomem *core;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 50141 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 01/15] spmi: pmic_arb: block access of invalid read and writes
  2017-05-30 12:38 ` [PATCH V1 01/15] spmi: pmic_arb: block access of invalid read and writes Kiran Gunda
@ 2017-05-31  0:33   ` Stephen Boyd
  2017-06-12 11:26     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31  0:33 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET,
	Subbaraman Narayanamurthy, David Collins, linux-kernel,
	linux-arm-msm, adharmap, aghayal

On 05/30, Kiran Gunda wrote:
> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> 
> The system crashes due to bad access when reading from an non configured
> peripheral and when writing to peripheral which is not owned by current
> ee. This patch verifies ownership to avoid crashing on
> write.

What systems? As far as I know we don't have any bad accesses
happening right now. If they are happening, we should fix the
code that's accessing hardware that isn't owned by them.

> For reads, since the forward mapping table, data_channel->ppid, is
> towards the end of the block, we use the core size to figure the
> max number of ppids supported. The table starts at an offset of 0x800
> within the block, so size - 0x800 will give us the area used by the
> table. Since each table is 4 bytes long (core_size - 0x800) / 4 will
> gives us the number of data_channel supported.
> This new protection is functional on hw v2.

Which brings us to the next question which is why do we need this
patch at all? We aren't probing hardware to see what we have
access to and then populating device structures based on that.
Instead, we're just populating DT nodes that we've hardcoded in
the dts files, so I'm a little lost on why we would have a node
in there that we couldn't access. Please add such details to the
commit text.

> 
> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
> ---
>  drivers/spmi/spmi-pmic-arb.c | 84 +++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 83 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
> index 5ec3a59..df463d4 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -111,6 +111,7 @@ enum pmic_arb_cmd_op_code {
>   * @ee:			the current Execution Environment
>   * @min_apid:		minimum APID (used for bounding IRQ search)
>   * @max_apid:		maximum APID
> + * @max_periph:		maximum number of PMIC peripherals supported by HW.

Nitpick: Most of these lines don't end with a full-stop.

>   * @mapping_table:	in-memory copy of PPID -> APID mapping table.
>   * @domain:		irq domain object for PMIC IRQ domain
>   * @spmic:		SPMI controller object
> @@ -132,6 +133,7 @@ struct spmi_pmic_arb_dev {
>  	u8			ee;
>  	u16			min_apid;
>  	u16			max_apid;
> +	u16			max_periph;
>  	u32			*mapping_table;
>  	DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS);
>  	struct irq_domain	*domain;
> @@ -140,11 +142,13 @@ struct spmi_pmic_arb_dev {
>  	const struct pmic_arb_ver_ops *ver_ops;
>  	u16			*ppid_to_chan;
>  	u16			last_channel;
> +	u8			*chan_to_owner;

And we didn't document this one.

>  };
>  
>  /**
>   * pmic_arb_ver: version dependent functionality.
>   *
> + * @mode:	access rights to specified pmic peripheral.
>   * @non_data_cmd:	on v1 issues an spmi non-data command.
>   *			on v2 no HW support, returns -EOPNOTSUPP.
>   * @offset:		on v1 offset of per-ee channel.
> @@ -160,6 +164,8 @@ struct spmi_pmic_arb_dev {
>   *			on v2 offset of SPMI_PIC_IRQ_CLEARn.
>   */
>  struct pmic_arb_ver_ops {
> +	int (*mode)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
> +			mode_t *mode);
>  	/* spmi commands (read_cmd, write_cmd, cmd) functionality */
>  	int (*offset)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
>  		      u32 *offset);
> @@ -313,11 +319,23 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
>  	u32 cmd;
>  	int rc;
>  	u32 offset;
> +	mode_t mode;
>  
>  	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
>  	if (rc)
>  		return rc;
>  
> +	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
> +	if (rc)
> +		return rc;
> +
> +	if (!(mode & S_IRUSR)) {

Using mode_t for hardware access is odd. Perhaps just come up
with some sort of READ/WRITE enum instead (if this sort of
checking is even needed)?

> +		dev_err(&pmic_arb->spmic->dev,

The dev_err() just after uses ctrl->dev? Why not here?

> +			"error: impermissible read from peripheral sid:%d addr:0x%x\n",
> +			sid, addr);
> +		return -EPERM;
> +	}
> +
>  	if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
>  		dev_err(&ctrl->dev,
>  			"pmic-arb supports 1..%d bytes per trans, but:%zu requested",
> @@ -364,11 +382,23 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
>  	u32 cmd;
>  	int rc;
>  	u32 offset;
> +	mode_t mode;
>  
>  	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
>  	if (rc)
>  		return rc;
>  
> +	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
> +	if (rc)
> +		return rc;
> +
> +	if (!(mode & S_IWUSR)) {
> +		dev_err(&pmic_arb->spmic->dev,

The dev_err() just after uses ctrl->dev? Why not here?

> +			"error: impermissible write to peripheral sid:%d addr:0x%x\n",
> +			sid, addr);
> +		return -EPERM;
> +	}
> +
>  	if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
>  		dev_err(&ctrl->dev,
>  			"pmic-arb supports 1..%d bytes per trans, but:%zu requested",
> @@ -727,6 +757,13 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
>  	return 0;
>  }
>  
> +static int
> +pmic_arb_mode_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, mode_t *mode)
> +{
> +	*mode = S_IRUSR | S_IWUSR;
> +	return 0;

If mode was only positive then errors could be negative and no
access could be 0. Then we could just return the mode from the
function instead of passing a pointer around.

> +}
> +
>  /* v1 offset per ee */
>  static int
>  pmic_arb_offset_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, u32 *offset)
> @@ -745,7 +782,11 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb_dev *pa, u16 ppid)
>  	 * PMIC_ARB_REG_CHNL is a table in HW mapping channel to ppid.
>  	 * ppid_to_chan is an in-memory invert of that table.
>  	 */
> -	for (chan = pa->last_channel; ; chan++) {
> +	for (chan = pa->last_channel; chan < pa->max_periph; chan++) {
> +		regval = readl_relaxed(pa->cnfg +
> +				      SPMI_OWNERSHIP_TABLE_REG(chan));
> +		pa->chan_to_owner[chan] = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
> +
>  		offset = PMIC_ARB_REG_CHNL(chan);
>  		if (offset >= pa->core_size)
>  			break;

Seems like an unrelated change to the mapping logic?

> @@ -767,6 +808,27 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb_dev *pa, u16 ppid)
>  }
>  
>  
> +static int
> +pmic_arb_mode_v2(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, mode_t *mode)

Probably spmi_pmic_arb_dev should be const here.

> +{
> +	u16 ppid = (sid << 8) | (addr >> 8);
> +	u16 chan;
> +	u8 owner;
> +
> +	chan = pa->ppid_to_chan[ppid];
> +	if (!(chan & PMIC_ARB_CHAN_VALID))
> +		return -ENODEV;
> +
> +	*mode = 0;
> +	*mode |= S_IRUSR;
> +
> +	chan &= ~PMIC_ARB_CHAN_VALID;
> +	owner = pa->chan_to_owner[chan];
> +	if (owner == pa->ee)
> +		*mode |= S_IWUSR;
> +	return 0;
> +}
> +
>  /* v2 offset per ppid (chan) and per ee */
>  static int
>  pmic_arb_offset_v2(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, u32 *offset)
> @@ -879,6 +943,12 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
>  
>  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
>  	pa->core_size = resource_size(res);
> +	if (pa->core_size <= 0x800) {
> +		dev_err(&pdev->dev, "core_size is smaller than 0x800. Failing Probe\n");

Not sure why probe is capitalized.

> +		err = -EINVAL;
> +		goto err_put_ctrl;
> +	}
> +

We don't need these sorts of DT validation checks. Please remove.

>  	core = devm_ioremap_resource(&ctrl->dev, res);
>  	if (IS_ERR(core)) {
>  		err = PTR_ERR(core);
> @@ -899,6 +969,9 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
>  		pa->core = core;
>  		pa->ver_ops = &pmic_arb_v2;
>  
> +		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL(0) */
> +		pa->max_periph =  (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;
> +
>  		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>  						   "obsrvr");
>  		pa->rd_base = devm_ioremap_resource(&ctrl->dev, res);
>  
>  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
> -- 
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
> --

P.S. Please put a newline in your signature so it doesn't exceed
80 columns.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 02/15] spmi: pmic-arb: rename spmi_pmic_arb_dev to spmi_pmic_arb
  2017-05-30 12:38 ` [PATCH V1 02/15] spmi: pmic-arb: rename spmi_pmic_arb_dev to spmi_pmic_arb Kiran Gunda
@ 2017-05-31  0:46   ` Stephen Boyd
  2017-06-01 16:11     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31  0:46 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Greg Kroah-Hartman, David Collins,
	Subbaraman Narayanamurthy, Christophe JAILLET, linux-kernel,
	linux-arm-msm, adharmap, aghayal

On 05/30, Kiran Gunda wrote:
> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> 
> Usually *_dev best used for structures that embed a struct device in
> them. spmi_pmic_arb_dev doesn't embed one. It is simply a driver data
> structure. Use an appropriate name for it.
> 
> Also there are many places in the driver that left shift the bit to
> generate a bit mask. Replace it with the BIT() macro.

That would be a different patch because the subject doesn't even
mention this.

> 
> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
> ---
>  drivers/spmi/spmi-pmic-arb.c | 164 +++++++++++++++++++++----------------------

Would also be nice if you ran scripts/objdiff on this so we can
be confident the code didn't change.

>  1 file changed, 82 insertions(+), 82 deletions(-)
> 
> diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
> index df463d4..7f918ea 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -58,10 +58,10 @@
>  
>  /* Channel Status fields */
>  enum pmic_arb_chnl_status {
> -	PMIC_ARB_STATUS_DONE	= (1 << 0),
> -	PMIC_ARB_STATUS_FAILURE	= (1 << 1),
> -	PMIC_ARB_STATUS_DENIED	= (1 << 2),
> -	PMIC_ARB_STATUS_DROPPED	= (1 << 3),
> +	PMIC_ARB_STATUS_DONE	= BIT(0),
> +	PMIC_ARB_STATUS_FAILURE	= BIT(1),
> +	PMIC_ARB_STATUS_DENIED	= BIT(2),
> +	PMIC_ARB_STATUS_DROPPED	= BIT(3),
>  };
>  
>  /* Command register fields */
> @@ -99,7 +99,7 @@ enum pmic_arb_cmd_op_code {
>  struct pmic_arb_ver_ops;
>  
>  /**
> - * spmi_pmic_arb_dev - SPMI PMIC Arbiter object
> + * spmi_pmic_arb - SPMI PMIC Arbiter object
>   *
>   * @rd_base:		on v1 "core", on v2 "observer" register base off DT.
>   * @wr_base:		on v1 "core", on v2 "chnls"    register base off DT.
> @@ -120,7 +120,7 @@ enum pmic_arb_cmd_op_code {
>   * @ppid_to_chan	in-memory copy of PPID -> channel (APID) mapping table.
>   *			v2 only.
>   */
> -struct spmi_pmic_arb_dev {
> +struct spmi_pmic_arb {
>  	void __iomem		*rd_base;
>  	void __iomem		*wr_base;
>  	void __iomem		*intr;
> @@ -164,10 +164,10 @@ struct spmi_pmic_arb_dev {
>   *			on v2 offset of SPMI_PIC_IRQ_CLEARn.
>   */
>  struct pmic_arb_ver_ops {
> -	int (*mode)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
> +	int (*mode)(struct spmi_pmic_arb *dev, u8 sid, u16 addr,

But we leave dev here? I'm losing faith that this patch is
worthwhile.

>  			mode_t *mode);
>  	/* spmi commands (read_cmd, write_cmd, cmd) functionality */
> -	int (*offset)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
> +	int (*offset)(struct spmi_pmic_arb *dev, u8 sid, u16 addr,
>  		      u32 *offset);
>  	u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc);
>  	int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid);
> @@ -178,16 +178,16 @@ struct pmic_arb_ver_ops {
>  	u32 (*irq_clear)(u8 n);
>  };
>  
> -static inline void pmic_arb_base_write(struct spmi_pmic_arb_dev *dev,
> +static inline void pmic_arb_base_write(struct spmi_pmic_arb *pa,
>  				       u32 offset, u32 val)
>  {
> -	writel_relaxed(val, dev->wr_base + offset);
> +	writel_relaxed(val, pa->wr_base + offset);

"pa" is a little confusing with things like physical address and
such. I would have gone for "arb", but the code is written
already, so why change it now?

>  }
>  
> -static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb_dev *dev,
> +static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb *pa,
>  				       u32 offset, u32 val)
>  {
> -	writel_relaxed(val, dev->rd_base + offset);
> +	writel_relaxed(val, pa->rd_base + offset);
>  }
>  
>  /**
> @@ -196,9 +196,10 @@ static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb_dev *dev,
>   * @reg:	register's address
>   * @buf:	output parameter, length must be bc + 1
>   */
> -static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
> +static void pa_read_data(struct spmi_pmic_arb *pa, u8 *buf, u32 reg, u8 bc)

In fact, I would rename these pa_{read,write}_data() functions as
pmic_arb_{read,write}_data() to be consistent. These are the only
places "pa_" is used right now.

>  {
> -	u32 data = __raw_readl(dev->rd_base + reg);
> +	u32 data = __raw_readl(pa->rd_base + reg);
> +
>  	memcpy(buf, &data, (bc & 3) + 1);
>  }
>  
> @@ -209,23 +210,24 @@ static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
>   * @buf:	buffer to write. length must be bc + 1.
>   */
>  static void
> -pa_write_data(struct spmi_pmic_arb_dev *dev, const u8 *buf, u32 reg, u8 bc)
> +pa_write_data(struct spmi_pmic_arb *pa, const u8 *buf, u32 reg, u8 bc)
>  {
>  	u32 data = 0;
> +
>  	memcpy(&data, buf, (bc & 3) + 1);
> -	__raw_writel(data, dev->wr_base + reg);
> +	pmic_arb_base_write(pa, reg, data);

This is an unrelated change. Not sure what's going on with this
diff but we most likely want to keep the __raw_writel() here. See
how renames introduce bugs and why we don't value them?

>  }
>  
> @@ -270,22 +272,22 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
>  static int
>  pmic_arb_non_data_cmd_v1(struct spmi_controller *ctrl, u8 opc, u8 sid)
>  {
> -	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
> +	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
>  	unsigned long flags;
>  	u32 cmd;
>  	int rc;
>  	u32 offset;
>  
> -	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, 0, &offset);
> +	rc = pa->ver_ops->offset(pa, sid, 0, &offset);
>  	if (rc)
>  		return rc;
>  
>  	cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20);
>  
> -	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
> -	pmic_arb_base_write(pmic_arb, offset + PMIC_ARB_CMD, cmd);
> -	rc = pmic_arb_wait_for_done(ctrl, pmic_arb->wr_base, sid, 0);
> -	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
> +	raw_spin_lock_irqsave(&pa->lock, flags);
> +	pmic_arb_base_write(pa, offset + PMIC_ARB_CMD, cmd);
> +	rc = pmic_arb_wait_for_done(ctrl, pa->wr_base, sid, 0);
> +	raw_spin_unlock_irqrestore(&pa->lock, flags);
>  
>  	return rc;

Yeah pmic_arb sounds fine too. Not sure why we changed anything
in this function.

>  }
> @@ -299,7 +301,7 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
>  /* Non-data command */
>  static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
>  {
> -	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
> +	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
>  
>  	dev_dbg(&ctrl->dev, "cmd op:0x%x sid:%d\n", opc, sid);
>  
> @@ -307,13 +309,13 @@ static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
>  	if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
>  		return -EINVAL;
>  
> -	return pmic_arb->ver_ops->non_data_cmd(ctrl, opc, sid);
> +	return pa->ver_ops->non_data_cmd(ctrl, opc, sid);

Same story...

>  }
>  
>  static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
>  			     u16 addr, u8 *buf, size_t len)
>  {
> -	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
> +	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
>  	unsigned long flags;
>  	u8 bc = len - 1;
>  	u32 cmd;
> @@ -321,16 +323,16 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
>  	u32 offset;
>  	mode_t mode;
>  
> -	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
> +	rc = pa->ver_ops->offset(pa, sid, addr, &offset);
>  	if (rc)
>  		return rc;
>  
> -	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
> +	rc = pa->ver_ops->mode(pa, sid, addr, &mode);
>  	if (rc)
>  		return rc;
>  
>  	if (!(mode & S_IRUSR)) {
> -		dev_err(&pmic_arb->spmic->dev,
> +		dev_err(&pa->spmic->dev,
>  			"error: impermissible read from peripheral sid:%d addr:0x%x\n",
>  			sid, addr);
>  		return -EPERM;
> @@ -353,30 +355,29 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
>  	else
>  		return -EINVAL;
>  
> -	cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc);
> +	cmd = pa->ver_ops->fmt_cmd(opc, sid, addr, bc);
>  
> -	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
> -	pmic_arb_set_rd_cmd(pmic_arb, offset + PMIC_ARB_CMD, cmd);
> -	rc = pmic_arb_wait_for_done(ctrl, pmic_arb->rd_base, sid, addr);
> +	raw_spin_lock_irqsave(&pa->lock, flags);
> +	pmic_arb_set_rd_cmd(pa, offset + PMIC_ARB_CMD, cmd);
> +	rc = pmic_arb_wait_for_done(ctrl, pa->rd_base, sid, addr);
>  	if (rc)
>  		goto done;
>  
> -	pa_read_data(pmic_arb, buf, offset + PMIC_ARB_RDATA0,
> +	pa_read_data(pa, buf, offset + PMIC_ARB_RDATA0,
>  		     min_t(u8, bc, 3));
>  
>  	if (bc > 3)
> -		pa_read_data(pmic_arb, buf + 4,
> -				offset + PMIC_ARB_RDATA1, bc - 4);
> +		pa_read_data(pa, buf + 4, offset + PMIC_ARB_RDATA1, bc - 4);
>  
>  done:
> -	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
> +	raw_spin_unlock_irqrestore(&pa->lock, flags);
>  	return rc;
>  }
>  
>  static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
>  			      u16 addr, const u8 *buf, size_t len)
>  {
> -	struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
> +	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
>  	unsigned long flags;
>  	u8 bc = len - 1;
>  	u32 cmd;
> @@ -384,16 +385,16 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
>  	u32 offset;
>  	mode_t mode;
>  
> -	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
> +	rc = pa->ver_ops->offset(pa, sid, addr, &offset);
>  	if (rc)
>  		return rc;
>  
> -	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
> +	rc = pa->ver_ops->mode(pa, sid, addr, &mode);
>  	if (rc)
>  		return rc;
>  
>  	if (!(mode & S_IWUSR)) {
> -		dev_err(&pmic_arb->spmic->dev,
> +		dev_err(&pa->spmic->dev,
>  			"error: impermissible write to peripheral sid:%d addr:0x%x\n",
>  			sid, addr);
>  		return -EPERM;
> @@ -418,20 +419,18 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
>  	else
>  		return -EINVAL;
>  
> -	cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc);
> +	cmd = pa->ver_ops->fmt_cmd(opc, sid, addr, bc);
>  
>  	/* Write data to FIFOs */
> -	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
> -	pa_write_data(pmic_arb, buf, offset + PMIC_ARB_WDATA0,
> -		      min_t(u8, bc, 3));
> +	raw_spin_lock_irqsave(&pa->lock, flags);
> +	pa_write_data(pa, buf, offset + PMIC_ARB_WDATA0, min_t(u8, bc, 3));
>  	if (bc > 3)
> -		pa_write_data(pmic_arb, buf + 4,
> -				offset + PMIC_ARB_WDATA1, bc - 4);
> +		pa_write_data(pa, buf + 4, offset + PMIC_ARB_WDATA1, bc - 4);
>  
>  	/* Start the transaction */
> -	pmic_arb_base_write(pmic_arb, offset + PMIC_ARB_CMD, cmd);
> -	rc = pmic_arb_wait_for_done(ctrl, pmic_arb->wr_base, sid, addr);
> -	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
> +	pmic_arb_base_write(pa, offset + PMIC_ARB_CMD, cmd);
> +	rc = pmic_arb_wait_for_done(ctrl, pa->wr_base, sid, addr);
> +	raw_spin_unlock_irqrestore(&pa->lock, flags);
>  
>  	return rc;
>  }

Same story for all this diff.

> @@ -457,7 +456,7 @@ struct spmi_pmic_arb_qpnpint_type {
>  static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
>  			       size_t len)
>  {
> -	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
> +	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
>  	u8 sid = d->hwirq >> 24;
>  	u8 per = d->hwirq >> 16;
>  
> @@ -470,7 +469,7 @@ static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
>  
>  static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
>  {
> -	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
> +	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
>  	u8 sid = d->hwirq >> 24;
>  	u8 per = d->hwirq >> 16;
>  
> @@ -481,7 +480,7 @@ static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
>  				    d->irq);
>  }
>  
> -static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
> +static void periph_interrupt(struct spmi_pmic_arb *pa, u8 apid)
>  {
>  	unsigned int irq;
>  	u32 status;
> @@ -490,7 +489,7 @@ static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
>  	status = readl_relaxed(pa->intr + pa->ver_ops->irq_status(apid));
>  	while (status) {
>  		id = ffs(status) - 1;
> -		status &= ~(1 << id);
> +		status &= ~BIT(id);
>  		irq = irq_find_mapping(pa->domain,
>  				       pa->apid_to_ppid[apid] << 16
>  				     | id << 8
> @@ -501,7 +500,7 @@ static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
>  
>  static void pmic_arb_chained_irq(struct irq_desc *desc)
>  {
> -	struct spmi_pmic_arb_dev *pa = irq_desc_get_handler_data(desc);
> +	struct spmi_pmic_arb *pa = irq_desc_get_handler_data(desc);
>  	struct irq_chip *chip = irq_desc_get_chip(desc);
>  	void __iomem *intr = pa->intr;
>  	int first = pa->min_apid >> 5;
> @@ -516,7 +515,7 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
>  				      pa->ver_ops->owner_acc_status(pa->ee, i));
>  		while (status) {
>  			id = ffs(status) - 1;
> -			status &= ~(1 << id);
> +			status &= ~BIT(id);
>  			periph_interrupt(pa, id + i * 32);
>  		}
>  	}
> @@ -526,23 +525,23 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
>  
>  static void qpnpint_irq_ack(struct irq_data *d)
>  {
> -	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
> +	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
>  	u8 irq  = d->hwirq >> 8;
>  	u8 apid = d->hwirq;
>  	unsigned long flags;
>  	u8 data;
>  
>  	raw_spin_lock_irqsave(&pa->lock, flags);
> -	writel_relaxed(1 << irq, pa->intr + pa->ver_ops->irq_clear(apid));
> +	writel_relaxed(BIT(irq), pa->intr + pa->ver_ops->irq_clear(apid));
>  	raw_spin_unlock_irqrestore(&pa->lock, flags);
>  
> -	data = 1 << irq;
> +	data = BIT(irq);
>  	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
>  }
>  
>  static void qpnpint_irq_mask(struct irq_data *d)
>  {
> -	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
> +	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
>  	u8 irq  = d->hwirq >> 8;
>  	u8 apid = d->hwirq;
>  	unsigned long flags;
> @@ -558,13 +557,13 @@ static void qpnpint_irq_mask(struct irq_data *d)
>  	}
>  	raw_spin_unlock_irqrestore(&pa->lock, flags);
>  
> -	data = 1 << irq;
> +	data = BIT(irq);
>  	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
>  }
>  
>  static void qpnpint_irq_unmask(struct irq_data *d)
>  {
> -	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
> +	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
>  	u8 irq  = d->hwirq >> 8;
>  	u8 apid = d->hwirq;
>  	unsigned long flags;
> @@ -579,7 +578,7 @@ static void qpnpint_irq_unmask(struct irq_data *d)
>  	}
>  	raw_spin_unlock_irqrestore(&pa->lock, flags);
>  
> -	data = 1 << irq;
> +	data = BIT(irq);
>  	qpnpint_spmi_write(d, QPNPINT_REG_EN_SET, &data, 1);
>  }
>  
> @@ -590,7 +589,7 @@ static void qpnpint_irq_enable(struct irq_data *d)
>  
>  	qpnpint_irq_unmask(d);
>  
> -	data = 1 << irq;
> +	data = BIT(irq);
>  	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
>  }
>  
> @@ -598,25 +597,26 @@ static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
>  {
>  	struct spmi_pmic_arb_qpnpint_type type;
>  	u8 irq = d->hwirq >> 8;
> +	u8 bit_mask_irq = BIT(irq);

Why the local variable? Just do the ~BIT(irq) thing in place and
let the compiler take care of the hoist?

>  
>  	qpnpint_spmi_read(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
>  
>  	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
> -		type.type |= 1 << irq;
> +		type.type |= bit_mask_irq;
>  		if (flow_type & IRQF_TRIGGER_RISING)
> -			type.polarity_high |= 1 << irq;
> +			type.polarity_high |= bit_mask_irq;
>  		if (flow_type & IRQF_TRIGGER_FALLING)
> -			type.polarity_low  |= 1 << irq;
> +			type.polarity_low  |= bit_mask_irq;
>  	} else {
>  		if ((flow_type & (IRQF_TRIGGER_HIGH)) &&
>  		    (flow_type & (IRQF_TRIGGER_LOW)))
>  			return -EINVAL;
>  
> -		type.type &= ~(1 << irq); /* level trig */
> +		type.type &= ~bit_mask_irq; /* level trig */
>  		if (flow_type & IRQF_TRIGGER_HIGH)
> -			type.polarity_high |= 1 << irq;
> +			type.polarity_high |= bit_mask_irq;
>  		else
> -			type.polarity_low  |= 1 << irq;
> +			type.polarity_low  |= bit_mask_irq;
>  	}
>  
>  	qpnpint_spmi_write(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
> @@ -657,7 +657,7 @@ struct spmi_pmic_arb_irq_spec {

Overall I see little to no value with this patch. I suggest you
drop the rename. The BIT() thing may be ok, but again, not sure
there's any benefit.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 03/15] spmi: pmic-arb: fix inconsistent use of apid and chan
  2017-05-30 12:38 ` [PATCH V1 03/15] spmi: pmic-arb: fix inconsistent use of apid and chan Kiran Gunda
@ 2017-05-31  1:31   ` Stephen Boyd
  2017-06-01 16:37     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31  1:31 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Greg Kroah-Hartman, David Collins, Christophe JAILLET,
	linux-kernel, linux-arm-msm, adharmap, aghayal

On 05/30, Kiran Gunda wrote:
> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> 
> The driver currently uses "apid" and "chan" to mean apid. Remove
> the use of chan and use only apid.

I'm not so sure. It currently uses "chan" to mean the offset to
add to the "PMIC Arbiter channel registers" so that we can access
the appropriate peripheral via the arbiter registers. I actually
can't remember what APID or PPID stand for, so perhaps describing
that as well would be helpful so we can navigate this acronym
soup.

> 
> On a SPMI bus there is allocation to manage up to 4K peripherals.
> However, in practice only few peripherals are instantiated
> and only few among the instantiated ones actually interrupt.
> 
> APID is CPU's way of keeping track of peripherals that could interrupt.
> There is a table that maps the 256 interrupting peripherals to
> a number between 0 and 255. This number is called APID. Information about
> that interrupting peripheral is stored in registers offset by its
> corresponding apid.

That's all fine, but perhaps we shouldn't worry about "apid"
being attached to interrupts? I mean, I can imagine some
peripheral that doesn't interrupt, but we want to read/write it
and that must be done with the "channel" or "apid" or really the
"magic offset from the base of the channel registers" to do so.
Probably APID is fine, as long as APID means "application
processor peripheral id" or something along those lines.

> 
> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
> ---
>  drivers/spmi/spmi-pmic-arb.c | 68 ++++++++++++++++++++++----------------------
>  1 file changed, 34 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
> index 7f918ea..7201611 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -117,7 +117,7 @@ enum pmic_arb_cmd_op_code {
>   * @spmic:		SPMI controller object
>   * @apid_to_ppid:	in-memory copy of APID -> PPID mapping table.
>   * @ver_ops:		version dependent operations.
> - * @ppid_to_chan	in-memory copy of PPID -> channel (APID) mapping table.
> + * @ppid_to_apid	in-memory copy of PPID -> channel (APID) mapping table.

PPID->APID? No channel?

>   *			v2 only.
>   */
>  struct spmi_pmic_arb {
> @@ -140,9 +140,9 @@ struct spmi_pmic_arb {
>  	struct spmi_controller	*spmic;
>  	u16			*apid_to_ppid;
>  	const struct pmic_arb_ver_ops *ver_ops;
> -	u16			*ppid_to_chan;
> -	u16			last_channel;
> -	u8			*chan_to_owner;
> +	u16			*ppid_to_apid;
> +	u16			last_apid;
> +	u8			*apid_to_owner;
>  };
>  
>  /**
> @@ -772,22 +772,22 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
>  	return 0;
>  }
>  
> -static u16 pmic_arb_find_chan(struct spmi_pmic_arb *pa, u16 ppid)
> +static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
>  {
>  	u32 regval, offset;
> -	u16 chan;
> +	u16 apid;
>  	u16 id;
>  
>  	/*
>  	 * PMIC_ARB_REG_CHNL is a table in HW mapping channel to ppid.

Is this comment still relevant?

> -	 * ppid_to_chan is an in-memory invert of that table.
> +	 * ppid_to_apid is an in-memory invert of that table.
>  	 */
> -	for (chan = pa->last_channel; chan < pa->max_periph; chan++) {
> +	for (apid = pa->last_apid; apid < pa->max_periph; apid++) {
>  		regval = readl_relaxed(pa->cnfg +
> -				      SPMI_OWNERSHIP_TABLE_REG(chan));
> -		pa->chan_to_owner[chan] = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
> +				      SPMI_OWNERSHIP_TABLE_REG(apid));
> +		pa->apid_to_owner[apid] = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
>  
> -		offset = PMIC_ARB_REG_CHNL(chan);
> +		offset = PMIC_ARB_REG_CHNL(apid);
>  		if (offset >= pa->core_size)
>  			break;
>  
> @@ -796,15 +796,15 @@ static u16 pmic_arb_find_chan(struct spmi_pmic_arb *pa, u16 ppid)
>  			continue;
>  
>  		id = (regval >> 8) & PMIC_ARB_PPID_MASK;
> -		pa->ppid_to_chan[id] = chan | PMIC_ARB_CHAN_VALID;
> +		pa->ppid_to_apid[id] = apid | PMIC_ARB_CHAN_VALID;

Why do we still call the flag PMIC_ARB_CHAN_VALID then? Shouldn't
it be PMIC_ARB_APID_VALID?

>  		if (id == ppid) {
> -			chan |= PMIC_ARB_CHAN_VALID;
> +			apid |= PMIC_ARB_CHAN_VALID;
>  			break;
>  		}
>  	}
> -	pa->last_channel = chan & ~PMIC_ARB_CHAN_VALID;
> +	pa->last_apid = apid & ~PMIC_ARB_CHAN_VALID;
>  
> -	return chan;
> +	return apid;
>  }
>  
>  

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 04/15] spmi: pmic-arb: optimize table lookups
  2017-05-30 12:38 ` [PATCH V1 04/15] spmi: pmic-arb: optimize table lookups Kiran Gunda
@ 2017-05-31  1:44   ` Stephen Boyd
  2017-06-01 16:53     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31  1:44 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Christophe JAILLET, David Collins, linux-kernel, linux-arm-msm,
	adharmap, aghayal

On 05/30, Kiran Gunda wrote:
> diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
> index 7201611..6320f1f 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -164,6 +164,8 @@ struct spmi_pmic_arb {
>   *			on v2 offset of SPMI_PIC_IRQ_CLEARn.
>   */
>  struct pmic_arb_ver_ops {
> +	int (*ppid_to_apid)(struct spmi_pmic_arb *pa, u8 sid, u16 addr,
> +			u8 *apid);

Nitpick: It's called "pa" but "dev" in the next line.

>  	int (*mode)(struct spmi_pmic_arb *dev, u8 sid, u16 addr,
>  			mode_t *mode);
>  	/* spmi commands (read_cmd, write_cmd, cmd) functionality */
> @@ -657,42 +659,6 @@ struct spmi_pmic_arb_irq_spec {
>  	unsigned irq:3;
>  };
>  
> -static int search_mapping_table(struct spmi_pmic_arb *pa,
> -				struct spmi_pmic_arb_irq_spec *spec,

Perhaps the spec should be removed at some point if this was the
only place it was passed to.

> -				u8 *apid)

This code looks mostly unchanged, so please leave it as it is and
move the pmic_arb_ppid_to_apid_v1() function here so we can see
what actually changed.

> -{
> -	u16 ppid = spec->slave << 8 | spec->per;
> -	u32 *mapping_table = pa->mapping_table;
> -	int index = 0, i;
> -	u32 data;
> -
> -	for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
> -		if (!test_and_set_bit(index, pa->mapping_table_valid))
> -			mapping_table[index] = readl_relaxed(pa->cnfg +
> -						SPMI_MAPPING_TABLE_REG(index));
> -
> -		data = mapping_table[index];
> -
> -		if (ppid & BIT(SPMI_MAPPING_BIT_INDEX(data))) {
> -			if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) {
> -				index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
> -			} else {
> -				*apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
> -				return 0;
> -			}
> -		} else {
> -			if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) {
> -				index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
> -			} else {
> -				*apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
> -				return 0;
> -			}
> -		}
> -	}
> -
> -	return -ENODEV;
> -}
> -
>  static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
>  					   struct device_node *controller,
>  					   const u32 *intspec,
> @@ -702,7 +668,7 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
>  {
>  	struct spmi_pmic_arb *pa = d->host_data;
>  	struct spmi_pmic_arb_irq_spec spec;
> -	int err;
> +	int rc;
>  	u8 apid;
>  
>  	dev_dbg(&pa->spmic->dev,
> @@ -720,11 +686,14 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
>  	spec.per   = intspec[1];
>  	spec.irq   = intspec[2];
>  
> -	err = search_mapping_table(pa, &spec, &apid);
> -	if (err)
> -		return err;
> -
> -	pa->apid_to_ppid[apid] = spec.slave << 8 | spec.per;
> +	rc = pa->ver_ops->ppid_to_apid(pa, intspec[0],
> +			(intspec[1] << 8), &apid);
> +	if (rc < 0) {
> +		dev_err(&pa->spmic->dev,
> +		"failed to xlate sid = 0x%x, periph = 0x%x, irq = %x rc = %d\n",
> +		intspec[0], intspec[1], intspec[2], rc);
> +		return rc;
> +	}
>  
>  	/* Keep track of {max,min}_apid for bounding search during interrupt */
>  	if (apid > pa->max_apid)
> @@ -758,6 +727,54 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
>  }
>  
>  static int
> +pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u8 *apid)
> +{
> +	u16 ppid = sid << 8 | ((addr >> 8) & 0xFF);

The function is called ppid_to_apid, but we pass in a sid and
addr. Just pass a ppid instead of both split out?

> +	u32 *mapping_table = pa->mapping_table;
> +	int index = 0, i;
> +	u16 apid_valid;
> +	u32 data;
> +
> +	apid_valid = pa->ppid_to_apid[ppid];
> +	if (apid_valid & PMIC_ARB_CHAN_VALID) {
> +		*apid = (apid_valid & ~PMIC_ARB_CHAN_VALID);
> +		return 0;
> +	}
> +

>From here to...

> +	for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
> +		if (!test_and_set_bit(index, pa->mapping_table_valid))
> +			mapping_table[index] = readl_relaxed(pa->cnfg +
> +						SPMI_MAPPING_TABLE_REG(index));
> +
> +		data = mapping_table[index];
> +
> +		if (ppid & BIT(SPMI_MAPPING_BIT_INDEX(data))) {
> +			if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) {
> +				index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
> +			} else {
> +				*apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
> +				pa->ppid_to_apid[ppid]
> +					= *apid | PMIC_ARB_CHAN_VALID;
> +				pa->apid_to_ppid[*apid] = ppid;
> +				return 0;
> +			}
> +		} else {
> +			if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) {
> +				index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
> +			} else {
> +				*apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
> +				pa->ppid_to_apid[ppid]
> +					= *apid | PMIC_ARB_CHAN_VALID;
> +				pa->apid_to_ppid[*apid] = ppid;
> +				return 0;
> +			}
> +		}
> +	}
> +
> +	return -ENODEV;
> +}

here is all unchanged? Oh except apid_to_ppid/ppid_to_apid is
inserted.

> +
> +static int
>  pmic_arb_mode_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
>  {
>  	*mode = S_IRUSR | S_IWUSR;
> @@ -797,6 +814,7 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
>  
>  		id = (regval >> 8) & PMIC_ARB_PPID_MASK;
>  		pa->ppid_to_apid[id] = apid | PMIC_ARB_CHAN_VALID;
> +		pa->apid_to_ppid[apid] = id;
>  		if (id == ppid) {
>  			apid |= PMIC_ARB_CHAN_VALID;
>  			break;
> @@ -809,20 +827,35 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
>  
>  
>  static int
> -pmic_arb_mode_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
> +pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, u8 *apid)
>  {
>  	u16 ppid = (sid << 8) | (addr >> 8);
> -	u16 apid;
> -	u8 owner;
> +	u16 apid_valid;
>  
> -	apid = pa->ppid_to_apid[ppid];
> -	if (!(apid & PMIC_ARB_CHAN_VALID))
> +	apid_valid = pa->ppid_to_apid[ppid];
> +	if (!(apid_valid & PMIC_ARB_CHAN_VALID))
> +		apid_valid = pmic_arb_find_apid(pa, ppid);
> +	if (!(apid_valid & PMIC_ARB_CHAN_VALID))
>  		return -ENODEV;
>  
> +	*apid = (apid_valid & ~PMIC_ARB_CHAN_VALID);

Useless parenthesis. Please remove.

Why can't we just return a number that's >= 0 for apid and < 0
for an error from this op? Pointer passing is odd style.

> +	return 0;
> +}
> +

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 05/15] spmi: pmic-arb: cleanup unrequested irqs
  2017-05-30 12:38 ` [PATCH V1 05/15] spmi: pmic-arb: cleanup unrequested irqs Kiran Gunda
@ 2017-05-31  1:57   ` Stephen Boyd
  2017-06-06 10:50     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31  1:57 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Christophe JAILLET, David Collins, linux-kernel, linux-arm-msm,
	adharmap, aghayal

On 05/30, Kiran Gunda wrote:
> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> 
> We see a unmapped irqs trigger right around bootup. This could
> likely be because the bootloader exited leaving the interrupts
> in an unknown or unhandled state.  Ack and mask the interrupt
> if one is found. A request_irq later will unmask it and also
> setup proper mapping structures.

Do we have systems where this is causing an interrupt storm due
to a level high interrupt or something? Just plain acking and
masking irqs at boot if we don't have an irq descriptor created
yet doesn't sound like a good idea, because we'll lose all
interrupts that happen before this driver probes?

> 
> Also the current driver ensures that no read/write transaction
> is in progress while it makes changes to the interrupt regions.
> This is not necessary because read/writes over spmi and arbiter
> interrupt control are independent operations. Hence, remove the
> synchronized accesses to interrupt region.

That's another patch for this paragraph.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 06/15] spmi: pmic-arb: fix missing interrupts
  2017-05-30 12:38 ` [PATCH V1 06/15] spmi: pmic-arb: fix missing interrupts Kiran Gunda
@ 2017-05-31  2:00   ` Stephen Boyd
  2017-06-01 17:06     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31  2:00 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Greg Kroah-Hartman, Christophe JAILLET,
	David Collins, Subbaraman Narayanamurthy, linux-kernel,
	linux-arm-msm, adharmap, aghayal

On 05/30, Kiran Gunda wrote:
> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> 
> irq_enable is called when the device resumes. Note that the
> irq_enable is called regardless of whether the interrupt was
> marked enabled/disabled in the descriptor or whether it was
> masked/unmasked at the controller while resuming.
> 
> The current driver unconditionally clears the interrupt in its
> irq_enable callback. This is dangerous as any interrupts that
> happen right before the resume could be missed.
> Remove the irq_enable callback and use mask/unmask instead.
> 
> Also remove struct pmic_arb_irq_spec as it serves no real purpose.
> It is used only in the translate function and the code is much
> cleaner without it.

Also a separate patch for that part....

> 
> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
> ---
>  drivers/spmi/spmi-pmic-arb.c | 29 +++--------------------------
>  1 file changed, 3 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
> index 0a5728c..bc03737 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -588,17 +588,6 @@ static void qpnpint_irq_unmask(struct irq_data *d)
>  	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
>  }
>  
> -static void qpnpint_irq_enable(struct irq_data *d)
> -{
> -	u8 irq  = d->hwirq >> 8;
> -	u8 data;
> -
> -	qpnpint_irq_unmask(d);
> -
> -	data = BIT(irq);
> -	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
> -}
> -
>  static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
>  {
>  	struct spmi_pmic_arb_qpnpint_type type;
> @@ -647,7 +636,6 @@ static int qpnpint_get_irqchip_state(struct irq_data *d,
>  
>  static struct irq_chip pmic_arb_irqchip = {
>  	.name		= "pmic_arb",
> -	.irq_enable	= qpnpint_irq_enable,
>  	.irq_ack	= qpnpint_irq_ack,
>  	.irq_mask	= qpnpint_irq_mask,
>  	.irq_unmask	= qpnpint_irq_unmask,

This looks ok.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 11/15] spmi: spmi-pmic-arb: enable the SPMI interrupt as a wakeup source
  2017-05-30 12:38 ` [PATCH V1 11/15] spmi: spmi-pmic-arb: enable the SPMI interrupt as a wakeup source Kiran Gunda
@ 2017-05-31 17:13   ` Stephen Boyd
  2017-06-08 11:30     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31 17:13 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET, David Collins,
	Subbaraman Narayanamurthy, linux-kernel, linux-arm-msm, adharmap,
	aghayal, Nicholas Troast

On 05/30, Kiran Gunda wrote:
> Currently the SPMI interrupt will not wake the device. Enable this
> interrupt as a wakeup source.
> 
> Signed-off-by: Nicholas Troast <ntroast@codeaurora.org>
> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
> ---
>  drivers/spmi/spmi-pmic-arb.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
> index 0deac33..2afe359 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -1140,6 +1140,7 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
>  	}
>  
>  	irq_set_chained_handler_and_data(pa->irq, pmic_arb_chained_irq, pa);
> +	enable_irq_wake(pa->irq);

Why don't we do this through an irq_set_wake callback in the
irqchip? That way, we don't mark this irq as wakeup if any child
irqs aren't marked as wakeup.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 12/15] spmi-pmic-arb: fix a possible null pointer dereference
  2017-05-30 12:39 ` [PATCH V1 12/15] spmi-pmic-arb: fix a possible null pointer dereference Kiran Gunda
@ 2017-05-31 17:29   ` Stephen Boyd
  2017-06-02  7:13     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31 17:29 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Greg Kroah-Hartman,
	Subbaraman Narayanamurthy, Christophe JAILLET, David Collins,
	linux-kernel, linux-arm-msm, adharmap, aghayal

On 05/30, Kiran Gunda wrote:
> diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
> index 2afe359..412481d 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -1003,6 +1003,12 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
>  	pa->spmic = ctrl;
>  
>  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
> +	if (!res) {
> +		dev_err(&pdev->dev, "core resource not specified\n");
> +		err = -EINVAL;
> +		goto err_put_ctrl;
> +	}
> +
>  	pa->core_size = resource_size(res);
>  	if (pa->core_size <= 0x800) {
>  		dev_err(&pdev->dev, "core_size is smaller than 0x800. Failing Probe\n");

I would prefer this patch instead, so that we can piggyback on
the error checking of the devm_ioremap_resource() code. Also, add
a Fixes: tag please so we can backport it as needed.


diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 5ec3a595dc7d..0cedbda60707 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -878,12 +878,12 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 	pa->spmic = ctrl;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
-	pa->core_size = resource_size(res);
 	core = devm_ioremap_resource(&ctrl->dev, res);
 	if (IS_ERR(core)) {
 		err = PTR_ERR(core);
 		goto err_put_ctrl;
 	}
+	pa->core_size = resource_size(res);
 
 	hw_ver = readl_relaxed(core + PMIC_ARB_VERSION);
 	is_v1  = (hw_ver < PMIC_ARB_VERSION_V2_MIN);

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 14/15] spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq
  2017-05-30 12:39 ` [PATCH V1 14/15] spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq Kiran Gunda
  2017-05-30 22:23     ` kbuild test robot
@ 2017-05-31 17:53   ` Stephen Boyd
  2017-06-02  7:26     ` kgunda
  1 sibling, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31 17:53 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, David Collins, Christophe JAILLET,
	Subbaraman Narayanamurthy, linux-kernel, linux-arm-msm, adharmap,
	aghayal

On 05/30, Kiran Gunda wrote:
> From: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
> 
> Currently, cleanup_irq() is invoked when a peripheral's interrupt
> fires and there is no mapping present in the interrupt domain of
> spmi interrupt controller.
> 
> The cleanup_irq clears the arbiter bit, clears the pmic interrupt
> and disables it at the pmic in that order. The last disable in
> cleanup_irq races with request_irq() in that it stomps over the
> enable issued by request_irq. Fix this by not writing to the pmic
> in cleanup_irq. The latched bit will be left set in the pmic,
> which will not send us more interrupts even if the enable bit
> stays enabled.
> 
> When a client wants to request an interrupt, use the activate
> callback on the irq_domain to clear latched bit. This ensures
> that the latched, if set due to the above changes in cleanup_irq
> or when the bootloader leaves it set, gets cleaned up, paving way
> for upcoming interrupts to trigger.
> 
> With this, there is a possibility of unwanted triggering of
> interrupt right after the latched bit is cleared - the interrupt
> may be left enabled too. To avoid that, clear the enable first
> followed by clearing the latched bit in the activate callback.
> 
> Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>

Please squash this with the patch that adds cleanup_irq() and
rewrite the commit text to combine details from both.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 08/15] spmi: pmic_arb: use appropriate flow handler
  2017-05-30 12:38 ` [PATCH V1 08/15] spmi: pmic_arb: use appropriate flow handler Kiran Gunda
@ 2017-05-31 19:03   ` Stephen Boyd
  2017-06-06 10:57     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31 19:03 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET, David Collins,
	Subbaraman Narayanamurthy, linux-kernel, linux-arm-msm, adharmap,
	aghayal

On 05/30, Kiran Gunda wrote:
> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> 
> The current code uses handle_level_irq flow handler even if the
> trigger type of the interrupt is edge. This can lead to missing
> of an edge transition that happens when the interrupt is being
> handled. The level flow handler masks the interrupt while it is
> being handled, so if an edge transition happens at that time,
> that edge is lost.
> 
> Use an edge flow handler for edge type interrupts which ensures
> that the interrupt stays enabled while being handled - at least
> until it triggers at which point the flow handler sets the
> IRQF_PENDING flag and only then masks the interrupt. That
> IRQF_PENDING state indicates an edge transition happened while
> the interrupt was being handled and the handler is called again.
> 
> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>

Do we have any edge interrupts in the tree right now? At least
RTC seems to be using edge... This should go back to stable with
a Fixes tag.

> ---
>  drivers/spmi/spmi-pmic-arb.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
> index 1d23df0..ad34491 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -625,6 +625,12 @@ static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
>  	}
>  
>  	qpnpint_spmi_write(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
> +
> +	if (flow_type & IRQ_TYPE_EDGE_BOTH)

IRQ_TYPE_EDGE_BOTH doesn't seem appropriate to use here. We're
really just testing to see if the type is an edge type, not if
it's BOTH edges.

> +		irq_set_handler_locked(d, handle_edge_irq);
> +	else
> +		irq_set_handler_locked(d, handle_level_irq);
> +

And we already have code that does that check:

	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))

so just put the irq_set_handler_locked() calls in those if
statements please.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 09/15] spmi: pmic-arb: check apid enabled before calling the handler
  2017-05-30 12:38 ` [PATCH V1 09/15] spmi: pmic-arb: check apid enabled before calling the handler Kiran Gunda
@ 2017-05-31 20:39   ` Stephen Boyd
  2017-06-14 15:38     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31 20:39 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, David Collins, Subbaraman Narayanamurthy,
	Christophe JAILLET, linux-kernel, linux-arm-msm, adharmap,
	aghayal

On 05/30, Kiran Gunda wrote:
> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> 
> The driver currently invokes the apid handler (periph_handler())

You mean periph_interrupt()?

> once it sees that the summary status bit for that apid is set.
> 
> However the hardware is designed to set that bit even if the apid
> interrupts are disabled. The driver should check whether the apid
> is indeed enabled before calling the apid handler.

Really? Wow that is awful. Or is this because ACC_ENABLE bit is
always set now and never cleared?

> 
> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
> ---
>  drivers/spmi/spmi-pmic-arb.c | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
> index ad34491..f8638fa 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -536,8 +536,8 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
>  	void __iomem *intr = pa->intr;
>  	int first = pa->min_apid >> 5;
>  	int last = pa->max_apid >> 5;
> -	u32 status;
> -	int i, id;
> +	u32 status, enable;
> +	int i, id, apid;
>  
>  	chained_irq_enter(chip, desc);
>  
> @@ -547,7 +547,11 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
>  		while (status) {
>  			id = ffs(status) - 1;
>  			status &= ~BIT(id);
> -			periph_interrupt(pa, id + i * 32);
> +			apid = id + i * 32;
> +			enable = readl_relaxed(intr +
> +					pa->ver_ops->acc_enable(apid));

Do we need to read the hardware to figure this out? After earlier
patches in this series we would never clear the
SPMI_PIC_ACC_ENABLE_BIT after one of the irqs in a peripheral is
unmasked for the first time (which looks to be fixing a bug in
the existing driver BTW). So in practice, this should almost
always be true.

In the one case that it isn't true, we'll be handling some other
irq for another peripheral and then hardware will tell us there's
an interrupt for a peripheral that doesn't have any interrupts
unmasked. We would call periph_interrupt() and then that
shouldn't see any interrupts in the status register for that
APID. So we do some more work, but nothing happens still. Did I
miss something? What is this fixing?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 07/15] spmi: pmic-arb: clear the latched status of the interrupt
  2017-05-30 12:38 ` [PATCH V1 07/15] spmi: pmic-arb: clear the latched status of the interrupt Kiran Gunda
@ 2017-05-31 22:03   ` Stephen Boyd
  2017-06-06 10:55     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31 22:03 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET,
	Subbaraman Narayanamurthy, David Collins, linux-kernel,
	linux-arm-msm, adharmap, aghayal

On 05/30, Kiran Gunda wrote:
> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> 
> PMIC interrupts each have an internal latched status bit which is
> not visible from any register.  This status bit is set as soon as
> the conditions specified in the interrupt type and polarity
> registers are met even if the interrupt is not enabled.  When it
> is set, nothing else changes within the PMIC and no interrupt
> notification packets are sent.  If the internal latched status
> bit is set when an interrupt is enabled, then the value is
> immediately propagated into the interrupt latched status register
> and an interrupt notification packet is sent out from the PMIC
> over SPMI.
> 
> This PMIC hardware behavior can lead to a situation where the
> handler for a level triggered interrupt is called immediately
> after enable_irq() is called even though the interrupt physically
> triggered while it was disabled within the genirq framework.
> This situation takes place if the the interrupt fires twice after

Double 'the'

> calling disable_irq().  The first time it fires, the level flow
> handler will mask and disregard it.  Unfortunately, the second
> time it fires, the internal latched status bit is set within the
> PMIC and no further notification is received.

because the interrupt has been disabled.

> When enable_irq()
> is called later, the interrupt is unmasked (enabled in the PMIC)
> which results in the PMIC immediately sending an interrupt
> notification packet out over SPMI.  This breaks the semantics
> of level triggered interrupts within the genirq framework since
> they should be completely ignored while disabled.

Ok. I wonder why the hardware latches interrupts at all.

> 
> The PMIC internal latched status behavior also affects how
> interrupts are treated during suspend.  While entering suspend,
> all interrupts not specified as wakeup mode are masked.  Upon
> resume, these interrupts are unmasked.  Thus if any of the
> non-wakeup PMIC interrupts fired while the system was suspended,
> then the PMIC will send interrupt notification packets out via
> SPMI as soon as they are unmasked during resume.  This behavior
> violates genirq semantics as well since non-wakeup interrupts
> should be completely ignored during suspend.
> 
> Modify the qpnpint_irq_unmask() function so that the interrupt
> latched status clear register is written immediately before the
> interrupt enable register.  This clears the internal latched
> status bit of the interrupt so that it cannot trigger spuriously
> immediately upon being enabled.
> 
> Also, while resuming an irq, an unmask could be called even if it
> was not previously masked.  So, before writing these registers,
> check if the interrupt is already enabled within the PMIC. If it
> is, then no further register writes are required.  This
> condition check ensures that a valid latched status register bit
> is not cleared until it is properly handled.
> 
> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 15/15] spmi: pmic-arb: instantiate spmi_devices at arch_initcall
  2017-05-30 12:39 ` [PATCH V1 15/15] spmi: pmic-arb: instantiate spmi_devices at arch_initcall Kiran Gunda
@ 2017-05-31 22:07   ` Stephen Boyd
  2017-07-18 11:49     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31 22:07 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET, Greg Kroah-Hartman,
	Subbaraman Narayanamurthy, David Collins, linux-kernel,
	linux-arm-msm, adharmap, aghayal

On 05/30, Kiran Gunda wrote:
> @@ -1384,7 +1384,12 @@ static int spmi_pmic_arb_remove(struct platform_device *pdev)
>  		.of_match_table = spmi_pmic_arb_match_table,
>  	},
>  };
> -module_platform_driver(spmi_pmic_arb_driver);
> +
> +int __init spmi_pmic_arb_init(void)

Missing static.

> +{
> +	return platform_driver_register(&spmi_pmic_arb_driver);
> +}
> +arch_initcall(spmi_pmic_arb_init);

We also lost module removal. Probably nobody tests it, but still
no mention of that in commit text.

I'm not sure we need this at all though. Is there something that
needs to probe early? Indicating what that is in the commit text
would be helpful.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 10/15] spmi: pmic_arb: add support for PMIC bus arbiter v3
  2017-05-30 12:38 ` [PATCH V1 10/15] spmi: pmic_arb: add support for PMIC bus arbiter v3 Kiran Gunda
@ 2017-05-31 22:18   ` Stephen Boyd
  2017-06-06 11:10     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-05-31 22:18 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, David Collins, Christophe JAILLET,
	Subbaraman Narayanamurthy, linux-kernel, linux-arm-msm, adharmap,
	aghayal

On 05/30, Kiran Gunda wrote:
>  
>  /* PMIC Arbiter channel registers offsets */
> @@ -96,6 +97,17 @@ enum pmic_arb_cmd_op_code {
>  /* interrupt enable bit */
>  #define SPMI_PIC_ACC_ENABLE_BIT		BIT(0)
>  
> +#define HWIRQ(slave_id, periph_id, irq_id, apid) \
> +	((((slave_id) & 0xF)   << 28) | \
> +	(((periph_id) & 0xFF)  << 20) | \
> +	(((irq_id)    & 0x7)   << 16) | \
> +	(((apid)      & 0x1FF) << 0))
> +
> +#define HWIRQ_SID(hwirq)  (((hwirq) >> 28) & 0xF)
> +#define HWIRQ_PER(hwirq)  (((hwirq) >> 20) & 0xFF)
> +#define HWIRQ_IRQ(hwirq)  (((hwirq) >> 16) & 0x7)
> +#define HWIRQ_APID(hwirq) (((hwirq) >> 0)  & 0x1FF)

How about lowercase and hwirq_to_*() macros? Then it's more
function like style. And spec_to_hwirq() or something?

> +
>  struct pmic_arb_ver_ops;
>  
>  struct apid_data {
> @@ -151,7 +163,9 @@ struct spmi_pmic_arb {
>  /**
>   * pmic_arb_ver: version dependent functionality.
>   *
> - * @mode:	access rights to specified pmic peripheral.
> + * @ver_str:		version string.
> + * @ppid_to_apid:	finds the apid for a given ppid.
> + * @mode:		access rights to specified pmic peripheral.

mode didn't need to change tabbing. Not sure why it's appearing
in the diff.

>   * @non_data_cmd:	on v1 issues an spmi non-data command.
>   *			on v2 no HW support, returns -EOPNOTSUPP.
>   * @offset:		on v1 offset of per-ee channel.
> @@ -177,10 +192,10 @@ struct pmic_arb_ver_ops {
>  	u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc);
>  	int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid);
>  	/* Interrupts controller functionality (offset of PIC registers) */
> -	u32 (*owner_acc_status)(u8 m, u8 n);
> -	u32 (*acc_enable)(u8 n);
> -	u32 (*irq_status)(u8 n);
> -	u32 (*irq_clear)(u8 n);
> +	u32 (*owner_acc_status)(u8 m, u16 n);
> +	u32 (*acc_enable)(u16 n);
> +	u32 (*irq_status)(u16 n);
> +	u32 (*irq_clear)(u16 n);
>  };
>  
>  static inline void pmic_arb_base_write(struct spmi_pmic_arb *pa,
> @@ -776,7 +787,7 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
>  }
>  
>  static int
> -pmic_arb_mode_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)
> +pmic_arb_mode_v1_v3(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t *mode)

Nice to know that the mode became useless in v3 and beyond! Sigh.

>  {
>  	*mode = S_IRUSR | S_IWUSR;
>  	return 0;
> @@ -987,21 +1017,21 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
>  
>  		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL(0) */
> -		pa->max_periph =  (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;
> +		pa->max_periph = (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;

This looks unrelated?

>  
>  		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>  						   "obsrvr");

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 13/15] spmi: pmic-arb: add support for HW version 5
  2017-05-30 12:39 ` [PATCH V1 13/15] spmi: pmic-arb: add support for HW version 5 Kiran Gunda
@ 2017-06-01  6:08   ` Stephen Boyd
  2017-06-08 11:28     ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-06-01  6:08 UTC (permalink / raw)
  To: Kiran Gunda
  Cc: Abhijeet Dharmapurikar, Greg Kroah-Hartman,
	Subbaraman Narayanamurthy, David Collins, Christophe JAILLET,
	linux-kernel, linux-arm-msm, adharmap, aghayal

On 05/30, Kiran Gunda wrote:
> diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
> index 412481d..b755c24 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -112,7 +123,8 @@ enum pmic_arb_cmd_op_code {
>  
>  struct apid_data {
>  	u16		ppid;
> -	u8		owner;
> +	u8		write_owner;
> +	u8		irq_owner;

How about irq_ee and write_ee instead?

>  };
>  
>  /**
>  static inline void pmic_arb_base_write(struct spmi_pmic_arb *pa,
> @@ -705,11 +724,18 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
>  			(intspec[1] << 8), &apid);
>  	if (rc < 0) {
>  		dev_err(&pa->spmic->dev,
> -		"failed to xlate sid = 0x%x, periph = 0x%x, irq = %x rc = %d\n",
> +		"failed to xlate sid = 0x%x, periph = 0x%x, irq = %u rc = %d\n",

What is this change? Also, use %#x instead of 0x%x and the "
should line up with the ( on the previous line.

>  		intspec[0], intspec[1], intspec[2], rc);
>  		return rc;
>  	}
>  
> +	if (pa->apid_data[apid].irq_owner != pa->ee) {
> +		dev_err(&pa->spmic->dev, "failed to xlate sid = 0x%x, periph = 0x%x, irq = %u: ee=%u but owner=%u\n",
> +			intspec[0], intspec[1], intspec[2], pa->ee,
> +			pa->apid_data[apid].irq_owner);
> +		return -ENODEV;
> +	}
> +
>  	/* Keep track of {max,min}_apid for bounding search during interrupt */
>  	if (apid > pa->max_apid)
>  		pa->max_apid = apid;
> @@ -814,9 +841,11 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
>  	for (apid = pa->last_apid; apid < pa->max_periph; apid++) {
>  		regval = readl_relaxed(pa->cnfg +
>  				      SPMI_OWNERSHIP_TABLE_REG(apid));
> -		pa->apid_data[apid].owner = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
> +		pa->apid_data[apid].irq_owner
> +			= SPMI_OWNERSHIP_PERIPH2OWNER(regval);
> +		pa->apid_data[apid].write_owner = pa->apid_data[apid].irq_owner;

Please use a local variable pointer *apid.

>  
> -		offset = PMIC_ARB_REG_CHNL(apid);
> +		offset = pa->ver_ops->channel_map_offset(apid);
>  		if (offset >= pa->core_size)
>  			break;
>  
> @@ -854,27 +883,110 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
>  	return 0;
>  }
>  
> +static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pa)
> +{
> +	u32 regval, offset;
> +	u16 apid, prev_apid, ppid;
> +	bool valid, is_irq_owner;
> +
> +	/*
> +	 * PMIC_ARB_REG_CHNL is a table in HW mapping APID (channel) to PPID.
> +	 * ppid_to_apid is an in-memory invert of that table.  In order to allow
> +	 * multiple EE's to write to a single PPID in arbiter version 5, there

Drop the apostrophe   ^

> +	 * is more than one APID mapped to each PPID.  The owner field for each
> +	 * of these mappings specifies the EE which is allowed to write to the
> +	 * APID.  The owner of the last (highest) APID for a given PPID will
> +	 * receive interrupts from the PPID.
> +	 */
> +	for (apid = 0; apid < pa->max_periph; apid++) {
> +		offset = pa->ver_ops->channel_map_offset(apid);
> +		if (offset >= pa->core_size)
> +			break;
> +
> +		regval = readl_relaxed(pa->core + offset);
> +		if (!regval)
> +			continue;
> +		ppid = (regval >> 8) & PMIC_ARB_PPID_MASK;
> +		is_irq_owner = PMIC_ARB_CHAN_IS_IRQ_OWNER(regval);
> +
> +		regval = readl_relaxed(pa->cnfg +
> +				      SPMI_OWNERSHIP_TABLE_REG(apid));
> +		pa->apid_data[apid].write_owner
> +			= SPMI_OWNERSHIP_PERIPH2OWNER(regval);

Please use a pointer like *apid and *prev where *apid is
incremented during the for-loop. That way we have shorter lines
of code:

		apid->write_owner = SPMI_OWNERSHIP_TABLE_REG(regval);

and

		if (valid && is_irq_owner && prev->write_owner == pa->ee) {

obviously the existing apid will need to be renamed to i, but
that's ok because it's a counter.

> +
> +		pa->apid_data[apid].irq_owner = is_irq_owner ?
> +			pa->apid_data[apid].write_owner : INVALID_EE;
> +
> +		valid = pa->ppid_to_apid[ppid] & PMIC_ARB_CHAN_VALID;
> +		prev_apid = pa->ppid_to_apid[ppid] & ~PMIC_ARB_CHAN_VALID;
> +
> +		if (valid && is_irq_owner &&
> +		    pa->apid_data[prev_apid].write_owner == pa->ee) {
> +			/*
> +			 * Duplicate PPID mapping after the one for this EE;
> +			 * override the irq owner
> +			 */
> +			pa->apid_data[prev_apid].irq_owner
> +				= pa->apid_data[apid].irq_owner;
> +		} else if (!valid || is_irq_owner) {
> +			/* First PPID mapping or duplicate for another EE */
> +			pa->ppid_to_apid[ppid] = apid | PMIC_ARB_CHAN_VALID;
> +		}
> +
> +		pa->apid_data[apid].ppid = ppid;
> +		pa->last_apid = apid;
> +	}
> +
> +	/* Dump the mapping table for debug purposes. */
> +	dev_dbg(&pa->spmic->dev, "PPID APID Write-EE IRQ-EE\n");
> +	for (ppid = 0; ppid < PMIC_ARB_MAX_PPID; ppid++) {
> +		valid = pa->ppid_to_apid[ppid] & PMIC_ARB_CHAN_VALID;
> +		apid = pa->ppid_to_apid[ppid] & ~PMIC_ARB_CHAN_VALID;
> +
> +		if (valid)
> +			dev_dbg(&pa->spmic->dev, "0x%03X %3u %2u %2u\n",

Same %#x story here.

> +				ppid, apid, pa->apid_data[apid].write_owner,
> +				pa->apid_data[apid].irq_owner);
> +	}
> +
> +	return 0;
> +}
> +
>  
> @@ -887,6 +999,27 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
>  	return 0;
>  }
>  
> +/*
> + * v5 offset per ee and per apid for observer channels and per apid for
> + * read/write channels.
> + */
> +static int
> +pmic_arb_offset_v5(struct spmi_pmic_arb *pa, u8 sid, u16 addr,
> +		   enum pmic_arb_channel ch_type, u32 *offset)
> +{
> +	u16 apid;
> +	int rc;
> +
> +	rc = pmic_arb_ppid_to_apid_v5(pa, sid, addr, &apid);
> +	if (rc < 0)
> +		return rc;
> +
> +	*offset = (ch_type == PMIC_ARB_CHANNEL_OBS)
> +			? 0x10000 * pa->ee + 0x80 * apid
> +			: 0x10000 * apid;

Please use a switch statement to handle the enum here. That way
we can get compiler checking to make sure all enumerations are
handled.

> +	return 0;
> +}
> +
>  static u32 pmic_arb_fmt_cmd_v1(u8 opc, u8 sid, u16 addr, u8 bc)
>  {
>  	return (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
> @@ -1033,11 +1213,14 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
>  
>  		if (hw_ver < PMIC_ARB_VERSION_V3_MIN)
>  			pa->ver_ops = &pmic_arb_v2;
> -		else
> +		else if (hw_ver < PMIC_ARB_VERSION_V5_MIN)
>  			pa->ver_ops = &pmic_arb_v3;
> +		else
> +			pa->ver_ops = &pmic_arb_v5;
>  
> -		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL(0) */
> -		pa->max_periph = (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;
> +		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL0 */
> +		pa->max_periph
> +		     = (pa->core_size - pa->ver_ops->channel_map_offset(0)) / 4;

This is really ugly. Please grow a local variable so we can keep
things on one line.

>  
>  		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>  						   "obsrvr");
> @@ -1074,6 +1257,14 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
>  		err = PTR_ERR(pa->intr);
>  		goto err_put_ctrl;
>  	}
> +	pa->acc_status = pa->intr;
> +
> +	/*
> +	 * PMIC arbiter v5 groups the IRQ control registers in the same hardware
> +	 * module as the read/write channels.
> +	 */
> +	if (hw_ver >= PMIC_ARB_VERSION_V5_MIN)
> +		pa->intr = pa->wr_base;

There's some weird things going on here. How about we make the
version ops return an __iomem pointer to the address instead of
an offset? That way we don't need to care what pa->intr is or add
pa->acc_status? That could be a patch early in the series that
adjusts the ops to return an iomem pointer, and perhaps also
update the 'n' variable to be 16 instead of 8 bits. We can also
express errors through iomem pointers with IS_ERR() checks, so it
nicely removes the need to retrieve offsets through references
sometimes too.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 02/15] spmi: pmic-arb: rename spmi_pmic_arb_dev to spmi_pmic_arb
  2017-05-31  0:46   ` Stephen Boyd
@ 2017-06-01 16:11     ` kgunda
  2017-06-02 18:29       ` Stephen Boyd
  0 siblings, 1 reply; 62+ messages in thread
From: kgunda @ 2017-06-01 16:11 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Greg Kroah-Hartman, David Collins,
	Subbaraman Narayanamurthy, Christophe JAILLET, linux-kernel,
	linux-arm-msm, adharmap, aghayal, linux-arm-msm-owner

Thanks Stephen for reviewing the patches. Responses inline.

Thanks,
Kiran

On 2017-05-31 06:16, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> 
>> Usually *_dev best used for structures that embed a struct device in
>> them. spmi_pmic_arb_dev doesn't embed one. It is simply a driver data
>> structure. Use an appropriate name for it.
>> 
>> Also there are many places in the driver that left shift the bit to
>> generate a bit mask. Replace it with the BIT() macro.
> 
> That would be a different patch because the subject doesn't even
> mention this.
> 
Sure. Agree. Will split this in to different patch.
>> 
>> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
>> ---
>>  drivers/spmi/spmi-pmic-arb.c | 164 
>> +++++++++++++++++++++----------------------
> 
> Would also be nice if you ran scripts/objdiff on this so we can
> be confident the code didn't change.
> 
Sure. Will do that in the next patch.

>>  1 file changed, 82 insertions(+), 82 deletions(-)
>> 
>> diff --git a/drivers/spmi/spmi-pmic-arb.c 
>> b/drivers/spmi/spmi-pmic-arb.c
>> index df463d4..7f918ea 100644
>> --- a/drivers/spmi/spmi-pmic-arb.c
>> +++ b/drivers/spmi/spmi-pmic-arb.c
>> @@ -58,10 +58,10 @@
>> 
>>  /* Channel Status fields */
>>  enum pmic_arb_chnl_status {
>> -	PMIC_ARB_STATUS_DONE	= (1 << 0),
>> -	PMIC_ARB_STATUS_FAILURE	= (1 << 1),
>> -	PMIC_ARB_STATUS_DENIED	= (1 << 2),
>> -	PMIC_ARB_STATUS_DROPPED	= (1 << 3),
>> +	PMIC_ARB_STATUS_DONE	= BIT(0),
>> +	PMIC_ARB_STATUS_FAILURE	= BIT(1),
>> +	PMIC_ARB_STATUS_DENIED	= BIT(2),
>> +	PMIC_ARB_STATUS_DROPPED	= BIT(3),
>>  };
>> 
>>  /* Command register fields */
>> @@ -99,7 +99,7 @@ enum pmic_arb_cmd_op_code {
>>  struct pmic_arb_ver_ops;
>> 
>>  /**
>> - * spmi_pmic_arb_dev - SPMI PMIC Arbiter object
>> + * spmi_pmic_arb - SPMI PMIC Arbiter object
>>   *
>>   * @rd_base:		on v1 "core", on v2 "observer" register base off DT.
>>   * @wr_base:		on v1 "core", on v2 "chnls"    register base off DT.
>> @@ -120,7 +120,7 @@ enum pmic_arb_cmd_op_code {
>>   * @ppid_to_chan	in-memory copy of PPID -> channel (APID) mapping 
>> table.
>>   *			v2 only.
>>   */
>> -struct spmi_pmic_arb_dev {
>> +struct spmi_pmic_arb {
>>  	void __iomem		*rd_base;
>>  	void __iomem		*wr_base;
>>  	void __iomem		*intr;
>> @@ -164,10 +164,10 @@ struct spmi_pmic_arb_dev {
>>   *			on v2 offset of SPMI_PIC_IRQ_CLEARn.
>>   */
>>  struct pmic_arb_ver_ops {
>> -	int (*mode)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
>> +	int (*mode)(struct spmi_pmic_arb *dev, u8 sid, u16 addr,
> 
> But we leave dev here? I'm losing faith that this patch is
> worthwhile.
Ok. As per your suggestion we will drop this renaming patch.

> 
>>  			mode_t *mode);
>>  	/* spmi commands (read_cmd, write_cmd, cmd) functionality */
>> -	int (*offset)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
>> +	int (*offset)(struct spmi_pmic_arb *dev, u8 sid, u16 addr,
>>  		      u32 *offset);
>>  	u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc);
>>  	int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid);
>> @@ -178,16 +178,16 @@ struct pmic_arb_ver_ops {
>>  	u32 (*irq_clear)(u8 n);
>>  };
>> 
>> -static inline void pmic_arb_base_write(struct spmi_pmic_arb_dev *dev,
>> +static inline void pmic_arb_base_write(struct spmi_pmic_arb *pa,
>>  				       u32 offset, u32 val)
>>  {
>> -	writel_relaxed(val, dev->wr_base + offset);
>> +	writel_relaxed(val, pa->wr_base + offset);
> 
> "pa" is a little confusing with things like physical address and
> such. I would have gone for "arb", but the code is written
> already, so why change it now?
> 
Ok. As per your suggestion we will drop this renaming patch.
>>  }
>> 
>> -static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb_dev *dev,
>> +static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb *pa,
>>  				       u32 offset, u32 val)
>>  {
>> -	writel_relaxed(val, dev->rd_base + offset);
>> +	writel_relaxed(val, pa->rd_base + offset);
>>  }
>> 
>>  /**
>> @@ -196,9 +196,10 @@ static inline void pmic_arb_set_rd_cmd(struct 
>> spmi_pmic_arb_dev *dev,
>>   * @reg:	register's address
>>   * @buf:	output parameter, length must be bc + 1
>>   */
>> -static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 
>> reg, u8 bc)
>> +static void pa_read_data(struct spmi_pmic_arb *pa, u8 *buf, u32 reg, 
>> u8 bc)
> 
> In fact, I would rename these pa_{read,write}_data() functions as
> pmic_arb_{read,write}_data() to be consistent. These are the only
> places "pa_" is used right now.
> 
Sure. Agree. Will rename this to pmic_arb_{read,write}_data in the next 
patch.
>>  {
>> -	u32 data = __raw_readl(dev->rd_base + reg);
>> +	u32 data = __raw_readl(pa->rd_base + reg);
>> +
>>  	memcpy(buf, &data, (bc & 3) + 1);
>>  }
>> 
>> @@ -209,23 +210,24 @@ static void pa_read_data(struct 
>> spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
>>   * @buf:	buffer to write. length must be bc + 1.
>>   */
>>  static void
>> -pa_write_data(struct spmi_pmic_arb_dev *dev, const u8 *buf, u32 reg, 
>> u8 bc)
>> +pa_write_data(struct spmi_pmic_arb *pa, const u8 *buf, u32 reg, u8 
>> bc)
>>  {
>>  	u32 data = 0;
>> +
>>  	memcpy(&data, buf, (bc & 3) + 1);
>> -	__raw_writel(data, dev->wr_base + reg);
>> +	pmic_arb_base_write(pa, reg, data);
> 
> This is an unrelated change. Not sure what's going on with this
> diff but we most likely want to keep the __raw_writel() here. See
> how renames introduce bugs and why we don't value them?
> 
Actually pmic_arb_base_write has the writel_relaxed inside it.
that's why we removed the __raw_writel to use the common function.
Anyways, we drop the renaming patch from this patch series.
>>  }
>> 
>> @@ -270,22 +272,22 @@ static int pmic_arb_wait_for_done(struct 
>> spmi_controller *ctrl,
>>  static int
>>  pmic_arb_non_data_cmd_v1(struct spmi_controller *ctrl, u8 opc, u8 
>> sid)
>>  {
>> -	struct spmi_pmic_arb_dev *pmic_arb = 
>> spmi_controller_get_drvdata(ctrl);
>> +	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
>>  	unsigned long flags;
>>  	u32 cmd;
>>  	int rc;
>>  	u32 offset;
>> 
>> -	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, 0, &offset);
>> +	rc = pa->ver_ops->offset(pa, sid, 0, &offset);
>>  	if (rc)
>>  		return rc;
>> 
>>  	cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20);
>> 
>> -	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
>> -	pmic_arb_base_write(pmic_arb, offset + PMIC_ARB_CMD, cmd);
>> -	rc = pmic_arb_wait_for_done(ctrl, pmic_arb->wr_base, sid, 0);
>> -	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
>> +	raw_spin_lock_irqsave(&pa->lock, flags);
>> +	pmic_arb_base_write(pa, offset + PMIC_ARB_CMD, cmd);
>> +	rc = pmic_arb_wait_for_done(ctrl, pa->wr_base, sid, 0);
>> +	raw_spin_unlock_irqrestore(&pa->lock, flags);
>> 
>>  	return rc;
> 
> Yeah pmic_arb sounds fine too. Not sure why we changed anything
> in this function.
> 
Ok. We will drop this renaming patch.
>>  }
>> @@ -299,7 +301,7 @@ static int pmic_arb_wait_for_done(struct 
>> spmi_controller *ctrl,
>>  /* Non-data command */
>>  static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
>>  {
>> -	struct spmi_pmic_arb_dev *pmic_arb = 
>> spmi_controller_get_drvdata(ctrl);
>> +	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
>> 
>>  	dev_dbg(&ctrl->dev, "cmd op:0x%x sid:%d\n", opc, sid);
>> 
>> @@ -307,13 +309,13 @@ static int pmic_arb_cmd(struct spmi_controller 
>> *ctrl, u8 opc, u8 sid)
>>  	if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
>>  		return -EINVAL;
>> 
>> -	return pmic_arb->ver_ops->non_data_cmd(ctrl, opc, sid);
>> +	return pa->ver_ops->non_data_cmd(ctrl, opc, sid);
> 
> Same story...
> 
Ok. We will drop this renaming patch.
>>  }
>> 
>>  static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 
>> sid,
>>  			     u16 addr, u8 *buf, size_t len)
>>  {
>> -	struct spmi_pmic_arb_dev *pmic_arb = 
>> spmi_controller_get_drvdata(ctrl);
>> +	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
>>  	unsigned long flags;
>>  	u8 bc = len - 1;
>>  	u32 cmd;
>> @@ -321,16 +323,16 @@ static int pmic_arb_read_cmd(struct 
>> spmi_controller *ctrl, u8 opc, u8 sid,
>>  	u32 offset;
>>  	mode_t mode;
>> 
>> -	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
>> +	rc = pa->ver_ops->offset(pa, sid, addr, &offset);
>>  	if (rc)
>>  		return rc;
>> 
>> -	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
>> +	rc = pa->ver_ops->mode(pa, sid, addr, &mode);
>>  	if (rc)
>>  		return rc;
>> 
>>  	if (!(mode & S_IRUSR)) {
>> -		dev_err(&pmic_arb->spmic->dev,
>> +		dev_err(&pa->spmic->dev,
>>  			"error: impermissible read from peripheral sid:%d addr:0x%x\n",
>>  			sid, addr);
>>  		return -EPERM;
>> @@ -353,30 +355,29 @@ static int pmic_arb_read_cmd(struct 
>> spmi_controller *ctrl, u8 opc, u8 sid,
>>  	else
>>  		return -EINVAL;
>> 
>> -	cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc);
>> +	cmd = pa->ver_ops->fmt_cmd(opc, sid, addr, bc);
>> 
>> -	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
>> -	pmic_arb_set_rd_cmd(pmic_arb, offset + PMIC_ARB_CMD, cmd);
>> -	rc = pmic_arb_wait_for_done(ctrl, pmic_arb->rd_base, sid, addr);
>> +	raw_spin_lock_irqsave(&pa->lock, flags);
>> +	pmic_arb_set_rd_cmd(pa, offset + PMIC_ARB_CMD, cmd);
>> +	rc = pmic_arb_wait_for_done(ctrl, pa->rd_base, sid, addr);
>>  	if (rc)
>>  		goto done;
>> 
>> -	pa_read_data(pmic_arb, buf, offset + PMIC_ARB_RDATA0,
>> +	pa_read_data(pa, buf, offset + PMIC_ARB_RDATA0,
>>  		     min_t(u8, bc, 3));
>> 
>>  	if (bc > 3)
>> -		pa_read_data(pmic_arb, buf + 4,
>> -				offset + PMIC_ARB_RDATA1, bc - 4);
>> +		pa_read_data(pa, buf + 4, offset + PMIC_ARB_RDATA1, bc - 4);
>> 
>>  done:
>> -	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
>> +	raw_spin_unlock_irqrestore(&pa->lock, flags);
>>  	return rc;
>>  }
>> 
>>  static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, 
>> u8 sid,
>>  			      u16 addr, const u8 *buf, size_t len)
>>  {
>> -	struct spmi_pmic_arb_dev *pmic_arb = 
>> spmi_controller_get_drvdata(ctrl);
>> +	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
>>  	unsigned long flags;
>>  	u8 bc = len - 1;
>>  	u32 cmd;
>> @@ -384,16 +385,16 @@ static int pmic_arb_write_cmd(struct 
>> spmi_controller *ctrl, u8 opc, u8 sid,
>>  	u32 offset;
>>  	mode_t mode;
>> 
>> -	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
>> +	rc = pa->ver_ops->offset(pa, sid, addr, &offset);
>>  	if (rc)
>>  		return rc;
>> 
>> -	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
>> +	rc = pa->ver_ops->mode(pa, sid, addr, &mode);
>>  	if (rc)
>>  		return rc;
>> 
>>  	if (!(mode & S_IWUSR)) {
>> -		dev_err(&pmic_arb->spmic->dev,
>> +		dev_err(&pa->spmic->dev,
>>  			"error: impermissible write to peripheral sid:%d addr:0x%x\n",
>>  			sid, addr);
>>  		return -EPERM;
>> @@ -418,20 +419,18 @@ static int pmic_arb_write_cmd(struct 
>> spmi_controller *ctrl, u8 opc, u8 sid,
>>  	else
>>  		return -EINVAL;
>> 
>> -	cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc);
>> +	cmd = pa->ver_ops->fmt_cmd(opc, sid, addr, bc);
>> 
>>  	/* Write data to FIFOs */
>> -	raw_spin_lock_irqsave(&pmic_arb->lock, flags);
>> -	pa_write_data(pmic_arb, buf, offset + PMIC_ARB_WDATA0,
>> -		      min_t(u8, bc, 3));
>> +	raw_spin_lock_irqsave(&pa->lock, flags);
>> +	pa_write_data(pa, buf, offset + PMIC_ARB_WDATA0, min_t(u8, bc, 3));
>>  	if (bc > 3)
>> -		pa_write_data(pmic_arb, buf + 4,
>> -				offset + PMIC_ARB_WDATA1, bc - 4);
>> +		pa_write_data(pa, buf + 4, offset + PMIC_ARB_WDATA1, bc - 4);
>> 
>>  	/* Start the transaction */
>> -	pmic_arb_base_write(pmic_arb, offset + PMIC_ARB_CMD, cmd);
>> -	rc = pmic_arb_wait_for_done(ctrl, pmic_arb->wr_base, sid, addr);
>> -	raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
>> +	pmic_arb_base_write(pa, offset + PMIC_ARB_CMD, cmd);
>> +	rc = pmic_arb_wait_for_done(ctrl, pa->wr_base, sid, addr);
>> +	raw_spin_unlock_irqrestore(&pa->lock, flags);
>> 
>>  	return rc;
>>  }
> 
> Same story for all this diff.
Ok. We will drop this renaming patch.
> 
>> @@ -457,7 +456,7 @@ struct spmi_pmic_arb_qpnpint_type {
>>  static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
>>  			       size_t len)
>>  {
>> -	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
>> +	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
>>  	u8 sid = d->hwirq >> 24;
>>  	u8 per = d->hwirq >> 16;
>> 
>> @@ -470,7 +469,7 @@ static void qpnpint_spmi_write(struct irq_data *d, 
>> u8 reg, void *buf,
>> 
>>  static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, 
>> size_t len)
>>  {
>> -	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
>> +	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
>>  	u8 sid = d->hwirq >> 24;
>>  	u8 per = d->hwirq >> 16;
>> 
>> @@ -481,7 +480,7 @@ static void qpnpint_spmi_read(struct irq_data *d, 
>> u8 reg, void *buf, size_t len)
>>  				    d->irq);
>>  }
>> 
>> -static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
>> +static void periph_interrupt(struct spmi_pmic_arb *pa, u8 apid)
>>  {
>>  	unsigned int irq;
>>  	u32 status;
>> @@ -490,7 +489,7 @@ static void periph_interrupt(struct 
>> spmi_pmic_arb_dev *pa, u8 apid)
>>  	status = readl_relaxed(pa->intr + pa->ver_ops->irq_status(apid));
>>  	while (status) {
>>  		id = ffs(status) - 1;
>> -		status &= ~(1 << id);
>> +		status &= ~BIT(id);
>>  		irq = irq_find_mapping(pa->domain,
>>  				       pa->apid_to_ppid[apid] << 16
>>  				     | id << 8
>> @@ -501,7 +500,7 @@ static void periph_interrupt(struct 
>> spmi_pmic_arb_dev *pa, u8 apid)
>> 
>>  static void pmic_arb_chained_irq(struct irq_desc *desc)
>>  {
>> -	struct spmi_pmic_arb_dev *pa = irq_desc_get_handler_data(desc);
>> +	struct spmi_pmic_arb *pa = irq_desc_get_handler_data(desc);
>>  	struct irq_chip *chip = irq_desc_get_chip(desc);
>>  	void __iomem *intr = pa->intr;
>>  	int first = pa->min_apid >> 5;
>> @@ -516,7 +515,7 @@ static void pmic_arb_chained_irq(struct irq_desc 
>> *desc)
>>  				      pa->ver_ops->owner_acc_status(pa->ee, i));
>>  		while (status) {
>>  			id = ffs(status) - 1;
>> -			status &= ~(1 << id);
>> +			status &= ~BIT(id);
>>  			periph_interrupt(pa, id + i * 32);
>>  		}
>>  	}
>> @@ -526,23 +525,23 @@ static void pmic_arb_chained_irq(struct irq_desc 
>> *desc)
>> 
>>  static void qpnpint_irq_ack(struct irq_data *d)
>>  {
>> -	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
>> +	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
>>  	u8 irq  = d->hwirq >> 8;
>>  	u8 apid = d->hwirq;
>>  	unsigned long flags;
>>  	u8 data;
>> 
>>  	raw_spin_lock_irqsave(&pa->lock, flags);
>> -	writel_relaxed(1 << irq, pa->intr + pa->ver_ops->irq_clear(apid));
>> +	writel_relaxed(BIT(irq), pa->intr + pa->ver_ops->irq_clear(apid));
>>  	raw_spin_unlock_irqrestore(&pa->lock, flags);
>> 
>> -	data = 1 << irq;
>> +	data = BIT(irq);
>>  	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
>>  }
>> 
>>  static void qpnpint_irq_mask(struct irq_data *d)
>>  {
>> -	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
>> +	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
>>  	u8 irq  = d->hwirq >> 8;
>>  	u8 apid = d->hwirq;
>>  	unsigned long flags;
>> @@ -558,13 +557,13 @@ static void qpnpint_irq_mask(struct irq_data *d)
>>  	}
>>  	raw_spin_unlock_irqrestore(&pa->lock, flags);
>> 
>> -	data = 1 << irq;
>> +	data = BIT(irq);
>>  	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
>>  }
>> 
>>  static void qpnpint_irq_unmask(struct irq_data *d)
>>  {
>> -	struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
>> +	struct spmi_pmic_arb *pa = irq_data_get_irq_chip_data(d);
>>  	u8 irq  = d->hwirq >> 8;
>>  	u8 apid = d->hwirq;
>>  	unsigned long flags;
>> @@ -579,7 +578,7 @@ static void qpnpint_irq_unmask(struct irq_data *d)
>>  	}
>>  	raw_spin_unlock_irqrestore(&pa->lock, flags);
>> 
>> -	data = 1 << irq;
>> +	data = BIT(irq);
>>  	qpnpint_spmi_write(d, QPNPINT_REG_EN_SET, &data, 1);
>>  }
>> 
>> @@ -590,7 +589,7 @@ static void qpnpint_irq_enable(struct irq_data *d)
>> 
>>  	qpnpint_irq_unmask(d);
>> 
>> -	data = 1 << irq;
>> +	data = BIT(irq);
>>  	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
>>  }
>> 
>> @@ -598,25 +597,26 @@ static int qpnpint_irq_set_type(struct irq_data 
>> *d, unsigned int flow_type)
>>  {
>>  	struct spmi_pmic_arb_qpnpint_type type;
>>  	u8 irq = d->hwirq >> 8;
>> +	u8 bit_mask_irq = BIT(irq);
> 
> Why the local variable? Just do the ~BIT(irq) thing in place and
> let the compiler take care of the hoist?
> 
Sure.. we will remove this local variable in the subsequent patch.
>> 
>>  	qpnpint_spmi_read(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
>> 
>>  	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
>> -		type.type |= 1 << irq;
>> +		type.type |= bit_mask_irq;
>>  		if (flow_type & IRQF_TRIGGER_RISING)
>> -			type.polarity_high |= 1 << irq;
>> +			type.polarity_high |= bit_mask_irq;
>>  		if (flow_type & IRQF_TRIGGER_FALLING)
>> -			type.polarity_low  |= 1 << irq;
>> +			type.polarity_low  |= bit_mask_irq;
>>  	} else {
>>  		if ((flow_type & (IRQF_TRIGGER_HIGH)) &&
>>  		    (flow_type & (IRQF_TRIGGER_LOW)))
>>  			return -EINVAL;
>> 
>> -		type.type &= ~(1 << irq); /* level trig */
>> +		type.type &= ~bit_mask_irq; /* level trig */
>>  		if (flow_type & IRQF_TRIGGER_HIGH)
>> -			type.polarity_high |= 1 << irq;
>> +			type.polarity_high |= bit_mask_irq;
>>  		else
>> -			type.polarity_low  |= 1 << irq;
>> +			type.polarity_low  |= bit_mask_irq;
>>  	}
>> 
>>  	qpnpint_spmi_write(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
>> @@ -657,7 +657,7 @@ struct spmi_pmic_arb_irq_spec {
> 
> Overall I see little to no value with this patch. I suggest you
> drop the rename. The BIT() thing may be ok, but again, not sure
> there's any benefit.
Ok.. Sure. We drop out the renaming patch in the next version
and will have only BIT() macro patch.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 03/15] spmi: pmic-arb: fix inconsistent use of apid and chan
  2017-05-31  1:31   ` Stephen Boyd
@ 2017-06-01 16:37     ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-01 16:37 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Greg Kroah-Hartman, David Collins, Christophe JAILLET,
	linux-kernel, linux-arm-msm, adharmap, aghayal,
	linux-arm-msm-owner

On 2017-05-31 07:01, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> 
>> The driver currently uses "apid" and "chan" to mean apid. Remove
>> the use of chan and use only apid.
> 
> I'm not so sure. It currently uses "chan" to mean the offset to
> add to the "PMIC Arbiter channel registers" so that we can access
> the appropriate peripheral via the arbiter registers. I actually
> can't remember what APID or PPID stand for, so perhaps describing
> that as well would be helpful so we can navigate this acronym
> soup.
> 
Yes. You are correct.
Will describe the "apid" and "ppid" in the next version patch.
>> 
>> On a SPMI bus there is allocation to manage up to 4K peripherals.
>> However, in practice only few peripherals are instantiated
>> and only few among the instantiated ones actually interrupt.
>> 
>> APID is CPU's way of keeping track of peripherals that could 
>> interrupt.
>> There is a table that maps the 256 interrupting peripherals to
>> a number between 0 and 255. This number is called APID. Information 
>> about
>> that interrupting peripheral is stored in registers offset by its
>> corresponding apid.
> 
> That's all fine, but perhaps we shouldn't worry about "apid"
> being attached to interrupts? I mean, I can imagine some
> peripheral that doesn't interrupt, but we want to read/write it
> and that must be done with the "channel" or "apid" or really the
> "magic offset from the base of the channel registers" to do so.
> Probably APID is fine, as long as APID means "application
> processor peripheral id" or something along those lines.
> 
Yes. you are right. APID means "Application peripheral id".
>> 
>> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
>> ---
>>  drivers/spmi/spmi-pmic-arb.c | 68 
>> ++++++++++++++++++++++----------------------
>>  1 file changed, 34 insertions(+), 34 deletions(-)
>> 
>> diff --git a/drivers/spmi/spmi-pmic-arb.c 
>> b/drivers/spmi/spmi-pmic-arb.c
>> index 7f918ea..7201611 100644
>> --- a/drivers/spmi/spmi-pmic-arb.c
>> +++ b/drivers/spmi/spmi-pmic-arb.c
>> @@ -117,7 +117,7 @@ enum pmic_arb_cmd_op_code {
>>   * @spmic:		SPMI controller object
>>   * @apid_to_ppid:	in-memory copy of APID -> PPID mapping table.
>>   * @ver_ops:		version dependent operations.
>> - * @ppid_to_chan	in-memory copy of PPID -> channel (APID) mapping 
>> table.
>> + * @ppid_to_apid	in-memory copy of PPID -> channel (APID) mapping 
>> table.
> 
> PPID->APID? No channel?
Sure. Will change it the next patch.
> 
>>   *			v2 only.
>>   */
>>  struct spmi_pmic_arb {
>> @@ -140,9 +140,9 @@ struct spmi_pmic_arb {
>>  	struct spmi_controller	*spmic;
>>  	u16			*apid_to_ppid;
>>  	const struct pmic_arb_ver_ops *ver_ops;
>> -	u16			*ppid_to_chan;
>> -	u16			last_channel;
>> -	u8			*chan_to_owner;
>> +	u16			*ppid_to_apid;
>> +	u16			last_apid;
>> +	u8			*apid_to_owner;
>>  };
>> 
>>  /**
>> @@ -772,22 +772,22 @@ static int qpnpint_irq_domain_map(struct 
>> irq_domain *d,
>>  	return 0;
>>  }
>> 
>> -static u16 pmic_arb_find_chan(struct spmi_pmic_arb *pa, u16 ppid)
>> +static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pa, u16 ppid)
>>  {
>>  	u32 regval, offset;
>> -	u16 chan;
>> +	u16 apid;
>>  	u16 id;
>> 
>>  	/*
>>  	 * PMIC_ARB_REG_CHNL is a table in HW mapping channel to ppid.
> 
> Is this comment still relevant?
We will change channel to apid in the next patch.
> 
>> -	 * ppid_to_chan is an in-memory invert of that table.
>> +	 * ppid_to_apid is an in-memory invert of that table.
>>  	 */
>> -	for (chan = pa->last_channel; chan < pa->max_periph; chan++) {
>> +	for (apid = pa->last_apid; apid < pa->max_periph; apid++) {
>>  		regval = readl_relaxed(pa->cnfg +
>> -				      SPMI_OWNERSHIP_TABLE_REG(chan));
>> -		pa->chan_to_owner[chan] = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
>> +				      SPMI_OWNERSHIP_TABLE_REG(apid));
>> +		pa->apid_to_owner[apid] = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
>> 
>> -		offset = PMIC_ARB_REG_CHNL(chan);
>> +		offset = PMIC_ARB_REG_CHNL(apid);
>>  		if (offset >= pa->core_size)
>>  			break;
>> 
>> @@ -796,15 +796,15 @@ static u16 pmic_arb_find_chan(struct 
>> spmi_pmic_arb *pa, u16 ppid)
>>  			continue;
>> 
>>  		id = (regval >> 8) & PMIC_ARB_PPID_MASK;
>> -		pa->ppid_to_chan[id] = chan | PMIC_ARB_CHAN_VALID;
>> +		pa->ppid_to_apid[id] = apid | PMIC_ARB_CHAN_VALID;
> 
> Why do we still call the flag PMIC_ARB_CHAN_VALID then? Shouldn't
> it be PMIC_ARB_APID_VALID?
> 
Yes. Agree. Will change it to PMIC_ARB_APID_VALID in the next patch.
>>  		if (id == ppid) {
>> -			chan |= PMIC_ARB_CHAN_VALID;
>> +			apid |= PMIC_ARB_CHAN_VALID;
>>  			break;
>>  		}
>>  	}
>> -	pa->last_channel = chan & ~PMIC_ARB_CHAN_VALID;
>> +	pa->last_apid = apid & ~PMIC_ARB_CHAN_VALID;
>> 
>> -	return chan;
>> +	return apid;
>>  }
>> 
>> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 04/15] spmi: pmic-arb: optimize table lookups
  2017-05-31  1:44   ` Stephen Boyd
@ 2017-06-01 16:53     ` kgunda
  2017-06-02 18:31       ` Stephen Boyd
  0 siblings, 1 reply; 62+ messages in thread
From: kgunda @ 2017-06-01 16:53 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Christophe JAILLET, David Collins, linux-kernel, linux-arm-msm,
	adharmap, aghayal, linux-arm-msm-owner

On 2017-05-31 07:14, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> diff --git a/drivers/spmi/spmi-pmic-arb.c 
>> b/drivers/spmi/spmi-pmic-arb.c
>> index 7201611..6320f1f 100644
>> --- a/drivers/spmi/spmi-pmic-arb.c
>> +++ b/drivers/spmi/spmi-pmic-arb.c
>> @@ -164,6 +164,8 @@ struct spmi_pmic_arb {
>>   *			on v2 offset of SPMI_PIC_IRQ_CLEARn.
>>   */
>>  struct pmic_arb_ver_ops {
>> +	int (*ppid_to_apid)(struct spmi_pmic_arb *pa, u8 sid, u16 addr,
>> +			u8 *apid);
> 
> Nitpick: It's called "pa" but "dev" in the next line.
> 
Will rename the pa -> dev in the next patch.
>>  	int (*mode)(struct spmi_pmic_arb *dev, u8 sid, u16 addr,
>>  			mode_t *mode);
>>  	/* spmi commands (read_cmd, write_cmd, cmd) functionality */
>> @@ -657,42 +659,6 @@ struct spmi_pmic_arb_irq_spec {
>>  	unsigned irq:3;
>>  };
>> 
>> -static int search_mapping_table(struct spmi_pmic_arb *pa,
>> -				struct spmi_pmic_arb_irq_spec *spec,
> 
> Perhaps the spec should be removed at some point if this was the
> only place it was passed to.
> 
Yes. This is passed only in this function. You want to remove this
structure and pass the slave, per and irq as function parameters?
If so we will do it in the next patch.

>> -				u8 *apid)
> 
> This code looks mostly unchanged, so please leave it as it is and
> move the pmic_arb_ppid_to_apid_v1() function here so we can see
> what actually changed.
> 
Sure. Will do that in the next patch.
>> -{
>> -	u16 ppid = spec->slave << 8 | spec->per;
>> -	u32 *mapping_table = pa->mapping_table;
>> -	int index = 0, i;
>> -	u32 data;
>> -
>> -	for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
>> -		if (!test_and_set_bit(index, pa->mapping_table_valid))
>> -			mapping_table[index] = readl_relaxed(pa->cnfg +
>> -						SPMI_MAPPING_TABLE_REG(index));
>> -
>> -		data = mapping_table[index];
>> -
>> -		if (ppid & BIT(SPMI_MAPPING_BIT_INDEX(data))) {
>> -			if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) {
>> -				index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
>> -			} else {
>> -				*apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
>> -				return 0;
>> -			}
>> -		} else {
>> -			if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) {
>> -				index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
>> -			} else {
>> -				*apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
>> -				return 0;
>> -			}
>> -		}
>> -	}
>> -
>> -	return -ENODEV;
>> -}
>> -
>>  static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
>>  					   struct device_node *controller,
>>  					   const u32 *intspec,
>> @@ -702,7 +668,7 @@ static int qpnpint_irq_domain_dt_translate(struct 
>> irq_domain *d,
>>  {
>>  	struct spmi_pmic_arb *pa = d->host_data;
>>  	struct spmi_pmic_arb_irq_spec spec;
>> -	int err;
>> +	int rc;
>>  	u8 apid;
>> 
>>  	dev_dbg(&pa->spmic->dev,
>> @@ -720,11 +686,14 @@ static int 
>> qpnpint_irq_domain_dt_translate(struct irq_domain *d,
>>  	spec.per   = intspec[1];
>>  	spec.irq   = intspec[2];
>> 
>> -	err = search_mapping_table(pa, &spec, &apid);
>> -	if (err)
>> -		return err;
>> -
>> -	pa->apid_to_ppid[apid] = spec.slave << 8 | spec.per;
>> +	rc = pa->ver_ops->ppid_to_apid(pa, intspec[0],
>> +			(intspec[1] << 8), &apid);
>> +	if (rc < 0) {
>> +		dev_err(&pa->spmic->dev,
>> +		"failed to xlate sid = 0x%x, periph = 0x%x, irq = %x rc = %d\n",
>> +		intspec[0], intspec[1], intspec[2], rc);
>> +		return rc;
>> +	}
>> 
>>  	/* Keep track of {max,min}_apid for bounding search during interrupt 
>> */
>>  	if (apid > pa->max_apid)
>> @@ -758,6 +727,54 @@ static int qpnpint_irq_domain_map(struct 
>> irq_domain *d,
>>  }
>> 
>>  static int
>> +pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, 
>> u8 *apid)
>> +{
>> +	u16 ppid = sid << 8 | ((addr >> 8) & 0xFF);
> 
> The function is called ppid_to_apid, but we pass in a sid and
> addr. Just pass a ppid instead of both split out?
> 
Sure .. Will do that in the next patch.
>> +	u32 *mapping_table = pa->mapping_table;
>> +	int index = 0, i;
>> +	u16 apid_valid;
>> +	u32 data;
>> +
>> +	apid_valid = pa->ppid_to_apid[ppid];
>> +	if (apid_valid & PMIC_ARB_CHAN_VALID) {
>> +		*apid = (apid_valid & ~PMIC_ARB_CHAN_VALID);
>> +		return 0;
>> +	}
>> +
> 
> From here to...
> 
>> +	for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
>> +		if (!test_and_set_bit(index, pa->mapping_table_valid))
>> +			mapping_table[index] = readl_relaxed(pa->cnfg +
>> +						SPMI_MAPPING_TABLE_REG(index));
>> +
>> +		data = mapping_table[index];
>> +
>> +		if (ppid & BIT(SPMI_MAPPING_BIT_INDEX(data))) {
>> +			if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) {
>> +				index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
>> +			} else {
>> +				*apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
>> +				pa->ppid_to_apid[ppid]
>> +					= *apid | PMIC_ARB_CHAN_VALID;
>> +				pa->apid_to_ppid[*apid] = ppid;
>> +				return 0;
>> +			}
>> +		} else {
>> +			if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) {
>> +				index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
>> +			} else {
>> +				*apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
>> +				pa->ppid_to_apid[ppid]
>> +					= *apid | PMIC_ARB_CHAN_VALID;
>> +				pa->apid_to_ppid[*apid] = ppid;
>> +				return 0;
>> +			}
>> +		}
>> +	}
>> +
>> +	return -ENODEV;
>> +}
> 
> here is all unchanged? Oh except apid_to_ppid/ppid_to_apid is
> inserted.
> 
Yes. correct. Will move this part to the original place in the next 
patch.
>> +
>> +static int
>>  pmic_arb_mode_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t 
>> *mode)
>>  {
>>  	*mode = S_IRUSR | S_IWUSR;
>> @@ -797,6 +814,7 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb 
>> *pa, u16 ppid)
>> 
>>  		id = (regval >> 8) & PMIC_ARB_PPID_MASK;
>>  		pa->ppid_to_apid[id] = apid | PMIC_ARB_CHAN_VALID;
>> +		pa->apid_to_ppid[apid] = id;
>>  		if (id == ppid) {
>>  			apid |= PMIC_ARB_CHAN_VALID;
>>  			break;
>> @@ -809,20 +827,35 @@ static u16 pmic_arb_find_apid(struct 
>> spmi_pmic_arb *pa, u16 ppid)
>> 
>> 
>>  static int
>> -pmic_arb_mode_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t 
>> *mode)
>> +pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pa, u8 sid, u16 addr, 
>> u8 *apid)
>>  {
>>  	u16 ppid = (sid << 8) | (addr >> 8);
>> -	u16 apid;
>> -	u8 owner;
>> +	u16 apid_valid;
>> 
>> -	apid = pa->ppid_to_apid[ppid];
>> -	if (!(apid & PMIC_ARB_CHAN_VALID))
>> +	apid_valid = pa->ppid_to_apid[ppid];
>> +	if (!(apid_valid & PMIC_ARB_CHAN_VALID))
>> +		apid_valid = pmic_arb_find_apid(pa, ppid);
>> +	if (!(apid_valid & PMIC_ARB_CHAN_VALID))
>>  		return -ENODEV;
>> 
>> +	*apid = (apid_valid & ~PMIC_ARB_CHAN_VALID);
> 
> Useless parenthesis. Please remove.
> 
Sure. Will remove it in the next patch.
> Why can't we just return a number that's >= 0 for apid and < 0
> for an error from this op? Pointer passing is odd style.
> 
Sure. Will change it in the next patch.
>> +	return 0;
>> +}
>> +

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 06/15] spmi: pmic-arb: fix missing interrupts
  2017-05-31  2:00   ` Stephen Boyd
@ 2017-06-01 17:06     ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-01 17:06 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Greg Kroah-Hartman, Christophe JAILLET,
	David Collins, Subbaraman Narayanamurthy, linux-kernel,
	linux-arm-msm, adharmap, aghayal, linux-arm-msm-owner

On 2017-05-31 07:30, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> 
>> irq_enable is called when the device resumes. Note that the
>> irq_enable is called regardless of whether the interrupt was
>> marked enabled/disabled in the descriptor or whether it was
>> masked/unmasked at the controller while resuming.
>> 
>> The current driver unconditionally clears the interrupt in its
>> irq_enable callback. This is dangerous as any interrupts that
>> happen right before the resume could be missed.
>> Remove the irq_enable callback and use mask/unmask instead.
>> 
>> Also remove struct pmic_arb_irq_spec as it serves no real purpose.
>> It is used only in the translate function and the code is much
>> cleaner without it.
> 
> Also a separate patch for that part....
> 
Sure. will split it in to different patch or move it in the
https://patchwork.kernel.org/patch/9754511/ patch as per your comment.
>> 
>> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
>> ---
>>  drivers/spmi/spmi-pmic-arb.c | 29 +++--------------------------
>>  1 file changed, 3 insertions(+), 26 deletions(-)
>> 
>> diff --git a/drivers/spmi/spmi-pmic-arb.c 
>> b/drivers/spmi/spmi-pmic-arb.c
>> index 0a5728c..bc03737 100644
>> --- a/drivers/spmi/spmi-pmic-arb.c
>> +++ b/drivers/spmi/spmi-pmic-arb.c
>> @@ -588,17 +588,6 @@ static void qpnpint_irq_unmask(struct irq_data 
>> *d)
>>  	qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
>>  }
>> 
>> -static void qpnpint_irq_enable(struct irq_data *d)
>> -{
>> -	u8 irq  = d->hwirq >> 8;
>> -	u8 data;
>> -
>> -	qpnpint_irq_unmask(d);
>> -
>> -	data = BIT(irq);
>> -	qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
>> -}
>> -
>>  static int qpnpint_irq_set_type(struct irq_data *d, unsigned int 
>> flow_type)
>>  {
>>  	struct spmi_pmic_arb_qpnpint_type type;
>> @@ -647,7 +636,6 @@ static int qpnpint_get_irqchip_state(struct 
>> irq_data *d,
>> 
>>  static struct irq_chip pmic_arb_irqchip = {
>>  	.name		= "pmic_arb",
>> -	.irq_enable	= qpnpint_irq_enable,
>>  	.irq_ack	= qpnpint_irq_ack,
>>  	.irq_mask	= qpnpint_irq_mask,
>>  	.irq_unmask	= qpnpint_irq_unmask,
> 
> This looks ok.
Thanks !

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 12/15] spmi-pmic-arb: fix a possible null pointer dereference
  2017-05-31 17:29   ` Stephen Boyd
@ 2017-06-02  7:13     ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-02  7:13 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Greg Kroah-Hartman,
	Subbaraman Narayanamurthy, Christophe JAILLET, David Collins,
	linux-kernel, linux-arm-msm, adharmap, aghayal,
	linux-arm-msm-owner

On 2017-05-31 22:59, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> diff --git a/drivers/spmi/spmi-pmic-arb.c 
>> b/drivers/spmi/spmi-pmic-arb.c
>> index 2afe359..412481d 100644
>> --- a/drivers/spmi/spmi-pmic-arb.c
>> +++ b/drivers/spmi/spmi-pmic-arb.c
>> @@ -1003,6 +1003,12 @@ static int spmi_pmic_arb_probe(struct 
>> platform_device *pdev)
>>  	pa->spmic = ctrl;
>> 
>>  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
>> +	if (!res) {
>> +		dev_err(&pdev->dev, "core resource not specified\n");
>> +		err = -EINVAL;
>> +		goto err_put_ctrl;
>> +	}
>> +
>>  	pa->core_size = resource_size(res);
>>  	if (pa->core_size <= 0x800) {
>>  		dev_err(&pdev->dev, "core_size is smaller than 0x800. Failing 
>> Probe\n");
> 
> I would prefer this patch instead, so that we can piggyback on
> the error checking of the devm_ioremap_resource() code. Also, add
> a Fixes: tag please so we can backport it as needed.
> 
Sure. We will modify as per your suggestion in the next patch.
> 
> diff --git a/drivers/spmi/spmi-pmic-arb.c 
> b/drivers/spmi/spmi-pmic-arb.c
> index 5ec3a595dc7d..0cedbda60707 100644
> --- a/drivers/spmi/spmi-pmic-arb.c
> +++ b/drivers/spmi/spmi-pmic-arb.c
> @@ -878,12 +878,12 @@ static int spmi_pmic_arb_probe(struct
> platform_device *pdev)
>  	pa->spmic = ctrl;
> 
>  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
> -	pa->core_size = resource_size(res);
>  	core = devm_ioremap_resource(&ctrl->dev, res);
>  	if (IS_ERR(core)) {
>  		err = PTR_ERR(core);
>  		goto err_put_ctrl;
>  	}
> +	pa->core_size = resource_size(res);
> 
>  	hw_ver = readl_relaxed(core + PMIC_ARB_VERSION);
>  	is_v1  = (hw_ver < PMIC_ARB_VERSION_V2_MIN);

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 14/15] spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq
  2017-05-31 17:53   ` Stephen Boyd
@ 2017-06-02  7:26     ` kgunda
  2017-06-06 11:27       ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: kgunda @ 2017-06-02  7:26 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, David Collins, Christophe JAILLET,
	Subbaraman Narayanamurthy, linux-kernel, linux-arm-msm, adharmap,
	aghayal, linux-arm-msm-owner

On 2017-05-31 23:23, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> From: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
>> 
>> Currently, cleanup_irq() is invoked when a peripheral's interrupt
>> fires and there is no mapping present in the interrupt domain of
>> spmi interrupt controller.
>> 
>> The cleanup_irq clears the arbiter bit, clears the pmic interrupt
>> and disables it at the pmic in that order. The last disable in
>> cleanup_irq races with request_irq() in that it stomps over the
>> enable issued by request_irq. Fix this by not writing to the pmic
>> in cleanup_irq. The latched bit will be left set in the pmic,
>> which will not send us more interrupts even if the enable bit
>> stays enabled.
>> 
>> When a client wants to request an interrupt, use the activate
>> callback on the irq_domain to clear latched bit. This ensures
>> that the latched, if set due to the above changes in cleanup_irq
>> or when the bootloader leaves it set, gets cleaned up, paving way
>> for upcoming interrupts to trigger.
>> 
>> With this, there is a possibility of unwanted triggering of
>> interrupt right after the latched bit is cleared - the interrupt
>> may be left enabled too. To avoid that, clear the enable first
>> followed by clearing the latched bit in the activate callback.
>> 
>> Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
>> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
> 
> Please squash this with the patch that adds cleanup_irq() and
> rewrite the commit text to combine details from both.
Sure. Will squash it in the next patch submission.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 02/15] spmi: pmic-arb: rename spmi_pmic_arb_dev to spmi_pmic_arb
  2017-06-01 16:11     ` kgunda
@ 2017-06-02 18:29       ` Stephen Boyd
  2017-06-05  6:28         ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-06-02 18:29 UTC (permalink / raw)
  To: kgunda
  Cc: Abhijeet Dharmapurikar, Greg Kroah-Hartman, David Collins,
	Subbaraman Narayanamurthy, Christophe JAILLET, linux-kernel,
	linux-arm-msm, adharmap, aghayal, linux-arm-msm-owner

On 06/01, kgunda@codeaurora.org wrote:
> >>@@ -209,23 +210,24 @@ static void pa_read_data(struct
> >>spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
> >>  * @buf:	buffer to write. length must be bc + 1.
> >>  */
> >> static void
> >>-pa_write_data(struct spmi_pmic_arb_dev *dev, const u8 *buf, u32
> >>reg, u8 bc)
> >>+pa_write_data(struct spmi_pmic_arb *pa, const u8 *buf, u32 reg,
> >>u8 bc)
> >> {
> >> 	u32 data = 0;
> >>+
> >> 	memcpy(&data, buf, (bc & 3) + 1);
> >>-	__raw_writel(data, dev->wr_base + reg);
> >>+	pmic_arb_base_write(pa, reg, data);
> >
> >This is an unrelated change. Not sure what's going on with this
> >diff but we most likely want to keep the __raw_writel() here. See
> >how renames introduce bugs and why we don't value them?
> >
> Actually pmic_arb_base_write has the writel_relaxed inside it.
> that's why we removed the __raw_writel to use the common function.
> Anyways, we drop the renaming patch from this patch series.

__raw_writel() is there on purpose because we're reading bytes at
a time and the CPU could be big-endian or little-endian.
readl_relaxed() would do a byte swap which we don't want.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 04/15] spmi: pmic-arb: optimize table lookups
  2017-06-01 16:53     ` kgunda
@ 2017-06-02 18:31       ` Stephen Boyd
  2017-06-05  6:33         ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-06-02 18:31 UTC (permalink / raw)
  To: kgunda
  Cc: Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Christophe JAILLET, David Collins, linux-kernel, linux-arm-msm,
	adharmap, aghayal, linux-arm-msm-owner

On 06/01, kgunda@codeaurora.org wrote:
> On 2017-05-31 07:14, Stephen Boyd wrote:
> >On 05/30, Kiran Gunda wrote:
> >>diff --git a/drivers/spmi/spmi-pmic-arb.c
> >>b/drivers/spmi/spmi-pmic-arb.c
> >>index 7201611..6320f1f 100644
> >>--- a/drivers/spmi/spmi-pmic-arb.c
> >>+++ b/drivers/spmi/spmi-pmic-arb.c
> >>@@ -657,42 +659,6 @@ struct spmi_pmic_arb_irq_spec {
> >> 	unsigned irq:3;
> >> };
> >>
> >>-static int search_mapping_table(struct spmi_pmic_arb *pa,
> >>-				struct spmi_pmic_arb_irq_spec *spec,
> >
> >Perhaps the spec should be removed at some point if this was the
> >only place it was passed to.
> >
> Yes. This is passed only in this function. You want to remove this
> structure and pass the slave, per and irq as function parameters?
> If so we will do it in the next patch.

We don't pass it anywhere though? So I'm just saying have local
variables instead of the structure.


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 02/15] spmi: pmic-arb: rename spmi_pmic_arb_dev to spmi_pmic_arb
  2017-06-02 18:29       ` Stephen Boyd
@ 2017-06-05  6:28         ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-05  6:28 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Greg Kroah-Hartman, David Collins,
	Subbaraman Narayanamurthy, Christophe JAILLET, linux-kernel,
	linux-arm-msm, adharmap, aghayal, linux-arm-msm-owner

On 2017-06-02 23:59, Stephen Boyd wrote:
> On 06/01, kgunda@codeaurora.org wrote:
>> >>@@ -209,23 +210,24 @@ static void pa_read_data(struct
>> >>spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
>> >>  * @buf:	buffer to write. length must be bc + 1.
>> >>  */
>> >> static void
>> >>-pa_write_data(struct spmi_pmic_arb_dev *dev, const u8 *buf, u32
>> >>reg, u8 bc)
>> >>+pa_write_data(struct spmi_pmic_arb *pa, const u8 *buf, u32 reg,
>> >>u8 bc)
>> >> {
>> >> 	u32 data = 0;
>> >>+
>> >> 	memcpy(&data, buf, (bc & 3) + 1);
>> >>-	__raw_writel(data, dev->wr_base + reg);
>> >>+	pmic_arb_base_write(pa, reg, data);
>> >
>> >This is an unrelated change. Not sure what's going on with this
>> >diff but we most likely want to keep the __raw_writel() here. See
>> >how renames introduce bugs and why we don't value them?
>> >
>> Actually pmic_arb_base_write has the writel_relaxed inside it.
>> that's why we removed the __raw_writel to use the common function.
>> Anyways, we drop the renaming patch from this patch series.
> 
> __raw_writel() is there on purpose because we're reading bytes at
> a time and the CPU could be big-endian or little-endian.
> readl_relaxed() would do a byte swap which we don't want.
ok. Thanks for clarifying it. We do not remove the __raw_writel.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 04/15] spmi: pmic-arb: optimize table lookups
  2017-06-02 18:31       ` Stephen Boyd
@ 2017-06-05  6:33         ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-05  6:33 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Christophe JAILLET, David Collins, linux-kernel, linux-arm-msm,
	adharmap, aghayal, linux-arm-msm-owner

On 2017-06-03 00:01, Stephen Boyd wrote:
> On 06/01, kgunda@codeaurora.org wrote:
>> On 2017-05-31 07:14, Stephen Boyd wrote:
>> >On 05/30, Kiran Gunda wrote:
>> >>diff --git a/drivers/spmi/spmi-pmic-arb.c
>> >>b/drivers/spmi/spmi-pmic-arb.c
>> >>index 7201611..6320f1f 100644
>> >>--- a/drivers/spmi/spmi-pmic-arb.c
>> >>+++ b/drivers/spmi/spmi-pmic-arb.c
>> >>@@ -657,42 +659,6 @@ struct spmi_pmic_arb_irq_spec {
>> >> 	unsigned irq:3;
>> >> };
>> >>
>> >>-static int search_mapping_table(struct spmi_pmic_arb *pa,
>> >>-				struct spmi_pmic_arb_irq_spec *spec,
>> >
>> >Perhaps the spec should be removed at some point if this was the
>> >only place it was passed to.
>> >
>> Yes. This is passed only in this function. You want to remove this
>> structure and pass the slave, per and irq as function parameters?
>> If so we will do it in the next patch.
> 
> We don't pass it anywhere though? So I'm just saying have local
> variables instead of the structure.
Sure. Thanks for the clarification.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 05/15] spmi: pmic-arb: cleanup unrequested irqs
  2017-05-31  1:57   ` Stephen Boyd
@ 2017-06-06 10:50     ` kgunda
  2017-06-13  2:11       ` Stephen Boyd
  0 siblings, 1 reply; 62+ messages in thread
From: kgunda @ 2017-06-06 10:50 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Christophe JAILLET, David Collins, linux-kernel, linux-arm-msm,
	adharmap, aghayal, linux-arm-msm-owner

On 2017-05-31 07:27, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> 
>> We see a unmapped irqs trigger right around bootup. This could
>> likely be because the bootloader exited leaving the interrupts
>> in an unknown or unhandled state.  Ack and mask the interrupt
>> if one is found. A request_irq later will unmask it and also
>> setup proper mapping structures.
> 
> Do we have systems where this is causing an interrupt storm due
> to a level high interrupt or something? Just plain acking and
> masking irqs at boot if we don't have an irq descriptor created
> yet doesn't sound like a good idea, because we'll lose all
> interrupts that happen before this driver probes?
> 
Yes. There were instances of an interrupt storm without this patch.
There is an RT_STATUS register in the  peripheral address space which
maintains the real time state and can be read by the client driver
before it registers for the irq. Few client drivers such as charger
already doing this.
>> 
>> Also the current driver ensures that no read/write transaction
>> is in progress while it makes changes to the interrupt regions.
>> This is not necessary because read/writes over spmi and arbiter
>> interrupt control are independent operations. Hence, remove the
>> synchronized accesses to interrupt region.
> 
> That's another patch for this paragraph.
This patch is already pulled in to Greg's tree.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 07/15] spmi: pmic-arb: clear the latched status of the interrupt
  2017-05-31 22:03   ` Stephen Boyd
@ 2017-06-06 10:55     ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-06 10:55 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET,
	Subbaraman Narayanamurthy, David Collins, linux-kernel,
	linux-arm-msm, adharmap, aghayal, linux-arm-msm-owner

On 2017-06-01 03:33, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> 
>> PMIC interrupts each have an internal latched status bit which is
>> not visible from any register.  This status bit is set as soon as
>> the conditions specified in the interrupt type and polarity
>> registers are met even if the interrupt is not enabled.  When it
>> is set, nothing else changes within the PMIC and no interrupt
>> notification packets are sent.  If the internal latched status
>> bit is set when an interrupt is enabled, then the value is
>> immediately propagated into the interrupt latched status register
>> and an interrupt notification packet is sent out from the PMIC
>> over SPMI.
>> 
>> This PMIC hardware behavior can lead to a situation where the
>> handler for a level triggered interrupt is called immediately
>> after enable_irq() is called even though the interrupt physically
>> triggered while it was disabled within the genirq framework.
>> This situation takes place if the the interrupt fires twice after
> 
> Double 'the'
> 
>> calling disable_irq().  The first time it fires, the level flow
>> handler will mask and disregard it.  Unfortunately, the second
>> time it fires, the internal latched status bit is set within the
>> PMIC and no further notification is received.
> 
> because the interrupt has been disabled.
> 
>> When enable_irq()
>> is called later, the interrupt is unmasked (enabled in the PMIC)
>> which results in the PMIC immediately sending an interrupt
>> notification packet out over SPMI.  This breaks the semantics
>> of level triggered interrupts within the genirq framework since
>> they should be completely ignored while disabled.
> 
> Ok. I wonder why the hardware latches interrupts at all.
> 
>> 
>> The PMIC internal latched status behavior also affects how
>> interrupts are treated during suspend.  While entering suspend,
>> all interrupts not specified as wakeup mode are masked.  Upon
>> resume, these interrupts are unmasked.  Thus if any of the
>> non-wakeup PMIC interrupts fired while the system was suspended,
>> then the PMIC will send interrupt notification packets out via
>> SPMI as soon as they are unmasked during resume.  This behavior
>> violates genirq semantics as well since non-wakeup interrupts
>> should be completely ignored during suspend.
>> 
>> Modify the qpnpint_irq_unmask() function so that the interrupt
>> latched status clear register is written immediately before the
>> interrupt enable register.  This clears the internal latched
>> status bit of the interrupt so that it cannot trigger spuriously
>> immediately upon being enabled.
>> 
>> Also, while resuming an irq, an unmask could be called even if it
>> was not previously masked.  So, before writing these registers,
>> check if the interrupt is already enabled within the PMIC. If it
>> is, then no further register writes are required.  This
>> condition check ensures that a valid latched status register bit
>> is not cleared until it is properly handled.
>> 
>> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
> 
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Thanks for reviewing and acking this.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 08/15] spmi: pmic_arb: use appropriate flow handler
  2017-05-31 19:03   ` Stephen Boyd
@ 2017-06-06 10:57     ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-06 10:57 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET, David Collins,
	Subbaraman Narayanamurthy, linux-kernel, linux-arm-msm, adharmap,
	aghayal, linux-arm-msm-owner

On 2017-06-01 00:33, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> 
>> The current code uses handle_level_irq flow handler even if the
>> trigger type of the interrupt is edge. This can lead to missing
>> of an edge transition that happens when the interrupt is being
>> handled. The level flow handler masks the interrupt while it is
>> being handled, so if an edge transition happens at that time,
>> that edge is lost.
>> 
>> Use an edge flow handler for edge type interrupts which ensures
>> that the interrupt stays enabled while being handled - at least
>> until it triggers at which point the flow handler sets the
>> IRQF_PENDING flag and only then masks the interrupt. That
>> IRQF_PENDING state indicates an edge transition happened while
>> the interrupt was being handled and the handler is called again.
>> 
>> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
> 
> Do we have any edge interrupts in the tree right now? At least
> RTC seems to be using edge... This should go back to stable with
> a Fixes tag.
> 
Yes. A bunch of internal drivers use edge interrupts.
>> ---
>>  drivers/spmi/spmi-pmic-arb.c | 6 ++++++
>>  1 file changed, 6 insertions(+)
>> 
>> diff --git a/drivers/spmi/spmi-pmic-arb.c 
>> b/drivers/spmi/spmi-pmic-arb.c
>> index 1d23df0..ad34491 100644
>> --- a/drivers/spmi/spmi-pmic-arb.c
>> +++ b/drivers/spmi/spmi-pmic-arb.c
>> @@ -625,6 +625,12 @@ static int qpnpint_irq_set_type(struct irq_data 
>> *d, unsigned int flow_type)
>>  	}
>> 
>>  	qpnpint_spmi_write(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
>> +
>> +	if (flow_type & IRQ_TYPE_EDGE_BOTH)
> 
> IRQ_TYPE_EDGE_BOTH doesn't seem appropriate to use here. We're
> really just testing to see if the type is an edge type, not if
> it's BOTH edges.
> 
Ok. Agree. Will fix in the follow up patch.
>> +		irq_set_handler_locked(d, handle_edge_irq);
>> +	else
>> +		irq_set_handler_locked(d, handle_level_irq);
>> +
> 
> And we already have code that does that check:
> 
> 	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
> 
> so just put the irq_set_handler_locked() calls in those if
> statements please.
Sure. Will fix in the follow up patch.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 10/15] spmi: pmic_arb: add support for PMIC bus arbiter v3
  2017-05-31 22:18   ` Stephen Boyd
@ 2017-06-06 11:10     ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-06 11:10 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, David Collins, Christophe JAILLET,
	Subbaraman Narayanamurthy, linux-kernel, linux-arm-msm, adharmap,
	aghayal, linux-arm-msm-owner

On 2017-06-01 03:48, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> 
>>  /* PMIC Arbiter channel registers offsets */
>> @@ -96,6 +97,17 @@ enum pmic_arb_cmd_op_code {
>>  /* interrupt enable bit */
>>  #define SPMI_PIC_ACC_ENABLE_BIT		BIT(0)
>> 
>> +#define HWIRQ(slave_id, periph_id, irq_id, apid) \
>> +	((((slave_id) & 0xF)   << 28) | \
>> +	(((periph_id) & 0xFF)  << 20) | \
>> +	(((irq_id)    & 0x7)   << 16) | \
>> +	(((apid)      & 0x1FF) << 0))
>> +
>> +#define HWIRQ_SID(hwirq)  (((hwirq) >> 28) & 0xF)
>> +#define HWIRQ_PER(hwirq)  (((hwirq) >> 20) & 0xFF)
>> +#define HWIRQ_IRQ(hwirq)  (((hwirq) >> 16) & 0x7)
>> +#define HWIRQ_APID(hwirq) (((hwirq) >> 0)  & 0x1FF)
> 
> How about lowercase and hwirq_to_*() macros? Then it's more
> function like style. And spec_to_hwirq() or something?
> 
Sure. Will change it in the follow up patch.
>> +
>>  struct pmic_arb_ver_ops;
>> 
>>  struct apid_data {
>> @@ -151,7 +163,9 @@ struct spmi_pmic_arb {
>>  /**
>>   * pmic_arb_ver: version dependent functionality.
>>   *
>> - * @mode:	access rights to specified pmic peripheral.
>> + * @ver_str:		version string.
>> + * @ppid_to_apid:	finds the apid for a given ppid.
>> + * @mode:		access rights to specified pmic peripheral.
> 
> mode didn't need to change tabbing. Not sure why it's appearing
> in the diff.
> 
When adding the new field description added extra tab for mode for 
alignment.
That's why it is showing up.
>>   * @non_data_cmd:	on v1 issues an spmi non-data command.
>>   *			on v2 no HW support, returns -EOPNOTSUPP.
>>   * @offset:		on v1 offset of per-ee channel.
>> @@ -177,10 +192,10 @@ struct pmic_arb_ver_ops {
>>  	u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc);
>>  	int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid);
>>  	/* Interrupts controller functionality (offset of PIC registers) */
>> -	u32 (*owner_acc_status)(u8 m, u8 n);
>> -	u32 (*acc_enable)(u8 n);
>> -	u32 (*irq_status)(u8 n);
>> -	u32 (*irq_clear)(u8 n);
>> +	u32 (*owner_acc_status)(u8 m, u16 n);
>> +	u32 (*acc_enable)(u16 n);
>> +	u32 (*irq_status)(u16 n);
>> +	u32 (*irq_clear)(u16 n);
>>  };
>> 
>>  static inline void pmic_arb_base_write(struct spmi_pmic_arb *pa,
>> @@ -776,7 +787,7 @@ static int qpnpint_irq_domain_map(struct 
>> irq_domain *d,
>>  }
>> 
>>  static int
>> -pmic_arb_mode_v1(struct spmi_pmic_arb *pa, u8 sid, u16 addr, mode_t 
>> *mode)
>> +pmic_arb_mode_v1_v3(struct spmi_pmic_arb *pa, u8 sid, u16 addr, 
>> mode_t *mode)
> 
> Nice to know that the mode became useless in v3 and beyond! Sigh.
> 
>>  {
>>  	*mode = S_IRUSR | S_IWUSR;
>>  	return 0;
>> @@ -987,21 +1017,21 @@ static int spmi_pmic_arb_probe(struct 
>> platform_device *pdev)
>> 
>>  		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL(0) */
>> -		pa->max_periph =  (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;
>> +		pa->max_periph = (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;
> 
> This looks unrelated?
> 
Yes. Just removed the extra space after '='.
>> 
>>  		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>>  						   "obsrvr");

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 14/15] spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq
  2017-06-02  7:26     ` kgunda
@ 2017-06-06 11:27       ` kgunda
  2017-06-13  2:10         ` Stephen Boyd
  0 siblings, 1 reply; 62+ messages in thread
From: kgunda @ 2017-06-06 11:27 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, David Collins, Christophe JAILLET,
	Subbaraman Narayanamurthy, linux-kernel, linux-arm-msm, adharmap,
	aghayal, linux-arm-msm-owner

On 2017-06-02 12:56, kgunda@codeaurora.org wrote:
> On 2017-05-31 23:23, Stephen Boyd wrote:
>> On 05/30, Kiran Gunda wrote:
>>> From: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
>>> 
>>> Currently, cleanup_irq() is invoked when a peripheral's interrupt
>>> fires and there is no mapping present in the interrupt domain of
>>> spmi interrupt controller.
>>> 
>>> The cleanup_irq clears the arbiter bit, clears the pmic interrupt
>>> and disables it at the pmic in that order. The last disable in
>>> cleanup_irq races with request_irq() in that it stomps over the
>>> enable issued by request_irq. Fix this by not writing to the pmic
>>> in cleanup_irq. The latched bit will be left set in the pmic,
>>> which will not send us more interrupts even if the enable bit
>>> stays enabled.
>>> 
>>> When a client wants to request an interrupt, use the activate
>>> callback on the irq_domain to clear latched bit. This ensures
>>> that the latched, if set due to the above changes in cleanup_irq
>>> or when the bootloader leaves it set, gets cleaned up, paving way
>>> for upcoming interrupts to trigger.
>>> 
>>> With this, there is a possibility of unwanted triggering of
>>> interrupt right after the latched bit is cleared - the interrupt
>>> may be left enabled too. To avoid that, clear the enable first
>>> followed by clearing the latched bit in the activate callback.
>>> 
>>> Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
>>> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
>> 
>> Please squash this with the patch that adds cleanup_irq() and
>> rewrite the commit text to combine details from both.
> Sure. Will squash it in the next patch submission.
Patch that adds cleanup_irq is already taken in to the tree.
Lets have this patch as is now.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 13/15] spmi: pmic-arb: add support for HW version 5
  2017-06-01  6:08   ` Stephen Boyd
@ 2017-06-08 11:28     ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-08 11:28 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Greg Kroah-Hartman,
	Subbaraman Narayanamurthy, David Collins, Christophe JAILLET,
	linux-kernel, linux-arm-msm, adharmap, aghayal,
	linux-arm-msm-owner

On 2017-06-01 11:38, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> diff --git a/drivers/spmi/spmi-pmic-arb.c 
>> b/drivers/spmi/spmi-pmic-arb.c
>> index 412481d..b755c24 100644
>> --- a/drivers/spmi/spmi-pmic-arb.c
>> +++ b/drivers/spmi/spmi-pmic-arb.c
>> @@ -112,7 +123,8 @@ enum pmic_arb_cmd_op_code {
>> 
>>  struct apid_data {
>>  	u16		ppid;
>> -	u8		owner;
>> +	u8		write_owner;
>> +	u8		irq_owner;
> 
> How about irq_ee and write_ee instead?
> 
Sure. will change it in the subsequent patch.
>>  };
>> 
>>  /**
>>  static inline void pmic_arb_base_write(struct spmi_pmic_arb *pa,
>> @@ -705,11 +724,18 @@ static int 
>> qpnpint_irq_domain_dt_translate(struct irq_domain *d,
>>  			(intspec[1] << 8), &apid);
>>  	if (rc < 0) {
>>  		dev_err(&pa->spmic->dev,
>> -		"failed to xlate sid = 0x%x, periph = 0x%x, irq = %x rc = %d\n",
>> +		"failed to xlate sid = 0x%x, periph = 0x%x, irq = %u rc = %d\n",
> 
> What is this change? Also, use %#x instead of 0x%x and the "
> should line up with the ( on the previous line.
> 
Sure. will change it in the subsequent patch.
>>  		intspec[0], intspec[1], intspec[2], rc);
>>  		return rc;
>>  	}
>> 
>> +	if (pa->apid_data[apid].irq_owner != pa->ee) {
>> +		dev_err(&pa->spmic->dev, "failed to xlate sid = 0x%x, periph = 
>> 0x%x, irq = %u: ee=%u but owner=%u\n",
>> +			intspec[0], intspec[1], intspec[2], pa->ee,
>> +			pa->apid_data[apid].irq_owner);
>> +		return -ENODEV;
>> +	}
>> +
>>  	/* Keep track of {max,min}_apid for bounding search during interrupt 
>> */
>>  	if (apid > pa->max_apid)
>>  		pa->max_apid = apid;
>> @@ -814,9 +841,11 @@ static u16 pmic_arb_find_apid(struct 
>> spmi_pmic_arb *pa, u16 ppid)
>>  	for (apid = pa->last_apid; apid < pa->max_periph; apid++) {
>>  		regval = readl_relaxed(pa->cnfg +
>>  				      SPMI_OWNERSHIP_TABLE_REG(apid));
>> -		pa->apid_data[apid].owner = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
>> +		pa->apid_data[apid].irq_owner
>> +			= SPMI_OWNERSHIP_PERIPH2OWNER(regval);
>> +		pa->apid_data[apid].write_owner = pa->apid_data[apid].irq_owner;
> 
> Please use a local variable pointer *apid.
> 
Sure. will change it in the subsequent patch.
>> 
>> -		offset = PMIC_ARB_REG_CHNL(apid);
>> +		offset = pa->ver_ops->channel_map_offset(apid);
>>  		if (offset >= pa->core_size)
>>  			break;
>> 
>> @@ -854,27 +883,110 @@ static u16 pmic_arb_find_apid(struct 
>> spmi_pmic_arb *pa, u16 ppid)
>>  	return 0;
>>  }
>> 
>> +static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pa)
>> +{
>> +	u32 regval, offset;
>> +	u16 apid, prev_apid, ppid;
>> +	bool valid, is_irq_owner;
>> +
>> +	/*
>> +	 * PMIC_ARB_REG_CHNL is a table in HW mapping APID (channel) to 
>> PPID.
>> +	 * ppid_to_apid is an in-memory invert of that table.  In order to 
>> allow
>> +	 * multiple EE's to write to a single PPID in arbiter version 5, 
>> there
> 
> Drop the apostrophe   ^
> 
Ok. will change it in the subsequent patch.
>> +	 * is more than one APID mapped to each PPID.  The owner field for 
>> each
>> +	 * of these mappings specifies the EE which is allowed to write to 
>> the
>> +	 * APID.  The owner of the last (highest) APID for a given PPID will
>> +	 * receive interrupts from the PPID.
>> +	 */
>> +	for (apid = 0; apid < pa->max_periph; apid++) {
>> +		offset = pa->ver_ops->channel_map_offset(apid);
>> +		if (offset >= pa->core_size)
>> +			break;
>> +
>> +		regval = readl_relaxed(pa->core + offset);
>> +		if (!regval)
>> +			continue;
>> +		ppid = (regval >> 8) & PMIC_ARB_PPID_MASK;
>> +		is_irq_owner = PMIC_ARB_CHAN_IS_IRQ_OWNER(regval);
>> +
>> +		regval = readl_relaxed(pa->cnfg +
>> +				      SPMI_OWNERSHIP_TABLE_REG(apid));
>> +		pa->apid_data[apid].write_owner
>> +			= SPMI_OWNERSHIP_PERIPH2OWNER(regval);
> 
> Please use a pointer like *apid and *prev where *apid is
> incremented during the for-loop. That way we have shorter lines
> of code:
> 
> 		apid->write_owner = SPMI_OWNERSHIP_TABLE_REG(regval);
> 
> and
> 
> 		if (valid && is_irq_owner && prev->write_owner == pa->ee) {
> 
> obviously the existing apid will need to be renamed to i, but
> that's ok because it's a counter.
> 
Sure. will do it in the subsequent patch..
>> +
>> +		pa->apid_data[apid].irq_owner = is_irq_owner ?
>> +			pa->apid_data[apid].write_owner : INVALID_EE;
>> +
>> +		valid = pa->ppid_to_apid[ppid] & PMIC_ARB_CHAN_VALID;
>> +		prev_apid = pa->ppid_to_apid[ppid] & ~PMIC_ARB_CHAN_VALID;
>> +
>> +		if (valid && is_irq_owner &&
>> +		    pa->apid_data[prev_apid].write_owner == pa->ee) {
>> +			/*
>> +			 * Duplicate PPID mapping after the one for this EE;
>> +			 * override the irq owner
>> +			 */
>> +			pa->apid_data[prev_apid].irq_owner
>> +				= pa->apid_data[apid].irq_owner;
>> +		} else if (!valid || is_irq_owner) {
>> +			/* First PPID mapping or duplicate for another EE */
>> +			pa->ppid_to_apid[ppid] = apid | PMIC_ARB_CHAN_VALID;
>> +		}
>> +
>> +		pa->apid_data[apid].ppid = ppid;
>> +		pa->last_apid = apid;
>> +	}
>> +
>> +	/* Dump the mapping table for debug purposes. */
>> +	dev_dbg(&pa->spmic->dev, "PPID APID Write-EE IRQ-EE\n");
>> +	for (ppid = 0; ppid < PMIC_ARB_MAX_PPID; ppid++) {
>> +		valid = pa->ppid_to_apid[ppid] & PMIC_ARB_CHAN_VALID;
>> +		apid = pa->ppid_to_apid[ppid] & ~PMIC_ARB_CHAN_VALID;
>> +
>> +		if (valid)
>> +			dev_dbg(&pa->spmic->dev, "0x%03X %3u %2u %2u\n",
> 
> Same %#x story here.
> 
Sure. will change it in the subsequent patch.
>> +				ppid, apid, pa->apid_data[apid].write_owner,
>> +				pa->apid_data[apid].irq_owner);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> 
>> @@ -887,6 +999,27 @@ static u16 pmic_arb_find_apid(struct 
>> spmi_pmic_arb *pa, u16 ppid)
>>  	return 0;
>>  }
>> 
>> +/*
>> + * v5 offset per ee and per apid for observer channels and per apid 
>> for
>> + * read/write channels.
>> + */
>> +static int
>> +pmic_arb_offset_v5(struct spmi_pmic_arb *pa, u8 sid, u16 addr,
>> +		   enum pmic_arb_channel ch_type, u32 *offset)
>> +{
>> +	u16 apid;
>> +	int rc;
>> +
>> +	rc = pmic_arb_ppid_to_apid_v5(pa, sid, addr, &apid);
>> +	if (rc < 0)
>> +		return rc;
>> +
>> +	*offset = (ch_type == PMIC_ARB_CHANNEL_OBS)
>> +			? 0x10000 * pa->ee + 0x80 * apid
>> +			: 0x10000 * apid;
> 
> Please use a switch statement to handle the enum here. That way
> we can get compiler checking to make sure all enumerations are
> handled.
> 
Sure. will change it in the subsequent patch.
>> +	return 0;
>> +}
>> +
>>  static u32 pmic_arb_fmt_cmd_v1(u8 opc, u8 sid, u16 addr, u8 bc)
>>  {
>>  	return (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
>> @@ -1033,11 +1213,14 @@ static int spmi_pmic_arb_probe(struct 
>> platform_device *pdev)
>> 
>>  		if (hw_ver < PMIC_ARB_VERSION_V3_MIN)
>>  			pa->ver_ops = &pmic_arb_v2;
>> -		else
>> +		else if (hw_ver < PMIC_ARB_VERSION_V5_MIN)
>>  			pa->ver_ops = &pmic_arb_v3;
>> +		else
>> +			pa->ver_ops = &pmic_arb_v5;
>> 
>> -		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL(0) */
>> -		pa->max_periph = (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;
>> +		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL0 */
>> +		pa->max_periph
>> +		     = (pa->core_size - pa->ver_ops->channel_map_offset(0)) / 4;
> 
> This is really ugly. Please grow a local variable so we can keep
> things on one line.
> 
Ok. will change it in the subsequent patch.
>> 
>>  		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>>  						   "obsrvr");
>> @@ -1074,6 +1257,14 @@ static int spmi_pmic_arb_probe(struct 
>> platform_device *pdev)
>>  		err = PTR_ERR(pa->intr);
>>  		goto err_put_ctrl;
>>  	}
>> +	pa->acc_status = pa->intr;
>> +
>> +	/*
>> +	 * PMIC arbiter v5 groups the IRQ control registers in the same 
>> hardware
>> +	 * module as the read/write channels.
>> +	 */
>> +	if (hw_ver >= PMIC_ARB_VERSION_V5_MIN)
>> +		pa->intr = pa->wr_base;
> 
> There's some weird things going on here. How about we make the
> version ops return an __iomem pointer to the address instead of
> an offset? That way we don't need to care what pa->intr is or add
> pa->acc_status? That could be a patch early in the series that
> adjusts the ops to return an iomem pointer, and perhaps also
> update the 'n' variable to be 16 instead of 8 bits. We can also
> express errors through iomem pointers with IS_ERR() checks, so it
> nicely removes the need to retrieve offsets through references
> sometimes too.
Yes. This looks good. Will change it in the subsequent patch series.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 11/15] spmi: spmi-pmic-arb: enable the SPMI interrupt as a wakeup source
  2017-05-31 17:13   ` Stephen Boyd
@ 2017-06-08 11:30     ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-08 11:30 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET, David Collins,
	Subbaraman Narayanamurthy, linux-kernel, linux-arm-msm, adharmap,
	aghayal, Nicholas Troast, linux-arm-msm-owner

On 2017-05-31 22:43, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> Currently the SPMI interrupt will not wake the device. Enable this
>> interrupt as a wakeup source.
>> 
>> Signed-off-by: Nicholas Troast <ntroast@codeaurora.org>
>> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
>> ---
>>  drivers/spmi/spmi-pmic-arb.c | 1 +
>>  1 file changed, 1 insertion(+)
>> 
>> diff --git a/drivers/spmi/spmi-pmic-arb.c 
>> b/drivers/spmi/spmi-pmic-arb.c
>> index 0deac33..2afe359 100644
>> --- a/drivers/spmi/spmi-pmic-arb.c
>> +++ b/drivers/spmi/spmi-pmic-arb.c
>> @@ -1140,6 +1140,7 @@ static int spmi_pmic_arb_probe(struct 
>> platform_device *pdev)
>>  	}
>> 
>>  	irq_set_chained_handler_and_data(pa->irq, pmic_arb_chained_irq, pa);
>> +	enable_irq_wake(pa->irq);
> 
> Why don't we do this through an irq_set_wake callback in the
> irqchip? That way, we don't mark this irq as wakeup if any child
> irqs aren't marked as wakeup.
Yes. This looks cleaner. Will change it in the subsequent patch.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 01/15] spmi: pmic_arb: block access of invalid read and writes
  2017-05-31  0:33   ` Stephen Boyd
@ 2017-06-12 11:26     ` kgunda
  2017-06-13  2:09       ` Stephen Boyd
  0 siblings, 1 reply; 62+ messages in thread
From: kgunda @ 2017-06-12 11:26 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET,
	Subbaraman Narayanamurthy, David Collins, linux-kernel,
	linux-arm-msm, adharmap, aghayal, linux-arm-msm-owner

On 2017-05-31 06:03, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> 
>> The system crashes due to bad access when reading from an non 
>> configured
>> peripheral and when writing to peripheral which is not owned by 
>> current
>> ee. This patch verifies ownership to avoid crashing on
>> write.
> 
> What systems? As far as I know we don't have any bad accesses
> happening right now. If they are happening, we should fix the
> code that's accessing hardware that isn't owned by them.
> 
This change greatly improves the debugging effort for developers by 
printing
a very simple and clear error message when an invalid SPMI access occurs
(due to bad DT configuration, bad bootloader SPMI permission 
configurations,
or other issues).  Without this change, such accesses will cause XPU 
violations
that crash the system and require extensive effort to decode.

>> For reads, since the forward mapping table, data_channel->ppid, is
>> towards the end of the block, we use the core size to figure the
>> max number of ppids supported. The table starts at an offset of 0x800
>> within the block, so size - 0x800 will give us the area used by the
>> table. Since each table is 4 bytes long (core_size - 0x800) / 4 will
>> gives us the number of data_channel supported.
>> This new protection is functional on hw v2.
> 
> Which brings us to the next question which is why do we need this
> patch at all? We aren't probing hardware to see what we have
> access to and then populating device structures based on that.
> Instead, we're just populating DT nodes that we've hardcoded in
> the dts files, so I'm a little lost on why we would have a node
> in there that we couldn't access. Please add such details to the
> commit text.
> 
invalid SPMI access occurs due to bad DT configuration, bad bootloader 
SPMI
permission configurations, or other issues. This change reduces the 
debugging
effort for developers by printing clear error message when an invalid 
SPMI
access occurs.
>> 
>> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
>> ---
>>  drivers/spmi/spmi-pmic-arb.c | 84 
>> +++++++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 83 insertions(+), 1 deletion(-)
>> 
>> diff --git a/drivers/spmi/spmi-pmic-arb.c 
>> b/drivers/spmi/spmi-pmic-arb.c
>> index 5ec3a59..df463d4 100644
>> --- a/drivers/spmi/spmi-pmic-arb.c
>> +++ b/drivers/spmi/spmi-pmic-arb.c
>> @@ -111,6 +111,7 @@ enum pmic_arb_cmd_op_code {
>>   * @ee:			the current Execution Environment
>>   * @min_apid:		minimum APID (used for bounding IRQ search)
>>   * @max_apid:		maximum APID
>> + * @max_periph:		maximum number of PMIC peripherals supported by HW.
> 
> Nitpick: Most of these lines don't end with a full-stop.
> 
Will address in the next clean up patch.
>>   * @mapping_table:	in-memory copy of PPID -> APID mapping table.
>>   * @domain:		irq domain object for PMIC IRQ domain
>>   * @spmic:		SPMI controller object
>> @@ -132,6 +133,7 @@ struct spmi_pmic_arb_dev {
>>  	u8			ee;
>>  	u16			min_apid;
>>  	u16			max_apid;
>> +	u16			max_periph;
>>  	u32			*mapping_table;
>>  	DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS);
>>  	struct irq_domain	*domain;
>> @@ -140,11 +142,13 @@ struct spmi_pmic_arb_dev {
>>  	const struct pmic_arb_ver_ops *ver_ops;
>>  	u16			*ppid_to_chan;
>>  	u16			last_channel;
>> +	u8			*chan_to_owner;
> 
> And we didn't document this one.
> 
Will document in the next clean up patch.
>>  };
>> 
>>  /**
>>   * pmic_arb_ver: version dependent functionality.
>>   *
>> + * @mode:	access rights to specified pmic peripheral.
>>   * @non_data_cmd:	on v1 issues an spmi non-data command.
>>   *			on v2 no HW support, returns -EOPNOTSUPP.
>>   * @offset:		on v1 offset of per-ee channel.
>> @@ -160,6 +164,8 @@ struct spmi_pmic_arb_dev {
>>   *			on v2 offset of SPMI_PIC_IRQ_CLEARn.
>>   */
>>  struct pmic_arb_ver_ops {
>> +	int (*mode)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
>> +			mode_t *mode);
>>  	/* spmi commands (read_cmd, write_cmd, cmd) functionality */
>>  	int (*offset)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr,
>>  		      u32 *offset);
>> @@ -313,11 +319,23 @@ static int pmic_arb_read_cmd(struct 
>> spmi_controller *ctrl, u8 opc, u8 sid,
>>  	u32 cmd;
>>  	int rc;
>>  	u32 offset;
>> +	mode_t mode;
>> 
>>  	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
>>  	if (rc)
>>  		return rc;
>> 
>> +	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
>> +	if (rc)
>> +		return rc;
>> +
>> +	if (!(mode & S_IRUSR)) {
> 
> Using mode_t for hardware access is odd. Perhaps just come up
> with some sort of READ/WRITE enum instead (if this sort of
> checking is even needed)?
> 
Sure. Will address in the next clean up patch.
>> +		dev_err(&pmic_arb->spmic->dev,
> 
> The dev_err() just after uses ctrl->dev? Why not here?
> 
Will address in the next clean up patch.
>> +			"error: impermissible read from peripheral sid:%d addr:0x%x\n",
>> +			sid, addr);
>> +		return -EPERM;
>> +	}
>> +
>>  	if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
>>  		dev_err(&ctrl->dev,
>>  			"pmic-arb supports 1..%d bytes per trans, but:%zu requested",
>> @@ -364,11 +382,23 @@ static int pmic_arb_write_cmd(struct 
>> spmi_controller *ctrl, u8 opc, u8 sid,
>>  	u32 cmd;
>>  	int rc;
>>  	u32 offset;
>> +	mode_t mode;
>> 
>>  	rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, &offset);
>>  	if (rc)
>>  		return rc;
>> 
>> +	rc = pmic_arb->ver_ops->mode(pmic_arb, sid, addr, &mode);
>> +	if (rc)
>> +		return rc;
>> +
>> +	if (!(mode & S_IWUSR)) {
>> +		dev_err(&pmic_arb->spmic->dev,
> 
> The dev_err() just after uses ctrl->dev? Why not here?
> 
Will address in the next clean up patch.
>> +			"error: impermissible write to peripheral sid:%d addr:0x%x\n",
>> +			sid, addr);
>> +		return -EPERM;
>> +	}
>> +
>>  	if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
>>  		dev_err(&ctrl->dev,
>>  			"pmic-arb supports 1..%d bytes per trans, but:%zu requested",
>> @@ -727,6 +757,13 @@ static int qpnpint_irq_domain_map(struct 
>> irq_domain *d,
>>  	return 0;
>>  }
>> 
>> +static int
>> +pmic_arb_mode_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, 
>> mode_t *mode)
>> +{
>> +	*mode = S_IRUSR | S_IWUSR;
>> +	return 0;
> 
> If mode was only positive then errors could be negative and no
> access could be 0. Then we could just return the mode from the
> function instead of passing a pointer around.
> 
Will modify in the next clean up patch.
>> +}
>> +
>>  /* v1 offset per ee */
>>  static int
>>  pmic_arb_offset_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, 
>> u32 *offset)
>> @@ -745,7 +782,11 @@ static u16 pmic_arb_find_chan(struct 
>> spmi_pmic_arb_dev *pa, u16 ppid)
>>  	 * PMIC_ARB_REG_CHNL is a table in HW mapping channel to ppid.
>>  	 * ppid_to_chan is an in-memory invert of that table.
>>  	 */
>> -	for (chan = pa->last_channel; ; chan++) {
>> +	for (chan = pa->last_channel; chan < pa->max_periph; chan++) {
>> +		regval = readl_relaxed(pa->cnfg +
>> +				      SPMI_OWNERSHIP_TABLE_REG(chan));
>> +		pa->chan_to_owner[chan] = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
>> +
>>  		offset = PMIC_ARB_REG_CHNL(chan);
>>  		if (offset >= pa->core_size)
>>  			break;
> 
> Seems like an unrelated change to the mapping logic?
> 
Will address in the next clean up patch.
>> @@ -767,6 +808,27 @@ static u16 pmic_arb_find_chan(struct 
>> spmi_pmic_arb_dev *pa, u16 ppid)
>>  }
>> 
>> 
>> +static int
>> +pmic_arb_mode_v2(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, 
>> mode_t *mode)
> 
> Probably spmi_pmic_arb_dev should be const here.
> 
Will address in the next clean up patch.
>> +{
>> +	u16 ppid = (sid << 8) | (addr >> 8);
>> +	u16 chan;
>> +	u8 owner;
>> +
>> +	chan = pa->ppid_to_chan[ppid];
>> +	if (!(chan & PMIC_ARB_CHAN_VALID))
>> +		return -ENODEV;
>> +
>> +	*mode = 0;
>> +	*mode |= S_IRUSR;
>> +
>> +	chan &= ~PMIC_ARB_CHAN_VALID;
>> +	owner = pa->chan_to_owner[chan];
>> +	if (owner == pa->ee)
>> +		*mode |= S_IWUSR;
>> +	return 0;
>> +}
>> +
>>  /* v2 offset per ppid (chan) and per ee */
>>  static int
>>  pmic_arb_offset_v2(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr, 
>> u32 *offset)
>> @@ -879,6 +943,12 @@ static int spmi_pmic_arb_probe(struct 
>> platform_device *pdev)
>> 
>>  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
>>  	pa->core_size = resource_size(res);
>> +	if (pa->core_size <= 0x800) {
>> +		dev_err(&pdev->dev, "core_size is smaller than 0x800. Failing 
>> Probe\n");
> 
> Not sure why probe is capitalized.
> 
Will address in the next clean up patch.
>> +		err = -EINVAL;
>> +		goto err_put_ctrl;
>> +	}
>> +
> 
> We don't need these sorts of DT validation checks. Please remove.
> 
Will remove it in the next clean up patch.
>>  	core = devm_ioremap_resource(&ctrl->dev, res);
>>  	if (IS_ERR(core)) {
>>  		err = PTR_ERR(core);
>> @@ -899,6 +969,9 @@ static int spmi_pmic_arb_probe(struct 
>> platform_device *pdev)
>>  		pa->core = core;
>>  		pa->ver_ops = &pmic_arb_v2;
>> 
>> +		/* the apid to ppid table starts at PMIC_ARB_REG_CHNL(0) */
>> +		pa->max_periph =  (pa->core_size - PMIC_ARB_REG_CHNL(0)) / 4;
>> +
>>  		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>>  						   "obsrvr");
>>  		pa->rd_base = devm_ioremap_resource(&ctrl->dev, res);
>> 
>>  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
>> --
>> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a 
>> member of Code Aurora Forum, hosted by The Linux Foundation
>> --
> 
> P.S. Please put a newline in your signature so it doesn't exceed
> 80 columns.
Thanks for the suggestion.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 01/15] spmi: pmic_arb: block access of invalid read and writes
  2017-06-12 11:26     ` kgunda
@ 2017-06-13  2:09       ` Stephen Boyd
  2017-06-14 15:09         ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-06-13  2:09 UTC (permalink / raw)
  To: kgunda
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET,
	Subbaraman Narayanamurthy, David Collins, linux-kernel,
	linux-arm-msm, adharmap, aghayal, linux-arm-msm-owner

On 06/12, kgunda@codeaurora.org wrote:
> On 2017-05-31 06:03, Stephen Boyd wrote:
> >On 05/30, Kiran Gunda wrote:
> >>From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> >>
> >>The system crashes due to bad access when reading from an non
> >>configured
> >>peripheral and when writing to peripheral which is not owned by
> >>current
> >>ee. This patch verifies ownership to avoid crashing on
> >>write.
> >
> >What systems? As far as I know we don't have any bad accesses
> >happening right now. If they are happening, we should fix the
> >code that's accessing hardware that isn't owned by them.
> >
> This change greatly improves the debugging effort for developers by
> printing
> a very simple and clear error message when an invalid SPMI access occurs
> (due to bad DT configuration, bad bootloader SPMI permission
> configurations,
> or other issues).  Without this change, such accesses will cause XPU
> violations
> that crash the system and require extensive effort to decode.

Right, but they're easily detectable because we would know almost
immediately that something isn't working when we integrate a
change. If you update the DT and it stops working, the DT is bad.
If you update the bootloader and it stops working, the bootloader
is bad, etc.

> 
> >>For reads, since the forward mapping table, data_channel->ppid, is
> >>towards the end of the block, we use the core size to figure the
> >>max number of ppids supported. The table starts at an offset of 0x800
> >>within the block, so size - 0x800 will give us the area used by the
> >>table. Since each table is 4 bytes long (core_size - 0x800) / 4 will
> >>gives us the number of data_channel supported.
> >>This new protection is functional on hw v2.
> >
> >Which brings us to the next question which is why do we need this
> >patch at all? We aren't probing hardware to see what we have
> >access to and then populating device structures based on that.
> >Instead, we're just populating DT nodes that we've hardcoded in
> >the dts files, so I'm a little lost on why we would have a node
> >in there that we couldn't access. Please add such details to the
> >commit text.
> >
> invalid SPMI access occurs due to bad DT configuration, bad
> bootloader SPMI
> permission configurations, or other issues. This change reduces the
> debugging
> effort for developers by printing clear error message when an
> invalid SPMI
> access occurs.

Well we also take an overhead on every read/write. Sure things
are slow so the overhead is negligible, but the permissions are
on a peripheral id basis, so really we should look into _not_
populating devices that aren't accessible in the first place.
Then we move the checks out of the read/write path and to a more
logical place whereby we prevent a driver from attempting to even
attach to read or write a register that is protected.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 14/15] spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq
  2017-06-06 11:27       ` kgunda
@ 2017-06-13  2:10         ` Stephen Boyd
  2017-07-18 11:53           ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-06-13  2:10 UTC (permalink / raw)
  To: kgunda
  Cc: Abhijeet Dharmapurikar, David Collins, Christophe JAILLET,
	Subbaraman Narayanamurthy, linux-kernel, linux-arm-msm, adharmap,
	aghayal, linux-arm-msm-owner

On 06/06, kgunda@codeaurora.org wrote:
> On 2017-06-02 12:56, kgunda@codeaurora.org wrote:
> >On 2017-05-31 23:23, Stephen Boyd wrote:
> >>On 05/30, Kiran Gunda wrote:
> >>>From: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
> >>>
> >>>Currently, cleanup_irq() is invoked when a peripheral's interrupt
> >>>fires and there is no mapping present in the interrupt domain of
> >>>spmi interrupt controller.
> >>>
> >>>The cleanup_irq clears the arbiter bit, clears the pmic interrupt
> >>>and disables it at the pmic in that order. The last disable in
> >>>cleanup_irq races with request_irq() in that it stomps over the
> >>>enable issued by request_irq. Fix this by not writing to the pmic
> >>>in cleanup_irq. The latched bit will be left set in the pmic,
> >>>which will not send us more interrupts even if the enable bit
> >>>stays enabled.
> >>>
> >>>When a client wants to request an interrupt, use the activate
> >>>callback on the irq_domain to clear latched bit. This ensures
> >>>that the latched, if set due to the above changes in cleanup_irq
> >>>or when the bootloader leaves it set, gets cleaned up, paving way
> >>>for upcoming interrupts to trigger.
> >>>
> >>>With this, there is a possibility of unwanted triggering of
> >>>interrupt right after the latched bit is cleared - the interrupt
> >>>may be left enabled too. To avoid that, clear the enable first
> >>>followed by clearing the latched bit in the activate callback.
> >>>
> >>>Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
> >>>Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
> >>
> >>Please squash this with the patch that adds cleanup_irq() and
> >>rewrite the commit text to combine details from both.
> >Sure. Will squash it in the next patch submission.
> Patch that adds cleanup_irq is already taken in to the tree.
> Lets have this patch as is now.

Is this the one with the kbuild error? IRQ domains are not always
there, so I don't know how this is expected to work.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 05/15] spmi: pmic-arb: cleanup unrequested irqs
  2017-06-06 10:50     ` kgunda
@ 2017-06-13  2:11       ` Stephen Boyd
  2017-06-14 15:04         ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-06-13  2:11 UTC (permalink / raw)
  To: kgunda
  Cc: Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Christophe JAILLET, David Collins, linux-kernel, linux-arm-msm,
	adharmap, aghayal, linux-arm-msm-owner

On 06/06, kgunda@codeaurora.org wrote:
> On 2017-05-31 07:27, Stephen Boyd wrote:
> >On 05/30, Kiran Gunda wrote:
> >>From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> >>
> >>We see a unmapped irqs trigger right around bootup. This could
> >>likely be because the bootloader exited leaving the interrupts
> >>in an unknown or unhandled state.  Ack and mask the interrupt
> >>if one is found. A request_irq later will unmask it and also
> >>setup proper mapping structures.
> >
> >Do we have systems where this is causing an interrupt storm due
> >to a level high interrupt or something? Just plain acking and
> >masking irqs at boot if we don't have an irq descriptor created
> >yet doesn't sound like a good idea, because we'll lose all
> >interrupts that happen before this driver probes?
> >
> Yes. There were instances of an interrupt storm without this patch.
> There is an RT_STATUS register in the  peripheral address space which
> maintains the real time state and can be read by the client driver
> before it registers for the irq. Few client drivers such as charger
> already doing this.

So you're saying that drivers need to read RT_STATUS to know if
they have a pending interrupt before requesting it? That sounds
bogus.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 05/15] spmi: pmic-arb: cleanup unrequested irqs
  2017-06-13  2:11       ` Stephen Boyd
@ 2017-06-14 15:04         ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-14 15:04 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Subbaraman Narayanamurthy,
	Christophe JAILLET, David Collins, linux-kernel, linux-arm-msm,
	adharmap, aghayal, linux-arm-msm-owner

On 2017-06-13 07:41, Stephen Boyd wrote:
> On 06/06, kgunda@codeaurora.org wrote:
>> On 2017-05-31 07:27, Stephen Boyd wrote:
>> >On 05/30, Kiran Gunda wrote:
>> >>From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> >>
>> >>We see a unmapped irqs trigger right around bootup. This could
>> >>likely be because the bootloader exited leaving the interrupts
>> >>in an unknown or unhandled state.  Ack and mask the interrupt
>> >>if one is found. A request_irq later will unmask it and also
>> >>setup proper mapping structures.
>> >
>> >Do we have systems where this is causing an interrupt storm due
>> >to a level high interrupt or something? Just plain acking and
>> >masking irqs at boot if we don't have an irq descriptor created
>> >yet doesn't sound like a good idea, because we'll lose all
>> >interrupts that happen before this driver probes?
>> >
>> Yes. There were instances of an interrupt storm without this patch.
>> There is an RT_STATUS register in the  peripheral address space which
>> maintains the real time state and can be read by the client driver
>> before it registers for the irq. Few client drivers such as charger
>> already doing this.
> 
> So you're saying that drivers need to read RT_STATUS to know if
> they have a pending interrupt before requesting it? That sounds
> bogus.
In  many cases a PMIC module driver does need to know the initial state 
of
the hardware during driver initialization and the RT_STATUS register 
indicates
this (irrespective of the IRQ_EN status).  The  reset value of IRQ_EN = 
0 and if
an event occurs before we request an IRQ, there is no way to know the 
initial state
even after we request this irq as there will be no pending interrupt 
because the
HW default value of IRQ_EN = 0. This can be known only through reading 
the RT_STATUS.

I understand your concern of clearing the IRQ before we request it does 
not seem
a clean way, do you have any other recommendation of this could be 
handled ?

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 01/15] spmi: pmic_arb: block access of invalid read and writes
  2017-06-13  2:09       ` Stephen Boyd
@ 2017-06-14 15:09         ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-14 15:09 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET,
	Subbaraman Narayanamurthy, David Collins, linux-kernel,
	linux-arm-msm, adharmap, aghayal, linux-arm-msm-owner

On 2017-06-13 07:39, Stephen Boyd wrote:
> On 06/12, kgunda@codeaurora.org wrote:
>> On 2017-05-31 06:03, Stephen Boyd wrote:
>> >On 05/30, Kiran Gunda wrote:
>> >>From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> >>
>> >>The system crashes due to bad access when reading from an non
>> >>configured
>> >>peripheral and when writing to peripheral which is not owned by
>> >>current
>> >>ee. This patch verifies ownership to avoid crashing on
>> >>write.
>> >
>> >What systems? As far as I know we don't have any bad accesses
>> >happening right now. If they are happening, we should fix the
>> >code that's accessing hardware that isn't owned by them.
>> >
>> This change greatly improves the debugging effort for developers by
>> printing
>> a very simple and clear error message when an invalid SPMI access 
>> occurs
>> (due to bad DT configuration, bad bootloader SPMI permission
>> configurations,
>> or other issues).  Without this change, such accesses will cause XPU
>> violations
>> that crash the system and require extensive effort to decode.
> 
> Right, but they're easily detectable because we would know almost
> immediately that something isn't working when we integrate a
> change. If you update the DT and it stops working, the DT is bad.
> If you update the bootloader and it stops working, the bootloader
> is bad, etc.
> 
Ok. Will send a patch to remove this code in the next series.
>> 
>> >>For reads, since the forward mapping table, data_channel->ppid, is
>> >>towards the end of the block, we use the core size to figure the
>> >>max number of ppids supported. The table starts at an offset of 0x800
>> >>within the block, so size - 0x800 will give us the area used by the
>> >>table. Since each table is 4 bytes long (core_size - 0x800) / 4 will
>> >>gives us the number of data_channel supported.
>> >>This new protection is functional on hw v2.
>> >
>> >Which brings us to the next question which is why do we need this
>> >patch at all? We aren't probing hardware to see what we have
>> >access to and then populating device structures based on that.
>> >Instead, we're just populating DT nodes that we've hardcoded in
>> >the dts files, so I'm a little lost on why we would have a node
>> >in there that we couldn't access. Please add such details to the
>> >commit text.
>> >
>> invalid SPMI access occurs due to bad DT configuration, bad
>> bootloader SPMI
>> permission configurations, or other issues. This change reduces the
>> debugging
>> effort for developers by printing clear error message when an
>> invalid SPMI
>> access occurs.
> 
> Well we also take an overhead on every read/write. Sure things
> are slow so the overhead is negligible, but the permissions are
> on a peripheral id basis, so really we should look into _not_
> populating devices that aren't accessible in the first place.
> Then we move the checks out of the read/write path and to a more
> logical place whereby we prevent a driver from attempting to even
> attach to read or write a register that is protected.
Ok. Will remove this code in the next patch series and try to implement 
it
as per your suggestion.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 09/15] spmi: pmic-arb: check apid enabled before calling the handler
  2017-05-31 20:39   ` Stephen Boyd
@ 2017-06-14 15:38     ` kgunda
  2017-06-16 21:11       ` Stephen Boyd
  0 siblings, 1 reply; 62+ messages in thread
From: kgunda @ 2017-06-14 15:38 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, David Collins, Subbaraman Narayanamurthy,
	Christophe JAILLET, linux-kernel, linux-arm-msm, adharmap,
	aghayal, linux-arm-msm-owner

On 2017-06-01 02:09, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> 
>> The driver currently invokes the apid handler (periph_handler())
> 
> You mean periph_interrupt()?
> 
Yes.
>> once it sees that the summary status bit for that apid is set.
>> 
>> However the hardware is designed to set that bit even if the apid
>> interrupts are disabled. The driver should check whether the apid
>> is indeed enabled before calling the apid handler.
> 
> Really? Wow that is awful. Or is this because ACC_ENABLE bit is
> always set now and never cleared?
> 
Yes. It is awful. It is not because of the ACC_ENABLE bit is set.
>> 
>> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
>> ---
>>  drivers/spmi/spmi-pmic-arb.c | 10 +++++++---
>>  1 file changed, 7 insertions(+), 3 deletions(-)
>> 
>> diff --git a/drivers/spmi/spmi-pmic-arb.c 
>> b/drivers/spmi/spmi-pmic-arb.c
>> index ad34491..f8638fa 100644
>> --- a/drivers/spmi/spmi-pmic-arb.c
>> +++ b/drivers/spmi/spmi-pmic-arb.c
>> @@ -536,8 +536,8 @@ static void pmic_arb_chained_irq(struct irq_desc 
>> *desc)
>>  	void __iomem *intr = pa->intr;
>>  	int first = pa->min_apid >> 5;
>>  	int last = pa->max_apid >> 5;
>> -	u32 status;
>> -	int i, id;
>> +	u32 status, enable;
>> +	int i, id, apid;
>> 
>>  	chained_irq_enter(chip, desc);
>> 
>> @@ -547,7 +547,11 @@ static void pmic_arb_chained_irq(struct irq_desc 
>> *desc)
>>  		while (status) {
>>  			id = ffs(status) - 1;
>>  			status &= ~BIT(id);
>> -			periph_interrupt(pa, id + i * 32);
>> +			apid = id + i * 32;
>> +			enable = readl_relaxed(intr +
>> +					pa->ver_ops->acc_enable(apid));
> 
> Do we need to read the hardware to figure this out? After earlier
> patches in this series we would never clear the
> SPMI_PIC_ACC_ENABLE_BIT after one of the irqs in a peripheral is
> unmasked for the first time (which looks to be fixing a bug in
> the existing driver BTW). So in practice, this should almost
> always be true.
> 
yes. We have removed clearing the SPMI_PIC_ACC_ENABLE_BIT from the 
irq_mask,
because if we disable this BIT it disables all the peripheral IRQs, 
which we don't want.

Once the peripheral fires the interrupt the summary status bit for that 
peripheral
is set even though the SPMI_PIC_ACC_ENABLE_BIT is not enabled. That's 
why we have to
read this register to not service the interrupt that is not 
requested/enabled yet.
This SPMI_PIC_ACC_ENABLE_BIT is enabled during the irq_unmask which is 
called from request_irq.

> In the one case that it isn't true, we'll be handling some other
> irq for another peripheral and then hardware will tell us there's
> an interrupt for a peripheral that doesn't have any interrupts
> unmasked. We would call periph_interrupt() and then that
> shouldn't see any interrupts in the status register for that
> APID. So we do some more work, but nothing happens still. Did I
> miss something? What is this fixing?

Yes. As you said this fixes the issue of calling the periph_interrupt
for some other irq that is not yet requested and enabled yet.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 09/15] spmi: pmic-arb: check apid enabled before calling the handler
  2017-06-14 15:38     ` kgunda
@ 2017-06-16 21:11       ` Stephen Boyd
  2017-06-21  5:02         ` kgunda
  0 siblings, 1 reply; 62+ messages in thread
From: Stephen Boyd @ 2017-06-16 21:11 UTC (permalink / raw)
  To: kgunda
  Cc: Abhijeet Dharmapurikar, David Collins, Subbaraman Narayanamurthy,
	Christophe JAILLET, linux-kernel, linux-arm-msm, adharmap,
	aghayal, linux-arm-msm-owner

On 06/14, kgunda@codeaurora.org wrote:
> On 2017-06-01 02:09, Stephen Boyd wrote:
> >On 05/30, Kiran Gunda wrote:
> >>From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> >>
> >>The driver currently invokes the apid handler (periph_handler())
> >
> >You mean periph_interrupt()?
> >
> Yes.
> >>once it sees that the summary status bit for that apid is set.
> >>
> >>However the hardware is designed to set that bit even if the apid
> >>interrupts are disabled. The driver should check whether the apid
> >>is indeed enabled before calling the apid handler.
> >
> >Really? Wow that is awful. Or is this because ACC_ENABLE bit is
> >always set now and never cleared?
> >
> Yes. It is awful. It is not because of the ACC_ENABLE bit is set.
> >>
> >>Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
> >>Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
> >>---
> >> drivers/spmi/spmi-pmic-arb.c | 10 +++++++---
> >> 1 file changed, 7 insertions(+), 3 deletions(-)
> >>
> >>diff --git a/drivers/spmi/spmi-pmic-arb.c
> >>b/drivers/spmi/spmi-pmic-arb.c
> >>index ad34491..f8638fa 100644
> >>--- a/drivers/spmi/spmi-pmic-arb.c
> >>+++ b/drivers/spmi/spmi-pmic-arb.c
> >>@@ -536,8 +536,8 @@ static void pmic_arb_chained_irq(struct
> >>irq_desc *desc)
> >> 	void __iomem *intr = pa->intr;
> >> 	int first = pa->min_apid >> 5;
> >> 	int last = pa->max_apid >> 5;
> >>-	u32 status;
> >>-	int i, id;
> >>+	u32 status, enable;
> >>+	int i, id, apid;
> >>
> >> 	chained_irq_enter(chip, desc);
> >>
> >>@@ -547,7 +547,11 @@ static void pmic_arb_chained_irq(struct
> >>irq_desc *desc)
> >> 		while (status) {
> >> 			id = ffs(status) - 1;
> >> 			status &= ~BIT(id);
> >>-			periph_interrupt(pa, id + i * 32);
> >>+			apid = id + i * 32;
> >>+			enable = readl_relaxed(intr +
> >>+					pa->ver_ops->acc_enable(apid));
> >
> >Do we need to read the hardware to figure this out? After earlier
> >patches in this series we would never clear the
> >SPMI_PIC_ACC_ENABLE_BIT after one of the irqs in a peripheral is
> >unmasked for the first time (which looks to be fixing a bug in
> >the existing driver BTW). So in practice, this should almost
> >always be true.
> >
> yes. We have removed clearing the SPMI_PIC_ACC_ENABLE_BIT from the
> irq_mask,
> because if we disable this BIT it disables all the peripheral IRQs,
> which we don't want.

Right, we could reference count it though and only clear and set
the bit when we mask and unmask the last irq in the peripheral.

> 
> Once the peripheral fires the interrupt the summary status bit for
> that peripheral
> is set even though the SPMI_PIC_ACC_ENABLE_BIT is not enabled.
> That's why we have to
> read this register to not service the interrupt that is not
> requested/enabled yet.
> This SPMI_PIC_ACC_ENABLE_BIT is enabled during the irq_unmask which
> is called from request_irq.

Ok. So this is again about handling the case where an interrupt
is pending out of the bootloader?

> 
> >In the one case that it isn't true, we'll be handling some other
> >irq for another peripheral and then hardware will tell us there's
> >an interrupt for a peripheral that doesn't have any interrupts
> >unmasked. We would call periph_interrupt() and then that
> >shouldn't see any interrupts in the status register for that
> >APID. So we do some more work, but nothing happens still. Did I
> >miss something? What is this fixing?
> 
> Yes. As you said this fixes the issue of calling the periph_interrupt
> for some other irq that is not yet requested and enabled yet.


Hmm. I seemed to miss the fact that periph_interrupt() will see
an unmasked interrupt and think it's valid. I thought that only
SPMI_PIC_ACC_ENABLE_BIT was broken, but you're saying that the
status register for a particular peripheral will always latch
interrupts even if we haven't enabled them?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 09/15] spmi: pmic-arb: check apid enabled before calling the handler
  2017-06-16 21:11       ` Stephen Boyd
@ 2017-06-21  5:02         ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-06-21  5:02 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, David Collins, Subbaraman Narayanamurthy,
	Christophe JAILLET, linux-kernel, linux-arm-msm, adharmap,
	aghayal, linux-arm-msm-owner

On 2017-06-17 02:41, Stephen Boyd wrote:
> On 06/14, kgunda@codeaurora.org wrote:
>> On 2017-06-01 02:09, Stephen Boyd wrote:
>> >On 05/30, Kiran Gunda wrote:
>> >>From: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> >>
>> >>The driver currently invokes the apid handler (periph_handler())
>> >
>> >You mean periph_interrupt()?
>> >
>> Yes.
>> >>once it sees that the summary status bit for that apid is set.
>> >>
>> >>However the hardware is designed to set that bit even if the apid
>> >>interrupts are disabled. The driver should check whether the apid
>> >>is indeed enabled before calling the apid handler.
>> >
>> >Really? Wow that is awful. Or is this because ACC_ENABLE bit is
>> >always set now and never cleared?
>> >
>> Yes. It is awful. It is not because of the ACC_ENABLE bit is set.
>> >>
>> >>Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
>> >>Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
>> >>---
>> >> drivers/spmi/spmi-pmic-arb.c | 10 +++++++---
>> >> 1 file changed, 7 insertions(+), 3 deletions(-)
>> >>
>> >>diff --git a/drivers/spmi/spmi-pmic-arb.c
>> >>b/drivers/spmi/spmi-pmic-arb.c
>> >>index ad34491..f8638fa 100644
>> >>--- a/drivers/spmi/spmi-pmic-arb.c
>> >>+++ b/drivers/spmi/spmi-pmic-arb.c
>> >>@@ -536,8 +536,8 @@ static void pmic_arb_chained_irq(struct
>> >>irq_desc *desc)
>> >> 	void __iomem *intr = pa->intr;
>> >> 	int first = pa->min_apid >> 5;
>> >> 	int last = pa->max_apid >> 5;
>> >>-	u32 status;
>> >>-	int i, id;
>> >>+	u32 status, enable;
>> >>+	int i, id, apid;
>> >>
>> >> 	chained_irq_enter(chip, desc);
>> >>
>> >>@@ -547,7 +547,11 @@ static void pmic_arb_chained_irq(struct
>> >>irq_desc *desc)
>> >> 		while (status) {
>> >> 			id = ffs(status) - 1;
>> >> 			status &= ~BIT(id);
>> >>-			periph_interrupt(pa, id + i * 32);
>> >>+			apid = id + i * 32;
>> >>+			enable = readl_relaxed(intr +
>> >>+					pa->ver_ops->acc_enable(apid));
>> >
>> >Do we need to read the hardware to figure this out? After earlier
>> >patches in this series we would never clear the
>> >SPMI_PIC_ACC_ENABLE_BIT after one of the irqs in a peripheral is
>> >unmasked for the first time (which looks to be fixing a bug in
>> >the existing driver BTW). So in practice, this should almost
>> >always be true.
>> >
>> yes. We have removed clearing the SPMI_PIC_ACC_ENABLE_BIT from the
>> irq_mask,
>> because if we disable this BIT it disables all the peripheral IRQs,
>> which we don't want.
> 
> Right, we could reference count it though and only clear and set
> the bit when we mask and unmask the last irq in the peripheral.
> 
Actually we are disabling the interrupt at peripheral level, so i 
believe
disabling the PIC_ACC_EN_BIT is not mandatory.
>> 
>> Once the peripheral fires the interrupt the summary status bit for
>> that peripheral
>> is set even though the SPMI_PIC_ACC_ENABLE_BIT is not enabled.
>> That's why we have to
>> read this register to not service the interrupt that is not
>> requested/enabled yet.
>> This SPMI_PIC_ACC_ENABLE_BIT is enabled during the irq_unmask which
>> is called from request_irq.
> 
> Ok. So this is again about handling the case where an interrupt
> is pending out of the bootloader?
> 
Yes.
>> 
>> >In the one case that it isn't true, we'll be handling some other
>> >irq for another peripheral and then hardware will tell us there's
>> >an interrupt for a peripheral that doesn't have any interrupts
>> >unmasked. We would call periph_interrupt() and then that
>> >shouldn't see any interrupts in the status register for that
>> >APID. So we do some more work, but nothing happens still. Did I
>> >miss something? What is this fixing?
>> 
>> Yes. As you said this fixes the issue of calling the periph_interrupt
>> for some other irq that is not yet requested and enabled yet.
> 
> 
> Hmm. I seemed to miss the fact that periph_interrupt() will see
> an unmasked interrupt and think it's valid. I thought that only
> SPMI_PIC_ACC_ENABLE_BIT was broken, but you're saying that the
> status register for a particular peripheral will always latch
> interrupts even if we haven't enabled them?
Yes. Correct. Both SPMI_PIC_OWNERm_ACC_STATUSn and SPMI_PIC_IRQ_STATUSn
are getting set when the peripheral fires the interrupt, even though we
haven't enable that particular peripheral bit in SPMI_PIC_ACC_ENABLEn 
register.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 15/15] spmi: pmic-arb: instantiate spmi_devices at arch_initcall
  2017-05-31 22:07   ` Stephen Boyd
@ 2017-07-18 11:49     ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-07-18 11:49 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, Christophe JAILLET, Greg Kroah-Hartman,
	Subbaraman Narayanamurthy, David Collins, linux-kernel,
	linux-arm-msm, adharmap, aghayal, linux-arm-msm-owner

On 2017-06-01 03:37, Stephen Boyd wrote:
> On 05/30, Kiran Gunda wrote:
>> @@ -1384,7 +1384,12 @@ static int spmi_pmic_arb_remove(struct 
>> platform_device *pdev)
>>  		.of_match_table = spmi_pmic_arb_match_table,
>>  	},
>>  };
>> -module_platform_driver(spmi_pmic_arb_driver);
>> +
>> +int __init spmi_pmic_arb_init(void)
> 
> Missing static.
> 
>> +{
>> +	return platform_driver_register(&spmi_pmic_arb_driver);
>> +}
>> +arch_initcall(spmi_pmic_arb_init);
> 
> We also lost module removal. Probably nobody tests it, but still
> no mention of that in commit text.
> 
> I'm not sure we need this at all though. Is there something that
> needs to probe early? Indicating what that is in the commit text
> would be helpful.
Dropped out this patch. As this is no more required.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH V1 14/15] spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq
  2017-06-13  2:10         ` Stephen Boyd
@ 2017-07-18 11:53           ` kgunda
  0 siblings, 0 replies; 62+ messages in thread
From: kgunda @ 2017-07-18 11:53 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Abhijeet Dharmapurikar, David Collins, Christophe JAILLET,
	Subbaraman Narayanamurthy, linux-kernel, linux-arm-msm, adharmap,
	aghayal, linux-arm-msm-owner

On 2017-06-13 07:40, Stephen Boyd wrote:
> On 06/06, kgunda@codeaurora.org wrote:
>> On 2017-06-02 12:56, kgunda@codeaurora.org wrote:
>> >On 2017-05-31 23:23, Stephen Boyd wrote:
>> >>On 05/30, Kiran Gunda wrote:
>> >>>From: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
>> >>>
>> >>>Currently, cleanup_irq() is invoked when a peripheral's interrupt
>> >>>fires and there is no mapping present in the interrupt domain of
>> >>>spmi interrupt controller.
>> >>>
>> >>>The cleanup_irq clears the arbiter bit, clears the pmic interrupt
>> >>>and disables it at the pmic in that order. The last disable in
>> >>>cleanup_irq races with request_irq() in that it stomps over the
>> >>>enable issued by request_irq. Fix this by not writing to the pmic
>> >>>in cleanup_irq. The latched bit will be left set in the pmic,
>> >>>which will not send us more interrupts even if the enable bit
>> >>>stays enabled.
>> >>>
>> >>>When a client wants to request an interrupt, use the activate
>> >>>callback on the irq_domain to clear latched bit. This ensures
>> >>>that the latched, if set due to the above changes in cleanup_irq
>> >>>or when the bootloader leaves it set, gets cleaned up, paving way
>> >>>for upcoming interrupts to trigger.
>> >>>
>> >>>With this, there is a possibility of unwanted triggering of
>> >>>interrupt right after the latched bit is cleared - the interrupt
>> >>>may be left enabled too. To avoid that, clear the enable first
>> >>>followed by clearing the latched bit in the activate callback.
>> >>>
>> >>>Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
>> >>>Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
>> >>
>> >>Please squash this with the patch that adds cleanup_irq() and
>> >>rewrite the commit text to combine details from both.
>> >Sure. Will squash it in the next patch submission.
>> Patch that adds cleanup_irq is already taken in to the tree.
>> Lets have this patch as is now.
> 
> Is this the one with the kbuild error? IRQ domains are not always
> there, so I don't know how this is expected to work.
Dropped out this patch as it is related to clearing the interrupts those 
are left enabled
by the boot loader. We thought of clearing all the apps owned interrupts 
in the UEFI itself.

^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2017-07-18 11:53 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-30 12:38 [PATCH V1 00/15]: support for spmi_pmic_arb v3/v5 and bug fixes Kiran Gunda
2017-05-30 12:38 ` Kiran Gunda
2017-05-30 12:38 ` [PATCH V1 01/15] spmi: pmic_arb: block access of invalid read and writes Kiran Gunda
2017-05-31  0:33   ` Stephen Boyd
2017-06-12 11:26     ` kgunda
2017-06-13  2:09       ` Stephen Boyd
2017-06-14 15:09         ` kgunda
2017-05-30 12:38 ` [PATCH V1 02/15] spmi: pmic-arb: rename spmi_pmic_arb_dev to spmi_pmic_arb Kiran Gunda
2017-05-31  0:46   ` Stephen Boyd
2017-06-01 16:11     ` kgunda
2017-06-02 18:29       ` Stephen Boyd
2017-06-05  6:28         ` kgunda
2017-05-30 12:38 ` [PATCH V1 03/15] spmi: pmic-arb: fix inconsistent use of apid and chan Kiran Gunda
2017-05-31  1:31   ` Stephen Boyd
2017-06-01 16:37     ` kgunda
2017-05-30 12:38 ` [PATCH V1 04/15] spmi: pmic-arb: optimize table lookups Kiran Gunda
2017-05-31  1:44   ` Stephen Boyd
2017-06-01 16:53     ` kgunda
2017-06-02 18:31       ` Stephen Boyd
2017-06-05  6:33         ` kgunda
2017-05-30 12:38 ` [PATCH V1 05/15] spmi: pmic-arb: cleanup unrequested irqs Kiran Gunda
2017-05-31  1:57   ` Stephen Boyd
2017-06-06 10:50     ` kgunda
2017-06-13  2:11       ` Stephen Boyd
2017-06-14 15:04         ` kgunda
2017-05-30 12:38 ` [PATCH V1 06/15] spmi: pmic-arb: fix missing interrupts Kiran Gunda
2017-05-31  2:00   ` Stephen Boyd
2017-06-01 17:06     ` kgunda
2017-05-30 12:38 ` [PATCH V1 07/15] spmi: pmic-arb: clear the latched status of the interrupt Kiran Gunda
2017-05-31 22:03   ` Stephen Boyd
2017-06-06 10:55     ` kgunda
2017-05-30 12:38 ` [PATCH V1 08/15] spmi: pmic_arb: use appropriate flow handler Kiran Gunda
2017-05-31 19:03   ` Stephen Boyd
2017-06-06 10:57     ` kgunda
2017-05-30 12:38 ` [PATCH V1 09/15] spmi: pmic-arb: check apid enabled before calling the handler Kiran Gunda
2017-05-31 20:39   ` Stephen Boyd
2017-06-14 15:38     ` kgunda
2017-06-16 21:11       ` Stephen Boyd
2017-06-21  5:02         ` kgunda
2017-05-30 12:38 ` [PATCH V1 10/15] spmi: pmic_arb: add support for PMIC bus arbiter v3 Kiran Gunda
2017-05-31 22:18   ` Stephen Boyd
2017-06-06 11:10     ` kgunda
2017-05-30 12:38 ` [PATCH V1 11/15] spmi: spmi-pmic-arb: enable the SPMI interrupt as a wakeup source Kiran Gunda
2017-05-31 17:13   ` Stephen Boyd
2017-06-08 11:30     ` kgunda
2017-05-30 12:39 ` [PATCH V1 12/15] spmi-pmic-arb: fix a possible null pointer dereference Kiran Gunda
2017-05-31 17:29   ` Stephen Boyd
2017-06-02  7:13     ` kgunda
2017-05-30 12:39 ` [PATCH V1 13/15] spmi: pmic-arb: add support for HW version 5 Kiran Gunda
2017-06-01  6:08   ` Stephen Boyd
2017-06-08 11:28     ` kgunda
2017-05-30 12:39 ` [PATCH V1 14/15] spmi: pmic-arb: do not ack and clear peripheral interrupts in cleanup_irq Kiran Gunda
2017-05-30 22:23   ` kbuild test robot
2017-05-30 22:23     ` kbuild test robot
2017-05-31 17:53   ` Stephen Boyd
2017-06-02  7:26     ` kgunda
2017-06-06 11:27       ` kgunda
2017-06-13  2:10         ` Stephen Boyd
2017-07-18 11:53           ` kgunda
2017-05-30 12:39 ` [PATCH V1 15/15] spmi: pmic-arb: instantiate spmi_devices at arch_initcall Kiran Gunda
2017-05-31 22:07   ` Stephen Boyd
2017-07-18 11:49     ` kgunda

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.