1 /* $NetBSD: exynos5410_clock.c,v 1.7 2021/01/27 03:10:19 thorpej 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.7 2021/01/27 03:10:19 thorpej 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_dpll" }, 64 { 5, "fout_mpll" }, 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 static struct clk *exynos5410_clock_get(void *, const char *); 112 static void exynos5410_clock_put(void *, struct clk *); 113 static u_int exynos5410_clock_get_rate(void *, struct clk *); 114 static int exynos5410_clock_set_rate(void *, struct clk *, u_int); 115 static int exynos5410_clock_enable(void *, struct clk *); 116 static int exynos5410_clock_disable(void *, struct clk *); 117 static int exynos5410_clock_set_parent(void *, struct clk *, struct clk *); 118 static struct clk *exynos5410_clock_get_parent(void *, struct clk *); 119 120 static const struct clk_funcs exynos5410_clock_funcs = { 121 .get = exynos5410_clock_get, 122 .put = exynos5410_clock_put, 123 .get_rate = exynos5410_clock_get_rate, 124 .set_rate = exynos5410_clock_set_rate, 125 .enable = exynos5410_clock_enable, 126 .disable = exynos5410_clock_disable, 127 .set_parent = exynos5410_clock_set_parent, 128 .get_parent = exynos5410_clock_get_parent, 129 }; 130 131 #define CLK_FIXED(_name, _rate) { \ 132 .base = { .name = (_name) }, .type = EXYNOS_CLK_FIXED, \ 133 .u = { .fixed = { .rate = (_rate) } } \ 134 } 135 136 #define CLK_PLL(_name, _parent, _lock, _con0) { \ 137 .base = { .name = (_name) }, .type = EXYNOS_CLK_PLL, \ 138 .parent = (_parent), \ 139 .u = { \ 140 .pll = { \ 141 .lock_reg = (_lock), \ 142 .con0_reg = (_con0), \ 143 } \ 144 } \ 145 } 146 147 #define CLK_MUXF(_name, _alias, _reg, _bits, _f, _p) { \ 148 .base = { .name = (_name), .flags = (_f) }, \ 149 .type = EXYNOS_CLK_MUX, \ 150 .alias = (_alias), \ 151 .u = { \ 152 .mux = { \ 153 .nparents = __arraycount(_p), \ 154 .parents = (_p), \ 155 .reg = (_reg), \ 156 .bits = (_bits) \ 157 } \ 158 } \ 159 } 160 161 #define CLK_MUXA(_name, _alias, _reg, _bits, _p) \ 162 CLK_MUXF(_name, _alias, _reg, _bits, 0, _p) 163 164 #define CLK_MUX(_name, _reg, _bits, _p) \ 165 CLK_MUXF(_name, NULL, _reg, _bits, 0, _p) 166 167 #define CLK_DIVF(_name, _parent, _reg, _bits, _f) { \ 168 .base = { .name = (_name), .flags = (_f) }, \ 169 .type = EXYNOS_CLK_DIV, \ 170 .parent = (_parent), \ 171 .u = { \ 172 .div = { \ 173 .reg = (_reg), \ 174 .bits = (_bits) \ 175 } \ 176 } \ 177 } 178 179 #define CLK_DIV(_name, _parent, _reg, _bits) \ 180 CLK_DIVF(_name, _parent, _reg, _bits, 0) 181 182 #define CLK_GATE(_name, _parent, _reg, _bits, _f) { \ 183 .base = { .name = (_name), .flags = (_f) }, \ 184 .type = EXYNOS_CLK_GATE, \ 185 .parent = (_parent), \ 186 .u = { \ 187 .gate = { \ 188 .reg = (_reg), \ 189 .bits = (_bits) \ 190 } \ 191 } \ 192 } 193 194 #define EXYNOS5410_APLL_LOCK 0x00000 195 #define EXYNOS5410_APLL_CON0 0x00100 196 #define EXYNOS5410_MPLL_LOCK 0x04000 197 #define EXYNOS5410_MPLL_CON0 0x04100 198 #define EXYNOS5410_CPLL_LOCK 0x10020 199 #define EXYNOS5410_EPLL_LOCK 0x10040 200 #define EXYNOS5410_CPLL_CON0 0x10120 201 #define EXYNOS5410_EPLL_CON0 0x10130 202 #define EXYNOS5410_EPLL_CON1 0x10134 203 #define EXYNOS5410_EPLL_CON2 0x10138 204 #define EXYNOS5410_BPLL_LOCK 0x20010 205 #define EXYNOS5410_BPLL_CON0 0x20110 206 #define EXYNOS5410_KPLL_LOCK 0x28000 207 #define EXYNOS5410_KPLL_CON0 0x28100 208 209 #define EXYNOS5410_SRC_CPU 0x00200 210 #define EXYNOS5410_SRC_CPERI1 0x04204 211 #define EXYNOS5410_SRC_TOP0 0x10210 212 #define EXYNOS5410_SRC_TOP1 0x10214 213 #define EXYNOS5410_SRC_TOP2 0x10218 214 #define EXYNOS5410_SRC_FSYS 0x10244 215 #define EXYNOS5410_SRC_PERIC0 0x10250 216 #define EXYNOS5410_SRC_MASK_FSYS 0x10340 217 #define EXYNOS5410_SRC_MASK_PERIC0 0x10350 218 #define EXYNOS5410_SRC_CDREX 0x20200 219 #define EXYNOS5410_SRC_KFC 0x28200 220 221 #define EXYNOS5410_DIV_CPU0 0x00500 222 #define EXYNOS5410_DIV_TOP0 0x10510 223 #define EXYNOS5410_DIV_TOP1 0x10514 224 #define EXYNOS5410_DIV_FSYS0 0x10548 225 #define EXYNOS5410_DIV_FSYS1 0x1054c 226 #define EXYNOS5410_DIV_FSYS2 0x10550 227 #define EXYNOS5410_DIV_PERIC0 0x10558 228 #define EXYNOS5410_DIV_PERIC3 0x10564 229 #define EXYNOS5410_DIV_KFC0 0x28500 230 231 #define EXYNOS5410_GATE_IP_G2D 0x08800 232 #define EXYNOS5410_GATE_BUS_FSYS0 0x10740 233 #define EXYNOS5410_GATE_TOP_SCLK_FSYS 0x10840 234 #define EXYNOS5410_GATE_TOP_SCLK_PERIC 0x10850 235 #define EXYNOS5410_GATE_IP_FSYS 0x10944 236 #define EXYNOS5410_GATE_IP_PERIC 0x10950 237 #define EXYNOS5410_GATE_IP_PERIS 0x10960 238 239 static const char *mout_apll_p[] = { "fin_pll", "fout_apll" }; 240 static const char *mout_bpll_p[] = { "fin_pll", "fout_bpll" }; 241 static const char *mout_cpll_p[] = { "fin_pll", "fout_cpll" }; 242 static const char *mout_epll_p[] = { "fin_pll", "fout_epll" }; 243 static const char *mout_mpll_p[] = { "fin_pll", "fout_mpll" }; 244 static const char *mout_kpll_p[] = { "fin_pll", "fout_kpll" }; 245 246 static const char *mout_cpu_p[] = { "mout_apll", "sclk_mpll" }; 247 static const char *mout_kfc_p[] = { "mout_kpll", "sclk_mpll" }; 248 249 static const char *mout_mpll_user_p[] = { "fin_pll", "sclk_mpll" }; 250 static const char *mout_bpll_user_p[] = { "fin_pll", "sclk_bpll" }; 251 static const char *mout_mpll_bpll_p[] = 252 { "sclk_mpll_muxed", "sclk_bpll_muxed" }; 253 static const char *mout_sclk_mpll_bpll_p[] = { "sclk_mpll_bpll", "fin_pll" }; 254 255 static const char *mout_group2_p[] = 256 { "fin_pll", "fin_pll", "none", "none", "none", "none", 257 "sclk_mpll_bpll", "none", "none", "sclk_cpll" }; 258 259 static struct exynos_clk exynos5410_clocks[] = { 260 CLK_FIXED("fin_pll", EXYNOS_F_IN_FREQ), 261 262 CLK_PLL("fout_apll", "fin_pll", EXYNOS5410_APLL_LOCK, 263 EXYNOS5410_APLL_CON0), 264 CLK_PLL("fout_bpll", "fin_pll", EXYNOS5410_BPLL_LOCK, 265 EXYNOS5410_BPLL_CON0), 266 CLK_PLL("fout_cpll", "fin_pll", EXYNOS5410_CPLL_LOCK, 267 EXYNOS5410_CPLL_CON0), 268 CLK_PLL("fout_epll", "fin_pll", EXYNOS5410_EPLL_LOCK, 269 EXYNOS5410_EPLL_CON0), 270 CLK_PLL("fout_mpll", "fin_pll", EXYNOS5410_MPLL_LOCK, 271 EXYNOS5410_MPLL_CON0), 272 CLK_PLL("fout_kpll", "fin_pll", EXYNOS5410_KPLL_LOCK, 273 EXYNOS5410_KPLL_CON0), 274 275 CLK_MUX("mout_apll", EXYNOS5410_SRC_CPU, __BIT(0), mout_apll_p), 276 CLK_MUX("mout_cpu", EXYNOS5410_SRC_CPU, __BIT(16), mout_cpu_p), 277 CLK_MUX("mout_kpll", EXYNOS5410_SRC_KFC, __BIT(0), mout_kpll_p), 278 CLK_MUX("mout_kfc", EXYNOS5410_SRC_KFC, __BIT(16), mout_kfc_p), 279 280 CLK_MUX("sclk_mpll", EXYNOS5410_SRC_CPERI1, __BIT(8), mout_mpll_p), 281 CLK_MUX("sclk_mpll_muxed", EXYNOS5410_SRC_TOP2, __BIT(20), mout_mpll_user_p), 282 CLK_MUX("sclk_bpll", EXYNOS5410_SRC_CDREX, __BIT(0), mout_bpll_p), 283 CLK_MUX("sclk_bpll_muxed", EXYNOS5410_SRC_TOP2, __BIT(24), mout_bpll_user_p), 284 CLK_MUX("sclk_epll", EXYNOS5410_SRC_TOP2, __BIT(12), mout_epll_p), 285 CLK_MUX("sclk_cpll", EXYNOS5410_SRC_TOP2, __BIT(8), mout_cpll_p), 286 CLK_MUX("sclk_mpll_bpll", EXYNOS5410_SRC_TOP1, __BIT(20), mout_mpll_bpll_p), 287 288 CLK_MUX("mout_mmc0", EXYNOS5410_SRC_FSYS, __BITS(3,0), mout_group2_p), 289 CLK_MUX("mout_mmc1", EXYNOS5410_SRC_FSYS, __BITS(7,4), mout_group2_p), 290 CLK_MUX("mout_mmc2", EXYNOS5410_SRC_FSYS, __BITS(11,8), mout_group2_p), 291 CLK_MUX("mout_usbd300", EXYNOS5410_SRC_FSYS, __BIT(28), mout_sclk_mpll_bpll_p), 292 CLK_MUX("mout_usbd301", EXYNOS5410_SRC_FSYS, __BIT(29), mout_sclk_mpll_bpll_p), 293 CLK_MUX("mout_uart0", EXYNOS5410_SRC_PERIC0, __BITS(3,0), mout_group2_p), 294 CLK_MUX("mout_uart1", EXYNOS5410_SRC_PERIC0, __BITS(7,4), mout_group2_p), 295 CLK_MUX("mout_uart2", EXYNOS5410_SRC_PERIC0, __BITS(11,8), mout_group2_p), 296 CLK_MUX("mout_uart3", EXYNOS5410_SRC_PERIC0, __BITS(15,12), mout_group2_p), 297 CLK_MUX("mout_pwm", EXYNOS5410_SRC_PERIC0, __BITS(27,24), mout_group2_p), 298 CLK_MUX("mout_aclk200", EXYNOS5410_SRC_TOP0, __BIT(12), mout_mpll_bpll_p), 299 CLK_MUX("mout_aclk400", EXYNOS5410_SRC_TOP0, __BIT(20), mout_mpll_bpll_p), 300 301 CLK_DIV("div_arm", "mout_cpu", EXYNOS5410_DIV_CPU0, __BITS(2,0)), 302 CLK_DIV("div_arm2", "div_arm", EXYNOS5410_DIV_CPU0, __BITS(30,28)), 303 304 CLK_DIV("div_acp", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(10,8)), 305 CLK_DIV("div_cpud", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(6,4)), 306 CLK_DIV("div_atb", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(18,16)), 307 CLK_DIV("pclk_dbg", "div_arm2", EXYNOS5410_DIV_CPU0, __BITS(22,20)), 308 309 CLK_DIV("div_kfc", "mout_kfc", EXYNOS5410_DIV_KFC0, __BITS(2,0)), 310 CLK_DIV("div_aclk", "div_kfc", EXYNOS5410_DIV_KFC0, __BITS(6,4)), 311 CLK_DIV("div_pclk", "div_kfc", EXYNOS5410_DIV_KFC0, __BITS(22,20)), 312 313 CLK_DIV("aclk66_pre", "sclk_mpll_muxed", EXYNOS5410_DIV_TOP1, __BITS(26,24)), 314 CLK_DIV("aclk66", "aclk66_pre", EXYNOS5410_DIV_TOP0, __BITS(2,0)), 315 316 CLK_DIV("dout_usbphy300", "mout_usbd300", EXYNOS5410_DIV_FSYS0, __BITS(19,16)), 317 CLK_DIV("dout_usbphy301", "mout_usbd301", EXYNOS5410_DIV_FSYS0, __BITS(23,20)), 318 CLK_DIV("dout_usbd300", "mout_usbd300", EXYNOS5410_DIV_FSYS0, __BITS(27,24)), 319 CLK_DIV("dout_usbd301", "mout_usbd301", EXYNOS5410_DIV_FSYS0, __BITS(31,28)), 320 321 CLK_DIV("dout_mmc0", "mout_mmc0", EXYNOS5410_DIV_FSYS1, __BITS(3,0)), 322 CLK_DIV("dout_mmc1", "mout_mmc1", EXYNOS5410_DIV_FSYS1, __BITS(19,16)), 323 CLK_DIV("dout_mmc2", "mout_mmc2", EXYNOS5410_DIV_FSYS2, __BITS(3,0)), 324 325 CLK_DIVF("dout_mmc_pre0", "dout_mmc0", EXYNOS5410_DIV_FSYS1, __BITS(15,8), 326 CLK_SET_RATE_PARENT), 327 CLK_DIVF("dout_mmc_pre1", "dout_mmc1", EXYNOS5410_DIV_FSYS1, __BITS(31,24), 328 CLK_SET_RATE_PARENT), 329 CLK_DIVF("dout_mmc_pre2", "dout_mmc2", EXYNOS5410_DIV_FSYS2, __BITS(15,8), 330 CLK_SET_RATE_PARENT), 331 332 CLK_DIV("div_uart0", "mout_uart0", EXYNOS5410_DIV_PERIC0, __BITS(3,0)), 333 CLK_DIV("div_uart1", "mout_uart1", EXYNOS5410_DIV_PERIC0, __BITS(7,4)), 334 CLK_DIV("div_uart2", "mout_uart2", EXYNOS5410_DIV_PERIC0, __BITS(11,8)), 335 CLK_DIV("div_uart3", "mout_uart3", EXYNOS5410_DIV_PERIC0, __BITS(15,12)), 336 337 CLK_DIV("dout_pwm", "mout_pwm", EXYNOS5410_DIV_PERIC3, __BITS(3,0)), 338 339 CLK_DIV("aclk200", "mout_aclk200", EXYNOS5410_DIV_TOP0, __BITS(14,12)), 340 CLK_DIV("aclk266", "sclk_mpll_muxed", EXYNOS5410_DIV_TOP0, __BITS(18,16)), 341 CLK_DIV("aclk400", "mout_aclk400", EXYNOS5410_DIV_TOP0, __BITS(26,24)), 342 343 CLK_GATE("sss", "aclk266", EXYNOS5410_GATE_IP_G2D, __BIT(2), 0), 344 345 CLK_GATE("mct", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(18), 0), 346 CLK_GATE("wdt", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(19), 0), 347 CLK_GATE("rtc", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(20), 0), 348 CLK_GATE("tmu", "aclk66", EXYNOS5410_GATE_IP_PERIS, __BIT(21), 0), 349 350 CLK_GATE("sclk_mmc0", "dout_mmc_pre0", EXYNOS5410_SRC_MASK_FSYS, 351 __BIT(0), CLK_SET_RATE_PARENT), 352 CLK_GATE("sclk_mmc1", "dout_mmc_pre1", EXYNOS5410_SRC_MASK_FSYS, 353 __BIT(4), CLK_SET_RATE_PARENT), 354 CLK_GATE("sclk_mmc2", "dout_mmc_pre2", EXYNOS5410_SRC_MASK_FSYS, 355 __BIT(8), CLK_SET_RATE_PARENT), 356 357 CLK_GATE("mmc0", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(12), 0), 358 CLK_GATE("mmc1", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(13), 0), 359 CLK_GATE("mmc2", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(14), 0), 360 CLK_GATE("pdma1", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(2), 0), 361 CLK_GATE("pdma0", "aclk200", EXYNOS5410_GATE_BUS_FSYS0, __BIT(1), 0), 362 363 CLK_GATE("sclk_usbphy301", "dout_usbphy301", EXYNOS5410_GATE_TOP_SCLK_FSYS, 364 __BIT(7), CLK_SET_RATE_PARENT), 365 CLK_GATE("sclk_usbphy300", "dout_usbphy300", EXYNOS5410_GATE_TOP_SCLK_FSYS, 366 __BIT(8), CLK_SET_RATE_PARENT), 367 CLK_GATE("sclk_usbd301", "dout_usbd301", EXYNOS5410_GATE_TOP_SCLK_FSYS, 368 __BIT(9), CLK_SET_RATE_PARENT), 369 CLK_GATE("sclk_usbd301", "dout_usbd301", EXYNOS5410_GATE_TOP_SCLK_FSYS, 370 __BIT(10), CLK_SET_RATE_PARENT), 371 372 CLK_GATE("sclk_pwm", "dout_pwm", EXYNOS5410_GATE_TOP_SCLK_PERIC, 373 __BIT(11), CLK_SET_RATE_PARENT), 374 375 CLK_GATE("uart0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(0), 0), 376 CLK_GATE("uart1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(1), 0), 377 CLK_GATE("uart2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(2), 0), 378 CLK_GATE("uart3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(3), 0), 379 CLK_GATE("i2c0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(6), 0), 380 CLK_GATE("i2c1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(7), 0), 381 CLK_GATE("i2c2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(8), 0), 382 CLK_GATE("i2c3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(9), 0), 383 CLK_GATE("usi0", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(10), 0), 384 CLK_GATE("usi1", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(11), 0), 385 CLK_GATE("usi2", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(12), 0), 386 CLK_GATE("usi3", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(13), 0), 387 CLK_GATE("pwm", "aclk66", EXYNOS5410_GATE_IP_PERIC, __BIT(24), 0), 388 389 CLK_GATE("sclk_uart0", "div_uart0", EXYNOS5410_SRC_MASK_PERIC0, 390 __BIT(0), CLK_SET_RATE_PARENT), 391 CLK_GATE("sclk_uart1", "div_uart1", EXYNOS5410_SRC_MASK_PERIC0, 392 __BIT(4), CLK_SET_RATE_PARENT), 393 CLK_GATE("sclk_uart2", "div_uart2", EXYNOS5410_SRC_MASK_PERIC0, 394 __BIT(8), CLK_SET_RATE_PARENT), 395 CLK_GATE("sclk_uart3", "div_uart3", EXYNOS5410_SRC_MASK_PERIC0, 396 __BIT(12), CLK_SET_RATE_PARENT), 397 398 CLK_GATE("usbh20", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(18), 0), 399 CLK_GATE("usbd301", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(19), 0), 400 CLK_GATE("usbd300", "aclk200", EXYNOS5410_GATE_IP_FSYS, __BIT(20), 0), 401 }; 402 403 static int exynos5410_clock_match(device_t, cfdata_t, void *); 404 static void exynos5410_clock_attach(device_t, device_t, void *); 405 406 struct exynos5410_clock_softc { 407 device_t sc_dev; 408 bus_space_tag_t sc_bst; 409 bus_space_handle_t sc_bsh; 410 411 struct clk_domain sc_clkdom; 412 }; 413 414 static void exynos5410_clock_print_header(void); 415 static void exynos5410_clock_print(struct exynos5410_clock_softc *, 416 struct exynos_clk *); 417 418 CFATTACH_DECL_NEW(exynos5410_clock, sizeof(struct exynos5410_clock_softc), 419 exynos5410_clock_match, exynos5410_clock_attach, NULL, NULL); 420 421 #define CLOCK_READ(sc, reg) \ 422 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 423 #define CLOCK_WRITE(sc, reg, val) \ 424 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 425 426 static const struct device_compatible_entry compat_data[] = { 427 { .compat = "samsung,exynos5410-clock" }, 428 DEVICE_COMPAT_EOL 429 }; 430 431 static int 432 exynos5410_clock_match(device_t parent, cfdata_t cf, void *aux) 433 { 434 struct fdt_attach_args * const faa = aux; 435 436 return of_compatible_match(faa->faa_phandle, compat_data); 437 } 438 439 static void 440 exynos5410_clock_attach(device_t parent, device_t self, void *aux) 441 { 442 struct exynos5410_clock_softc * const sc = device_private(self); 443 struct fdt_attach_args * const faa = aux; 444 bus_addr_t addr; 445 bus_size_t size; 446 int error; 447 448 if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) { 449 aprint_error(": couldn't get registers\n"); 450 return; 451 } 452 453 sc->sc_dev = self; 454 sc->sc_bst = faa->faa_bst; 455 456 error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh); 457 if (error) { 458 aprint_error(": couldn't map %#" PRIxBUSADDR ": %d", 459 addr, error); 460 return; 461 } 462 463 aprint_naive("\n"); 464 aprint_normal(": Exynos5410 Clock Controller\n"); 465 466 sc->sc_clkdom.funcs = &exynos5410_clock_funcs; 467 sc->sc_clkdom.priv = sc; 468 for (u_int n = 0; n < __arraycount(exynos5410_clocks); n++) { 469 exynos5410_clocks[n].base.domain = &sc->sc_clkdom; 470 } 471 472 fdtbus_register_clock_controller(self, faa->faa_phandle, 473 &exynos5410_car_fdtclock_funcs); 474 475 exynos5410_clock_print_header(); 476 for (u_int n = 0; n < __arraycount(exynos5410_clocks); n++) { 477 exynos5410_clock_print(sc, &exynos5410_clocks[n]); 478 } 479 } 480 481 static struct exynos_clk * 482 exynos5410_clock_find(const char *name) 483 { 484 u_int n; 485 486 for (n = 0; n < __arraycount(exynos5410_clocks); n++) { 487 if (strcmp(exynos5410_clocks[n].base.name, name) == 0) { 488 return &exynos5410_clocks[n]; 489 } 490 } 491 492 return NULL; 493 } 494 495 static struct exynos_clk * 496 exynos5410_clock_find_by_id(u_int clock_id) 497 { 498 u_int n; 499 500 for (n = 0; n < __arraycount(exynos5410_clock_ids); n++) { 501 if (exynos5410_clock_ids[n].id == clock_id) { 502 const char *name = exynos5410_clock_ids[n].name; 503 return exynos5410_clock_find(name); 504 } 505 } 506 507 return NULL; 508 } 509 510 static void 511 exynos5410_clock_print_header(void) 512 { 513 printf(" %-10s %2s %-10s %-5s %10s\n", 514 "clock", "", "parent", "type", "rate"); 515 printf(" %-10s %2s %-10s %-5s %10s\n", 516 "=====", "", "======", "====", "===="); 517 } 518 519 static void 520 exynos5410_clock_print(struct exynos5410_clock_softc *sc, 521 struct exynos_clk *eclk) 522 { 523 struct exynos_clk *eclk_parent; 524 struct clk *clk_parent; 525 const char *type = "?"; 526 527 switch (eclk->type) { 528 case EXYNOS_CLK_FIXED: 529 type = "fixed"; 530 break; 531 case EXYNOS_CLK_PLL: 532 type = "pll"; 533 break; 534 case EXYNOS_CLK_MUX: 535 type = "mux"; 536 break; 537 case EXYNOS_CLK_DIV: 538 type = "div"; 539 break; 540 case EXYNOS_CLK_GATE: 541 type = "gate"; 542 break; 543 } 544 545 clk_parent = exynos5410_clock_get_parent(sc, &eclk->base); 546 eclk_parent = (struct exynos_clk *)clk_parent; 547 548 printf(" %-10s %2s %-10s %-5s %10d Hz\n", 549 eclk->base.name, 550 eclk_parent ? "<-" : "", 551 eclk_parent ? eclk_parent->base.name : "", 552 type, clk_get_rate(&eclk->base)); 553 } 554 555 static struct clk * 556 exynos5410_clock_decode(device_t dev, int cc_phandle, const void *data, 557 size_t len) 558 { 559 struct exynos_clk *eclk; 560 561 /* #clock-cells should be 1 */ 562 if (len != 4) { 563 return NULL; 564 } 565 566 const u_int clock_id = be32dec(data); 567 568 eclk = exynos5410_clock_find_by_id(clock_id); 569 if (eclk) 570 return &eclk->base; 571 572 return NULL; 573 } 574 575 static u_int 576 exynos5410_clock_get_rate_pll(struct exynos5410_clock_softc *sc, 577 struct exynos_clk *eclk) 578 { 579 struct exynos_pll_clk *epll = &eclk->u.pll; 580 struct exynos_clk *clk_parent; 581 582 KASSERT(eclk->type == EXYNOS_CLK_PLL); 583 584 clk_parent = exynos5410_clock_find(eclk->parent); 585 KASSERT(clk_parent != NULL); 586 const u_int rate_parent = exynos5410_clock_get_rate(sc, 587 &clk_parent->base); 588 589 const uint32_t v = CLOCK_READ(sc, epll->con0_reg); 590 591 return PLL_FREQ(rate_parent, v); 592 } 593 594 static int 595 exynos5410_clock_set_rate_pll(struct exynos5410_clock_softc *sc, 596 struct exynos_clk *eclk, u_int rate) 597 { 598 /* TODO */ 599 return EOPNOTSUPP; 600 } 601 602 static int 603 exynos5410_clock_set_parent_mux(struct exynos5410_clock_softc *sc, 604 struct exynos_clk *eclk, struct exynos_clk *eclk_parent) 605 { 606 struct exynos_mux_clk *emux = &eclk->u.mux; 607 const char *pname = eclk_parent->base.name; 608 u_int sel; 609 610 KASSERT(eclk->type == EXYNOS_CLK_MUX); 611 612 for (sel = 0; sel < emux->nparents; sel++) { 613 if (strcmp(pname, emux->parents[sel]) == 0) { 614 break; 615 } 616 } 617 if (sel == emux->nparents) { 618 return EINVAL; 619 } 620 621 uint32_t v = CLOCK_READ(sc, emux->reg); 622 v &= ~emux->bits; 623 v |= __SHIFTIN(sel, emux->bits); 624 CLOCK_WRITE(sc, emux->reg, v); 625 626 return 0; 627 } 628 629 static struct exynos_clk * 630 exynos5410_clock_get_parent_mux(struct exynos5410_clock_softc *sc, 631 struct exynos_clk *eclk) 632 { 633 struct exynos_mux_clk *emux = &eclk->u.mux; 634 635 KASSERT(eclk->type == EXYNOS_CLK_MUX); 636 637 const uint32_t v = CLOCK_READ(sc, emux->reg); 638 const u_int sel = __SHIFTOUT(v, emux->bits); 639 640 KASSERT(sel < emux->nparents); 641 642 return exynos5410_clock_find(emux->parents[sel]); 643 } 644 645 static u_int 646 exynos5410_clock_get_rate_div(struct exynos5410_clock_softc *sc, 647 struct exynos_clk *eclk) 648 { 649 struct exynos_div_clk *ediv = &eclk->u.div; 650 struct clk *clk_parent; 651 652 KASSERT(eclk->type == EXYNOS_CLK_DIV); 653 654 clk_parent = exynos5410_clock_get_parent(sc, &eclk->base); 655 const u_int parent_rate = exynos5410_clock_get_rate(sc, clk_parent); 656 657 const uint32_t v = CLOCK_READ(sc, ediv->reg); 658 const u_int div = __SHIFTOUT(v, ediv->bits); 659 660 return parent_rate / (div + 1); 661 } 662 663 static int 664 exynos5410_clock_set_rate_div(struct exynos5410_clock_softc *sc, 665 struct exynos_clk *eclk, u_int rate) 666 { 667 struct exynos_div_clk *ediv = &eclk->u.div; 668 struct clk *clk_parent; 669 int tmp_div, new_div = -1; 670 u_int tmp_rate; 671 672 KASSERT(eclk->type == EXYNOS_CLK_DIV); 673 674 clk_parent = exynos5410_clock_get_parent(sc, &eclk->base); 675 const u_int parent_rate = exynos5410_clock_get_rate(sc, clk_parent); 676 677 for (tmp_div = 0; tmp_div < __SHIFTOUT_MASK(ediv->bits); tmp_div++) { 678 tmp_rate = parent_rate / (tmp_div + 1); 679 if (tmp_rate <= rate) { 680 new_div = tmp_div; 681 break; 682 } 683 } 684 if (new_div == -1) 685 return EINVAL; 686 687 uint32_t v = CLOCK_READ(sc, ediv->reg); 688 v &= ~ediv->bits; 689 v |= __SHIFTIN(new_div, ediv->bits); 690 CLOCK_WRITE(sc, ediv->reg, v); 691 692 return 0; 693 } 694 695 static int 696 exynos5410_clock_enable_gate(struct exynos5410_clock_softc *sc, 697 struct exynos_clk *eclk, bool enable) 698 { 699 struct exynos_gate_clk *egate = &eclk->u.gate; 700 701 KASSERT(eclk->type == EXYNOS_CLK_GATE); 702 703 uint32_t v = CLOCK_READ(sc, egate->reg); 704 if (enable) { 705 v |= egate->bits; 706 } else { 707 v &= ~egate->bits; 708 } 709 CLOCK_WRITE(sc, egate->reg, v); 710 711 return 0; 712 } 713 714 /* 715 * clk api 716 */ 717 718 static struct clk * 719 exynos5410_clock_get(void *priv, const char *name) 720 { 721 struct exynos_clk *eclk; 722 723 eclk = exynos5410_clock_find(name); 724 if (eclk == NULL) 725 return NULL; 726 727 atomic_inc_uint(&eclk->refcnt); 728 729 return &eclk->base; 730 } 731 732 static void 733 exynos5410_clock_put(void *priv, struct clk *clk) 734 { 735 struct exynos_clk *eclk = (struct exynos_clk *)clk; 736 737 KASSERT(eclk->refcnt > 0); 738 739 atomic_dec_uint(&eclk->refcnt); 740 } 741 742 static u_int 743 exynos5410_clock_get_rate(void *priv, struct clk *clk) 744 { 745 struct exynos_clk *eclk = (struct exynos_clk *)clk; 746 struct clk *clk_parent; 747 748 switch (eclk->type) { 749 case EXYNOS_CLK_FIXED: 750 return eclk->u.fixed.rate; 751 case EXYNOS_CLK_PLL: 752 return exynos5410_clock_get_rate_pll(priv, eclk); 753 case EXYNOS_CLK_MUX: 754 case EXYNOS_CLK_GATE: 755 clk_parent = exynos5410_clock_get_parent(priv, clk); 756 return exynos5410_clock_get_rate(priv, clk_parent); 757 case EXYNOS_CLK_DIV: 758 return exynos5410_clock_get_rate_div(priv, eclk); 759 default: 760 panic("exynos5410: unknown eclk type %d", eclk->type); 761 } 762 } 763 764 static int 765 exynos5410_clock_set_rate(void *priv, struct clk *clk, u_int rate) 766 { 767 struct exynos_clk *eclk = (struct exynos_clk *)clk; 768 769 KASSERT((clk->flags & CLK_SET_RATE_PARENT) == 0); 770 771 switch (eclk->type) { 772 case EXYNOS_CLK_FIXED: 773 return EIO; 774 case EXYNOS_CLK_PLL: 775 return exynos5410_clock_set_rate_pll(priv, eclk, rate); 776 case EXYNOS_CLK_MUX: 777 return EIO; 778 case EXYNOS_CLK_DIV: 779 return exynos5410_clock_set_rate_div(priv, eclk, rate); 780 case EXYNOS_CLK_GATE: 781 return EINVAL; 782 default: 783 panic("exynos5410: unknown eclk type %d", eclk->type); 784 } 785 } 786 787 static int 788 exynos5410_clock_enable(void *priv, struct clk *clk) 789 { 790 struct exynos_clk *eclk = (struct exynos_clk *)clk; 791 792 switch (eclk->type) { 793 case EXYNOS_CLK_FIXED: 794 return 0; /* always on */ 795 case EXYNOS_CLK_PLL: 796 return 0; /* XXX */ 797 case EXYNOS_CLK_MUX: 798 case EXYNOS_CLK_DIV: 799 return 0; 800 case EXYNOS_CLK_GATE: 801 return exynos5410_clock_enable_gate(priv, eclk, true); 802 default: 803 panic("exynos5410: unknown eclk type %d", eclk->type); 804 } 805 } 806 807 static int 808 exynos5410_clock_disable(void *priv, struct clk *clk) 809 { 810 struct exynos_clk *eclk = (struct exynos_clk *)clk; 811 812 switch (eclk->type) { 813 case EXYNOS_CLK_FIXED: 814 return EINVAL; /* always on */ 815 case EXYNOS_CLK_PLL: 816 return EINVAL; /* XXX */ 817 case EXYNOS_CLK_MUX: 818 case EXYNOS_CLK_DIV: 819 return EINVAL; 820 case EXYNOS_CLK_GATE: 821 return exynos5410_clock_enable_gate(priv, eclk, false); 822 default: 823 panic("exynos5410: unknown eclk type %d", eclk->type); 824 } 825 } 826 827 static int 828 exynos5410_clock_set_parent(void *priv, struct clk *clk, struct clk *clk_parent) 829 { 830 struct exynos_clk *eclk = (struct exynos_clk *)clk; 831 struct exynos_clk *eclk_parent = (struct exynos_clk *)clk_parent; 832 833 switch (eclk->type) { 834 case EXYNOS_CLK_FIXED: 835 case EXYNOS_CLK_PLL: 836 case EXYNOS_CLK_DIV: 837 case EXYNOS_CLK_GATE: 838 return EINVAL; 839 case EXYNOS_CLK_MUX: 840 return exynos5410_clock_set_parent_mux(priv, eclk, eclk_parent); 841 default: 842 panic("exynos5410: unknown eclk type %d", eclk->type); 843 } 844 } 845 846 static struct clk * 847 exynos5410_clock_get_parent(void *priv, struct clk *clk) 848 { 849 struct exynos_clk *eclk = (struct exynos_clk *)clk; 850 struct exynos_clk *eclk_parent = NULL; 851 852 switch (eclk->type) { 853 case EXYNOS_CLK_FIXED: 854 case EXYNOS_CLK_PLL: 855 case EXYNOS_CLK_DIV: 856 case EXYNOS_CLK_GATE: 857 if (eclk->parent != NULL) { 858 eclk_parent = exynos5410_clock_find(eclk->parent); 859 } 860 break; 861 case EXYNOS_CLK_MUX: 862 eclk_parent = exynos5410_clock_get_parent_mux(priv, eclk); 863 break; 864 default: 865 panic("exynos5410: unknown eclk type %d", eclk->type); 866 } 867 868 return (struct clk *)eclk_parent; 869 } 870