1 /* $NetBSD: exynos5410_clock.c,v 1.11 2025/12/14 20:12:26 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 2015-2017 Jared McNeill <jmcneill (at) invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: exynos5410_clock.c,v 1.11 2025/12/14 20:12:26 skrll Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/bus.h> 34 #include <sys/device.h> 35 #include <sys/intr.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/atomic.h> 39 40 #include <dev/clk/clk_backend.h> 41 42 #include <arm/samsung/exynos_reg.h> 43 #include <arm/samsung/exynos_var.h> 44 #include <arm/samsung/exynos_clock.h> 45 46 #include <dev/fdt/fdtvar.h> 47 48 static struct clk *exynos5410_clock_decode(device_t, int, const void *, size_t); 49 50 static const struct fdtbus_clock_controller_func exynos5410_car_fdtclock_funcs = { 51 .decode = exynos5410_clock_decode 52 }; 53 54 /* DT clock ID to clock name mappings */ 55 static struct exynos5410_clock_id { 56 u_int id; 57 const char *name; 58 } exynos5410_clock_ids[] = { 59 /* core clocks */ 60 { 1, "fin_pll" }, 61 { 2, "fout_apll" }, 62 { 3, "fout_cpll" }, 63 { 4, "fout_mpll" }, 64 { 5, "fout_bpll" }, 65 { 6, "fout_kpll" }, 66 { 7, "fout_epll" }, 67 68 /* gate for special clocks (sclk) */ 69 { 128, "sclk_uart0" }, 70 { 129, "sclk_uart1" }, 71 { 130, "sclk_uart2" }, 72 { 131, "sclk_uart3" }, 73 { 132, "sclk_mmc0" }, 74 { 133, "sclk_mmc1" }, 75 { 134, "sclk_mmc2" }, 76 { 150, "sclk_usbd300" }, 77 { 151, "sclk_usbd301" }, 78 { 152, "sclk_usbphy300" }, 79 { 153, "sclk_usbphy301" }, 80 { 155, "sclk_pwm" }, 81 82 /* gate clocks */ 83 { 257, "uart0" }, 84 { 258, "uart1" }, 85 { 259, "uart2" }, 86 { 260, "uart3" }, 87 { 261, "i2c0" }, 88 { 262, "i2c1" }, 89 { 263, "i2c2" }, 90 { 264, "i2c3" }, 91 { 265, "usi0" }, 92 { 266, "usi1" }, 93 { 267, "usi2" }, 94 { 268, "usi3" }, 95 { 279, "pwm" }, 96 { 315, "mct" }, 97 { 316, "wdt" }, 98 { 317, "rtc" }, 99 { 318, "tmu" }, 100 { 351, "mmc0" }, 101 { 352, "mmc1" }, 102 { 353, "mmc2" }, 103 { 362, "pdma0" }, 104 { 363, "pdma1" }, 105 { 365, "usbh20" }, 106 { 366, "usbd300" }, 107 { 367, "usbd301" }, 108 { 471, "sss" }, 109 }; 110 111 #define PLL_2650XRATE(_r, _m, _k, _p, _s) \ 112 { \ 113 .pll_rate = (_r), \ 114 .pll_m = (_m), \ 115 .pll_k = (_k), \ 116 .pll_p = (_p), \ 117 .pll_s = (_s), \ 118 } 119 120 static const struct exynos_pll_rates { 121 u_int pll_rate; 122 uint16_t pll_m; 123 uint16_t pll_k; 124 uint16_t pll_p; 125 uint16_t pll_s; 126 } exynos5410_pll2650x_24mhz_rates[] = { 127 PLL_2650XRATE(400000000U, 200, 0, 3, 2), 128 PLL_2650XRATE(333000000U, 111, 0, 2, 2), 129 PLL_2650XRATE(300000000U, 100, 0, 2, 2), 130 PLL_2650XRATE(266000000U, 266, 0, 3, 3), 131 PLL_2650XRATE(200000000U, 200, 0, 3, 3), 132 PLL_2650XRATE(192000000U, 192, 0, 3, 3), 133 PLL_2650XRATE(166000000U, 166, 0, 3, 3), 134 PLL_2650XRATE(133000000U, 266, 0, 3, 4), 135 PLL_2650XRATE(100000000U, 200, 0, 3, 4), 136 PLL_2650XRATE(66000000U, 176, 0, 2, 5), 137 }; 138 139 static struct clk *exynos5410_clock_get(void *, const char *); 140 static void exynos5410_clock_put(void *, struct clk *); 141 static u_int exynos5410_clock_get_rate(void *, struct clk *); 142 static int exynos5410_clock_set_rate(void *, struct clk *, u_int); 143 static int exynos5410_clock_enable(void *, struct clk *); 144 static int exynos5410_clock_disable(void *, struct clk *); 145 static int exynos5410_clock_set_parent(void *, struct clk *, struct clk *); 146 static struct clk *exynos5410_clock_get_parent(void *, struct clk *); 147 148 static const struct clk_funcs exynos5410_clock_funcs = { 149 .get = exynos5410_clock_get, 150 .put = exynos5410_clock_put, 151 .get_rate = exynos5410_clock_get_rate, 152 .set_rate = exynos5410_clock_set_rate, 153 .enable = exynos5410_clock_enable, 154 .disable = exynos5410_clock_disable, 155 .set_parent = exynos5410_clock_set_parent, 156 .get_parent = exynos5410_clock_get_parent, 157 }; 158 159 #define CLK_FIXED(_name, _rate) { \ 160 .base = { .name = (_name) }, .type = EXYNOS_CLK_FIXED, \ 161 .u = { .fixed = { .rate = (_rate) } } \ 162 } 163 164 #define CLK_PLL35XX(_name, _parent, _lock, _con0) { \ 165 .base = { .name = (_name) }, \ 166 .type = EXYNOS_CLK_PLL35XX, \ 167 .parent = (_parent), \ 168 .u = { \ 169 .pll = { \ 170 .lock_reg = (_lock), \ 171 .con0_reg = (_con0), \ 172 } \ 173 } \ 174 } 175 176 #define CLK_PLL2650X(_name, _parent, _lock, _con0, _con1) { \ 177 .base = { .name = (_name) }, \ 178 .type = EXYNOS_CLK_PLL2650X, \ 179 .parent = (_parent), \ 180 .u = { \ 181 .pll = { \ 182 .lock_reg = (_lock), \ 183 .con0_reg = (_con0), \ 184 .con1_reg = (_con1), \ 185 } \ 186 } \ 187 } 188 189 #define CLK_MUXF(_name, _alias, _reg, _bits, _f, _p) { \ 190 .base = { .name = (_name), .flags = (_f) }, \ 191 .type = EXYNOS_CLK_MUX, \ 192 .alias = (_alias), \ 193 .u = { \ 194 .mux = { \ 195 .nparents = __arraycount(_p), \ 196 .parents = (_p), \ 197 .reg = (_reg), \ 198 .bits = (_bits) \ 199 } \ 200 } \ 201 } 202 203 #define CLK_MUXA(_name, _alias, _reg, _bits, _p) \ 204 CLK_MUXF(_name, _alias, _reg, _bits, 0, _p) 205 206 #define CLK_MUX(_name, _reg, _bits, _p) \ 207 CLK_MUXF(_name, NULL, _reg, _bits, 0, _p) 208 209 #define CLK_DIVF(_name, _parent, _reg, _bits, _f) { \ 210 .base = { .name = (_name), .flags = (_f) }, \ 211 .type = EXYNOS_CLK_DIV, \ 212 .parent = (_parent), \ 213 .u = { \ 214 .div = { \ 215 .reg = (_reg), \ 216 .bits = (_bits) \ 217 } \ 218 } \ 219 } 220 221 #define CLK_DIV(_name, _parent, _reg, _bits) \ 222 CLK_DIVF(_name, _parent, _reg, _bits, 0) 223 224 #define CLK_GATE(_name, _parent, _reg, _bits, _f) { \ 225 .base = { .name = (_name), .flags = (_f) }, \ 226 .type = EXYNOS_CLK_GATE, \ 227 .parent = (_parent), \ 228 .u = { \ 229 .gate = { \ 230 .reg = (_reg), \ 231 .bits = (_bits) \ 232 } \ 233 } \ 234 } 235 236 #define EXYNOS5410_APLL_LOCK 0x00000 237 #define EXYNOS5410_APLL_CON0 0x00100 238 #define EXYNOS5410_MPLL_LOCK 0x04000 239 #define EXYNOS5410_MPLL_CON0 0x04100 240 #define EXYNOS5410_CPLL_LOCK 0x10020 241 #define EXYNOS5410_EPLL_LOCK 0x10040 242 #define EXYNOS5410_CPLL_CON0 0x10120 243 #define EXYNOS5410_EPLL_CON0 0x10130 244 #define EXYNOS5410_EPLL_CON1 0x10134 245 #define EXYNOS5410_EPLL_CON2 0x10138 246 #define EXYNOS5410_BPLL_LOCK 0x20010 247 #define EXYNOS5410_BPLL_CON0 0x20110 248 #define EXYNOS5410_KPLL_LOCK 0x28000 249 #define EXYNOS5410_KPLL_CON0 0x28100 250 251 #define EXYNOS5410_SRC_CPU 0x00200 252 #define EXYNOS5410_SRC_CPERI1 0x04204 253 #define EXYNOS5410_SRC_TOP0 0x10210 254 #define EXYNOS5410_SRC_TOP1 0x10214 255 #define EXYNOS5410_SRC_TOP2 0x10218 256 #define EXYNOS5410_SRC_FSYS 0x10244 257 #define EXYNOS5410_SRC_PERIC0 0x10250 258 #define EXYNOS5410_SRC_MASK_FSYS 0x10340 259 #define EXYNOS5410_SRC_MASK_PERIC0 0x10350 260 #define EXYNOS5410_SRC_CDREX 0x20200 261 #define EXYNOS5410_SRC_KFC 0x28200 262 263 #define EXYNOS5410_DIV_CPU0 0x00500 264 #define EXYNOS5410_DIV_TOP0 0x10510 265 #define EXYNOS5410_DIV_TOP1 0x10514 266 #define EXYNOS5410_DIV_FSYS0 0x10548 267 #define EXYNOS5410_DIV_FSYS1 0x1054c 268 #define EXYNOS5410_DIV_FSYS2 0x10550 269 #define EXYNOS5410_DIV_PERIC0 0x10558 270 #define EXYNOS5410_DIV_PERIC3 0x10564 271 #define EXYNOS5410_DIV_KFC0 0x28500 272 273 #define EXYNOS5410_GATE_IP_G2D 0x08800 274 #define EXYNOS5410_GATE_BUS_FSYS0 0x10740 275 #define EXYNOS5410_GATE_TOP_SCLK_FSYS 0x10840 276 #define EXYNOS5410_GATE_TOP_SCLK_PERIC 0x10850 277 #define EXYNOS5410_GATE_IP_FSYS 0x10944 278 #define EXYNOS5410_GATE_IP_PERIC 0x10950 279 #define EXYNOS5410_GATE_IP_PERIS 0x10960 280 281 static const char *mout_apll_p[] = { "fin_pll", "fout_apll" }; 282 static const char *mout_bpll_p[] = { "fin_pll", "fout_bpll" }; 283 static const char *mout_cpll_p[] = { "fin_pll", "fout_cpll" }; 284 static const char *mout_epll_p[] = { "fin_pll", "fout_epll" }; 285 static const char *mout_mpll_p[] = { "fin_pll", "fout_mpll" }; 286 static const char *mout_kpll_p[] = { "fin_pll", "fout_kpll" }; 287 288 static const char *mout_cpu_p[] = { "mout_apll", "sclk_mpll" }; 289 static const char *mout_kfc_p[] = { "mout_kpll", "sclk_mpll" }; 290 291 static const char *mout_mpll_user_p[] = { "fin_pll", "sclk_mpll" }; 292 static const char *mout_bpll_user_p[] = { "fin_pll", "sclk_bpll" }; 293 static const char *mout_mpll_bpll_p[] = 294 { "sclk_mpll_muxed", "sclk_bpll_muxed" }; 295 static const char *mout_sclk_mpll_bpll_p[] = { "sclk_mpll_bpll", "fin_pll" }; 296 297 static const char *mout_group2_p[] = 298 { "fin_pll", "fin_pll", "none", "none", "none", "none", 299 "sclk_mpll_bpll", "none", "none", "sclk_cpll" }; 300 301 static struct exynos_clk exynos5410_clocks[] = { 302 CLK_FIXED("fin_pll", EXYNOS_F_IN_FREQ), 303 304 CLK_PLL35XX("fout_apll", "fin_pll", EXYNOS5410_APLL_LOCK, 305 EXYNOS5410_APLL_CON0), 306 CLK_PLL35XX("fout_bpll", "fin_pll", EXYNOS5410_BPLL_LOCK, 307 EXYNOS5410_BPLL_CON0), 308 CLK_PLL35XX("fout_cpll", "fin_pll", EXYNOS5410_CPLL_LOCK, 309 EXYNOS5410_CPLL_CON0), 310 CLK_PLL2650X("fout_epll", "fin_pll", EXYNOS5410_EPLL_LOCK, 311 EXYNOS5410_EPLL_CON0, 312 EXYNOS5410_EPLL_CON1), 313 CLK_PLL35XX("fout_mpll", "fin_pll", EXYNOS5410_MPLL_LOCK, 314 EXYNOS5410_MPLL_CON0), 315 CLK_PLL35XX("fout_kpll", "fin_pll", EXYNOS5410_KPLL_LOCK, 316 EXYNOS5410_KPLL_CON0), 317 318 CLK_MUX("mout_apll", EXYNOS5410_SRC_CPU, __BIT(0), mout_apll_p), 319 CLK_MUX("mout_cpu", EXYNOS5410_SRC_CPU, __BIT(16), mout_cpu_p), 320 CLK_MUX("mout_kpll", EXYNOS5410_SRC_KFC, __BIT(0), mout_kpll_p), 321 CLK_MUX("mout_kfc", EXYNOS5410_SRC_KFC, __BIT(16), mout_kfc_p), 322 323 CLK_MUX("sclk_mpll", EXYNOS5410_SRC_CPERI1, __BIT(8), mout_mpll_p), 324 CLK_MUX("sclk_mpll_muxed", EXYNOS5410_SRC_TOP2, __BIT(20), mout_mpll_user_p), 325 CLK_MUX("sclk_bpll", EXYNOS5410_SRC_CDREX, __BIT(0), mout_bpll_p), 326 CLK_MUX("sclk_bpll_muxed", EXYNOS5410_SRC_TOP2, __BIT(24), mout_bpll_user_p), 327 CLK_MUX("sclk_epll", EXYNOS5410_SRC_TOP2, __BIT(12), mout_epll_p), 328 CLK_MUX("sclk_cpll", EXYNOS5410_SRC_TOP2, __BIT(8), mout_cpll_p), 329 CLK_MUX("sclk_mpll_bpll", EXYNOS5410_SRC_TOP1, __BIT(20), mout_mpll_bpll_p), 330 331 CLK_MUX("mout_mmc0", EXYNOS5410_SRC_FSYS, __BITS(3,0), mout_group2_p), 332 CLK_MUX("mout_mmc1", EXYNOS5410_SRC_FSYS, __BITS(7,4), mout_group2_p), 333 CLK_MUX("mout_mmc2", EXYNOS5410_SRC_FSYS, __BITS(11,8), mout_group2_p), 334 CLK_MUX("mout_usbd300", EXYNOS5410_SRC_FSYS, __BIT(28), mout_sclk_mpll_bpll_p), 335 CLK_MUX("mout_usbd301", EXYNOS5410_SRC_FSYS, __BIT(29), mout_sclk_mpll_bpll_p), 336 CLK_MUX("mout_uart0", EXYNOS5410_SRC_PERIC0, __BITS(3,0), mout_group2_p), 337 CLK_MUX("mout_uart1", EXYNOS5410_SRC_PERIC0, __BITS(7,4), mout_group2_p), 338 CLK_MUX("mout_uart2", EXYNOS5410_SRC_PERIC0, __BITS(11,8), mout_group2_p), 339 CLK_MUX("mout_uart3", EXYNOS5410_SRC_PERIC0, __BITS(15,12), mout_group2_p), 340 CLK_MUX("mout_pwm", EXYNOS5410_SRC_PERIC0, __BITS(27,24), mout_group2_p), 341 CLK_MUX("mout_aclk200", EXYNOS5410_SRC_TOP0, __BIT(12), mout_mpll_bpll_p), 342 CLK_MUX("mout_aclk400", EXYNOS5410_SRC_TOP0, __BIT(20), mout_mpll_bpll_p), 343 344 CLK_DIV("div_arm", "mout_cpu", EXYNOS5410_DIV_CPU0, __BITS(2,0)), 345 CLK_DIV("div_arm2", "div_arm", EXYNOS5410_DIV_CPU0, __BITS(30,28)), 346 347 CLK_DIV("div_acp", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(10,8)), 348 CLK_DIV("div_cpud", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(6,4)), 349 CLK_DIV("div_atb", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(18,16)), 350 CLK_DIV("pclk_dbg", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(22,20)), 351 352 CLK_DIV("div_kfc", "mout_kfc", EXYNOS5410_DIV_KFC0, __BITS(2,0)), 353 CLK_DIV("div_aclk", "div_kfc", EXYNOS5410_DIV_KFC0, __BITS(6,4)), 354 CLK_DIV("div_pclk", "div_kfc", EXYNOS5410_DIV_KFC0, __BITS(22,20)), 355 356 CLK_DIV("aclk66_pre", "sclk_mpll_muxed", EXYNOS5410_DIV_TOP1, __BITS(26,24)), 357 CLK_DIV("aclk66", "aclk66_pre", EXYNOS5410_DIV_TOP0, __BITS(2,0)), 358 359 CLK_DIV("dout_usbphy300", "mout_usbd300", EXYNOS5410_DIV_FSYS0, __BITS(19,16)), 360 CLK_DIV("dout_usbphy301", "mout_usbd301", EXYNOS5410_DIV_FSYS0, __BITS(23,20)), 361 CLK_DIV("dout_usbd300", "mout_usbd300", EXYNOS5410_DIV_FSYS0, __BITS(27,24)), 362 CLK_DIV("dout_usbd301", "mout_usbd301", EXYNOS5410_DIV_FSYS0, __BITS(31,28)), 363 364 CLK_DIV("dout_mmc0", "mout_mmc0", EXYNOS5410_DIV_FSYS1, __BITS(3,0)), 365 CLK_DIV("dout_mmc1", "mout_mmc1", EXYNOS5410_DIV_FSYS1, __BITS(19,16)), 366 CLK_DIV("dout_mmc2", "mout_mmc2", EXYNOS5410_DIV_FSYS2, __BITS(3,0)), 367 368 CLK_DIVF("dout_mmc_pre0", "dout_mmc0", EXYNOS5410_DIV_FSYS1, __BITS(15,8), 369 CLK_SET_RATE_PARENT), 370 CLK_DIVF("dout_mmc_pre1", "dout_mmc1", EXYNOS5410_DIV_FSYS1, __BITS(31,24), 371 CLK_SET_RATE_PARENT), 372 CLK_DIVF("dout_mmc_pre2", "dout_mmc2", EXYNOS5410_DIV_FSYS2, __BITS(15,8), 373 CLK_SET_RATE_PARENT), 374 375 CLK_DIV("div_uart0", "mout_uart0", EXYNOS5410_DIV_PERIC0, __BITS(3,0)), 376 CLK_DIV("div_uart1", "mout_uart1", EXYNOS5410_DIV_PERIC0, __BITS(7,4)), 377 CLK_DIV("div_uart2", "mout_uart2", EXYNOS5410_DIV_PERIC0, __BITS(11,8)), 378 CLK_DIV("div_uart3", "mout_uart3", EXYNOS5410_DIV_PERIC0, __BITS(15,12)), 379 380 CLK_DIV("dout_pwm", "mout_pwm", EXYNOS5410_DIV_PERIC3, __BITS(3,0)), 381 382 CLK_DIV("aclk200", "mout_aclk200", EXYNOS5410_DIV_TOP0, __BITS(14,12)), 383 CLK_DIV("aclk266", "sclk_mpll_muxed", EXYNOS5410_DIV_TOP0, __BITS(18,16)), 384 CLK_DIV("aclk400", "mout_aclk400", EXYNOS5410_DIV_TOP0, __BITS(26,24)), 385 386 CLK_GATE("sss", "aclk266", EXYNOS5410_GATE_IP_G2D, __BIT(2), 0), 387 388 CLK_GATE("mct", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(18), 0), 389 CLK_GATE("wdt", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(19), 0), 390 CLK_GATE("rtc", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(20), 0), 391 CLK_GATE("tmu", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(21), 0), 392 393 CLK_GATE("sclk_mmc0", "dout_mmc_pre0", EXYNOS5410_SRC_MASK_FSYS, 394 __BIT(0), CLK_SET_RATE_PARENT), 395 CLK_GATE("sclk_mmc1", "dout_mmc_pre1", EXYNOS5410_SRC_MASK_FSYS, 396 __BIT(4), CLK_SET_RATE_PARENT), 397 CLK_GATE("sclk_mmc2", "dout_mmc_pre2", EXYNOS5410_SRC_MASK_FSYS, 398 __BIT(8), CLK_SET_RATE_PARENT), 399 400 CLK_GATE("mmc0", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(12), 0), 401 CLK_GATE("mmc1", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(13), 0), 402 CLK_GATE("mmc2", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(14), 0), 403 CLK_GATE("pdma1", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(2), 0), 404 CLK_GATE("pdma0", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(1), 0), 405 406 CLK_GATE("sclk_usbphy301", "dout_usbphy301", EXYNOS5410_GATE_TOP_SCLK_FSYS, 407 __BIT(7), CLK_SET_RATE_PARENT), 408 CLK_GATE("sclk_usbphy300", "dout_usbphy300", EXYNOS5410_GATE_TOP_SCLK_FSYS, 409 __BIT(8), CLK_SET_RATE_PARENT), 410 CLK_GATE("sclk_usbd300", "dout_usbd300", EXYNOS5410_GATE_TOP_SCLK_FSYS, 411 __BIT(9), CLK_SET_RATE_PARENT), 412 CLK_GATE("sclk_usbd301", "dout_usbd301", EXYNOS5410_GATE_TOP_SCLK_FSYS, 413 __BIT(10), CLK_SET_RATE_PARENT), 414 415 CLK_GATE("sclk_pwm", "dout_pwm", EXYNOS5410_GATE_TOP_SCLK_PERIC, 416 __BIT(11), CLK_SET_RATE_PARENT), 417 418 CLK_GATE("uart0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(0), 0), 419 CLK_GATE("uart1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(1), 0), 420 CLK_GATE("uart2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(2), 0), 421 CLK_GATE("uart3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(3), 0), 422 CLK_GATE("i2c0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(6), 0), 423 CLK_GATE("i2c1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(7), 0), 424 CLK_GATE("i2c2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(8), 0), 425 CLK_GATE("i2c3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(9), 0), 426 CLK_GATE("usi0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(10), 0), 427 CLK_GATE("usi1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(11), 0), 428 CLK_GATE("usi2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(12), 0), 429 CLK_GATE("usi3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(13), 0), 430 CLK_GATE("pwm", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(24), 0), 431 432 CLK_GATE("sclk_uart0", "div_uart0", EXYNOS5410_SRC_MASK_PERIC0, 433 __BIT(0), CLK_SET_RATE_PARENT), 434 CLK_GATE("sclk_uart1", "div_uart1", EXYNOS5410_SRC_MASK_PERIC0, 435 __BIT(4), CLK_SET_RATE_PARENT), 436 CLK_GATE("sclk_uart2", "div_uart2", EXYNOS5410_SRC_MASK_PERIC0, 437 __BIT(8), CLK_SET_RATE_PARENT), 438 CLK_GATE("sclk_uart3", "div_uart3", EXYNOS5410_SRC_MASK_PERIC0, 439 __BIT(12), CLK_SET_RATE_PARENT), 440 441 CLK_GATE("usbh20", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(18), 0), 442 CLK_GATE("usbd301", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(19), 0), 443 CLK_GATE("usbd300", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(20), 0), 444 }; 445 446 static int exynos5410_clock_match(device_t, cfdata_t, void *); 447 static void exynos5410_clock_attach(device_t, device_t, void *); 448 449 struct exynos5410_clock_softc { 450 device_t sc_dev; 451 bus_space_tag_t sc_bst; 452 bus_space_handle_t sc_bsh; 453 454 struct clk_domain sc_clkdom; 455 const struct exynos_pll_rates * 456 sc_pll_rates; 457 size_t sc_pll_nrates; 458 }; 459 460 static void exynos5410_clock_print_header(void); 461 static void exynos5410_clock_print(struct exynos5410_clock_softc *, 462 struct exynos_clk *); 463 464 CFATTACH_DECL_NEW(exynos5410_clock, sizeof(struct exynos5410_clock_softc), 465 exynos5410_clock_match, exynos5410_clock_attach, NULL, NULL); 466 467 #define CLOCK_READ(sc, reg) \ 468 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 469 #define CLOCK_WRITE(sc, reg, val) \ 470 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 471 472 static const struct device_compatible_entry compat_data[] = { 473 { .compat = "samsung,exynos5410-clock" }, 474 DEVICE_COMPAT_EOL 475 }; 476 477 static int 478 exynos5410_clock_match(device_t parent, cfdata_t cf, void *aux) 479 { 480 struct fdt_attach_args * const faa = aux; 481 482 return of_compatible_match(faa->faa_phandle, compat_data); 483 } 484 485 static void 486 exynos5410_clock_attach(device_t parent, device_t self, void *aux) 487 { 488 struct exynos5410_clock_softc * const sc = device_private(self); 489 struct fdt_attach_args * const faa = aux; 490 const int phandle = faa->faa_phandle; 491 bus_addr_t addr; 492 bus_size_t size; 493 int error; 494 495 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 496 aprint_error(": couldn't get registers\n"); 497 return; 498 } 499 500 sc->sc_dev = self; 501 sc->sc_bst = faa->faa_bst; 502 503 error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh); 504 if (error) { 505 aprint_error(": couldn't map %#" PRIxBUSADDR ": %d", 506 addr, error); 507 return; 508 } 509 510 aprint_naive("\n"); 511 aprint_normal(": Exynos5410 Clock Controller\n"); 512 513 struct clk * clk = fdtbus_clock_get_index(phandle, 0); 514 if (clk_get_rate(clk) == 24 * 1000 * 1000) { 515 sc->sc_pll_rates = exynos5410_pll2650x_24mhz_rates; 516 sc->sc_pll_nrates = __arraycount(exynos5410_pll2650x_24mhz_rates); 517 } 518 519 sc->sc_clkdom.funcs = &exynos5410_clock_funcs; 520 sc->sc_clkdom.priv = sc; 521 for (u_int n = 0; n < __arraycount(exynos5410_clocks); n++) { 522 exynos5410_clocks[n].base.domain = &sc->sc_clkdom; 523 } 524 525 fdtbus_register_clock_controller(self, faa->faa_phandle, 526 &exynos5410_car_fdtclock_funcs); 527 528 exynos5410_clock_print_header(); 529 for (u_int n = 0; n < __arraycount(exynos5410_clocks); n++) { 530 exynos5410_clock_print(sc, &exynos5410_clocks[n]); 531 } 532 } 533 534 static struct exynos_clk * 535 exynos5410_clock_find(const char *name) 536 { 537 u_int n; 538 539 for (n = 0; n < __arraycount(exynos5410_clocks); n++) { 540 if (strcmp(exynos5410_clocks[n].base.name, name) == 0) { 541 return &exynos5410_clocks[n]; 542 } 543 } 544 545 return NULL; 546 } 547 548 static struct exynos_clk * 549 exynos5410_clock_find_by_id(u_int clock_id) 550 { 551 u_int n; 552 553 for (n = 0; n < __arraycount(exynos5410_clock_ids); n++) { 554 if (exynos5410_clock_ids[n].id == clock_id) { 555 const char *name = exynos5410_clock_ids[n].name; 556 return exynos5410_clock_find(name); 557 } 558 } 559 560 return NULL; 561 } 562 563 static void 564 exynos5410_clock_print_header(void) 565 { 566 printf(" %-10s %2s %-10s %-5s %10s\n", 567 "clock", "", "parent", "type", "rate"); 568 printf(" %-10s %2s %-10s %-5s %10s\n", 569 "=====", "", "======", "====", "===="); 570 } 571 572 static void 573 exynos5410_clock_print(struct exynos5410_clock_softc *sc, 574 struct exynos_clk *eclk) 575 { 576 struct exynos_clk *eclk_parent; 577 struct clk *clk_parent; 578 const char *type = "?"; 579 580 switch (eclk->type) { 581 case EXYNOS_CLK_FIXED: 582 type = "fixed"; 583 break; 584 case EXYNOS_CLK_PLL35XX: 585 case EXYNOS_CLK_PLL2650X: 586 type = "pll"; 587 break; 588 case EXYNOS_CLK_MUX: 589 type = "mux"; 590 break; 591 case EXYNOS_CLK_DIV: 592 type = "div"; 593 break; 594 case EXYNOS_CLK_GATE: 595 type = "gate"; 596 break; 597 } 598 599 clk_parent = exynos5410_clock_get_parent(sc, &eclk->base); 600 eclk_parent = (struct exynos_clk *)clk_parent; 601 602 printf(" %-10s %2s %-10s %-5s %10d Hz\n", 603 eclk->base.name, 604 eclk_parent ? "<-" : "", 605 eclk_parent ? eclk_parent->base.name : "", 606 type, clk_get_rate(&eclk->base)); 607 } 608 609 static struct clk * 610 exynos5410_clock_decode(device_t dev, int cc_phandle, const void *data, 611 size_t len) 612 { 613 struct exynos_clk *eclk; 614 615 /* #clock-cells should be 1 */ 616 if (len != 4) { 617 return NULL; 618 } 619 620 const u_int clock_id = be32dec(data); 621 622 eclk = exynos5410_clock_find_by_id(clock_id); 623 if (eclk) 624 return &eclk->base; 625 626 return NULL; 627 } 628 629 static u_int 630 exynos5410_clock_get_rate_pll35xx(struct exynos5410_clock_softc *sc, 631 struct exynos_clk *eclk) 632 { 633 struct exynos_pll_clk *epll = &eclk->u.pll; 634 struct exynos_clk *clk_parent; 635 636 KASSERT(eclk->type == EXYNOS_CLK_PLL35XX); 637 638 clk_parent = exynos5410_clock_find(eclk->parent); 639 KASSERT(clk_parent != NULL); 640 const u_int rate_parent = exynos5410_clock_get_rate(sc, 641 &clk_parent->base); 642 643 const uint32_t v = CLOCK_READ(sc, epll->con0_reg); 644 645 return PLL35XX_FREQ(rate_parent, v); 646 } 647 648 static int 649 exynos5410_clock_set_rate_pll35xx(struct exynos5410_clock_softc *sc, 650 struct exynos_clk *eclk, u_int rate) 651 { 652 /* TODO */ 653 return EOPNOTSUPP; 654 } 655 656 657 static u_int 658 exynos5410_clock_get_rate_pll2650x(struct exynos5410_clock_softc *sc, 659 struct exynos_clk *eclk) 660 { 661 struct exynos_pll_clk *epll = &eclk->u.pll; 662 struct exynos_clk *clk_parent; 663 664 KASSERT(eclk->type == EXYNOS_CLK_PLL2650X); 665 666 clk_parent = exynos5410_clock_find(eclk->parent); 667 KASSERT(clk_parent != NULL); 668 const u_int rate_parent = exynos5410_clock_get_rate(sc, 669 &clk_parent->base); 670 671 const uint32_t v0 = CLOCK_READ(sc, epll->con0_reg); 672 const uint32_t v1 = CLOCK_READ(sc, epll->con1_reg); 673 674 return PLL2650X_FREQ(rate_parent, v0, v1); 675 } 676 677 static int 678 exynos5410_clock_set_rate_pll2650x(struct exynos5410_clock_softc *sc, 679 struct exynos_clk *eclk, u_int rate) 680 { 681 struct exynos_pll_clk *epll = &eclk->u.pll; 682 683 KASSERT(eclk->type == EXYNOS_CLK_PLL2650X); 684 685 const struct exynos_pll_rates *pll_rates = sc->sc_pll_rates; 686 const size_t pll_nrates = sc->sc_pll_nrates; 687 if (pll_rates == NULL) 688 return EOPNOTSUPP; 689 690 const struct exynos_pll_rates *pll_rate = NULL; 691 for (size_t i = 0; i < pll_nrates; i++) { 692 if (rate == pll_rates[i].pll_rate) { 693 pll_rate = &pll_rates[i]; 694 break; 695 } 696 } 697 698 if (pll_rate == NULL) 699 return EOPNOTSUPP; 700 701 uint32_t v0 = CLOCK_READ(sc, epll->con0_reg); 702 uint32_t v1 = CLOCK_READ(sc, epll->con1_reg); 703 704 v0 &= ~(PLL2650X_CON0_M | PLL2650X_CON0_P | PLL2650X_CON0_S); 705 v1 &= ~(PLL2650X_CON1_K); 706 707 v0 |= 708 PLL_CON0_ENABLE | 709 __SHIFTIN(pll_rate->pll_m, PLL2650X_CON0_M) | 710 __SHIFTIN(pll_rate->pll_p, PLL2650X_CON0_P) | 711 __SHIFTIN(pll_rate->pll_s, PLL2650X_CON0_S); 712 713 v1 |= 714 __SHIFTIN(pll_rate->pll_k, PLL2650X_CON1_K); 715 716 CLOCK_WRITE(sc, epll->lock_reg, 717 pll_rate->pll_p * PLL2650X_LOCK_FACTOR); 718 719 CLOCK_WRITE(sc, epll->con0_reg, v0); 720 CLOCK_WRITE(sc, epll->con1_reg, v1); 721 722 bool locked = false; 723 for (size_t i = 0; i < 1000000; i++) { 724 uint32_t con0 = CLOCK_READ(sc, epll->con0_reg); 725 if ((con0 & PLL_CON0_LOCKED) != 0) { 726 locked = true; 727 break; 728 } 729 } 730 731 return locked ? 0 : ETIMEDOUT; 732 } 733 734 static int 735 exynos5410_clock_set_parent_mux(struct exynos5410_clock_softc *sc, 736 struct exynos_clk *eclk, struct exynos_clk *eclk_parent) 737 { 738 struct exynos_mux_clk *emux = &eclk->u.mux; 739 const char *pname = eclk_parent->base.name; 740 u_int sel; 741 742 KASSERT(eclk->type == EXYNOS_CLK_MUX); 743 744 for (sel = 0; sel < emux->nparents; sel++) { 745 if (strcmp(pname, emux->parents[sel]) == 0) { 746 break; 747 } 748 } 749 if (sel == emux->nparents) { 750 return EINVAL; 751 } 752 753 uint32_t v = CLOCK_READ(sc, emux->reg); 754 v &= ~emux->bits; 755 v |= __SHIFTIN(sel, emux->bits); 756 CLOCK_WRITE(sc, emux->reg, v); 757 758 return 0; 759 } 760 761 static struct exynos_clk * 762 exynos5410_clock_get_parent_mux(struct exynos5410_clock_softc *sc, 763 struct exynos_clk *eclk) 764 { 765 struct exynos_mux_clk *emux = &eclk->u.mux; 766 767 KASSERT(eclk->type == EXYNOS_CLK_MUX); 768 769 const uint32_t v = CLOCK_READ(sc, emux->reg); 770 const u_int sel = __SHIFTOUT(v, emux->bits); 771 772 KASSERT(sel < emux->nparents); 773 774 return exynos5410_clock_find(emux->parents[sel]); 775 } 776 777 static u_int 778 exynos5410_clock_get_rate_div(struct exynos5410_clock_softc *sc, 779 struct exynos_clk *eclk) 780 { 781 struct exynos_div_clk *ediv = &eclk->u.div; 782 struct clk *clk_parent; 783 784 KASSERT(eclk->type == EXYNOS_CLK_DIV); 785 786 clk_parent = exynos5410_clock_get_parent(sc, &eclk->base); 787 const u_int parent_rate = exynos5410_clock_get_rate(sc, clk_parent); 788 789 const uint32_t v = CLOCK_READ(sc, ediv->reg); 790 const u_int div = __SHIFTOUT(v, ediv->bits); 791 792 return parent_rate / (div + 1); 793 } 794 795 static int 796 exynos5410_clock_set_rate_div(struct exynos5410_clock_softc *sc, 797 struct exynos_clk *eclk, u_int rate) 798 { 799 struct exynos_div_clk *ediv = &eclk->u.div; 800 struct clk *clk_parent; 801 int tmp_div, new_div = -1; 802 u_int tmp_rate; 803 804 KASSERT(eclk->type == EXYNOS_CLK_DIV); 805 806 clk_parent = exynos5410_clock_get_parent(sc, &eclk->base); 807 const u_int parent_rate = exynos5410_clock_get_rate(sc, clk_parent); 808 809 for (tmp_div = 0; tmp_div < __SHIFTOUT_MASK(ediv->bits); tmp_div++) { 810 tmp_rate = parent_rate / (tmp_div + 1); 811 if (tmp_rate <= rate) { 812 new_div = tmp_div; 813 break; 814 } 815 } 816 if (new_div == -1) 817 return EINVAL; 818 819 uint32_t v = CLOCK_READ(sc, ediv->reg); 820 v &= ~ediv->bits; 821 v |= __SHIFTIN(new_div, ediv->bits); 822 CLOCK_WRITE(sc, ediv->reg, v); 823 824 return 0; 825 } 826 827 static int 828 exynos5410_clock_enable_gate(struct exynos5410_clock_softc *sc, 829 struct exynos_clk *eclk, bool enable) 830 { 831 struct exynos_gate_clk *egate = &eclk->u.gate; 832 833 KASSERT(eclk->type == EXYNOS_CLK_GATE); 834 835 uint32_t v = CLOCK_READ(sc, egate->reg); 836 if (enable) { 837 v |= egate->bits; 838 } else { 839 v &= ~egate->bits; 840 } 841 CLOCK_WRITE(sc, egate->reg, v); 842 843 return 0; 844 } 845 846 /* 847 * clk api 848 */ 849 850 static struct clk * 851 exynos5410_clock_get(void *priv, const char *name) 852 { 853 struct exynos_clk *eclk; 854 855 eclk = exynos5410_clock_find(name); 856 if (eclk == NULL) 857 return NULL; 858 859 atomic_inc_uint(&eclk->refcnt); 860 861 return &eclk->base; 862 } 863 864 static void 865 exynos5410_clock_put(void *priv, struct clk *clk) 866 { 867 struct exynos_clk *eclk = (struct exynos_clk *)clk; 868 869 KASSERT(eclk->refcnt > 0); 870 871 atomic_dec_uint(&eclk->refcnt); 872 } 873 874 static u_int 875 exynos5410_clock_get_rate(void *priv, struct clk *clk) 876 { 877 struct exynos_clk *eclk = (struct exynos_clk *)clk; 878 struct clk *clk_parent; 879 880 switch (eclk->type) { 881 case EXYNOS_CLK_FIXED: 882 return eclk->u.fixed.rate; 883 case EXYNOS_CLK_PLL35XX: 884 return exynos5410_clock_get_rate_pll35xx(priv, eclk); 885 case EXYNOS_CLK_PLL2650X: 886 return exynos5410_clock_get_rate_pll2650x(priv, eclk); 887 case EXYNOS_CLK_MUX: 888 case EXYNOS_CLK_GATE: 889 clk_parent = exynos5410_clock_get_parent(priv, clk); 890 return exynos5410_clock_get_rate(priv, clk_parent); 891 case EXYNOS_CLK_DIV: 892 return exynos5410_clock_get_rate_div(priv, eclk); 893 default: 894 panic("exynos5410: unknown eclk type %d", eclk->type); 895 } 896 } 897 898 static int 899 exynos5410_clock_set_rate(void *priv, struct clk *clk, u_int rate) 900 { 901 struct exynos_clk *eclk = (struct exynos_clk *)clk; 902 903 KASSERT((clk->flags & CLK_SET_RATE_PARENT) == 0); 904 905 switch (eclk->type) { 906 case EXYNOS_CLK_FIXED: 907 return EIO; 908 case EXYNOS_CLK_PLL35XX: 909 return exynos5410_clock_set_rate_pll35xx(priv, eclk, rate); 910 case EXYNOS_CLK_PLL2650X: 911 return exynos5410_clock_set_rate_pll2650x(priv, eclk, rate); 912 case EXYNOS_CLK_MUX: 913 return EIO; 914 case EXYNOS_CLK_DIV: 915 return exynos5410_clock_set_rate_div(priv, eclk, rate); 916 case EXYNOS_CLK_GATE: 917 return EINVAL; 918 default: 919 panic("exynos5410: unknown eclk type %d", eclk->type); 920 } 921 } 922 923 static int 924 exynos5410_clock_enable(void *priv, struct clk *clk) 925 { 926 struct exynos_clk *eclk = (struct exynos_clk *)clk; 927 928 switch (eclk->type) { 929 case EXYNOS_CLK_FIXED: 930 return 0; /* always on */ 931 case EXYNOS_CLK_PLL35XX: 932 case EXYNOS_CLK_PLL2650X: 933 return 0; /* XXX */ 934 case EXYNOS_CLK_MUX: 935 case EXYNOS_CLK_DIV: 936 return 0; 937 case EXYNOS_CLK_GATE: 938 return exynos5410_clock_enable_gate(priv, eclk, true); 939 default: 940 panic("exynos5410: unknown eclk type %d", eclk->type); 941 } 942 } 943 944 static int 945 exynos5410_clock_disable(void *priv, struct clk *clk) 946 { 947 struct exynos_clk *eclk = (struct exynos_clk *)clk; 948 949 switch (eclk->type) { 950 case EXYNOS_CLK_FIXED: 951 return EINVAL; /* always on */ 952 case EXYNOS_CLK_PLL35XX: 953 case EXYNOS_CLK_PLL2650X: 954 return EINVAL; /* XXX */ 955 case EXYNOS_CLK_MUX: 956 case EXYNOS_CLK_DIV: 957 return EINVAL; 958 case EXYNOS_CLK_GATE: 959 return exynos5410_clock_enable_gate(priv, eclk, false); 960 default: 961 panic("exynos5410: unknown eclk type %d", eclk->type); 962 } 963 } 964 965 static int 966 exynos5410_clock_set_parent(void *priv, struct clk *clk, struct clk *clk_parent) 967 { 968 struct exynos_clk *eclk = (struct exynos_clk *)clk; 969 struct exynos_clk *eclk_parent = (struct exynos_clk *)clk_parent; 970 971 switch (eclk->type) { 972 case EXYNOS_CLK_FIXED: 973 case EXYNOS_CLK_PLL35XX: 974 case EXYNOS_CLK_PLL2650X: 975 case EXYNOS_CLK_DIV: 976 case EXYNOS_CLK_GATE: 977 return EINVAL; 978 case EXYNOS_CLK_MUX: 979 return exynos5410_clock_set_parent_mux(priv, eclk, eclk_parent); 980 default: 981 panic("exynos5410: unknown eclk type %d", eclk->type); 982 } 983 } 984 985 static struct clk * 986 exynos5410_clock_get_parent(void *priv, struct clk *clk) 987 { 988 struct exynos_clk *eclk = (struct exynos_clk *)clk; 989 struct exynos_clk *eclk_parent = NULL; 990 991 switch (eclk->type) { 992 case EXYNOS_CLK_FIXED: 993 case EXYNOS_CLK_PLL35XX: 994 case EXYNOS_CLK_PLL2650X: 995 case EXYNOS_CLK_DIV: 996 case EXYNOS_CLK_GATE: 997 if (eclk->parent != NULL) { 998 eclk_parent = exynos5410_clock_find(eclk->parent); 999 } 1000 break; 1001 case EXYNOS_CLK_MUX: 1002 eclk_parent = exynos5410_clock_get_parent_mux(priv, eclk); 1003 break; 1004 default: 1005 panic("exynos5410: unknown eclk type %d", eclk->type); 1006 } 1007 1008 return (struct clk *)eclk_parent; 1009 } 1010