From d4638642aa0a2b39d6f7666538c7df073f67aadb Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Thu, 5 Jan 2023 16:22:54 +0100 Subject: [PATCH 1/6] clk: renesas: r9a06g032: Handle h2mode setting based on USBF presence The CFG_USB[H2MODE] allows to switch the USB configuration. The configuration supported are: - One host and one device or - Two hosts Set CFG_USB[H2MODE] based on the USBF controller (USB device) availability. Signed-off-by: Herve Codina Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230105152257.310642-3-herve.codina@bootlin.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a06g032-clocks.c | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c index 983faa5707b9..087146f2ee06 100644 --- a/drivers/clk/renesas/r9a06g032-clocks.c +++ b/drivers/clk/renesas/r9a06g032-clocks.c @@ -25,6 +25,8 @@ #include #include +#define R9A06G032_SYSCTRL_USB 0x00 +#define R9A06G032_SYSCTRL_USB_H2MODE (1<<1) #define R9A06G032_SYSCTRL_DMAMUX 0xA0 struct r9a06g032_gate { @@ -918,6 +920,29 @@ static void r9a06g032_clocks_del_clk_provider(void *data) of_clk_del_provider(data); } +static void __init r9a06g032_init_h2mode(struct r9a06g032_priv *clocks) +{ + struct device_node *usbf_np = NULL; + u32 usb; + + while ((usbf_np = of_find_compatible_node(usbf_np, NULL, + "renesas,rzn1-usbf"))) { + if (of_device_is_available(usbf_np)) + break; + } + + usb = readl(clocks->reg + R9A06G032_SYSCTRL_USB); + if (usbf_np) { + /* 1 host and 1 device mode */ + usb &= ~R9A06G032_SYSCTRL_USB_H2MODE; + of_node_put(usbf_np); + } else { + /* 2 hosts mode */ + usb |= R9A06G032_SYSCTRL_USB_H2MODE; + } + writel(usb, clocks->reg + R9A06G032_SYSCTRL_USB); +} + static int __init r9a06g032_clocks_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -947,6 +972,9 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev) clocks->reg = of_iomap(np, 0); if (WARN_ON(!clocks->reg)) return -ENOMEM; + + r9a06g032_init_h2mode(clocks); + for (i = 0; i < ARRAY_SIZE(r9a06g032_clocks); ++i) { const struct r9a06g032_clkdesc *d = &r9a06g032_clocks[i]; const char *parent_name = d->source ? From 1c052043c79af5f70e80e2acd4dd70904ae08666 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 11 Jan 2023 09:23:34 +0100 Subject: [PATCH 2/6] clk: renesas: cpg-mssr: Remove superfluous check in resume code When the code flow arrives at printing the error message in cpg_mssr_resume_noirq(), we know for sure that we are not running on an RZ/A Soc, as the code checked for that before. Fixes: ace342097768e35f ("clk: renesas: cpg-mssr: Fix STBCR suspend/resume handling") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/144a3e66d748c0c17f3524ac8fa6ece5bf5b6f1e.1673425314.git.geert+renesas@glider.be --- drivers/clk/renesas/renesas-cpg-mssr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 5dce9779324d..202aeb232044 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -943,9 +943,8 @@ static int cpg_mssr_resume_noirq(struct device *dev) } if (!i) - dev_warn(dev, "Failed to enable %s%u[0x%x]\n", - priv->reg_layout == CLK_REG_LAYOUT_RZ_A ? - "STB" : "SMSTP", reg, oldval & mask); + dev_warn(dev, "Failed to enable SMSTP%u[0x%x]\n", reg, + oldval & mask); } return 0; From 584d29912db27e56eaaccd225e283e1f429e4f83 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 8 Dec 2022 10:56:58 +0100 Subject: [PATCH 3/6] clk: renesas: r8a779g0: Add custom clock for PLL2 Currently the PLLs are modeled as fixed factor clocks, based on initial settings. However, enabling CPU boost clock rates requires increasing the PLL clock rates. Add a custom clock driver to model the PLL clocks on R-Car Gen4, and use it for PLL2 on R-Car V4H. This allows the Z clock (Cortex-A76 core clock) to request PLL rate changes, and enable boost mode for the High Performance mode. For now this is limited to integer multiplication modes. Note that the definition for CPG_PLLxCR0_NI uses the value for R-Car V4H. On R-Car S4-8, the integer and fractional multiplication fields are one bit larger resp. smaller, but R-Car S4-8 does not support High Performance mode. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/76a5952900a6e15604c640bc8a27762e0e936677.1670492384.git.geert+renesas@glider.be --- drivers/clk/renesas/r8a779g0-cpg-mssr.c | 14 +-- drivers/clk/renesas/rcar-gen4-cpg.c | 156 ++++++++++++++++++++++++ drivers/clk/renesas/rcar-gen4-cpg.h | 1 + 3 files changed, 164 insertions(+), 7 deletions(-) diff --git a/drivers/clk/renesas/r8a779g0-cpg-mssr.c b/drivers/clk/renesas/r8a779g0-cpg-mssr.c index 745ff9214fe8..48d9f34bbf37 100644 --- a/drivers/clk/renesas/r8a779g0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c @@ -66,13 +66,13 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = { DEF_INPUT("extalr", CLK_EXTALR), /* Internal Core Clocks */ - DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN4_MAIN, CLK_EXTAL), - DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN4_PLL1, CLK_MAIN), - DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN4_PLL2, CLK_MAIN), - DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN4_PLL3, CLK_MAIN), - DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN4_PLL4, CLK_MAIN), - DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN), - DEF_BASE(".pll6", CLK_PLL6, CLK_TYPE_GEN4_PLL6, CLK_MAIN), + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN4_MAIN, CLK_EXTAL), + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN4_PLL1, CLK_MAIN), + DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN4_PLL2_VAR, CLK_MAIN), + DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN4_PLL3, CLK_MAIN), + DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN4_PLL4, CLK_MAIN), + DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN), + DEF_BASE(".pll6", CLK_PLL6, CLK_TYPE_GEN4_PLL6, CLK_MAIN), DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 2, 1), diff --git a/drivers/clk/renesas/rcar-gen4-cpg.c b/drivers/clk/renesas/rcar-gen4-cpg.c index e27832e5114f..c68d8b987054 100644 --- a/drivers/clk/renesas/rcar-gen4-cpg.c +++ b/drivers/clk/renesas/rcar-gen4-cpg.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "renesas-cpg-mssr.h" @@ -27,6 +28,152 @@ static const struct rcar_gen4_cpg_pll_config *cpg_pll_config __initdata; static unsigned int cpg_clk_extalr __initdata; static u32 cpg_mode __initdata; +#define CPG_PLLECR 0x0820 /* PLL Enable Control Register */ + +#define CPG_PLLECR_PLLST(n) BIT(8 + ((n) < 3 ? (n) - 1 : \ + (n) > 3 ? (n) + 1 : n)) /* PLLn Circuit Status */ + +#define CPG_PLL1CR0 0x830 /* PLLn Control Registers */ +#define CPG_PLL1CR1 0x8b0 +#define CPG_PLL2CR0 0x834 +#define CPG_PLL2CR1 0x8b8 +#define CPG_PLL3CR0 0x83c +#define CPG_PLL3CR1 0x8c0 +#define CPG_PLL4CR0 0x844 +#define CPG_PLL4CR1 0x8c8 +#define CPG_PLL6CR0 0x84c +#define CPG_PLL6CR1 0x8d8 + +#define CPG_PLLxCR0_KICK BIT(31) +#define CPG_PLLxCR0_NI GENMASK(27, 20) /* Integer mult. factor */ +#define CPG_PLLxCR0_SSMODE GENMASK(18, 16) /* PLL mode */ +#define CPG_PLLxCR0_SSMODE_FM BIT(18) /* Fractional Multiplication */ +#define CPG_PLLxCR0_SSMODE_DITH BIT(17) /* Frequency Dithering */ +#define CPG_PLLxCR0_SSMODE_CENT BIT(16) /* Center (vs. Down) Spread Dithering */ +#define CPG_PLLxCR0_SSFREQ GENMASK(14, 8) /* SSCG Modulation Frequency */ +#define CPG_PLLxCR0_SSDEPT GENMASK(6, 0) /* SSCG Modulation Depth */ + +#define SSMODE_FM BIT(2) /* Fractional Multiplication */ +#define SSMODE_DITHER BIT(1) /* Frequency Dithering */ +#define SSMODE_CENTER BIT(0) /* Center (vs. Down) Spread Dithering */ + +/* PLL Clocks */ +struct cpg_pll_clk { + struct clk_hw hw; + void __iomem *pllcr0_reg; + void __iomem *pllecr_reg; + u32 pllecr_pllst_mask; +}; + +#define to_pll_clk(_hw) container_of(_hw, struct cpg_pll_clk, hw) + +static unsigned long cpg_pll_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cpg_pll_clk *pll_clk = to_pll_clk(hw); + unsigned int mult; + + mult = FIELD_GET(CPG_PLLxCR0_NI, readl(pll_clk->pllcr0_reg)) + 1; + + return parent_rate * mult * 2; +} + +static int cpg_pll_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + unsigned int min_mult, max_mult, mult; + unsigned long prate; + + prate = req->best_parent_rate * 2; + min_mult = max(div64_ul(req->min_rate, prate), 1ULL); + max_mult = min(div64_ul(req->max_rate, prate), 256ULL); + if (max_mult < min_mult) + return -EINVAL; + + mult = DIV_ROUND_CLOSEST_ULL(req->rate, prate); + mult = clamp(mult, min_mult, max_mult); + + req->rate = prate * mult; + return 0; +} + +static int cpg_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct cpg_pll_clk *pll_clk = to_pll_clk(hw); + unsigned int mult; + u32 val; + + mult = DIV_ROUND_CLOSEST_ULL(rate, parent_rate * 2); + mult = clamp(mult, 1U, 256U); + + if (readl(pll_clk->pllcr0_reg) & CPG_PLLxCR0_KICK) + return -EBUSY; + + cpg_reg_modify(pll_clk->pllcr0_reg, CPG_PLLxCR0_NI, + FIELD_PREP(CPG_PLLxCR0_NI, mult - 1)); + + /* + * Set KICK bit in PLLxCR0 to update hardware setting and wait for + * clock change completion. + */ + cpg_reg_modify(pll_clk->pllcr0_reg, 0, CPG_PLLxCR0_KICK); + + /* + * Note: There is no HW information about the worst case latency. + * + * Using experimental measurements, it seems that no more than + * ~45 µs are needed, independently of the CPU rate. + * Since this value might be dependent on external xtal rate, pll + * rate or even the other emulation clocks rate, use 1000 as a + * "super" safe value. + */ + return readl_poll_timeout(pll_clk->pllecr_reg, val, + val & pll_clk->pllecr_pllst_mask, 0, 1000); +} + +static const struct clk_ops cpg_pll_clk_ops = { + .recalc_rate = cpg_pll_clk_recalc_rate, + .determine_rate = cpg_pll_clk_determine_rate, + .set_rate = cpg_pll_clk_set_rate, +}; + +static struct clk * __init cpg_pll_clk_register(const char *name, + const char *parent_name, + void __iomem *base, + unsigned int cr0_offset, + unsigned int cr1_offset, + unsigned int index) + +{ + struct cpg_pll_clk *pll_clk; + struct clk_init_data init = {}; + struct clk *clk; + + pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); + if (!pll_clk) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &cpg_pll_clk_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + + pll_clk->hw.init = &init; + pll_clk->pllcr0_reg = base + cr0_offset; + pll_clk->pllecr_reg = base + CPG_PLLECR; + pll_clk->pllecr_pllst_mask = CPG_PLLECR_PLLST(index); + + /* Disable Fractional Multiplication and Frequency Dithering */ + writel(0, base + cr1_offset); + cpg_reg_modify(pll_clk->pllcr0_reg, CPG_PLLxCR0_SSMODE, 0); + + clk = clk_register(NULL, &pll_clk->hw); + if (IS_ERR(clk)) + kfree(pll_clk); + + return clk; +} /* * Z0 Clock & Z1 Clock */ @@ -205,6 +352,15 @@ struct clk * __init rcar_gen4_cpg_clk_register(struct device *dev, div = cpg_pll_config->pll1_div; break; + case CLK_TYPE_GEN4_PLL2_VAR: + /* + * PLL2 is implemented as a custom clock, to change the + * multiplier when cpufreq changes between normal and boost + * modes. + */ + return cpg_pll_clk_register(core->name, __clk_get_name(parent), + base, CPG_PLL2CR0, CPG_PLL2CR1, 2); + case CLK_TYPE_GEN4_PLL2: mult = cpg_pll_config->pll2_mult; div = cpg_pll_config->pll2_div; diff --git a/drivers/clk/renesas/rcar-gen4-cpg.h b/drivers/clk/renesas/rcar-gen4-cpg.h index 0a0e3bdb3a66..006537e29e4e 100644 --- a/drivers/clk/renesas/rcar-gen4-cpg.h +++ b/drivers/clk/renesas/rcar-gen4-cpg.h @@ -13,6 +13,7 @@ enum rcar_gen4_clk_types { CLK_TYPE_GEN4_MAIN = CLK_TYPE_CUSTOM, CLK_TYPE_GEN4_PLL1, CLK_TYPE_GEN4_PLL2, + CLK_TYPE_GEN4_PLL2_VAR, CLK_TYPE_GEN4_PLL2X_3X, /* r8a779a0 only */ CLK_TYPE_GEN4_PLL3, CLK_TYPE_GEN4_PLL4, From c9baa3bbe909b8e4a263394afc80b5a499bd23c2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Jan 2023 01:52:16 +0000 Subject: [PATCH 4/6] clk: renesas: r8a779a0: Tidy up DMAC name on SYS-DMAC "sydm" is a bit name. Let's rename it to the common "sys-dmac". Signed-off-by: Kuninori Morimoto Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/87tu0nz3xr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index e02542ca24a0..fcc8279647a6 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -176,8 +176,8 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8), DEF_MOD("scif4", 705, R8A779A0_CLK_S1D8), DEF_MOD("sdhi0", 706, R8A779A0_CLK_SD0), - DEF_MOD("sydm1", 709, R8A779A0_CLK_S1D2), - DEF_MOD("sydm2", 710, R8A779A0_CLK_S1D2), + DEF_MOD("sys-dmac1", 709, R8A779A0_CLK_S1D2), + DEF_MOD("sys-dmac2", 710, R8A779A0_CLK_S1D2), DEF_MOD("tmu0", 713, R8A779A0_CLK_CL16MCK), DEF_MOD("tmu1", 714, R8A779A0_CLK_S1D4), DEF_MOD("tmu2", 715, R8A779A0_CLK_S1D4), From 3797edf94b51387cc97fc5773d3e3e11c8d10dd4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Jan 2023 01:51:59 +0000 Subject: [PATCH 5/6] clk: renesas: r8a779g0: Tidy up DMAC name on SYS-DMAC "sydm" is a bit name. Let's rename it to the common "sys-dmac". Signed-off-by: Kuninori Morimoto Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/87v8l3z3y8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779g0-cpg-mssr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/r8a779g0-cpg-mssr.c b/drivers/clk/renesas/r8a779g0-cpg-mssr.c index 48d9f34bbf37..2bb9dea025ac 100644 --- a/drivers/clk/renesas/r8a779g0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c @@ -192,8 +192,8 @@ static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = { DEF_MOD("scif3", 704, R8A779G0_CLK_SASYNCPERD4), DEF_MOD("scif4", 705, R8A779G0_CLK_SASYNCPERD4), DEF_MOD("sdhi", 706, R8A779G0_CLK_SD0), - DEF_MOD("sydm0", 709, R8A779G0_CLK_S0D6_PER), - DEF_MOD("sydm1", 710, R8A779G0_CLK_S0D6_PER), + DEF_MOD("sys-dmac0", 709, R8A779G0_CLK_S0D6_PER), + DEF_MOD("sys-dmac1", 710, R8A779G0_CLK_S0D6_PER), DEF_MOD("tmu0", 713, R8A779G0_CLK_SASYNCRT), DEF_MOD("tmu1", 714, R8A779G0_CLK_SASYNCPERD2), DEF_MOD("tmu2", 715, R8A779G0_CLK_SASYNCPERD2), From bd176e46e9c23f669b28630cc8f3fb1b89fd610e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 23 Jan 2023 19:31:24 +0100 Subject: [PATCH 6/6] clk: renesas: r8a779g0: Add CAN-FD clocks Add the CANFD core clock and the CANFD0 module clock, which are used by the CAN-FD Interface on the Renesas R-Car V4H (R8A779G0) SoC. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/a78f534bd80f170f3f1267f3270fdb3b7a73b5d4.1674498643.git.geert+renesas@glider.be --- drivers/clk/renesas/r8a779g0-cpg-mssr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/renesas/r8a779g0-cpg-mssr.c b/drivers/clk/renesas/r8a779g0-cpg-mssr.c index 2bb9dea025ac..7fca11204f74 100644 --- a/drivers/clk/renesas/r8a779g0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c @@ -145,6 +145,7 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = { DEF_FIXED("viobusd2", R8A779G0_CLK_VIOBUSD2, CLK_VIO, 2, 1), DEF_FIXED("vcbus", R8A779G0_CLK_VCBUS, CLK_VC, 1, 1), DEF_FIXED("vcbusd2", R8A779G0_CLK_VCBUSD2, CLK_VC, 2, 1), + DEF_DIV6P1("canfd", R8A779G0_CLK_CANFD, CLK_PLL5_DIV4, 0x878), DEF_FIXED("dsiref", R8A779G0_CLK_DSIREF, CLK_PLL5_DIV4, 48, 1), DEF_DIV6P1("dsiext", R8A779G0_CLK_DSIEXT, CLK_PLL5_DIV4, 0x884), @@ -163,6 +164,7 @@ static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = { DEF_MOD("avb0", 211, R8A779G0_CLK_S0D4_HSC), DEF_MOD("avb1", 212, R8A779G0_CLK_S0D4_HSC), DEF_MOD("avb2", 213, R8A779G0_CLK_S0D4_HSC), + DEF_MOD("canfd0", 328, R8A779G0_CLK_SASYNCPERD2), DEF_MOD("dis0", 411, R8A779G0_CLK_VIOBUSD2), DEF_MOD("dsitxlink0", 415, R8A779G0_CLK_VIOBUSD2), DEF_MOD("dsitxlink1", 416, R8A779G0_CLK_VIOBUSD2),