* Re: [PATCH 08/23] driver core: platform: provide platform_device_set_of_node_from_dev()
From: Andy Shevchenko @ 2026-06-16 9:41 UTC (permalink / raw)
To: Johan Hovold
Cc: Bartosz Golaszewski, Lee Jones, Mark Brown, Thierry Reding,
Sebastian Hesselbarth, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Srinivas Kandagatla,
Greg Kroah-Hartman, Vinod Koul, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Saravana Kannan,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Andi Shyti, Joerg Roedel,
Will Deacon, Robin Murphy, Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Ulf Hansson, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Matthew Brost, Thomas Hellström, Rodrigo Vivi, David Airlie,
Simona Vetter, Peter Chen, Paul Cercueil, Bin Liu, Philipp Zabel,
Maximilian Luz, Hans de Goede, Ilpo Järvinen,
Krzysztof Kozlowski, Benjamin Herrenschmidt, brgl, linux-kernel,
netdev, linux-arm-msm, linux-sound, driver-core, devicetree,
linuxppc-dev, linux-i2c, iommu, linux-pm, imx, linux-arm-kernel,
intel-xe, dri-devel, linux-usb, linux-mips, platform-driver-x86
In-Reply-To: <aiZpJkQBXg2pcczy@hovoldconsulting.com>
On Mon, Jun 08, 2026 at 09:03:02AM +0200, Johan Hovold wrote:
> On Fri, Jun 05, 2026 at 05:53:04PM +0300, Andy Shevchenko wrote:
> > On Fri, Jun 05, 2026 at 02:16:17PM +0200, Johan Hovold wrote:
> > > On Wed, Jun 03, 2026 at 12:44:55AM +0300, Andy Shevchenko wrote:
> > > > On Thu, May 21, 2026 at 10:36:31AM +0200, Bartosz Golaszewski wrote:
> > > > > Provide a platform-specific variant of device_set_of_node_from_dev(). In
> > > > > addition to bumping the reference count of the OF node being assigned,
> > > > > it also assigns the fwnode of the platform device.
> > > >
> > > > Can we rather investigate the way how to make that of node reuse thingy
> > > > (which is used solely by pin control) differently and then drop this confusing
> > > > device_set_of_node_from_dev() call altogether?
> > >
> > > No, that call is needed. See commit 4e75e1d7dac9 ("driver core: add
> > > helper to reuse a device-tree node") for details.
> >
> > Bart fixes the problem with the platform driver. At the result this will be
> > the only device_set_node() + 'reused = true'. As for 'reused' flag, the need
> > is only for pinmux/pin control stuff.
>
> And any other resource which may (eventually) be claimed by driver core
> or bus code.
>
> > The question here is if there is a better
> > way to make that 'reused' be done automatically without need of setting some
> > flag explicitly.
>
> That's not really relevant to the series at hand.
It's not, but it's relevant in a long-term for understanding how we can get
this done in a better way.
> If this is something we want to merge then you need to continue setting
> the flag in order not to cause regressions.
Yes, that's how it's now.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v3 3/8] irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper
From: sashiko-bot @ 2026-06-16 9:36 UTC (permalink / raw)
To: Maulik Shah; +Cc: devicetree, conor+dt, robh
In-Reply-To: <20260616-hamoa_pdc_v3-v3-3-4d8e1504ea75@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Uninitialized spinlock acquired during driver probe.
--
commit ff89675171bbba82a63beea5300191b24d1a290f
Author: Maulik Shah <maulik.shah@oss.qualcomm.com>
irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper
This commit removes the pdc_enable_intr() wrapper and moves its locking
into pdc_enable_intr_bank(), as the lock is only needed for the shared
bank and not for individual IRQ_CFG registers.
> diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
> index b9acb0f25c9c8..6c556464d37c0 100644
> --- a/drivers/irqchip/qcom-pdc.c
> +++ b/drivers/irqchip/qcom-pdc.c
> @@ -206,6 +206,8 @@ static void pdc_enable_intr_bank(int pin_out, bool on)
> index = FIELD_GET(IRQ_ENABLE_BANK_INDEX_MASK, pin_out);
> mask = FIELD_GET(IRQ_ENABLE_BANK_BIT_MASK, pin_out);
>
> + guard(raw_spinlock)(&pdc->lock);
[Severity: High]
Does this cause an uninitialized spinlock to be acquired during driver probe?
Looking at qcom_pdc_probe(), the lock is initialized after setting up the pin
mapping:
qcom_pdc_probe() {
...
ret = pdc_setup_pin_mapping(dev, node);
...
raw_spin_lock_init(&pdc->lock);
...
}
And pdc_setup_pin_mapping() invokes pdc->enable_intr() for each pin:
pdc_setup_pin_mapping() {
...
for (int i = 0; i < pdc->region[n].cnt; i++)
pdc->enable_intr(i + pdc->region[n].pin_base, 0);
...
}
Previously, pdc_setup_pin_mapping() bypassed the lock because it was held in
the pdc_enable_intr() wrapper, not the enable_intr() callback. By moving the
lock down into pdc_enable_intr_bank(), won't the probe sequence now attempt to
acquire a zero-initialized lock before it has been initialized with
raw_spin_lock_init()?
> +
> enable = pdc_reg_read(pdc->regs->irq_en_reg, index);
> __assign_bit(mask, &enable, on);
>
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260616-hamoa_pdc_v3-v3-0-4d8e1504ea75@oss.qualcomm.com?part=3
^ permalink raw reply
* Re: [PATCH v3 05/12] iio: dac: ad5686: add support for missing power supplies
From: Joshua Crofts @ 2026-06-16 9:33 UTC (permalink / raw)
To: Rodrigo Alencar via B4 Relay
Cc: rodrigo.alencar, Michael Auchter, linux, linux-iio, devicetree,
linux-kernel, linux-hardening, Michael Hennerich,
Jonathan Cameron, David Lechner, Andy Shevchenko, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, Kees Cook,
Gustavo A. R. Silva
In-Reply-To: <20260616-ad5686-new-features-v3-5-f829fb7e9262@analog.com>
On Tue, 16 Jun 2026 09:21:11 +0100
Rodrigo Alencar via B4 Relay <devnull+rodrigo.alencar.analog.com@kernel.org> wrote:
> st->use_internal_vref = ret == -ENODEV;
> st->vref_mv = st->use_internal_vref ? st->chip_info->int_vref_mv : ret / 1000;
I'd use a macro from <linux/units.h> instead of just doing / 1000.
> + if (!st->vref_mv)
> + return dev_err_probe(dev, -EINVAL,
> + "invalid or not provided vref voltage\n");
> +
> + fsleep(5); /* power-up time */
I'd recommend using a macro to define the sleep time, removing
the need for a comment.
> /* Initialize masks to all ones */
> st->pwr_down_mask = ~0;
>
Otherwise LGTM!
--
Kind regards
CJD
^ permalink raw reply
* [PATCH v3 8/8] arm64: dts: qcom: x1e80100: Add deepest idle state
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
In-Reply-To: <20260616-hamoa_pdc_v3-v3-0-4d8e1504ea75@oss.qualcomm.com>
Add deepest idle state as GPIO IRQs can work as wakeup capable interrupts
in deepest idle state.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/hamoa.dtsi | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi
index 4ba751a65142..47e425003028 100644
--- a/arch/arm64/boot/dts/qcom/hamoa.dtsi
+++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi
@@ -302,6 +302,14 @@ cluster_cl5: cluster-sleep-1 {
exit-latency-us = <4000>;
min-residency-us = <7000>;
};
+
+ domain_ss3: domain-sleep-0 {
+ compatible = "domain-idle-state";
+ arm,psci-suspend-param = <0x0200c354>;
+ entry-latency-us = <2800>;
+ exit-latency-us = <4400>;
+ min-residency-us = <9000>;
+ };
};
};
@@ -460,7 +468,7 @@ cluster_pd2: power-domain-cpu-cluster2 {
system_pd: power-domain-system {
#power-domain-cells = <0>;
- /* TODO: system-wide idle states */
+ domain-idle-states = <&domain_ss3>;
};
};
--
2.43.0
^ permalink raw reply related
* [PATCH v3 7/8] Revert "pinctrl: qcom: x1e80100: Bypass PDC wakeup parent for now"
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
In-Reply-To: <20260616-hamoa_pdc_v3-v3-0-4d8e1504ea75@oss.qualcomm.com>
This reverts commit 602cb14e310a ("pinctrl: qcom: x1e80100: Bypass PDC
wakeup parent for now").
PDC interrupts no more break GPIOs PDC irqchip is updated to work for
pass through or secondary mode. Update nwakeirq_map to reflect the GPIO
to PDC irq map size.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/pinctrl/qcom/pinctrl-x1e80100.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/pinctrl/qcom/pinctrl-x1e80100.c b/drivers/pinctrl/qcom/pinctrl-x1e80100.c
index 8d2b8246170b..e4c0abcd95b9 100644
--- a/drivers/pinctrl/qcom/pinctrl-x1e80100.c
+++ b/drivers/pinctrl/qcom/pinctrl-x1e80100.c
@@ -1836,9 +1836,7 @@ static const struct msm_pinctrl_soc_data x1e80100_pinctrl = {
.ngroups = ARRAY_SIZE(x1e80100_groups),
.ngpios = 239,
.wakeirq_map = x1e80100_pdc_map,
- /* TODO: Enabling PDC currently breaks GPIO interrupts */
- .nwakeirq_map = 0,
- /* .nwakeirq_map = ARRAY_SIZE(x1e80100_pdc_map), */
+ .nwakeirq_map = ARRAY_SIZE(x1e80100_pdc_map),
.egpio_func = 9,
};
--
2.43.0
^ permalink raw reply related
* [PATCH v3 6/8] pinctrl: qcom: Acknowledge IRQs for PDC interrupt controller
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah, Stephan Gerhold
In-Reply-To: <20260616-hamoa_pdc_v3-v3-0-4d8e1504ea75@oss.qualcomm.com>
From: Stephan Gerhold <stephan.gerhold@linaro.org>
PDC needs to acknowledge incoming GPIO interrupts to clear the latched
interrupt status in secondary mode of PDC. For level-triggered IRQs this
happens automatically in irq_eoi() but for edge-triggered IRQs this needs
to happen as early as possible in the IRQ handler.
Implement this by using handle_fasteoi_ack_irq() as IRQ handler in this
situation and forward the irq_ack() callback to the parent IRQ chip.
Signed-off-by: Stephan Gerhold <stephan.gerhold@linaro.org>
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/pinctrl/qcom/pinctrl-msm.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 11db6564c44d..17665e1a9dbc 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -995,6 +995,16 @@ static void msm_gpio_irq_ack(struct irq_data *d)
if (test_bit(d->hwirq, pctrl->skip_wake_irqs)) {
if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
msm_gpio_update_dual_edge_parent(d);
+
+ /*
+ * During early initialization of the IRQ hierarchy,
+ * irq_ack() is called by __irq_set_handler() before
+ * the parent IRQ chip has been set up. This is why
+ * we additionally need to check for d->parent_data->chip.
+ */
+
+ if (d->parent_data->chip && d->parent_data->chip->irq_ack)
+ irq_chip_ack_parent(d);
return;
}
@@ -1067,7 +1077,10 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
if (test_bit(d->hwirq, pctrl->skip_wake_irqs)) {
clear_bit(d->hwirq, pctrl->dual_edge_irqs);
- irq_set_handler_locked(d, handle_fasteoi_irq);
+ if (type & IRQ_TYPE_LEVEL_MASK)
+ irq_set_handler_locked(d, handle_fasteoi_irq);
+ else
+ irq_set_handler_locked(d, handle_fasteoi_ack_irq);
return 0;
}
@@ -1395,6 +1408,7 @@ static const struct irq_chip msm_gpio_irq_chip = {
.flags = (IRQCHIP_MASK_ON_SUSPEND |
IRQCHIP_SET_TYPE_MASKED |
IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND |
+ IRQCHIP_EOI_THREADED |
IRQCHIP_IMMUTABLE),
};
--
2.43.0
^ permalink raw reply related
* [PATCH v3 5/8] irqchip/qcom-pdc: Configure PDC to pass through mode
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
In-Reply-To: <20260616-hamoa_pdc_v3-v3-0-4d8e1504ea75@oss.qualcomm.com>
All PDC irqchip supports pass through mode in which both Direct SPIs and
GPIO IRQs (as SPIs) are sent to GIC without latching at PDC.
Newer PDCs (v3.0 onwards) also support additional secondary controller mode
where PDC latches GPIO IRQs and sends to GIC as level type IRQ. Direct SPIs
still works same as pass through mode without latching at PDC even in
secondary controller mode.
All the SoCs so far default uses pass through mode with the exception of
x1e. x1e PDC may be set to secondary controller mode for builds on CRD
boards whereas it may be set to pass through mode for IoT-EVK boards.
The mode configuration is done in firmware and initially shipped windows
firmware did not have SCM interface to read or modify the PDC mode.
Later only write access is opened up for non secure world.
Using the write access available add changes to modify the PDC mode to
pass through mode via SCM write. When the write fails (on older firmware)
assume to work in secondary mode.
In secondary mode set the separate irqchip for the GPIOs to perform
additional operations only for the GPIO irqs.
Co-developed-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
Signed-off-by: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/irqchip/qcom-pdc.c | 220 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 208 insertions(+), 12 deletions(-)
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 1aa6be42307c..c6f2935ff788 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -20,12 +20,18 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/firmware/qcom/qcom_scm.h>
#define PDC_MAX_IRQS 256
#define IRQ_ENABLE_BANK_MAX BITS_TO_BYTES(PDC_MAX_IRQS)
#define IRQ_ENABLE_BANK_INDEX_MASK GENMASK(31, 5)
#define IRQ_ENABLE_BANK_BIT_MASK GENMASK(4, 0)
+/* Secure DRV register to configure the PDC mode via qcom_scm_io_writel() */
+#define PDC_GPIO_INT_CTL_ENABLE 0xb2045e8
+#define PDC_PASS_THROUGH_MODE 0x0
+#define PDC_SECONDARY_MODE 0x1
+
#define PDC_DRV_SIZE 0x10000
#define PDC_VERSION_REG 0x1000
#define PDC_VERSION_MAJOR GENMASK(23, 16)
@@ -85,10 +91,14 @@ struct pdc_regs {
/**
* struct pdc_irq_cfg: bit fields for PDC IRQ_CFG register
*
+ * @gpio_irq_sts: bit number for GPIO_STATUS field
+ * @gpio_irq_mask: bit number for GPIO_MASK field
* @irq_enable: bit number for IRQ_ENABLE field
* @irq_type: GENMASK for IRQ_TYPE field
*/
struct pdc_irq_cfg {
+ u32 gpio_irq_sts;
+ u32 gpio_irq_mask;
u32 irq_enable;
u32 irq_type;
};
@@ -103,11 +113,14 @@ struct pdc_irq_cfg {
* @num_gpios: Total number of GPIOs forwarded as SPI interrupts
* @region: PDC interrupt continuous range
* @region_cnt: Total PDC ranges
+ * @mode: PDC_PASS_THROUGH_MODE or PDC_SECONDARY_MODE
* @x1e_quirk: x1e H/W Bug handling
* @lock: lock for IRQ_ENABLE_BANK protection
* @regs: PDC regs (IRQ_ENABLE_BANK and IRQ_CFG)
* @cfg_fields: Fields of IRQ_CFG reg
* @enable_intr: pointer to enable function based on PDC version
+ * @unmask_gpio: pointer to GPIO irq unmask function
+ * @clear_gpio: pointer to GPIO irq clear function
*/
struct pdc_desc {
void __iomem *base;
@@ -119,6 +132,7 @@ struct pdc_desc {
struct pdc_pin_region *region;
int region_cnt;
+ u8 mode;
bool x1e_quirk;
raw_spinlock_t lock;
@@ -127,6 +141,8 @@ struct pdc_desc {
const struct pdc_irq_cfg *cfg_fields;
void (*enable_intr)(int pin_out, bool on);
+ void (*unmask_gpio)(int pin_out, bool on);
+ void (*clear_gpio)(int pin_out);
};
static const struct pdc_regs pdc_v3_2 = {
@@ -135,6 +151,8 @@ static const struct pdc_regs pdc_v3_2 = {
};
static const struct pdc_irq_cfg pdc_cfg_v3_2 = {
+ .gpio_irq_sts = 5,
+ .gpio_irq_mask = 4,
.irq_enable = 3,
.irq_type = GENMASK(2, 0),
};
@@ -146,6 +164,8 @@ static const struct pdc_regs pdc_v3_0 = {
};
static const struct pdc_irq_cfg pdc_cfg_v3_0 = {
+ .gpio_irq_sts = 4,
+ .gpio_irq_mask = 3,
.irq_type = GENMASK(2, 0),
};
@@ -184,6 +204,15 @@ static u32 pdc_reg_read(int reg, u32 i)
return readl_relaxed(pdc->base + reg + i * sizeof(u32));
}
+static inline bool pdc_pin_is_gpio(int pin_out)
+{
+ /*
+ * PDC allocates direct SPIs at the beginning and
+ * all GPIOs as SPIs are allocated after direct SPIs.
+ */
+ return pin_out >= pdc->num_spis;
+}
+
static void pdc_x1e_irq_enable_write(u32 bank, u32 enable)
{
void __iomem *base;
@@ -231,6 +260,30 @@ static void pdc_enable_intr_bank(int pin_out, bool on)
pdc_reg_write(pdc->regs->irq_en_reg, index, enable);
}
+static void pdc_clear_gpio_cfg(int pin_out)
+{
+ unsigned long gpio_sts;
+
+ if (pdc->version < PDC_VERSION_3_0)
+ return;
+
+ gpio_sts = pdc_reg_read(pdc->regs->irq_cfg_reg, pin_out);
+ __clear_bit(pdc->cfg_fields->gpio_irq_sts, &gpio_sts);
+ pdc_reg_write(pdc->regs->irq_cfg_reg, pin_out, gpio_sts);
+}
+
+static void pdc_unmask_gpio_cfg(int pin_out, bool unmask)
+{
+ unsigned long gpio_mask;
+
+ if (pdc->version < PDC_VERSION_3_0)
+ return;
+
+ gpio_mask = pdc_reg_read(pdc->regs->irq_cfg_reg, pin_out);
+ __assign_bit(pdc->cfg_fields->gpio_irq_mask, &gpio_mask, !unmask);
+ pdc_reg_write(pdc->regs->irq_cfg_reg, pin_out, gpio_mask);
+}
+
static void pdc_enable_intr_cfg(int pin_out, bool on)
{
unsigned long enable = pdc_reg_read(pdc->regs->irq_cfg_reg, pin_out);
@@ -245,12 +298,40 @@ static void qcom_pdc_gic_disable(struct irq_data *d)
irq_chip_disable_parent(d);
}
+static void qcom_pdc_gic_secondary_disable(struct irq_data *d)
+{
+ pdc->enable_intr(d->hwirq, false);
+ pdc->unmask_gpio(d->hwirq, false);
+ irq_chip_disable_parent(d);
+}
+
static void qcom_pdc_gic_enable(struct irq_data *d)
{
pdc->enable_intr(d->hwirq, true);
irq_chip_enable_parent(d);
}
+static void qcom_pdc_gic_secondary_enable(struct irq_data *d)
+{
+ pdc->enable_intr(d->hwirq, true);
+ pdc->unmask_gpio(d->hwirq, true);
+ irq_chip_enable_parent(d);
+}
+
+static void qcom_pdc_secondary_ack(struct irq_data *d)
+{
+ if (!irqd_is_level_type(d))
+ pdc->clear_gpio(d->hwirq);
+}
+
+static void qcom_pdc_gic_secondary_eoi(struct irq_data *d)
+{
+ if (irqd_is_level_type(d))
+ pdc->clear_gpio(d->hwirq);
+
+ irq_chip_eoi_parent(d);
+}
+
/*
* GIC does not handle falling edge or active low. To allow falling edge and
* active low interrupts to be handled at GIC, PDC has an inverter that inverts
@@ -338,6 +419,67 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
return 0;
}
+/**
+ * qcom_pdc_gic_set_type: Configure PDC for the interrupt
+ *
+ * @d: the interrupt data
+ * @type: the interrupt type
+ *
+ * All @type are forwarded as Level type to parent GIC
+ */
+static int qcom_pdc_gic_secondary_set_type(struct irq_data *d, unsigned int type)
+{
+ enum pdc_irq_config_bits pdc_type;
+ enum pdc_irq_config_bits old_pdc_type;
+ int ret;
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ pdc_type = PDC_EDGE_RISING;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ pdc_type = PDC_EDGE_FALLING;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ pdc_type = PDC_EDGE_DUAL;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ pdc_type = PDC_LEVEL_HIGH;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ pdc_type = PDC_LEVEL_LOW;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ old_pdc_type = pdc_reg_read(pdc->regs->irq_cfg_reg, d->hwirq);
+ pdc_type |= (old_pdc_type & ~pdc->cfg_fields->irq_type);
+ pdc_reg_write(pdc->regs->irq_cfg_reg, d->hwirq, pdc_type);
+
+ type = IRQ_TYPE_LEVEL_HIGH;
+ pdc->clear_gpio(d->hwirq);
+
+ ret = irq_chip_set_type_parent(d, type);
+ if (ret)
+ return ret;
+
+ /*
+ * When we change types the PDC can give a phantom interrupt.
+ * Clear it. Specifically the phantom shows up when reconfiguring
+ * polarity of interrupt without changing the state of the signal
+ * but let's be consistent and clear it always.
+ *
+ * Doing this works because we have IRQCHIP_SET_TYPE_MASKED so the
+ * interrupt will be cleared before the rest of the system sees it.
+ */
+ if (old_pdc_type != pdc_type)
+ irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, false);
+
+ return 0;
+}
+
static struct irq_chip qcom_pdc_gic_chip = {
.name = "PDC",
.irq_eoi = irq_chip_eoi_parent,
@@ -357,6 +499,26 @@ static struct irq_chip qcom_pdc_gic_chip = {
.irq_set_affinity = irq_chip_set_affinity_parent,
};
+static struct irq_chip qcom_pdc_gic_secondary_chip = {
+ .name = "PDC",
+ .irq_ack = qcom_pdc_secondary_ack,
+ .irq_eoi = qcom_pdc_gic_secondary_eoi,
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_disable = qcom_pdc_gic_secondary_disable,
+ .irq_enable = qcom_pdc_gic_secondary_enable,
+ .irq_get_irqchip_state = irq_chip_get_parent_state,
+ .irq_set_irqchip_state = irq_chip_set_parent_state,
+ .irq_retrigger = irq_chip_retrigger_hierarchy,
+ .irq_set_type = qcom_pdc_gic_secondary_set_type,
+ .flags = IRQCHIP_MASK_ON_SUSPEND |
+ IRQCHIP_SET_TYPE_MASKED |
+ IRQCHIP_SKIP_SET_WAKE |
+ IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND,
+ .irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+};
+
static struct pdc_pin_region *get_pin_region(int pin)
{
for (int i = 0; i < pdc->region_cnt; i++) {
@@ -385,20 +547,37 @@ static int qcom_pdc_alloc(struct irq_domain *domain, unsigned int virq,
if (hwirq == GPIO_NO_WAKE_IRQ)
return irq_domain_disconnect_hierarchy(domain, virq);
- ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
- &qcom_pdc_gic_chip, NULL);
- if (ret)
- return ret;
+ /*
+ * PDC secondary chip is only set for the GPIO interrupts as SPIs.
+ * Direct SPI interrupts are still in pass through mode (no latching
+ * at PDC).
+ */
+ if (pdc->mode == PDC_PASS_THROUGH_MODE || !pdc_pin_is_gpio(hwirq)) {
+ ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+ &qcom_pdc_gic_chip,
+ NULL);
+ if (ret)
+ return ret;
- region = get_pin_region(hwirq);
- if (!region)
- return irq_domain_disconnect_hierarchy(domain->parent, virq);
+ if (type & IRQ_TYPE_EDGE_BOTH)
+ type = IRQ_TYPE_EDGE_RISING;
- if (type & IRQ_TYPE_EDGE_BOTH)
- type = IRQ_TYPE_EDGE_RISING;
+ if (type & IRQ_TYPE_LEVEL_MASK)
+ type = IRQ_TYPE_LEVEL_HIGH;
+ } else {
+ ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+ &qcom_pdc_gic_secondary_chip,
+ NULL);
+ if (ret)
+ return ret;
- if (type & IRQ_TYPE_LEVEL_MASK)
+ /* Secondary mode converts all interrupts to LEVEL HIGH type */
type = IRQ_TYPE_LEVEL_HIGH;
+ }
+
+ region = get_pin_region(hwirq);
+ if (!region)
+ return irq_domain_disconnect_hierarchy(domain->parent, virq);
parent_fwspec.fwnode = domain->parent->fwnode;
parent_fwspec.param_count = 3;
@@ -449,8 +628,13 @@ static int pdc_setup_pin_mapping(struct device *dev, struct device_node *np)
if (ret)
return ret;
- for (int i = 0; i < pdc->region[n].cnt; i++)
- pdc->enable_intr(i + pdc->region[n].pin_base, 0);
+ for (int i = 0; i < pdc->region[n].cnt; i++) {
+ if (pdc_pin_is_gpio(i + pdc->region[n].pin_base) &&
+ pdc->mode == PDC_SECONDARY_MODE)
+ pdc->clear_gpio(i + pdc->region[n].pin_base);
+
+ pdc->enable_intr(i + pdc->region[n].pin_base, false);
+ }
}
return 0;
@@ -501,6 +685,8 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
pdc->enable_intr = pdc_enable_intr_bank;
}
+ pdc->mode = PDC_PASS_THROUGH_MODE;
+
/*
* PDC has multiple DRV regions, each one provides the same set of
* registers for a particular client in the system. Due to a hardware
@@ -518,6 +704,16 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
}
pdc->x1e_quirk = true;
+
+ if (!qcom_scm_is_available())
+ return -EPROBE_DEFER;
+
+ ret = qcom_scm_io_writel(PDC_GPIO_INT_CTL_ENABLE, PDC_PASS_THROUGH_MODE);
+ if (ret) {
+ pdc->mode = PDC_SECONDARY_MODE;
+ pdc->unmask_gpio = pdc_unmask_gpio_cfg;
+ pdc->clear_gpio = pdc_clear_gpio_cfg;
+ }
}
irq_param = pdc_reg_read(pdc->regs->irq_param_reg, 0);
--
2.43.0
^ permalink raw reply related
* [PATCH v3 4/8] irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
In-Reply-To: <20260616-hamoa_pdc_v3-v3-0-4d8e1504ea75@oss.qualcomm.com>
Before commit 4dc70713dc24 ("irqchip/qcom-pdc: Kill non-wakeup irqdomain")
there are separate domains for direct SPIs and GPIO used as SPIs. Separate
domains can be useful in case irqchip want to differentiate both of them.
Since commit unified both the domains there is no way to differentiate.
In preparation to add the second level interrupt controller support where
GPIO interrupts get latched at PDC (but not direct SPIs) there is a need to
differentiate between SPIs and GPIOs as SPIs. Reverting above commit do not
seem a good option either which leads to waste of resources.
PDC HW have the IRQ_PARAM register telling number of direct SPIs and number
of GPIOs as SPIs. Further PDC allocates direct SPIs at the beginning and
all GPIOs as SPIs are allocated at the end. This information can be used in
driver to differentiate them.
Add the support to read this register and keep this information in
struct pdc_desc. Later change utilizes same.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/irqchip/qcom-pdc.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 6c556464d37c..1aa6be42307c 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -61,6 +61,11 @@
* | | [4] GPIO_STATUS| [4] GPIO_MASK |
* | [31:3] Unused | [3] GPIO_MASK | [3] IRQ_ENABLE |
* | [0:2] Type | [0:2] Type | [0:2] Type |
+ * |---------------------------------------------------------------|
+ * | IRQ_PARAM | IRQ_PARAM | IRQ_PARAM |
+ * | | |
+ * | [15:8] NUM_GPIO | [15:8] NUM_GPIO | [15:8] NUM_GPIO |
+ * | [7:0] NUM_SPI | [7:0] NUM_SPI | [7:0] NUM_SPI |
* +---------------------------------------------------------------+
*/
@@ -69,10 +74,12 @@
*
* @irq_en_reg: IRQ_ENABLE_BANK register location
* @irq_cfg_reg: IRQ_CFG register location
+ * @irq_param_reg: IRQ_PARAM register location
*/
struct pdc_regs {
u32 irq_en_reg;
u32 irq_cfg_reg;
+ u32 irq_param_reg;
};
/**
@@ -92,6 +99,8 @@ struct pdc_irq_cfg {
* @base: PDC base register for DRV2 / HLOS
* @prev_base: PDC DRV1 base, applicable only for x1e RTL bug.
* @version: PDC version
+ * @num_spis: Total number of direct SPI interrupts
+ * @num_gpios: Total number of GPIOs forwarded as SPI interrupts
* @region: PDC interrupt continuous range
* @region_cnt: Total PDC ranges
* @x1e_quirk: x1e H/W Bug handling
@@ -104,6 +113,8 @@ struct pdc_desc {
void __iomem *base;
void __iomem *prev_base;
u32 version;
+ u32 num_spis;
+ u32 num_gpios;
struct pdc_pin_region *region;
int region_cnt;
@@ -120,6 +131,7 @@ struct pdc_desc {
static const struct pdc_regs pdc_v3_2 = {
.irq_cfg_reg = 0x110,
+ .irq_param_reg = 0x100c,
};
static const struct pdc_irq_cfg pdc_cfg_v3_2 = {
@@ -130,6 +142,7 @@ static const struct pdc_irq_cfg pdc_cfg_v3_2 = {
static const struct pdc_regs pdc_v3_0 = {
.irq_en_reg = 0x10,
.irq_cfg_reg = 0x110,
+ .irq_param_reg = 0x100c,
};
static const struct pdc_irq_cfg pdc_cfg_v3_0 = {
@@ -139,6 +152,7 @@ static const struct pdc_irq_cfg pdc_cfg_v3_0 = {
static const struct pdc_regs pdc_v2_7 = {
.irq_en_reg = 0x10,
.irq_cfg_reg = 0x110,
+ .irq_param_reg = 0x100c,
};
static const struct pdc_irq_cfg pdc_cfg_v2_7 = {
@@ -449,6 +463,7 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
struct device *dev = &pdev->dev;
resource_size_t res_size;
struct resource res;
+ u32 irq_param;
int ret;
/* compat with old sm8150 DT which had very small region for PDC */
@@ -505,6 +520,10 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
pdc->x1e_quirk = true;
}
+ irq_param = pdc_reg_read(pdc->regs->irq_param_reg, 0);
+ pdc->num_spis = FIELD_GET(GENMASK(7, 0), irq_param);
+ pdc->num_gpios = FIELD_GET(GENMASK(15, 8), irq_param);
+
parent_domain = irq_find_host(parent);
if (!parent_domain) {
pr_err("%pOF: unable to find PDC's parent domain\n", node);
--
2.43.0
^ permalink raw reply related
* [PATCH v3 3/8] irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
In-Reply-To: <20260616-hamoa_pdc_v3-v3-0-4d8e1504ea75@oss.qualcomm.com>
pdc->enable_intr() function already points to respective version
specific enable function. pdc_enable_intr() now only kept as wrapper.
Remove the wrapper and invoke pdc->enable_intr() from caller.
Locking in pdc_enable_intr() applies lock to all pdc->enable_intr()
however its only required for pdc_enable_intr_bank() which uses
a shared bank across all interrupts. pdc_enable_intr_cfg() do not
required locking as IRQ_CFG registers are one per interrupt. Move
locking accordingly.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/irqchip/qcom-pdc.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index b9acb0f25c9c..6c556464d37c 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -206,6 +206,8 @@ static void pdc_enable_intr_bank(int pin_out, bool on)
index = FIELD_GET(IRQ_ENABLE_BANK_INDEX_MASK, pin_out);
mask = FIELD_GET(IRQ_ENABLE_BANK_BIT_MASK, pin_out);
+ guard(raw_spinlock)(&pdc->lock);
+
enable = pdc_reg_read(pdc->regs->irq_en_reg, index);
__assign_bit(mask, &enable, on);
@@ -223,22 +225,15 @@ static void pdc_enable_intr_cfg(int pin_out, bool on)
pdc_reg_write(pdc->regs->irq_cfg_reg, pin_out, enable);
}
-static void pdc_enable_intr(struct irq_data *d, bool on)
-{
- guard(raw_spinlock)(&pdc->lock);
-
- pdc->enable_intr(d->hwirq, on);
-}
-
static void qcom_pdc_gic_disable(struct irq_data *d)
{
- pdc_enable_intr(d, false);
+ pdc->enable_intr(d->hwirq, false);
irq_chip_disable_parent(d);
}
static void qcom_pdc_gic_enable(struct irq_data *d)
{
- pdc_enable_intr(d, true);
+ pdc->enable_intr(d->hwirq, true);
irq_chip_enable_parent(d);
}
--
2.43.0
^ permalink raw reply related
* [PATCH v3 2/8] irqchip/qcom-pdc: Move all statics to struct pdc_desc
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
In-Reply-To: <20260616-hamoa_pdc_v3-v3-0-4d8e1504ea75@oss.qualcomm.com>
There are multiple statics used. Move all to struct pdc_desc to better
align with versioning support. Document them.
No functional impact.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/irqchip/qcom-pdc.c | 77 ++++++++++++++++++++++++----------------------
1 file changed, 40 insertions(+), 37 deletions(-)
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 23276325211d..b9acb0f25c9c 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -92,15 +92,30 @@ struct pdc_irq_cfg {
* @base: PDC base register for DRV2 / HLOS
* @prev_base: PDC DRV1 base, applicable only for x1e RTL bug.
* @version: PDC version
+ * @region: PDC interrupt continuous range
+ * @region_cnt: Total PDC ranges
+ * @x1e_quirk: x1e H/W Bug handling
+ * @lock: lock for IRQ_ENABLE_BANK protection
* @regs: PDC regs (IRQ_ENABLE_BANK and IRQ_CFG)
* @cfg_fields: Fields of IRQ_CFG reg
+ * @enable_intr: pointer to enable function based on PDC version
*/
struct pdc_desc {
void __iomem *base;
void __iomem *prev_base;
u32 version;
+
+ struct pdc_pin_region *region;
+ int region_cnt;
+
+ bool x1e_quirk;
+
+ raw_spinlock_t lock;
+
const struct pdc_regs *regs;
const struct pdc_irq_cfg *cfg_fields;
+
+ void (*enable_intr)(int pin_out, bool on);
};
static const struct pdc_regs pdc_v3_2 = {
@@ -138,11 +153,6 @@ struct pdc_pin_region {
#define pin_to_hwirq(r, p) ((r)->parent_base + (p) - (r)->pin_base)
-static DEFINE_RAW_SPINLOCK(pdc_lock);
-static struct pdc_pin_region *pdc_region;
-static int pdc_region_cnt;
-static unsigned int pdc_version;
-static bool pdc_x1e_quirk;
static struct pdc_desc *pdc;
static void pdc_base_reg_write(void __iomem *base, int reg, u32 i, u32 val)
@@ -199,7 +209,7 @@ static void pdc_enable_intr_bank(int pin_out, bool on)
enable = pdc_reg_read(pdc->regs->irq_en_reg, index);
__assign_bit(mask, &enable, on);
- if (pdc_x1e_quirk)
+ if (pdc->x1e_quirk)
pdc_x1e_irq_enable_write(index, enable);
else
pdc_reg_write(pdc->regs->irq_en_reg, index, enable);
@@ -213,21 +223,11 @@ static void pdc_enable_intr_cfg(int pin_out, bool on)
pdc_reg_write(pdc->regs->irq_cfg_reg, pin_out, enable);
}
-static void __pdc_enable_intr(int pin_out, bool on)
-{
- if (pdc_version < PDC_VERSION_3_2)
- pdc_enable_intr_bank(pin_out, on);
- else
- pdc_enable_intr_cfg(pin_out, on);
-}
-
static void pdc_enable_intr(struct irq_data *d, bool on)
{
- unsigned long flags;
+ guard(raw_spinlock)(&pdc->lock);
- raw_spin_lock_irqsave(&pdc_lock, flags);
- __pdc_enable_intr(d->hwirq, on);
- raw_spin_unlock_irqrestore(&pdc_lock, flags);
+ pdc->enable_intr(d->hwirq, on);
}
static void qcom_pdc_gic_disable(struct irq_data *d)
@@ -350,12 +350,10 @@ static struct irq_chip qcom_pdc_gic_chip = {
static struct pdc_pin_region *get_pin_region(int pin)
{
- int i;
-
- for (i = 0; i < pdc_region_cnt; i++) {
- if (pin >= pdc_region[i].pin_base &&
- pin < pdc_region[i].pin_base + pdc_region[i].cnt)
- return &pdc_region[i];
+ for (int i = 0; i < pdc->region_cnt; i++) {
+ if (pin >= pdc->region[i].pin_base &&
+ pin < pdc->region[i].pin_base + pdc->region[i].cnt)
+ return &pdc->region[i];
}
return NULL;
@@ -411,39 +409,39 @@ static const struct irq_domain_ops qcom_pdc_ops = {
static int pdc_setup_pin_mapping(struct device *dev, struct device_node *np)
{
- int ret, n, i;
+ int ret, n;
n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32));
if (n <= 0 || n % 3)
return -EINVAL;
- pdc_region_cnt = n / 3;
- pdc_region = devm_kcalloc(dev, pdc_region_cnt, sizeof(*pdc_region),
- GFP_KERNEL);
- if (!pdc_region) {
- pdc_region_cnt = 0;
+ pdc->region_cnt = n / 3;
+ pdc->region = devm_kcalloc(dev, pdc->region_cnt, sizeof(*pdc->region),
+ GFP_KERNEL);
+ if (!pdc->region) {
+ pdc->region_cnt = 0;
return -ENOMEM;
}
- for (n = 0; n < pdc_region_cnt; n++) {
+ for (n = 0; n < pdc->region_cnt; n++) {
ret = of_property_read_u32_index(np, "qcom,pdc-ranges",
n * 3 + 0,
- &pdc_region[n].pin_base);
+ &pdc->region[n].pin_base);
if (ret)
return ret;
ret = of_property_read_u32_index(np, "qcom,pdc-ranges",
n * 3 + 1,
- &pdc_region[n].parent_base);
+ &pdc->region[n].parent_base);
if (ret)
return ret;
ret = of_property_read_u32_index(np, "qcom,pdc-ranges",
n * 3 + 2,
- &pdc_region[n].cnt);
+ &pdc->region[n].cnt);
if (ret)
return ret;
- for (i = 0; i < pdc_region[n].cnt; i++)
- __pdc_enable_intr(i + pdc_region[n].pin_base, 0);
+ for (int i = 0; i < pdc->region[n].cnt; i++)
+ pdc->enable_intr(i + pdc->region[n].pin_base, 0);
}
return 0;
@@ -481,13 +479,16 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
if (pdc->version >= PDC_VERSION_3_2) {
pdc->cfg_fields = &pdc_cfg_v3_2;
pdc->regs = &pdc_v3_2;
+ pdc->enable_intr = pdc_enable_intr_cfg;
} else if (pdc->version < PDC_VERSION_3_2 &&
pdc->version >= PDC_VERSION_3_0) {
pdc->cfg_fields = &pdc_cfg_v3_0;
pdc->regs = &pdc_v3_0;
+ pdc->enable_intr = pdc_enable_intr_bank;
} else {
pdc->cfg_fields = &pdc_cfg_v2_7;
pdc->regs = &pdc_v2_7;
+ pdc->enable_intr = pdc_enable_intr_bank;
}
/*
@@ -506,7 +507,7 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
return -ENXIO;
}
- pdc_x1e_quirk = true;
+ pdc->x1e_quirk = true;
}
parent_domain = irq_find_host(parent);
@@ -521,6 +522,8 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
return ret;
}
+ raw_spin_lock_init(&pdc->lock);
+
pdc_domain = irq_domain_create_hierarchy(parent_domain,
IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP,
PDC_MAX_IRQS,
--
2.43.0
^ permalink raw reply related
* [PATCH v3 1/8] irqchip/qcom-pdc: restructure version support
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah
In-Reply-To: <20260616-hamoa_pdc_v3-v3-0-4d8e1504ea75@oss.qualcomm.com>
PDC irqchip updates IRQ_ENABLE and IRQ_CFG and for three different
versions v2.7, v3.0 and v3.2. These registers are organized in H/W
as below on various SoCs.
+---------------------------------------------------------------+
| SM8350, SM8450 | SM8550, Hamoa | SM8650, SM8750 |
|---------------------------------------------------------------|
| v2.7 | v3.0 | v3.2 |
|---------------------------------------------------------------|
| IRQ_ENABLE_BANK | IRQ_ENABLE_BANK | NA |
|---------------------------------------------------------------|
| IRQ_CFG | IRQ_CFG | IRQ_CFG |
| | | |
| | | [31:6] Unused |
| | [31:5] Unused | [5] GPIO_STATUS |
| | [4] GPIO_STATUS| [4] GPIO_MASK |
| [31:3] Unused | [3] GPIO_MASK | [3] IRQ_ENABLE |
| [0:2] Type | [0:2] Type | [0:2] Type |
+---------------------------------------------------------------|
All SoCs PDC irqchip supports "pass through mode" in which all interrupts
are forwarded to the GIC without any latching at PDC H/W.
So far irqchip did not utilize GPIO_STATUS and GPIO_MASK from IRQ_CFG
register for v3.0 and v3.2 since they are only needed to be configured
when PDC runs in specific mode named "second level interrupt controller"
where it can latch the GPIO interrupts in GPIO_STATUS and forward GPIO
interrupts to GIC as LEVEL_HIGH type SPI interrupt.
All the SoCs defaulted to pass through mode with the exception of some
x1e. x1e PDC may be set to secondary controller mode for builds on CRD
boards whereas it may be set to pass through mode for IoT-EVK boards.
Restructure in preparation to add the second level interrupt controller
mode utilizing GPIO_STATUS and GPIO_MASK bits which changed the bit
positions between v3.0 and v3.2.
No functional impact with the change.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
drivers/irqchip/qcom-pdc.c | 207 ++++++++++++++++++++++++++++++++-------------
1 file changed, 149 insertions(+), 58 deletions(-)
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 2014dbb0bc43..23276325211d 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -21,21 +21,12 @@
#include <linux/slab.h>
#include <linux/types.h>
-#define PDC_MAX_GPIO_IRQS 256
-#define PDC_DRV_SIZE 0x10000
-
-/* Valid only on HW version < 3.2 */
-#define IRQ_ENABLE_BANK 0x10
-#define IRQ_ENABLE_BANK_MAX (IRQ_ENABLE_BANK + BITS_TO_BYTES(PDC_MAX_GPIO_IRQS))
+#define PDC_MAX_IRQS 256
+#define IRQ_ENABLE_BANK_MAX BITS_TO_BYTES(PDC_MAX_IRQS)
#define IRQ_ENABLE_BANK_INDEX_MASK GENMASK(31, 5)
#define IRQ_ENABLE_BANK_BIT_MASK GENMASK(4, 0)
-#define IRQ_i_CFG 0x110
-
-/* Valid only on HW version >= 3.2 */
-#define IRQ_i_CFG_IRQ_ENABLE 3
-
-#define IRQ_i_CFG_TYPE_MASK GENMASK(2, 0)
+#define PDC_DRV_SIZE 0x10000
#define PDC_VERSION_REG 0x1000
#define PDC_VERSION_MAJOR GENMASK(23, 16)
#define PDC_VERSION_MINOR GENMASK(15, 8)
@@ -46,6 +37,98 @@
/* Notable PDC versions */
#define PDC_VERSION_3_2 PDC_VERSION(3, 2, 0)
+#define PDC_VERSION_3_0 PDC_VERSION(3, 0, 0)
+#define PDC_VERSION_2_7 PDC_VERSION(2, 7, 0)
+
+/*
+ * PDC H/W registers layout per version:
+ *
+ * IRQ_ENABLE_BANK[b], b = 0....BITS_TO_BYTES(PDC_MAX_IRQS)
+ * IRQ_CFG[n], n = 0....PDC_MAX_IRQS
+ *
+ * +---------------------------------------------------------------+
+ * | v2.7 | v3.0 | v3.2 |
+ * |---------------------------------------------------------------|
+ * | BASE | BASE | BASE |
+ * |---------------------------------------------------------------|
+ * | |
+ * | IRQ_ENABLE_BANK | IRQ_ENABLE_BANK | NA |
+ * |---------------------------------------------------------------|
+ * | IRQ_CFG | IRQ_CFG | IRQ_CFG |
+ * | | | |
+ * | | | [31:6] Unused |
+ * | | [31:5] Unused | [5] GPIO_STATUS |
+ * | | [4] GPIO_STATUS| [4] GPIO_MASK |
+ * | [31:3] Unused | [3] GPIO_MASK | [3] IRQ_ENABLE |
+ * | [0:2] Type | [0:2] Type | [0:2] Type |
+ * +---------------------------------------------------------------+
+ */
+
+/**
+ * struct pdc_regs: PDC registers location
+ *
+ * @irq_en_reg: IRQ_ENABLE_BANK register location
+ * @irq_cfg_reg: IRQ_CFG register location
+ */
+struct pdc_regs {
+ u32 irq_en_reg;
+ u32 irq_cfg_reg;
+};
+
+/**
+ * struct pdc_irq_cfg: bit fields for PDC IRQ_CFG register
+ *
+ * @irq_enable: bit number for IRQ_ENABLE field
+ * @irq_type: GENMASK for IRQ_TYPE field
+ */
+struct pdc_irq_cfg {
+ u32 irq_enable;
+ u32 irq_type;
+};
+
+/**
+ * struct pdc_desc: PDC driver state
+ *
+ * @base: PDC base register for DRV2 / HLOS
+ * @prev_base: PDC DRV1 base, applicable only for x1e RTL bug.
+ * @version: PDC version
+ * @regs: PDC regs (IRQ_ENABLE_BANK and IRQ_CFG)
+ * @cfg_fields: Fields of IRQ_CFG reg
+ */
+struct pdc_desc {
+ void __iomem *base;
+ void __iomem *prev_base;
+ u32 version;
+ const struct pdc_regs *regs;
+ const struct pdc_irq_cfg *cfg_fields;
+};
+
+static const struct pdc_regs pdc_v3_2 = {
+ .irq_cfg_reg = 0x110,
+};
+
+static const struct pdc_irq_cfg pdc_cfg_v3_2 = {
+ .irq_enable = 3,
+ .irq_type = GENMASK(2, 0),
+};
+
+static const struct pdc_regs pdc_v3_0 = {
+ .irq_en_reg = 0x10,
+ .irq_cfg_reg = 0x110,
+};
+
+static const struct pdc_irq_cfg pdc_cfg_v3_0 = {
+ .irq_type = GENMASK(2, 0),
+};
+
+static const struct pdc_regs pdc_v2_7 = {
+ .irq_en_reg = 0x10,
+ .irq_cfg_reg = 0x110,
+};
+
+static const struct pdc_irq_cfg pdc_cfg_v2_7 = {
+ .irq_type = GENMASK(2, 0),
+};
struct pdc_pin_region {
u32 pin_base;
@@ -56,12 +139,11 @@ struct pdc_pin_region {
#define pin_to_hwirq(r, p) ((r)->parent_base + (p) - (r)->pin_base)
static DEFINE_RAW_SPINLOCK(pdc_lock);
-static void __iomem *pdc_base;
-static void __iomem *pdc_prev_base;
static struct pdc_pin_region *pdc_region;
static int pdc_region_cnt;
static unsigned int pdc_version;
static bool pdc_x1e_quirk;
+static struct pdc_desc *pdc;
static void pdc_base_reg_write(void __iomem *base, int reg, u32 i, u32 val)
{
@@ -70,12 +152,12 @@ static void pdc_base_reg_write(void __iomem *base, int reg, u32 i, u32 val)
static void pdc_reg_write(int reg, u32 i, u32 val)
{
- pdc_base_reg_write(pdc_base, reg, i, val);
+ pdc_base_reg_write(pdc->base, reg, i, val);
}
static u32 pdc_reg_read(int reg, u32 i)
{
- return readl_relaxed(pdc_base + reg + i * sizeof(u32));
+ return readl_relaxed(pdc->base + reg + i * sizeof(u32));
}
static void pdc_x1e_irq_enable_write(u32 bank, u32 enable)
@@ -86,24 +168,24 @@ static void pdc_x1e_irq_enable_write(u32 bank, u32 enable)
switch (bank) {
case 0 ... 1:
/* Use previous DRV (client) region and shift to bank 3-4 */
- base = pdc_prev_base;
+ base = pdc->prev_base;
bank += 3;
break;
case 2 ... 4:
/* Use our own region and shift to bank 0-2 */
- base = pdc_base;
+ base = pdc->base;
bank -= 2;
break;
case 5:
/* No fixup required for bank 5 */
- base = pdc_base;
+ base = pdc->base;
break;
default:
WARN_ON(1);
return;
}
- pdc_base_reg_write(base, IRQ_ENABLE_BANK, bank, enable);
+ pdc_base_reg_write(base, pdc->regs->irq_en_reg, bank, enable);
}
static void pdc_enable_intr_bank(int pin_out, bool on)
@@ -114,21 +196,21 @@ static void pdc_enable_intr_bank(int pin_out, bool on)
index = FIELD_GET(IRQ_ENABLE_BANK_INDEX_MASK, pin_out);
mask = FIELD_GET(IRQ_ENABLE_BANK_BIT_MASK, pin_out);
- enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
+ enable = pdc_reg_read(pdc->regs->irq_en_reg, index);
__assign_bit(mask, &enable, on);
if (pdc_x1e_quirk)
pdc_x1e_irq_enable_write(index, enable);
else
- pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
+ pdc_reg_write(pdc->regs->irq_en_reg, index, enable);
}
static void pdc_enable_intr_cfg(int pin_out, bool on)
{
- unsigned long enable = pdc_reg_read(IRQ_i_CFG, pin_out);
+ unsigned long enable = pdc_reg_read(pdc->regs->irq_cfg_reg, pin_out);
- __assign_bit(IRQ_i_CFG_IRQ_ENABLE, &enable, on);
- pdc_reg_write(IRQ_i_CFG, pin_out, enable);
+ __assign_bit(pdc->cfg_fields->irq_enable, &enable, on);
+ pdc_reg_write(pdc->regs->irq_cfg_reg, pin_out, enable);
}
static void __pdc_enable_intr(int pin_out, bool on)
@@ -224,9 +306,9 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
- old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq);
- pdc_type |= (old_pdc_type & ~IRQ_i_CFG_TYPE_MASK);
- pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type);
+ old_pdc_type = pdc_reg_read(pdc->regs->irq_cfg_reg, d->hwirq);
+ pdc_type |= (old_pdc_type & ~pdc->cfg_fields->irq_type);
+ pdc_reg_write(pdc->regs->irq_cfg_reg, d->hwirq, pdc_type);
ret = irq_chip_set_type_parent(d, type);
if (ret)
@@ -327,7 +409,7 @@ static const struct irq_domain_ops qcom_pdc_ops = {
.free = irq_domain_free_irqs_common,
};
-static int pdc_setup_pin_mapping(struct device_node *np)
+static int pdc_setup_pin_mapping(struct device *dev, struct device_node *np)
{
int ret, n, i;
@@ -336,7 +418,8 @@ static int pdc_setup_pin_mapping(struct device_node *np)
return -EINVAL;
pdc_region_cnt = n / 3;
- pdc_region = kzalloc_objs(*pdc_region, pdc_region_cnt);
+ pdc_region = devm_kcalloc(dev, pdc_region_cnt, sizeof(*pdc_region),
+ GFP_KERNEL);
if (!pdc_region) {
pdc_region_cnt = 0;
return -ENOMEM;
@@ -366,11 +449,11 @@ static int pdc_setup_pin_mapping(struct device_node *np)
return 0;
}
-
static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *parent)
{
struct irq_domain *parent_domain, *pdc_domain;
struct device_node *node = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
resource_size_t res_size;
struct resource res;
int ret;
@@ -383,6 +466,30 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
if (res_size > resource_size(&res))
pr_warn("%pOF: invalid reg size, please fix DT\n", node);
+ pdc = devm_kzalloc(dev, sizeof(*pdc), GFP_KERNEL);
+ if (!pdc)
+ return -ENOMEM;
+
+ pdc->base = devm_ioremap(dev, res.start, res_size);
+ if (!pdc->base) {
+ pr_err("%pOF: unable to map PDC registers\n", node);
+ return -ENXIO;
+ }
+
+ pdc->version = pdc_reg_read(PDC_VERSION_REG, 0);
+
+ if (pdc->version >= PDC_VERSION_3_2) {
+ pdc->cfg_fields = &pdc_cfg_v3_2;
+ pdc->regs = &pdc_v3_2;
+ } else if (pdc->version < PDC_VERSION_3_2 &&
+ pdc->version >= PDC_VERSION_3_0) {
+ pdc->cfg_fields = &pdc_cfg_v3_0;
+ pdc->regs = &pdc_v3_0;
+ } else {
+ pdc->cfg_fields = &pdc_cfg_v2_7;
+ pdc->regs = &pdc_v2_7;
+ }
+
/*
* PDC has multiple DRV regions, each one provides the same set of
* registers for a particular client in the system. Due to a hardware
@@ -392,8 +499,9 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
* region with the expected offset to preserve support for old DTs.
*/
if (of_device_is_compatible(node, "qcom,x1e80100-pdc")) {
- pdc_prev_base = ioremap(res.start - PDC_DRV_SIZE, IRQ_ENABLE_BANK_MAX);
- if (!pdc_prev_base) {
+ pdc->prev_base = devm_ioremap(dev, res.start - PDC_DRV_SIZE,
+ pdc->regs->irq_en_reg + IRQ_ENABLE_BANK_MAX);
+ if (!pdc->prev_base) {
pr_err("%pOF: unable to map previous PDC DRV region\n", node);
return -ENXIO;
}
@@ -401,48 +509,31 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare
pdc_x1e_quirk = true;
}
- pdc_base = ioremap(res.start, res_size);
- if (!pdc_base) {
- pr_err("%pOF: unable to map PDC registers\n", node);
- ret = -ENXIO;
- goto fail;
- }
-
- pdc_version = pdc_reg_read(PDC_VERSION_REG, 0);
-
parent_domain = irq_find_host(parent);
if (!parent_domain) {
pr_err("%pOF: unable to find PDC's parent domain\n", node);
- ret = -ENXIO;
- goto fail;
+ return -ENXIO;
}
- ret = pdc_setup_pin_mapping(node);
+ ret = pdc_setup_pin_mapping(dev, node);
if (ret) {
pr_err("%pOF: failed to init PDC pin-hwirq mapping\n", node);
- goto fail;
+ return ret;
}
pdc_domain = irq_domain_create_hierarchy(parent_domain,
- IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP,
- PDC_MAX_GPIO_IRQS,
- of_fwnode_handle(node),
- &qcom_pdc_ops, NULL);
+ IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP,
+ PDC_MAX_IRQS,
+ of_fwnode_handle(node),
+ &qcom_pdc_ops, NULL);
if (!pdc_domain) {
pr_err("%pOF: PDC domain add failed\n", node);
- ret = -ENOMEM;
- goto fail;
+ return -ENOMEM;
}
irq_domain_update_bus_token(pdc_domain, DOMAIN_BUS_WAKEUP);
return 0;
-
-fail:
- kfree(pdc_region);
- iounmap(pdc_base);
- iounmap(pdc_prev_base);
- return ret;
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(qcom_pdc)
--
2.43.0
^ permalink raw reply related
* [PATCH v3 0/8] x1e80100: Enable PDC wake GPIOs and deepest idle state
From: Maulik Shah @ 2026-06-16 9:25 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Gleixner, Linus Walleij
Cc: linux-arm-msm, linux-kernel, devicetree, linux-gpio, Sneh Mankad,
Maulik Shah, Stephan Gerhold
There are two modes PDC irqchip can work in
- pass through mode
- secondary controller mode
Secondary mode is supported depending on SoC using PDC HW Version v3.0
or higher.
+------------------------------------------------------------------------+
| SoC | SM8350, SM8450 | SM8550, Hamoa | SM8650, SM8750 |
|----------------------------------------------------------- ------------|
| Version | v2.7 | v3.0 | v3.2 |
|------------------------------------------------------------------------|
| Pass through | Yes | Yes | Yes |
|------------------------------------------------------------------------|
| Secondary | No | Yes | Yes |
+------------------------------------------------------------------------+
All PDC irqchip supports pass through mode in which both Direct SPIs and
GPIO IRQs (as SPIs) are sent to GIC without latching at PDC, PDC only does
inversion when needed for falling edge to rising edge or level low to level
high, as the GIC do not support falling edge/level low interrupts.
Newer PDCs (v3.0 onwards) also support additional secondary controller mode
where PDC latches GPIO IRQs and sends to GIC as level type IRQ. Direct SPIs
still works same as pass through mode without latching at PDC even in
secondary controller mode.
All the SoCs defaulted to pass through mode with the exception of some x1e.
x1e PDC may be set to secondary controller mode for builds on CRD boards
whereas it may be set to pass through mode for IoT-EVK boards. The mode
configuration is done in firmware and initially shipped windows firmware
did not have SCM interface to read or modify the PDC configuration.
Later only write access is opened up for non secure world.
Using the write access available add changes to modify the PDC mode to
pass through mode via SCM write. When the write fails (on older firmware)
assume to work in secondary mode.
As the deepest idle state as the PDC can now wake up SoC from GPIOs and
revert commit 602cb14e310a ("pinctrl: qcom: x1e80100: Bypass PDC wakeup
parent for now").
The series has been tested on x1e80100 CRD with both old and new firmware
and also on kaanapali. Test conducted with tlmm-test module after
applying [3] as test module needed to be fixed first.
All 17/17 passes in pass through mode and 16/17 passes in secondary mode.
Failing test tlmm_test_rising_while_disabled seems to be because when in
irq disabled state PDC is not latching the edge interrupt.
Test #1: Pass through mode on x1e80100 CRD (New firmware)
root@qcom-armv8a:~# insmod tlmm-test.ko gpio=91
KTAP version 1
1..1
KTAP version 1
# Subtest: tlmm-test
# module: tlmm_test
1..17
ok 1 tlmm_test_silent_rising
ok 2 tlmm_test_silent_falling
ok 3 tlmm_test_silent_low
ok 4 tlmm_test_silent_high
ok 5 tlmm_test_rising
ok 6 tlmm_test_falling
ok 7 tlmm_test_high
ok 8 tlmm_test_low
ok 9 tlmm_test_rising_in_handler
ok 10 tlmm_test_falling_in_handler
ok 11 tlmm_test_thread_rising
ok 12 tlmm_test_thread_falling
ok 13 tlmm_test_thread_high
ok 14 tlmm_test_thread_low
ok 15 tlmm_test_thread_rising_in_handler
ok 16 tlmm_test_thread_falling_in_handler
ok 17 tlmm_test_rising_while_disabled
ok 1 tlmm-test
Test #2: Secondary mode on x1e80100 CRD (Old firmware)
root@qcom-armv8a:~# insmod tlmm-test.ko gpio=91
KTAP version 1
1..1
KTAP version 1
# Subtest: tlmm-test
# module: tlmm_test
1..17
ok 1 tlmm_test_silent_rising
ok 2 tlmm_test_silent_falling
ok 3 tlmm_test_silent_low
ok 4 tlmm_test_silent_high
ok 5 tlmm_test_rising
ok 6 tlmm_test_falling
ok 7 tlmm_test_high
ok 8 tlmm_test_low
ok 9 tlmm_test_rising_in_handler
ok 10 tlmm_test_falling_in_handler
ok 11 tlmm_test_thread_rising
ok 12 tlmm_test_thread_falling
ok 13 tlmm_test_thread_high
ok 14 tlmm_test_thread_low
ok 15 tlmm_test_thread_rising_in_handler
ok 16 tlmm_test_thread_falling_in_handler
# tlmm_test_rising_while_disabled: ASSERTION FAILED at drivers/pinctrl/qcom/tlmm-test.c:545
Expected atomic_read(&priv->intr_count) == 1, but
atomic_read(&priv->intr_count) == 0 (0x0)
not ok 17 tlmm_test_rising_while_disabled
not ok 1 tlmm-test
root@qcom-armv8a:~#
v2 series is dependent on [1] as mostly all changes are already reviewed.
v3 series is dependent on [2] which is already merged in linux-next
[1] https://lore.kernel.org/linux-arm-msm/20260410184124.1068210-1-mukesh.ojha@oss.qualcomm.com/
[2] https://lore.kernel.org/linux-arm-msm/20260527095426.2324504-1-mukesh.ojha@oss.qualcomm.com/
[3] https://lore.kernel.org/linux-arm-msm/20260529-tlmm_test_changes-v1-0-88bfdccb4369@oss.qualcomm.com/
---
Changes in v3:
- Add test results in cover letter with tlmm-test module
- Fix coding style and struct defination
- Convert raw_spin_lock to guard(raw_spin_lock) and remove _irqsave
- Use bit number instead of GENMASK() for single bit fields
- Use __assign_bit() and __clear_bit() APIs for single bit modifications
- Use devm_ioremap() instead of ioremap()
- Use devm_kcalloc() instead of kzalloc_objs()
- Add separate irq chips for pass through and secondary mode IRQs
- Add IRQCHIP_EOI_THREADED flag for threaded IRQ on pinctrl irqchip
- Link to v2: https://patch.msgid.link/20260526-hamoa_pdc-v2-0-f6857af1ce91@oss.qualcomm.com
Changes in v2:
- Update to mention SoC names along with PDC versions in cover letter
- Drop devicetree change to remove scm interconnects
- Use qcom_scm_is_available() to wait for dependency on SCM
- Drop binding change mentioning qcom,qmp and PDC config reg
- Restructure version support and move all statics to struct pdc_desc
- Remove pdc_enable_intr() wrapper
- Differentiate direct SPI and GPIOs as SPI using PDC IRQ PARAM reg
- Add changes to make PDC work in secondary controller mode
- Rework and include Stephan's change to invoke irq_ack() for edge interrupt
- Mention dependency via b4 prerequisites and cover letter
- Link to v1: https://lore.kernel.org/r/20260312-hamoa_pdc-v1-0-760c8593ce50@oss.qualcomm.com
---
To: Bjorn Andersson <andersson@kernel.org>
To: Konrad Dybcio <konradybcio@kernel.org>
To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Thomas Gleixner <tglx@kernel.org>
To: Linus Walleij <linusw@kernel.org>
Cc: linux-arm-msm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-gpio@vger.kernel.org
Cc: Sneh Mankad <sneh.mankad@oss.qualcomm.com>
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
---
Maulik Shah (7):
irqchip/qcom-pdc: restructure version support
irqchip/qcom-pdc: Move all statics to struct pdc_desc
irqchip/qcom-pdc: Remove pdc_enable_intr() wrapper
irqchip/qcom-pdc: Differentiate between direct SPI and GPIO as SPI
irqchip/qcom-pdc: Configure PDC to pass through mode
Revert "pinctrl: qcom: x1e80100: Bypass PDC wakeup parent for now"
arm64: dts: qcom: x1e80100: Add deepest idle state
Stephan Gerhold (1):
pinctrl: qcom: Acknowledge IRQs for PDC interrupt controller
arch/arm64/boot/dts/qcom/hamoa.dtsi | 10 +-
drivers/irqchip/qcom-pdc.c | 506 +++++++++++++++++++++++++-------
drivers/pinctrl/qcom/pinctrl-msm.c | 16 +-
drivers/pinctrl/qcom/pinctrl-x1e80100.c | 4 +-
4 files changed, 430 insertions(+), 106 deletions(-)
---
base-commit: 8d6dbbbe3ba62de0a63e962ee004afb848c8e3ac
change-id: 20260605-hamoa_pdc_v3-6dabc845021c
Best regards,
--
Maulik Shah <maulik.shah@oss.qualcomm.com>
^ permalink raw reply
* [PATCH v2 4/4] arm64: dts: qcom: sc8180x-lenovo-flex-5g: Describe the display power net
From: Konrad Dybcio @ 2026-06-16 9:08 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Dmitry Baryshkov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Vinod Koul
Cc: linux-arm-msm, devicetree, linux-kernel, Konrad Dybcio
In-Reply-To: <20260616-topic-8180_disp_power-v2-0-167785993231@oss.qualcomm.com>
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Describe and wire up the power supplies for the eDP panel and its
backlight. Previously, this was only working because of settings
inherited from the bootloader.
Fixes: 20dea72a393c ("arm64: dts: qcom: sc8180x: Introduce Lenovo Flex 5G")
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
.../arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts | 47 ++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
index 0d2cfb830e83..7601afc3d7bf 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
+++ b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
@@ -26,6 +26,7 @@ backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pmc8180c_lpg 4 1000000>;
enable-gpios = <&pmc8180c_gpios 8 GPIO_ACTIVE_HIGH>;
+ power-supply = <&vled_bl_pw>;
pinctrl-0 = <&bl_pwm_default>;
pinctrl-names = "default";
@@ -157,6 +158,38 @@ cdsp_mem: cdsp-region@98900000 {
};
};
+ vled_bl_pw: regulator-vled-bl-pw {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VLED_BL_PW";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&pmc8180_2_gpios 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&bl_pwr_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_lcm_3v3: regulator-edp-3p3 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_LCM_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 130 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&lcm_3v3_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
vreg_s4a_1p8: regulator-pm8150-s4 {
compatible = "regulator-fixed";
regulator-name = "vreg_s4a_1p8";
@@ -438,6 +471,7 @@ &mdss_edp {
aux-bus {
panel {
compatible = "edp-panel";
+ power-supply = <&vreg_lcm_3v3>;
no-hpd;
backlight = <&backlight>;
@@ -472,6 +506,13 @@ &pcie3_phy {
status = "okay";
};
+&pmc8180_2_gpios {
+ bl_pwr_en: bl-pwr-en-state {
+ pins = "gpio1";
+ function = "normal";
+ };
+};
+
&pmc8180_pwrkey {
status = "okay";
};
@@ -765,6 +806,12 @@ ts_int_default: ts-int-default-state {
drive-strength = <2>;
};
+ lcm_3v3_en: lcm-3v3-en-state {
+ pins = "gpio130";
+ function = "gpio";
+ bias-disable;
+ };
+
usbprim_sbu_default: usbprim-sbu-state {
oe-n-pins {
pins = "gpio152";
--
2.54.0
^ permalink raw reply related
* [PATCH v2 3/4] arm64: dts: qcom: sc8180x-lenovo-flex-5g: Rename regulator nodes
From: Konrad Dybcio @ 2026-06-16 9:08 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Dmitry Baryshkov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Vinod Koul
Cc: linux-arm-msm, devicetree, linux-kernel, Konrad Dybcio
In-Reply-To: <20260616-topic-8180_disp_power-v2-0-167785993231@oss.qualcomm.com>
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Align with the contemporary way of naming regulator nodes (regulator-
prefix) in preparation for adding more of them.
Reorder the renamed entries to match the expectations of the DT coding
style doc.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
index d86a31ddede2..0d2cfb830e83 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
+++ b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts
@@ -157,14 +157,7 @@ cdsp_mem: cdsp-region@98900000 {
};
};
- vph_pwr: vph-pwr-regulator {
- compatible = "regulator-fixed";
- regulator-name = "vph_pwr";
- regulator-min-microvolt = <3700000>;
- regulator-max-microvolt = <3700000>;
- };
-
- vreg_s4a_1p8: pm8150-s4-regulator {
+ vreg_s4a_1p8: regulator-pm8150-s4 {
compatible = "regulator-fixed";
regulator-name = "vreg_s4a_1p8";
@@ -177,6 +170,13 @@ vreg_s4a_1p8: pm8150-s4-regulator {
vin-supply = <&vph_pwr>;
};
+ vph_pwr: regulator-vph-pwr {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ };
+
usbprim-sbu-mux {
compatible = "pericom,pi3usb102", "gpio-sbu-mux";
--
2.54.0
^ permalink raw reply related
* [PATCH v2 2/4] arm64: dts: qcom: sc8180x-primus: Describe the display power net
From: Konrad Dybcio @ 2026-06-16 9:08 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Dmitry Baryshkov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Vinod Koul
Cc: linux-arm-msm, devicetree, linux-kernel, Konrad Dybcio
In-Reply-To: <20260616-topic-8180_disp_power-v2-0-167785993231@oss.qualcomm.com>
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Describe and wire up the power supplies for the eDP panel and its
backlight. Previously, this was only working because of settings
inherited from the bootloader.
Fixes: 2ce38cc1e8fe ("arm64: dts: qcom: sc8180x: Introduce Primus")
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/sc8180x-primus.dts | 48 ++++++++++++++++++++++++++++-
1 file changed, 47 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/sc8180x-primus.dts b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
index ffe7c45366ed..e34f4758ebe2 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
+++ b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
@@ -29,9 +29,10 @@ backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pmc8180c_lpg 4 1000000>;
enable-gpios = <&pmc8180c_gpios 8 GPIO_ACTIVE_HIGH>;
+ power-supply = <&vled_bl_pw>;
- pinctrl-names = "default";
pinctrl-0 = <&bl_pwm_default>;
+ pinctrl-names = "default";
};
chosen {
@@ -167,6 +168,38 @@ reserved-region@9a500000 {
};
};
+ vled_bl_pw: regulator-vled-bl-pw {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VLED_BL_PW";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&pmc8180_2_gpios 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&bl_pwr_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_lcm_3v3: regulator-edp-3p3 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_LCM_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 130 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&lcm_3v3_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
vreg_nvme_0p9: regulator-nvme-0p9 {
compatible = "regulator-fixed";
regulator-name = "vreg_nvme_0p9";
@@ -540,6 +573,7 @@ &mdss_edp {
aux-bus {
panel {
compatible = "edp-panel";
+ power-supply = <&vreg_lcm_3v3>;
backlight = <&backlight>;
@@ -769,6 +803,12 @@ &wifi {
};
/* PINCTRL */
+&pmc8180_2_gpios {
+ bl_pwr_en: bl-pwr-en-state {
+ pins = "gpio1";
+ function = "normal";
+ };
+};
&pmc8180c_gpios {
bl_pwm_default: bl-pwm-default-state {
@@ -950,4 +990,10 @@ rx-pins {
bias-pull-up;
};
};
+
+ lcm_3v3_en: lcm-3v3-en-state {
+ pins = "gpio130";
+ function = "gpio";
+ bias-disable;
+ };
};
--
2.54.0
^ permalink raw reply related
* [PATCH v2 1/4] arm64: dts: qcom: sc8180x-primus: Rename regulator nodes
From: Konrad Dybcio @ 2026-06-16 9:08 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Dmitry Baryshkov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Vinod Koul
Cc: linux-arm-msm, devicetree, linux-kernel, Konrad Dybcio
In-Reply-To: <20260616-topic-8180_disp_power-v2-0-167785993231@oss.qualcomm.com>
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
The nodes would be sorted correctly, if their names started with
"regulator-" (which is the style used in the latest submissions).
Touch that up.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/sc8180x-primus.dts | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sc8180x-primus.dts b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
index aff398390eba..ffe7c45366ed 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
+++ b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts
@@ -167,7 +167,7 @@ reserved-region@9a500000 {
};
};
- vreg_nvme_0p9: nvme-0p9-regulator {
+ vreg_nvme_0p9: regulator-nvme-0p9 {
compatible = "regulator-fixed";
regulator-name = "vreg_nvme_0p9";
@@ -177,7 +177,7 @@ vreg_nvme_0p9: nvme-0p9-regulator {
regulator-always-on;
};
- vreg_nvme_3p3: nvme-3p3-regulator {
+ vreg_nvme_3p3: regulator-nvme-3p3 {
compatible = "regulator-fixed";
regulator-name = "vreg_nvme_3p3";
@@ -190,7 +190,7 @@ vreg_nvme_3p3: nvme-3p3-regulator {
regulator-always-on;
};
- vdd_kb_tp_3v3: vdd-kb-tp-3v3-regulator {
+ vdd_kb_tp_3v3: regulator-vdd-kb-tp-3v3 {
compatible = "regulator-fixed";
regulator-name = "vdd_kb_tp_3v3";
regulator-min-microvolt = <3300000>;
@@ -205,7 +205,7 @@ vdd_kb_tp_3v3: vdd-kb-tp-3v3-regulator {
pinctrl-0 = <&kb_tp_3v3_en_active_state>;
};
- vph_pwr: vph-pwr-regulator {
+ vph_pwr: regulator-vph-pwr {
compatible = "regulator-fixed";
regulator-name = "vph_pwr";
regulator-min-microvolt = <3700000>;
--
2.54.0
^ permalink raw reply related
* [PATCH v2 0/4] Describe display voltage regulators on SC8180X devices
From: Konrad Dybcio @ 2026-06-16 9:08 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Dmitry Baryshkov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Vinod Koul
Cc: linux-arm-msm, devicetree, linux-kernel, Konrad Dybcio
Let Linux control these supplies to both ensure a known state and allow
for some power savings.
This series is compile-tested only, but verified against schematics.
Resolves the following kind of DT checker warnings:
sc8180x-lenovo-flex-5g.dtb: panel (edp-panel): 'power-supply' is a required property
Making the SC8180X platform warning-free.
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
Changes in v2:
- Fix a typo in the bl_pwr_en pinctrl node name
- Pick up tags
- Link to v1: https://patch.msgid.link/20260615-topic-8180_disp_power-v1-0-18d36b548c48@oss.qualcomm.com
To: Bjorn Andersson <andersson@kernel.org>
To: Konrad Dybcio <konradybcio@kernel.org>
To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Vinod Koul <vkoul@kernel.org>
Cc: linux-arm-msm@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
Konrad Dybcio (4):
arm64: dts: qcom: sc8180x-primus: Rename regulator nodes
arm64: dts: qcom: sc8180x-primus: Describe the display power net
arm64: dts: qcom: sc8180x-lenovo-flex-5g: Rename regulator nodes
arm64: dts: qcom: sc8180x-lenovo-flex-5g: Describe the display power net
.../arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts | 57 ++++++++++++++++++++--
arch/arm64/boot/dts/qcom/sc8180x-primus.dts | 56 +++++++++++++++++++--
2 files changed, 103 insertions(+), 10 deletions(-)
---
base-commit: c425609d6ac4012c8bbf01ec2e10e801b1923a7b
change-id: 20260615-topic-8180_disp_power-d14df352dcb7
Best regards,
--
Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v3 2/3] iio: adc: Add ti-ads1110 support to ti-ads1100 driver
From: Andy Shevchenko @ 2026-06-16 9:06 UTC (permalink / raw)
To: David Lechner
Cc: Jakub Szczudlo, linux-iio, andy, antoniu.miclaus, conor+dt,
devicetree, duje, jic23, jishnu.prakash, jorge.marques, krzk+dt,
linusw, linux-kernel, marcelo.schmitt, mazziesaccount,
mike.looijmans, nuno.sa, robh, sakari.ailus, wens, joshua.crofts1
In-Reply-To: <43e4c4f4-0b13-4331-80ce-7353408c78f5@baylibre.com>
On Mon, Jun 15, 2026 at 05:29:17PM -0500, David Lechner wrote:
> On 6/13/26 2:09 PM, Jakub Szczudlo wrote:
> > Add ADS1110 support that have faster datarate than ADS1100, it also uses
> > internal voltage reference of 2.048V for measurement.
...
> > +#define ADS1100_MAX_DRDY_TIMEOUT 7500000
>
> Always nice to include the units in the identifier name.
>
> ADS1100_MAX_DRDY_TIMEOUT_us
I think for seconds unit we stuck with capital letters.
But I appreciate the attempt.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2] dt-bindings: rtc: Convert rtc-cmos binding to YAML
From: sashiko-bot @ 2026-06-16 9:04 UTC (permalink / raw)
To: Teja Sai Charan B; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260616085659.12809-1-tejaasaye@gmail.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Low] The node name in the YAML example uses a unit address that does not match its 'reg' property, which will cause a dtc warning and fail `make dt_binding_check`.
- [Low] A stray file `result.txt` containing intermediate search and build output was accidentally included in the patch.
- [Low] Important explanatory text about firmware initialization was dropped during the conversion to YAML.
--
commit 141cef115f7766092691376134d5e5d70aca938a
Author: Teja Sai Charan Bellamkonda <tejaasaye@gmail.com>
dt-bindings: rtc: Convert rtc-cmos binding to YAML
Convert the rtc-cmos devicetree bindings to dt schema.
> diff --git a/Documentation/devicetree/bindings/rtc/rtc-cmos.yaml b/Documentation/devicetree/bindings/rtc/rtc-cmos.yaml
> new file mode 100644
> index 0000000000000..ba4812778115c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/rtc/rtc-cmos.yaml
[ ... ]
> + ctrl-reg:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description:
> + Initial value of the control register
> + (also known as Register B).
> +
> + freq-reg:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description:
> + Initial value of the frequency register
> + (also known as Register A).
[Severity: Low]
The original text binding contained information explaining that Register A
and B are usually initialized by firmware (e.g., BIOS), and if not, can be
performed by the driver. Should this explanatory text be preserved in the
descriptions here to retain the original context?
[ ... ]
> +examples:
> + - |
> + bus {
> + #address-cells = <2>;
> + #size-cells = <1>;
> +
> + rtc@70 {
> + compatible = "motorola,mc146818";
> + reg = <1 0x70 2>;
[Severity: Low]
Since the bus has #address-cells = <2> and the reg property starts with 1,
should the node name be formatted as rtc@1,70 instead of rtc@70? A mismatched
unit address will result in dtc warnings and fail make dt_binding_check.
[ ... ]
> diff --git a/result.txt b/result.txt
> new file mode 100644
> index 0000000000000..5e90660b93ec2
> --- /dev/null
> +++ b/result.txt
> @@ -0,0 +1,17 @@
> +arch/x86/kernel/x86_init.c:42: { .compatible = "motorola,mc146818" },
> +arch/x86/platform/ce4100/falconfalls.dts:420: compatible = "intel,ce4100-rtc", "motorola,mc146818";
[Severity: Low]
Was this result.txt file intentionally included? It appears to be a local
search and build log that accidentally made it into the patch.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260616085659.12809-1-tejaasaye@gmail.com?part=1
^ permalink raw reply
* [PATCH v2] dt-bindings: rtc: Convert rtc-cmos binding to YAML
From: Teja Sai Charan B @ 2026-06-16 8:56 UTC (permalink / raw)
To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-rtc, devicetree, linux-kernel, Teja Sai Charan Bellamkonda
From: Teja Sai Charan Bellamkonda <tejaasaye@gmail.com>
Convert the rtc-cmos devicetree bindings to dt schema.
Signed-off-by: Teja Sai Charan Bellamkonda <tejaasaye@gmail.com>
---
Changes in v2:
- Allow intel,ce4100-rtc compatible used by existing DTS files
---
.../devicetree/bindings/rtc/rtc-cmos.txt | 27 ---------
.../devicetree/bindings/rtc/rtc-cmos.yaml | 60 +++++++++++++++++++
result.txt | 17 ++++++
3 files changed, 77 insertions(+), 27 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/rtc/rtc-cmos.txt
create mode 100644 Documentation/devicetree/bindings/rtc/rtc-cmos.yaml
create mode 100644 result.txt
diff --git a/Documentation/devicetree/bindings/rtc/rtc-cmos.txt b/Documentation/devicetree/bindings/rtc/rtc-cmos.txt
deleted file mode 100644
index 7d7b5f6bda65..000000000000
--- a/Documentation/devicetree/bindings/rtc/rtc-cmos.txt
+++ /dev/null
@@ -1,27 +0,0 @@
- Motorola mc146818 compatible RTC
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Required properties:
- - compatible : "motorola,mc146818"
- - reg : should contain registers location and length.
-
-Optional properties:
- - interrupts : should contain interrupt.
- - ctrl-reg : Contains the initial value of the control register also
- called "Register B".
- - freq-reg : Contains the initial value of the frequency register also
- called "Register A".
-
-"Register A" and "B" are usually initialized by the firmware (BIOS for
-instance). If this is not done, it can be performed by the driver.
-
-ISA Example:
-
- rtc@70 {
- compatible = "motorola,mc146818";
- interrupts = <8 3>;
- interrupt-parent = <&ioapic1>;
- ctrl-reg = <2>;
- freq-reg = <0x26>;
- reg = <1 0x70 2>;
- };
diff --git a/Documentation/devicetree/bindings/rtc/rtc-cmos.yaml b/Documentation/devicetree/bindings/rtc/rtc-cmos.yaml
new file mode 100644
index 000000000000..ba4812778115
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-cmos.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/rtc-cmos.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Motorola mc146818 compatible RTC
+
+maintainers:
+ - Alexandre Belloni <alexandre.belloni@bootlin.com>
+
+properties:
+ compatible:
+ oneOf:
+ - const: motorola,mc146818
+
+ - items:
+ - const: intel,ce4100-rtc
+ - const: motorola,mc146818
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ ctrl-reg:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Initial value of the control register
+ (also known as Register B).
+
+ freq-reg:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Initial value of the frequency register
+ (also known as Register A).
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ bus {
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ rtc@70 {
+ compatible = "motorola,mc146818";
+ reg = <1 0x70 2>;
+
+ interrupts = <8 3>;
+
+ ctrl-reg = <2>;
+ freq-reg = <0x26>;
+ };
+ };
diff --git a/result.txt b/result.txt
new file mode 100644
index 000000000000..5e90660b93ec
--- /dev/null
+++ b/result.txt
@@ -0,0 +1,17 @@
+arch/x86/kernel/x86_init.c:42: { .compatible = "motorola,mc146818" },
+arch/x86/platform/ce4100/falconfalls.dts:420: compatible = "intel,ce4100-rtc", "motorola,mc146818";
+arch/mips/boot/dts/loongson/rs780e-pch.dtsi:31: compatible = "motorola,mc146818";
+arch/mips/boot/dts/mti/malta.dts:110: compatible = "motorola,mc146818";
+arch/alpha/kernel/rtc.c:25: * We don't want to use the rtc-cmos driver, because we don't want to support
+drivers/built-in.a:1031:rtc/rtc-cmos.o/
+drivers/rtc/built-in.a:11:rtc-cmos.o/
+drivers/rtc/.rtc-mc146818-lib.o.cmd:1:savedcmd_drivers/rtc/rtc-mc146818-lib.o := gcc -Wp,-MMD,drivers/rtc/.rtc-mc146818-lib.o.d -nostdinc -I./arch/x86/include -I./arch/x86/include/generated -I./include -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/compiler-version.h -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -std=gnu11 -fshort-wchar -funsigned-char -fno-common -fno-PIE -fno-strict-aliasing -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -mno-sse4a -fcf-protection=none -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -march=x86-64 -mtune=generic -mno-red-zone -mcmodel=kernel -mstack-protector-guard-reg=gs -mstack-protector-guard-symbol=__ref_stack_chk_guard -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -mindirect-branch-cs-prefix -mfunction-return=thunk-extern -fno-jump-tables -mharden-sls=all -fpatchable-function-entry=16,16 -fno-delete-null-pointer-checks -O2 -fno-allow-store-data-races -fstack-protector-strong -fno-omit-frame-pointer -fno-optimize-sibling-calls -ftrivial-auto-var-init=zero -fno-stack-clash-protection -fzero-call-used-regs=used-gpr -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -falign-functions=16 -fstrict-flex-arrays=3 -fms-extensions -fno-strict-overflow -fno-stack-check -fconserve-stack -fno-builtin-wcslen -Wall -Wextra -Wundef -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Werror=strict-prototypes -Wno-format-security -Wno-trigraphs -Wno-frame-address -Wno-address-of-packed-member -Wmissing-declarations -Wmissing-prototypes -Wframe-larger-than=1024 -Wno-main -Wno-dangling-pointer -Wvla-larger-than=1 -Wno-pointer-sign -Wcast-function-type -Wno-array-bounds -Wno-stringop-overflow -Wno-alloc-size-larger-than -Wimplicit-fallthrough=5 -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -Wenum-conversion -Wunused -Wno-unused-but-set-variable -Wno-unused-const-variable -Wno-packed-not-aligned -Wno-format-overflow -Wno-format-truncation -Wno-stringop-truncation -Wno-override-init -Wno-missing-field-initializers -Wno-type-limits -Wno-shift-negative-value -Wno-maybe-uninitialized -Wno-sign-compare -Wno-unused-parameter -g -gdwarf-5 -fsanitize=bounds-strict -fsanitize=shift -fsanitize=bool -fsanitize=enum -DKBUILD_MODFILE='"drivers/rtc/rtc-mc146818-lib"' -DKBUILD_BASENAME='"rtc_mc146818_lib"' -DKBUILD_MODNAME='"rtc_mc146818_lib"' -D__KBUILD_MODNAME=rtc_mc146818_lib -c -o drivers/rtc/rtc-mc146818-lib.o drivers/rtc/rtc-mc146818-lib.c
+drivers/rtc/.built-in.a.cmd:1:savedcmd_drivers/rtc/built-in.a := rm -f drivers/rtc/built-in.a; printf "drivers/rtc/%s " lib.o class.o interface.o nvmem.o dev.o proc.o sysfs.o rtc-mc146818-lib.o rtc-cmos.o | xargs ar cDPrST drivers/rtc/built-in.a
+drivers/rtc/Kconfig:1065: will be called rtc-cmos.
+drivers/rtc/Makefile:45:obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
+drivers/rtc/.rtc-cmos.o.cmd:1:savedcmd_drivers/rtc/rtc-cmos.o := gcc -Wp,-MMD,drivers/rtc/.rtc-cmos.o.d -nostdinc -I./arch/x86/include -I./arch/x86/include/generated -I./include -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/compiler-version.h -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -std=gnu11 -fshort-wchar -funsigned-char -fno-common -fno-PIE -fno-strict-aliasing -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -mno-sse4a -fcf-protection=none -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -march=x86-64 -mtune=generic -mno-red-zone -mcmodel=kernel -mstack-protector-guard-reg=gs -mstack-protector-guard-symbol=__ref_stack_chk_guard -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -mindirect-branch-cs-prefix -mfunction-return=thunk-extern -fno-jump-tables -mharden-sls=all -fpatchable-function-entry=16,16 -fno-delete-null-pointer-checks -O2 -fno-allow-store-data-races -fstack-protector-strong -fno-omit-frame-pointer -fno-optimize-sibling-calls -ftrivial-auto-var-init=zero -fno-stack-clash-protection -fzero-call-used-regs=used-gpr -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -falign-functions=16 -fstrict-flex-arrays=3 -fms-extensions -fno-strict-overflow -fno-stack-check -fconserve-stack -fno-builtin-wcslen -Wall -Wextra -Wundef -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Werror=strict-prototypes -Wno-format-security -Wno-trigraphs -Wno-frame-address -Wno-address-of-packed-member -Wmissing-declarations -Wmissing-prototypes -Wframe-larger-than=1024 -Wno-main -Wno-dangling-pointer -Wvla-larger-than=1 -Wno-pointer-sign -Wcast-function-type -Wno-array-bounds -Wno-stringop-overflow -Wno-alloc-size-larger-than -Wimplicit-fallthrough=5 -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -Wenum-conversion -Wunused -Wno-unused-but-set-variable -Wno-unused-const-variable -Wno-packed-not-aligned -Wno-format-overflow -Wno-format-truncation -Wno-stringop-truncation -Wno-override-init -Wno-missing-field-initializers -Wno-type-limits -Wno-shift-negative-value -Wno-maybe-uninitialized -Wno-sign-compare -Wno-unused-parameter -g -gdwarf-5 -fsanitize=bounds-strict -fsanitize=shift -fsanitize=bool -fsanitize=enum -DKBUILD_MODFILE='"drivers/rtc/rtc-cmos"' -DKBUILD_BASENAME='"rtc_cmos"' -DKBUILD_MODNAME='"rtc_cmos"' -D__KBUILD_MODNAME=rtc_cmos -c -o drivers/rtc/rtc-cmos.o drivers/rtc/rtc-cmos.c
+drivers/rtc/.rtc-cmos.o.cmd:3:source_drivers/rtc/rtc-cmos.o := drivers/rtc/rtc-cmos.c
+drivers/rtc/.rtc-cmos.o.cmd:5:deps_drivers/rtc/rtc-cmos.o := \
+drivers/rtc/.rtc-cmos.o.cmd:1372:drivers/rtc/rtc-cmos.o: $(deps_drivers/rtc/rtc-cmos.o)
+drivers/rtc/.rtc-cmos.o.cmd:1374:$(deps_drivers/rtc/rtc-cmos.o):
+drivers/rtc/rtc-cmos.c:1382: .compatible = "motorola,mc146818",
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 0/2] drm: Add driver for the Solomon SSD1351 OLED controller
From: Javier Martinez Canillas @ 2026-06-16 8:55 UTC (permalink / raw)
To: Amit Barzilai
Cc: Amit Barzilai, airlied, conor+dt, devicetree, dri-devel, krzk+dt,
linux-kernel, maarten.lankhorst, mripard, robh, simona,
tzimmermann, Alberto Ruiz
In-Reply-To: <20260615181253.97551-1-amit.barzilai22@gmail.com>
Amit Barzilai <amit.barzilai22@gmail.com> writes:
> Hi Javier,
>
> Thanks you for the detailed review and for the Reviewed-by on the binding.
>
You are welcome.
> I agree with folding the SSD1351 into ssd130x rather than keeping it
> standalone. My plan for the v2 driver series follows your two steps:
>
> 1. Add RGB565 support to the existing SSD133X family (so the SSD1331 gains
> 65k color), gating the format on a per-variant flag in device_info so the
> existing RGB332 path is untouched.
> 2. Add a new SSD135X family for the SSD1351 on top of that, reusing the
> ssd133x data path (the update_rect window logic is already
> format-agnostic) and adding only the SSD1351-specific bits - the 0x5c
> write-RAM command and its init sequence.
>
These make sense to me.
> I'm deferring step 3 (native 256k color) for now since, as you suspected,
> there's no matching DRM fourcc, and I'm dropping the 0/180 rotation support
> to keep the series focused; it can come back later.
>
This also makes sense. Having 256k color support is nice to have, but so was
65k color for SSD1331, that didn't prevent me to add support for that family.
> Two things I'd like to confirm before I send the series:
>
> - I have an SSD1331 panel, but it is currently unsoldered and I don't have
> the means to solder it myself. I'm trying to arrange testing through
> someone else - I can't promise it will work out. If it doesn't, the
> SSD1331 RGB565 change would be compile-tested only (I do have SSD1351
> hardware to test the new family). Is compile-tested-only acceptable for
> the SSD1331 part, or would you prefer I hold that piece until it can be
> verified on hardware?
That's OK. I've a SSD1331 that I used to test the SSD130X support when I was
working on it. So I can test your SSD1331 changes without any problem.
> - Could you confirm the RGB565 byte order the SSD1331 expects? The
> standalone SSD1351 code used big-endian (drm_fb_xrgb8888_to_rgb565be);
> I want the shared conversion helper to match the SSD1331 datasheet.
>
If I read the SSD1331 data sheet correctly I see that it support different 65k
formats but it does support the same 64k color depth format than the SSD1351.
Only supporting that variant is totally fine so that you could reuse it for
both chip families.
> Separately, I've sent the DT binding as a standalone v2. Since I dropped the
> width/height and rotation properties per Krzysztof's review, I did not carry
> your Reviewed-by forward - please re-review at your convenience.
>
Yes, that looks good to me. I already gave it my r-b again.
BTW, I just added some cleanup patches from Alberto that simplify how the driver
send multiple commands. Please base your v2 on drm-misc-next branch to ensure it
does not conflict with your changes.
> Thanks,
> Amit
>
--
Best regards,
Javier Martinez Canillas
Core Platforms
Red Hat
^ permalink raw reply
* Re: [PATCH V13 3/9] iio: imu: inv_icm42607: Add inv_icm42607 Core Driver
From: Andy Shevchenko @ 2026-06-16 8:53 UTC (permalink / raw)
To: Chris Morgan
Cc: linux-iio, andy, nuno.sa, dlechner, jic23, jean-baptiste.maneyrol,
linux-rockchip, devicetree, heiko, conor+dt, krzk+dt, robh,
Chris Morgan
In-Reply-To: <20260615172554.160910-4-macroalpha82@gmail.com>
On Mon, Jun 15, 2026 at 12:25:46PM -0500, Chris Morgan wrote:
> Add the core component of a new inv_icm42607 driver. This includes
> a few setup functions and the full register definition in the
> header file, as well as the bits necessary to compile and probe the
> device when used on an i2c bus.
...
> +#ifndef INV_ICM42607_H_
> +#define INV_ICM42607_H_
> +
> +#include <linux/bits.h>
> +#include <linux/iio/iio.h>
> +#include <linux/mutex.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/time.h>
> +#include <linux/types.h>
+ asm/byteorder.h // cpu_to_le16()
...
> +#include <linux/bitfield.h>
> +#include <linux/dev_printk.h>
> +#include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +
> +
Single blank line is enough.
> +#include "inv_icm42607.h"
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2] dt-bindings: i2c: i2c-mux-pinctrl: change maintainer
From: Wolfram Sang @ 2026-06-16 8:49 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: linux-i2c, Thierry Reding, Peter Rosin, Andi Shyti, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
In-Reply-To: <c41975e9-e238-441f-a71d-3c7bf3d67e21@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 615 bytes --]
On Tue, Jun 16, 2026 at 10:41:23AM +0200, Krzysztof Kozlowski wrote:
> On 16/06/2026 08:07, Wolfram Sang wrote:
> > The YAML conversion added me as maintainer but I can't recall being
> > asked nor do I want to maintain it. Thierry has created the YAML file
> > and works for the company which contributed the driver.
> >
> > Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
> > Acked-by: Thierry Reding <thierry.reding@kernel.org>
> > ---
>
>
> I think Conor also acked it already.
>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Yes, my fault. Sorry!
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v2 2/2] iio: adc: add Axiado SARADC driver
From: Petar Stepanovic @ 2026-06-16 8:47 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Akhila Kavi, Prasad Bolisetty, Jonathan Cameron, David Lechner,
Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Harshit Shah, linux-iio, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <aisPbXOB6cofF4_r@ashevche-desk.local>
On 6/11/2026 9:41 PM, Andy Shevchenko wrote:
>> +struct axiado_saradc {
>> + void __iomem *regs;
>> + struct clk *clk;
>> + unsigned long clk_rate;
>> + int vref_uV;
>> + struct mutex lock; /* Serializes ADC conversions. */
>> +};
> Is `pahole` satisfied with the chosen layout?
Thanks, Andy.
I checked it and found that the current layout can be improved. I will rearrange the structure members in v3 to avoid the layout issue.
I will also address the other comments in v3.
Regards,
Petar
^ permalink raw reply
* Re: [PATCH v2 2/2] iio: adc: add Axiado SARADC driver
From: Petar Stepanovic @ 2026-06-16 8:45 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Akhila Kavi, Prasad Bolisetty, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Harshit Shah, linux-iio, devicetree, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260611110923.2f55d280@jic23-huawei>
On 6/11/2026 12:09 PM, Jonathan Cameron wrote:
>> +
>> +#define AX_SARADC_MANUAL_CTRL_EN(ch) \
>> + (AX_SARADC_MANUAL_CTRL_ENABLE | \
> Why tabs to place the \ above and spaces here? I don't mind
> that much which you use, but aim for consistency.
Thanks, Jonathan.
The indentation issue was not intentional. It was probably my mistake while copying and adjusting that code, and it looks like my editor replaced some tabs with spaces during the copy.
I will address all of these comments in v3 and clean up the formatting consistently across the driver.
[...]
>> +
>> + regval = FIELD_PREP(AX_SARADC_GLOBAL_CTRL_CH_EN_MASK,
>> + GENMASK(soc_data->num_channels - 1, 0)) |
> For readability that G should be under the a of the line above so it's
> obvious this line starts with a parameter of FIELD_PREP.
>
> The particular form of indentation you have here with an effective 8 spaces
> after the start of the function call seems to be something I'm commenting
> on a lot at the moment. Is some tool defaulting to that?
Yes, that was the same indentation issue. I will fix the |FIELD_PREP()|alignment in v3 and check the rest of the driver for the same pattern.
Regards,
Petar
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox