linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/2] Add support for Qualcomm MFD PMIC register layout
@ 2021-03-23 18:43 Guru Das Srinagesh
  2021-03-23 18:43 ` [PATCH v4 1/2] regmap-irq: Introduce virtual regs to handle more config regs Guru Das Srinagesh
  2021-03-23 18:43 ` [PATCH v4 2/2] regmap-irq: Add driver callback to configure virtual regs Guru Das Srinagesh
  0 siblings, 2 replies; 3+ messages in thread
From: Guru Das Srinagesh @ 2021-03-23 18:43 UTC (permalink / raw)
  To: Mark Brown, Markus Elfring, Lee Jones, Rob Herring
  Cc: Bjorn Andersson, Greg KH, Guenter Roeck, Joe Perches,
	Subbaraman Narayanamurthy, David Collins, Anirudh Ghayal,
	linux-arm-msm, linux-kernel, devicetree, Guru Das Srinagesh

Changes from v3:
- Implemented the scheme proposed in my response to Mark in [4].
- Dropped the RFC tag from this patch series as this series has been tested on
  target with a client driver utilizing these changes.

Changes from v2:
- Split up framework changes patch for better comprehension.
- Dropped PM8008 driver example and converted it into example code in cover
  letter and commit text.
- Added more info in cover letter and commit message as per v2 feedback.

This is a follow-up as promised [1] to the earlier attempts [2] [3] to upstream
the driver that has been hitherto used to handle IRQs for Qualcomm's PMICs that
have multiple on-board peripherals when they are interfaced over the I2C
interface.

This series is a rewrite of that driver while making use of the regmap-irq
framework, which needs some modifications to handle the register layout of
Qualcomm's PMICs. This is an RFC because I would like to get feedback on my
general approach before submitting as a patch per se.

Qualcomm's MFD chips have a top level interrupt status register and sub-irqs
(peripherals).  When a bit in the main status register goes high, it means that
the peripheral corresponding to that bit has an unserviced interrupt. If the
bit is not set, this means that the corresponding peripheral does not.

The differences between Qualcomm's register layout and what the regmap-irq
framework assumes are best described with an example:

Suppose that there are three peripherals onboard an MFD chip: MISC, TEMP_ALARM
and GPIO01. Each of these peripherals has the following IRQ configuration
registers: mask, type and ack. There is a top level interrupt status register
and per-peripheral status registers as well (not shown below).

The regmap-irq framework expects all similar registers to be at a fixed stride
from each other, for each peripheral, as below (with stride = 1). 

	/* All mask registers together */
	MISC_INT_MASK		0x1011
	TEMP_ALARM_INT_MASK	0x1012
	GPIO01_INT_MASK		0x1013
	
	/* All type registers together */
	MISC_INT_TYPE		0x2011
	TEMP_ALARM_INT_TYPE	0x2012
	GPIO01_INT_TYPE		0x2013
	
	/* All ack registers together */
	MISC_INT_ACK		0x3011
	TEMP_ALARM_INT_ACK	0x3012
	GPIO01_INT_ACK		0x3013

In contrast, QCOM's registers are laid out as follows:

	/* All of MISC peripheral's registers together */
	MISC_INT_MASK		0x1011
	MISC_INT_TYPE		0x1012
	MISC_INT_ACK		0x1013

	/* All of TEMP_ALARM peripheral's registers together */
	TEMP_ALARM_INT_MASK	0x2011
	TEMP_ALARM_INT_TYPE	0x2012
	TEMP_ALARM_INT_ACK	0x2013
	
	/* All of GPIO01 peripheral's registers together */
	GPIO01_INT_MASK		0x3011
	GPIO01_INT_TYPE		0x3012
	GPIO01_INT_ACK		0x3013

As is evident, the different IRQ configuration registers are just (0x11, 0x12,
0x13) with offsets of (0x1000, 0x2000 and 0x3000) respectively in QCOM's case.
If the *_base registers fed to the struct regmap_irq_chip could be set to the
first peripheral (MISC in this example), then through the sub_reg_offsets
mechanism, we could add the offsets _to_ the *_base register values to get at
the configuration registers for each peripheral.

Hopefully this will help when reviewing the changes in this series.

[1] https://lore.kernel.org/lkml/20200519185757.GA13992@codeaurora.org/
[2] https://lore.kernel.org/lkml/cover.1588037638.git.gurus@codeaurora.org/
[3] https://lore.kernel.org/lkml/cover.1588115326.git.gurus@codeaurora.org/
[4] https://lore.kernel.org/lkml/20210315203336.GA8977@codeaurora.org/

Guru Das Srinagesh (2):
  regmap-irq: Introduce virtual regs to handle more config regs
  regmap-irq: Add driver callback to configure virtual regs

 drivers/base/regmap/regmap-irq.c | 43 +++++++++++++++++++++++++++++++++++++++-
 include/linux/regmap.h           |  9 +++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)

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


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

* [PATCH v4 1/2] regmap-irq: Introduce virtual regs to handle more config regs
  2021-03-23 18:43 [PATCH v4 0/2] Add support for Qualcomm MFD PMIC register layout Guru Das Srinagesh
@ 2021-03-23 18:43 ` Guru Das Srinagesh
  2021-03-23 18:43 ` [PATCH v4 2/2] regmap-irq: Add driver callback to configure virtual regs Guru Das Srinagesh
  1 sibling, 0 replies; 3+ messages in thread
From: Guru Das Srinagesh @ 2021-03-23 18:43 UTC (permalink / raw)
  To: Mark Brown, Markus Elfring, Lee Jones, Rob Herring
  Cc: Bjorn Andersson, Greg KH, Guenter Roeck, Joe Perches,
	Subbaraman Narayanamurthy, David Collins, Anirudh Ghayal,
	linux-arm-msm, linux-kernel, devicetree, Guru Das Srinagesh

Add "virtual" registers support to handle any irq configuration
registers in addition to the ones the framework currently supports
(status, mask, unmask, wake, type and ack). These are non-standard
registers that further configure irq type on some devices, so enable the
framework to add a variable number of them.

Signed-off-by: Guru Das Srinagesh <gurus@codeaurora.org>
---
 drivers/base/regmap/regmap-irq.c | 38 +++++++++++++++++++++++++++++++++++++-
 include/linux/regmap.h           |  5 +++++
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index e1d8fc9e..d1ade76 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -38,6 +38,7 @@ struct regmap_irq_chip_data {
 	unsigned int *wake_buf;
 	unsigned int *type_buf;
 	unsigned int *type_buf_def;
+	unsigned int **virt_buf;
 
 	unsigned int irq_reg_stride;
 	unsigned int type_reg_stride;
@@ -94,7 +95,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
 {
 	struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
 	struct regmap *map = d->map;
-	int i, ret;
+	int i, j, ret;
 	u32 reg;
 	u32 unmask_offset;
 	u32 val;
@@ -218,6 +219,20 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
 		}
 	}
 
+	if (d->chip->num_virt_regs) {
+		for (i = 0; i < d->chip->num_virt_regs; i++) {
+			for (j = 0; j < d->chip->num_regs; j++) {
+				reg = sub_irq_reg(d, d->chip->virt_reg_base[i],
+						  j);
+				ret = regmap_write(map, reg, d->virt_buf[i][j]);
+				if (ret != 0)
+					dev_err(d->map->dev,
+						"Failed to write virt 0x%x: %d\n",
+						reg, ret);
+			}
+		}
+	}
+
 	if (d->chip->runtime_pm)
 		pm_runtime_put(map->dev);
 
@@ -691,6 +706,24 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
 			goto err_alloc;
 	}
 
+	if (chip->num_virt_regs) {
+		/*
+		 * Create virt_buf[chip->num_extra_config_regs][chip->num_regs]
+		 */
+		d->virt_buf = kcalloc(chip->num_virt_regs, sizeof(*d->virt_buf),
+				      GFP_KERNEL);
+		if (!d->virt_buf)
+			goto err_alloc;
+
+		for (i = 0; i < chip->num_virt_regs; i++) {
+			d->virt_buf[i] = kcalloc(chip->num_regs,
+						 sizeof(unsigned int),
+						 GFP_KERNEL);
+			if (!d->virt_buf[i])
+				goto err_alloc;
+		}
+	}
+
 	d->irq_chip = regmap_irq_chip;
 	d->irq_chip.name = chip->name;
 	d->irq = irq;
@@ -863,6 +896,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
 	kfree(d->mask_buf);
 	kfree(d->status_buf);
 	kfree(d->status_reg_buf);
+	for (i = 0; i < chip->num_virt_regs; i++)
+		kfree(d->virt_buf[i]);
+	kfree(d->virt_buf);
 	kfree(d);
 	return ret;
 }
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 18910bd..4c75717 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -1383,6 +1383,8 @@ struct regmap_irq_sub_irq_map {
  *		     peripheral to first peripheral.
  * @num_main_regs: Number of 'main status' irq registers for chips which have
  *		   main_status set.
+ * @num_virt_regs: Number of non-standard irq configuration registers.
+ *		   If zero unsupported.
  *
  * @status_base: Base status register address.
  * @mask_base:   Base mask register address.
@@ -1393,6 +1395,7 @@ struct regmap_irq_sub_irq_map {
  *               Using zero value is possible with @use_ack bit.
  * @wake_base:   Base address for wake enables.  If zero unsupported.
  * @type_base:   Base address for irq type.  If zero unsupported.
+ * @virt_reg_base:   Base addresses for extra config regs.
  * @irq_reg_stride:  Stride to use for chips where registers are not contiguous.
  * @init_ack_masked: Ack all masked interrupts once during initalization.
  * @mask_invert: Inverted mask register: cleared bits are masked out.
@@ -1437,6 +1440,7 @@ struct regmap_irq_chip {
 	unsigned int num_main_status_bits;
 	struct regmap_irq_sub_irq_map *sub_reg_offsets;
 	int num_main_regs;
+	int num_virt_regs;
 
 	unsigned int status_base;
 	unsigned int mask_base;
@@ -1444,6 +1448,7 @@ struct regmap_irq_chip {
 	unsigned int ack_base;
 	unsigned int wake_base;
 	unsigned int type_base;
+	unsigned int *virt_reg_base;
 	unsigned int irq_reg_stride;
 	bool mask_writeonly:1;
 	bool init_ack_masked:1;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


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

* [PATCH v4 2/2] regmap-irq: Add driver callback to configure virtual regs
  2021-03-23 18:43 [PATCH v4 0/2] Add support for Qualcomm MFD PMIC register layout Guru Das Srinagesh
  2021-03-23 18:43 ` [PATCH v4 1/2] regmap-irq: Introduce virtual regs to handle more config regs Guru Das Srinagesh
@ 2021-03-23 18:43 ` Guru Das Srinagesh
  1 sibling, 0 replies; 3+ messages in thread
From: Guru Das Srinagesh @ 2021-03-23 18:43 UTC (permalink / raw)
  To: Mark Brown, Markus Elfring, Lee Jones, Rob Herring
  Cc: Bjorn Andersson, Greg KH, Guenter Roeck, Joe Perches,
	Subbaraman Narayanamurthy, David Collins, Anirudh Ghayal,
	linux-arm-msm, linux-kernel, devicetree, Guru Das Srinagesh

Enable drivers to configure and modify "virtual" registers, which are
non-standard registers that further configure irq type on some devices.
Since they are non-standard, enable drivers to configure them according
to their particular idiosyncrasies by specifying an optional callback
function while registering with the framework.

Signed-off-by: Guru Das Srinagesh <gurus@codeaurora.org>
---
 drivers/base/regmap/regmap-irq.c | 5 +++++
 include/linux/regmap.h           | 4 ++++
 2 files changed, 9 insertions(+)

diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index d1ade76..e6343ccc 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -333,6 +333,11 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type)
 	default:
 		return -EINVAL;
 	}
+
+	if (d->chip->set_type_virt)
+		return d->chip->set_type_virt(d->virt_buf, type, data->hwirq,
+					      reg);
+
 	return 0;
 }
 
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 4c75717..7cf143ce 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -1426,6 +1426,8 @@ struct regmap_irq_sub_irq_map {
  *		     before regmap_irq_handler process the interrupts.
  * @handle_post_irq: Driver specific callback to handle interrupt from device
  *		     after handling the interrupts in regmap_irq_handler().
+ * @set_type_virt:   Driver specific callback to extend regmap_irq_set_type()
+ *		     and configure virt regs.
  * @irq_drv_data:    Driver specific IRQ data which is passed as parameter when
  *		     driver specific pre/post interrupt handler is called.
  *
@@ -1473,6 +1475,8 @@ struct regmap_irq_chip {
 
 	int (*handle_pre_irq)(void *irq_drv_data);
 	int (*handle_post_irq)(void *irq_drv_data);
+	int (*set_type_virt)(unsigned int **buf, unsigned int type,
+			     unsigned long hwirq, int reg);
 	void *irq_drv_data;
 };
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


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

end of thread, other threads:[~2021-03-23 18:44 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-23 18:43 [PATCH v4 0/2] Add support for Qualcomm MFD PMIC register layout Guru Das Srinagesh
2021-03-23 18:43 ` [PATCH v4 1/2] regmap-irq: Introduce virtual regs to handle more config regs Guru Das Srinagesh
2021-03-23 18:43 ` [PATCH v4 2/2] regmap-irq: Add driver callback to configure virtual regs Guru Das Srinagesh

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).