Introduce clock support for Airoha EN7581 SoC
Subsystems (3)
v2 cover Introduce clock support for Airoha EN7581 SoC
this series is based on the following series:
https://patchwork.kernel.org/project/linux-arm-kernel/cover/[email protected]/
Changes since v1:
- add .enable()/disable() callbacks to pcie ops
- introduce en_clk_soc_data data structure in order to define multiple clk_ops for each supported SoC
- rename clock node from system-controller to clock-controller
- add missing item descriptions in dt-binding
Lorenzo Bianconi (4):
dt-bindings: clock: airoha: add EN7581 binding
arm64: dts: airoha: Add EN7581 clock node
clk: en7523: Add en_clk_soc_data data structure
clk: en7523: Add EN7581 support
.../bindings/clock/airoha,en7523-scu.yaml | 31 ++- arch/arm64/boot/dts/airoha/en7581.dtsi | 9 + drivers/clk/clk-en7523.c | 190 ++++++++++++++++-- 3 files changed, 211 insertions(+), 19 deletions(-)
Signature · 1 line
2.44.0
PATCH v2 1/4 dt-bindings: clock: airoha: add EN7581 binding
Introduce Airoha EN7581 entry in Airoha EN7523 clock binding
--- .../bindings/clock/airoha,en7523-scu.yaml | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +29 -2
@@ -29,10 +29,13 @@ description: | properties: compatible: items: - - const: airoha,en7523-scu + - enum: + - airoha,en7523-scu + - airoha,en7581-scu reg: - maxItems: 2 + minItems: 2 + maxItems: 3 "#clock-cells": description:
@@ -45,6 +48,30 @@ required: - reg - '#clock-cells' +allOf: + - if: + properties: + compatible: + const: airoha,en7523-scu + then: + properties: + reg: + items: + - description: scu base address + - description: misc scu base address + + - if: + properties: + compatible: + const: airoha,en7581-scu + then: + properties: + reg: + items: + - description: scu base address + - description: misc scu base address + - description: pb scu base address + additionalProperties: false examples:
Signature · 1 line
2.44.0
Re: [PATCH v2 1/4] dt-bindings: clock: airoha: add EN7581 binding
Quoted 14 lines · Lorenzo Bianconi
Introduce Airoha EN7581 entry in Airoha EN7523 clock binding
Signed-off-by Lorenzo Bianconi <[email protected]>--- .../bindings/clock/airoha,en7523-scu.yaml | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +0
-0@@ -29,10 +29,13 @@ description: | properties: compatible:
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml description: | · line 38
Quoted 10 lines
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +5
-2items: - - const: airoha,en7523-scu + - enum: + - airoha,en7523-scu + - airoha,en7581-scu reg: - maxItems: 2 + minItems: 2 + maxItems: 3
Best regards,
Krzysztof
Re: [PATCH v2 1/4] dt-bindings: clock: airoha: add EN7581 binding
In reply to Lorenzo BianconiQuoting Lorenzo Bianconi (2024-04-06 03:43:41)
Quoted 4 lines
Introduce Airoha EN7581 entry in Airoha EN7523 clock binding
Signed-off-by Lorenzo Bianconi <[email protected]>---
Applied to clk-next
PATCH v2 2/4 arm64: dts: airoha: Add EN7581 clock node
In reply to Lorenzo BianconiIntroduce the Airoha EN7581 clock node in Airoha EN7581 dtsi
--- arch/arm64/boot/dts/airoha/en7581.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/arm64/boot/dts/airoha/en7581.dtsi +9 -0
@@ -2,6 +2,7 @@ #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/en7523-clk.h> / { interrupt-parent = <&gic>;
@@ -150,5 +151,13 @@ uart1: serial@1fbf0000 { interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>; clock-frequency = <1843200>; }; + + scuclk: clock-controller@1fa20000 { + compatible = "airoha,en7581-scu"; + reg = <0x0 0x1fa20000 0x0 0x400>, + <0x0 0x1fb00000 0x0 0x1000>, + <0x0 0x1fbe3400 0x0 0xfc>; + #clock-cells = <1>; + }; }; };
Signature · 1 line
2.44.0
PATCH v2 3/4 clk: en7523: Add en_clk_soc_data data structure
In reply to Lorenzo BianconiIntroduce en_clk_soc_data data structure in order to define multiple clk_ops for each supported SoC. This is a preliminary patch to introduce EN7581 clock support.
--- drivers/clk/clk-en7523.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
drivers/clk/clk-en7523.c +20 -12
@@ -47,6 +47,10 @@ struct en_clk_gate {struct clk_hw hw; }; +struct en_clk_soc_data { +const struct clk_ops pcie_ops; +}; +static const u32 gsw_base[] = {400000000 ,500000000 };static const u32 emi_base[] = {333000000 ,400000000 };static const u32 bus_base[] = {500000000 ,540000000 };
@@ -145,11 +149,6 @@ static const struct en_clk_desc en7523_base_clks[] = { } }; -static const struct of_device_id of_match_clk_en7523[] = { - { .compatible ="airoha,en7523-scu" , }, - {/* sentinel */ } -}; -static unsigned int en7523_get_base_rate (void __iomem *base,unsigned int i) {const struct en_clk_desc *desc = &en7523_base_clks[i];
@@ -247,14 +246,10 @@ static void en7523_pci_unprepare(struct clk_hw *hw)static struct clk_hw *en7523_register_pcie_clk (struct device *dev,void __iomem *np_base) { -static const struct clk_ops pcie_gate_ops = { - .is_enabled = en7523_pci_is_enabled, - .prepare = en7523_pci_prepare, - .unprepare = en7523_pci_unprepare, - }; +const struct en_clk_soc_data *soc_data =of_device_get_match_data (dev);struct clk_init_data init = { .name ="pcie" , - .ops = &pcie_gate_ops, + .ops = &soc_data->pcie_ops, };struct en_clk_gate *cg;
@@ -264,7 +259,7 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev, cg->base = np_base; cg->hw.init = &init; -en7523_pci_unprepare (&cg->hw); + init.ops->unprepare (&cg->hw);if (clk_hw_register (dev, &cg->hw))return NULL ;
@@ -333,6 +328,19 @@ static int en7523_clk_probe(struct platform_device *pdev)return r; } +static const struct en_clk_soc_data en7523_data = { + .pcie_ops = { + .is_enabled = en7523_pci_is_enabled, + .prepare = en7523_pci_prepare, + .unprepare = en7523_pci_unprepare, + }, +}; + +static const struct of_device_id of_match_clk_en7523[] = { + { .compatible ="airoha,en7523-scu" , .data = &en7523_data }, + {/* sentinel */ } +}; +static struct platform_driver clk_en7523_drv = { .probe = en7523_clk_probe, .driver = {
Signature · 1 line
2.44.0
Re: [PATCH v2 3/4] clk: en7523: Add en_clk_soc_data data structure
Quoting Lorenzo Bianconi (2024-04-06 03:43:43)
Quoted 7 lines
Introduce
en_clk_soc_datadata structure in order to define multipleclk_opsfor each supported SoC. This is a preliminary patch to introduce EN7581 clock support.Tested-by Zhengping Zhang <[email protected]>Signed-off-by Lorenzo Bianconi <[email protected]>---
Applied to clk-next
PATCH v2 4/4 clk: en7523: Add EN7581 support
In reply to Lorenzo BianconiIntroduce EN7581 clock support to clk-en7523 driver. Add hw_init callback to en_clk_soc_data data structure.
--- drivers/clk/clk-en7523.c | 158 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 153 insertions(+), 5 deletions(-)
drivers/clk/clk-en7523.c +153 -5
@@ -4,13 +4,16 @@#include <linux/clk-provider.h> #include <linux/io.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <dt-bindings/clock/en7523-clk.h> #define REG_PCI_CONTROL 0x88#define REG_PCI_CONTROL_PERSTOUT BIT(29)#define REG_PCI_CONTROL_PERSTOUT1 BIT(26) +#define REG_PCI_CONTROL_REFCLK_EN0 BIT(23)#define REG_PCI_CONTROL_REFCLK_EN1 BIT(22) +#define REG_PCI_CONTROL_PERSTOUT2 BIT(16)#define REG_GSW_CLK_DIV_SEL 0x1b4#define REG_EMI_CLK_DIV_SEL 0x1b8#define REG_BUS_CLK_DIV_SEL 0x1bc
@@ -18,10 +21,25 @@#define REG_SPI_CLK_FREQ_SEL 0x1c8#define REG_NPU_CLK_DIV_SEL 0x1fc#define REG_CRYPTO_CLKSRC 0x200 -#define REG_RESET_CONTROL 0x834 +#define REG_RESET_CONTROL2 0x830 +#define REG_RESET2_CONTROL_PCIE2 BIT(27) +#define REG_RESET_CONTROL1 0x834#define REG_RESET_CONTROL_PCIEHB BIT(29)#define REG_RESET_CONTROL_PCIE1 BIT(27)#define REG_RESET_CONTROL_PCIE2 BIT(26) +/* EN7581 */ +#define REG_PCIE0_MEM 0x00 +#define REG_PCIE0_MEM_MASK 0x04 +#define REG_PCIE1_MEM 0x08 +#define REG_PCIE1_MEM_MASK 0x0c +#define REG_PCIE2_MEM 0x10 +#define REG_PCIE2_MEM_MASK 0x14 +#define REG_PCIE_RESET_OPEN_DRAIN 0x018c +#define REG_PCIE_RESET_OPEN_DRAIN_MASK GENMASK(2, 0) +#define REG_NP_SCU_PCIC 0x88 +#define REG_NP_SCU_SSTR 0x9c +#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13) +#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)struct en_clk_desc {int id;
@@ -49,6 +67,8 @@ struct en_clk_gate {struct en_clk_soc_data {const struct clk_ops pcie_ops; +int (*hw_init)(struct platform_device *pdev,void __iomem *base, +void __iomem *np_base); };static const u32 gsw_base[] = {400000000 ,500000000 };
@@ -211,14 +231,14 @@ static int en7523_pci_prepare(struct clk_hw *hw)usleep_range (1000 ,2000 );/* Reset to default */ - val =readl (np_base +REG_RESET_CONTROL ); + val =readl (np_base +REG_RESET_CONTROL1 ); mask =REG_RESET_CONTROL_PCIE1 |REG_RESET_CONTROL_PCIE2 |REG_RESET_CONTROL_PCIEHB ; -writel (val & ~mask, np_base +REG_RESET_CONTROL ); +writel (val & ~mask, np_base +REG_RESET_CONTROL1 );usleep_range (1000 ,2000 ); -writel (val | mask, np_base +REG_RESET_CONTROL ); +writel (val | mask, np_base +REG_RESET_CONTROL1 );msleep (100 ); -writel (val & ~mask, np_base +REG_RESET_CONTROL ); +writel (val & ~mask, np_base +REG_RESET_CONTROL1 );usleep_range (5000 ,10000 );/* Release device */
@@ -259,6 +279,9 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev, cg->base = np_base; cg->hw.init = &init; + +if (init.ops->disable) + init.ops->disable (&cg->hw); init.ops->unprepare (&cg->hw);if (clk_hw_register (dev, &cg->hw))
@@ -267,6 +290,111 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev,return &cg->hw; } +static int en7581_pci_is_enabled (struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); +u32 val, mask; + + mask =REG_PCI_CONTROL_REFCLK_EN0 |REG_PCI_CONTROL_REFCLK_EN1 ; + val =readl (cg->base +REG_PCI_CONTROL ); +return (val & mask) == mask; +} + +static int en7581_pci_prepare (struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); +void __iomem *np_base = cg->base; +u32 val, mask; + + mask =REG_RESET_CONTROL_PCIE1 |REG_RESET_CONTROL_PCIE2 | +REG_RESET_CONTROL_PCIEHB ; + val =readl (np_base +REG_RESET_CONTROL1 ); +writel (val & ~mask, np_base +REG_RESET_CONTROL1 ); + val =readl (np_base +REG_RESET_CONTROL2 ); +writel (val & ~REG_RESET2_CONTROL_PCIE2 , np_base +REG_RESET_CONTROL2 ); +usleep_range (5000 ,10000 ); + +return 0 ; +} + +static int en7581_pci_enable (struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); +void __iomem *np_base = cg->base; +u32 val, mask; + + mask =REG_PCI_CONTROL_REFCLK_EN0 |REG_PCI_CONTROL_REFCLK_EN1 | +REG_PCI_CONTROL_PERSTOUT1 |REG_PCI_CONTROL_PERSTOUT2 | +REG_PCI_CONTROL_PERSTOUT ; + val =readl (np_base +REG_PCI_CONTROL ); +writel (val | mask, np_base +REG_PCI_CONTROL ); +msleep (250 ); + +return 0 ; +} + +static void en7581_pci_unprepare (struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); +void __iomem *np_base = cg->base; +u32 val, mask; + + mask =REG_RESET_CONTROL_PCIE1 |REG_RESET_CONTROL_PCIE2 | +REG_RESET_CONTROL_PCIEHB ; + val =readl (np_base +REG_RESET_CONTROL1 ); +writel (val | mask, np_base +REG_RESET_CONTROL1 ); + mask =REG_RESET_CONTROL_PCIE1 |REG_RESET_CONTROL_PCIE2 ; +writel (val | mask, np_base +REG_RESET_CONTROL1 ); + val =readl (np_base +REG_RESET_CONTROL2 ); +writel (val |REG_RESET_CONTROL_PCIE2 , np_base +REG_RESET_CONTROL2 ); +msleep (100 ); +} + +static void en7581_pci_disable (struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); +void __iomem *np_base = cg->base; +u32 val, mask; + + mask =REG_PCI_CONTROL_REFCLK_EN0 |REG_PCI_CONTROL_REFCLK_EN1 | +REG_PCI_CONTROL_PERSTOUT1 |REG_PCI_CONTROL_PERSTOUT2 | +REG_PCI_CONTROL_PERSTOUT ; + val =readl (np_base +REG_PCI_CONTROL ); +writel (val & ~mask, np_base +REG_PCI_CONTROL ); +usleep_range (1000 ,2000 ); +} + +static int en7581_clk_hw_init (struct platform_device *pdev, +void __iomem *base, +void __iomem *np_base) +{ +void __iomem *pb_base; +u32 val; + + pb_base =devm_platform_ioremap_resource (pdev,2 ); +if (IS_ERR (pb_base)) +return PTR_ERR (pb_base); + + val =readl (np_base +REG_NP_SCU_SSTR ); + val &= ~(REG_PCIE_XSI0_SEL_MASK |REG_PCIE_XSI1_SEL_MASK ); +writel (val, np_base +REG_NP_SCU_SSTR ); + val =readl (np_base +REG_NP_SCU_PCIC ); +writel (val |3 , np_base +REG_NP_SCU_PCIC ); + +writel (0x20000000 , pb_base +REG_PCIE0_MEM ); +writel (0xfc000000 , pb_base +REG_PCIE0_MEM_MASK ); +writel (0x24000000 , pb_base +REG_PCIE1_MEM ); +writel (0xfc000000 , pb_base +REG_PCIE1_MEM_MASK ); +writel (0x28000000 , pb_base +REG_PCIE2_MEM ); +writel (0xfc000000 , pb_base +REG_PCIE2_MEM_MASK ); + + val =readl (base +REG_PCIE_RESET_OPEN_DRAIN ); +writel (val |REG_PCIE_RESET_OPEN_DRAIN_MASK , + base +REG_PCIE_RESET_OPEN_DRAIN ); + +return 0 ; +} +static void en7523_register_clocks (struct device *dev,struct clk_hw_onecell_data *clk_data,void __iomem *base,void __iomem *np_base) {
@@ -299,6 +427,7 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_datstatic int en7523_clk_probe (struct platform_device *pdev) {struct device_node *node = pdev->dev.of_node; +const struct en_clk_soc_data *soc_data;struct clk_hw_onecell_data *clk_data;void __iomem *base, *np_base;int r;
@@ -311,6 +440,13 @@ static int en7523_clk_probe(struct platform_device *pdev)if (IS_ERR (np_base))return PTR_ERR (np_base); + soc_data =of_device_get_match_data (&pdev->dev); +if (soc_data->hw_init) { + r = soc_data->hw_init (pdev, base, np_base); +if (r) +return r; + } + clk_data =devm_kzalloc (&pdev->dev,struct_size (clk_data, hws,EN7523_NUM_CLOCKS ),GFP_KERNEL );
@@ -336,8 +472,20 @@ static const struct en_clk_soc_data en7523_data = { }, }; +static const struct en_clk_soc_data en7581_data = { + .pcie_ops = { + .is_enabled = en7581_pci_is_enabled, + .prepare = en7581_pci_prepare, + .enable = en7581_pci_enable, + .unprepare = en7581_pci_unprepare, + .disable = en7581_pci_disable, + }, + .hw_init = en7581_clk_hw_init, +}; +static const struct of_device_id of_match_clk_en7523[] = { { .compatible ="airoha,en7523-scu" , .data = &en7523_data }, + { .compatible ="airoha,en7581-scu" , .data = &en7581_data }, {/* sentinel */ } };
Signature · 1 line
2.44.0
Re: [PATCH v2 4/4] clk: en7523: Add EN7581 support
Quoting Lorenzo Bianconi (2024-04-06 03:43:44)
Quoted 6 lines
Introduce EN7581 clock support to clk-en7523 driver. Add
hw_initcallback toen_clk_soc_datadata structure.Tested-by Zhengping Zhang <[email protected]>Signed-off-by Lorenzo Bianconi <[email protected]>---
Applied to clk-next
Re: (subset) [PATCH v2 0/4] Introduce clock support for Airoha EN7581 SoC
In reply to Lorenzo BianconiQuoted 11 lines · Lorenzo Bianconi
this series is based on the following series:
https://patchwork.kernel.org/project/linux-arm-kernel/cover/[email protected]/Changes since v1:
- add .enable()/disable() callbacks to pcie ops
- introduceen_clk_soc_datadata structure in order to define multipleclk_opsfor each supported SoC
- rename clock node from system-controller to clock-controller
- add missing item descriptions in dt-binding[...]
Applied to v6.9-next/dts64, thanks!
[2/4] arm64: dts: airoha: Add EN7581 clock node
commit: 1dd2e7b97c3c8554f3339397ef6656d90af3ae1d
Cheers,
Angelo