From b448e46f6846c9a1306e17eb174c1bdcde6c8d88 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 11 Nov 2024 16:38:01 +0000 Subject: [PATCH 1/9] dt-bindings: net: cdns,macb: Add compatible for Raspberry Pi RP1 The Raspberry Pi RP1 chip has the Cadence GEM ethernet controller, so add a compatible string for it. Signed-off-by: Dave Stevenson --- Documentation/devicetree/bindings/net/cdns,macb.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/net/cdns,macb.yaml b/Documentation/devicetree/bindings/net/cdns,macb.yaml index a9edfe6c125409..63a3be1581e1ce 100644 --- a/Documentation/devicetree/bindings/net/cdns,macb.yaml +++ b/Documentation/devicetree/bindings/net/cdns,macb.yaml @@ -54,6 +54,7 @@ properties: - cdns,np4-macb # NP4 SoC devices - microchip,sama7g5-emac # Microchip SAMA7G5 ethernet interface - microchip,sama7g5-gem # Microchip SAMA7G5 gigabit ethernet interface + - raspberrypi,rp1-gem # Raspberry Pi RP1 gigabit ethernet interface - sifive,fu540-c000-gem # SiFive FU540-C000 SoC - cdns,emac # Generic - cdns,gem # Generic From 7502d70426167d4f506d03becc0b4730459b1c70 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 11 Nov 2024 16:40:07 +0000 Subject: [PATCH 2/9] net: macb: Add support for Raspberry Pi RP1 ethernet controller The RP1 chip has the Cadence GEM block, but wants the tx_clock to always run at 125MHz, in the same way as sama7g5. Add the relevant configuration. Signed-off-by: Dave Stevenson --- drivers/net/ethernet/cadence/macb_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 0f9080371c4eee..acff4a4e79333d 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -5023,6 +5023,17 @@ static const struct macb_config versal_config = { .usrio = &macb_default_usrio, }; +static const struct macb_config raspberrypi_rp1_config = { + .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_CLK_HW_CHG | + MACB_CAPS_JUMBO | + MACB_CAPS_GEM_HAS_PTP, + .dma_burst_length = 16, + .clk_init = macb_clk_init, + .init = macb_init, + .usrio = &macb_default_usrio, + .jumbo_max_len = 10240, +}; + static const struct of_device_id macb_dt_ids[] = { { .compatible = "cdns,at91sam9260-macb", .data = &at91sam9260_config }, { .compatible = "cdns,macb" }, @@ -5043,6 +5054,7 @@ static const struct of_device_id macb_dt_ids[] = { { .compatible = "microchip,mpfs-macb", .data = &mpfs_config }, { .compatible = "microchip,sama7g5-gem", .data = &sama7g5_gem_config }, { .compatible = "microchip,sama7g5-emac", .data = &sama7g5_emac_config }, + { .compatible = "raspberrypi,rp1-gem", .data = &raspberrypi_rp1_config }, { .compatible = "xlnx,zynqmp-gem", .data = &zynqmp_config}, { .compatible = "xlnx,zynq-gem", .data = &zynq_config }, { .compatible = "xlnx,versal-gem", .data = &versal_config}, From 944f61638264b0bf5b388e53948ebf1729768d54 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 25 Nov 2024 12:30:06 +0000 Subject: [PATCH 3/9] rp1: clk: Only set PLL_SEC_RST in rp1_pll_divider_off Rather than clearing all the bits in rp1_pll_divider_off and setting PLL_SEC_RST, retain the status of all the other bits. Signed-off-by: Dave Stevenson --- drivers/clk/clk-rp1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-rp1.c b/drivers/clk/clk-rp1.c index ae383588063ae9..a1419844da4017 100644 --- a/drivers/clk/clk-rp1.c +++ b/drivers/clk/clk-rp1.c @@ -927,7 +927,8 @@ static void rp1_pll_divider_off(struct clk_hw *hw) const struct rp1_pll_data *data = divider->data; spin_lock(&clockman->regs_lock); - clockman_write(clockman, data->ctrl_reg, PLL_SEC_RST); + clockman_write(clockman, data->ctrl_reg, + clockman_read(clockman, data->ctrl_reg) | PLL_SEC_RST); spin_unlock(&clockman->regs_lock); } From 4a9e687a2da5c57aca2b85ebeb48d99ba656e41f Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Fri, 8 Nov 2024 17:36:13 +0000 Subject: [PATCH 4/9] rp1: clk: Rationalise the use of the CLK_IS_CRITICAL flag The clock setup had been copied from clk-bcm2835 which had to cope with the firmware having configured clocks, so there were flags of CLK_IS_CRITICAL and CLK_IGNORE_UNUSED dotted around. That isn't the situation with RP1 where only the main PLLs, CLK_SYS, and CLK_SLOW_SYS are critical, so update the configuration to match. Signed-off-by: Dave Stevenson --- drivers/clk/clk-rp1.c | 41 ++++++----------------------------------- 1 file changed, 6 insertions(+), 35 deletions(-) diff --git a/drivers/clk/clk-rp1.c b/drivers/clk/clk-rp1.c index a1419844da4017..65ff2a6bc822e1 100644 --- a/drivers/clk/clk-rp1.c +++ b/drivers/clk/clk-rp1.c @@ -1504,8 +1504,6 @@ static const struct clk_ops rp1_varsrc_ops = { .round_rate = rp1_varsrc_round_rate, }; -static bool rp1_clk_is_claimed(const char *name); - static struct clk_hw *rp1_register_pll_core(struct rp1_clockman *clockman, const void *data) { @@ -1521,7 +1519,7 @@ static struct clk_hw *rp1_register_pll_core(struct rp1_clockman *clockman, init.num_parents = 1; init.name = pll_core_data->name; init.ops = &rp1_pll_core_ops; - init.flags = pll_core_data->flags | CLK_IGNORE_UNUSED | CLK_IS_CRITICAL; + init.flags = pll_core_data->flags | CLK_IS_CRITICAL; pll_core = kzalloc(sizeof(*pll_core), GFP_KERNEL); if (!pll_core) @@ -1554,7 +1552,7 @@ static struct clk_hw *rp1_register_pll(struct rp1_clockman *clockman, init.num_parents = 1; init.name = pll_data->name; init.ops = &rp1_pll_ops; - init.flags = pll_data->flags | CLK_IGNORE_UNUSED | CLK_IS_CRITICAL; + init.flags = pll_data->flags | CLK_IGNORE_UNUSED; pll = kzalloc(sizeof(*pll), GFP_KERNEL); if (!pll) @@ -1635,11 +1633,6 @@ static struct clk_hw *rp1_register_pll_divider(struct rp1_clockman *clockman, divider->div.hw.init = &init; divider->div.table = pll_sec_div_table; - if (!rp1_clk_is_claimed(divider_data->source_pll)) - init.flags |= CLK_IS_CRITICAL; - if (!rp1_clk_is_claimed(divider_data->name)) - divider->div.flags |= CLK_IS_CRITICAL; - divider->clockman = clockman; divider->data = divider_data; @@ -1861,6 +1854,8 @@ static const struct rp1_clk_desc clk_desc_array[] = { .max_freq = 200 * MHz, .fc0_src = FC_NUM(0, 4), .clk_src_mask = 0x3, + /* Always enabled in hardware */ + .flags = CLK_IS_CRITICAL, ), [RP1_CLK_SLOW_SYS] = REGISTER_CLK( @@ -1875,6 +1870,8 @@ static const struct rp1_clk_desc clk_desc_array[] = { .max_freq = 50 * MHz, .fc0_src = FC_NUM(1, 4), .clk_src_mask = 0x1, + /* Always enabled in hardware */ + .flags = CLK_IS_CRITICAL, ), [RP1_CLK_UART] = REGISTER_CLK( @@ -2394,24 +2391,6 @@ static const struct rp1_clk_desc clk_desc_array[] = { [RP1_CLK_MIPI1_DSI_BYTECLOCK] = REGISTER_VARSRC("clksrc_mipi1_dsi_byteclk"), }; -static bool rp1_clk_claimed[ARRAY_SIZE(clk_desc_array)]; - -static bool rp1_clk_is_claimed(const char *name) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(clk_desc_array); i++) { - if (clk_desc_array[i].data) { - const char *clk_name = *(const char **)(clk_desc_array[i].data); - - if (!strcmp(name, clk_name)) - return rp1_clk_claimed[i]; - } - } - - return false; -} - static int rp1_clk_probe(struct platform_device *pdev) { const struct rp1_clk_desc *desc; @@ -2422,7 +2401,6 @@ static int rp1_clk_probe(struct platform_device *pdev) const size_t asize = ARRAY_SIZE(clk_desc_array); u32 chip_id, platform; unsigned int i; - u32 clk_id; int ret; clockman = devm_kzalloc(dev, struct_size(clockman, onecell.hws, asize), @@ -2439,13 +2417,6 @@ static int rp1_clk_probe(struct platform_device *pdev) if (IS_ERR(clockman->regs)) return PTR_ERR(clockman->regs); - memset(rp1_clk_claimed, 0, sizeof(rp1_clk_claimed)); - for (i = 0; - !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks", - i, &clk_id); - i++) - rp1_clk_claimed[clk_id] = true; - platform_set_drvdata(pdev, clockman); clockman->onecell.num = asize; From 325a73a8b446dd7d4dd6d11e010e9fcb3f5ac7ad Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 11 Nov 2024 15:18:14 +0000 Subject: [PATCH 5/9] dt: arm64: Fixup RP1 ethernet DT configuration Configure RP1's ethernet block to do the correct thing. clk_eth is intended to be fixed at 125MHz, so use a new compatible, and use assigned-clocks to configure the clock appropriately. Signed-off-by: Dave Stevenson --- arch/arm64/boot/dts/broadcom/rp1.dtsi | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/broadcom/rp1.dtsi b/arch/arm64/boot/dts/broadcom/rp1.dtsi index 73d517ad219057..065308e9aa08e2 100644 --- a/arch/arm64/boot/dts/broadcom/rp1.dtsi +++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi @@ -32,6 +32,7 @@ // RP1_PLL_VIDEO_CORE and dividers are now managed by VEC,DPI drivers <&rp1_clocks RP1_PLL_SYS>, <&rp1_clocks RP1_PLL_SYS_SEC>, + <&rp1_clocks RP1_CLK_ETH>, <&rp1_clocks RP1_PLL_AUDIO>, <&rp1_clocks RP1_PLL_AUDIO_SEC>, <&rp1_clocks RP1_CLK_SYS>, @@ -46,6 +47,7 @@ <1536000000>, // RP1_PLL_AUDIO_CORE <200000000>, // RP1_PLL_SYS <125000000>, // RP1_PLL_SYS_SEC + <125000000>, // RP1_CLK_ETH <61440000>, // RP1_PLL_AUDIO <192000000>, // RP1_PLL_AUDIO_SEC <200000000>, // RP1_CLK_SYS @@ -976,12 +978,14 @@ rp1_eth: ethernet@100000 { reg = <0xc0 0x40100000 0x0 0x4000>; - compatible = "cdns,macb"; + compatible = "raspberrypi,rp1-gem", "cdns,macb"; #address-cells = <1>; #size-cells = <0>; interrupts = ; - clocks = <&macb_pclk &macb_hclk &rp1_clocks RP1_CLK_ETH_TSU>; - clock-names = "pclk", "hclk", "tsu_clk"; + clocks = <&macb_pclk &macb_hclk + &rp1_clocks RP1_CLK_ETH_TSU + &rp1_clocks RP1_CLK_ETH>; + clock-names = "pclk", "hclk", "tsu_clk", "tx_clk"; phy-mode = "rgmii-id"; cdns,aw2w-max-pipe = /bits/ 8 <8>; cdns,ar2r-max-pipe = /bits/ 8 <8>; From 95642ab50c249e516146cbba3098bd015bfc5a53 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 13 Nov 2024 13:10:27 +0000 Subject: [PATCH 6/9] clk: rp1: Add RP1_CLK_DMA. The DMA block has a clock, but wasn't defined in the driver. This resulted in the parent being disabled as unused, and then DMA stopped working. Signed-off-by: Dave Stevenson --- drivers/clk/clk-rp1.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/clk/clk-rp1.c b/drivers/clk/clk-rp1.c index 65ff2a6bc822e1..3afc089c3a8838 100644 --- a/drivers/clk/clk-rp1.c +++ b/drivers/clk/clk-rp1.c @@ -1874,6 +1874,27 @@ static const struct rp1_clk_desc clk_desc_array[] = { .flags = CLK_IS_CRITICAL, ), + [RP1_CLK_DMA] = REGISTER_CLK( + .name = "clk_dma", + .parents = {"pll_sys_pri_ph", + "pll_video", + "xosc", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5"}, + .num_std_parents = 0, + .num_aux_parents = 9, + .ctrl_reg = CLK_DMA_CTRL, + .div_int_reg = CLK_DMA_DIV_INT, + .sel_reg = CLK_DMA_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 100 * MHz, + .fc0_src = FC_NUM(2, 2), + ), + [RP1_CLK_UART] = REGISTER_CLK( .name = "clk_uart", .parents = {"pll_sys_pri_ph", From 31993fda95b74158322e0a6ae71c2913391685e1 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Fri, 8 Nov 2024 17:37:08 +0000 Subject: [PATCH 7/9] rp1: clk: Remove CLK_IGNORE_UNUSED flags There should be no issue in disabling the RP1 clocks as long as the kernel knows about all consumers. Signed-off-by: Dave Stevenson --- drivers/clk/clk-rp1.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-rp1.c b/drivers/clk/clk-rp1.c index 3afc089c3a8838..3ae2f51d4771dd 100644 --- a/drivers/clk/clk-rp1.c +++ b/drivers/clk/clk-rp1.c @@ -1552,7 +1552,7 @@ static struct clk_hw *rp1_register_pll(struct rp1_clockman *clockman, init.num_parents = 1; init.name = pll_data->name; init.ops = &rp1_pll_ops; - init.flags = pll_data->flags | CLK_IGNORE_UNUSED; + init.flags = pll_data->flags; pll = kzalloc(sizeof(*pll), GFP_KERNEL); if (!pll) @@ -1586,7 +1586,7 @@ static struct clk_hw *rp1_register_pll_ph(struct rp1_clockman *clockman, init.num_parents = 1; init.name = ph_data->name; init.ops = &rp1_pll_ph_ops; - init.flags = ph_data->flags | CLK_IGNORE_UNUSED; + init.flags = ph_data->flags; ph = kzalloc(sizeof(*ph), GFP_KERNEL); if (!ph) @@ -1619,7 +1619,7 @@ static struct clk_hw *rp1_register_pll_divider(struct rp1_clockman *clockman, init.num_parents = 1; init.name = divider_data->name; init.ops = &rp1_pll_divider_ops; - init.flags = divider_data->flags | CLK_IGNORE_UNUSED; + init.flags = divider_data->flags; divider = devm_kzalloc(clockman->dev, sizeof(*divider), GFP_KERNEL); if (!divider) @@ -1662,7 +1662,7 @@ static struct clk_hw *rp1_register_clock(struct rp1_clockman *clockman, init.num_parents = clock_data->num_std_parents + clock_data->num_aux_parents; init.name = clock_data->name; - init.flags = clock_data->flags | CLK_IGNORE_UNUSED; + init.flags = clock_data->flags; init.ops = &rp1_clk_ops; clock = devm_kzalloc(clockman->dev, sizeof(*clock), GFP_KERNEL); @@ -1692,7 +1692,6 @@ static struct clk_hw *rp1_register_varsrc(struct rp1_clockman *clockman, init.parent_names = &ref_clock; init.num_parents = 1; init.name = name; - init.flags = CLK_IGNORE_UNUSED; init.ops = &rp1_varsrc_ops; clock = devm_kzalloc(clockman->dev, sizeof(*clock), GFP_KERNEL); From 2ade9283493fc585080494aa0fa22ba2a6149dd3 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 11 Nov 2024 17:11:18 +0000 Subject: [PATCH 8/9] dt: rp1: Use clk_sys for ethernet hclk and pclk hclk and pclk of the MAC are connected to clk_sys, so define them as being connected accordingly, rather than having fake fixed clocks for them. Signed-off-by: Dave Stevenson --- arch/arm64/boot/dts/broadcom/rp1.dtsi | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/arch/arm64/boot/dts/broadcom/rp1.dtsi b/arch/arm64/boot/dts/broadcom/rp1.dtsi index 065308e9aa08e2..26d85792bfaa56 100644 --- a/arch/arm64/boot/dts/broadcom/rp1.dtsi +++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi @@ -982,7 +982,8 @@ #address-cells = <1>; #size-cells = <0>; interrupts = ; - clocks = <&macb_pclk &macb_hclk + clocks = <&rp1_clocks RP1_CLK_SYS + &rp1_clocks RP1_CLK_SYS &rp1_clocks RP1_CLK_ETH_TSU &rp1_clocks RP1_CLK_ETH>; clock-names = "pclk", "hclk", "tsu_clk", "tx_clk"; @@ -1230,18 +1231,6 @@ clock-output-names = "xosc"; clock-frequency = <50000000>; }; - macb_pclk: macb_pclk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-output-names = "pclk"; - clock-frequency = <200000000>; - }; - macb_hclk: macb_hclk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-output-names = "hclk"; - clock-frequency = <200000000>; - }; sdio_src: sdio_src { // 400 MHz on FPGA. PLL sys VCO on asic compatible = "fixed-clock"; From 56a949d9dc4c942915383a9540a87224d1b53c8c Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 13 Nov 2024 13:11:33 +0000 Subject: [PATCH 9/9] dt: rp1: Link RP1 DMA to the associated clock This makes the kernel representation of the clock structure match reality. Signed-off-by: Dave Stevenson --- arch/arm64/boot/dts/broadcom/rp1.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/broadcom/rp1.dtsi b/arch/arm64/boot/dts/broadcom/rp1.dtsi index 26d85792bfaa56..605fc6b350c006 100644 --- a/arch/arm64/boot/dts/broadcom/rp1.dtsi +++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi @@ -1081,7 +1081,7 @@ reg = <0xc0 0x40188000 0x0 0x1000>; compatible = "snps,axi-dma-1.01a"; interrupts = ; - clocks = <&sdhci_core &rp1_clocks RP1_CLK_SYS>; + clocks = <&rp1_clocks RP1_CLK_DMA &rp1_clocks RP1_CLK_SYS>; clock-names = "core-clk", "cfgr-clk"; #dma-cells = <1>;