|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
| 2 | +/* |
| 3 | + * RZ/G3L CPG driver |
| 4 | + * |
| 5 | + * Copyright (C) 2026 Renesas Electronics Corp. |
| 6 | + */ |
| 7 | + |
| 8 | +#include <linux/clk-provider.h> |
| 9 | +#include <linux/device.h> |
| 10 | +#include <linux/init.h> |
| 11 | +#include <linux/kernel.h> |
| 12 | + |
| 13 | +#include <dt-bindings/clock/renesas,r9a08g046-cpg.h> |
| 14 | + |
| 15 | +#include "rzg2l-cpg.h" |
| 16 | + |
| 17 | +/* RZ/G3L Specific registers. */ |
| 18 | +#define G3L_CPG_PL2_DDIV (0x204) |
| 19 | +#define G3L_CPG_PL3_DDIV (0x208) |
| 20 | +#define G3L_CLKDIVSTATUS (0x280) |
| 21 | + |
| 22 | +/* RZ/G3L Specific division configuration. */ |
| 23 | +#define G3L_DIVPL2A DDIV_PACK(G3L_CPG_PL2_DDIV, 0, 2) |
| 24 | +#define G3L_DIVPL2B DDIV_PACK(G3L_CPG_PL2_DDIV, 4, 2) |
| 25 | +#define G3L_DIVPL3A DDIV_PACK(G3L_CPG_PL3_DDIV, 0, 2) |
| 26 | + |
| 27 | +/* RZ/G3L Clock status configuration. */ |
| 28 | +#define G3L_DIVPL2A_STS DDIV_PACK(G3L_CLKDIVSTATUS, 4, 1) |
| 29 | +#define G3L_DIVPL2B_STS DDIV_PACK(G3L_CLKDIVSTATUS, 5, 1) |
| 30 | +#define G3L_DIVPL3A_STS DDIV_PACK(G3L_CLKDIVSTATUS, 8, 1) |
| 31 | + |
| 32 | +enum clk_ids { |
| 33 | + /* Core Clock Outputs exported to DT */ |
| 34 | + LAST_DT_CORE_CLK = R9A08G046_USB_SCLK, |
| 35 | + |
| 36 | + /* External Input Clocks */ |
| 37 | + CLK_EXTAL, |
| 38 | + CLK_ETH0_TXC_TX_CLK_IN, |
| 39 | + CLK_ETH0_RXC_RX_CLK_IN, |
| 40 | + CLK_ETH1_TXC_TX_CLK_IN, |
| 41 | + CLK_ETH1_RXC_RX_CLK_IN, |
| 42 | + |
| 43 | + /* Internal Core Clocks */ |
| 44 | + CLK_PLL2, |
| 45 | + CLK_PLL2_DIV2, |
| 46 | + CLK_PLL3, |
| 47 | + CLK_PLL3_DIV2, |
| 48 | + |
| 49 | + /* Module Clocks */ |
| 50 | + MOD_CLK_BASE, |
| 51 | +}; |
| 52 | + |
| 53 | +/* Divider tables */ |
| 54 | +static const struct clk_div_table dtable_4_128[] = { |
| 55 | + { 0, 4 }, |
| 56 | + { 1, 8 }, |
| 57 | + { 2, 16 }, |
| 58 | + { 3, 128 }, |
| 59 | + { 0, 0 }, |
| 60 | +}; |
| 61 | + |
| 62 | +static const struct clk_div_table dtable_8_256[] = { |
| 63 | + { 0, 8 }, |
| 64 | + { 1, 16 }, |
| 65 | + { 2, 32 }, |
| 66 | + { 3, 256 }, |
| 67 | + { 0, 0 }, |
| 68 | +}; |
| 69 | + |
| 70 | +static const struct cpg_core_clk r9a08g046_core_clks[] __initconst = { |
| 71 | + /* External Clock Inputs */ |
| 72 | + DEF_INPUT("extal", CLK_EXTAL), |
| 73 | + DEF_INPUT("eth0_txc_tx_clk", CLK_ETH0_TXC_TX_CLK_IN), |
| 74 | + DEF_INPUT("eth0_rxc_rx_clk", CLK_ETH0_RXC_RX_CLK_IN), |
| 75 | + DEF_INPUT("eth1_txc_tx_clk", CLK_ETH1_TXC_TX_CLK_IN), |
| 76 | + DEF_INPUT("eth1_rxc_rx_clk", CLK_ETH1_RXC_RX_CLK_IN), |
| 77 | + |
| 78 | + /* Internal Core Clocks */ |
| 79 | + DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3), |
| 80 | + DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3), |
| 81 | + DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2), |
| 82 | + DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2), |
| 83 | + |
| 84 | + /* Core output clk */ |
| 85 | + DEF_G3S_DIV("P0", R9A08G046_CLK_P0, CLK_PLL2_DIV2, G3L_DIVPL2B, G3L_DIVPL2B_STS, |
| 86 | + dtable_8_256, 0, 0, 0, NULL), |
| 87 | + DEF_G3S_DIV("P1", R9A08G046_CLK_P1, CLK_PLL3_DIV2, G3L_DIVPL3A, G3L_DIVPL3A_STS, |
| 88 | + dtable_4_128, 0, 0, 0, NULL), |
| 89 | + DEF_G3S_DIV("P3", R9A08G046_CLK_P3, CLK_PLL2_DIV2, G3L_DIVPL2A, G3L_DIVPL2A_STS, |
| 90 | + dtable_4_128, 0, 0, 0, NULL), |
| 91 | +}; |
| 92 | + |
| 93 | +static const struct rzg2l_mod_clk r9a08g046_mod_clks[] = { |
| 94 | + DEF_MOD("gic_gicclk", R9A08G046_GIC600_GICCLK, R9A08G046_CLK_P1, 0x514, 0, |
| 95 | + MSTOP(BUS_PERI_COM, BIT(12))), |
| 96 | + DEF_MOD("ia55_pclk", R9A08G046_IA55_PCLK, R9A08G046_CLK_P0, 0x518, 0, |
| 97 | + MSTOP(BUS_PERI_CPU, BIT(13))), |
| 98 | + DEF_MOD("ia55_clk", R9A08G046_IA55_CLK, R9A08G046_CLK_P1, 0x518, 1, |
| 99 | + MSTOP(BUS_PERI_CPU, BIT(13))), |
| 100 | + DEF_MOD("dmac_aclk", R9A08G046_DMAC_ACLK, R9A08G046_CLK_P3, 0x52c, 0, |
| 101 | + MSTOP(BUS_REG1, BIT(2))), |
| 102 | + DEF_MOD("dmac_pclk", R9A08G046_DMAC_PCLK, R9A08G046_CLK_P3, 0x52c, 1, |
| 103 | + MSTOP(BUS_REG1, BIT(3))), |
| 104 | + DEF_MOD("scif0_clk_pck", R9A08G046_SCIF0_CLK_PCK, R9A08G046_CLK_P0, 0x584, 0, |
| 105 | + MSTOP(BUS_MCPU2, BIT(1))), |
| 106 | +}; |
| 107 | + |
| 108 | +static const struct rzg2l_reset r9a08g046_resets[] = { |
| 109 | + DEF_RST(R9A08G046_GIC600_GICRESET_N, 0x814, 0), |
| 110 | + DEF_RST(R9A08G046_GIC600_DBG_GICRESET_N, 0x814, 1), |
| 111 | + DEF_RST(R9A08G046_IA55_RESETN, 0x818, 0), |
| 112 | + DEF_RST(R9A08G046_DMAC_ARESETN, 0x82c, 0), |
| 113 | + DEF_RST(R9A08G046_DMAC_RST_ASYNC, 0x82c, 1), |
| 114 | + DEF_RST(R9A08G046_SCIF0_RST_SYSTEM_N, 0x884, 0), |
| 115 | +}; |
| 116 | + |
| 117 | +static const unsigned int r9a08g046_crit_mod_clks[] __initconst = { |
| 118 | + MOD_CLK_BASE + R9A08G046_GIC600_GICCLK, |
| 119 | + MOD_CLK_BASE + R9A08G046_IA55_CLK, |
| 120 | + MOD_CLK_BASE + R9A08G046_DMAC_ACLK, |
| 121 | +}; |
| 122 | + |
| 123 | +static const unsigned int r9a08g046_crit_resets[] = { |
| 124 | + R9A08G046_DMAC_ARESETN, |
| 125 | + R9A08G046_DMAC_RST_ASYNC, |
| 126 | +}; |
| 127 | + |
| 128 | +const struct rzg2l_cpg_info r9a08g046_cpg_info = { |
| 129 | + /* Core Clocks */ |
| 130 | + .core_clks = r9a08g046_core_clks, |
| 131 | + .num_core_clks = ARRAY_SIZE(r9a08g046_core_clks), |
| 132 | + .last_dt_core_clk = LAST_DT_CORE_CLK, |
| 133 | + .num_total_core_clks = MOD_CLK_BASE, |
| 134 | + |
| 135 | + /* Critical Module Clocks */ |
| 136 | + .crit_mod_clks = r9a08g046_crit_mod_clks, |
| 137 | + .num_crit_mod_clks = ARRAY_SIZE(r9a08g046_crit_mod_clks), |
| 138 | + |
| 139 | + /* Module Clocks */ |
| 140 | + .mod_clks = r9a08g046_mod_clks, |
| 141 | + .num_mod_clks = ARRAY_SIZE(r9a08g046_mod_clks), |
| 142 | + .num_hw_mod_clks = R9A08G046_BSC_X_BCK_BSC + 1, |
| 143 | + |
| 144 | + /* Resets */ |
| 145 | + .resets = r9a08g046_resets, |
| 146 | + .num_resets = R9A08G046_BSC_X_PRESET_BSC + 1, /* Last reset ID + 1 */ |
| 147 | + |
| 148 | + /* Critical Resets */ |
| 149 | + .crit_resets = r9a08g046_crit_resets, |
| 150 | + .num_crit_resets = ARRAY_SIZE(r9a08g046_crit_resets), |
| 151 | + |
| 152 | + .has_clk_mon_regs = true, |
| 153 | +}; |
0 commit comments