* Re: [PATCH] arm64: Fix double TCR_T0SZ_OFFSET shift
From: Will Deacon @ 2024-04-02 11:58 UTC (permalink / raw)
To: Seongsu Park
Cc: catalin.marinas, ardb, mark.rutland, linux-arm-kernel,
linux-kernel, Leem ChaeHoon, Gyeonggeon Choi, Soomin Cho,
DaeRo Lee, kmasta
In-Reply-To: <20240402104950.170632-1-sgsu.park@samsung.com>
On Tue, Apr 02, 2024 at 07:49:50PM +0900, Seongsu Park wrote:
> We have already shifted the value of t0sz in TCR_T0SZ by TCR_T0SZ_OFFSET.
> So, the TCR_T0SZ_OFFSET shift here should be removed.
>
> Co-developed-by: Leem ChaeHoon <infinite.run@gmail.com>
> Signed-off-by: Leem ChaeHoon <infinite.run@gmail.com>
> Co-developed-by: Gyeonggeon Choi <gychoi@student.42seoul.kr>
> Signed-off-by: Gyeonggeon Choi <gychoi@student.42seoul.kr>
> Co-developed-by: Soomin Cho <to.soomin@gmail.com>
> Signed-off-by: Soomin Cho <to.soomin@gmail.com>
> Co-developed-by: DaeRo Lee <skseofh@gmail.com>
> Signed-off-by: DaeRo Lee <skseofh@gmail.com>
> Co-developed-by: kmasta <kmasta.study@gmail.com>
> Signed-off-by: kmasta <kmasta.study@gmail.com>
> Signed-off-by: Seongsu Park <sgsu.park@samsung.com>
heh, that's quite a lot of people. Did you remove three chars each? :p
> ---
> arch/arm64/include/asm/mmu_context.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
> index c768d16b81a4..58de99836d2e 100644
> --- a/arch/arm64/include/asm/mmu_context.h
> +++ b/arch/arm64/include/asm/mmu_context.h
> @@ -76,7 +76,7 @@ static inline void __cpu_set_tcr_t0sz(unsigned long t0sz)
> return;
>
> tcr &= ~TCR_T0SZ_MASK;
> - tcr |= t0sz << TCR_T0SZ_OFFSET;
> + tcr |= t0sz;
Thankfully, TCR_T0SZ_OFFSET is 0 so this isn't as alarming as it looks.
Even so, if we're going to make the code consistent, then shouldn't the
earlier conditional be updated too?
if ((tcr & TCR_T0SZ_MASK) >> TCR_T0SZ_OFFSET == t0sz)
return;
seems to assume that t0sz is unshifted.
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] dt-bindings: watchdog: Convert Aspeed binding to DT schema
From: Andrew Jeffery @ 2024-04-02 12:01 UTC (permalink / raw)
To: wim, linux
Cc: Andrew Jeffery, robh, krzysztof.kozlowski+dt, conor+dt, joel, zev,
linux-watchdog, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel
Squash warnings such as:
```
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-galaxy100.dtb: /ahb/apb@1e600000/watchdog@1e785000: failed to match any schema with compatible: ['aspeed,ast2400-wdt']
```
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
---
.../bindings/watchdog/aspeed,ast2400-wdt.yaml | 130 ++++++++++++++++++
.../bindings/watchdog/aspeed-wdt.txt | 73 ----------
2 files changed, 130 insertions(+), 73 deletions(-)
create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
delete mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
diff --git a/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml b/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
new file mode 100644
index 000000000000..10fcb50c4051
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/aspeed,ast2400-wdt.yaml
@@ -0,0 +1,130 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/watchdog/aspeed,ast2400-wdt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Aspeed watchdog timer controllers
+
+maintainers:
+ - Andrew Jeffery <andrew@codeconstruct.com.au>
+
+properties:
+ compatible:
+ enum:
+ - aspeed,ast2400-wdt
+ - aspeed,ast2500-wdt
+ - aspeed,ast2600-wdt
+
+ reg:
+ maxItems: 1
+
+ clocks: true
+
+ aspeed,reset-type:
+ enum:
+ - cpu
+ - soc
+ - system
+ - none
+ description: |
+ Reset behaviour - The watchdog can be programmed to generate one of three
+ different types of reset when a timeout occcurs.
+
+ Specifying 'cpu' will only reset the processor on a timeout event.
+
+ Specifying 'soc' will reset a configurable subset of the SoC's controllers
+ on a timeout event. Controllers critical to the SoC's operation may remain untouched.
+
+ Specifying 'system' will reset all controllers on a timeout event, as if EXTRST had been asserted.
+ Specifying "none" will cause the timeout event to have no reset effect.
+ Another watchdog engine on the chip must be used for chip reset operations.
+
+ The default reset type is "system"
+
+ aspeed,alt-boot:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: |
+ Direct the watchdog to configure the SoC to boot from the alternative boot
+ region if a timeout occurs.
+
+ aspeed,external-signal:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: |
+ Assert the timeout event on an external signal pin associated with the
+ watchdog controller instance. The pin must be muxed appropriately.
+
+ aspeed,ext-pulse-duration:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ The duration, in microseconds, of the pulse emitted on the external signal pin
+
+ aspeed,ext-push-pull:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: |
+ If aspeed,external-signal is specified in the node, set the external
+ signal pin's drive type to push-pull. If aspeed,ext-push-pull is not
+ specified then the pin is configured as open-drain.
+
+ aspeed,ext-active-high:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: |
+ If both aspeed,external-signal and aspeed,ext-push-pull are specified in
+ the node, set the pulse polarity to active-high. If aspeed,ext-active-high
+ is not specified then the pin is configured as active-low.
+
+ aspeed,reset-mask:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 1
+ maxItems: 2
+ description: |
+ A bitmaks indicating which peripherals will be reset if the watchdog
+ timer expires. On AST2500 SoCs this should be a single word defined using
+ the AST2500_WDT_RESET_* macros; on AST2600 SoCs this should be a two-word
+ array with the first word defined using the AST2600_WDT_RESET1_* macros,
+ and the second word defined using the AST2600_WDT_RESET2_* macros.
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - if:
+ anyOf:
+ - required:
+ - aspeed,ext-push-pull
+ - required:
+ - aspeed,ext-active-high
+ - required:
+ - aspeed,reset-mask
+ then:
+ properties:
+ compatible:
+ enum:
+ - aspeed,ast2500-wdt
+ - aspeed,ast2600-wdt
+ - if:
+ required:
+ - aspeed,ext-active-high
+ then:
+ required:
+ - aspeed,ext-push-pull
+
+additionalProperties: false
+
+examples:
+ - |
+ wdt1: watchdog@1e785000 {
+ compatible = "aspeed,ast2400-wdt";
+ reg = <0x1e785000 0x1c>;
+ aspeed,reset-type = "system";
+ aspeed,external-signal;
+ };
+ - |
+ #include <dt-bindings/watchdog/aspeed-wdt.h>
+ wdt2: watchdog@1e785040 {
+ compatible = "aspeed,ast2600-wdt";
+ reg = <0x1e785040 0x40>;
+ aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
+ (AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
+ };
diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
deleted file mode 100644
index 3208adb3e52e..000000000000
--- a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
+++ /dev/null
@@ -1,73 +0,0 @@
-Aspeed Watchdog Timer
-
-Required properties:
- - compatible: must be one of:
- - "aspeed,ast2400-wdt"
- - "aspeed,ast2500-wdt"
- - "aspeed,ast2600-wdt"
-
- - reg: physical base address of the controller and length of memory mapped
- region
-
-Optional properties:
-
- - aspeed,reset-type = "cpu|soc|system|none"
-
- Reset behavior - Whenever a timeout occurs the watchdog can be programmed
- to generate one of three different, mutually exclusive, types of resets.
-
- Type "none" can be specified to indicate that no resets are to be done.
- This is useful in situations where another watchdog engine on chip is
- to perform the reset.
-
- If 'aspeed,reset-type=' is not specified the default is to enable system
- reset.
-
- Reset types:
-
- - cpu: Reset CPU on watchdog timeout
-
- - soc: Reset 'System on Chip' on watchdog timeout
-
- - system: Reset system on watchdog timeout
-
- - none: No reset is performed on timeout. Assumes another watchdog
- engine is responsible for this.
-
- - aspeed,alt-boot: If property is present then boot from alternate block.
- - aspeed,external-signal: If property is present then signal is sent to
- external reset counter (only WDT1 and WDT2). If not
- specified no external signal is sent.
- - aspeed,ext-pulse-duration: External signal pulse duration in microseconds
-
-Optional properties for AST2500-compatible watchdogs:
- - aspeed,ext-push-pull: If aspeed,external-signal is present, set the pin's
- drive type to push-pull. The default is open-drain.
- - aspeed,ext-active-high: If aspeed,external-signal is present and and the pin
- is configured as push-pull, then set the pulse
- polarity to active-high. The default is active-low.
-
-Optional properties for AST2500- and AST2600-compatible watchdogs:
- - aspeed,reset-mask: A bitmask indicating which peripherals will be reset if
- the watchdog timer expires. On AST2500 this should be a
- single word defined using the AST2500_WDT_RESET_* macros;
- on AST2600 this should be a two-word array with the first
- word defined using the AST2600_WDT_RESET1_* macros and the
- second word defined using the AST2600_WDT_RESET2_* macros.
-
-Examples:
-
- wdt1: watchdog@1e785000 {
- compatible = "aspeed,ast2400-wdt";
- reg = <0x1e785000 0x1c>;
- aspeed,reset-type = "system";
- aspeed,external-signal;
- };
-
- #include <dt-bindings/watchdog/aspeed-wdt.h>
- wdt2: watchdog@1e785040 {
- compatible = "aspeed,ast2600-wdt";
- reg = <0x1e785040 0x40>;
- aspeed,reset-mask = <AST2600_WDT_RESET1_DEFAULT
- (AST2600_WDT_RESET2_DEFAULT & ~AST2600_WDT_RESET2_LPC)>;
- };
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 2/9] perf/arm-cmn: Avoid explicit cpumask var allocation from stack
From: Dawei Li @ 2024-04-02 10:56 UTC (permalink / raw)
To: will, mark.rutland
Cc: xueshuai, renyu.zj, yangyicong, jonathan.cameron, andersson,
konrad.dybcio, linux-arm-kernel, linux-kernel, linux-arm-msm,
Dawei Li
In-Reply-To: <20240402105610.1695644-1-dawei.li@shingroup.cn>
For CONFIG_CPUMASK_OFFSTACK=y kernel, explicit allocation of cpumask
variable on stack is not recommended since it can cause potential stack
overflow.
Instead, kernel code should always use *cpumask_var API(s) to allocate
cpumask var in config- neutral way, leaving allocation strategy to
CONFIG_CPUMASK_OFFSTACK.
Use *cpumask_var API(s) to address it.
Signed-off-by: Dawei Li <dawei.li@shingroup.cn>
---
drivers/perf/arm-cmn.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 7ef9c7e4836b..7278fd72d3da 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -1949,21 +1949,26 @@ static int arm_cmn_pmu_offline_cpu(unsigned int cpu, struct hlist_node *cpuhp_no
{
struct arm_cmn *cmn;
unsigned int target;
+ cpumask_var_t mask;
int node;
- cpumask_t mask;
cmn = hlist_entry_safe(cpuhp_node, struct arm_cmn, cpuhp_node);
if (cpu != cmn->cpu)
return 0;
+ if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+ return 0;
+
node = dev_to_node(cmn->dev);
- if (cpumask_and(&mask, cpumask_of_node(node), cpu_online_mask) &&
- cpumask_andnot(&mask, &mask, cpumask_of(cpu)))
- target = cpumask_any(&mask);
+ if (cpumask_and(mask, cpumask_of_node(node), cpu_online_mask) &&
+ cpumask_andnot(mask, mask, cpumask_of(cpu)))
+ target = cpumask_any(mask);
else
target = cpumask_any_but(cpu_online_mask, cpu);
if (target < nr_cpu_ids)
arm_cmn_migrate(cmn, target);
+
+ free_cpumask_var(mask);
return 0;
}
--
2.27.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 7/9] perf/hisi_uncore: Avoid explicit cpumask var allocation from stack
From: Dawei Li @ 2024-04-02 10:56 UTC (permalink / raw)
To: will, mark.rutland
Cc: xueshuai, renyu.zj, yangyicong, jonathan.cameron, andersson,
konrad.dybcio, linux-arm-kernel, linux-kernel, linux-arm-msm,
Dawei Li
In-Reply-To: <20240402105610.1695644-1-dawei.li@shingroup.cn>
For CONFIG_CPUMASK_OFFSTACK=y kernel, explicit allocation of cpumask
variable on stack is not recommended since it can cause potential stack
overflow.
Instead, kernel code should always use *cpumask_var API(s) to allocate
cpumask var in config- neutral way, leaving allocation strategy to
CONFIG_CPUMASK_OFFSTACK.
Use *cpumask_var API(s) to address it.
Signed-off-by: Dawei Li <dawei.li@shingroup.cn>
---
drivers/perf/hisilicon/hisi_uncore_pmu.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
index 04031450d5fe..06891d23b21c 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -504,7 +504,7 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
{
struct hisi_pmu *hisi_pmu = hlist_entry_safe(node, struct hisi_pmu,
node);
- cpumask_t pmu_online_cpus;
+ cpumask_var_t pmu_online_cpus;
unsigned int target;
if (!cpumask_test_and_clear_cpu(cpu, &hisi_pmu->associated_cpus))
@@ -514,21 +514,26 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
if (hisi_pmu->on_cpu != cpu)
return 0;
+ if (!alloc_cpumask_var(&pmu_online_cpus, GFP_KERNEL))
+ return 0;
+
/* Give up ownership of the PMU */
hisi_pmu->on_cpu = -1;
/* Choose a new CPU to migrate ownership of the PMU to */
- cpumask_and(&pmu_online_cpus, &hisi_pmu->associated_cpus,
+ cpumask_and(pmu_online_cpus, &hisi_pmu->associated_cpus,
cpu_online_mask);
- target = cpumask_any_but(&pmu_online_cpus, cpu);
+ target = cpumask_any_but(pmu_online_cpus, cpu);
if (target >= nr_cpu_ids)
- return 0;
+ goto __free_cpumask;
perf_pmu_migrate_context(&hisi_pmu->pmu, cpu, target);
/* Use this CPU for event counting */
hisi_pmu->on_cpu = target;
WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(target)));
+__free_cpumask:
+ free_cpumask_var(pmu_online_cpus);
return 0;
}
EXPORT_SYMBOL_GPL(hisi_uncore_pmu_offline_cpu);
--
2.27.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH] ARM: dts: imx7s-warp: Fix OV2680 supply names
From: Shawn Guo @ 2024-04-02 10:58 UTC (permalink / raw)
To: Fabio Estevam; +Cc: shawnguo, linux-arm-kernel, rmfrfs, Fabio Estevam
In-Reply-To: <20240323125327.1398102-1-festevam@gmail.com>
On Sat, Mar 23, 2024 at 09:53:27AM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <festevam@denx.de>
>
> Fix the OV2680 supply names according to ovti,ov2680.yaml.
>
> Signed-off-by: Fabio Estevam <festevam@denx.de>
Do we want to have a Fixes tag for it?
Shawn
> ---
> arch/arm/boot/dts/nxp/imx/imx7s-warp.dts | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts
> index ba7231b364bb..c26888b7af3f 100644
> --- a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts
> +++ b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts
> @@ -201,9 +201,9 @@ ov2680: camera@36 {
> clocks = <&osc>;
> clock-names = "xvclk";
> reset-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
> - DOVDD-supply = <&sw2_reg>;
> - DVDD-supply = <&sw2_reg>;
> - AVDD-supply = <®_peri_3p15v>;
> + dovdd-supply = <&sw2_reg>;
> + dvdd-supply = <&sw2_reg>;
> + avdd-supply = <®_peri_3p15v>;
>
> port {
> ov2680_to_mipi: endpoint {
> --
> 2.34.1
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/2] ARM: boot: dts: microchip: at91-sama7g5ek: Replace regulator-suspend-voltage with the valid property
From: Krzysztof Kozlowski @ 2024-04-02 12:07 UTC (permalink / raw)
To: Andrei.Simion, robh, krzysztof.kozlowski+dt, conor+dt,
Nicolas.Ferre, alexandre.belloni, claudiu.beznea, Mihai.Sain
Cc: linux-arm-kernel, linux-kernel, devicetree
In-Reply-To: <312bed1a-0b8a-457d-a2e2-b8ee1b6f443b@microchip.com>
On 02/04/2024 13:27, Andrei.Simion@microchip.com wrote:
> On 02.04.2024 13:39, Krzysztof Kozlowski wrote:
>> [You don't often get email from krzysztof.kozlowski@linaro.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>>
>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>
>> On 02/04/2024 11:12, Andrei Simion wrote:
>>> Replace regulator-suspend-voltage with regulator-suspend-microvolt.
>>
>> Why?
>>
>
> at91-sama7g5ek.dtb: mcp16502@5b: regulators:VDD_(CORE|OTHER)|LDO[1-2]:
> regulator-state-standby 'regulator-suspend-voltage' does not match any of
> the regexes 'pinctrl-[0-9]+' from schema
> $id: http://devicetree.org/schemas/regulator/microchip,mcp16502.yaml#
>
> no property named regulator-suspend-voltage in
> https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/regulator/regulator.yaml
> so if it is using this property there will be no effect as it was expected in
> https://github.com/torvalds/linux/commit/85b1304b9daa06367139b471789c7ddb76250b9f
>
>> Please explain what is the bug and how it manifests itself. Is one
>> property incorrect and other correct?
>>
> The main reason is explained in the cover-letter but if you ask me to explain in each commit I will do it in next version.
Cover letter does not go to commit history. Each commit should explain
why you are doing it. Usually piece of the warning is quite
self-explanatory, thus one easy way to achieve the point - answer why.
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v8 3/7] spmi: pmic-arb: Fix some compile warnings about members not being described
From: Abel Vesa @ 2024-04-02 12:07 UTC (permalink / raw)
To: Stephen Boyd, Matthias Brugger, Bjorn Andersson, Konrad Dybcio,
Dmitry Baryshkov, Neil Armstrong, AngeloGioacchino Del Regno,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Srini Kandagatla, Johan Hovold, linux-kernel, linux-arm-kernel,
linux-arm-msm, linux-mediatek, devicetree, Abel Vesa
In-Reply-To: <20240402-spmi-multi-master-support-v8-0-ce6f2d14a058@linaro.org>
Fix the following compile warnings:
warning: Function parameter or struct member 'core' not described in 'spmi_pmic_arb'
warning: Function parameter or struct member 'core_size' not described in 'spmi_pmic_arb'
warning: Function parameter or struct member 'mapping_table_valid' not described in 'spmi_pmic_arb'
warning: Function parameter or struct member 'pmic_arb' not described in 'pmic_arb_read_data'
warning: Function parameter or struct member 'pmic_arb' not described in 'pmic_arb_write_data'
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
drivers/spmi/spmi-pmic-arb.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 9ed1180fe31f..704fd4506971 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -132,6 +132,8 @@ struct apid_data {
* @wr_base: on v1 "core", on v2 "chnls" register base off DT.
* @intr: address of the SPMI interrupt control registers.
* @cnfg: address of the PMIC Arbiter configuration registers.
+ * @core: core register base for v2 and above only (see above)
+ * @core_size: core register base size
* @lock: lock to synchronize accesses.
* @channel: execution environment channel to use for accesses.
* @irq: PMIC ARB interrupt.
@@ -144,6 +146,7 @@ struct apid_data {
* @apid_count: on v5 and v7: number of APIDs associated with the
* particular SPMI bus instance
* @mapping_table: in-memory copy of PPID -> APID mapping table.
+ * @mapping_table_valid:bitmap containing valid-only periphs
* @domain: irq domain object for PMIC IRQ domain
* @spmic: SPMI controller object
* @ver_ops: version dependent operations.
@@ -232,6 +235,7 @@ static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb *pmic_arb,
/**
* pmic_arb_read_data: reads pmic-arb's register and copy 1..4 bytes to buf
+ * @pmic_arb: the SPMI PMIC arbiter
* @bc: byte count -1. range: 0..3
* @reg: register's address
* @buf: output parameter, length must be bc + 1
@@ -246,6 +250,7 @@ pmic_arb_read_data(struct spmi_pmic_arb *pmic_arb, u8 *buf, u32 reg, u8 bc)
/**
* pmic_arb_write_data: write 1..4 bytes from buf to pmic-arb's register
+ * @pmic_arb: the SPMI PMIC arbiter
* @bc: byte-count -1. range: 0..3.
* @reg: register's address.
* @buf: buffer to write. length must be bc + 1.
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v8 2/7] dt-bindings: spmi: Deprecate qcom,bus-id
From: Abel Vesa @ 2024-04-02 12:07 UTC (permalink / raw)
To: Stephen Boyd, Matthias Brugger, Bjorn Andersson, Konrad Dybcio,
Dmitry Baryshkov, Neil Armstrong, AngeloGioacchino Del Regno,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Srini Kandagatla, Johan Hovold, linux-kernel, linux-arm-kernel,
linux-arm-msm, linux-mediatek, devicetree, Abel Vesa,
Krzysztof Kozlowski
In-Reply-To: <20240402-spmi-multi-master-support-v8-0-ce6f2d14a058@linaro.org>
As it is optional and no platform is actually using the secondary bus,
deprecate the qcom,bus-id property. For newer platforms that implement
SPMI PMIC ARB v7 in HW, the X1E80100 approach should be used.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml b/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml
index f983b4af6db9..51daf1b847a9 100644
--- a/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml
+++ b/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml
@@ -92,6 +92,7 @@ properties:
description: >
SPMI bus instance. only applicable to PMIC arbiter version 7 and beyond.
Supported values, 0 = primary bus, 1 = secondary bus
+ deprecated: true
required:
- compatible
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v8 1/7] dt-bindings: spmi: Add X1E80100 SPMI PMIC ARB schema
From: Abel Vesa @ 2024-04-02 12:07 UTC (permalink / raw)
To: Stephen Boyd, Matthias Brugger, Bjorn Andersson, Konrad Dybcio,
Dmitry Baryshkov, Neil Armstrong, AngeloGioacchino Del Regno,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Srini Kandagatla, Johan Hovold, linux-kernel, linux-arm-kernel,
linux-arm-msm, linux-mediatek, devicetree, Abel Vesa,
Krzysztof Kozlowski
In-Reply-To: <20240402-spmi-multi-master-support-v8-0-ce6f2d14a058@linaro.org>
Add dedicated schema for X1E80100 PMIC ARB (v7) as it allows multiple
buses by declaring them as child nodes.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
.../bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml | 136 +++++++++++++++++++++
1 file changed, 136 insertions(+)
diff --git a/Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml b/Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml
new file mode 100644
index 000000000000..f32a7ae33b4b
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spmi/qcom,x1e80100-spmi-pmic-arb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm X1E80100 SPMI Controller (PMIC Arbiter v7)
+
+maintainers:
+ - Stephen Boyd <sboyd@kernel.org>
+
+description: |
+ The X1E80100 SPMI PMIC Arbiter implements HW version 7 and it's an SPMI
+ controller with wrapping arbitration logic to allow for multiple on-chip
+ devices to control up to 2 SPMI separate buses.
+
+ The PMIC Arbiter can also act as an interrupt controller, providing interrupts
+ to slave devices.
+
+properties:
+ compatible:
+ const: qcom,x1e80100-spmi-pmic-arb
+
+ reg:
+ items:
+ - description: core registers
+ - description: tx-channel per virtual slave regosters
+ - description: rx-channel (called observer) per virtual slave registers
+
+ reg-names:
+ items:
+ - const: core
+ - const: chnls
+ - const: obsrvr
+
+ ranges: true
+
+ '#address-cells':
+ const: 2
+
+ '#size-cells':
+ const: 2
+
+ qcom,ee:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 5
+ description: >
+ indicates the active Execution Environment identifier
+
+ qcom,channel:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 5
+ description: >
+ which of the PMIC Arb provided channels to use for accesses
+
+patternProperties:
+ "^spmi@[a-f0-9]+$":
+ type: object
+ $ref: /schemas/spmi/spmi.yaml
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ items:
+ - description: configuration registers
+ - description: interrupt controller registers
+
+ reg-names:
+ items:
+ - const: cnfg
+ - const: intr
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-names:
+ const: periph_irq
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 4
+ description: |
+ cell 1: slave ID for the requested interrupt (0-15)
+ cell 2: peripheral ID for requested interrupt (0-255)
+ cell 3: the requested peripheral interrupt (0-7)
+ cell 4: interrupt flags indicating level-sense information,
+ as defined in dt-bindings/interrupt-controller/irq.h
+
+required:
+ - compatible
+ - reg-names
+ - qcom,ee
+ - qcom,channel
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ spmi: arbiter@c400000 {
+ compatible = "qcom,x1e80100-spmi-pmic-arb";
+ reg = <0 0x0c400000 0 0x3000>,
+ <0 0x0c500000 0 0x4000000>,
+ <0 0x0c440000 0 0x80000>;
+ reg-names = "core", "chnls", "obsrvr";
+
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ spmi_bus0: spmi@c42d000 {
+ reg = <0 0x0c42d000 0 0x4000>,
+ <0 0x0c4c0000 0 0x10000>;
+ reg-names = "cnfg", "intr";
+
+ interrupt-names = "periph_irq";
+ interrupts-extended = <&pdc 1 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+
+ #address-cells = <2>;
+ #size-cells = <0>;
+ };
+ };
+ };
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v8 0/7] spmi: pmic-arb: Add support for multiple buses
From: Abel Vesa @ 2024-04-02 12:07 UTC (permalink / raw)
To: Stephen Boyd, Matthias Brugger, Bjorn Andersson, Konrad Dybcio,
Dmitry Baryshkov, Neil Armstrong, AngeloGioacchino Del Regno,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Srini Kandagatla, Johan Hovold, linux-kernel, linux-arm-kernel,
linux-arm-msm, linux-mediatek, devicetree, Abel Vesa,
Krzysztof Kozlowski
This patchset prepares for and adds support for 2 buses, which is supported
in HW starting with version 7. Until now, none of the currently
supported platforms in upstream have used the second bus. The X1E80100
platform, on the other hand, needs the second bus for the USB2.0 to work
as there are 3 SMB2360 PMICs which provide eUSB2 repeaters and they are
all found on the second bus.
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
Changes in v8:
- Added Neil's R-b tag to the 3rd patch
- Fixed compile warnings already existent by adding another patch
- Fixed compile warning about get_core_resources, reported by Neil
- Dropped and moved the spurious core removal changes, as suggested by Neil
- Link to v7: https://lore.kernel.org/r/20240329-spmi-multi-master-support-v7-0-7b902824246c@linaro.org
Changes in v7:
- This time really collected Krzysztof's R-b tags
- Added Neil's R-b tag to the 4th patch
- Split the multi bus patch into two separate patches, one for adding
the bus object and one for the secondary bus, as per Neil's suggestion
- Fixed regression for single bus platforms triggered by casting to
pmic_arb instead of bus in pmic_arb_non_data_cmd_v1
- Fixed bus object allocation by using ctrl drvdata instead
- Prefixed the spmi node property in x1e80100 schema with '^'
- Fixed struct and function documentation warnings reported by Neil
Changes in v6 (resend):
- Collected Krzysztof's R-b tags
- Link to v6: https://lore.kernel.org/r/20240222-spmi-multi-master-support-v6-0-bc34ea9561da@linaro.org
Changes in v6:
- Changed the compatible to platform specific (X1E80100) along with the
schema. Fixed the spmi buses unit addresses and added the empty ranges
property. Added missing properties to the spmi buses and the
"unevaluatedProperties: false".
- Deprecated the "qcom,bus-id" in the legacy schema.
- Changed the driver to check for legacy compatible first
- Link to v5: https://lore.kernel.org/r/20240221-spmi-multi-master-support-v5-0-3255ca413a0b@linaro.org
Changes in v5:
- Dropped the RFC as there aren't any concerns about the approach anymore
- Dropped the unused dev and res variables from pmic_arb_get_obsrvr_chnls_v2
- Link to v4: https://lore.kernel.org/r/20240220-spmi-multi-master-support-v4-0-dc813c878ba8@linaro.org
Changes in v4:
- Fixed comment above pmic_arb_init_apid_v7 by dropping the extra "bus" word
- Swicthed to devm_platform_ioremap_resource_byname for obsrvr and chnls.
The core remains with platform_get_resource_byname as we need the core size.
- Dropped comment from probe related to the need of platform_get_resource_byname
as it not true anymore.
- Dropped the qcom,bus-id optional property.
- Link to v3: https://lore.kernel.org/r/20240214-spmi-multi-master-support-v3-0-0bae0ef04faf@linaro.org
Changes in v3:
- Split the change into 3 separate patches. First 2 patches are moving
apid init and core resources into version specific ops. Third one is
adding the support for 2 buses and dedicated compatible.
- Added separate bindings patch
- Link to v2: https://lore.kernel.org/r/20240213-spmi-multi-master-support-v2-1-b3b102326906@linaro.org
Changes in v2:
- Reworked it so that it registers a spmi controller for each bus
rather than relying on the generic framework to pass on the bus
(master) id.
- Link to v1: https://lore.kernel.org/r/20240207-spmi-multi-master-support-v1-0-ce57f301c7fd@linaro.org
---
Abel Vesa (7):
dt-bindings: spmi: Add X1E80100 SPMI PMIC ARB schema
dt-bindings: spmi: Deprecate qcom,bus-id
spmi: pmic-arb: Fix some compile warnings about members not being described
spmi: pmic-arb: Make the APID init a version operation
spmi: pmic-arb: Make core resources acquiring a version operation
spmi: pmic-arb: Register controller for bus instead of arbiter
spmi: pmic-arb: Add multi bus support
.../bindings/spmi/qcom,spmi-pmic-arb.yaml | 1 +
.../bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml | 136 +++
drivers/spmi/spmi-pmic-arb.c | 952 +++++++++++++--------
3 files changed, 723 insertions(+), 366 deletions(-)
---
base-commit: c0b832517f627ead3388c6f0c74e8ac10ad5774b
change-id: 20240207-spmi-multi-master-support-832a704b779b
Best regards,
--
Abel Vesa <abel.vesa@linaro.org>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v8 7/7] spmi: pmic-arb: Add multi bus support
From: Abel Vesa @ 2024-04-02 12:07 UTC (permalink / raw)
To: Stephen Boyd, Matthias Brugger, Bjorn Andersson, Konrad Dybcio,
Dmitry Baryshkov, Neil Armstrong, AngeloGioacchino Del Regno,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Srini Kandagatla, Johan Hovold, linux-kernel, linux-arm-kernel,
linux-arm-msm, linux-mediatek, devicetree, Abel Vesa
In-Reply-To: <20240402-spmi-multi-master-support-v8-0-ce6f2d14a058@linaro.org>
Starting with HW version 7, there are actually two separate buses
(with two separate sets of wires). So add support for the second bus.
The first platform that needs this support for the second bus is the
Qualcomm X1 Elite, so add the compatible for it as well.
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
drivers/spmi/spmi-pmic-arb.c | 138 +++++++++++++++++++++++++++++++++++++------
1 file changed, 120 insertions(+), 18 deletions(-)
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 3db622ed80de..52b9e275a7b2 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -95,6 +96,8 @@ enum pmic_arb_channel {
PMIC_ARB_CHANNEL_OBS,
};
+#define PMIC_ARB_MAX_BUSES 2
+
/* Maximum number of support PMIC peripherals */
#define PMIC_ARB_MAX_PERIPHS 512
#define PMIC_ARB_MAX_PERIPHS_V7 1024
@@ -148,6 +151,7 @@ struct spmi_pmic_arb;
* @min_apid: minimum APID (used for bounding IRQ search)
* @max_apid: maximum APID
* @irq: PMIC ARB interrupt.
+ * @id: unique ID of the bus
*/
struct spmi_pmic_arb_bus {
struct spmi_pmic_arb *pmic_arb;
@@ -165,6 +169,7 @@ struct spmi_pmic_arb_bus {
u16 min_apid;
u16 max_apid;
int irq;
+ u8 id;
};
/**
@@ -179,7 +184,8 @@ struct spmi_pmic_arb_bus {
* @ee: the current Execution Environment
* @ver_ops: version dependent operations.
* @max_periphs: Number of elements in apid_data[]
- * @bus: per arbiter bus instance
+ * @buses: per arbiter buses instances
+ * @buses_available: number of buses registered
*/
struct spmi_pmic_arb {
void __iomem *rd_base;
@@ -191,7 +197,8 @@ struct spmi_pmic_arb {
u8 ee;
const struct pmic_arb_ver_ops *ver_ops;
int max_periphs;
- struct spmi_pmic_arb_bus *bus;
+ struct spmi_pmic_arb_bus *buses[PMIC_ARB_MAX_BUSES];
+ int buses_available;
};
/**
@@ -220,7 +227,7 @@ struct spmi_pmic_arb {
struct pmic_arb_ver_ops {
const char *ver_str;
int (*get_core_resources)(struct platform_device *pdev, void __iomem *core);
- int (*init_apid)(struct spmi_pmic_arb_bus *bus);
+ int (*init_apid)(struct spmi_pmic_arb_bus *bus, int index);
int (*ppid_to_apid)(struct spmi_pmic_arb_bus *bus, u16 ppid);
/* spmi commands (read_cmd, write_cmd, cmd) functionality */
int (*offset)(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
@@ -309,8 +316,8 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
}
if (status & PMIC_ARB_STATUS_FAILURE) {
- dev_err(&ctrl->dev, "%s: %#x %#x: transaction failed (%#x)\n",
- __func__, sid, addr, status);
+ dev_err(&ctrl->dev, "%s: %#x %#x: transaction failed (%#x) reg: 0x%x\n",
+ __func__, sid, addr, status, offset);
WARN_ON(1);
return -EIO;
}
@@ -326,8 +333,8 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
udelay(1);
}
- dev_err(&ctrl->dev, "%s: %#x %#x: timeout, status %#x\n",
- __func__, sid, addr, status);
+ dev_err(&ctrl->dev, "%s: %#x %#x %#x: timeout, status %#x\n",
+ __func__, bus->id, sid, addr, status);
return -ETIMEDOUT;
}
@@ -1006,11 +1013,17 @@ static int pmic_arb_get_core_resources_v1(struct platform_device *pdev,
return 0;
}
-static int pmic_arb_init_apid_v1(struct spmi_pmic_arb_bus *bus)
+static int pmic_arb_init_apid_v1(struct spmi_pmic_arb_bus *bus, int index)
{
struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u32 *mapping_table;
+ if (index) {
+ dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n",
+ index);
+ return -EINVAL;
+ }
+
mapping_table = devm_kcalloc(&bus->spmic->dev, pmic_arb->max_periphs,
sizeof(*mapping_table), GFP_KERNEL);
if (!mapping_table)
@@ -1253,11 +1266,17 @@ static int pmic_arb_offset_v2(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
return 0x1000 * pmic_arb->ee + 0x8000 * apid;
}
-static int pmic_arb_init_apid_v5(struct spmi_pmic_arb_bus *bus)
+static int pmic_arb_init_apid_v5(struct spmi_pmic_arb_bus *bus, int index)
{
struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
int ret;
+ if (index) {
+ dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n",
+ index);
+ return -EINVAL;
+ }
+
bus->base_apid = 0;
bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
PMIC_ARB_FEATURES_PERIPH_MASK;
@@ -1329,6 +1348,50 @@ static int pmic_arb_get_core_resources_v7(struct platform_device *pdev,
return pmic_arb_get_obsrvr_chnls_v2(pdev);
}
+/*
+ * Only v7 supports 2 buses. Each bus will get a different apid count, read
+ * from different registers.
+ */
+static int pmic_arb_init_apid_v7(struct spmi_pmic_arb_bus *bus, int index)
+{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
+ int ret;
+
+ if (index == 0) {
+ bus->base_apid = 0;
+ bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
+ PMIC_ARB_FEATURES_PERIPH_MASK;
+ } else if (index == 1) {
+ bus->base_apid = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
+ PMIC_ARB_FEATURES_PERIPH_MASK;
+ bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES1) &
+ PMIC_ARB_FEATURES_PERIPH_MASK;
+ } else {
+ dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n",
+ bus->id);
+ return -EINVAL;
+ }
+
+ if (bus->base_apid + bus->apid_count > pmic_arb->max_periphs) {
+ dev_err(&bus->spmic->dev, "Unsupported APID count %d detected\n",
+ bus->base_apid + bus->apid_count);
+ return -EINVAL;
+ }
+
+ ret = pmic_arb_init_apid_min_max(bus);
+ if (ret)
+ return ret;
+
+ ret = pmic_arb_read_apid_map_v5(bus);
+ if (ret) {
+ dev_err(&bus->spmic->dev, "could not read APID->PPID mapping table, rc= %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
/*
* v7 offset per ee and per apid for observer channels and per apid for
* read/write channels.
@@ -1581,7 +1644,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v5 = {
static const struct pmic_arb_ver_ops pmic_arb_v7 = {
.ver_str = "v7",
.get_core_resources = pmic_arb_get_core_resources_v7,
- .init_apid = pmic_arb_init_apid_v5,
+ .init_apid = pmic_arb_init_apid_v7,
.ppid_to_apid = pmic_arb_ppid_to_apid_v5,
.non_data_cmd = pmic_arb_non_data_cmd_v2,
.offset = pmic_arb_offset_v7,
@@ -1605,6 +1668,7 @@ static int spmi_pmic_arb_bus_init(struct platform_device *pdev,
struct device_node *node,
struct spmi_pmic_arb *pmic_arb)
{
+ int bus_index = pmic_arb->buses_available;
struct spmi_pmic_arb_bus *bus;
struct device *dev = &pdev->dev;
struct spmi_controller *ctrl;
@@ -1623,7 +1687,7 @@ static int spmi_pmic_arb_bus_init(struct platform_device *pdev,
bus = spmi_controller_get_drvdata(ctrl);
- pmic_arb->bus = bus;
+ pmic_arb->buses[bus_index] = bus;
bus->ppid_to_apid = devm_kcalloc(dev, PMIC_ARB_MAX_PPID,
sizeof(*bus->ppid_to_apid),
@@ -1666,12 +1730,13 @@ static int spmi_pmic_arb_bus_init(struct platform_device *pdev,
bus->cnfg = cnfg;
bus->irq = irq;
bus->spmic = ctrl;
+ bus->id = bus_index;
- ret = pmic_arb->ver_ops->init_apid(bus);
+ ret = pmic_arb->ver_ops->init_apid(bus, bus_index);
if (ret)
return ret;
- dev_dbg(&pdev->dev, "adding irq domain\n");
+ dev_dbg(&pdev->dev, "adding irq domain for bus %d\n", bus_index);
bus->domain = irq_domain_add_tree(dev->of_node,
&pmic_arb_irq_domain_ops, bus);
@@ -1684,14 +1749,53 @@ static int spmi_pmic_arb_bus_init(struct platform_device *pdev,
pmic_arb_chained_irq, bus);
ctrl->dev.of_node = node;
+ dev_set_name(&ctrl->dev, "spmi-%d", bus_index);
ret = devm_spmi_controller_add(dev, ctrl);
if (ret)
return ret;
+ pmic_arb->buses_available++;
+
return 0;
}
+static int spmi_pmic_arb_register_buses(struct spmi_pmic_arb *pmic_arb,
+ struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct device_node *child;
+ int ret;
+
+ /* legacy mode doesn't provide child node for the bus */
+ if (of_device_is_compatible(node, "qcom,spmi-pmic-arb"))
+ return spmi_pmic_arb_bus_init(pdev, node, pmic_arb);
+
+ for_each_available_child_of_node(node, child) {
+ if (of_node_name_eq(child, "spmi")) {
+ ret = spmi_pmic_arb_bus_init(pdev, child, pmic_arb);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static void spmi_pmic_arb_deregister_buses(struct spmi_pmic_arb *pmic_arb)
+{
+ int i;
+
+ for (i = 0; i < PMIC_ARB_MAX_BUSES; i++) {
+ struct spmi_pmic_arb_bus *bus = pmic_arb->buses[i];
+
+ irq_set_chained_handler_and_data(bus->irq,
+ NULL, NULL);
+ irq_domain_remove(bus->domain);
+ }
+}
+
static int spmi_pmic_arb_probe(struct platform_device *pdev)
{
struct spmi_pmic_arb *pmic_arb;
@@ -1762,21 +1866,19 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
pmic_arb->ee = ee;
- return spmi_pmic_arb_bus_init(pdev, dev->of_node, pmic_arb);
+ return spmi_pmic_arb_register_buses(pmic_arb, pdev);
}
static void spmi_pmic_arb_remove(struct platform_device *pdev)
{
struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev);
- struct spmi_pmic_arb_bus *bus = pmic_arb->bus;
- irq_set_chained_handler_and_data(bus->irq,
- NULL, NULL);
- irq_domain_remove(bus->domain);
+ spmi_pmic_arb_deregister_buses(pmic_arb);
}
static const struct of_device_id spmi_pmic_arb_match_table[] = {
{ .compatible = "qcom,spmi-pmic-arb", },
+ { .compatible = "qcom,x1e80100-spmi-pmic-arb", },
{},
};
MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table);
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v8 6/7] spmi: pmic-arb: Register controller for bus instead of arbiter
From: Abel Vesa @ 2024-04-02 12:07 UTC (permalink / raw)
To: Stephen Boyd, Matthias Brugger, Bjorn Andersson, Konrad Dybcio,
Dmitry Baryshkov, Neil Armstrong, AngeloGioacchino Del Regno,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Srini Kandagatla, Johan Hovold, linux-kernel, linux-arm-kernel,
linux-arm-msm, linux-mediatek, devicetree, Abel Vesa
In-Reply-To: <20240402-spmi-multi-master-support-v8-0-ce6f2d14a058@linaro.org>
Introduce the bus object in order to decouple the resources
that are bus specific from the arbiter. This way the SPMI controller
is registered with the generic framework at a bus level rather than
arbiter. This is needed in order to prepare for multi bus support.
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
drivers/spmi/spmi-pmic-arb.c | 647 ++++++++++++++++++++++++-------------------
1 file changed, 369 insertions(+), 278 deletions(-)
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index ff777b4a6f33..3db622ed80de 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spmi.h>
@@ -125,61 +126,72 @@ struct apid_data {
u8 irq_ee;
};
+struct spmi_pmic_arb;
+
/**
- * struct spmi_pmic_arb - SPMI PMIC Arbiter object
+ * struct spmi_pmic_arb_bus - SPMI PMIC Arbiter Bus object
*
- * @rd_base: on v1 "core", on v2 "observer" register base off DT.
- * @wr_base: on v1 "core", on v2 "chnls" register base off DT.
+ * @pmic_arb: the SPMI PMIC Arbiter the bus belongs to.
+ * @domain: irq domain object for PMIC IRQ domain
* @intr: address of the SPMI interrupt control registers.
* @cnfg: address of the PMIC Arbiter configuration registers.
- * @core: core register base for v2 and above only (see above)
- * @core_size: core register base size
- * @lock: lock to synchronize accesses.
- * @channel: execution environment channel to use for accesses.
- * @irq: PMIC ARB interrupt.
- * @ee: the current Execution Environment
- * @bus_instance: on v7: 0 = primary SPMI bus, 1 = secondary SPMI bus
- * @min_apid: minimum APID (used for bounding IRQ search)
- * @max_apid: maximum APID
+ * @spmic: spmi controller registered for this bus
* @base_apid: on v7: minimum APID associated with the particular SPMI
* bus instance
* @apid_count: on v5 and v7: number of APIDs associated with the
* particular SPMI bus instance
* @mapping_table: in-memory copy of PPID -> APID mapping table.
* @mapping_table_valid:bitmap containing valid-only periphs
- * @domain: irq domain object for PMIC IRQ domain
- * @spmic: SPMI controller object
- * @ver_ops: version dependent operations.
* @ppid_to_apid: in-memory copy of PPID -> APID mapping table.
* @last_apid: Highest value APID in use
* @apid_data: Table of data for all APIDs
+ * @min_apid: minimum APID (used for bounding IRQ search)
+ * @max_apid: maximum APID
+ * @irq: PMIC ARB interrupt.
+ */
+struct spmi_pmic_arb_bus {
+ struct spmi_pmic_arb *pmic_arb;
+ struct irq_domain *domain;
+ void __iomem *intr;
+ void __iomem *cnfg;
+ struct spmi_controller *spmic;
+ u16 base_apid;
+ int apid_count;
+ u32 *mapping_table;
+ DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS);
+ u16 *ppid_to_apid;
+ u16 last_apid;
+ struct apid_data *apid_data;
+ u16 min_apid;
+ u16 max_apid;
+ int irq;
+};
+
+/**
+ * struct spmi_pmic_arb - SPMI PMIC Arbiter object
+ *
+ * @rd_base: on v1 "core", on v2 "observer" register base off DT.
+ * @wr_base: on v1 "core", on v2 "chnls" register base off DT.
+ * @core: core register base for v2 and above only (see above)
+ * @core_size: core register base size
+ * @lock: lock to synchronize accesses.
+ * @channel: execution environment channel to use for accesses.
+ * @ee: the current Execution Environment
+ * @ver_ops: version dependent operations.
* @max_periphs: Number of elements in apid_data[]
+ * @bus: per arbiter bus instance
*/
struct spmi_pmic_arb {
void __iomem *rd_base;
void __iomem *wr_base;
- void __iomem *intr;
- void __iomem *cnfg;
void __iomem *core;
resource_size_t core_size;
raw_spinlock_t lock;
u8 channel;
- int irq;
u8 ee;
- u32 bus_instance;
- u16 min_apid;
- u16 max_apid;
- u16 base_apid;
- int apid_count;
- u32 *mapping_table;
- DECLARE_BITMAP(mapping_table_valid, PMIC_ARB_MAX_PERIPHS);
- struct irq_domain *domain;
- struct spmi_controller *spmic;
const struct pmic_arb_ver_ops *ver_ops;
- u16 *ppid_to_apid;
- u16 last_apid;
- struct apid_data *apid_data;
int max_periphs;
+ struct spmi_pmic_arb_bus *bus;
};
/**
@@ -208,21 +220,21 @@ struct spmi_pmic_arb {
struct pmic_arb_ver_ops {
const char *ver_str;
int (*get_core_resources)(struct platform_device *pdev, void __iomem *core);
- int (*init_apid)(struct spmi_pmic_arb *pmic_arb);
- int (*ppid_to_apid)(struct spmi_pmic_arb *pmic_arb, u16 ppid);
+ int (*init_apid)(struct spmi_pmic_arb_bus *bus);
+ int (*ppid_to_apid)(struct spmi_pmic_arb_bus *bus, u16 ppid);
/* spmi commands (read_cmd, write_cmd, cmd) functionality */
- int (*offset)(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
- enum pmic_arb_channel ch_type);
+ int (*offset)(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
+ enum pmic_arb_channel ch_type);
u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc);
int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid);
/* Interrupts controller functionality (offset of PIC registers) */
- void __iomem *(*owner_acc_status)(struct spmi_pmic_arb *pmic_arb, u8 m,
+ void __iomem *(*owner_acc_status)(struct spmi_pmic_arb_bus *bus, u8 m,
u16 n);
- void __iomem *(*acc_enable)(struct spmi_pmic_arb *pmic_arb, u16 n);
- void __iomem *(*irq_status)(struct spmi_pmic_arb *pmic_arb, u16 n);
- void __iomem *(*irq_clear)(struct spmi_pmic_arb *pmic_arb, u16 n);
+ void __iomem *(*acc_enable)(struct spmi_pmic_arb_bus *bus, u16 n);
+ void __iomem *(*irq_status)(struct spmi_pmic_arb_bus *bus, u16 n);
+ void __iomem *(*irq_clear)(struct spmi_pmic_arb_bus *bus, u16 n);
u32 (*apid_map_offset)(u16 n);
- void __iomem *(*apid_owner)(struct spmi_pmic_arb *pmic_arb, u16 n);
+ void __iomem *(*apid_owner)(struct spmi_pmic_arb_bus *bus, u16 n);
};
static inline void pmic_arb_base_write(struct spmi_pmic_arb *pmic_arb,
@@ -272,13 +284,14 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
void __iomem *base, u8 sid, u16 addr,
enum pmic_arb_channel ch_type)
{
- struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u32 status = 0;
u32 timeout = PMIC_ARB_TIMEOUT_US;
u32 offset;
int rc;
- rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr, ch_type);
+ rc = pmic_arb->ver_ops->offset(bus, sid, addr, ch_type);
if (rc < 0)
return rc;
@@ -321,13 +334,14 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
static int
pmic_arb_non_data_cmd_v1(struct spmi_controller *ctrl, u8 opc, u8 sid)
{
- struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
unsigned long flags;
u32 cmd;
int rc;
u32 offset;
- rc = pmic_arb->ver_ops->offset(pmic_arb, sid, 0, PMIC_ARB_CHANNEL_RW);
+ rc = pmic_arb->ver_ops->offset(bus, sid, 0, PMIC_ARB_CHANNEL_RW);
if (rc < 0)
return rc;
@@ -363,20 +377,21 @@ static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
return pmic_arb->ver_ops->non_data_cmd(ctrl, opc, sid);
}
-static int pmic_arb_fmt_read_cmd(struct spmi_pmic_arb *pmic_arb, u8 opc, u8 sid,
+static int pmic_arb_fmt_read_cmd(struct spmi_pmic_arb_bus *bus, u8 opc, u8 sid,
u16 addr, size_t len, u32 *cmd, u32 *offset)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u8 bc = len - 1;
int rc;
- rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr,
+ rc = pmic_arb->ver_ops->offset(bus, sid, addr,
PMIC_ARB_CHANNEL_OBS);
if (rc < 0)
return rc;
*offset = rc;
if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
- dev_err(&pmic_arb->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
+ dev_err(&bus->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
PMIC_ARB_MAX_TRANS_BYTES, len);
return -EINVAL;
}
@@ -400,7 +415,8 @@ static int pmic_arb_read_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd,
u32 offset, u8 sid, u16 addr, u8 *buf,
size_t len)
{
- struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u8 bc = len - 1;
int rc;
@@ -422,12 +438,13 @@ static int pmic_arb_read_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd,
static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
u16 addr, u8 *buf, size_t len)
{
- struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
unsigned long flags;
u32 cmd, offset;
int rc;
- rc = pmic_arb_fmt_read_cmd(pmic_arb, opc, sid, addr, len, &cmd,
+ rc = pmic_arb_fmt_read_cmd(bus, opc, sid, addr, len, &cmd,
&offset);
if (rc)
return rc;
@@ -439,21 +456,22 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
return rc;
}
-static int pmic_arb_fmt_write_cmd(struct spmi_pmic_arb *pmic_arb, u8 opc,
+static int pmic_arb_fmt_write_cmd(struct spmi_pmic_arb_bus *bus, u8 opc,
u8 sid, u16 addr, size_t len, u32 *cmd,
u32 *offset)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u8 bc = len - 1;
int rc;
- rc = pmic_arb->ver_ops->offset(pmic_arb, sid, addr,
+ rc = pmic_arb->ver_ops->offset(bus, sid, addr,
PMIC_ARB_CHANNEL_RW);
if (rc < 0)
return rc;
*offset = rc;
if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
- dev_err(&pmic_arb->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
+ dev_err(&bus->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
PMIC_ARB_MAX_TRANS_BYTES, len);
return -EINVAL;
}
@@ -479,7 +497,8 @@ static int pmic_arb_write_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd,
u32 offset, u8 sid, u16 addr,
const u8 *buf, size_t len)
{
- struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u8 bc = len - 1;
/* Write data to FIFOs */
@@ -498,12 +517,13 @@ static int pmic_arb_write_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd,
static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
u16 addr, const u8 *buf, size_t len)
{
- struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
unsigned long flags;
u32 cmd, offset;
int rc;
- rc = pmic_arb_fmt_write_cmd(pmic_arb, opc, sid, addr, len, &cmd,
+ rc = pmic_arb_fmt_write_cmd(bus, opc, sid, addr, len, &cmd,
&offset);
if (rc)
return rc;
@@ -519,18 +539,19 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
static int pmic_arb_masked_write(struct spmi_controller *ctrl, u8 sid, u16 addr,
const u8 *buf, const u8 *mask, size_t len)
{
- struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u32 read_cmd, read_offset, write_cmd, write_offset;
u8 temp[PMIC_ARB_MAX_TRANS_BYTES];
unsigned long flags;
int rc, i;
- rc = pmic_arb_fmt_read_cmd(pmic_arb, SPMI_CMD_EXT_READL, sid, addr, len,
+ rc = pmic_arb_fmt_read_cmd(bus, SPMI_CMD_EXT_READL, sid, addr, len,
&read_cmd, &read_offset);
if (rc)
return rc;
- rc = pmic_arb_fmt_write_cmd(pmic_arb, SPMI_CMD_EXT_WRITEL, sid, addr,
+ rc = pmic_arb_fmt_write_cmd(bus, SPMI_CMD_EXT_WRITEL, sid, addr,
len, &write_cmd, &write_offset);
if (rc)
return rc;
@@ -573,25 +594,25 @@ struct spmi_pmic_arb_qpnpint_type {
static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
size_t len)
{
- struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
+ struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
u8 sid = hwirq_to_sid(d->hwirq);
u8 per = hwirq_to_per(d->hwirq);
- if (pmic_arb_write_cmd(pmic_arb->spmic, SPMI_CMD_EXT_WRITEL, sid,
+ if (pmic_arb_write_cmd(bus->spmic, SPMI_CMD_EXT_WRITEL, sid,
(per << 8) + reg, buf, len))
- dev_err_ratelimited(&pmic_arb->spmic->dev, "failed irqchip transaction on %x\n",
+ dev_err_ratelimited(&bus->spmic->dev, "failed irqchip transaction on %x\n",
d->irq);
}
static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
{
- struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
+ struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
u8 sid = hwirq_to_sid(d->hwirq);
u8 per = hwirq_to_per(d->hwirq);
- if (pmic_arb_read_cmd(pmic_arb->spmic, SPMI_CMD_EXT_READL, sid,
+ if (pmic_arb_read_cmd(bus->spmic, SPMI_CMD_EXT_READL, sid,
(per << 8) + reg, buf, len))
- dev_err_ratelimited(&pmic_arb->spmic->dev, "failed irqchip transaction on %x\n",
+ dev_err_ratelimited(&bus->spmic->dev, "failed irqchip transaction on %x\n",
d->irq);
}
@@ -599,47 +620,49 @@ static int qpnpint_spmi_masked_write(struct irq_data *d, u8 reg,
const void *buf, const void *mask,
size_t len)
{
- struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
+ struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
u8 sid = hwirq_to_sid(d->hwirq);
u8 per = hwirq_to_per(d->hwirq);
int rc;
- rc = pmic_arb_masked_write(pmic_arb->spmic, sid, (per << 8) + reg, buf,
+ rc = pmic_arb_masked_write(bus->spmic, sid, (per << 8) + reg, buf,
mask, len);
if (rc)
- dev_err_ratelimited(&pmic_arb->spmic->dev, "failed irqchip transaction on %x rc=%d\n",
+ dev_err_ratelimited(&bus->spmic->dev, "failed irqchip transaction on %x rc=%d\n",
d->irq, rc);
return rc;
}
-static void cleanup_irq(struct spmi_pmic_arb *pmic_arb, u16 apid, int id)
+static void cleanup_irq(struct spmi_pmic_arb_bus *bus, u16 apid, int id)
{
- u16 ppid = pmic_arb->apid_data[apid].ppid;
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
+ u16 ppid = bus->apid_data[apid].ppid;
u8 sid = ppid >> 8;
u8 per = ppid & 0xFF;
u8 irq_mask = BIT(id);
- dev_err_ratelimited(&pmic_arb->spmic->dev, "%s apid=%d sid=0x%x per=0x%x irq=%d\n",
- __func__, apid, sid, per, id);
- writel_relaxed(irq_mask, pmic_arb->ver_ops->irq_clear(pmic_arb, apid));
+ dev_err_ratelimited(&bus->spmic->dev, "%s apid=%d sid=0x%x per=0x%x irq=%d\n",
+ __func__, apid, sid, per, id);
+ writel_relaxed(irq_mask, pmic_arb->ver_ops->irq_clear(bus, apid));
}
-static int periph_interrupt(struct spmi_pmic_arb *pmic_arb, u16 apid)
+static int periph_interrupt(struct spmi_pmic_arb_bus *bus, u16 apid)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
unsigned int irq;
u32 status, id;
int handled = 0;
- u8 sid = (pmic_arb->apid_data[apid].ppid >> 8) & 0xF;
- u8 per = pmic_arb->apid_data[apid].ppid & 0xFF;
+ u8 sid = (bus->apid_data[apid].ppid >> 8) & 0xF;
+ u8 per = bus->apid_data[apid].ppid & 0xFF;
- status = readl_relaxed(pmic_arb->ver_ops->irq_status(pmic_arb, apid));
+ status = readl_relaxed(pmic_arb->ver_ops->irq_status(bus, apid));
while (status) {
id = ffs(status) - 1;
status &= ~BIT(id);
- irq = irq_find_mapping(pmic_arb->domain,
- spec_to_hwirq(sid, per, id, apid));
+ irq = irq_find_mapping(bus->domain,
+ spec_to_hwirq(sid, per, id, apid));
if (irq == 0) {
- cleanup_irq(pmic_arb, apid, id);
+ cleanup_irq(bus, apid, id);
continue;
}
generic_handle_irq(irq);
@@ -651,16 +674,17 @@ static int periph_interrupt(struct spmi_pmic_arb *pmic_arb, u16 apid)
static void pmic_arb_chained_irq(struct irq_desc *desc)
{
- struct spmi_pmic_arb *pmic_arb = irq_desc_get_handler_data(desc);
+ struct spmi_pmic_arb_bus *bus = irq_desc_get_handler_data(desc);
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
const struct pmic_arb_ver_ops *ver_ops = pmic_arb->ver_ops;
struct irq_chip *chip = irq_desc_get_chip(desc);
- int first = pmic_arb->min_apid;
- int last = pmic_arb->max_apid;
+ int first = bus->min_apid;
+ int last = bus->max_apid;
/*
* acc_offset will be non-zero for the secondary SPMI bus instance on
* v7 controllers.
*/
- int acc_offset = pmic_arb->base_apid >> 5;
+ int acc_offset = bus->base_apid >> 5;
u8 ee = pmic_arb->ee;
u32 status, enable, handled = 0;
int i, id, apid;
@@ -671,7 +695,7 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
chained_irq_enter(chip, desc);
for (i = first >> 5; i <= last >> 5; ++i) {
- status = readl_relaxed(ver_ops->owner_acc_status(pmic_arb, ee, i - acc_offset));
+ status = readl_relaxed(ver_ops->owner_acc_status(bus, ee, i - acc_offset));
if (status)
acc_valid = true;
@@ -685,9 +709,9 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
continue;
}
enable = readl_relaxed(
- ver_ops->acc_enable(pmic_arb, apid));
+ ver_ops->acc_enable(bus, apid));
if (enable & SPMI_PIC_ACC_ENABLE_BIT)
- if (periph_interrupt(pmic_arb, apid) != 0)
+ if (periph_interrupt(bus, apid) != 0)
handled++;
}
}
@@ -696,19 +720,19 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
if (!acc_valid) {
for (i = first; i <= last; i++) {
/* skip if APPS is not irq owner */
- if (pmic_arb->apid_data[i].irq_ee != pmic_arb->ee)
+ if (bus->apid_data[i].irq_ee != pmic_arb->ee)
continue;
irq_status = readl_relaxed(
- ver_ops->irq_status(pmic_arb, i));
+ ver_ops->irq_status(bus, i));
if (irq_status) {
enable = readl_relaxed(
- ver_ops->acc_enable(pmic_arb, i));
+ ver_ops->acc_enable(bus, i));
if (enable & SPMI_PIC_ACC_ENABLE_BIT) {
- dev_dbg(&pmic_arb->spmic->dev,
+ dev_dbg(&bus->spmic->dev,
"Dispatching IRQ for apid=%d status=%x\n",
i, irq_status);
- if (periph_interrupt(pmic_arb, i) != 0)
+ if (periph_interrupt(bus, i) != 0)
handled++;
}
}
@@ -723,12 +747,13 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
static void qpnpint_irq_ack(struct irq_data *d)
{
- struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
+ struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u8 irq = hwirq_to_irq(d->hwirq);
u16 apid = hwirq_to_apid(d->hwirq);
u8 data;
- writel_relaxed(BIT(irq), pmic_arb->ver_ops->irq_clear(pmic_arb, apid));
+ writel_relaxed(BIT(irq), pmic_arb->ver_ops->irq_clear(bus, apid));
data = BIT(irq);
qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
@@ -744,14 +769,15 @@ static void qpnpint_irq_mask(struct irq_data *d)
static void qpnpint_irq_unmask(struct irq_data *d)
{
- struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
+ struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
const struct pmic_arb_ver_ops *ver_ops = pmic_arb->ver_ops;
u8 irq = hwirq_to_irq(d->hwirq);
u16 apid = hwirq_to_apid(d->hwirq);
u8 buf[2];
writel_relaxed(SPMI_PIC_ACC_ENABLE_BIT,
- ver_ops->acc_enable(pmic_arb, apid));
+ ver_ops->acc_enable(bus, apid));
qpnpint_spmi_read(d, QPNPINT_REG_EN_SET, &buf[0], 1);
if (!(buf[0] & BIT(irq))) {
@@ -808,9 +834,9 @@ static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
static int qpnpint_irq_set_wake(struct irq_data *d, unsigned int on)
{
- struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
+ struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
- return irq_set_irq_wake(pmic_arb->irq, on);
+ return irq_set_irq_wake(bus->irq, on);
}
static int qpnpint_get_irqchip_state(struct irq_data *d,
@@ -832,17 +858,18 @@ static int qpnpint_get_irqchip_state(struct irq_data *d,
static int qpnpint_irq_domain_activate(struct irq_domain *domain,
struct irq_data *d, bool reserve)
{
- struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
+ struct spmi_pmic_arb_bus *bus = irq_data_get_irq_chip_data(d);
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u16 periph = hwirq_to_per(d->hwirq);
u16 apid = hwirq_to_apid(d->hwirq);
u16 sid = hwirq_to_sid(d->hwirq);
u16 irq = hwirq_to_irq(d->hwirq);
u8 buf;
- if (pmic_arb->apid_data[apid].irq_ee != pmic_arb->ee) {
- dev_err(&pmic_arb->spmic->dev, "failed to xlate sid = %#x, periph = %#x, irq = %u: ee=%u but owner=%u\n",
+ if (bus->apid_data[apid].irq_ee != pmic_arb->ee) {
+ dev_err(&bus->spmic->dev, "failed to xlate sid = %#x, periph = %#x, irq = %u: ee=%u but owner=%u\n",
sid, periph, irq, pmic_arb->ee,
- pmic_arb->apid_data[apid].irq_ee);
+ bus->apid_data[apid].irq_ee);
return -ENODEV;
}
@@ -869,15 +896,16 @@ static int qpnpint_irq_domain_translate(struct irq_domain *d,
unsigned long *out_hwirq,
unsigned int *out_type)
{
- struct spmi_pmic_arb *pmic_arb = d->host_data;
+ struct spmi_pmic_arb_bus *bus = d->host_data;
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u32 *intspec = fwspec->param;
u16 apid, ppid;
int rc;
- dev_dbg(&pmic_arb->spmic->dev, "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
+ dev_dbg(&bus->spmic->dev, "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
intspec[0], intspec[1], intspec[2]);
- if (irq_domain_get_of_node(d) != pmic_arb->spmic->dev.of_node)
+ if (irq_domain_get_of_node(d) != bus->spmic->dev.of_node)
return -EINVAL;
if (fwspec->param_count != 4)
return -EINVAL;
@@ -885,37 +913,37 @@ static int qpnpint_irq_domain_translate(struct irq_domain *d,
return -EINVAL;
ppid = intspec[0] << 8 | intspec[1];
- rc = pmic_arb->ver_ops->ppid_to_apid(pmic_arb, ppid);
+ rc = pmic_arb->ver_ops->ppid_to_apid(bus, ppid);
if (rc < 0) {
- dev_err(&pmic_arb->spmic->dev, "failed to xlate sid = %#x, periph = %#x, irq = %u rc = %d\n",
- intspec[0], intspec[1], intspec[2], rc);
+ dev_err(&bus->spmic->dev, "failed to xlate sid = %#x, periph = %#x, irq = %u rc = %d\n",
+ intspec[0], intspec[1], intspec[2], rc);
return rc;
}
apid = rc;
/* Keep track of {max,min}_apid for bounding search during interrupt */
- if (apid > pmic_arb->max_apid)
- pmic_arb->max_apid = apid;
- if (apid < pmic_arb->min_apid)
- pmic_arb->min_apid = apid;
+ if (apid > bus->max_apid)
+ bus->max_apid = apid;
+ if (apid < bus->min_apid)
+ bus->min_apid = apid;
*out_hwirq = spec_to_hwirq(intspec[0], intspec[1], intspec[2], apid);
*out_type = intspec[3] & IRQ_TYPE_SENSE_MASK;
- dev_dbg(&pmic_arb->spmic->dev, "out_hwirq = %lu\n", *out_hwirq);
+ dev_dbg(&bus->spmic->dev, "out_hwirq = %lu\n", *out_hwirq);
return 0;
}
static struct lock_class_key qpnpint_irq_lock_class, qpnpint_irq_request_class;
-static void qpnpint_irq_domain_map(struct spmi_pmic_arb *pmic_arb,
+static void qpnpint_irq_domain_map(struct spmi_pmic_arb_bus *bus,
struct irq_domain *domain, unsigned int virq,
irq_hw_number_t hwirq, unsigned int type)
{
irq_flow_handler_t handler;
- dev_dbg(&pmic_arb->spmic->dev, "virq = %u, hwirq = %lu, type = %u\n",
+ dev_dbg(&bus->spmic->dev, "virq = %u, hwirq = %lu, type = %u\n",
virq, hwirq, type);
if (type & IRQ_TYPE_EDGE_BOTH)
@@ -926,7 +954,7 @@ static void qpnpint_irq_domain_map(struct spmi_pmic_arb *pmic_arb,
irq_set_lockdep_class(virq, &qpnpint_irq_lock_class,
&qpnpint_irq_request_class);
- irq_domain_set_info(domain, virq, hwirq, &pmic_arb_irqchip, pmic_arb,
+ irq_domain_set_info(domain, virq, hwirq, &pmic_arb_irqchip, bus,
handler, NULL, NULL);
}
@@ -934,7 +962,7 @@ static int qpnpint_irq_domain_alloc(struct irq_domain *domain,
unsigned int virq, unsigned int nr_irqs,
void *data)
{
- struct spmi_pmic_arb *pmic_arb = domain->host_data;
+ struct spmi_pmic_arb_bus *bus = domain->host_data;
struct irq_fwspec *fwspec = data;
irq_hw_number_t hwirq;
unsigned int type;
@@ -945,20 +973,22 @@ static int qpnpint_irq_domain_alloc(struct irq_domain *domain,
return ret;
for (i = 0; i < nr_irqs; i++)
- qpnpint_irq_domain_map(pmic_arb, domain, virq + i, hwirq + i,
+ qpnpint_irq_domain_map(bus, domain, virq + i, hwirq + i,
type);
return 0;
}
-static int pmic_arb_init_apid_min_max(struct spmi_pmic_arb *pmic_arb)
+static int pmic_arb_init_apid_min_max(struct spmi_pmic_arb_bus *bus)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
+
/*
* Initialize max_apid/min_apid to the opposite bounds, during
* the irq domain translation, we are sure to update these
*/
- pmic_arb->max_apid = 0;
- pmic_arb->min_apid = pmic_arb->max_periphs - 1;
+ bus->max_apid = 0;
+ bus->min_apid = pmic_arb->max_periphs - 1;
return 0;
}
@@ -976,37 +1006,38 @@ static int pmic_arb_get_core_resources_v1(struct platform_device *pdev,
return 0;
}
-static int pmic_arb_init_apid_v1(struct spmi_pmic_arb *pmic_arb)
+static int pmic_arb_init_apid_v1(struct spmi_pmic_arb_bus *bus)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u32 *mapping_table;
- mapping_table = devm_kcalloc(&pmic_arb->spmic->dev, pmic_arb->max_periphs,
+ mapping_table = devm_kcalloc(&bus->spmic->dev, pmic_arb->max_periphs,
sizeof(*mapping_table), GFP_KERNEL);
if (!mapping_table)
return -ENOMEM;
- pmic_arb->mapping_table = mapping_table;
+ bus->mapping_table = mapping_table;
- return pmic_arb_init_apid_min_max(pmic_arb);
+ return pmic_arb_init_apid_min_max(bus);
}
-static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pmic_arb, u16 ppid)
+static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb_bus *bus, u16 ppid)
{
- u32 *mapping_table = pmic_arb->mapping_table;
+ u32 *mapping_table = bus->mapping_table;
int index = 0, i;
u16 apid_valid;
u16 apid;
u32 data;
- apid_valid = pmic_arb->ppid_to_apid[ppid];
+ apid_valid = bus->ppid_to_apid[ppid];
if (apid_valid & PMIC_ARB_APID_VALID) {
apid = apid_valid & ~PMIC_ARB_APID_VALID;
return apid;
}
for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
- if (!test_and_set_bit(index, pmic_arb->mapping_table_valid))
- mapping_table[index] = readl_relaxed(pmic_arb->cnfg +
+ if (!test_and_set_bit(index, bus->mapping_table_valid))
+ mapping_table[index] = readl_relaxed(bus->cnfg +
SPMI_MAPPING_TABLE_REG(index));
data = mapping_table[index];
@@ -1016,9 +1047,9 @@ static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pmic_arb, u16 ppid)
index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
} else {
apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
- pmic_arb->ppid_to_apid[ppid]
+ bus->ppid_to_apid[ppid]
= apid | PMIC_ARB_APID_VALID;
- pmic_arb->apid_data[apid].ppid = ppid;
+ bus->apid_data[apid].ppid = ppid;
return apid;
}
} else {
@@ -1026,9 +1057,9 @@ static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pmic_arb, u16 ppid)
index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
} else {
apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
- pmic_arb->ppid_to_apid[ppid]
+ bus->ppid_to_apid[ppid]
= apid | PMIC_ARB_APID_VALID;
- pmic_arb->apid_data[apid].ppid = ppid;
+ bus->apid_data[apid].ppid = ppid;
return apid;
}
}
@@ -1038,24 +1069,26 @@ static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pmic_arb, u16 ppid)
}
/* v1 offset per ee */
-static int pmic_arb_offset_v1(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
- enum pmic_arb_channel ch_type)
+static int pmic_arb_offset_v1(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
+ enum pmic_arb_channel ch_type)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
return 0x800 + 0x80 * pmic_arb->channel;
}
-static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pmic_arb, u16 ppid)
+static u16 pmic_arb_find_apid(struct spmi_pmic_arb_bus *bus, u16 ppid)
{
- struct apid_data *apidd = &pmic_arb->apid_data[pmic_arb->last_apid];
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
+ struct apid_data *apidd = &bus->apid_data[bus->last_apid];
u32 regval, offset;
u16 id, apid;
- for (apid = pmic_arb->last_apid; ; apid++, apidd++) {
+ for (apid = bus->last_apid; ; apid++, apidd++) {
offset = pmic_arb->ver_ops->apid_map_offset(apid);
if (offset >= pmic_arb->core_size)
break;
- regval = readl_relaxed(pmic_arb->ver_ops->apid_owner(pmic_arb,
+ regval = readl_relaxed(pmic_arb->ver_ops->apid_owner(bus,
apid));
apidd->irq_ee = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
apidd->write_ee = apidd->irq_ee;
@@ -1065,14 +1098,14 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pmic_arb, u16 ppid)
continue;
id = (regval >> 8) & PMIC_ARB_PPID_MASK;
- pmic_arb->ppid_to_apid[id] = apid | PMIC_ARB_APID_VALID;
+ bus->ppid_to_apid[id] = apid | PMIC_ARB_APID_VALID;
apidd->ppid = id;
if (id == ppid) {
apid |= PMIC_ARB_APID_VALID;
break;
}
}
- pmic_arb->last_apid = apid & ~PMIC_ARB_APID_VALID;
+ bus->last_apid = apid & ~PMIC_ARB_APID_VALID;
return apid;
}
@@ -1104,21 +1137,22 @@ static int pmic_arb_get_core_resources_v2(struct platform_device *pdev,
return pmic_arb_get_obsrvr_chnls_v2(pdev);
}
-static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pmic_arb, u16 ppid)
+static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb_bus *bus, u16 ppid)
{
u16 apid_valid;
- apid_valid = pmic_arb->ppid_to_apid[ppid];
+ apid_valid = bus->ppid_to_apid[ppid];
if (!(apid_valid & PMIC_ARB_APID_VALID))
- apid_valid = pmic_arb_find_apid(pmic_arb, ppid);
+ apid_valid = pmic_arb_find_apid(bus, ppid);
if (!(apid_valid & PMIC_ARB_APID_VALID))
return -ENODEV;
return apid_valid & ~PMIC_ARB_APID_VALID;
}
-static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb)
+static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb_bus *bus)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
struct apid_data *apidd;
struct apid_data *prev_apidd;
u16 i, apid, ppid, apid_max;
@@ -1140,9 +1174,9 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb)
* where N = number of APIDs supported by the primary bus and
* M = number of APIDs supported by the secondary bus
*/
- apidd = &pmic_arb->apid_data[pmic_arb->base_apid];
- apid_max = pmic_arb->base_apid + pmic_arb->apid_count;
- for (i = pmic_arb->base_apid; i < apid_max; i++, apidd++) {
+ apidd = &bus->apid_data[bus->base_apid];
+ apid_max = bus->base_apid + bus->apid_count;
+ for (i = bus->base_apid; i < apid_max; i++, apidd++) {
offset = pmic_arb->ver_ops->apid_map_offset(i);
if (offset >= pmic_arb->core_size)
break;
@@ -1153,19 +1187,18 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb)
ppid = (regval >> 8) & PMIC_ARB_PPID_MASK;
is_irq_ee = PMIC_ARB_CHAN_IS_IRQ_OWNER(regval);
- regval = readl_relaxed(pmic_arb->ver_ops->apid_owner(pmic_arb,
- i));
+ regval = readl_relaxed(pmic_arb->ver_ops->apid_owner(bus, i));
apidd->write_ee = SPMI_OWNERSHIP_PERIPH2OWNER(regval);
apidd->irq_ee = is_irq_ee ? apidd->write_ee : INVALID_EE;
- valid = pmic_arb->ppid_to_apid[ppid] & PMIC_ARB_APID_VALID;
- apid = pmic_arb->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID;
- prev_apidd = &pmic_arb->apid_data[apid];
+ valid = bus->ppid_to_apid[ppid] & PMIC_ARB_APID_VALID;
+ apid = bus->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID;
+ prev_apidd = &bus->apid_data[apid];
if (!valid || apidd->write_ee == pmic_arb->ee) {
/* First PPID mapping or one for this EE */
- pmic_arb->ppid_to_apid[ppid] = i | PMIC_ARB_APID_VALID;
+ bus->ppid_to_apid[ppid] = i | PMIC_ARB_APID_VALID;
} else if (valid && is_irq_ee &&
prev_apidd->write_ee == pmic_arb->ee) {
/*
@@ -1176,42 +1209,43 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb)
}
apidd->ppid = ppid;
- pmic_arb->last_apid = i;
+ bus->last_apid = i;
}
/* Dump the mapping table for debug purposes. */
- dev_dbg(&pmic_arb->spmic->dev, "PPID APID Write-EE IRQ-EE\n");
+ dev_dbg(&bus->spmic->dev, "PPID APID Write-EE IRQ-EE\n");
for (ppid = 0; ppid < PMIC_ARB_MAX_PPID; ppid++) {
- apid = pmic_arb->ppid_to_apid[ppid];
+ apid = bus->ppid_to_apid[ppid];
if (apid & PMIC_ARB_APID_VALID) {
apid &= ~PMIC_ARB_APID_VALID;
- apidd = &pmic_arb->apid_data[apid];
- dev_dbg(&pmic_arb->spmic->dev, "%#03X %3u %2u %2u\n",
- ppid, apid, apidd->write_ee, apidd->irq_ee);
+ apidd = &bus->apid_data[apid];
+ dev_dbg(&bus->spmic->dev, "%#03X %3u %2u %2u\n",
+ ppid, apid, apidd->write_ee, apidd->irq_ee);
}
}
return 0;
}
-static int pmic_arb_ppid_to_apid_v5(struct spmi_pmic_arb *pmic_arb, u16 ppid)
+static int pmic_arb_ppid_to_apid_v5(struct spmi_pmic_arb_bus *bus, u16 ppid)
{
- if (!(pmic_arb->ppid_to_apid[ppid] & PMIC_ARB_APID_VALID))
+ if (!(bus->ppid_to_apid[ppid] & PMIC_ARB_APID_VALID))
return -ENODEV;
- return pmic_arb->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID;
+ return bus->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID;
}
/* v2 offset per ppid and per ee */
-static int pmic_arb_offset_v2(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
- enum pmic_arb_channel ch_type)
+static int pmic_arb_offset_v2(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
+ enum pmic_arb_channel ch_type)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u16 apid;
u16 ppid;
int rc;
ppid = sid << 8 | ((addr >> 8) & 0xFF);
- rc = pmic_arb_ppid_to_apid_v2(pmic_arb, ppid);
+ rc = pmic_arb_ppid_to_apid_v2(bus, ppid);
if (rc < 0)
return rc;
@@ -1219,27 +1253,28 @@ static int pmic_arb_offset_v2(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
return 0x1000 * pmic_arb->ee + 0x8000 * apid;
}
-static int pmic_arb_init_apid_v5(struct spmi_pmic_arb *pmic_arb)
+static int pmic_arb_init_apid_v5(struct spmi_pmic_arb_bus *bus)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
int ret;
- pmic_arb->base_apid = 0;
- pmic_arb->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
- PMIC_ARB_FEATURES_PERIPH_MASK;
+ bus->base_apid = 0;
+ bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
+ PMIC_ARB_FEATURES_PERIPH_MASK;
- if (pmic_arb->base_apid + pmic_arb->apid_count > pmic_arb->max_periphs) {
- dev_err(&pmic_arb->spmic->dev, "Unsupported APID count %d detected\n",
- pmic_arb->base_apid + pmic_arb->apid_count);
+ if (bus->base_apid + bus->apid_count > pmic_arb->max_periphs) {
+ dev_err(&bus->spmic->dev, "Unsupported APID count %d detected\n",
+ bus->base_apid + bus->apid_count);
return -EINVAL;
}
- ret = pmic_arb_init_apid_min_max(pmic_arb);
+ ret = pmic_arb_init_apid_min_max(bus);
if (ret)
return ret;
- ret = pmic_arb_read_apid_map_v5(pmic_arb);
+ ret = pmic_arb_read_apid_map_v5(bus);
if (ret) {
- dev_err(&pmic_arb->spmic->dev, "could not read APID->PPID mapping table, rc= %d\n",
+ dev_err(&bus->spmic->dev, "could not read APID->PPID mapping table, rc= %d\n",
ret);
return ret;
}
@@ -1251,15 +1286,16 @@ static int pmic_arb_init_apid_v5(struct spmi_pmic_arb *pmic_arb)
* v5 offset per ee and per apid for observer channels and per apid for
* read/write channels.
*/
-static int pmic_arb_offset_v5(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
- enum pmic_arb_channel ch_type)
+static int pmic_arb_offset_v5(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
+ enum pmic_arb_channel ch_type)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u16 apid;
int rc;
u32 offset = 0;
u16 ppid = (sid << 8) | (addr >> 8);
- rc = pmic_arb_ppid_to_apid_v5(pmic_arb, ppid);
+ rc = pmic_arb_ppid_to_apid_v5(bus, ppid);
if (rc < 0)
return rc;
@@ -1269,8 +1305,8 @@ static int pmic_arb_offset_v5(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
offset = 0x10000 * pmic_arb->ee + 0x80 * apid;
break;
case PMIC_ARB_CHANNEL_RW:
- if (pmic_arb->apid_data[apid].write_ee != pmic_arb->ee) {
- dev_err(&pmic_arb->spmic->dev, "disallowed SPMI write to sid=%u, addr=0x%04X\n",
+ if (bus->apid_data[apid].write_ee != pmic_arb->ee) {
+ dev_err(&bus->spmic->dev, "disallowed SPMI write to sid=%u, addr=0x%04X\n",
sid, addr);
return -EPERM;
}
@@ -1297,15 +1333,16 @@ static int pmic_arb_get_core_resources_v7(struct platform_device *pdev,
* v7 offset per ee and per apid for observer channels and per apid for
* read/write channels.
*/
-static int pmic_arb_offset_v7(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
- enum pmic_arb_channel ch_type)
+static int pmic_arb_offset_v7(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
+ enum pmic_arb_channel ch_type)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
u16 apid;
int rc;
u32 offset = 0;
u16 ppid = (sid << 8) | (addr >> 8);
- rc = pmic_arb->ver_ops->ppid_to_apid(pmic_arb, ppid);
+ rc = pmic_arb->ver_ops->ppid_to_apid(bus, ppid);
if (rc < 0)
return rc;
@@ -1315,8 +1352,8 @@ static int pmic_arb_offset_v7(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
offset = 0x8000 * pmic_arb->ee + 0x20 * apid;
break;
case PMIC_ARB_CHANNEL_RW:
- if (pmic_arb->apid_data[apid].write_ee != pmic_arb->ee) {
- dev_err(&pmic_arb->spmic->dev, "disallowed SPMI write to sid=%u, addr=0x%04X\n",
+ if (bus->apid_data[apid].write_ee != pmic_arb->ee) {
+ dev_err(&bus->spmic->dev, "disallowed SPMI write to sid=%u, addr=0x%04X\n",
sid, addr);
return -EPERM;
}
@@ -1338,104 +1375,110 @@ static u32 pmic_arb_fmt_cmd_v2(u8 opc, u8 sid, u16 addr, u8 bc)
}
static void __iomem *
-pmic_arb_owner_acc_status_v1(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)
+pmic_arb_owner_acc_status_v1(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
{
- return pmic_arb->intr + 0x20 * m + 0x4 * n;
+ return bus->intr + 0x20 * m + 0x4 * n;
}
static void __iomem *
-pmic_arb_owner_acc_status_v2(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)
+pmic_arb_owner_acc_status_v2(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
{
- return pmic_arb->intr + 0x100000 + 0x1000 * m + 0x4 * n;
+ return bus->intr + 0x100000 + 0x1000 * m + 0x4 * n;
}
static void __iomem *
-pmic_arb_owner_acc_status_v3(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)
+pmic_arb_owner_acc_status_v3(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
{
- return pmic_arb->intr + 0x200000 + 0x1000 * m + 0x4 * n;
+ return bus->intr + 0x200000 + 0x1000 * m + 0x4 * n;
}
static void __iomem *
-pmic_arb_owner_acc_status_v5(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)
+pmic_arb_owner_acc_status_v5(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
{
- return pmic_arb->intr + 0x10000 * m + 0x4 * n;
+ return bus->intr + 0x10000 * m + 0x4 * n;
}
static void __iomem *
-pmic_arb_owner_acc_status_v7(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)
+pmic_arb_owner_acc_status_v7(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
{
- return pmic_arb->intr + 0x1000 * m + 0x4 * n;
+ return bus->intr + 0x1000 * m + 0x4 * n;
}
static void __iomem *
-pmic_arb_acc_enable_v1(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_acc_enable_v1(struct spmi_pmic_arb_bus *bus, u16 n)
{
- return pmic_arb->intr + 0x200 + 0x4 * n;
+ return bus->intr + 0x200 + 0x4 * n;
}
static void __iomem *
-pmic_arb_acc_enable_v2(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_acc_enable_v2(struct spmi_pmic_arb_bus *bus, u16 n)
{
- return pmic_arb->intr + 0x1000 * n;
+ return bus->intr + 0x1000 * n;
}
static void __iomem *
-pmic_arb_acc_enable_v5(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_acc_enable_v5(struct spmi_pmic_arb_bus *bus, u16 n)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
return pmic_arb->wr_base + 0x100 + 0x10000 * n;
}
static void __iomem *
-pmic_arb_acc_enable_v7(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_acc_enable_v7(struct spmi_pmic_arb_bus *bus, u16 n)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
return pmic_arb->wr_base + 0x100 + 0x1000 * n;
}
static void __iomem *
-pmic_arb_irq_status_v1(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_irq_status_v1(struct spmi_pmic_arb_bus *bus, u16 n)
{
- return pmic_arb->intr + 0x600 + 0x4 * n;
+ return bus->intr + 0x600 + 0x4 * n;
}
static void __iomem *
-pmic_arb_irq_status_v2(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_irq_status_v2(struct spmi_pmic_arb_bus *bus, u16 n)
{
- return pmic_arb->intr + 0x4 + 0x1000 * n;
+ return bus->intr + 0x4 + 0x1000 * n;
}
static void __iomem *
-pmic_arb_irq_status_v5(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_irq_status_v5(struct spmi_pmic_arb_bus *bus, u16 n)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
return pmic_arb->wr_base + 0x104 + 0x10000 * n;
}
static void __iomem *
-pmic_arb_irq_status_v7(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_irq_status_v7(struct spmi_pmic_arb_bus *bus, u16 n)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
return pmic_arb->wr_base + 0x104 + 0x1000 * n;
}
static void __iomem *
-pmic_arb_irq_clear_v1(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_irq_clear_v1(struct spmi_pmic_arb_bus *bus, u16 n)
{
- return pmic_arb->intr + 0xA00 + 0x4 * n;
+ return bus->intr + 0xA00 + 0x4 * n;
}
static void __iomem *
-pmic_arb_irq_clear_v2(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_irq_clear_v2(struct spmi_pmic_arb_bus *bus, u16 n)
{
- return pmic_arb->intr + 0x8 + 0x1000 * n;
+ return bus->intr + 0x8 + 0x1000 * n;
}
static void __iomem *
-pmic_arb_irq_clear_v5(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_irq_clear_v5(struct spmi_pmic_arb_bus *bus, u16 n)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
return pmic_arb->wr_base + 0x108 + 0x10000 * n;
}
static void __iomem *
-pmic_arb_irq_clear_v7(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_irq_clear_v7(struct spmi_pmic_arb_bus *bus, u16 n)
{
+ struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
return pmic_arb->wr_base + 0x108 + 0x1000 * n;
}
@@ -1455,9 +1498,9 @@ static u32 pmic_arb_apid_map_offset_v7(u16 n)
}
static void __iomem *
-pmic_arb_apid_owner_v2(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_apid_owner_v2(struct spmi_pmic_arb_bus *bus, u16 n)
{
- return pmic_arb->cnfg + 0x700 + 0x4 * n;
+ return bus->cnfg + 0x700 + 0x4 * n;
}
/*
@@ -1466,9 +1509,9 @@ pmic_arb_apid_owner_v2(struct spmi_pmic_arb *pmic_arb, u16 n)
* 0.
*/
static void __iomem *
-pmic_arb_apid_owner_v7(struct spmi_pmic_arb *pmic_arb, u16 n)
+pmic_arb_apid_owner_v7(struct spmi_pmic_arb_bus *bus, u16 n)
{
- return pmic_arb->cnfg + 0x4 * (n - pmic_arb->base_apid);
+ return bus->cnfg + 0x4 * (n - bus->base_apid);
}
static const struct pmic_arb_ver_ops pmic_arb_v1 = {
@@ -1558,29 +1601,120 @@ static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
.translate = qpnpint_irq_domain_translate,
};
+static int spmi_pmic_arb_bus_init(struct platform_device *pdev,
+ struct device_node *node,
+ struct spmi_pmic_arb *pmic_arb)
+{
+ struct spmi_pmic_arb_bus *bus;
+ struct device *dev = &pdev->dev;
+ struct spmi_controller *ctrl;
+ void __iomem *intr;
+ void __iomem *cnfg;
+ int index, ret;
+ u32 irq;
+
+ ctrl = devm_spmi_controller_alloc(dev, sizeof(*bus));
+ if (IS_ERR(ctrl))
+ return PTR_ERR(ctrl);
+
+ ctrl->cmd = pmic_arb_cmd;
+ ctrl->read_cmd = pmic_arb_read_cmd;
+ ctrl->write_cmd = pmic_arb_write_cmd;
+
+ bus = spmi_controller_get_drvdata(ctrl);
+
+ pmic_arb->bus = bus;
+
+ bus->ppid_to_apid = devm_kcalloc(dev, PMIC_ARB_MAX_PPID,
+ sizeof(*bus->ppid_to_apid),
+ GFP_KERNEL);
+ if (!bus->ppid_to_apid)
+ return -ENOMEM;
+
+ bus->apid_data = devm_kcalloc(dev, pmic_arb->max_periphs,
+ sizeof(*bus->apid_data),
+ GFP_KERNEL);
+ if (!bus->apid_data)
+ return -ENOMEM;
+
+ index = of_property_match_string(node, "reg-names", "cnfg");
+ if (index < 0) {
+ dev_err(dev, "cnfg reg region missing");
+ return -EINVAL;
+ }
+
+ cnfg = devm_of_iomap(dev, node, index, NULL);
+ if (IS_ERR(cnfg))
+ return PTR_ERR(cnfg);
+
+ index = of_property_match_string(node, "reg-names", "intr");
+ if (index < 0) {
+ dev_err(dev, "intr reg region missing");
+ return -EINVAL;
+ }
+
+ intr = devm_of_iomap(dev, node, index, NULL);
+ if (IS_ERR(intr))
+ return PTR_ERR(intr);
+
+ irq = of_irq_get_byname(node, "periph_irq");
+ if (irq < 0)
+ return irq;
+
+ bus->pmic_arb = pmic_arb;
+ bus->intr = intr;
+ bus->cnfg = cnfg;
+ bus->irq = irq;
+ bus->spmic = ctrl;
+
+ ret = pmic_arb->ver_ops->init_apid(bus);
+ if (ret)
+ return ret;
+
+ dev_dbg(&pdev->dev, "adding irq domain\n");
+
+ bus->domain = irq_domain_add_tree(dev->of_node,
+ &pmic_arb_irq_domain_ops, bus);
+ if (!bus->domain) {
+ dev_err(&pdev->dev, "unable to create irq_domain\n");
+ return -ENOMEM;
+ }
+
+ irq_set_chained_handler_and_data(bus->irq,
+ pmic_arb_chained_irq, bus);
+
+ ctrl->dev.of_node = node;
+
+ ret = devm_spmi_controller_add(dev, ctrl);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int spmi_pmic_arb_probe(struct platform_device *pdev)
{
struct spmi_pmic_arb *pmic_arb;
- struct spmi_controller *ctrl;
+ struct device *dev = &pdev->dev;
struct resource *res;
void __iomem *core;
u32 channel, ee, hw_ver;
int err;
- ctrl = devm_spmi_controller_alloc(&pdev->dev, sizeof(*pmic_arb));
- if (IS_ERR(ctrl))
- return PTR_ERR(ctrl);
-
- pmic_arb = spmi_controller_get_drvdata(ctrl);
- pmic_arb->spmic = ctrl;
+ pmic_arb = devm_kzalloc(dev, sizeof(*pmic_arb), GFP_KERNEL);
+ if (!pmic_arb)
+ return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
- core = devm_ioremap(&ctrl->dev, res->start, resource_size(res));
+ core = devm_ioremap(dev, res->start, resource_size(res));
if (IS_ERR(core))
return PTR_ERR(core);
pmic_arb->core_size = resource_size(res);
+ platform_set_drvdata(pdev, pmic_arb);
+ raw_spin_lock_init(&pmic_arb->lock);
+
hw_ver = readl_relaxed(core + PMIC_ARB_VERSION);
if (hw_ver < PMIC_ARB_VERSION_V2_MIN)
@@ -1594,30 +1728,12 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
else
pmic_arb->ver_ops = &pmic_arb_v7;
- dev_info(&ctrl->dev, "PMIC arbiter version %s (0x%x)\n",
- pmic_arb->ver_ops->ver_str, hw_ver);
-
err = pmic_arb->ver_ops->get_core_resources(pdev, core);
if (err)
return err;
- err = pmic_arb->ver_ops->init_apid(pmic_arb);
- if (err)
- return err;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
- pmic_arb->intr = devm_ioremap_resource(&ctrl->dev, res);
- if (IS_ERR(pmic_arb->intr))
- return PTR_ERR(pmic_arb->intr);
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cnfg");
- pmic_arb->cnfg = devm_ioremap_resource(&ctrl->dev, res);
- if (IS_ERR(pmic_arb->cnfg))
- return PTR_ERR(pmic_arb->cnfg);
-
- pmic_arb->irq = platform_get_irq_byname(pdev, "periph_irq");
- if (pmic_arb->irq < 0)
- return pmic_arb->irq;
+ dev_info(dev, "PMIC arbiter version %s (0x%x)\n",
+ pmic_arb->ver_ops->ver_str, hw_ver);
err = of_property_read_u32(pdev->dev.of_node, "qcom,channel", &channel);
if (err) {
@@ -1646,42 +1762,17 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
pmic_arb->ee = ee;
- platform_set_drvdata(pdev, ctrl);
- raw_spin_lock_init(&pmic_arb->lock);
-
- ctrl->cmd = pmic_arb_cmd;
- ctrl->read_cmd = pmic_arb_read_cmd;
- ctrl->write_cmd = pmic_arb_write_cmd;
-
- dev_dbg(&pdev->dev, "adding irq domain\n");
- pmic_arb->domain = irq_domain_add_tree(pdev->dev.of_node,
- &pmic_arb_irq_domain_ops, pmic_arb);
- if (!pmic_arb->domain) {
- dev_err(&pdev->dev, "unable to create irq_domain\n");
- return -ENOMEM;
- }
-
- irq_set_chained_handler_and_data(pmic_arb->irq, pmic_arb_chained_irq,
- pmic_arb);
- err = spmi_controller_add(ctrl);
- if (err)
- goto err_domain_remove;
-
- return 0;
-
-err_domain_remove:
- irq_set_chained_handler_and_data(pmic_arb->irq, NULL, NULL);
- irq_domain_remove(pmic_arb->domain);
- return err;
+ return spmi_pmic_arb_bus_init(pdev, dev->of_node, pmic_arb);
}
static void spmi_pmic_arb_remove(struct platform_device *pdev)
{
- struct spmi_controller *ctrl = platform_get_drvdata(pdev);
- struct spmi_pmic_arb *pmic_arb = spmi_controller_get_drvdata(ctrl);
- spmi_controller_remove(ctrl);
- irq_set_chained_handler_and_data(pmic_arb->irq, NULL, NULL);
- irq_domain_remove(pmic_arb->domain);
+ struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev);
+ struct spmi_pmic_arb_bus *bus = pmic_arb->bus;
+
+ irq_set_chained_handler_and_data(bus->irq,
+ NULL, NULL);
+ irq_domain_remove(bus->domain);
}
static const struct of_device_id spmi_pmic_arb_match_table[] = {
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v8 5/7] spmi: pmic-arb: Make core resources acquiring a version operation
From: Abel Vesa @ 2024-04-02 12:07 UTC (permalink / raw)
To: Stephen Boyd, Matthias Brugger, Bjorn Andersson, Konrad Dybcio,
Dmitry Baryshkov, Neil Armstrong, AngeloGioacchino Del Regno,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Srini Kandagatla, Johan Hovold, linux-kernel, linux-arm-kernel,
linux-arm-msm, linux-mediatek, devicetree, Abel Vesa
In-Reply-To: <20240402-spmi-multi-master-support-v8-0-ce6f2d14a058@linaro.org>
Rather than setting up the core, obsrv and chnls in probe by using
version specific conditionals, add a dedicated "get_core_resources"
version specific op and move the acquiring in there. Since there are
no current users of the second bus yet, drop the comment about why
devm_platform_ioremap_resource can't be used in case of "core",
as it is not applicable anymore.
Don't switch to devm_platform_ioremap_resource though as we need
to keep track of core size.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
drivers/spmi/spmi-pmic-arb.c | 114 +++++++++++++++++++++++++++----------------
1 file changed, 71 insertions(+), 43 deletions(-)
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index dc969f8bed18..ff777b4a6f33 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -186,6 +186,7 @@ struct spmi_pmic_arb {
* struct pmic_arb_ver_ops - version dependent functionality.
*
* @ver_str: version string.
+ * @get_core_resources: initializes the core, observer and channels
* @init_apid: finds the apid base and count
* @ppid_to_apid: finds the apid for a given ppid.
* @non_data_cmd: on v1 issues an spmi non-data command.
@@ -206,6 +207,7 @@ struct spmi_pmic_arb {
*/
struct pmic_arb_ver_ops {
const char *ver_str;
+ int (*get_core_resources)(struct platform_device *pdev, void __iomem *core);
int (*init_apid)(struct spmi_pmic_arb *pmic_arb);
int (*ppid_to_apid)(struct spmi_pmic_arb *pmic_arb, u16 ppid);
/* spmi commands (read_cmd, write_cmd, cmd) functionality */
@@ -961,6 +963,19 @@ static int pmic_arb_init_apid_min_max(struct spmi_pmic_arb *pmic_arb)
return 0;
}
+static int pmic_arb_get_core_resources_v1(struct platform_device *pdev,
+ void __iomem *core)
+{
+ struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev);
+
+ pmic_arb->wr_base = core;
+ pmic_arb->rd_base = core;
+
+ pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS;
+
+ return 0;
+}
+
static int pmic_arb_init_apid_v1(struct spmi_pmic_arb *pmic_arb)
{
u32 *mapping_table;
@@ -1062,6 +1077,33 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pmic_arb, u16 ppid)
return apid;
}
+static int pmic_arb_get_obsrvr_chnls_v2(struct platform_device *pdev)
+{
+ struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev);
+
+ pmic_arb->rd_base = devm_platform_ioremap_resource_byname(pdev, "obsrvr");
+ if (IS_ERR(pmic_arb->rd_base))
+ return PTR_ERR(pmic_arb->rd_base);
+
+ pmic_arb->wr_base = devm_platform_ioremap_resource_byname(pdev, "chnls");
+ if (IS_ERR(pmic_arb->wr_base))
+ return PTR_ERR(pmic_arb->wr_base);
+
+ return 0;
+}
+
+static int pmic_arb_get_core_resources_v2(struct platform_device *pdev,
+ void __iomem *core)
+{
+ struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev);
+
+ pmic_arb->core = core;
+
+ pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS;
+
+ return pmic_arb_get_obsrvr_chnls_v2(pdev);
+}
+
static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pmic_arb, u16 ppid)
{
u16 apid_valid;
@@ -1239,6 +1281,18 @@ static int pmic_arb_offset_v5(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
return offset;
}
+static int pmic_arb_get_core_resources_v7(struct platform_device *pdev,
+ void __iomem *core)
+{
+ struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev);
+
+ pmic_arb->core = core;
+
+ pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS_V7;
+
+ return pmic_arb_get_obsrvr_chnls_v2(pdev);
+}
+
/*
* v7 offset per ee and per apid for observer channels and per apid for
* read/write channels.
@@ -1419,6 +1473,7 @@ pmic_arb_apid_owner_v7(struct spmi_pmic_arb *pmic_arb, u16 n)
static const struct pmic_arb_ver_ops pmic_arb_v1 = {
.ver_str = "v1",
+ .get_core_resources = pmic_arb_get_core_resources_v1,
.init_apid = pmic_arb_init_apid_v1,
.ppid_to_apid = pmic_arb_ppid_to_apid_v1,
.non_data_cmd = pmic_arb_non_data_cmd_v1,
@@ -1434,6 +1489,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v1 = {
static const struct pmic_arb_ver_ops pmic_arb_v2 = {
.ver_str = "v2",
+ .get_core_resources = pmic_arb_get_core_resources_v2,
.init_apid = pmic_arb_init_apid_v1,
.ppid_to_apid = pmic_arb_ppid_to_apid_v2,
.non_data_cmd = pmic_arb_non_data_cmd_v2,
@@ -1449,6 +1505,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v2 = {
static const struct pmic_arb_ver_ops pmic_arb_v3 = {
.ver_str = "v3",
+ .get_core_resources = pmic_arb_get_core_resources_v2,
.init_apid = pmic_arb_init_apid_v1,
.ppid_to_apid = pmic_arb_ppid_to_apid_v2,
.non_data_cmd = pmic_arb_non_data_cmd_v2,
@@ -1464,6 +1521,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v3 = {
static const struct pmic_arb_ver_ops pmic_arb_v5 = {
.ver_str = "v5",
+ .get_core_resources = pmic_arb_get_core_resources_v2,
.init_apid = pmic_arb_init_apid_v5,
.ppid_to_apid = pmic_arb_ppid_to_apid_v5,
.non_data_cmd = pmic_arb_non_data_cmd_v2,
@@ -1479,6 +1537,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v5 = {
static const struct pmic_arb_ver_ops pmic_arb_v7 = {
.ver_str = "v7",
+ .get_core_resources = pmic_arb_get_core_resources_v7,
.init_apid = pmic_arb_init_apid_v5,
.ppid_to_apid = pmic_arb_ppid_to_apid_v5,
.non_data_cmd = pmic_arb_non_data_cmd_v2,
@@ -1515,16 +1574,6 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
pmic_arb = spmi_controller_get_drvdata(ctrl);
pmic_arb->spmic = ctrl;
- /*
- * Please don't replace this with devm_platform_ioremap_resource() or
- * devm_ioremap_resource(). These both result in a call to
- * devm_request_mem_region() which prevents multiple mappings of this
- * register address range. SoCs with PMIC arbiter v7 may define two
- * arbiter devices, for the two physical SPMI interfaces, which share
- * some register address ranges (i.e. "core", "obsrvr", and "chnls").
- * Ensure that both devices probe successfully by calling devm_ioremap()
- * which does not result in a devm_request_mem_region() call.
- */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
core = devm_ioremap(&ctrl->dev, res->start, resource_size(res));
if (IS_ERR(core))
@@ -1534,44 +1583,23 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
hw_ver = readl_relaxed(core + PMIC_ARB_VERSION);
- if (hw_ver < PMIC_ARB_VERSION_V2_MIN) {
+ if (hw_ver < PMIC_ARB_VERSION_V2_MIN)
pmic_arb->ver_ops = &pmic_arb_v1;
- pmic_arb->wr_base = core;
- pmic_arb->rd_base = core;
- } else {
- pmic_arb->core = core;
-
- if (hw_ver < PMIC_ARB_VERSION_V3_MIN)
- pmic_arb->ver_ops = &pmic_arb_v2;
- else if (hw_ver < PMIC_ARB_VERSION_V5_MIN)
- pmic_arb->ver_ops = &pmic_arb_v3;
- else if (hw_ver < PMIC_ARB_VERSION_V7_MIN)
- pmic_arb->ver_ops = &pmic_arb_v5;
- else
- pmic_arb->ver_ops = &pmic_arb_v7;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "obsrvr");
- pmic_arb->rd_base = devm_ioremap(&ctrl->dev, res->start,
- resource_size(res));
- if (IS_ERR(pmic_arb->rd_base))
- return PTR_ERR(pmic_arb->rd_base);
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "chnls");
- pmic_arb->wr_base = devm_ioremap(&ctrl->dev, res->start,
- resource_size(res));
- if (IS_ERR(pmic_arb->wr_base))
- return PTR_ERR(pmic_arb->wr_base);
- }
+ else if (hw_ver < PMIC_ARB_VERSION_V3_MIN)
+ pmic_arb->ver_ops = &pmic_arb_v2;
+ else if (hw_ver < PMIC_ARB_VERSION_V5_MIN)
+ pmic_arb->ver_ops = &pmic_arb_v3;
+ else if (hw_ver < PMIC_ARB_VERSION_V7_MIN)
+ pmic_arb->ver_ops = &pmic_arb_v5;
+ else
+ pmic_arb->ver_ops = &pmic_arb_v7;
dev_info(&ctrl->dev, "PMIC arbiter version %s (0x%x)\n",
pmic_arb->ver_ops->ver_str, hw_ver);
- if (hw_ver < PMIC_ARB_VERSION_V7_MIN)
- pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS;
- else
- pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS_V7;
+ err = pmic_arb->ver_ops->get_core_resources(pdev, core);
+ if (err)
+ return err;
err = pmic_arb->ver_ops->init_apid(pmic_arb);
if (err)
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v8 4/7] spmi: pmic-arb: Make the APID init a version operation
From: Abel Vesa @ 2024-04-02 12:07 UTC (permalink / raw)
To: Stephen Boyd, Matthias Brugger, Bjorn Andersson, Konrad Dybcio,
Dmitry Baryshkov, Neil Armstrong, AngeloGioacchino Del Regno,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Srini Kandagatla, Johan Hovold, linux-kernel, linux-arm-kernel,
linux-arm-msm, linux-mediatek, devicetree, Abel Vesa
In-Reply-To: <20240402-spmi-multi-master-support-v8-0-ce6f2d14a058@linaro.org>
Rather than using conditionals in probe function, add the APID init
as a version specific operation. Due to v7, which supports multiple
buses, pass on the bus index to be used for sorting out the apid base
and count.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
drivers/spmi/spmi-pmic-arb.c | 144 +++++++++++++++++++++----------------------
1 file changed, 69 insertions(+), 75 deletions(-)
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 704fd4506971..dc969f8bed18 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -186,6 +186,7 @@ struct spmi_pmic_arb {
* struct pmic_arb_ver_ops - version dependent functionality.
*
* @ver_str: version string.
+ * @init_apid: finds the apid base and count
* @ppid_to_apid: finds the apid for a given ppid.
* @non_data_cmd: on v1 issues an spmi non-data command.
* on v2 no HW support, returns -EOPNOTSUPP.
@@ -205,6 +206,7 @@ struct spmi_pmic_arb {
*/
struct pmic_arb_ver_ops {
const char *ver_str;
+ int (*init_apid)(struct spmi_pmic_arb *pmic_arb);
int (*ppid_to_apid)(struct spmi_pmic_arb *pmic_arb, u16 ppid);
/* spmi commands (read_cmd, write_cmd, cmd) functionality */
int (*offset)(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
@@ -947,6 +949,32 @@ static int qpnpint_irq_domain_alloc(struct irq_domain *domain,
return 0;
}
+static int pmic_arb_init_apid_min_max(struct spmi_pmic_arb *pmic_arb)
+{
+ /*
+ * Initialize max_apid/min_apid to the opposite bounds, during
+ * the irq domain translation, we are sure to update these
+ */
+ pmic_arb->max_apid = 0;
+ pmic_arb->min_apid = pmic_arb->max_periphs - 1;
+
+ return 0;
+}
+
+static int pmic_arb_init_apid_v1(struct spmi_pmic_arb *pmic_arb)
+{
+ u32 *mapping_table;
+
+ mapping_table = devm_kcalloc(&pmic_arb->spmic->dev, pmic_arb->max_periphs,
+ sizeof(*mapping_table), GFP_KERNEL);
+ if (!mapping_table)
+ return -ENOMEM;
+
+ pmic_arb->mapping_table = mapping_table;
+
+ return pmic_arb_init_apid_min_max(pmic_arb);
+}
+
static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb *pmic_arb, u16 ppid)
{
u32 *mapping_table = pmic_arb->mapping_table;
@@ -1149,6 +1177,34 @@ static int pmic_arb_offset_v2(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
return 0x1000 * pmic_arb->ee + 0x8000 * apid;
}
+static int pmic_arb_init_apid_v5(struct spmi_pmic_arb *pmic_arb)
+{
+ int ret;
+
+ pmic_arb->base_apid = 0;
+ pmic_arb->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) &
+ PMIC_ARB_FEATURES_PERIPH_MASK;
+
+ if (pmic_arb->base_apid + pmic_arb->apid_count > pmic_arb->max_periphs) {
+ dev_err(&pmic_arb->spmic->dev, "Unsupported APID count %d detected\n",
+ pmic_arb->base_apid + pmic_arb->apid_count);
+ return -EINVAL;
+ }
+
+ ret = pmic_arb_init_apid_min_max(pmic_arb);
+ if (ret)
+ return ret;
+
+ ret = pmic_arb_read_apid_map_v5(pmic_arb);
+ if (ret) {
+ dev_err(&pmic_arb->spmic->dev, "could not read APID->PPID mapping table, rc= %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
/*
* v5 offset per ee and per apid for observer channels and per apid for
* read/write channels.
@@ -1363,6 +1419,7 @@ pmic_arb_apid_owner_v7(struct spmi_pmic_arb *pmic_arb, u16 n)
static const struct pmic_arb_ver_ops pmic_arb_v1 = {
.ver_str = "v1",
+ .init_apid = pmic_arb_init_apid_v1,
.ppid_to_apid = pmic_arb_ppid_to_apid_v1,
.non_data_cmd = pmic_arb_non_data_cmd_v1,
.offset = pmic_arb_offset_v1,
@@ -1377,6 +1434,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v1 = {
static const struct pmic_arb_ver_ops pmic_arb_v2 = {
.ver_str = "v2",
+ .init_apid = pmic_arb_init_apid_v1,
.ppid_to_apid = pmic_arb_ppid_to_apid_v2,
.non_data_cmd = pmic_arb_non_data_cmd_v2,
.offset = pmic_arb_offset_v2,
@@ -1391,6 +1449,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v2 = {
static const struct pmic_arb_ver_ops pmic_arb_v3 = {
.ver_str = "v3",
+ .init_apid = pmic_arb_init_apid_v1,
.ppid_to_apid = pmic_arb_ppid_to_apid_v2,
.non_data_cmd = pmic_arb_non_data_cmd_v2,
.offset = pmic_arb_offset_v2,
@@ -1405,6 +1464,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v3 = {
static const struct pmic_arb_ver_ops pmic_arb_v5 = {
.ver_str = "v5",
+ .init_apid = pmic_arb_init_apid_v5,
.ppid_to_apid = pmic_arb_ppid_to_apid_v5,
.non_data_cmd = pmic_arb_non_data_cmd_v2,
.offset = pmic_arb_offset_v5,
@@ -1419,6 +1479,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v5 = {
static const struct pmic_arb_ver_ops pmic_arb_v7 = {
.ver_str = "v7",
+ .init_apid = pmic_arb_init_apid_v5,
.ppid_to_apid = pmic_arb_ppid_to_apid_v5,
.non_data_cmd = pmic_arb_non_data_cmd_v2,
.offset = pmic_arb_offset_v7,
@@ -1444,7 +1505,6 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
struct spmi_controller *ctrl;
struct resource *res;
void __iomem *core;
- u32 *mapping_table;
u32 channel, ee, hw_ver;
int err;
@@ -1472,12 +1532,6 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
pmic_arb->core_size = resource_size(res);
- pmic_arb->ppid_to_apid = devm_kcalloc(&ctrl->dev, PMIC_ARB_MAX_PPID,
- sizeof(*pmic_arb->ppid_to_apid),
- GFP_KERNEL);
- if (!pmic_arb->ppid_to_apid)
- return -ENOMEM;
-
hw_ver = readl_relaxed(core + PMIC_ARB_VERSION);
if (hw_ver < PMIC_ARB_VERSION_V2_MIN) {
@@ -1511,58 +1565,17 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
return PTR_ERR(pmic_arb->wr_base);
}
- pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS;
+ dev_info(&ctrl->dev, "PMIC arbiter version %s (0x%x)\n",
+ pmic_arb->ver_ops->ver_str, hw_ver);
- if (hw_ver >= PMIC_ARB_VERSION_V7_MIN) {
+ if (hw_ver < PMIC_ARB_VERSION_V7_MIN)
+ pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS;
+ else
pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS_V7;
- /* Optional property for v7: */
- of_property_read_u32(pdev->dev.of_node, "qcom,bus-id",
- &pmic_arb->bus_instance);
- if (pmic_arb->bus_instance > 1) {
- dev_err(&pdev->dev, "invalid bus instance (%u) specified\n",
- pmic_arb->bus_instance);
- return -EINVAL;
- }
- if (pmic_arb->bus_instance == 0) {
- pmic_arb->base_apid = 0;
- pmic_arb->apid_count =
- readl_relaxed(core + PMIC_ARB_FEATURES) &
- PMIC_ARB_FEATURES_PERIPH_MASK;
- } else {
- pmic_arb->base_apid =
- readl_relaxed(core + PMIC_ARB_FEATURES) &
- PMIC_ARB_FEATURES_PERIPH_MASK;
- pmic_arb->apid_count =
- readl_relaxed(core + PMIC_ARB_FEATURES1) &
- PMIC_ARB_FEATURES_PERIPH_MASK;
- }
-
- if (pmic_arb->base_apid + pmic_arb->apid_count > pmic_arb->max_periphs) {
- dev_err(&pdev->dev, "Unsupported APID count %d detected\n",
- pmic_arb->base_apid + pmic_arb->apid_count);
- return -EINVAL;
- }
- } else if (hw_ver >= PMIC_ARB_VERSION_V5_MIN) {
- pmic_arb->base_apid = 0;
- pmic_arb->apid_count = readl_relaxed(core + PMIC_ARB_FEATURES) &
- PMIC_ARB_FEATURES_PERIPH_MASK;
-
- if (pmic_arb->apid_count > pmic_arb->max_periphs) {
- dev_err(&pdev->dev, "Unsupported APID count %d detected\n",
- pmic_arb->apid_count);
- return -EINVAL;
- }
- }
-
- pmic_arb->apid_data = devm_kcalloc(&ctrl->dev, pmic_arb->max_periphs,
- sizeof(*pmic_arb->apid_data),
- GFP_KERNEL);
- if (!pmic_arb->apid_data)
- return -ENOMEM;
-
- dev_info(&ctrl->dev, "PMIC arbiter version %s (0x%x)\n",
- pmic_arb->ver_ops->ver_str, hw_ver);
+ err = pmic_arb->ver_ops->init_apid(pmic_arb);
+ if (err)
+ return err;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
pmic_arb->intr = devm_ioremap_resource(&ctrl->dev, res);
@@ -1604,16 +1617,6 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
}
pmic_arb->ee = ee;
- mapping_table = devm_kcalloc(&ctrl->dev, pmic_arb->max_periphs,
- sizeof(*mapping_table), GFP_KERNEL);
- if (!mapping_table)
- return -ENOMEM;
-
- pmic_arb->mapping_table = mapping_table;
- /* Initialize max_apid/min_apid to the opposite bounds, during
- * the irq domain translation, we are sure to update these */
- pmic_arb->max_apid = 0;
- pmic_arb->min_apid = pmic_arb->max_periphs - 1;
platform_set_drvdata(pdev, ctrl);
raw_spin_lock_init(&pmic_arb->lock);
@@ -1622,15 +1625,6 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
ctrl->read_cmd = pmic_arb_read_cmd;
ctrl->write_cmd = pmic_arb_write_cmd;
- if (hw_ver >= PMIC_ARB_VERSION_V5_MIN) {
- err = pmic_arb_read_apid_map_v5(pmic_arb);
- if (err) {
- dev_err(&pdev->dev, "could not read APID->PPID mapping table, rc= %d\n",
- err);
- return err;
- }
- }
-
dev_dbg(&pdev->dev, "adding irq domain\n");
pmic_arb->domain = irq_domain_add_tree(pdev->dev.of_node,
&pmic_arb_irq_domain_ops, pmic_arb);
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH] dt-bindings: mfd: syscon: Add ti,am62p-cpsw-mac-efuse compatible
From: Krzysztof Kozlowski @ 2024-04-02 12:08 UTC (permalink / raw)
To: Siddharth Vadapalli, lee, robh, krzk+dt, conor+dt
Cc: devicetree, linux-kernel, linux-arm-kernel, srk
In-Reply-To: <20240402105708.4114146-1-s-vadapalli@ti.com>
On 02/04/2024 12:57, Siddharth Vadapalli wrote:
> The CTRLMMR_MAC_IDx registers within the CTRL_MMR space of TI's AM62p SoC
> contain the MAC Address programmed in the eFuse. Add compatible for
> allowing the CPSW driver to obtain a regmap for the CTRLMMR_MAC_IDx
> registers within the System Controller device-tree node. The default MAC
> Address for the interface corresponding to the first MAC port will be set
> to the value programmed in the eFuse.
>
> Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
> ---
>
> This patch is based on linux-next tagged next-20240402.
Where is the DTS using it?
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v6 3/4] dt-bindings: watchdog: aspeed-wdt: Add aspeed,scu
From: Andrew Jeffery @ 2024-04-02 12:09 UTC (permalink / raw)
To: Rob Herring, Peter Yin
Cc: patrick, Wim Van Sebroeck, Guenter Roeck, Krzysztof Kozlowski,
Conor Dooley, Joel Stanley, linux-watchdog, devicetree,
linux-arm-kernel, linux-aspeed, linux-kernel
In-Reply-To: <20240401135637.GA342928-robh@kernel.org>
On Mon, 2024-04-01 at 08:56 -0500, Rob Herring wrote:
> On Thu, Mar 28, 2024 at 10:22:30AM +0800, Peter Yin wrote:
> > To use the SCU register to obtain reset flags for supporting
> > bootstatus.
> >
> > Signed-off-by: Peter Yin <peteryin.openbmc@gmail.com>
> > ---
> > Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt | 4 ++++
> > 1 file changed, 4 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > index 3208adb3e52e..80a1f58b5a2e 100644
> > --- a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > +++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> > @@ -8,6 +8,8 @@ Required properties:
> >
> > - reg: physical base address of the controller and length of memory mapped
> > region
> > + - aspeed,scu: a reference to the System Control Unit node of the Aspeed
> > + SOC.
>
> You cannot add new required properties as that is an ABI break.
>
> If there's only 1 SCU instance, you can just fetch its node by
> compatible with no DT change.
>
> What's the plan for converting this binding to schema? This is the 2nd
> new property in 6 months.
I had a patch converting it in a local branch which I've now sent:
https://lore.kernel.org/all/20240402120118.282035-1-andrew@codeconstruct.com.au/
Perhaps we can pull it into this series?
Andrew
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v1 2/6] clk: meson: a1: pll: support 'syspll' general-purpose PLL for CPU clock
From: Dmitry Rokosov @ 2024-04-02 12:15 UTC (permalink / raw)
To: Jerome Brunet
Cc: neil.armstrong, mturquette, sboyd, robh+dt,
krzysztof.kozlowski+dt, khilman, martin.blumenstingl, kernel,
rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel,
linux-arm-kernel
In-Reply-To: <1j4jckjftk.fsf@starbuckisacylon.baylibre.com>
On Tue, Apr 02, 2024 at 11:00:42AM +0200, Jerome Brunet wrote:
>
> On Fri 29 Mar 2024 at 23:58, Dmitry Rokosov <ddrokosov@salutedevices.com> wrote:
>
> > The 'syspll' PLL, also known as the system PLL, is a general and
> > essential PLL responsible for generating the CPU clock frequency.
> > With its wide-ranging capabilities, it is designed to accommodate
> > frequencies within the range of 768MHz to 1536MHz.
> >
> > Signed-off-by: Dmitry Rokosov <ddrokosov@salutedevices.com>
> > ---
> > drivers/clk/meson/a1-pll.c | 78 ++++++++++++++++++++++++++++++++++++++
> > drivers/clk/meson/a1-pll.h | 6 +++
> > 2 files changed, 84 insertions(+)
> >
> > diff --git a/drivers/clk/meson/a1-pll.c b/drivers/clk/meson/a1-pll.c
> > index 60b2e53e7e51..02fd2d325cc6 100644
> > --- a/drivers/clk/meson/a1-pll.c
> > +++ b/drivers/clk/meson/a1-pll.c
> > @@ -138,6 +138,81 @@ static struct clk_regmap hifi_pll = {
> > },
> > };
> >
> > +static const struct pll_mult_range sys_pll_mult_range = {
> > + .min = 32,
> > + .max = 64,
> > +};
> > +
> > +/*
> > + * We assume that the sys_pll_clk has already been set up by the low-level
> > + * bootloaders as the main CPU PLL source. Therefore, it is not necessary to
> > + * run the initialization sequence.
> > + */
>
> I see no reason to make such assumption.
> This clock is no read-only, it apparently is able to re-lock so assuming
> anything from the bootloader is just asking from trouble
>
Indeed, I have implemented the following initialization sequence. I have
dumped the bootloader setup and included it in the definition of my
sys_pll. However, I have encountered an issue with the enable bit. If I
leave the enable bit switched on by default, there is a possibility that
the bootloader selects a fixed CPU clock while the sys_pll should be
switched off. On the other hand, if I keep the enable bit switched off
by default, the bootloader might configure the CPU clock to use sys_pll,
resulting in the execution halting when the initialization sequence is
run. This situation has led me to assume that we should place our trust
in the bootloader setup.
If you believe it is necessary to include the initialization sequence, I
can prepare it with the sys_pll enabled by default.
> > +static struct clk_regmap sys_pll = {
> > + .data = &(struct meson_clk_pll_data){
> > + .en = {
> > + .reg_off = ANACTRL_SYSPLL_CTRL0,
> > + .shift = 28,
> > + .width = 1,
> > + },
> > + .m = {
> > + .reg_off = ANACTRL_SYSPLL_CTRL0,
> > + .shift = 0,
> > + .width = 8,
> > + },
> > + .n = {
> > + .reg_off = ANACTRL_SYSPLL_CTRL0,
> > + .shift = 10,
> > + .width = 5,
> > + },
> > + .frac = {
> > + .reg_off = ANACTRL_SYSPLL_CTRL1,
> > + .shift = 0,
> > + .width = 19,
> > + },
> > + .l = {
> > + .reg_off = ANACTRL_SYSPLL_STS,
> > + .shift = 31,
> > + .width = 1,
> > + },
> > + .current_en = {
> > + .reg_off = ANACTRL_SYSPLL_CTRL0,
> > + .shift = 26,
> > + .width = 1,
> > + },
> > + .l_detect = {
> > + .reg_off = ANACTRL_SYSPLL_CTRL2,
> > + .shift = 6,
> > + .width = 1,
> > + },
> > + .range = &sys_pll_mult_range,
> > + },
> > + .hw.init = &(struct clk_init_data){
> > + .name = "sys_pll",
> > + .ops = &meson_clk_pll_ops,
> > + .parent_names = (const char *[]){ "syspll_in" },
> > + .num_parents = 1,
> > + /*
> > + * This clock is used as the main CPU PLL source in low-level
> > + * bootloaders, and it is necessary to mark it as critical.
> > + */
> > + .flags = CLK_IS_CRITICAL,
>
> No I don't think so. Downstream consumer maybe critical but that one is
> not, unless it is read-only.
>
> A CPU pll, like on the g12 family, is unlikely to be read-only since the
> PLL will need to relock to change rates. During this phase, there will
> be no reate coming from the PLL so the PLL is not critical and you must
> be able to "park" your CPU an another clock while poking this one
>
Initially, I tagged it with CLK_IS_CRITICAL because I observed in the
kernel start that CCF disables it. However, upon further understanding,
I realized that this happened due to other reasons. I believe that if I
provide an init sequence where sys_pll is enabled by default, CCF will
not disable this clock.
> > + },
> > +};
> > +
> > +static struct clk_fixed_factor sys_pll_div16 = {
> > + .mult = 1,
> > + .div = 16,
> > + .hw.init = &(struct clk_init_data){
> > + .name = "sys_pll_div16",
> > + .ops = &clk_fixed_factor_ops,
> > + .parent_hws = (const struct clk_hw *[]) {
> > + &sys_pll.hw
> > + },
> > + .num_parents = 1,
> > + },
> > +};
> > +
> > static struct clk_fixed_factor fclk_div2_div = {
> > .mult = 1,
> > .div = 2,
> > @@ -283,6 +358,8 @@ static struct clk_hw *a1_pll_hw_clks[] = {
> > [CLKID_FCLK_DIV5] = &fclk_div5.hw,
> > [CLKID_FCLK_DIV7] = &fclk_div7.hw,
> > [CLKID_HIFI_PLL] = &hifi_pll.hw,
> > + [CLKID_SYS_PLL] = &sys_pll.hw,
> > + [CLKID_SYS_PLL_DIV16] = &sys_pll_div16.hw,
> > };
> >
> > static struct clk_regmap *const a1_pll_regmaps[] = {
> > @@ -293,6 +370,7 @@ static struct clk_regmap *const a1_pll_regmaps[] = {
> > &fclk_div5,
> > &fclk_div7,
> > &hifi_pll,
> > + &sys_pll,
> > };
> >
> > static struct regmap_config a1_pll_regmap_cfg = {
> > diff --git a/drivers/clk/meson/a1-pll.h b/drivers/clk/meson/a1-pll.h
> > index 4be17b2bf383..666d9b2137e9 100644
> > --- a/drivers/clk/meson/a1-pll.h
> > +++ b/drivers/clk/meson/a1-pll.h
> > @@ -18,6 +18,12 @@
> > #define ANACTRL_FIXPLL_CTRL0 0x0
> > #define ANACTRL_FIXPLL_CTRL1 0x4
> > #define ANACTRL_FIXPLL_STS 0x14
> > +#define ANACTRL_SYSPLL_CTRL0 0x80
> > +#define ANACTRL_SYSPLL_CTRL1 0x84
> > +#define ANACTRL_SYSPLL_CTRL2 0x88
> > +#define ANACTRL_SYSPLL_CTRL3 0x8c
> > +#define ANACTRL_SYSPLL_CTRL4 0x90
> > +#define ANACTRL_SYSPLL_STS 0x94
> > #define ANACTRL_HIFIPLL_CTRL0 0xc0
> > #define ANACTRL_HIFIPLL_CTRL1 0xc4
> > #define ANACTRL_HIFIPLL_CTRL2 0xc8
--
Thank you,
Dmitry
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v4 4/5] dt-bindings: fsl-imx-sdma: Add I2C peripheral types ID
From: Rob Herring @ 2024-04-02 12:20 UTC (permalink / raw)
To: Frank Li
Cc: NXP Linux Team, Vinod Koul, Shawn Guo, Joy Zou,
Krzysztof Kozlowski, dmaengine, linux-kernel, Conor Dooley,
devicetree, Pengutronix Kernel Team, linux-arm-kernel,
Sascha Hauer, imx, Fabio Estevam
In-Reply-To: <20240329-sdma_upstream-v4-4-daeb3067dea7@nxp.com>
On Fri, 29 Mar 2024 10:34:44 -0400, Frank Li wrote:
> Add peripheral types ID 26 for I2C because sdma firmware (sdma-6q: v3.6,
> sdma-7d: v4.6) support I2C DMA transfer.
>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> Documentation/devicetree/bindings/dma/fsl,imx-sdma.yaml | 1 +
> 1 file changed, 1 insertion(+)
>
Please add Acked-by/Reviewed-by tags when posting new versions. However,
there's no need to repost patches *only* to add the tags. The upstream
maintainer will do that for acks received on the version they apply.
If a tag was not added on purpose, please state why and what changed.
Missing tags:
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] pinctrl: armada-37xx: remove an unused variable
From: Linus Walleij @ 2024-04-02 12:27 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
Arnd Bergmann, linux-arm-kernel, linux-gpio, linux-kernel
In-Reply-To: <20240322132205.906729-1-arnd@kernel.org>
On Fri, Mar 22, 2024 at 2:22 PM Arnd Bergmann <arnd@kernel.org> wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> This variable has never been used and can be removed to avoid a W=1 warning:
>
> drivers/pinctrl/mvebu/pinctrl-armada-37xx.c:837:6: error: variable 'i' set but not used [-Werror,-Wunused-but-set-variable]
> 837 | int i = 0;
>
> Fixes: 87466ccd9401 ("pinctrl: armada-37xx: Add pin controller support for Armada 37xx")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Patch applied!
Yours,
Linus Walleij
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] dt-bindings: mfd: syscon: Add ti,am62p-cpsw-mac-efuse compatible
From: Siddharth Vadapalli @ 2024-04-02 12:30 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Siddharth Vadapalli, lee, robh, krzk+dt, conor+dt, devicetree,
linux-kernel, linux-arm-kernel, srk
In-Reply-To: <2e9b6a91-43d3-4b23-830d-40e607505d8c@kernel.org>
On Tue, Apr 02, 2024 at 02:08:32PM +0200, Krzysztof Kozlowski wrote:
> On 02/04/2024 12:57, Siddharth Vadapalli wrote:
> > The CTRLMMR_MAC_IDx registers within the CTRL_MMR space of TI's AM62p SoC
> > contain the MAC Address programmed in the eFuse. Add compatible for
> > allowing the CPSW driver to obtain a regmap for the CTRLMMR_MAC_IDx
> > registers within the System Controller device-tree node. The default MAC
> > Address for the interface corresponding to the first MAC port will be set
> > to the value programmed in the eFuse.
> >
> > Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
> > ---
> >
> > This patch is based on linux-next tagged next-20240402.
>
> Where is the DTS using it?
The current implementation in the device-tree for older TI K3 SoCs is as
follows:
cpsw_port1: port@1 {
reg = <1>;
ti,mac-only;
label = "port1";
phys = <&phy_gmii_sel 1>;
mac-address = [00 00 00 00 00 00];
ti,syscon-efuse = <&wkup_conf 0x200>;
};
The "ti,syscon-efuse" property passes the reference to the System
Controller node as well as the offset to the CTRLMMR_MAC_IDx registers
within the CTRL_MMR space.
This implementation works only when the System Controller node
(wkup_conf or its equivalent depending on the SoC) has the compatible
"syscon". From AM62p SoC onwards, it was decided that the System
Controller nodes have to be modelled as a "simple-bus", due to which the
"syscon" based regmapping within the driver that uses the
"ti,syscon-efuse" property will no longer work directly. Therefore, with
this patch, the upcoming device-tree changes for AM62p will be:
1) Update in the System Controller node to use the newly added
compatible for mapping the CTRLMMR_MAC_IDx registers:
wkup_conf: bus@43000000 {
compatible = "simple-bus";
reg = <0x00 0x43000000 0x00 0x20000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00 0x00 0x43000000 0x20000>;
bootph-all;
chipid: chipid@14 {
reg = <0x14 0x4>;
bootph-all;
};
+
+ cpsw_mac_efuse: cpsw-mac-efuse@200 {
+ compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
+ reg = <0x200 0x8>;
+ };
};
2) Update within the cpsw_port1 node for passing the "cpsw_mac_efuse"
node:
cpsw_port1: port@1 {
reg = <1>;
ti,mac-only;
label = "port1";
phys = <&phy_gmii_sel 1>;
mac-address = [00 00 00 00 00 00];
+ ti,syscon-efuse = <&cpsw_mac_efuse 0x0>;
};
>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Thank you for reviewing and acking this patch.
Regards,
Siddharth.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] irqchip/gic-v3-its: Don't need VSYNC if VMAPP with {V, Alloc}=={0, x}
From: Marc Zyngier @ 2024-04-02 12:35 UTC (permalink / raw)
To: t00849498; +Cc: tglx, linux-arm-kernel, linux-kernel, guoyang2, wangwudi
In-Reply-To: <20240402114147.3788881-1-tangnianyao@huawei.com>
On Tue, 02 Apr 2024 12:41:47 +0100,
t00849498 <tangnianyao@huawei.com> wrote:
>
> From GIC spec, a VMAPP with {V, Alloc}=={0, x} is self-synchronizing,
It'd be nice to quote the part of the spec (5.3.19).
> This means the ITS command queue does not show the command as
> consumed until all of its effects are completed. A VSYNC with unmapped
> vpeid is not needed.
>
> Signed-off-by: t00849498 <tangnianyao@huawei.com>
Previous contributions with the same email address had the name
"Nianyao Tang" associated with it. Was it wrong in the past? Or is the
above wrong?
> ---
> drivers/irqchip/irq-gic-v3-its.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index fca888b36680..a0ca5dcbb245 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -789,6 +789,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
> unsigned long vpt_addr, vconf_addr;
> u64 target;
> bool alloc;
> + bool unmap_v4_1 = !desc->its_vmapp_cmd.valid && is_v4_1(its);
>
> its_encode_cmd(cmd, GITS_CMD_VMAPP);
> its_encode_vpeid(cmd, desc->its_vmapp_cmd.vpe->vpe_id);
> @@ -832,6 +833,9 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
> out:
> its_fixup_cmd(cmd);
>
> + if (unmap_v4_1)
> + return NULL;
> +
> return valid_vpe(its, desc->its_vmapp_cmd.vpe);
> }
>
This is a bit ugly. We already have a whole block dedicated to
handling VMAPP with V=0 and GICv4.1, and it'd be more readable to keep
all that code together. Something like the untested patch below.
Thanks,
M.
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index fca888b36680..2a537cbfcb07 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -786,6 +786,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
struct its_cmd_block *cmd,
struct its_cmd_desc *desc)
{
+ struct its_vpe *vpe = valid_vpe(its, desc->its_vmapp_cmd.vpe);
unsigned long vpt_addr, vconf_addr;
u64 target;
bool alloc;
@@ -798,6 +799,11 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
if (is_v4_1(its)) {
alloc = !atomic_dec_return(&desc->its_vmapp_cmd.vpe->vmapp_count);
its_encode_alloc(cmd, alloc);
+ /*
+ * Unmapping a VPE is self-synchronizing on GICv4.1,
+ * no need to issue a VSYNC.
+ */
+ vpe = NULL;
}
goto out;
@@ -832,7 +838,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
out:
its_fixup_cmd(cmd);
- return valid_vpe(its, desc->its_vmapp_cmd.vpe);
+ return vpe;
}
static struct its_vpe *its_build_vmapti_cmd(struct its_node *its,
--
Without deviation from the norm, progress is not possible.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH net-next 2/3] net: stmmac: add support for RZ/N1 GMAC
From: Romain Gantois @ 2024-04-02 12:37 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Geert Uytterhoeven, Magnus Damm, Alexandre Torgue, Jose Abreu,
Maxime Coquelin, Russell King, Clément Léger
Cc: Thomas Petazzoni, netdev, devicetree, linux-kernel,
linux-renesas-soc, linux-stm32, linux-arm-kernel, Romain Gantois
In-Reply-To: <20240402-rzn1-gmac1-v1-0-5be2b2894d8c@bootlin.com>
From: Clément Léger <clement.leger@bootlin.com>
Add support for the Renesas RZ/N1 GMAC. This support can make use of a
custom RZ/N1 PCS which is fetched by parsing the pcs-handle device tree
property.
Signed-off-by: "Clément Léger" <clement.leger@bootlin.com>
Co-developed-by: Romain Gantois <romain.gantois@bootlin.com>
Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>
---
MAINTAINERS | 6 ++
drivers/net/ethernet/stmicro/stmmac/Kconfig | 12 ++++
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c | 87 ++++++++++++++++++++++++
4 files changed, 106 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 6a233e1a3cf2..9735c7d2ee38 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18833,6 +18833,12 @@ F: include/dt-bindings/net/pcs-rzn1-miic.h
F: include/linux/pcs-rzn1-miic.h
F: net/dsa/tag_rzn1_a5psw.c
+RENESAS RZ/N1 DWMAC GLUE LAYER
+M: Romain Gantois <romain.gantois@bootlin.com>
+S: Maintained
+F: Documentation/devicetree/bindings/net/renesas,rzn1-gmac.yaml
+F: drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c
+
RENESAS RZ/N1 RTC CONTROLLER DRIVER
M: Miquel Raynal <miquel.raynal@bootlin.com>
L: linux-rtc@vger.kernel.org
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 4ec61f1ee71a..05cc07b8f48c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -142,6 +142,18 @@ config DWMAC_ROCKCHIP
This selects the Rockchip RK3288 SoC glue layer support for
the stmmac device driver.
+config DWMAC_RZN1
+ tristate "Renesas RZ/N1 dwmac support"
+ default ARCH_RZN1
+ depends on OF && (ARCH_RZN1 || COMPILE_TEST)
+ select PCS_RZN1_MIIC
+ help
+ Support for Ethernet controller on Renesas RZ/N1 SoC family.
+
+ This selects the Renesas RZ/N1 SoC glue layer support for
+ the stmmac device driver. This support can make use of a custom MII
+ converter PCS device.
+
config DWMAC_SOCFPGA
tristate "SOCFPGA dwmac support"
default ARCH_INTEL_SOCFPGA
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 26cad4344701..c2f0e91f6bf8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o
obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o
obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-ethqos.o
obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
+obj-$(CONFIG_DWMAC_RZN1) += dwmac-rzn1.o
obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o
obj-$(CONFIG_DWMAC_STARFIVE) += dwmac-starfive.o
obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c
new file mode 100644
index 000000000000..5216d7890992
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2024 Schneider-Electric
+ *
+ * Clément Léger <clement.leger@bootlin.com>
+ */
+
+#include <linux/of.h>
+#include <linux/pcs-rzn1-miic.h>
+#include <linux/phylink.h>
+#include <linux/platform_device.h>
+
+#include "stmmac_platform.h"
+#include "stmmac.h"
+
+static int rzn1_dwmac_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct plat_stmmacenet_data *plat_dat;
+ struct stmmac_resources stmmac_res;
+ struct device *dev = &pdev->dev;
+ struct device_node *pcs_node;
+ struct stmmac_priv *priv;
+ struct phylink_pcs *pcs;
+ struct net_device *ndev;
+ int ret;
+
+ ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+ if (ret)
+ return ret;
+
+ plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
+ if (IS_ERR(plat_dat))
+ return PTR_ERR(plat_dat);
+
+ plat_dat->bsp_priv = plat_dat;
+
+ ret = stmmac_dvr_probe(dev, plat_dat, &stmmac_res);
+ if (ret)
+ return ret;
+
+ ndev = platform_get_drvdata(pdev);
+ priv = netdev_priv(ndev);
+
+ pcs_node = of_parse_phandle(np, "pcs-handle", 0);
+ if (pcs_node) {
+ pcs = miic_create(dev, pcs_node);
+ of_node_put(pcs_node);
+ if (IS_ERR(pcs))
+ return PTR_ERR(pcs);
+
+ priv->hw->phylink_pcs = pcs;
+ }
+
+ return 0;
+}
+
+static void rzn1_dwmac_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+
+ stmmac_pltfr_remove(pdev);
+
+ if (priv->hw->phylink_pcs)
+ miic_destroy(priv->hw->phylink_pcs);
+}
+
+static const struct of_device_id rzn1_dwmac_match[] = {
+ { .compatible = "renesas,rzn1-gmac" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rzn1_dwmac_match);
+
+static struct platform_driver rzn1_dwmac_driver = {
+ .probe = rzn1_dwmac_probe,
+ .remove_new = rzn1_dwmac_remove,
+ .driver = {
+ .name = "rzn1-dwmac",
+ .of_match_table = rzn1_dwmac_match,
+ },
+};
+module_platform_driver(rzn1_dwmac_driver);
+
+MODULE_AUTHOR("Clément Léger <clement.leger@bootlin.com>");
+MODULE_DESCRIPTION("Renesas RZN1 DWMAC specific glue layer");
+MODULE_LICENSE("GPL");
--
2.44.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH net-next 1/3] dt-bindings: net: renesas,rzn1-gmac: Document RZ/N1 GMAC support
From: Romain Gantois @ 2024-04-02 12:37 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Geert Uytterhoeven, Magnus Damm, Alexandre Torgue, Jose Abreu,
Maxime Coquelin, Russell King, Clément Léger
Cc: Thomas Petazzoni, netdev, devicetree, linux-kernel,
linux-renesas-soc, linux-stm32, linux-arm-kernel, Romain Gantois
In-Reply-To: <20240402-rzn1-gmac1-v1-0-5be2b2894d8c@bootlin.com>
From: Clément Léger <clement.leger@bootlin.com>
The RZ/N1 series of MPUs feature up to two Gigabit Ethernet controllers.
These controllers are based on Synopsys IPs. They can be connected to
RZ/N1 RGMII/RMII converters.
Add a binding that describes these GMAC devices.
Signed-off-by: "Clément Léger" <clement.leger@bootlin.com>
[rgantois: commit log]
Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>
---
.../devicetree/bindings/net/renesas,rzn1-gmac.yaml | 66 ++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/renesas,rzn1-gmac.yaml b/Documentation/devicetree/bindings/net/renesas,rzn1-gmac.yaml
new file mode 100644
index 000000000000..c6f61fb1e5b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/renesas,rzn1-gmac.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/renesas,rzn1-gmac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas GMAC
+
+maintainers:
+ - Romain Gantois <romain.gantois@bootlin.com>
+
+select:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - renesas,r9a06g032-gmac
+ - renesas,rzn1-gmac
+ required:
+ - compatible
+
+allOf:
+ - $ref: snps,dwmac.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r9a06g032-gmac
+ - const: renesas,rzn1-gmac
+ - const: snps,dwmac
+
+ pcs-handle:
+ description:
+ phandle pointing to a PCS sub-node compatible with
+ renesas,rzn1-miic.yaml#
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r9a06g032-sysctrl.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ ethernet@44000000 {
+ compatible = "renesas,r9a06g032-gmac", "renesas,rzn1-gmac", "snps,dwmac";
+ reg = <0x44000000 0x2000>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
+ clock-names = "stmmaceth";
+ clocks = <&sysctrl R9A06G032_HCLK_GMAC0>;
+ snps,multicast-filter-bins = <256>;
+ snps,perfect-filter-entries = <128>;
+ tx-fifo-depth = <2048>;
+ rx-fifo-depth = <4096>;
+ pcs-handle = <&mii_conv1>;
+ phy-mode = "mii";
+ };
+
+...
--
2.44.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH net-next 0/3] net: stmmac: Add support for RZN1 GMAC devices
From: Romain Gantois @ 2024-04-02 12:36 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Geert Uytterhoeven, Magnus Damm, Alexandre Torgue, Jose Abreu,
Maxime Coquelin, Russell King, Clément Léger
Cc: Thomas Petazzoni, netdev, devicetree, linux-kernel,
linux-renesas-soc, linux-stm32, linux-arm-kernel, Romain Gantois
Hello everyone,
This is version one of my series that adds support for a Gigabit Ethernet
controller featured in the Renesas r9a06g032 SoC, of the RZ/N1 family. This
GMAC device is based on a Synopsys IP and is compatible with the stmmac driver.
My former colleague Clément Léger originally sent a series for this driver,
but an issue in bringing up the PCS clock had blocked the upstreaming
process. This issue has since been resolved by the following series:
https://lore.kernel.org/all/20240326-rxc_bugfix-v6-0-24a74e5c761f@bootlin.com/
This series consists of a devicetree binding describing the RZN1 GMAC
controller IP, a node for the GMAC1 device in the r9a06g032 SoC device
tree, and the GMAC driver itself which is a glue layer in stmmac.
Best Regards,
Romain Gantois
---
Clément Léger (3):
dt-bindings: net: renesas,rzn1-gmac: Document RZ/N1 GMAC support
net: stmmac: add support for RZ/N1 GMAC
ARM: dts: r9a06g032: describe GMAC1
.../devicetree/bindings/net/renesas,rzn1-gmac.yaml | 66 ++++++++++++++++
MAINTAINERS | 6 ++
arch/arm/boot/dts/renesas/r9a06g032.dtsi | 19 +++++
drivers/net/ethernet/stmicro/stmmac/Kconfig | 12 +++
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c | 87 ++++++++++++++++++++++
6 files changed, 191 insertions(+)
---
base-commit: 5fc68320c1fb3c7d456ddcae0b4757326a043e6f
change-id: 20240402-rzn1-gmac1-685cf8793d0e
Best regards,
--
Romain Gantois <romain.gantois@bootlin.com>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH net-next 3/3] ARM: dts: r9a06g032: describe GMAC1
From: Romain Gantois @ 2024-04-02 12:37 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Geert Uytterhoeven, Magnus Damm, Alexandre Torgue, Jose Abreu,
Maxime Coquelin, Russell King, Clément Léger
Cc: Thomas Petazzoni, netdev, devicetree, linux-kernel,
linux-renesas-soc, linux-stm32, linux-arm-kernel, Romain Gantois
In-Reply-To: <20240402-rzn1-gmac1-v1-0-5be2b2894d8c@bootlin.com>
From: Clément Léger <clement.leger@bootlin.com>
The r9a06g032 SoC of the RZ/N1 family features two GMAC devices named
GMAC1/2, that are based on Synopsys cores. GMAC1 is connected to a
RGMII/RMII converter that is already described in this device tree.
Signed-off-by: "Clément Léger" <clement.leger@bootlin.com>
[rgantois: commit log]
Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>
---
arch/arm/boot/dts/renesas/r9a06g032.dtsi | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm/boot/dts/renesas/r9a06g032.dtsi b/arch/arm/boot/dts/renesas/r9a06g032.dtsi
index fa63e1afc4ef..cab7a641f95b 100644
--- a/arch/arm/boot/dts/renesas/r9a06g032.dtsi
+++ b/arch/arm/boot/dts/renesas/r9a06g032.dtsi
@@ -316,6 +316,25 @@ dma1: dma-controller@40105000 {
data-width = <8>;
};
+ gmac1: ethernet@44000000 {
+ compatible = "renesas,r9a06g032-gmac", "renesas,rzn1-gmac", "snps,dwmac";
+ reg = <0x44000000 0x2000>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
+ clocks = <&sysctrl R9A06G032_HCLK_GMAC0>;
+ clock-names = "stmmaceth";
+ power-domains = <&sysctrl>;
+ snps,multicast-filter-bins = <256>;
+ snps,perfect-filter-entries = <128>;
+ tx-fifo-depth = <2048>;
+ rx-fifo-depth = <4096>;
+ pcs-handle = <&mii_conv1>;
+ status = "disabled";
+ };
+
gmac2: ethernet@44002000 {
compatible = "renesas,r9a06g032-gmac", "renesas,rzn1-gmac", "snps,dwmac";
reg = <0x44002000 0x2000>;
--
2.44.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
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