FILE
r9a09g077-cpg.c
File preview with syntax highlighting.
linux-6.19.14/drivers/clk/renesas/r9a09g077-cpg.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * r9a09g077 Clock Pulse Generator / Module Standby and Software Reset 4 * 5 * Copyright (C) 2025 Renesas Electronics Corp. 6 * 7 */ 8 9#include <linux/bitfield.h> 10#include <linux/clk-provider.h> 11#include <linux/device.h> 12#include <linux/init.h> 13#include <linux/kernel.h> 14 15#include <dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h> 16#include <dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h> 17#include "renesas-cpg-mssr.h" 18 19#define RZT2H_REG_BLOCK_SHIFT 11 20#define RZT2H_REG_OFFSET_MASK GENMASK(10, 0) 21#define RZT2H_REG_CONF(block, offset) (((block) << RZT2H_REG_BLOCK_SHIFT) | \ 22 ((offset) & RZT2H_REG_OFFSET_MASK)) 23 24#define RZT2H_REG_BLOCK(x) ((x) >> RZT2H_REG_BLOCK_SHIFT) 25#define RZT2H_REG_OFFSET(x) ((x) & RZT2H_REG_OFFSET_MASK) 26 27#define SCKCR RZT2H_REG_CONF(0, 0x00) 28#define SCKCR2 RZT2H_REG_CONF(1, 0x04) 29#define SCKCR3 RZT2H_REG_CONF(0, 0x08) 30 31#define OFFSET_MASK GENMASK(31, 20) 32#define SHIFT_MASK GENMASK(19, 12) 33#define WIDTH_MASK GENMASK(11, 8) 34 35#define CONF_PACK(offset, shift, width) \ 36 (FIELD_PREP_CONST(OFFSET_MASK, (offset)) | \ 37 FIELD_PREP_CONST(SHIFT_MASK, (shift)) | \ 38 FIELD_PREP_CONST(WIDTH_MASK, (width))) 39 40#define GET_SHIFT(val) FIELD_GET(SHIFT_MASK, val) 41#define GET_WIDTH(val) FIELD_GET(WIDTH_MASK, val) 42#define GET_REG_OFFSET(val) FIELD_GET(OFFSET_MASK, val) 43 44#define DIVCA55C0 CONF_PACK(SCKCR2, 8, 1) 45#define DIVCA55C1 CONF_PACK(SCKCR2, 9, 1) 46#define DIVCA55C2 CONF_PACK(SCKCR2, 10, 1) 47#define DIVCA55C3 CONF_PACK(SCKCR2, 11, 1) 48#define DIVCA55S CONF_PACK(SCKCR2, 12, 1) 49#define DIVSPI3ASYNC CONF_PACK(SCKCR2, 16, 2) 50#define DIVSCI5ASYNC CONF_PACK(SCKCR2, 18, 2) 51 52#define DIVSPI0ASYNC CONF_PACK(SCKCR3, 0, 2) 53#define DIVSPI1ASYNC CONF_PACK(SCKCR3, 2, 2) 54#define DIVSPI2ASYNC CONF_PACK(SCKCR3, 4, 2) 55#define DIVSCI0ASYNC CONF_PACK(SCKCR3, 6, 2) 56#define DIVSCI1ASYNC CONF_PACK(SCKCR3, 8, 2) 57#define DIVSCI2ASYNC CONF_PACK(SCKCR3, 10, 2) 58#define DIVSCI3ASYNC CONF_PACK(SCKCR3, 12, 2) 59#define DIVSCI4ASYNC CONF_PACK(SCKCR3, 14, 2) 60 61#define SEL_PLL CONF_PACK(SCKCR, 22, 1) 62 63enum rzt2h_clk_types { 64 CLK_TYPE_RZT2H_DIV = CLK_TYPE_CUSTOM, /* Clock with divider */ 65 CLK_TYPE_RZT2H_MUX, /* Clock with clock source selector */ 66}; 67 68#define DEF_DIV(_name, _id, _parent, _conf, _dtable) \ 69 DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_DIV, .conf = _conf, \ 70 .parent = _parent, .dtable = _dtable, .flag = 0) 71#define DEF_MUX(_name, _id, _conf, _parent_names, _num_parents, _mux_flags) \ 72 DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_MUX, .conf = _conf, \ 73 .parent_names = _parent_names, .num_parents = _num_parents, \ 74 .flag = 0, .mux_flags = _mux_flags) 75 76enum clk_ids { 77 /* Core Clock Outputs exported to DT */ 78 LAST_DT_CORE_CLK = R9A09G077_ETCLKE, 79 80 /* External Input Clocks */ 81 CLK_EXTAL, 82 83 /* Internal Core Clocks */ 84 CLK_LOCO, 85 CLK_PLL0, 86 CLK_PLL1, 87 CLK_PLL2, 88 CLK_PLL4, 89 CLK_SEL_CLK_PLL0, 90 CLK_SEL_CLK_PLL1, 91 CLK_SEL_CLK_PLL2, 92 CLK_SEL_CLK_PLL4, 93 CLK_PLL4D1, 94 CLK_SCI0ASYNC, 95 CLK_SCI1ASYNC, 96 CLK_SCI2ASYNC, 97 CLK_SCI3ASYNC, 98 CLK_SCI4ASYNC, 99 CLK_SCI5ASYNC, 100 CLK_SPI0ASYNC, 101 CLK_SPI1ASYNC, 102 CLK_SPI2ASYNC, 103 CLK_SPI3ASYNC, 104 105 /* Module Clocks */ 106 MOD_CLK_BASE, 107}; 108 109static const struct clk_div_table dtable_1_2[] = { 110 {0, 2}, 111 {1, 1}, 112 {0, 0}, 113}; 114 115static const struct clk_div_table dtable_24_25_30_32[] = { 116 {0, 32}, 117 {1, 30}, 118 {2, 25}, 119 {3, 24}, 120 {0, 0}, 121}; 122 123/* Mux clock tables */ 124 125static const char * const sel_clk_pll0[] = { ".loco", ".pll0" }; 126static const char * const sel_clk_pll1[] = { ".loco", ".pll1" }; 127static const char * const sel_clk_pll2[] = { ".loco", ".pll2" }; 128static const char * const sel_clk_pll4[] = { ".loco", ".pll4" }; 129 130static const struct cpg_core_clk r9a09g077_core_clks[] __initconst = { 131 /* External Clock Inputs */ 132 DEF_INPUT("extal", CLK_EXTAL), 133 134 /* Internal Core Clocks */ 135 DEF_RATE(".loco", CLK_LOCO, 1000 * 1000), 136 DEF_FIXED(".pll0", CLK_PLL0, CLK_EXTAL, 1, 48), 137 DEF_FIXED(".pll1", CLK_PLL1, CLK_EXTAL, 1, 40), 138 DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 1, 32), 139 DEF_FIXED(".pll4", CLK_PLL4, CLK_EXTAL, 1, 96), 140 141 DEF_MUX(".sel_clk_pll0", CLK_SEL_CLK_PLL0, SEL_PLL, 142 sel_clk_pll0, ARRAY_SIZE(sel_clk_pll0), CLK_MUX_READ_ONLY), 143 DEF_MUX(".sel_clk_pll1", CLK_SEL_CLK_PLL1, SEL_PLL, 144 sel_clk_pll1, ARRAY_SIZE(sel_clk_pll1), CLK_MUX_READ_ONLY), 145 DEF_MUX(".sel_clk_pll2", CLK_SEL_CLK_PLL2, SEL_PLL, 146 sel_clk_pll2, ARRAY_SIZE(sel_clk_pll2), CLK_MUX_READ_ONLY), 147 DEF_MUX(".sel_clk_pll4", CLK_SEL_CLK_PLL4, SEL_PLL, 148 sel_clk_pll4, ARRAY_SIZE(sel_clk_pll4), CLK_MUX_READ_ONLY), 149 150 DEF_FIXED(".pll4d1", CLK_PLL4D1, CLK_SEL_CLK_PLL4, 1, 1), 151 DEF_DIV(".sci0async", CLK_SCI0ASYNC, CLK_PLL4D1, DIVSCI0ASYNC, 152 dtable_24_25_30_32), 153 DEF_DIV(".sci1async", CLK_SCI1ASYNC, CLK_PLL4D1, DIVSCI1ASYNC, 154 dtable_24_25_30_32), 155 DEF_DIV(".sci2async", CLK_SCI2ASYNC, CLK_PLL4D1, DIVSCI2ASYNC, 156 dtable_24_25_30_32), 157 DEF_DIV(".sci3async", CLK_SCI3ASYNC, CLK_PLL4D1, DIVSCI3ASYNC, 158 dtable_24_25_30_32), 159 DEF_DIV(".sci4async", CLK_SCI4ASYNC, CLK_PLL4D1, DIVSCI4ASYNC, 160 dtable_24_25_30_32), 161 DEF_DIV(".sci5async", CLK_SCI5ASYNC, CLK_PLL4D1, DIVSCI5ASYNC, 162 dtable_24_25_30_32), 163 164 DEF_DIV(".spi0async", CLK_SPI0ASYNC, CLK_PLL4D1, DIVSPI0ASYNC, 165 dtable_24_25_30_32), 166 DEF_DIV(".spi1async", CLK_SPI1ASYNC, CLK_PLL4D1, DIVSPI1ASYNC, 167 dtable_24_25_30_32), 168 DEF_DIV(".spi2async", CLK_SPI2ASYNC, CLK_PLL4D1, DIVSPI2ASYNC, 169 dtable_24_25_30_32), 170 DEF_DIV(".spi3async", CLK_SPI3ASYNC, CLK_PLL4D1, DIVSPI3ASYNC, 171 dtable_24_25_30_32), 172 173 /* Core output clk */ 174 DEF_DIV("CA55C0", R9A09G077_CLK_CA55C0, CLK_SEL_CLK_PLL0, DIVCA55C0, 175 dtable_1_2), 176 DEF_DIV("CA55C1", R9A09G077_CLK_CA55C1, CLK_SEL_CLK_PLL0, DIVCA55C1, 177 dtable_1_2), 178 DEF_DIV("CA55C2", R9A09G077_CLK_CA55C2, CLK_SEL_CLK_PLL0, DIVCA55C2, 179 dtable_1_2), 180 DEF_DIV("CA55C3", R9A09G077_CLK_CA55C3, CLK_SEL_CLK_PLL0, DIVCA55C3, 181 dtable_1_2), 182 DEF_DIV("CA55S", R9A09G077_CLK_CA55S, CLK_SEL_CLK_PLL0, DIVCA55S, 183 dtable_1_2), 184 DEF_FIXED("PCLKGPTL", R9A09G077_CLK_PCLKGPTL, CLK_SEL_CLK_PLL1, 2, 1), 185 DEF_FIXED("PCLKH", R9A09G077_CLK_PCLKH, CLK_SEL_CLK_PLL1, 4, 1), 186 DEF_FIXED("PCLKM", R9A09G077_CLK_PCLKM, CLK_SEL_CLK_PLL1, 8, 1), 187 DEF_FIXED("PCLKL", R9A09G077_CLK_PCLKL, CLK_SEL_CLK_PLL1, 16, 1), 188 DEF_FIXED("PCLKAH", R9A09G077_CLK_PCLKAH, CLK_PLL4D1, 6, 1), 189 DEF_FIXED("PCLKAM", R9A09G077_CLK_PCLKAM, CLK_PLL4D1, 12, 1), 190 DEF_FIXED("SDHI_CLKHS", R9A09G077_SDHI_CLKHS, CLK_SEL_CLK_PLL2, 1, 1), 191 DEF_FIXED("USB_CLK", R9A09G077_USB_CLK, CLK_PLL4D1, 48, 1), 192 DEF_FIXED("ETCLKA", R9A09G077_ETCLKA, CLK_SEL_CLK_PLL1, 5, 1), 193 DEF_FIXED("ETCLKB", R9A09G077_ETCLKB, CLK_SEL_CLK_PLL1, 8, 1), 194 DEF_FIXED("ETCLKC", R9A09G077_ETCLKC, CLK_SEL_CLK_PLL1, 10, 1), 195 DEF_FIXED("ETCLKD", R9A09G077_ETCLKD, CLK_SEL_CLK_PLL1, 20, 1), 196 DEF_FIXED("ETCLKE", R9A09G077_ETCLKE, CLK_SEL_CLK_PLL1, 40, 1), 197}; 198 199static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = { 200 DEF_MOD("sci0fck", 8, CLK_SCI0ASYNC), 201 DEF_MOD("sci1fck", 9, CLK_SCI1ASYNC), 202 DEF_MOD("sci2fck", 10, CLK_SCI2ASYNC), 203 DEF_MOD("sci3fck", 11, CLK_SCI3ASYNC), 204 DEF_MOD("sci4fck", 12, CLK_SCI4ASYNC), 205 DEF_MOD("iic0", 100, R9A09G077_CLK_PCLKL), 206 DEF_MOD("iic1", 101, R9A09G077_CLK_PCLKL), 207 DEF_MOD("spi0", 104, CLK_SPI0ASYNC), 208 DEF_MOD("spi1", 105, CLK_SPI1ASYNC), 209 DEF_MOD("spi2", 106, CLK_SPI2ASYNC), 210 DEF_MOD("adc0", 206, R9A09G077_CLK_PCLKH), 211 DEF_MOD("adc1", 207, R9A09G077_CLK_PCLKH), 212 DEF_MOD("adc2", 225, R9A09G077_CLK_PCLKM), 213 DEF_MOD("tsu", 307, R9A09G077_CLK_PCLKL), 214 DEF_MOD("gmac0", 400, R9A09G077_CLK_PCLKM), 215 DEF_MOD("ethsw", 401, R9A09G077_CLK_PCLKM), 216 DEF_MOD("ethss", 403, R9A09G077_CLK_PCLKM), 217 DEF_MOD("usb", 408, R9A09G077_CLK_PCLKAM), 218 DEF_MOD("gmac1", 416, R9A09G077_CLK_PCLKAM), 219 DEF_MOD("gmac2", 417, R9A09G077_CLK_PCLKAM), 220 DEF_MOD("sci5fck", 600, CLK_SCI5ASYNC), 221 DEF_MOD("iic2", 601, R9A09G077_CLK_PCLKL), 222 DEF_MOD("spi3", 602, CLK_SPI3ASYNC), 223 DEF_MOD("sdhi0", 1212, R9A09G077_CLK_PCLKAM), 224 DEF_MOD("sdhi1", 1213, R9A09G077_CLK_PCLKAM), 225}; 226 227static struct clk * __init 228r9a09g077_cpg_div_clk_register(struct device *dev, 229 const struct cpg_core_clk *core, 230 void __iomem *addr, struct cpg_mssr_pub *pub) 231{ 232 const struct clk *parent; 233 const char *parent_name; 234 struct clk_hw *clk_hw; 235 236 parent = pub->clks[core->parent]; 237 if (IS_ERR(parent)) 238 return ERR_CAST(parent); 239 240 parent_name = __clk_get_name(parent); 241 242 if (core->dtable) 243 clk_hw = devm_clk_hw_register_divider_table(dev, core->name, 244 parent_name, 245 CLK_SET_RATE_PARENT, 246 addr, 247 GET_SHIFT(core->conf), 248 GET_WIDTH(core->conf), 249 core->flag, 250 core->dtable, 251 &pub->rmw_lock); 252 else 253 clk_hw = devm_clk_hw_register_divider(dev, core->name, 254 parent_name, 255 CLK_SET_RATE_PARENT, 256 addr, 257 GET_SHIFT(core->conf), 258 GET_WIDTH(core->conf), 259 core->flag, &pub->rmw_lock); 260 261 if (IS_ERR(clk_hw)) 262 return ERR_CAST(clk_hw); 263 264 return clk_hw->clk; 265} 266 267static struct clk * __init 268r9a09g077_cpg_mux_clk_register(struct device *dev, 269 const struct cpg_core_clk *core, 270 void __iomem *addr, struct cpg_mssr_pub *pub) 271{ 272 struct clk_hw *clk_hw; 273 274 clk_hw = devm_clk_hw_register_mux(dev, core->name, 275 core->parent_names, core->num_parents, 276 core->flag, 277 addr, 278 GET_SHIFT(core->conf), 279 GET_WIDTH(core->conf), 280 core->mux_flags, &pub->rmw_lock); 281 if (IS_ERR(clk_hw)) 282 return ERR_CAST(clk_hw); 283 284 return clk_hw->clk; 285} 286 287static struct clk * __init 288r9a09g077_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, 289 const struct cpg_mssr_info *info, 290 struct cpg_mssr_pub *pub) 291{ 292 u32 offset = GET_REG_OFFSET(core->conf); 293 void __iomem *base = RZT2H_REG_BLOCK(offset) ? pub->base1 : pub->base0; 294 void __iomem *addr = base + RZT2H_REG_OFFSET(offset); 295 296 switch (core->type) { 297 case CLK_TYPE_RZT2H_DIV: 298 return r9a09g077_cpg_div_clk_register(dev, core, addr, pub); 299 case CLK_TYPE_RZT2H_MUX: 300 return r9a09g077_cpg_mux_clk_register(dev, core, addr, pub); 301 default: 302 return ERR_PTR(-EINVAL); 303 } 304} 305 306const struct cpg_mssr_info r9a09g077_cpg_mssr_info = { 307 /* Core Clocks */ 308 .core_clks = r9a09g077_core_clks, 309 .num_core_clks = ARRAY_SIZE(r9a09g077_core_clks), 310 .last_dt_core_clk = LAST_DT_CORE_CLK, 311 .num_total_core_clks = MOD_CLK_BASE, 312 313 /* Module Clocks */ 314 .mod_clks = r9a09g077_mod_clks, 315 .num_mod_clks = ARRAY_SIZE(r9a09g077_mod_clks), 316 .num_hw_mod_clks = 14 * 32, 317 318 .reg_layout = CLK_REG_LAYOUT_RZ_T2H, 319 .cpg_clk_register = r9a09g077_cpg_clk_register, 320};
~/
Read-only file preview.