public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] irqchip/qcom-pdc: support v3.2 HW
@ 2023-08-29  9:21 Dmitry Baryshkov
  2023-08-29  9:21 ` [PATCH v3 1/2] irqchip/qcom-pdc: Add support for " Dmitry Baryshkov
  2023-08-29  9:21 ` [PATCH v3 2/2] arm64: dts: qcom: sm8150: extend the size of the PDC resource Dmitry Baryshkov
  0 siblings, 2 replies; 6+ messages in thread
From: Dmitry Baryshkov @ 2023-08-29  9:21 UTC (permalink / raw)
  To: Andy Gross, Bjorn Andersson, Konrad Dybcio, Thomas Gleixner,
	Marc Zyngier
  Cc: linux-arm-msm, linux-kernel

As Neil's patch has been dropped, because of the regression, squash the
fix for sm8150 into the original patch (so that we don't have broken
kernel commit).

Changes since v2:
- Fix PDC resource size if it is too short instead of setting version to
  dummy 0 value (Marc).
- Squashed the fix into the original patch.

Changes since v1:
- Changed IRQ_ENABLE handling based on Maulik's comments

Dmitry Baryshkov (1):
  arm64: dts: qcom: sm8150: extend the size of the PDC resource

Neil Armstrong (1):
  irqchip/qcom-pdc: Add support for v3.2 HW

 arch/arm64/boot/dts/qcom/sm8150.dtsi |  2 +-
 drivers/irqchip/qcom-pdc.c           | 73 ++++++++++++++++++++++------
 2 files changed, 60 insertions(+), 15 deletions(-)

-- 
2.39.2


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

* [PATCH v3 1/2] irqchip/qcom-pdc: Add support for v3.2 HW
  2023-08-29  9:21 [PATCH v3 0/2] irqchip/qcom-pdc: support v3.2 HW Dmitry Baryshkov
@ 2023-08-29  9:21 ` Dmitry Baryshkov
  2023-08-29  9:50   ` Maulik Shah (mkshah)
  2023-08-29 12:30   ` Marc Zyngier
  2023-08-29  9:21 ` [PATCH v3 2/2] arm64: dts: qcom: sm8150: extend the size of the PDC resource Dmitry Baryshkov
  1 sibling, 2 replies; 6+ messages in thread
From: Dmitry Baryshkov @ 2023-08-29  9:21 UTC (permalink / raw)
  To: Andy Gross, Bjorn Andersson, Konrad Dybcio, Thomas Gleixner,
	Marc Zyngier
  Cc: linux-arm-msm, linux-kernel, Neil Armstrong

From: Neil Armstrong <neil.armstrong@linaro.org>

Starting from HW version 3.2 the IRQ_ENABLE bit has moved to the
IRQ_i_CFG register and requires a change of the driver to avoid
writing into an undefined register address.

Get the HW version from registers and set the IRQ_ENABLE bit to the
correct register depending on the HW version.

Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
[DB: fix crash on sm8150 DTs which listed short PDC region]
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/irqchip/qcom-pdc.c | 73 ++++++++++++++++++++++++++++++--------
 1 file changed, 59 insertions(+), 14 deletions(-)

diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index a32c0d28d038..f9f44b494b1d 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -22,9 +22,22 @@
 
 #define PDC_MAX_GPIO_IRQS	256
 
+/* Valid only on HW version < 3.2 */
 #define IRQ_ENABLE_BANK		0x10
 #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_VERSION		0x1000
+
+/* Notable PDC versions */
+enum {
+	PDC_VERSION_3_2	= 0x30200,
+};
+
 struct pdc_pin_region {
 	u32 pin_base;
 	u32 parent_base;
@@ -37,6 +50,7 @@ static DEFINE_RAW_SPINLOCK(pdc_lock);
 static void __iomem *pdc_base;
 static struct pdc_pin_region *pdc_region;
 static int pdc_region_cnt;
+static unsigned int pdc_version;
 
 static void pdc_reg_write(int reg, u32 i, u32 val)
 {
@@ -53,15 +67,22 @@ static void pdc_enable_intr(struct irq_data *d, bool on)
 	int pin_out = d->hwirq;
 	unsigned long enable;
 	unsigned long flags;
-	u32 index, mask;
-
-	index = pin_out / 32;
-	mask = pin_out % 32;
 
 	raw_spin_lock_irqsave(&pdc_lock, flags);
-	enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
-	__assign_bit(mask, &enable, on);
-	pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
+	if (pdc_version < PDC_VERSION_3_2) {
+		u32 index, mask;
+
+		index = pin_out / 32;
+		mask = pin_out % 32;
+
+		enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
+		__assign_bit(mask, &enable, on);
+		pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
+	} else {
+		enable = pdc_reg_read(IRQ_i_CFG, pin_out);
+		__assign_bit(IRQ_i_CFG_IRQ_ENABLE, &enable, on);
+		pdc_reg_write(IRQ_i_CFG, pin_out, enable);
+	}
 	raw_spin_unlock_irqrestore(&pdc_lock, flags);
 }
 
@@ -142,6 +163,7 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
 	}
 
 	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);
 
 	ret = irq_chip_set_type_parent(d, type);
@@ -246,7 +268,7 @@ static const struct irq_domain_ops qcom_pdc_ops = {
 static int pdc_setup_pin_mapping(struct device_node *np)
 {
 	int ret, n, i;
-	u32 irq_index, reg_index, val;
+	unsigned long val;
 
 	n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32));
 	if (n <= 0 || n % 3)
@@ -277,28 +299,51 @@ static int pdc_setup_pin_mapping(struct device_node *np)
 			return ret;
 
 		for (i = 0; i < pdc_region[n].cnt; i++) {
-			reg_index = (i + pdc_region[n].pin_base) >> 5;
-			irq_index = (i + pdc_region[n].pin_base) & 0x1f;
-			val = pdc_reg_read(IRQ_ENABLE_BANK, reg_index);
-			val &= ~BIT(irq_index);
-			pdc_reg_write(IRQ_ENABLE_BANK, reg_index, val);
+			if (pdc_version < PDC_VERSION_3_2) {
+				u32 irq_index, reg_index;
+
+				reg_index = (i + pdc_region[n].pin_base) >> 5;
+				irq_index = (i + pdc_region[n].pin_base) & 0x1f;
+				val = pdc_reg_read(IRQ_ENABLE_BANK, reg_index);
+				__assign_bit(irq_index, &val, 0);
+				pdc_reg_write(IRQ_ENABLE_BANK, reg_index, val);
+			} else {
+				u32 irq;
+
+				irq = i + pdc_region[n].pin_base;
+				val = pdc_reg_read(IRQ_i_CFG, irq);
+				__assign_bit(IRQ_i_CFG_IRQ_ENABLE, &val,  0);
+				pdc_reg_write(IRQ_i_CFG, irq, val);
+			}
 		}
 	}
 
 	return 0;
 }
 
+#define QCOM_PDC_SIZE 0x30000
+
 static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
 {
 	struct irq_domain *parent_domain, *pdc_domain;
+	struct resource res;
+	resource_size_t res_size;
 	int ret;
 
-	pdc_base = of_iomap(node, 0);
+	/* compat with old sm8150 DT which had very small region for PDC */
+	if (of_address_to_resource(node, 0, &res))
+		return -EINVAL;
+
+	res_size = max_t(resource_size_t, resource_size(&res), QCOM_PDC_SIZE);
+
+	pdc_base = ioremap(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, 0);
+
 	parent_domain = irq_find_host(parent);
 	if (!parent_domain) {
 		pr_err("%pOF: unable to find PDC's parent domain\n", node);
-- 
2.39.2


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

* [PATCH v3 2/2] arm64: dts: qcom: sm8150: extend the size of the PDC resource
  2023-08-29  9:21 [PATCH v3 0/2] irqchip/qcom-pdc: support v3.2 HW Dmitry Baryshkov
  2023-08-29  9:21 ` [PATCH v3 1/2] irqchip/qcom-pdc: Add support for " Dmitry Baryshkov
@ 2023-08-29  9:21 ` Dmitry Baryshkov
  2023-08-29  9:33   ` Neil Armstrong
  1 sibling, 1 reply; 6+ messages in thread
From: Dmitry Baryshkov @ 2023-08-29  9:21 UTC (permalink / raw)
  To: Andy Gross, Bjorn Andersson, Konrad Dybcio, Thomas Gleixner,
	Marc Zyngier
  Cc: linux-arm-msm, linux-kernel

Follow the example of other platforms and extend the PDC resource region
to 0x30000, so that the PDC driver can read the PDC_VERSION register.

Fixes: 397ad94668c1 ("arm64: dts: qcom: sm8150: Add pdc interrupt controller node")
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 arch/arm64/boot/dts/qcom/sm8150.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index 380712aee977..38c5d6dbd0d7 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -3923,7 +3923,7 @@ dispcc: clock-controller@af00000 {
 
 		pdc: interrupt-controller@b220000 {
 			compatible = "qcom,sm8150-pdc", "qcom,pdc";
-			reg = <0 0x0b220000 0 0x400>;
+			reg = <0 0x0b220000 0 0x30000>;
 			qcom,pdc-ranges = <0 480 94>, <94 609 31>,
 					  <125 63 1>;
 			#interrupt-cells = <2>;
-- 
2.39.2


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

* Re: [PATCH v3 2/2] arm64: dts: qcom: sm8150: extend the size of the PDC resource
  2023-08-29  9:21 ` [PATCH v3 2/2] arm64: dts: qcom: sm8150: extend the size of the PDC resource Dmitry Baryshkov
@ 2023-08-29  9:33   ` Neil Armstrong
  0 siblings, 0 replies; 6+ messages in thread
From: Neil Armstrong @ 2023-08-29  9:33 UTC (permalink / raw)
  To: Dmitry Baryshkov, Andy Gross, Bjorn Andersson, Konrad Dybcio,
	Thomas Gleixner, Marc Zyngier
  Cc: linux-arm-msm, linux-kernel

On 29/08/2023 11:21, Dmitry Baryshkov wrote:
> Follow the example of other platforms and extend the PDC resource region
> to 0x30000, so that the PDC driver can read the PDC_VERSION register.
> 
> Fixes: 397ad94668c1 ("arm64: dts: qcom: sm8150: Add pdc interrupt controller node")
> Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>   arch/arm64/boot/dts/qcom/sm8150.dtsi | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
> index 380712aee977..38c5d6dbd0d7 100644
> --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
> @@ -3923,7 +3923,7 @@ dispcc: clock-controller@af00000 {
>   
>   		pdc: interrupt-controller@b220000 {
>   			compatible = "qcom,sm8150-pdc", "qcom,pdc";
> -			reg = <0 0x0b220000 0 0x400>;
> +			reg = <0 0x0b220000 0 0x30000>;
>   			qcom,pdc-ranges = <0 480 94>, <94 609 31>,
>   					  <125 63 1>;
>   			#interrupt-cells = <2>;

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

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

* Re: [PATCH v3 1/2] irqchip/qcom-pdc: Add support for v3.2 HW
  2023-08-29  9:21 ` [PATCH v3 1/2] irqchip/qcom-pdc: Add support for " Dmitry Baryshkov
@ 2023-08-29  9:50   ` Maulik Shah (mkshah)
  2023-08-29 12:30   ` Marc Zyngier
  1 sibling, 0 replies; 6+ messages in thread
From: Maulik Shah (mkshah) @ 2023-08-29  9:50 UTC (permalink / raw)
  To: Dmitry Baryshkov, Andy Gross, Bjorn Andersson, Konrad Dybcio,
	Thomas Gleixner, Marc Zyngier
  Cc: linux-arm-msm, linux-kernel, Neil Armstrong

Hi,

On 8/29/2023 2:51 PM, Dmitry Baryshkov wrote:
> From: Neil Armstrong <neil.armstrong@linaro.org>
>
> Starting from HW version 3.2 the IRQ_ENABLE bit has moved to the
> IRQ_i_CFG register and requires a change of the driver to avoid
> writing into an undefined register address.
>
> Get the HW version from registers and set the IRQ_ENABLE bit to the
> correct register depending on the HW version.
>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> [DB: fix crash on sm8150 DTs which listed short PDC region]
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>   drivers/irqchip/qcom-pdc.c | 73 ++++++++++++++++++++++++++++++--------
>   1 file changed, 59 insertions(+), 14 deletions(-)

Reviewed-by: Maulik Shah <quic_mkshah@quicinc.com>

Thanks,
Maulik


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

* Re: [PATCH v3 1/2] irqchip/qcom-pdc: Add support for v3.2 HW
  2023-08-29  9:21 ` [PATCH v3 1/2] irqchip/qcom-pdc: Add support for " Dmitry Baryshkov
  2023-08-29  9:50   ` Maulik Shah (mkshah)
@ 2023-08-29 12:30   ` Marc Zyngier
  1 sibling, 0 replies; 6+ messages in thread
From: Marc Zyngier @ 2023-08-29 12:30 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Andy Gross, Bjorn Andersson, Konrad Dybcio, Thomas Gleixner,
	linux-arm-msm, linux-kernel, Neil Armstrong

On Tue, 29 Aug 2023 10:21:18 +0100,
Dmitry Baryshkov <dmitry.baryshkov@linaro.org> wrote:
> 
> From: Neil Armstrong <neil.armstrong@linaro.org>
> 
> Starting from HW version 3.2 the IRQ_ENABLE bit has moved to the
> IRQ_i_CFG register and requires a change of the driver to avoid
> writing into an undefined register address.
> 
> Get the HW version from registers and set the IRQ_ENABLE bit to the
> correct register depending on the HW version.
> 
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> [DB: fix crash on sm8150 DTs which listed short PDC region]
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>  drivers/irqchip/qcom-pdc.c | 73 ++++++++++++++++++++++++++++++--------
>  1 file changed, 59 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
> index a32c0d28d038..f9f44b494b1d 100644
> --- a/drivers/irqchip/qcom-pdc.c
> +++ b/drivers/irqchip/qcom-pdc.c
> @@ -22,9 +22,22 @@
>  
>  #define PDC_MAX_GPIO_IRQS	256
>  
> +/* Valid only on HW version < 3.2 */
>  #define IRQ_ENABLE_BANK		0x10
>  #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_VERSION		0x1000

That's an offset, right? Maybe spelling it as such would make this
more readable...

> +
> +/* Notable PDC versions */
> +enum {
> +	PDC_VERSION_3_2	= 0x30200,

... specially when reading this (why is it all of a sudden an enum?).

> +};
> +
>  struct pdc_pin_region {
>  	u32 pin_base;
>  	u32 parent_base;
> @@ -37,6 +50,7 @@ static DEFINE_RAW_SPINLOCK(pdc_lock);
>  static void __iomem *pdc_base;
>  static struct pdc_pin_region *pdc_region;
>  static int pdc_region_cnt;
> +static unsigned int pdc_version;
>  
>  static void pdc_reg_write(int reg, u32 i, u32 val)
>  {
> @@ -53,15 +67,22 @@ static void pdc_enable_intr(struct irq_data *d, bool on)
>  	int pin_out = d->hwirq;
>  	unsigned long enable;
>  	unsigned long flags;
> -	u32 index, mask;
> -
> -	index = pin_out / 32;
> -	mask = pin_out % 32;
>  
>  	raw_spin_lock_irqsave(&pdc_lock, flags);
> -	enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
> -	__assign_bit(mask, &enable, on);
> -	pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
> +	if (pdc_version < PDC_VERSION_3_2) {
> +		u32 index, mask;
> +
> +		index = pin_out / 32;
> +		mask = pin_out % 32;
> +
> +		enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
> +		__assign_bit(mask, &enable, on);
> +		pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
> +	} else {
> +		enable = pdc_reg_read(IRQ_i_CFG, pin_out);
> +		__assign_bit(IRQ_i_CFG_IRQ_ENABLE, &enable, on);
> +		pdc_reg_write(IRQ_i_CFG, pin_out, enable);
> +	}
>  	raw_spin_unlock_irqrestore(&pdc_lock, flags);
>  }
>  
> @@ -142,6 +163,7 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
>  	}
>  
>  	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);
>  
>  	ret = irq_chip_set_type_parent(d, type);
> @@ -246,7 +268,7 @@ static const struct irq_domain_ops qcom_pdc_ops = {
>  static int pdc_setup_pin_mapping(struct device_node *np)
>  {
>  	int ret, n, i;
> -	u32 irq_index, reg_index, val;
> +	unsigned long val;
>  
>  	n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32));
>  	if (n <= 0 || n % 3)
> @@ -277,28 +299,51 @@ static int pdc_setup_pin_mapping(struct device_node *np)
>  			return ret;
>  
>  		for (i = 0; i < pdc_region[n].cnt; i++) {
> -			reg_index = (i + pdc_region[n].pin_base) >> 5;
> -			irq_index = (i + pdc_region[n].pin_base) & 0x1f;
> -			val = pdc_reg_read(IRQ_ENABLE_BANK, reg_index);
> -			val &= ~BIT(irq_index);
> -			pdc_reg_write(IRQ_ENABLE_BANK, reg_index, val);
> +			if (pdc_version < PDC_VERSION_3_2) {
> +				u32 irq_index, reg_index;
> +
> +				reg_index = (i + pdc_region[n].pin_base) >> 5;
> +				irq_index = (i + pdc_region[n].pin_base) & 0x1f;
> +				val = pdc_reg_read(IRQ_ENABLE_BANK, reg_index);
> +				__assign_bit(irq_index, &val, 0);
> +				pdc_reg_write(IRQ_ENABLE_BANK, reg_index, val);
> +			} else {
> +				u32 irq;
> +
> +				irq = i + pdc_region[n].pin_base;
> +				val = pdc_reg_read(IRQ_i_CFG, irq);
> +				__assign_bit(IRQ_i_CFG_IRQ_ENABLE, &val,  0);
> +				pdc_reg_write(IRQ_i_CFG, irq, val);
> +			}

This is a bit backwards. The PDC version doesn't change within the
loop. But more importantly, this is a rewrite of the pdc_enable_intr()
helper, only taking raw indices instead of an irq_data pointer.

Surely this can be written in a better way.

>  		}
>  	}
>  
>  	return 0;
>  }
>  
> +#define QCOM_PDC_SIZE 0x30000
> +
>  static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
>  {
>  	struct irq_domain *parent_domain, *pdc_domain;
> +	struct resource res;
> +	resource_size_t res_size;

nit: swapping these two lines will make things vaguely more readable.

>  	int ret;
>  
> -	pdc_base = of_iomap(node, 0);
> +	/* compat with old sm8150 DT which had very small region for PDC */
> +	if (of_address_to_resource(node, 0, &res))
> +		return -EINVAL;
> +
> +	res_size = max_t(resource_size_t, resource_size(&res), QCOM_PDC_SIZE);

This probably deserves a warning so that DTs that do not have the
correct size get fixed.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

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

end of thread, other threads:[~2023-08-29 12:31 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-29  9:21 [PATCH v3 0/2] irqchip/qcom-pdc: support v3.2 HW Dmitry Baryshkov
2023-08-29  9:21 ` [PATCH v3 1/2] irqchip/qcom-pdc: Add support for " Dmitry Baryshkov
2023-08-29  9:50   ` Maulik Shah (mkshah)
2023-08-29 12:30   ` Marc Zyngier
2023-08-29  9:21 ` [PATCH v3 2/2] arm64: dts: qcom: sm8150: extend the size of the PDC resource Dmitry Baryshkov
2023-08-29  9:33   ` Neil Armstrong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox