linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/8] Modernize pm8921 with irqdomains, regmap, DT
@ 2014-02-26 18:59 Stephen Boyd
  2014-02-26 18:59 ` [PATCH v4 1/8] mfd: Move pm8xxx-irq.c contents into only driver that uses it Stephen Boyd
                   ` (7 more replies)
  0 siblings, 8 replies; 17+ messages in thread
From: Stephen Boyd @ 2014-02-26 18:59 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones
  Cc: linux-kernel, linux-arm-msm, devicetree, Mark Brown, linux-arm-kernel

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 v3:
 * Added irqdomain Kconfig select
 * New patch to loosen Kconfig on PM8921 config
 * Picked up acked-by

Changes since v2:
 * Picked up reviewed-by tags
 * Fixed irqdomain teardown in driver remove
 * No magical 256 constant
 * Renamed domain to irqdomain
 * Clarified kzalloc call
 * Pushed ssbi regmap helpers into header file
 * Fixed whitespace noise in patch 6

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 (8):
  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
  mfd: pm8921: Loosen Kconfig dependency
  devicetree: bindings: Document PM8921/8058 PMICs

 .../devicetree/bindings/mfd/qcom,pm8xxx.txt        |  63 +++
 drivers/mfd/Kconfig                                |  15 +-
 drivers/mfd/Makefile                               |   1 -
 drivers/mfd/pm8921-core.c                          | 427 ++++++++++++++++++---
 drivers/mfd/pm8xxx-irq.c                           | 371 ------------------
 include/linux/mfd/pm8xxx/irq.h                     |  59 ---
 include/linux/mfd/pm8xxx/pm8921.h                  |  30 --
 include/linux/ssbi.h                               |  20 +
 8 files changed, 460 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


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

* [PATCH v4 1/8] mfd: Move pm8xxx-irq.c contents into only driver that uses it
  2014-02-26 18:59 [PATCH v4 0/8] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
@ 2014-02-26 18:59 ` Stephen Boyd
  2014-02-27  8:33   ` Lee Jones
  2014-02-26 18:59 ` [PATCH v4 2/8] mfd: pm8921: Update for genirq changes Stephen Boyd
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Stephen Boyd @ 2014-02-26 18:59 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.

Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/mfd/Kconfig            |  10 --
 drivers/mfd/Makefile           |   1 -
 drivers/mfd/pm8921-core.c      | 348 ++++++++++++++++++++++++++++++++++++++
 drivers/mfd/pm8xxx-irq.c       | 371 -----------------------------------------
 include/linux/mfd/pm8xxx/irq.h |  23 ---
 5 files changed, 348 insertions(+), 405 deletions(-)
 delete mode 100644 drivers/mfd/pm8xxx-irq.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 49bb445d846a..b4431d2995a1 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -487,16 +487,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/Makefile b/drivers/mfd/Makefile
index 5aea5ef0a62f..311c01409503 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -150,7 +150,6 @@ obj-$(CONFIG_MFD_SI476X_CORE)	+= si476x-core.o
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o omap-usb-tll.o
 obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o ssbi.o
-obj-$(CONFIG_MFD_PM8XXX_IRQ) 	+= pm8xxx-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)	+= tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090)	+= tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE)	+= aat2870-core.o
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 484fe66e6c88..50e0a9b69b9d 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 1360e20adf11..000000000000
--- 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 f83d6b43ecbb..1a11b02383f0 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] 17+ messages in thread

* [PATCH v4 2/8] mfd: pm8921: Update for genirq changes
  2014-02-26 18:59 [PATCH v4 0/8] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
  2014-02-26 18:59 ` [PATCH v4 1/8] mfd: Move pm8xxx-irq.c contents into only driver that uses it Stephen Boyd
@ 2014-02-26 18:59 ` Stephen Boyd
  2014-02-27  8:34   ` Lee Jones
  2014-02-26 18:59 ` [PATCH v4 3/8] mfd: pm8921: Migrate to irqdomains Stephen Boyd
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Stephen Boyd @ 2014-02-26 18:59 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 b4431d2995a1..bee2d2c81c2a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -474,7 +474,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 50e0a9b69b9d..9ddc31f7a71d 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] 17+ messages in thread

* [PATCH v4 3/8] mfd: pm8921: Migrate to irqdomains
  2014-02-26 18:59 [PATCH v4 0/8] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
  2014-02-26 18:59 ` [PATCH v4 1/8] mfd: Move pm8xxx-irq.c contents into only driver that uses it Stephen Boyd
  2014-02-26 18:59 ` [PATCH v4 2/8] mfd: pm8921: Update for genirq changes Stephen Boyd
@ 2014-02-26 18:59 ` Stephen Boyd
  2014-02-27  8:34   ` Lee Jones
  2014-02-26 18:59 ` [PATCH v4 4/8] mfd: ssbi: Add regmap read/write helpers Stephen Boyd
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Stephen Boyd @ 2014-02-26 18:59 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.

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         | 198 +++++++++++++++-----------------------
 include/linux/mfd/pm8xxx/irq.h    |  36 -------
 include/linux/mfd/pm8xxx/pm8921.h |  30 ------
 4 files changed, 76 insertions(+), 189 deletions(-)
 delete mode 100644 include/linux/mfd/pm8xxx/irq.h
 delete mode 100644 include/linux/mfd/pm8xxx/pm8921.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index bee2d2c81c2a..c9b672c5dfa8 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -474,6 +474,7 @@ config MFD_PM8XXX
 config MFD_PM8921_CORE
 	tristate "Qualcomm PM8921 PMIC chip"
 	depends on (ARCH_MSM || HEXAGON)
+	select IRQ_DOMAIN
 	select MFD_CORE
 	select MFD_PM8XXX
 	help
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 9ddc31f7a71d..c25e7dae150b 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
 
@@ -53,11 +53,12 @@
 #define REG_HWREV		0x002  /* PMIC4 revision */
 #define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
 
+#define PM8921_NR_IRQS		256
+
 struct pm_irq_chip {
 	struct device		*dev;
 	spinlock_t		pm_irq_lock;
-	unsigned int		devirq;
-	unsigned int		irq_base;
+	struct irq_domain	*irqdomain;
 	unsigned int		num_irqs;
 	unsigned int		num_blocks;
 	unsigned int		num_masters;
@@ -138,7 +139,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->irqdomain, pmirq);
 			generic_handle_irq(irq);
 		}
 	}
@@ -197,12 +198,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 +212,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 +226,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 +285,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,67 +316,29 @@ bail_out:
 	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);
-	}
+static struct lock_class_key pm8xxx_irq_lock_class;
 
-	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);
+static int pm8xxx_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				   irq_hw_number_t hwirq)
+{
+	struct pm_irq_chip *chip = d->host_data;
 
-	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);
+	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(chip->irq_base + pmirq, IRQF_VALID);
+	set_irq_flags(irq, IRQF_VALID);
 #else
-		irq_set_noprobe(chip->irq_base + pmirq);
+	irq_set_noprobe(irq);
 #endif
-	}
-
-	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);
-
-	return chip;
-}
-
-static int pm8xxx_irq_exit(struct pm_irq_chip *chip)
-{
-	irq_set_chained_handler(chip->devirq, NULL);
-	kfree(chip);
 	return 0;
 }
 
+static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
+	.xlate = irq_domain_xlate_twocell,
+	.map = pm8xxx_irq_domain_map,
+};
+
 static int pm8921_readb(const struct device *dev, u16 addr, u8 *val)
 {
 	const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
@@ -432,42 +389,19 @@ 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;
+	struct pm_irq_chip *chip;
+	unsigned int nirqs = PM8921_NR_IRQS;
 
-	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 +432,55 @@ 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);
+	chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
+					sizeof(chip->config[0]) * nirqs,
+					GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	pmic->irq_chip = chip;
+	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);
+
+	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, nirqs,
+						&pm8xxx_irq_domain_ops,
+						chip);
+	if (!chip->irqdomain)
+		return -ENODEV;
+
+	irq_set_handler_data(irq, chip);
+	irq_set_chained_handler(irq, pm8xxx_irq_handler);
+	irq_set_irq_wake(irq, 1);
+
+	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
 	if (rc) {
-		pr_err("Cannot add subdevices rc=%d\n", rc);
-		goto err;
+		irq_set_chained_handler(irq, NULL);
+		irq_set_handler_data(irq, NULL);
+		irq_domain_remove(chip->irqdomain);
 	}
 
-	/* gpio might not work if no irq device is found */
-	WARN_ON(pmic->irq_chip == NULL);
+	return rc;
+}
 
+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;
-		}
-	}
+	int irq = platform_get_irq(pdev, 0);
+	struct pm8921 *pmic = pm8921_drvdata.pm_chip_data;
+	struct pm_irq_chip *chip = pmic->irq_chip;
+
+	device_for_each_child(&pdev->dev, NULL, pm8921_remove_child);
+	irq_set_chained_handler(irq, NULL);
+	irq_set_handler_data(irq, NULL);
+	irq_domain_remove(chip->irqdomain);
 
 	return 0;
 }
diff --git a/include/linux/mfd/pm8xxx/irq.h b/include/linux/mfd/pm8xxx/irq.h
deleted file mode 100644
index 1a11b02383f0..000000000000
--- 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 00fa3de7659d..000000000000
--- 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] 17+ messages in thread

* [PATCH v4 4/8] mfd: ssbi: Add regmap read/write helpers
  2014-02-26 18:59 [PATCH v4 0/8] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
                   ` (2 preceding siblings ...)
  2014-02-26 18:59 ` [PATCH v4 3/8] mfd: pm8921: Migrate to irqdomains Stephen Boyd
@ 2014-02-26 18:59 ` Stephen Boyd
  2014-02-27  8:35   ` Lee Jones
  2014-02-26 18:59 ` [PATCH v4 5/8] mfd: pm8921: Use ssbi regmap Stephen Boyd
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Stephen Boyd @ 2014-02-26 18:59 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 registers via a "no-bus" regmap.

Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 include/linux/ssbi.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/include/linux/ssbi.h b/include/linux/ssbi.h
index bcbb642a7641..087b08a4d333 100644
--- a/include/linux/ssbi.h
+++ b/include/linux/ssbi.h
@@ -20,4 +20,24 @@
 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);
 
+static inline int
+ssbi_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+	int ret;
+	u8 v;
+
+	ret = ssbi_read(context, reg, &v, 1);
+	if (!ret)
+		*val = v;
+
+	return ret;
+}
+
+static inline int
+ssbi_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+	u8 v = val;
+	return ssbi_write(context, reg, &v, 1);
+}
+
 #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] 17+ messages in thread

* [PATCH v4 5/8] mfd: pm8921: Use ssbi regmap
  2014-02-26 18:59 [PATCH v4 0/8] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
                   ` (3 preceding siblings ...)
  2014-02-26 18:59 ` [PATCH v4 4/8] mfd: ssbi: Add regmap read/write helpers Stephen Boyd
@ 2014-02-26 18:59 ` Stephen Boyd
  2014-02-27  8:35   ` Lee Jones
  2014-02-26 18:59 ` [PATCH v4 6/8] mfd: pm8921: Add DT match table Stephen Boyd
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Stephen Boyd @ 2014-02-26 18:59 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel

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>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/mfd/Kconfig       |  1 +
 drivers/mfd/pm8921-core.c | 66 +++++++++++++++++++++++++++--------------------
 2 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c9b672c5dfa8..be98d88acfb8 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -477,6 +477,7 @@ config MFD_PM8921_CORE
 	select IRQ_DOMAIN
 	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 c25e7dae150b..e9340bd6d1ab 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>
@@ -57,6 +58,7 @@
 
 struct pm_irq_chip {
 	struct device		*dev;
+	struct regmap		*regmap;
 	spinlock_t		pm_irq_lock;
 	struct irq_domain	*irqdomain;
 	unsigned int		num_irqs;
@@ -70,29 +72,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:
@@ -100,19 +92,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:
@@ -123,7 +116,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) {
@@ -148,10 +141,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;
@@ -173,12 +167,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;
@@ -283,7 +277,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);
 
@@ -294,14 +288,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);
@@ -389,11 +383,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;
 	struct pm_irq_chip *chip;
@@ -409,8 +413,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;
@@ -419,7 +428,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);
@@ -440,6 +449,7 @@ static int pm8921_probe(struct platform_device *pdev)
 
 	pmic->irq_chip = chip;
 	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);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


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

* [PATCH v4 6/8] mfd: pm8921: Add DT match table
  2014-02-26 18:59 [PATCH v4 0/8] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
                   ` (4 preceding siblings ...)
  2014-02-26 18:59 ` [PATCH v4 5/8] mfd: pm8921: Use ssbi regmap Stephen Boyd
@ 2014-02-26 18:59 ` Stephen Boyd
  2014-02-27  8:35   ` Lee Jones
  2014-02-26 18:59 ` [PATCH v4 7/8] mfd: pm8921: Loosen Kconfig dependency Stephen Boyd
  2014-02-26 18:59 ` [PATCH v4 8/8] devicetree: bindings: Document PM8921/8058 PMICs Stephen Boyd
  7 siblings, 1 reply; 17+ messages in thread
From: Stephen Boyd @ 2014-02-26 18:59 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.

Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/mfd/pm8921-core.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index e9340bd6d1ab..3aab6ace5eb5 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -392,6 +392,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;
@@ -501,6 +508,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] 17+ messages in thread

* [PATCH v4 7/8] mfd: pm8921: Loosen Kconfig dependency
  2014-02-26 18:59 [PATCH v4 0/8] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
                   ` (5 preceding siblings ...)
  2014-02-26 18:59 ` [PATCH v4 6/8] mfd: pm8921: Add DT match table Stephen Boyd
@ 2014-02-26 18:59 ` Stephen Boyd
  2014-02-27  8:37   ` Lee Jones
  2014-02-26 18:59 ` [PATCH v4 8/8] devicetree: bindings: Document PM8921/8058 PMICs Stephen Boyd
  7 siblings, 1 reply; 17+ messages in thread
From: Stephen Boyd @ 2014-02-26 18:59 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel

Allow this driver to be compiled on all ARM builds as it doesn't
rely on anything within arm/mach-msm.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/mfd/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index be98d88acfb8..42d592a2e392 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -473,7 +473,7 @@ config MFD_PM8XXX
 
 config MFD_PM8921_CORE
 	tristate "Qualcomm PM8921 PMIC chip"
-	depends on (ARCH_MSM || HEXAGON)
+	depends on (ARM || HEXAGON)
 	select IRQ_DOMAIN
 	select MFD_CORE
 	select MFD_PM8XXX
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


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

* [PATCH v4 8/8] devicetree: bindings: Document PM8921/8058 PMICs
  2014-02-26 18:59 [PATCH v4 0/8] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
                   ` (6 preceding siblings ...)
  2014-02-26 18:59 ` [PATCH v4 7/8] mfd: pm8921: Loosen Kconfig dependency Stephen Boyd
@ 2014-02-26 18:59 ` Stephen Boyd
  2014-02-27  8:38   ` Lee Jones
  7 siblings, 1 reply; 17+ messages in thread
From: Stephen Boyd @ 2014-02-26 18:59 UTC (permalink / raw)
  To: Samuel Ortiz, Lee Jones
  Cc: 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>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.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 000000000000..e3fe625ffd58
--- /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


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

* Re: [PATCH v4 1/8] mfd: Move pm8xxx-irq.c contents into only driver that uses it
  2014-02-26 18:59 ` [PATCH v4 1/8] mfd: Move pm8xxx-irq.c contents into only driver that uses it Stephen Boyd
@ 2014-02-27  8:33   ` Lee Jones
  0 siblings, 0 replies; 17+ messages in thread
From: Lee Jones @ 2014-02-27  8:33 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Samuel Ortiz, 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.
> 
> Acked-by: Lee Jones <lee.jones@linaro.org>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/mfd/Kconfig            |  10 --
>  drivers/mfd/Makefile           |   1 -
>  drivers/mfd/pm8921-core.c      | 348 ++++++++++++++++++++++++++++++++++++++
>  drivers/mfd/pm8xxx-irq.c       | 371 -----------------------------------------
>  include/linux/mfd/pm8xxx/irq.h |  23 ---
>  5 files changed, 348 insertions(+), 405 deletions(-)
>  delete mode 100644 drivers/mfd/pm8xxx-irq.c

Applied, thanks.

-- 
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] 17+ messages in thread

* Re: [PATCH v4 2/8] mfd: pm8921: Update for genirq changes
  2014-02-26 18:59 ` [PATCH v4 2/8] mfd: pm8921: Update for genirq changes Stephen Boyd
@ 2014-02-27  8:34   ` Lee Jones
  0 siblings, 0 replies; 17+ messages in thread
From: Lee Jones @ 2014-02-27  8:34 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Samuel Ortiz, 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(-)

Applied, thanks.

-- 
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] 17+ messages in thread

* Re: [PATCH v4 3/8] mfd: pm8921: Migrate to irqdomains
  2014-02-26 18:59 ` [PATCH v4 3/8] mfd: pm8921: Migrate to irqdomains Stephen Boyd
@ 2014-02-27  8:34   ` Lee Jones
  0 siblings, 0 replies; 17+ messages in thread
From: Lee Jones @ 2014-02-27  8:34 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

On Wed, 26 Feb 2014, Stephen Boyd wrote:

> Convert this driver to use irqdomains so that the PMIC's child
> devices can be converted to devicetree.
> 
> 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         | 198 +++++++++++++++-----------------------
>  include/linux/mfd/pm8xxx/irq.h    |  36 -------
>  include/linux/mfd/pm8xxx/pm8921.h |  30 ------
>  4 files changed, 76 insertions(+), 189 deletions(-)
>  delete mode 100644 include/linux/mfd/pm8xxx/irq.h
>  delete mode 100644 include/linux/mfd/pm8xxx/pm8921.h

Applied, thanks.

-- 
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] 17+ messages in thread

* Re: [PATCH v4 4/8] mfd: ssbi: Add regmap read/write helpers
  2014-02-26 18:59 ` [PATCH v4 4/8] mfd: ssbi: Add regmap read/write helpers Stephen Boyd
@ 2014-02-27  8:35   ` Lee Jones
  0 siblings, 0 replies; 17+ messages in thread
From: Lee Jones @ 2014-02-27  8:35 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Samuel Ortiz, linux-arm-msm, Mark Brown, linux-kernel, linux-arm-kernel

On Wed, 26 Feb 2014, Stephen Boyd wrote:

> Add read and write helper functions that the pm8921-core driver
> can use to read and write ssbi registers via a "no-bus" regmap.
> 
> Cc: Mark Brown <broonie@kernel.org>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  include/linux/ssbi.h | 20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)

Applied, thanks.

-- 
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] 17+ messages in thread

* Re: [PATCH v4 5/8] mfd: pm8921: Use ssbi regmap
  2014-02-26 18:59 ` [PATCH v4 5/8] mfd: pm8921: Use ssbi regmap Stephen Boyd
@ 2014-02-27  8:35   ` Lee Jones
  0 siblings, 0 replies; 17+ messages in thread
From: Lee Jones @ 2014-02-27  8:35 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

On Wed, 26 Feb 2014, 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>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/mfd/Kconfig       |  1 +
>  drivers/mfd/pm8921-core.c | 66 +++++++++++++++++++++++++++--------------------
>  2 files changed, 39 insertions(+), 28 deletions(-)

Applied, thanks.

-- 
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] 17+ messages in thread

* Re: [PATCH v4 6/8] mfd: pm8921: Add DT match table
  2014-02-26 18:59 ` [PATCH v4 6/8] mfd: pm8921: Add DT match table Stephen Boyd
@ 2014-02-27  8:35   ` Lee Jones
  0 siblings, 0 replies; 17+ messages in thread
From: Lee Jones @ 2014-02-27  8:35 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

On Wed, 26 Feb 2014, Stephen Boyd wrote:

> Allow this driver to probe based on devicetree.
> 
> Acked-by: Lee Jones <lee.jones@linaro.org>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/mfd/pm8921-core.c | 8 ++++++++
>  1 file changed, 8 insertions(+)

Applied, thanks.

-- 
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] 17+ messages in thread

* Re: [PATCH v4 7/8] mfd: pm8921: Loosen Kconfig dependency
  2014-02-26 18:59 ` [PATCH v4 7/8] mfd: pm8921: Loosen Kconfig dependency Stephen Boyd
@ 2014-02-27  8:37   ` Lee Jones
  0 siblings, 0 replies; 17+ messages in thread
From: Lee Jones @ 2014-02-27  8:37 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Samuel Ortiz, linux-kernel, linux-arm-msm, linux-arm-kernel

On Wed, 26 Feb 2014, Stephen Boyd wrote:

> Allow this driver to be compiled on all ARM builds as it doesn't
> rely on anything within arm/mach-msm.
> 
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/mfd/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks.

-- 
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] 17+ messages in thread

* Re: [PATCH v4 8/8] devicetree: bindings: Document PM8921/8058 PMICs
  2014-02-26 18:59 ` [PATCH v4 8/8] devicetree: bindings: Document PM8921/8058 PMICs Stephen Boyd
@ 2014-02-27  8:38   ` Lee Jones
  0 siblings, 0 replies; 17+ messages in thread
From: Lee Jones @ 2014-02-27  8:38 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>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  .../devicetree/bindings/mfd/qcom,pm8xxx.txt        | 63 ++++++++++++++++++++++
>  1 file changed, 63 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt

This patch has been on the MLs for some time now and hasn't received
any feedback from the DT guys.

Patch looks good (despite the lack IRQ defines), applied.

-- 
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] 17+ messages in thread

end of thread, other threads:[~2014-02-27  8:39 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-26 18:59 [PATCH v4 0/8] Modernize pm8921 with irqdomains, regmap, DT Stephen Boyd
2014-02-26 18:59 ` [PATCH v4 1/8] mfd: Move pm8xxx-irq.c contents into only driver that uses it Stephen Boyd
2014-02-27  8:33   ` Lee Jones
2014-02-26 18:59 ` [PATCH v4 2/8] mfd: pm8921: Update for genirq changes Stephen Boyd
2014-02-27  8:34   ` Lee Jones
2014-02-26 18:59 ` [PATCH v4 3/8] mfd: pm8921: Migrate to irqdomains Stephen Boyd
2014-02-27  8:34   ` Lee Jones
2014-02-26 18:59 ` [PATCH v4 4/8] mfd: ssbi: Add regmap read/write helpers Stephen Boyd
2014-02-27  8:35   ` Lee Jones
2014-02-26 18:59 ` [PATCH v4 5/8] mfd: pm8921: Use ssbi regmap Stephen Boyd
2014-02-27  8:35   ` Lee Jones
2014-02-26 18:59 ` [PATCH v4 6/8] mfd: pm8921: Add DT match table Stephen Boyd
2014-02-27  8:35   ` Lee Jones
2014-02-26 18:59 ` [PATCH v4 7/8] mfd: pm8921: Loosen Kconfig dependency Stephen Boyd
2014-02-27  8:37   ` Lee Jones
2014-02-26 18:59 ` [PATCH v4 8/8] devicetree: bindings: Document PM8921/8058 PMICs Stephen Boyd
2014-02-27  8:38   ` 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).