linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/7] Modernize pm8921 with irqdomains, regmap, DT
@ 2013-12-23 20:45 Stephen Boyd
  2013-12-23 20:45 ` [PATCH v2 1/7] mfd: Move pm8xxx-irq.c contents into only driver that uses it Stephen Boyd
                   ` (6 more replies)
  0 siblings, 7 replies; 23+ messages in thread
From: Stephen Boyd @ 2013-12-23 20:45 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Mark Brown,
	devicetree-u79uwXL29TY76Z2rM5mHXA

These patches lay the groundwork for converting the pm8921 sub-devices
to devicetree as well as simplify the API by migrating the core code
to use the regmap API instead of the custom pm8xxx read/write wrapper.

Changes since v1:
 * First 3 cleanup patches dropped because they're applied upstream
 * New regmap read/write helpers
 * New patch for DT match table
 * New binding document

Stephen Boyd (7):
  mfd: Move pm8xxx-irq.c contents into only driver that uses it
  mfd: pm8921: Update for genirq changes
  mfd: pm8921: Migrate to irqdomains
  mfd: ssbi: Add regmap read/write helpers
  mfd: pm8921: Use ssbi regmap
  mfd: pm8921: Add DT match table
  devicetree: bindings: Document PM8921/8058 PMICs

 .../devicetree/bindings/mfd/qcom,pm8xxx.txt        |  63 +++
 drivers/mfd/Kconfig                                |  12 +-
 drivers/mfd/pm8921-core.c                          | 424 ++++++++++++++++++---
 drivers/mfd/pm8xxx-irq.c                           | 371 ------------------
 drivers/mfd/ssbi.c                                 |  13 +
 include/linux/mfd/pm8xxx/irq.h                     |  59 ---
 include/linux/mfd/pm8xxx/pm8921.h                  |  30 --
 include/linux/ssbi.h                               |   3 +
 8 files changed, 449 insertions(+), 526 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt
 delete mode 100644 drivers/mfd/pm8xxx-irq.c
 delete mode 100644 include/linux/mfd/pm8xxx/irq.h
 delete mode 100644 include/linux/mfd/pm8xxx/pm8921.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 1/7] mfd: Move pm8xxx-irq.c contents into only driver that uses it
  2013-12-23 20:45 [PATCH v2 0/7] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
@ 2013-12-23 20:45 ` Stephen Boyd
  2014-01-06 14:47   ` Lee Jones
  2013-12-23 20:45 ` [PATCH v2 2/7] mfd: pm8921: Update for genirq changes Stephen Boyd
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Stephen Boyd @ 2013-12-23 20:45 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel

The pm8xxx-irq.c code is practically mandatory given that the
pm8921-core driver will WARN about it missing and the Kconfig
marks it as default y when a PM8xxx chips is enabled. The only
reason the file was split out was because we planned to support
other pm8xxx chips with different pm8xxx-core.c files. Now that
we have DT on ARM this isn't necessary because we should be able
to support all the ssbi based PM8xxx chips in one driver and one
file with no data bloat. Let's move this code into the only
driver that uses it right now (pm8921) so that it's always compiled when
needed. In the future we can rename pm8921-core.c to something
more generic.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/mfd/Kconfig            |  10 --
 drivers/mfd/pm8921-core.c      | 348 ++++++++++++++++++++++++++++++++++++++
 drivers/mfd/pm8xxx-irq.c       | 371 -----------------------------------------
 include/linux/mfd/pm8xxx/irq.h |  23 ---
 4 files changed, 348 insertions(+), 404 deletions(-)
 delete mode 100644 drivers/mfd/pm8xxx-irq.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 914c3d1..9ee4ce6 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -466,16 +466,6 @@ config MFD_PM8921_CORE
 	  Say M here if you want to include support for PM8921 chip as a module.
 	  This will build a module called "pm8921-core".
 
-config MFD_PM8XXX_IRQ
-	bool "Qualcomm PM8xxx IRQ features"
-	depends on MFD_PM8XXX
-	default y if MFD_PM8XXX
-	help
-	  This is the IRQ driver for Qualcomm PM 8xxx PMIC chips.
-
-	  This is required to use certain other PM 8xxx features, such as GPIO
-	  and MPP.
-
 config MFD_RDC321X
 	tristate "RDC R-321x southbridge"
 	select MFD_CORE
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index a6841f7..669f8f2 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -14,6 +14,8 @@
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -22,15 +24,361 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pm8xxx/irq.h>
+
+#define	SSBI_REG_ADDR_IRQ_BASE		0x1BB
+
+#define	SSBI_REG_ADDR_IRQ_ROOT		(SSBI_REG_ADDR_IRQ_BASE + 0)
+#define	SSBI_REG_ADDR_IRQ_M_STATUS1	(SSBI_REG_ADDR_IRQ_BASE + 1)
+#define	SSBI_REG_ADDR_IRQ_M_STATUS2	(SSBI_REG_ADDR_IRQ_BASE + 2)
+#define	SSBI_REG_ADDR_IRQ_M_STATUS3	(SSBI_REG_ADDR_IRQ_BASE + 3)
+#define	SSBI_REG_ADDR_IRQ_M_STATUS4	(SSBI_REG_ADDR_IRQ_BASE + 4)
+#define	SSBI_REG_ADDR_IRQ_BLK_SEL	(SSBI_REG_ADDR_IRQ_BASE + 5)
+#define	SSBI_REG_ADDR_IRQ_IT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 6)
+#define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
+#define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
+
+#define	PM_IRQF_LVL_SEL			0x01	/* level select */
+#define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
+#define	PM_IRQF_MASK_RE			0x04	/* mask rising edge */
+#define	PM_IRQF_CLR			0x08	/* clear interrupt */
+#define	PM_IRQF_BITS_MASK		0x70
+#define	PM_IRQF_BITS_SHIFT		4
+#define	PM_IRQF_WRITE			0x80
+
+#define	PM_IRQF_MASK_ALL		(PM_IRQF_MASK_FE | \
+					PM_IRQF_MASK_RE)
 
 #define REG_HWREV		0x002  /* PMIC4 revision */
 #define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
 
+struct pm_irq_chip {
+	struct device		*dev;
+	spinlock_t		pm_irq_lock;
+	unsigned int		devirq;
+	unsigned int		irq_base;
+	unsigned int		num_irqs;
+	unsigned int		num_blocks;
+	unsigned int		num_masters;
+	u8			config[0];
+};
+
 struct pm8921 {
 	struct device			*dev;
 	struct pm_irq_chip		*irq_chip;
 };
 
+static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp)
+{
+	return pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp);
+}
+
+static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp)
+{
+	return pm8xxx_readb(chip->dev,
+			SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp);
+}
+
+static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip)
+{
+	int	rc;
+
+	spin_lock(&chip->pm_irq_lock);
+	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+	if (rc) {
+		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
+		goto bail;
+	}
+
+	rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
+	if (rc)
+		pr_err("Failed Reading Status rc=%d\n", rc);
+bail:
+	spin_unlock(&chip->pm_irq_lock);
+	return rc;
+}
+
+static int pm8xxx_config_irq(struct pm_irq_chip *chip, u8 bp, u8 cp)
+{
+	int	rc;
+
+	spin_lock(&chip->pm_irq_lock);
+	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+	if (rc) {
+		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
+		goto bail;
+	}
+
+	cp |= PM_IRQF_WRITE;
+	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp);
+	if (rc)
+		pr_err("Failed Configuring IRQ rc=%d\n", rc);
+bail:
+	spin_unlock(&chip->pm_irq_lock);
+	return rc;
+}
+
+static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
+{
+	int pmirq, irq, i, ret = 0;
+	u8 bits;
+
+	ret = pm8xxx_read_block_irq(chip, block, &bits);
+	if (ret) {
+		pr_err("Failed reading %d block ret=%d", block, ret);
+		return ret;
+	}
+	if (!bits) {
+		pr_err("block bit set in master but no irqs: %d", block);
+		return 0;
+	}
+
+	/* Check IRQ bits */
+	for (i = 0; i < 8; i++) {
+		if (bits & (1 << i)) {
+			pmirq = block * 8 + i;
+			irq = pmirq + chip->irq_base;
+			generic_handle_irq(irq);
+		}
+	}
+	return 0;
+}
+
+static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
+{
+	u8 blockbits;
+	int block_number, i, ret = 0;
+
+	ret = pm8xxx_read_master_irq(chip, master, &blockbits);
+	if (ret) {
+		pr_err("Failed to read master %d ret=%d\n", master, ret);
+		return ret;
+	}
+	if (!blockbits) {
+		pr_err("master bit set in root but no blocks: %d", master);
+		return 0;
+	}
+
+	for (i = 0; i < 8; i++)
+		if (blockbits & (1 << i)) {
+			block_number = master * 8 + i;	/* block # */
+			ret |= pm8xxx_irq_block_handler(chip, block_number);
+		}
+	return ret;
+}
+
+static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
+	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
+	u8	root;
+	int	i, ret, masters = 0;
+
+	ret = pm8xxx_read_root_irq(chip, &root);
+	if (ret) {
+		pr_err("Can't read root status ret=%d\n", ret);
+		return;
+	}
+
+	/* on pm8xxx series masters start from bit 1 of the root */
+	masters = root >> 1;
+
+	/* Read allowed masters for blocks. */
+	for (i = 0; i < chip->num_masters; i++)
+		if (masters & (1 << i))
+			pm8xxx_irq_master_handler(chip, i);
+
+	irq_chip->irq_ack(&desc->irq_data);
+}
+
+static void pm8xxx_irq_mask_ack(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = d->irq - chip->irq_base;
+	int	master, irq_bit;
+	u8	block, config;
+
+	block = pmirq / 8;
+	master = block / 8;
+	irq_bit = pmirq % 8;
+
+	config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
+	pm8xxx_config_irq(chip, block, config);
+}
+
+static void pm8xxx_irq_unmask(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = d->irq - chip->irq_base;
+	int	master, irq_bit;
+	u8	block, config;
+
+	block = pmirq / 8;
+	master = block / 8;
+	irq_bit = pmirq % 8;
+
+	config = chip->config[pmirq];
+	pm8xxx_config_irq(chip, block, config);
+}
+
+static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = d->irq - chip->irq_base;
+	int master, irq_bit;
+	u8 block, config;
+
+	block = pmirq / 8;
+	master = block / 8;
+	irq_bit  = pmirq % 8;
+
+	chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
+							| PM_IRQF_MASK_ALL;
+	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
+		if (flow_type & IRQF_TRIGGER_RISING)
+			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
+		if (flow_type & IRQF_TRIGGER_FALLING)
+			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
+	} else {
+		chip->config[pmirq] |= PM_IRQF_LVL_SEL;
+
+		if (flow_type & IRQF_TRIGGER_HIGH)
+			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
+		else
+			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
+	}
+
+	config = chip->config[pmirq] | PM_IRQF_CLR;
+	return pm8xxx_config_irq(chip, block, config);
+}
+
+static int pm8xxx_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+	return 0;
+}
+
+static struct irq_chip pm8xxx_irq_chip = {
+	.name		= "pm8xxx",
+	.irq_mask_ack	= pm8xxx_irq_mask_ack,
+	.irq_unmask	= pm8xxx_irq_unmask,
+	.irq_set_type	= pm8xxx_irq_set_type,
+	.irq_set_wake	= pm8xxx_irq_set_wake,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND,
+};
+
+/**
+ * pm8xxx_get_irq_stat - get the status of the irq line
+ * @chip: pointer to identify a pmic irq controller
+ * @irq: the irq number
+ *
+ * The pm8xxx gpio and mpp rely on the interrupt block to read
+ * the values on their pins. This function is to facilitate reading
+ * the status of a gpio or an mpp line. The caller has to convert the
+ * gpio number to irq number.
+ *
+ * RETURNS:
+ * an int indicating the value read on that line
+ */
+static int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
+{
+	int pmirq, rc;
+	u8  block, bits, bit;
+	unsigned long flags;
+
+	if (chip == NULL || irq < chip->irq_base ||
+			irq >= chip->irq_base + chip->num_irqs)
+		return -EINVAL;
+
+	pmirq = irq - chip->irq_base;
+
+	block = pmirq / 8;
+	bit = pmirq % 8;
+
+	spin_lock_irqsave(&chip->pm_irq_lock, flags);
+
+	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
+	if (rc) {
+		pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n",
+			irq, pmirq, block, rc);
+		goto bail_out;
+	}
+
+	rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
+	if (rc) {
+		pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
+			irq, pmirq, block, rc);
+		goto bail_out;
+	}
+
+	rc = (bits & (1 << bit)) ? 1 : 0;
+
+bail_out:
+	spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
+
+	return rc;
+}
+
+static struct pm_irq_chip *pm8xxx_irq_init(struct device *dev,
+				const struct pm8xxx_irq_platform_data *pdata)
+{
+	struct pm_irq_chip  *chip;
+	int devirq, rc;
+	unsigned int pmirq;
+
+	if (!pdata) {
+		pr_err("No platform data\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	devirq = pdata->devirq;
+	if (devirq < 0) {
+		pr_err("missing devirq\n");
+		rc = devirq;
+		return ERR_PTR(-EINVAL);
+	}
+
+	chip = kzalloc(sizeof(struct pm_irq_chip)
+			+ sizeof(u8) * pdata->irq_cdata.nirqs, GFP_KERNEL);
+	if (!chip) {
+		pr_err("Cannot alloc pm_irq_chip struct\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	chip->dev = dev;
+	chip->devirq = devirq;
+	chip->irq_base = pdata->irq_base;
+	chip->num_irqs = pdata->irq_cdata.nirqs;
+	chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
+	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
+	spin_lock_init(&chip->pm_irq_lock);
+
+	for (pmirq = 0; pmirq < chip->num_irqs; pmirq++) {
+		irq_set_chip_and_handler(chip->irq_base + pmirq,
+				&pm8xxx_irq_chip,
+				handle_level_irq);
+		irq_set_chip_data(chip->irq_base + pmirq, chip);
+#ifdef CONFIG_ARM
+		set_irq_flags(chip->irq_base + pmirq, IRQF_VALID);
+#else
+		irq_set_noprobe(chip->irq_base + pmirq);
+#endif
+	}
+
+	irq_set_irq_type(devirq, pdata->irq_trigger_flag);
+	irq_set_handler_data(devirq, chip);
+	irq_set_chained_handler(devirq, pm8xxx_irq_handler);
+	set_irq_wake(devirq, 1);
+
+	return chip;
+}
+
+static int pm8xxx_irq_exit(struct pm_irq_chip *chip)
+{
+	irq_set_chained_handler(chip->devirq, NULL);
+	kfree(chip);
+	return 0;
+}
+
 static int pm8921_readb(const struct device *dev, u16 addr, u8 *val)
 {
 	const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c
deleted file mode 100644
index 1360e20..0000000
--- a/drivers/mfd/pm8xxx-irq.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#define pr_fmt(fmt)	"%s: " fmt, __func__
-
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/mfd/pm8xxx/core.h>
-#include <linux/mfd/pm8xxx/irq.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-/* PMIC8xxx IRQ */
-
-#define	SSBI_REG_ADDR_IRQ_BASE		0x1BB
-
-#define	SSBI_REG_ADDR_IRQ_ROOT		(SSBI_REG_ADDR_IRQ_BASE + 0)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS1	(SSBI_REG_ADDR_IRQ_BASE + 1)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS2	(SSBI_REG_ADDR_IRQ_BASE + 2)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS3	(SSBI_REG_ADDR_IRQ_BASE + 3)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS4	(SSBI_REG_ADDR_IRQ_BASE + 4)
-#define	SSBI_REG_ADDR_IRQ_BLK_SEL	(SSBI_REG_ADDR_IRQ_BASE + 5)
-#define	SSBI_REG_ADDR_IRQ_IT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 6)
-#define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
-#define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
-
-#define	PM_IRQF_LVL_SEL			0x01	/* level select */
-#define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
-#define	PM_IRQF_MASK_RE			0x04	/* mask rising edge */
-#define	PM_IRQF_CLR			0x08	/* clear interrupt */
-#define	PM_IRQF_BITS_MASK		0x70
-#define	PM_IRQF_BITS_SHIFT		4
-#define	PM_IRQF_WRITE			0x80
-
-#define	PM_IRQF_MASK_ALL		(PM_IRQF_MASK_FE | \
-					PM_IRQF_MASK_RE)
-
-struct pm_irq_chip {
-	struct device		*dev;
-	spinlock_t		pm_irq_lock;
-	unsigned int		devirq;
-	unsigned int		irq_base;
-	unsigned int		num_irqs;
-	unsigned int		num_blocks;
-	unsigned int		num_masters;
-	u8			config[0];
-};
-
-static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp)
-{
-	return pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp);
-}
-
-static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp)
-{
-	return pm8xxx_readb(chip->dev,
-			SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp);
-}
-
-static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip)
-{
-	int	rc;
-
-	spin_lock(&chip->pm_irq_lock);
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
-	if (rc) {
-		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
-		goto bail;
-	}
-
-	rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
-	if (rc)
-		pr_err("Failed Reading Status rc=%d\n", rc);
-bail:
-	spin_unlock(&chip->pm_irq_lock);
-	return rc;
-}
-
-static int pm8xxx_config_irq(struct pm_irq_chip *chip, u8 bp, u8 cp)
-{
-	int	rc;
-
-	spin_lock(&chip->pm_irq_lock);
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
-	if (rc) {
-		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
-		goto bail;
-	}
-
-	cp |= PM_IRQF_WRITE;
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp);
-	if (rc)
-		pr_err("Failed Configuring IRQ rc=%d\n", rc);
-bail:
-	spin_unlock(&chip->pm_irq_lock);
-	return rc;
-}
-
-static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
-{
-	int pmirq, irq, i, ret = 0;
-	u8 bits;
-
-	ret = pm8xxx_read_block_irq(chip, block, &bits);
-	if (ret) {
-		pr_err("Failed reading %d block ret=%d", block, ret);
-		return ret;
-	}
-	if (!bits) {
-		pr_err("block bit set in master but no irqs: %d", block);
-		return 0;
-	}
-
-	/* Check IRQ bits */
-	for (i = 0; i < 8; i++) {
-		if (bits & (1 << i)) {
-			pmirq = block * 8 + i;
-			irq = pmirq + chip->irq_base;
-			generic_handle_irq(irq);
-		}
-	}
-	return 0;
-}
-
-static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
-{
-	u8 blockbits;
-	int block_number, i, ret = 0;
-
-	ret = pm8xxx_read_master_irq(chip, master, &blockbits);
-	if (ret) {
-		pr_err("Failed to read master %d ret=%d\n", master, ret);
-		return ret;
-	}
-	if (!blockbits) {
-		pr_err("master bit set in root but no blocks: %d", master);
-		return 0;
-	}
-
-	for (i = 0; i < 8; i++)
-		if (blockbits & (1 << i)) {
-			block_number = master * 8 + i;	/* block # */
-			ret |= pm8xxx_irq_block_handler(chip, block_number);
-		}
-	return ret;
-}
-
-static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
-	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
-	u8	root;
-	int	i, ret, masters = 0;
-
-	ret = pm8xxx_read_root_irq(chip, &root);
-	if (ret) {
-		pr_err("Can't read root status ret=%d\n", ret);
-		return;
-	}
-
-	/* on pm8xxx series masters start from bit 1 of the root */
-	masters = root >> 1;
-
-	/* Read allowed masters for blocks. */
-	for (i = 0; i < chip->num_masters; i++)
-		if (masters & (1 << i))
-			pm8xxx_irq_master_handler(chip, i);
-
-	irq_chip->irq_ack(&desc->irq_data);
-}
-
-static void pm8xxx_irq_mask_ack(struct irq_data *d)
-{
-	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-	unsigned int pmirq = d->irq - chip->irq_base;
-	int	master, irq_bit;
-	u8	block, config;
-
-	block = pmirq / 8;
-	master = block / 8;
-	irq_bit = pmirq % 8;
-
-	config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
-	pm8xxx_config_irq(chip, block, config);
-}
-
-static void pm8xxx_irq_unmask(struct irq_data *d)
-{
-	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-	unsigned int pmirq = d->irq - chip->irq_base;
-	int	master, irq_bit;
-	u8	block, config;
-
-	block = pmirq / 8;
-	master = block / 8;
-	irq_bit = pmirq % 8;
-
-	config = chip->config[pmirq];
-	pm8xxx_config_irq(chip, block, config);
-}
-
-static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-	unsigned int pmirq = d->irq - chip->irq_base;
-	int master, irq_bit;
-	u8 block, config;
-
-	block = pmirq / 8;
-	master = block / 8;
-	irq_bit  = pmirq % 8;
-
-	chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
-							| PM_IRQF_MASK_ALL;
-	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-		if (flow_type & IRQF_TRIGGER_RISING)
-			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
-		if (flow_type & IRQF_TRIGGER_FALLING)
-			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
-	} else {
-		chip->config[pmirq] |= PM_IRQF_LVL_SEL;
-
-		if (flow_type & IRQF_TRIGGER_HIGH)
-			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
-		else
-			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
-	}
-
-	config = chip->config[pmirq] | PM_IRQF_CLR;
-	return pm8xxx_config_irq(chip, block, config);
-}
-
-static int pm8xxx_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-	return 0;
-}
-
-static struct irq_chip pm8xxx_irq_chip = {
-	.name		= "pm8xxx",
-	.irq_mask_ack	= pm8xxx_irq_mask_ack,
-	.irq_unmask	= pm8xxx_irq_unmask,
-	.irq_set_type	= pm8xxx_irq_set_type,
-	.irq_set_wake	= pm8xxx_irq_set_wake,
-	.flags		= IRQCHIP_MASK_ON_SUSPEND,
-};
-
-/**
- * pm8xxx_get_irq_stat - get the status of the irq line
- * @chip: pointer to identify a pmic irq controller
- * @irq: the irq number
- *
- * The pm8xxx gpio and mpp rely on the interrupt block to read
- * the values on their pins. This function is to facilitate reading
- * the status of a gpio or an mpp line. The caller has to convert the
- * gpio number to irq number.
- *
- * RETURNS:
- * an int indicating the value read on that line
- */
-int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
-{
-	int pmirq, rc;
-	u8  block, bits, bit;
-	unsigned long flags;
-
-	if (chip == NULL || irq < chip->irq_base ||
-			irq >= chip->irq_base + chip->num_irqs)
-		return -EINVAL;
-
-	pmirq = irq - chip->irq_base;
-
-	block = pmirq / 8;
-	bit = pmirq % 8;
-
-	spin_lock_irqsave(&chip->pm_irq_lock, flags);
-
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
-	if (rc) {
-		pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n",
-			irq, pmirq, block, rc);
-		goto bail_out;
-	}
-
-	rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
-	if (rc) {
-		pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
-			irq, pmirq, block, rc);
-		goto bail_out;
-	}
-
-	rc = (bits & (1 << bit)) ? 1 : 0;
-
-bail_out:
-	spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
-
-	return rc;
-}
-EXPORT_SYMBOL_GPL(pm8xxx_get_irq_stat);
-
-struct pm_irq_chip *  pm8xxx_irq_init(struct device *dev,
-				const struct pm8xxx_irq_platform_data *pdata)
-{
-	struct pm_irq_chip  *chip;
-	int devirq, rc;
-	unsigned int pmirq;
-
-	if (!pdata) {
-		pr_err("No platform data\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	devirq = pdata->devirq;
-	if (devirq < 0) {
-		pr_err("missing devirq\n");
-		rc = devirq;
-		return ERR_PTR(-EINVAL);
-	}
-
-	chip = kzalloc(sizeof(struct pm_irq_chip)
-			+ sizeof(u8) * pdata->irq_cdata.nirqs, GFP_KERNEL);
-	if (!chip) {
-		pr_err("Cannot alloc pm_irq_chip struct\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	chip->dev = dev;
-	chip->devirq = devirq;
-	chip->irq_base = pdata->irq_base;
-	chip->num_irqs = pdata->irq_cdata.nirqs;
-	chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
-	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
-	spin_lock_init(&chip->pm_irq_lock);
-
-	for (pmirq = 0; pmirq < chip->num_irqs; pmirq++) {
-		irq_set_chip_and_handler(chip->irq_base + pmirq,
-				&pm8xxx_irq_chip,
-				handle_level_irq);
-		irq_set_chip_data(chip->irq_base + pmirq, chip);
-#ifdef CONFIG_ARM
-		set_irq_flags(chip->irq_base + pmirq, IRQF_VALID);
-#else
-		irq_set_noprobe(chip->irq_base + pmirq);
-#endif
-	}
-
-	irq_set_irq_type(devirq, pdata->irq_trigger_flag);
-	irq_set_handler_data(devirq, chip);
-	irq_set_chained_handler(devirq, pm8xxx_irq_handler);
-	set_irq_wake(devirq, 1);
-
-	return chip;
-}
-
-int pm8xxx_irq_exit(struct pm_irq_chip *chip)
-{
-	irq_set_chained_handler(chip->devirq, NULL);
-	kfree(chip);
-	return 0;
-}
diff --git a/include/linux/mfd/pm8xxx/irq.h b/include/linux/mfd/pm8xxx/irq.h
index f83d6b4..1a11b02 100644
--- a/include/linux/mfd/pm8xxx/irq.h
+++ b/include/linux/mfd/pm8xxx/irq.h
@@ -33,27 +33,4 @@ struct pm8xxx_irq_platform_data {
 	int				irq_trigger_flag;
 };
 
-struct pm_irq_chip;
-
-#ifdef CONFIG_MFD_PM8XXX_IRQ
-int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq);
-struct pm_irq_chip *pm8xxx_irq_init(struct device *dev,
-				const struct pm8xxx_irq_platform_data *pdata);
-int pm8xxx_irq_exit(struct pm_irq_chip *chip);
-#else
-static inline int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
-{
-	return -ENXIO;
-}
-static inline struct pm_irq_chip *pm8xxx_irq_init(
-				const struct device *dev,
-				const struct pm8xxx_irq_platform_data *pdata)
-{
-	return ERR_PTR(-ENXIO);
-}
-static inline int pm8xxx_irq_exit(struct pm_irq_chip *chip)
-{
-	return -ENXIO;
-}
-#endif /* CONFIG_MFD_PM8XXX_IRQ */
 #endif /* __MFD_PM8XXX_IRQ_H */
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v2 2/7] mfd: pm8921: Update for genirq changes
  2013-12-23 20:45 [PATCH v2 0/7] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
  2013-12-23 20:45 ` [PATCH v2 1/7] mfd: Move pm8xxx-irq.c contents into only driver that uses it Stephen Boyd
@ 2013-12-23 20:45 ` Stephen Boyd
  2013-12-23 20:45 ` [PATCH v2 3/7] mfd: pm8921: Migrate to irqdomains Stephen Boyd
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2013-12-23 20:45 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel

Since this code has been marked broken for some time a few genirq
tree wide changes weren't made. set_irq_wake() was renamed to
irq_set_irq_wake() in commit a0cd9ca2b (genirq: Namespace
cleanup, 2011-02-10) and commit 10a8c383 (irq: introduce entry
and exit functions for chained handlers) introduced the chained
irq functions but this driver wasn't updated to use them. Fix
these problems and remove the BROKEN marking on this driver.

Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/mfd/Kconfig       | 1 -
 drivers/mfd/pm8921-core.c | 7 +++++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 9ee4ce6..35007ed 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -453,7 +453,6 @@ config MFD_PM8XXX
 config MFD_PM8921_CORE
 	tristate "Qualcomm PM8921 PMIC chip"
 	depends on (ARCH_MSM || HEXAGON)
-	depends on BROKEN
 	select MFD_CORE
 	select MFD_PM8XXX
 	help
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 669f8f2..7964932 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -15,6 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -174,6 +175,8 @@ static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
 	u8	root;
 	int	i, ret, masters = 0;
 
+	chained_irq_enter(irq_chip, desc);
+
 	ret = pm8xxx_read_root_irq(chip, &root);
 	if (ret) {
 		pr_err("Can't read root status ret=%d\n", ret);
@@ -188,7 +191,7 @@ static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
 		if (masters & (1 << i))
 			pm8xxx_irq_master_handler(chip, i);
 
-	irq_chip->irq_ack(&desc->irq_data);
+	chained_irq_exit(irq_chip, desc);
 }
 
 static void pm8xxx_irq_mask_ack(struct irq_data *d)
@@ -367,7 +370,7 @@ static struct pm_irq_chip *pm8xxx_irq_init(struct device *dev,
 	irq_set_irq_type(devirq, pdata->irq_trigger_flag);
 	irq_set_handler_data(devirq, chip);
 	irq_set_chained_handler(devirq, pm8xxx_irq_handler);
-	set_irq_wake(devirq, 1);
+	irq_set_irq_wake(devirq, 1);
 
 	return chip;
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v2 3/7] mfd: pm8921: Migrate to irqdomains
  2013-12-23 20:45 [PATCH v2 0/7] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
  2013-12-23 20:45 ` [PATCH v2 1/7] mfd: Move pm8xxx-irq.c contents into only driver that uses it Stephen Boyd
  2013-12-23 20:45 ` [PATCH v2 2/7] mfd: pm8921: Update for genirq changes Stephen Boyd
@ 2013-12-23 20:45 ` Stephen Boyd
  2014-01-06 15:53   ` Lee Jones
  2013-12-23 20:46 ` [PATCH v2 4/7] mfd: ssbi: Add regmap read/write helpers Stephen Boyd
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Stephen Boyd @ 2013-12-23 20:45 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel

Convert this driver to use irqdomains so that the PMIC's child
devices can be converted to devicetree.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/mfd/pm8921-core.c         | 184 ++++++++++++++------------------------
 include/linux/mfd/pm8xxx/irq.h    |  36 --------
 include/linux/mfd/pm8xxx/pm8921.h |  30 -------
 3 files changed, 65 insertions(+), 185 deletions(-)
 delete mode 100644 include/linux/mfd/pm8xxx/irq.h
 delete mode 100644 include/linux/mfd/pm8xxx/pm8921.h

diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 7964932..5d1d509 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -17,15 +17,15 @@
 #include <linux/interrupt.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/ssbi.h>
+#include <linux/of_platform.h>
 #include <linux/mfd/core.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/mfd/pm8xxx/core.h>
-#include <linux/mfd/pm8xxx/irq.h>
 
 #define	SSBI_REG_ADDR_IRQ_BASE		0x1BB
 
@@ -56,8 +56,7 @@
 struct pm_irq_chip {
 	struct device		*dev;
 	spinlock_t		pm_irq_lock;
-	unsigned int		devirq;
-	unsigned int		irq_base;
+	struct irq_domain	*domain;
 	unsigned int		num_irqs;
 	unsigned int		num_blocks;
 	unsigned int		num_masters;
@@ -138,7 +137,7 @@ static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
 	for (i = 0; i < 8; i++) {
 		if (bits & (1 << i)) {
 			pmirq = block * 8 + i;
-			irq = pmirq + chip->irq_base;
+			irq = irq_find_mapping(chip->domain, pmirq);
 			generic_handle_irq(irq);
 		}
 	}
@@ -197,12 +196,11 @@ static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
 static void pm8xxx_irq_mask_ack(struct irq_data *d)
 {
 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-	unsigned int pmirq = d->irq - chip->irq_base;
-	int	master, irq_bit;
+	unsigned int pmirq = irqd_to_hwirq(d);
+	int	irq_bit;
 	u8	block, config;
 
 	block = pmirq / 8;
-	master = block / 8;
 	irq_bit = pmirq % 8;
 
 	config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
@@ -212,12 +210,11 @@ static void pm8xxx_irq_mask_ack(struct irq_data *d)
 static void pm8xxx_irq_unmask(struct irq_data *d)
 {
 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-	unsigned int pmirq = d->irq - chip->irq_base;
-	int	master, irq_bit;
+	unsigned int pmirq = irqd_to_hwirq(d);
+	int	irq_bit;
 	u8	block, config;
 
 	block = pmirq / 8;
-	master = block / 8;
 	irq_bit = pmirq % 8;
 
 	config = chip->config[pmirq];
@@ -227,12 +224,11 @@ static void pm8xxx_irq_unmask(struct irq_data *d)
 static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-	unsigned int pmirq = d->irq - chip->irq_base;
-	int master, irq_bit;
+	unsigned int pmirq = irqd_to_hwirq(d);
+	int irq_bit;
 	u8 block, config;
 
 	block = pmirq / 8;
-	master = block / 8;
 	irq_bit  = pmirq % 8;
 
 	chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
@@ -287,12 +283,9 @@ static int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
 	int pmirq, rc;
 	u8  block, bits, bit;
 	unsigned long flags;
+	struct irq_data *irq_data = irq_get_irq_data(irq);
 
-	if (chip == NULL || irq < chip->irq_base ||
-			irq >= chip->irq_base + chip->num_irqs)
-		return -EINVAL;
-
-	pmirq = irq - chip->irq_base;
+	pmirq = irq_data->hwirq;
 
 	block = pmirq / 8;
 	bit = pmirq % 8;
@@ -321,64 +314,55 @@ bail_out:
 	return rc;
 }
 
-static struct pm_irq_chip *pm8xxx_irq_init(struct device *dev,
-				const struct pm8xxx_irq_platform_data *pdata)
+static struct lock_class_key pm8xxx_irq_lock_class;
+
+static int pm8xxx_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				   irq_hw_number_t hwirq)
 {
-	struct pm_irq_chip  *chip;
-	int devirq, rc;
-	unsigned int pmirq;
+	struct pm_irq_chip *chip = d->host_data;
 
-	if (!pdata) {
-		pr_err("No platform data\n");
-		return ERR_PTR(-EINVAL);
-	}
+	irq_set_lockdep_class(irq, &pm8xxx_irq_lock_class);
+	irq_set_chip_and_handler(irq, &pm8xxx_irq_chip, handle_level_irq);
+	irq_set_chip_data(irq, chip);
+#ifdef CONFIG_ARM
+	set_irq_flags(irq, IRQF_VALID);
+#else
+	irq_set_noprobe(irq);
+#endif
+	return 0;
+}
 
-	devirq = pdata->devirq;
-	if (devirq < 0) {
-		pr_err("missing devirq\n");
-		rc = devirq;
-		return ERR_PTR(-EINVAL);
-	}
+static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
+	.xlate = irq_domain_xlate_twocell,
+	.map = pm8xxx_irq_domain_map,
+};
 
-	chip = kzalloc(sizeof(struct pm_irq_chip)
-			+ sizeof(u8) * pdata->irq_cdata.nirqs, GFP_KERNEL);
-	if (!chip) {
-		pr_err("Cannot alloc pm_irq_chip struct\n");
-		return ERR_PTR(-EINVAL);
-	}
+static int pm8xxx_irq_init(struct platform_device *pdev, unsigned int irq)
+{
+	struct pm_irq_chip  *chip;
+	unsigned int nirqs = 256;
+
+	chip = devm_kzalloc(&pdev->dev, sizeof(*chip) + sizeof(u8) * nirqs,
+			    GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
 
-	chip->dev = dev;
-	chip->devirq = devirq;
-	chip->irq_base = pdata->irq_base;
-	chip->num_irqs = pdata->irq_cdata.nirqs;
+	chip->dev = &pdev->dev;
+	chip->num_irqs = nirqs;
 	chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
 	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
 	spin_lock_init(&chip->pm_irq_lock);
 
-	for (pmirq = 0; pmirq < chip->num_irqs; pmirq++) {
-		irq_set_chip_and_handler(chip->irq_base + pmirq,
-				&pm8xxx_irq_chip,
-				handle_level_irq);
-		irq_set_chip_data(chip->irq_base + pmirq, chip);
-#ifdef CONFIG_ARM
-		set_irq_flags(chip->irq_base + pmirq, IRQF_VALID);
-#else
-		irq_set_noprobe(chip->irq_base + pmirq);
-#endif
-	}
+	chip->domain = irq_domain_add_linear(pdev->dev.of_node, nirqs,
+						&pm8xxx_irq_domain_ops,
+						chip);
+	if (!chip->domain)
+		return -ENODEV;
 
-	irq_set_irq_type(devirq, pdata->irq_trigger_flag);
-	irq_set_handler_data(devirq, chip);
-	irq_set_chained_handler(devirq, pm8xxx_irq_handler);
-	irq_set_irq_wake(devirq, 1);
+	irq_set_handler_data(irq, chip);
+	irq_set_chained_handler(irq, pm8xxx_irq_handler);
+	irq_set_irq_wake(irq, 1);
 
-	return chip;
-}
-
-static int pm8xxx_irq_exit(struct pm_irq_chip *chip)
-{
-	irq_set_chained_handler(chip->devirq, NULL);
-	kfree(chip);
 	return 0;
 }
 
@@ -432,42 +416,18 @@ static struct pm8xxx_drvdata pm8921_drvdata = {
 	.pmic_read_irq_stat	= pm8921_read_irq_stat,
 };
 
-static int pm8921_add_subdevices(const struct pm8921_platform_data
-					   *pdata,
-					   struct pm8921 *pmic,
-					   u32 rev)
-{
-	int ret = 0, irq_base = 0;
-	struct pm_irq_chip *irq_chip;
-
-	if (pdata->irq_pdata) {
-		pdata->irq_pdata->irq_cdata.nirqs = PM8921_NR_IRQS;
-		pdata->irq_pdata->irq_cdata.rev = rev;
-		irq_base = pdata->irq_pdata->irq_base;
-		irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
-
-		if (IS_ERR(irq_chip)) {
-			pr_err("Failed to init interrupts ret=%ld\n",
-					PTR_ERR(irq_chip));
-			return PTR_ERR(irq_chip);
-		}
-		pmic->irq_chip = irq_chip;
-	}
-	return ret;
-}
-
 static int pm8921_probe(struct platform_device *pdev)
 {
-	const struct pm8921_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct pm8921 *pmic;
 	int rc;
 	u8 val;
+	unsigned int irq;
 	u32 rev;
 
-	if (!pdata) {
-		pr_err("missing platform data\n");
-		return -EINVAL;
-	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
 
 	pmic = devm_kzalloc(&pdev->dev, sizeof(struct pm8921), GFP_KERNEL);
 	if (!pmic) {
@@ -498,37 +458,23 @@ static int pm8921_probe(struct platform_device *pdev)
 	pm8921_drvdata.pm_chip_data = pmic;
 	platform_set_drvdata(pdev, &pm8921_drvdata);
 
-	rc = pm8921_add_subdevices(pdata, pmic, rev);
-	if (rc) {
-		pr_err("Cannot add subdevices rc=%d\n", rc);
-		goto err;
-	}
+	rc = pm8xxx_irq_init(pdev, irq);
+	if (rc)
+		return rc;
 
-	/* gpio might not work if no irq device is found */
-	WARN_ON(pmic->irq_chip == NULL);
+	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+}
 
+static int pm8921_remove_child(struct device *dev, void *unused)
+{
+	platform_device_unregister(to_platform_device(dev));
 	return 0;
-
-err:
-	mfd_remove_devices(pmic->dev);
-	return rc;
 }
 
 static int pm8921_remove(struct platform_device *pdev)
 {
-	struct pm8xxx_drvdata *drvdata;
-	struct pm8921 *pmic = NULL;
-
-	drvdata = platform_get_drvdata(pdev);
-	if (drvdata)
-		pmic = drvdata->pm_chip_data;
-	if (pmic)
-		mfd_remove_devices(pmic->dev);
-	if (pmic->irq_chip) {
-		pm8xxx_irq_exit(pmic->irq_chip);
-		pmic->irq_chip = NULL;
-	}
-
+	device_for_each_child(&pdev->dev, NULL, pm8921_remove_child);
+	irq_set_chained_handler(platform_get_irq(pdev, 0), NULL);
 	return 0;
 }
 
diff --git a/include/linux/mfd/pm8xxx/irq.h b/include/linux/mfd/pm8xxx/irq.h
deleted file mode 100644
index 1a11b02..0000000
--- a/include/linux/mfd/pm8xxx/irq.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-/*
- * Qualcomm PMIC irq 8xxx driver header file
- *
- */
-
-#ifndef __MFD_PM8XXX_IRQ_H
-#define __MFD_PM8XXX_IRQ_H
-
-#include <linux/errno.h>
-#include <linux/err.h>
-
-struct pm8xxx_irq_core_data {
-	u32		rev;
-	int		nirqs;
-};
-
-struct pm8xxx_irq_platform_data {
-	int				irq_base;
-	struct pm8xxx_irq_core_data	irq_cdata;
-	int				devirq;
-	int				irq_trigger_flag;
-};
-
-#endif /* __MFD_PM8XXX_IRQ_H */
diff --git a/include/linux/mfd/pm8xxx/pm8921.h b/include/linux/mfd/pm8xxx/pm8921.h
deleted file mode 100644
index 00fa3de..0000000
--- a/include/linux/mfd/pm8xxx/pm8921.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-/*
- * Qualcomm PMIC 8921 driver header file
- *
- */
-
-#ifndef __MFD_PM8921_H
-#define __MFD_PM8921_H
-
-#include <linux/mfd/pm8xxx/irq.h>
-
-#define PM8921_NR_IRQS		256
-
-struct pm8921_platform_data {
-	int					irq_base;
-	struct pm8xxx_irq_platform_data		*irq_pdata;
-};
-
-#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v2 4/7] mfd: ssbi: Add regmap read/write helpers
  2013-12-23 20:45 [PATCH v2 0/7] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
                   ` (2 preceding siblings ...)
  2013-12-23 20:45 ` [PATCH v2 3/7] mfd: pm8921: Migrate to irqdomains Stephen Boyd
@ 2013-12-23 20:46 ` Stephen Boyd
  2013-12-24 12:54   ` Mark Brown
  2013-12-23 20:46 ` [PATCH v2 5/7] mfd: pm8921: Use ssbi regmap Stephen Boyd
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Stephen Boyd @ 2013-12-23 20:46 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Mark Brown

Add read and write helper functions that the pm8921-core driver
can use to read and write ssbi regsiters via a "no-bus" regmap.

Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/mfd/ssbi.c   | 13 +++++++++++++
 include/linux/ssbi.h |  3 +++
 2 files changed, 16 insertions(+)

diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c
index b78942e..c5d270f 100644
--- a/drivers/mfd/ssbi.c
+++ b/drivers/mfd/ssbi.c
@@ -269,6 +269,19 @@ int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len)
 }
 EXPORT_SYMBOL_GPL(ssbi_write);
 
+int ssbi_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+	*val = 0;
+	return ssbi_read(context, reg, (u8 *)val, 1);
+}
+EXPORT_SYMBOL_GPL(ssbi_reg_read);
+
+int ssbi_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+	return ssbi_write(context, reg, (u8 *)&val, 1);
+}
+EXPORT_SYMBOL_GPL(ssbi_reg_write);
+
 static int ssbi_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
diff --git a/include/linux/ssbi.h b/include/linux/ssbi.h
index bcbb642..b862f3d 100644
--- a/include/linux/ssbi.h
+++ b/include/linux/ssbi.h
@@ -20,4 +20,7 @@
 int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len);
 int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len);
 
+int ssbi_reg_read(void *context, unsigned int reg, unsigned int *val);
+int ssbi_reg_write(void *context, unsigned int reg, unsigned int val);
+
 #endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v2 5/7] mfd: pm8921: Use ssbi regmap
  2013-12-23 20:45 [PATCH v2 0/7] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
                   ` (3 preceding siblings ...)
  2013-12-23 20:46 ` [PATCH v2 4/7] mfd: ssbi: Add regmap read/write helpers Stephen Boyd
@ 2013-12-23 20:46 ` Stephen Boyd
  2013-12-30 12:34   ` Mark Brown
  2013-12-23 20:46 ` [PATCH v2 6/7] mfd: pm8921: Add DT match table Stephen Boyd
       [not found] ` <1387831563-13535-1-git-send-email-sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  6 siblings, 1 reply; 23+ messages in thread
From: Stephen Boyd @ 2013-12-23 20:46 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Mark Brown

Use a regmap so that the pm8xxx read/write APIs can be removed
once all consumer drivers are converted.

Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/mfd/Kconfig       |  1 +
 drivers/mfd/pm8921-core.c | 72 +++++++++++++++++++++++++++--------------------
 2 files changed, 42 insertions(+), 31 deletions(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 35007ed..e4a3ae2 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -455,6 +455,7 @@ config MFD_PM8921_CORE
 	depends on (ARCH_MSM || HEXAGON)
 	select MFD_CORE
 	select MFD_PM8XXX
+	select REGMAP
 	help
 	  If you say yes to this option, support will be included for the
 	  built-in PM8921 PMIC chip.
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 5d1d509..d13cb6e 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/ssbi.h>
+#include <linux/regmap.h>
 #include <linux/of_platform.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/pm8xxx/core.h>
@@ -55,6 +56,7 @@
 
 struct pm_irq_chip {
 	struct device		*dev;
+	struct regmap		*regmap;
 	spinlock_t		pm_irq_lock;
 	struct irq_domain	*domain;
 	unsigned int		num_irqs;
@@ -68,29 +70,19 @@ struct pm8921 {
 	struct pm_irq_chip		*irq_chip;
 };
 
-static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp)
-{
-	return pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp);
-}
-
-static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp)
-{
-	return pm8xxx_readb(chip->dev,
-			SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp);
-}
-
-static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip)
+static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
+				 unsigned int *ip)
 {
 	int	rc;
 
 	spin_lock(&chip->pm_irq_lock);
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
 	if (rc) {
 		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
 		goto bail;
 	}
 
-	rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
+	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
 	if (rc)
 		pr_err("Failed Reading Status rc=%d\n", rc);
 bail:
@@ -98,19 +90,20 @@ bail:
 	return rc;
 }
 
-static int pm8xxx_config_irq(struct pm_irq_chip *chip, u8 bp, u8 cp)
+static int
+pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp)
 {
 	int	rc;
 
 	spin_lock(&chip->pm_irq_lock);
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
 	if (rc) {
 		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
 		goto bail;
 	}
 
 	cp |= PM_IRQF_WRITE;
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp);
+	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_CONFIG, cp);
 	if (rc)
 		pr_err("Failed Configuring IRQ rc=%d\n", rc);
 bail:
@@ -121,7 +114,7 @@ bail:
 static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
 {
 	int pmirq, irq, i, ret = 0;
-	u8 bits;
+	unsigned int bits;
 
 	ret = pm8xxx_read_block_irq(chip, block, &bits);
 	if (ret) {
@@ -146,10 +139,11 @@ static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
 
 static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
 {
-	u8 blockbits;
+	unsigned int blockbits;
 	int block_number, i, ret = 0;
 
-	ret = pm8xxx_read_master_irq(chip, master, &blockbits);
+	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_M_STATUS1 + master,
+			  &blockbits);
 	if (ret) {
 		pr_err("Failed to read master %d ret=%d\n", master, ret);
 		return ret;
@@ -171,12 +165,12 @@ static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
 	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
-	u8	root;
+	unsigned int root;
 	int	i, ret, masters = 0;
 
 	chained_irq_enter(irq_chip, desc);
 
-	ret = pm8xxx_read_root_irq(chip, &root);
+	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root);
 	if (ret) {
 		pr_err("Can't read root status ret=%d\n", ret);
 		return;
@@ -281,7 +275,7 @@ static struct irq_chip pm8xxx_irq_chip = {
 static int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
 {
 	int pmirq, rc;
-	u8  block, bits, bit;
+	unsigned int  block, bits, bit;
 	unsigned long flags;
 	struct irq_data *irq_data = irq_get_irq_data(irq);
 
@@ -292,14 +286,14 @@ static int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
 
 	spin_lock_irqsave(&chip->pm_irq_lock, flags);
 
-	rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
+	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
 	if (rc) {
 		pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n",
 			irq, pmirq, block, rc);
 		goto bail_out;
 	}
 
-	rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
+	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
 	if (rc) {
 		pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
 			irq, pmirq, block, rc);
@@ -337,7 +331,8 @@ static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
 	.map = pm8xxx_irq_domain_map,
 };
 
-static int pm8xxx_irq_init(struct platform_device *pdev, unsigned int irq)
+static int pm8xxx_irq_init(struct platform_device *pdev, struct regmap *regmap,
+			   unsigned int irq)
 {
 	struct pm_irq_chip  *chip;
 	unsigned int nirqs = 256;
@@ -347,7 +342,7 @@ static int pm8xxx_irq_init(struct platform_device *pdev, unsigned int irq)
 	if (!chip)
 		return -ENOMEM;
 
-	chip->dev = &pdev->dev;
+	chip->regmap = regmap;
 	chip->num_irqs = nirqs;
 	chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
 	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
@@ -416,11 +411,21 @@ static struct pm8xxx_drvdata pm8921_drvdata = {
 	.pmic_read_irq_stat	= pm8921_read_irq_stat,
 };
 
+static const struct regmap_config ssbi_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.max_register = 0x3ff,
+	.fast_io = true,
+	.reg_read = ssbi_reg_read,
+	.reg_write = ssbi_reg_write
+};
+
 static int pm8921_probe(struct platform_device *pdev)
 {
 	struct pm8921 *pmic;
+	struct regmap *regmap;
 	int rc;
-	u8 val;
+	unsigned int val;
 	unsigned int irq;
 	u32 rev;
 
@@ -435,8 +440,13 @@ static int pm8921_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	regmap = devm_regmap_init(&pdev->dev, NULL, pdev->dev.parent,
+				  &ssbi_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
 	/* Read PMIC chip revision */
-	rc = ssbi_read(pdev->dev.parent, REG_HWREV, &val, sizeof(val));
+	rc = regmap_read(regmap, REG_HWREV, &val);
 	if (rc) {
 		pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
 		return rc;
@@ -445,7 +455,7 @@ static int pm8921_probe(struct platform_device *pdev)
 	rev = val;
 
 	/* Read PMIC chip revision 2 */
-	rc = ssbi_read(pdev->dev.parent, REG_HWREV_2, &val, sizeof(val));
+	rc = regmap_read(regmap, REG_HWREV_2, &val);
 	if (rc) {
 		pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
 			REG_HWREV_2, rc);
@@ -458,7 +468,7 @@ static int pm8921_probe(struct platform_device *pdev)
 	pm8921_drvdata.pm_chip_data = pmic;
 	platform_set_drvdata(pdev, &pm8921_drvdata);
 
-	rc = pm8xxx_irq_init(pdev, irq);
+	rc = pm8xxx_irq_init(pdev, regmap, irq);
 	if (rc)
 		return rc;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v2 6/7] mfd: pm8921: Add DT match table
  2013-12-23 20:45 [PATCH v2 0/7] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
                   ` (4 preceding siblings ...)
  2013-12-23 20:46 ` [PATCH v2 5/7] mfd: pm8921: Use ssbi regmap Stephen Boyd
@ 2013-12-23 20:46 ` Stephen Boyd
  2014-01-06 11:52   ` Lee Jones
       [not found] ` <1387831563-13535-1-git-send-email-sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  6 siblings, 1 reply; 23+ messages in thread
From: Stephen Boyd @ 2013-12-23 20:46 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel

Allow this driver to probe based on devicetree.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/mfd/pm8921-core.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index d13cb6e..290f0da 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -420,6 +420,13 @@ static const struct regmap_config ssbi_regmap_config = {
 	.reg_write = ssbi_reg_write
 };
 
+static const struct of_device_id pm8921_id_table[] = {
+	{ .compatible = "qcom,pm8058", },
+	{ .compatible = "qcom,pm8921", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pm8921_id_table);
+
 static int pm8921_probe(struct platform_device *pdev)
 {
 	struct pm8921 *pmic;
@@ -429,7 +436,6 @@ static int pm8921_probe(struct platform_device *pdev)
 	unsigned int irq;
 	u32 rev;
 
-
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
 		return irq;
@@ -494,6 +500,7 @@ static struct platform_driver pm8921_driver = {
 	.driver		= {
 		.name	= "pm8921-core",
 		.owner	= THIS_MODULE,
+		.of_match_table = pm8921_id_table,
 	},
 };
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v2 7/7] devicetree: bindings: Document PM8921/8058 PMICs
       [not found] ` <1387831563-13535-1-git-send-email-sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2013-12-23 20:46   ` Stephen Boyd
  2014-01-06 11:53     ` Lee Jones
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Boyd @ 2013-12-23 20:46 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA

PM8921 and PM8058 are PMICs found paired with MSM8960 and MSM8660
devices respectively. They contain subdevices such as keypads,
RTC, regulators, clocks, etc.

Cc: <devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Signed-off-by: Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 .../devicetree/bindings/mfd/qcom,pm8xxx.txt        | 63 ++++++++++++++++++++++
 1 file changed, 63 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt

diff --git a/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt
new file mode 100644
index 0000000..e3fe625
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt
@@ -0,0 +1,63 @@
+Qualcomm PM8xxx PMIC multi-function devices
+
+PROPERTIES
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be one of:
+		    "qcom,pm8058"
+		    "qcom,pm8921"
+
+- #address-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 1
+
+- #size-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 0
+
+- interrupts:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: specifies the interrupt that indicates a subdevice
+		    has generated an interrupt (summary interrupt). The
+		    format of the specifier is defined by the binding document
+		    describing the node's interrupt parent.
+
+- #interrupt-cells:
+	Usage: required
+	Value type : <u32>
+	Definition: must be 2. Specifies the number of cells needed to encode
+		    an interrupt source. The 1st cell contains the interrupt
+		    number. The 2nd cell is the trigger type and level flags
+		    encoded as follows:
+
+			1 = low-to-high edge triggered
+			2 = high-to-low edge triggered
+			4 = active high level-sensitive
+			8 = active low level-sensitive
+
+- interrupt-controller:
+	Usage: required
+	Value type: <empty>
+	Definition: identifies this node as an interrupt controller
+
+EXAMPLE
+
+	pmicintc: pmic@0 {
+		compatible = "qcom,pm8921";
+		interrupts = <104 8>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pwrkey {
+			compatible = "qcom,pm8921-pwrkey";
+			interrupt-parent = <&pmicintc>;
+			interrupts = <50 1>, <51 1>;
+		};
+	};
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 4/7] mfd: ssbi: Add regmap read/write helpers
  2013-12-23 20:46 ` [PATCH v2 4/7] mfd: ssbi: Add regmap read/write helpers Stephen Boyd
@ 2013-12-24 12:54   ` Mark Brown
  2013-12-26 19:41     ` Stephen Boyd
  0 siblings, 1 reply; 23+ messages in thread
From: Mark Brown @ 2013-12-24 12:54 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Samuel Ortiz, Lee Jones, linux-kernel, linux-arm-msm, linux-arm-kernel

On Mon, Dec 23, 2013 at 12:46:00PM -0800, Stephen Boyd wrote:

> +int ssbi_reg_read(void *context, unsigned int reg, unsigned int *val)
> +{
> +	*val = 0;
> +	return ssbi_read(context, reg, (u8 *)val, 1);
> +}
> +EXPORT_SYMBOL_GPL(ssbi_reg_read);
> +
> +int ssbi_reg_write(void *context, unsigned int reg, unsigned int val)
> +{
> +	return ssbi_write(context, reg, (u8 *)&val, 1);
> +}
> +EXPORT_SYMBOL_GPL(ssbi_reg_write);

Not a big deal but could these just be inlined in the headers?

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

* Re: [PATCH v2 4/7] mfd: ssbi: Add regmap read/write helpers
  2013-12-24 12:54   ` Mark Brown
@ 2013-12-26 19:41     ` Stephen Boyd
  2013-12-28 14:52       ` Mark Brown
  2014-01-06 11:50       ` Lee Jones
  0 siblings, 2 replies; 23+ messages in thread
From: Stephen Boyd @ 2013-12-26 19:41 UTC (permalink / raw)
  To: Mark Brown
  Cc: Samuel Ortiz, Lee Jones, linux-kernel, linux-arm-msm, linux-arm-kernel

On 12/24, Mark Brown wrote:
> On Mon, Dec 23, 2013 at 12:46:00PM -0800, Stephen Boyd wrote:
> 
> > +int ssbi_reg_read(void *context, unsigned int reg, unsigned int *val)
> > +{
> > +	*val = 0;
> > +	return ssbi_read(context, reg, (u8 *)val, 1);
> > +}
> > +EXPORT_SYMBOL_GPL(ssbi_reg_read);
> > +
> > +int ssbi_reg_write(void *context, unsigned int reg, unsigned int val)
> > +{
> > +	return ssbi_write(context, reg, (u8 *)&val, 1);
> > +}
> > +EXPORT_SYMBOL_GPL(ssbi_reg_write);
> 
> Not a big deal but could these just be inlined in the headers?

Sure, I can do that if I need to resend? The only benefit I see
is two less symbols exported.

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

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

* Re: [PATCH v2 4/7] mfd: ssbi: Add regmap read/write helpers
  2013-12-26 19:41     ` Stephen Boyd
@ 2013-12-28 14:52       ` Mark Brown
  2014-01-06 11:50       ` Lee Jones
  1 sibling, 0 replies; 23+ messages in thread
From: Mark Brown @ 2013-12-28 14:52 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-arm-msm, Lee Jones, Samuel Ortiz, linux-arm-kernel, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 465 bytes --]

On Thu, Dec 26, 2013 at 11:41:33AM -0800, Stephen Boyd wrote:
> On 12/24, Mark Brown wrote:

> > Not a big deal but could these just be inlined in the headers?

> Sure, I can do that if I need to resend? The only benefit I see
> is two less symbols exported.

It also means that everything will be marginally faster since there
will be one less level of function call but yeah, there's little
practical benefit - it's a stylistic thing rather than a practical one.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

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

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

* Re: [PATCH v2 5/7] mfd: pm8921: Use ssbi regmap
  2013-12-23 20:46 ` [PATCH v2 5/7] mfd: pm8921: Use ssbi regmap Stephen Boyd
@ 2013-12-30 12:34   ` Mark Brown
  0 siblings, 0 replies; 23+ messages in thread
From: Mark Brown @ 2013-12-30 12:34 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Samuel Ortiz, Lee Jones, linux-kernel, linux-arm-msm, linux-arm-kernel

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

On Mon, Dec 23, 2013 at 12:46:01PM -0800, Stephen Boyd wrote:
> Use a regmap so that the pm8xxx read/write APIs can be removed
> once all consumer drivers are converted.

Reviewed-by: Mark Brown <broonie@linaro.org>

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH v2 4/7] mfd: ssbi: Add regmap read/write helpers
  2013-12-26 19:41     ` Stephen Boyd
  2013-12-28 14:52       ` Mark Brown
@ 2014-01-06 11:50       ` Lee Jones
  2014-01-06 22:26         ` Stephen Boyd
  1 sibling, 1 reply; 23+ messages in thread
From: Lee Jones @ 2014-01-06 11:50 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Mark Brown, Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

On Thu, 26 Dec 2013, Stephen Boyd wrote:

> On 12/24, Mark Brown wrote:
> > On Mon, Dec 23, 2013 at 12:46:00PM -0800, Stephen Boyd wrote:
> > 
> > > +int ssbi_reg_read(void *context, unsigned int reg, unsigned int *val)
> > > +{
> > > +	*val = 0;
> > > +	return ssbi_read(context, reg, (u8 *)val, 1);
> > > +}
> > > +EXPORT_SYMBOL_GPL(ssbi_reg_read);
> > > +
> > > +int ssbi_reg_write(void *context, unsigned int reg, unsigned int val)
> > > +{
> > > +	return ssbi_write(context, reg, (u8 *)&val, 1);
> > > +}
> > > +EXPORT_SYMBOL_GPL(ssbi_reg_write);
> > 
> > Not a big deal but could these just be inlined in the headers?
> 
> Sure, I can do that if I need to resend? The only benefit I see
> is two less symbols exported.

Yes please. After this review.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v2 6/7] mfd: pm8921: Add DT match table
  2013-12-23 20:46 ` [PATCH v2 6/7] mfd: pm8921: Add DT match table Stephen Boyd
@ 2014-01-06 11:52   ` Lee Jones
  2014-01-06 18:03     ` Stephen Boyd
  0 siblings, 1 reply; 23+ messages in thread
From: Lee Jones @ 2014-01-06 11:52 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

> Allow this driver to probe based on devicetree.
> 
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/mfd/pm8921-core.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
> index d13cb6e..290f0da 100644
> --- a/drivers/mfd/pm8921-core.c
> +++ b/drivers/mfd/pm8921-core.c
> @@ -420,6 +420,13 @@ static const struct regmap_config ssbi_regmap_config = {
>  	.reg_write = ssbi_reg_write
>  };
>  
> +static const struct of_device_id pm8921_id_table[] = {
> +	{ .compatible = "qcom,pm8058", },
> +	{ .compatible = "qcom,pm8921", },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, pm8921_id_table);
> +
>  static int pm8921_probe(struct platform_device *pdev)
>  {
>  	struct pm8921 *pmic;
> @@ -429,7 +436,6 @@ static int pm8921_probe(struct platform_device *pdev)
>  	unsigned int irq;
>  	u32 rev;
>  
> -

Sneaky!

>  	irq = platform_get_irq(pdev, 0);
>  	if (irq < 0)
>  		return irq;
> @@ -494,6 +500,7 @@ static struct platform_driver pm8921_driver = {
>  	.driver		= {
>  		.name	= "pm8921-core",
>  		.owner	= THIS_MODULE,
> +		.of_match_table = pm8921_id_table,
>  	},
>  };

Patch fine:
  Acked-by: Lee Jones <lee.jones@linaro.org>

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v2 7/7] devicetree: bindings: Document PM8921/8058 PMICs
  2013-12-23 20:46   ` [PATCH v2 7/7] devicetree: bindings: Document PM8921/8058 PMICs Stephen Boyd
@ 2014-01-06 11:53     ` Lee Jones
  0 siblings, 0 replies; 23+ messages in thread
From: Lee Jones @ 2014-01-06 11:53 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel, devicetree

> PM8921 and PM8058 are PMICs found paired with MSM8960 and MSM8660
> devices respectively. They contain subdevices such as keypads,
> RTC, regulators, clocks, etc.
> 
> Cc: <devicetree@vger.kernel.org>

Still waiting on these guys.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v2 1/7] mfd: Move pm8xxx-irq.c contents into only driver that uses it
  2013-12-23 20:45 ` [PATCH v2 1/7] mfd: Move pm8xxx-irq.c contents into only driver that uses it Stephen Boyd
@ 2014-01-06 14:47   ` Lee Jones
  0 siblings, 0 replies; 23+ messages in thread
From: Lee Jones @ 2014-01-06 14:47 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

On Mon, 23 Dec 2013, Stephen Boyd wrote:

> The pm8xxx-irq.c code is practically mandatory given that the
> pm8921-core driver will WARN about it missing and the Kconfig
> marks it as default y when a PM8xxx chips is enabled. The only
> reason the file was split out was because we planned to support
> other pm8xxx chips with different pm8xxx-core.c files. Now that
> we have DT on ARM this isn't necessary because we should be able
> to support all the ssbi based PM8xxx chips in one driver and one
> file with no data bloat. Let's move this code into the only
> driver that uses it right now (pm8921) so that it's always compiled when
> needed. In the future we can rename pm8921-core.c to something
> more generic.
> 
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/mfd/Kconfig            |  10 --
>  drivers/mfd/pm8921-core.c      | 348 ++++++++++++++++++++++++++++++++++++++
>  drivers/mfd/pm8xxx-irq.c       | 371 -----------------------------------------
>  include/linux/mfd/pm8xxx/irq.h |  23 ---
>  4 files changed, 348 insertions(+), 404 deletions(-)
>  delete mode 100644 drivers/mfd/pm8xxx-irq.c

Acked-by: Lee Jones <lee.jones@linaro.org>

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v2 3/7] mfd: pm8921: Migrate to irqdomains
  2013-12-23 20:45 ` [PATCH v2 3/7] mfd: pm8921: Migrate to irqdomains Stephen Boyd
@ 2014-01-06 15:53   ` Lee Jones
  2014-01-06 20:33     ` Stephen Boyd
  0 siblings, 1 reply; 23+ messages in thread
From: Lee Jones @ 2014-01-06 15:53 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

> Convert this driver to use irqdomains so that the PMIC's child
> devices can be converted to devicetree.
> 
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/mfd/pm8921-core.c         | 184 ++++++++++++++------------------------
>  include/linux/mfd/pm8xxx/irq.h    |  36 --------
>  include/linux/mfd/pm8xxx/pm8921.h |  30 -------
>  3 files changed, 65 insertions(+), 185 deletions(-)
>  delete mode 100644 include/linux/mfd/pm8xxx/irq.h
>  delete mode 100644 include/linux/mfd/pm8xxx/pm8921.h
> 

<snip>

> @@ -56,8 +56,7 @@
>  struct pm_irq_chip {
>  	struct device		*dev;
>  	spinlock_t		pm_irq_lock;
> -	unsigned int		devirq;
> -	unsigned int		irq_base;
> +	struct irq_domain	*domain;

It's probably best to explicitly specify 'irqdomain' here in order to
eliminate any possibility of ambiguity.

>  	unsigned int		num_irqs;
>  	unsigned int		num_blocks;
>  	unsigned int		num_masters;
> @@ -138,7 +137,7 @@ static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
>  	for (i = 0; i < 8; i++) {
>  		if (bits & (1 << i)) {
>  			pmirq = block * 8 + i;
> -			irq = pmirq + chip->irq_base;
> +			irq = irq_find_mapping(chip->domain, pmirq);

Going by this patch only, it appears you're calling irq_find_mapping()
before you've called irq_create_mapping(). This won't work, so unless
you've called the latter in a previous patch, you should ensure that
you do so.

>  			generic_handle_irq(irq);
>  		}
>  	}
> @@ -197,12 +196,11 @@ static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
>  static void pm8xxx_irq_mask_ack(struct irq_data *d)
>  {
>  	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
> -	unsigned int pmirq = d->irq - chip->irq_base;
> -	int	master, irq_bit;
> +	unsigned int pmirq = irqd_to_hwirq(d);

Why don't you call it hwirq instead of pmirq?

> +	int	irq_bit;
>  	u8	block, config;
>  
>  	block = pmirq / 8;

Ah, I guess you're keeping the original naming convention.

> -	master = block / 8;

What was the point in this anyway? Was it completely superfluous?

<snip>

> +static int pm8xxx_irq_init(struct platform_device *pdev, unsigned int irq)
> +{
> +	struct pm_irq_chip  *chip;
> +	unsigned int nirqs = 256;

No magic numbers please.

> +	chip = devm_kzalloc(&pdev->dev, sizeof(*chip) + sizeof(u8) * nirqs,
> +			    GFP_KERNEL);

What does the sizeof(u8) add here?

<snip>

> +	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> +}

Can't you use the MFD core instead?

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v2 6/7] mfd: pm8921: Add DT match table
  2014-01-06 11:52   ` Lee Jones
@ 2014-01-06 18:03     ` Stephen Boyd
  0 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2014-01-06 18:03 UTC (permalink / raw)
  To: Lee Jones; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

On 01/06/14 03:52, Lee Jones wrote:
>> Allow this driver to probe based on devicetree.
>>
>> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
>> ---
>>  drivers/mfd/pm8921-core.c | 9 ++++++++-
>>  1 file changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
>> index d13cb6e..290f0da 100644
>> --- a/drivers/mfd/pm8921-core.c
>> +++ b/drivers/mfd/pm8921-core.c
>> @@ -420,6 +420,13 @@ static const struct regmap_config ssbi_regmap_config = {
>>  	.reg_write = ssbi_reg_write
>>  };
>>  
>> +static const struct of_device_id pm8921_id_table[] = {
>> +	{ .compatible = "qcom,pm8058", },
>> +	{ .compatible = "qcom,pm8921", },
>> +	{ }
>> +};
>> +MODULE_DEVICE_TABLE(of, pm8921_id_table);
>> +
>>  static int pm8921_probe(struct platform_device *pdev)
>>  {
>>  	struct pm8921 *pmic;
>> @@ -429,7 +436,6 @@ static int pm8921_probe(struct platform_device *pdev)
>>  	unsigned int irq;
>>  	u32 rev;
>>  
>> -
> Sneaky!

Sorry, I messed up this patch. This removal is supposed to be in an
earlier patch. Fixed now.

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

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

* Re: [PATCH v2 3/7] mfd: pm8921: Migrate to irqdomains
  2014-01-06 15:53   ` Lee Jones
@ 2014-01-06 20:33     ` Stephen Boyd
  2014-01-07  8:22       ` Lee Jones
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Boyd @ 2014-01-06 20:33 UTC (permalink / raw)
  To: Lee Jones; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

On 01/06/14 07:53, Lee Jones wrote:
>
>> @@ -56,8 +56,7 @@
>>  struct pm_irq_chip {
>>  	struct device		*dev;
>>  	spinlock_t		pm_irq_lock;
>> -	unsigned int		devirq;
>> -	unsigned int		irq_base;
>> +	struct irq_domain	*domain;
> It's probably best to explicitly specify 'irqdomain' here in order to
> eliminate any possibility of ambiguity.

Ok. Renamed.

>
>>  	unsigned int		num_irqs;
>>  	unsigned int		num_blocks;
>>  	unsigned int		num_masters;
>> @@ -138,7 +137,7 @@ static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
>>  	for (i = 0; i < 8; i++) {
>>  		if (bits & (1 << i)) {
>>  			pmirq = block * 8 + i;
>> -			irq = pmirq + chip->irq_base;
>> +			irq = irq_find_mapping(chip->domain, pmirq);
> Going by this patch only, it appears you're calling irq_find_mapping()
> before you've called irq_create_mapping(). This won't work, so unless
> you've called the latter in a previous patch, you should ensure that
> you do so.
>

Interrupts seem to work. I think that's because the mapping is created
when the consumer drivers call request_irq().

>From what I can tell, if we call irq_find_mapping() and there is no
mapping associated with it then we have a spurious irq. If that happens
we'll call handle_generic_irq() with 0 and that will cause
handle_bad_irq() to be called and a debug message to be logged. That
seems like a good outcome.

>> -	master = block / 8;
> What was the point in this anyway? Was it completely superfluous?

I think it was just copy/paste without thinking if the variables are
actually used.

>
>> +static int pm8xxx_irq_init(struct platform_device *pdev, unsigned int irq)
>> +{
>> +	struct pm_irq_chip  *chip;
>> +	unsigned int nirqs = 256;
> No magic numbers please.

Done.

>
>> +	chip = devm_kzalloc(&pdev->dev, sizeof(*chip) + sizeof(u8) * nirqs,
>> +			    GFP_KERNEL);
> What does the sizeof(u8) add here?
>

This was just keeping the same code that was already there. I will do
sizeof(chip->config[0]) instead which is more future proof if that array
changes type later on.

>
>> +	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
>> +}
> Can't you use the MFD core instead?
>

Are you suggesting using mfd_add_devices()? At first glance it looks
like that would require an array of mfd_cell structures that do nothing
besides match compatible strings in the DT. Using of_platform_populate()
achieves the same goal and doesn't require an array of mfd_cell
structures for each different pm8xxx chip that comes along, meaning
simpler code.

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

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

* Re: [PATCH v2 4/7] mfd: ssbi: Add regmap read/write helpers
  2014-01-06 11:50       ` Lee Jones
@ 2014-01-06 22:26         ` Stephen Boyd
  0 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2014-01-06 22:26 UTC (permalink / raw)
  To: Lee Jones
  Cc: Mark Brown, Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

On 01/06/14 03:50, Lee Jones wrote:
> On Thu, 26 Dec 2013, Stephen Boyd wrote:
>
>> On 12/24, Mark Brown wrote:
>>> On Mon, Dec 23, 2013 at 12:46:00PM -0800, Stephen Boyd wrote:
>>>
>>>> +int ssbi_reg_read(void *context, unsigned int reg, unsigned int *val)
>>>> +{
>>>> +	*val = 0;
>>>> +	return ssbi_read(context, reg, (u8 *)val, 1);
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(ssbi_reg_read);
>>>> +
>>>> +int ssbi_reg_write(void *context, unsigned int reg, unsigned int val)
>>>> +{
>>>> +	return ssbi_write(context, reg, (u8 *)&val, 1);
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(ssbi_reg_write);
>>> Not a big deal but could these just be inlined in the headers?
>> Sure, I can do that if I need to resend? The only benefit I see
>> is two less symbols exported.
> Yes please. After this review.
>

Ok done. Just waiting for you to reply on patch 3 until I resend.

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

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

* Re: [PATCH v2 3/7] mfd: pm8921: Migrate to irqdomains
  2014-01-06 20:33     ` Stephen Boyd
@ 2014-01-07  8:22       ` Lee Jones
  2014-01-07 19:54         ` Stephen Boyd
  0 siblings, 1 reply; 23+ messages in thread
From: Lee Jones @ 2014-01-07  8:22 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

> >>  	unsigned int		num_irqs;
> >>  	unsigned int		num_blocks;
> >>  	unsigned int		num_masters;
> >> @@ -138,7 +137,7 @@ static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
> >>  	for (i = 0; i < 8; i++) {
> >>  		if (bits & (1 << i)) {
> >>  			pmirq = block * 8 + i;
> >> -			irq = pmirq + chip->irq_base;
> >> +			irq = irq_find_mapping(chip->domain, pmirq);
> > Going by this patch only, it appears you're calling irq_find_mapping()
> > before you've called irq_create_mapping(). This won't work, so unless
> > you've called the latter in a previous patch, you should ensure that
> > you do so.
> >
> 
> Interrupts seem to work. I think that's because the mapping is created
> when the consumer drivers call request_irq().
> 
> From what I can tell, if we call irq_find_mapping() and there is no
> mapping associated with it then we have a spurious irq. If that happens
> we'll call handle_generic_irq() with 0 and that will cause
> handle_bad_irq() to be called and a debug message to be logged. That
> seems like a good outcome.

I would try to adhere to the documentation in case we are missing
something or some of the semantics change. Please read:
Documentation/IRQ-domain.txt. Specifically, "=== irq_domain usage ==="
from line 39, which says to call irq_create_mapping() to indeed, create
the mapping.

> > What does the sizeof(u8) add here?
> >
> 
> This was just keeping the same code that was already there. I will do
> sizeof(chip->config[0]) instead which is more future proof if that array
> changes type later on.

Ah, now I see what it's doing. Perhaps brackets would be of use to
ensure readers aren't confused. I also think the sizeof() would be
helpful too, so:

        chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
                            (sizeof(chip->config[0]) * nirqs), GFP_KERNEL);

> >> +	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> >> +}
> > Can't you use the MFD core instead?
> >
> 
> Are you suggesting using mfd_add_devices()? At first glance it looks
> like that would require an array of mfd_cell structures that do nothing
> besides match compatible strings in the DT. Using of_platform_populate()
> achieves the same goal and doesn't require an array of mfd_cell
> structures for each different pm8xxx chip that comes along, meaning
> simpler code.

I'm inclined to agree, but playing Devil's advocate here, as a device
using the MFD subsystem it's often clearer to readers and other people
looking for examples if the MFD core functionality is used. For
instance, I now have no idea what devices the PM8xxx encompasses
without looking at the DTS file. A small cell structure is a small
price to pay for code clarity IMHO.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v2 3/7] mfd: pm8921: Migrate to irqdomains
  2014-01-07  8:22       ` Lee Jones
@ 2014-01-07 19:54         ` Stephen Boyd
  2014-01-08  8:14           ` Lee Jones
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Boyd @ 2014-01-07 19:54 UTC (permalink / raw)
  To: Lee Jones; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

On 01/07, Lee Jones wrote:
> > >> +	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> > >> +}
> > > Can't you use the MFD core instead?
> > >
> > 
> > Are you suggesting using mfd_add_devices()? At first glance it looks
> > like that would require an array of mfd_cell structures that do nothing
> > besides match compatible strings in the DT. Using of_platform_populate()
> > achieves the same goal and doesn't require an array of mfd_cell
> > structures for each different pm8xxx chip that comes along, meaning
> > simpler code.
> 
> I'm inclined to agree, but playing Devil's advocate here, as a device
> using the MFD subsystem it's often clearer to readers and other people
> looking for examples if the MFD core functionality is used. For
> instance, I now have no idea what devices the PM8xxx encompasses
> without looking at the DTS file. A small cell structure is a small
> price to pay for code clarity IMHO.
> 

Why not just put that information in the binding document? And
how is this different from adding a bunch of C files to match a
set of compatible strings that a dts file has just so that we can
add all the devices on a board (think board files for an SoC).
Sure it documents the devices on a board, but we've been moving
away from that by using of_platform_populate().

IMHO the code is clear. I want to add all subnodes of this
device's node as children struct devices. Using
of_platform_populate() says that, whereas mfd_add_devices() says
I want to add these specific subnodes of this device's node.

Also, as more drivers are written and more bindings are ratified
this platform driver will need to be updated with more cells and
more compatible strings, causing more inter-tree dependencies and
more patches. Please, let's avoid this if we can.

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

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

* Re: [PATCH v2 3/7] mfd: pm8921: Migrate to irqdomains
  2014-01-07 19:54         ` Stephen Boyd
@ 2014-01-08  8:14           ` Lee Jones
  0 siblings, 0 replies; 23+ messages in thread
From: Lee Jones @ 2014-01-08  8:14 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

On Tue, 07 Jan 2014, Stephen Boyd wrote:

> On 01/07, Lee Jones wrote:
> > > >> +	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> > > >> +}
> > > > Can't you use the MFD core instead?
> > > >
> > > 
> > > Are you suggesting using mfd_add_devices()? At first glance it looks
> > > like that would require an array of mfd_cell structures that do nothing
> > > besides match compatible strings in the DT. Using of_platform_populate()
> > > achieves the same goal and doesn't require an array of mfd_cell
> > > structures for each different pm8xxx chip that comes along, meaning
> > > simpler code.
> > 
> > I'm inclined to agree, but playing Devil's advocate here, as a device
> > using the MFD subsystem it's often clearer to readers and other people
> > looking for examples if the MFD core functionality is used. For
> > instance, I now have no idea what devices the PM8xxx encompasses
> > without looking at the DTS file. A small cell structure is a small
> > price to pay for code clarity IMHO.
> > 
> 
> Why not just put that information in the binding document? And
> how is this different from adding a bunch of C files to match a
> set of compatible strings that a dts file has just so that we can
> add all the devices on a board (think board files for an SoC).
> Sure it documents the devices on a board, but we've been moving
> away from that by using of_platform_populate().
> 
> IMHO the code is clear. I want to add all subnodes of this
> device's node as children struct devices. Using
> of_platform_populate() says that, whereas mfd_add_devices() says
> I want to add these specific subnodes of this device's node.
> 
> Also, as more drivers are written and more bindings are ratified
> this platform driver will need to be updated with more cells and
> more compatible strings, causing more inter-tree dependencies and
> more patches. Please, let's avoid this if we can.

Okay, that's fine. There are a few discussions floating around about
this. If I find some time, I'll have to have a think about the pros
and cons of either approach. This is okay for now.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

end of thread, other threads:[~2014-01-08  8:14 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-23 20:45 [PATCH v2 0/7] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
2013-12-23 20:45 ` [PATCH v2 1/7] mfd: Move pm8xxx-irq.c contents into only driver that uses it Stephen Boyd
2014-01-06 14:47   ` Lee Jones
2013-12-23 20:45 ` [PATCH v2 2/7] mfd: pm8921: Update for genirq changes Stephen Boyd
2013-12-23 20:45 ` [PATCH v2 3/7] mfd: pm8921: Migrate to irqdomains Stephen Boyd
2014-01-06 15:53   ` Lee Jones
2014-01-06 20:33     ` Stephen Boyd
2014-01-07  8:22       ` Lee Jones
2014-01-07 19:54         ` Stephen Boyd
2014-01-08  8:14           ` Lee Jones
2013-12-23 20:46 ` [PATCH v2 4/7] mfd: ssbi: Add regmap read/write helpers Stephen Boyd
2013-12-24 12:54   ` Mark Brown
2013-12-26 19:41     ` Stephen Boyd
2013-12-28 14:52       ` Mark Brown
2014-01-06 11:50       ` Lee Jones
2014-01-06 22:26         ` Stephen Boyd
2013-12-23 20:46 ` [PATCH v2 5/7] mfd: pm8921: Use ssbi regmap Stephen Boyd
2013-12-30 12:34   ` Mark Brown
2013-12-23 20:46 ` [PATCH v2 6/7] mfd: pm8921: Add DT match table Stephen Boyd
2014-01-06 11:52   ` Lee Jones
2014-01-06 18:03     ` Stephen Boyd
     [not found] ` <1387831563-13535-1-git-send-email-sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2013-12-23 20:46   ` [PATCH v2 7/7] devicetree: bindings: Document PM8921/8058 PMICs Stephen Boyd
2014-01-06 11:53     ` Lee Jones

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).