1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12#include "../../arch/arm/clock.h" 13#include "../../mach/exynos/clock.h" 14#if defined(CONFIG_PLAT_EXYNOS5422) 15#include "exynos_5422_clock.h" 16#else 17#include "exynos_common_clock.h" 18#endif 19#include "../../services.h" 20#include <assert.h> 21#include <string.h> 22#include <utils/util.h> 23 24#define EXYNOS5_CMU_CPU_PADDR 0x10010000 25#define EXYNOS5_CMU_CORE_PADDR 0x10014000 26#define EXYNOS5_CMU_ACP_PADDR 0x10018000 27#define EXYNOS5_CMU_ISP_PADDR 0x1001C000 28#define EXYNOS5_CMU_TOP_PADDR 0x10020000 29#define EXYNOS5_CMU_LEX_PADDR 0x10024000 30#define EXYNOS5_CMU_R0X_PADDR 0x10028000 31#define EXYNOS5_CMU_R1X_PADDR 0x1002C000 32#define EXYNOS5_CMU_CDREX_PADDR 0x10030000 33#define EXYNOS5_CMU_MEM_PADDR 0x10038000 34 35#define EXYNOS5_CMU_SIZE 0x1000 36#define EXYNOS5_CMU_CPU_SIZE EXYNOS5_CMU_SIZE 37#define EXYNOS5_CMU_CORE_SIZE EXYNOS5_CMU_SIZE 38#define EXYNOS5_CMU_ACP_SIZE EXYNOS5_CMU_SIZE 39#define EXYNOS5_CMU_ISP_SIZE EXYNOS5_CMU_SIZE 40#define EXYNOS5_CMU_TOP_SIZE EXYNOS5_CMU_SIZE 41#define EXYNOS5_CMU_LEX_SIZE EXYNOS5_CMU_SIZE 42#define EXYNOS5_CMU_R0X_SIZE EXYNOS5_CMU_SIZE 43#define EXYNOS5_CMU_R1X_SIZE EXYNOS5_CMU_SIZE 44#define EXYNOS5_CMU_CDREX_SIZE EXYNOS5_CMU_SIZE 45#define EXYNOS5_CMU_MEM_SIZE EXYNOS5_CMU_SIZE 46 47#define CLKID_UART0 CLKID(TOP, 20, 0) 48#define CLKID_UART1 CLKID(TOP, 20, 1) 49#define CLKID_UART2 CLKID(TOP, 20, 2) 50#define CLKID_UART3 CLKID(TOP, 20, 3) 51#define CLKID_PWM CLKID(TOP, 20, 5) 52#define CLKID_SPI0 CLKID(TOP, 21, 4) 53#define CLKID_SPI1 CLKID(TOP, 21, 5) 54#define CLKID_SPI2 CLKID(TOP, 21, 6) 55#define CLKID_SPI0_ISP CLKID(TOP, 28, 0) 56#define CLKID_SPI1_ISP CLKID(TOP, 28, 1) 57 58volatile struct clk_regs* _clk_regs[NCLKREGS]; 59 60static struct clock master_clk = { CLK_OPS(MASTER, default_clk, NULL) }; 61 62static struct mpsk_tbl _ambcgpll_tbl[] = { 63 { 200, PLL_MPS( 100, 3, 2), 0 }, 64 { 333, PLL_MPS( 222, 4, 2), 0 }, 65 { 400, PLL_MPS( 100, 3, 1), 0 }, 66 { 533, PLL_MPS( 533, 12, 1), 0 }, 67 { 600, PLL_MPS( 200, 4, 1), 0 }, 68 { 667, PLL_MPS( 389, 7, 1), 0 }, 69 { 800, PLL_MPS( 100, 3, 0), 0 }, 70 { 1000, PLL_MPS( 125, 3, 0), 0 }, 71 { 1066, PLL_MPS( 533, 12, 0), 0 }, 72 { 1200, PLL_MPS( 150, 3, 0), 0 }, 73 { 1400, PLL_MPS( 175, 3, 0), 0 }, 74 { 1600, PLL_MPS( 200, 3, 0), 0 } 75}; 76 77static struct mpsk_tbl _epll_tbl[] = { 78 { 33, PLL_MPS( 131, 3, 5), 4719 }, 79 { 45, PLL_MPS( 90, 3, 4), 20762 }, 80 { 48, PLL_MPS( 64, 2, 4), 0 }, 81 { 49, PLL_MPS( 98, 3, 4), 19923 }, 82 { 50, PLL_MPS( 67, 2, 4), 43691 }, 83 { 68, PLL_MPS( 90, 2, 4), 20762 }, 84 { 74, PLL_MPS( 98, 2, 4), 19923 }, 85 { 80, PLL_MPS( 107, 2, 4), 43691 }, 86 { 84, PLL_MPS( 112, 2, 4), 0 }, 87 { 96, PLL_MPS( 64, 2, 3), 0 }, 88 { 144, PLL_MPS( 96, 2, 3), 0 }, 89 { 192, PLL_MPS( 64, 2, 2), 0 }, 90 { 288, PLL_MPS( 96, 2, 2), 0 }, 91}; 92 93static struct mpsk_tbl _vpll_tbl[] = { 94 { 27, PLL_MPS( 72, 2, 5), 0 }, 95 { 54, PLL_MPS( 72, 2, 4), 0 }, 96 { 74, PLL_MPS( 99, 2, 4), 0 }, 97 { 108, PLL_MPS( 72, 2, 3), 0 }, 98 { 148, PLL_MPS( 99, 2, 3), 59070 }, 99 { 149, PLL_MPS( 99, 2, 3), 0 }, 100 { 223, PLL_MPS( 74, 2, 2), 16384 }, 101 { 300, PLL_MPS( 100, 2, 2), 0 }, 102 { 320, PLL_MPS( 107, 2, 2), 43691 }, 103 { 330, PLL_MPS( 110, 2, 2), 0 }, 104 { 333, PLL_MPS( 111, 2, 2), 0 }, 105 { 335, PLL_MPS( 112, 2, 2), 43691 }, 106 { 371, PLL_MPS( 62, 2, 1), 53292 }, 107 { 445, PLL_MPS( 111, 3, 1), 17285 }, 108 { 446, PLL_MPS( 74, 2, 1), 16384 }, 109 { 519, PLL_MPS( 130, 3, 1), 52937 }, 110 { 600, PLL_MPS( 100, 2, 1), 0 }, 111}; 112 113static struct pll_priv sclkmpll_priv = PLL_PRIV(SCLKMPLL, MPS, _ambcgpll_tbl); 114static struct pll_priv sclkcpll_priv = PLL_PRIV(SCLKCPLL, MPS, _ambcgpll_tbl); 115 116static struct pll_priv sclkepll_priv = PLL_PRIV(SCLKEPLL, MPSK, _epll_tbl); 117static struct pll_priv sclkvpll_priv = PLL_PRIV(SCLKVPLL, MPSK, _vpll_tbl); 118 119static struct clock sclkmpll_clk = { CLK_OPS(SCLKMPLL, pll, &sclkmpll_priv) }; 120static struct clock sclkcpll_clk = { CLK_OPS(SCLKCPLL, pll, &sclkcpll_priv) }; 121static struct clock sclkepll_clk = { CLK_OPS(SCLKEPLL, pll, &sclkepll_priv) }; 122static struct clock sclkvpll_clk = { CLK_OPS(SCLKVPLL, pll, &sclkvpll_priv) }; 123 124#if !defined(CONFIG_PLAT_EXYNOS5422) 125static struct pll_priv sclkbpll_priv = PLL_PRIV(SCLKBPLL, MPS, _ambcgpll_tbl); 126static struct pll_priv sclkgpll_priv = PLL_PRIV(SCLKGPLL, MPS, _ambcgpll_tbl); 127 128static struct clock sclkgpll_clk = { CLK_OPS(SCLKGPLL, pll, &sclkgpll_priv) }; 129static struct clock sclkbpll_clk = { CLK_OPS(SCLKBPLL, pll, &sclkbpll_priv) }; 130#endif 131 132/* The SPI div register is a special case as we have 2 dividers, one of which 133 * is 2 nibbles wide */ 134static freq_t 135_spi_get_freq(clk_t* clk) 136{ 137 freq_t fin; 138 int clkid; 139 int rpre, r; 140 clkid = exynos_clk_get_priv_id(clk); 141 switch (clk->id) { 142 case CLK_SPI0_ISP: 143 clkid += 32; 144 break; 145 case CLK_SPI1_ISP: 146 clkid += 35; 147 break; 148 case CLK_SPI0: 149 clkid += 12; 150 break; 151 case CLK_SPI1: 152 clkid += 15; 153 break; 154 case CLK_SPI2: 155 clkid += 18; 156 break; 157 default: 158 return 0; 159 } 160 r = exynos_cmu_get_div(_clk_regs, clkid, 1); 161 rpre = exynos_cmu_get_div(_clk_regs, clkid + 2, 2); 162 fin = clk_get_freq(clk->parent); 163 return fin / (r + 1) / (rpre + 1); 164} 165 166static freq_t 167_spi_set_freq(clk_t* clk, freq_t hz) 168{ 169 freq_t fin; 170 int clkid; 171 int rpre, r; 172 clkid = exynos_clk_get_priv_id(clk); 173 switch (clk->id) { 174 case CLK_SPI0_ISP: 175 clkid += 32; 176 break; 177 case CLK_SPI1_ISP: 178 clkid += 35; 179 break; 180 case CLK_SPI0: 181 clkid += 12; 182 break; 183 case CLK_SPI1: 184 clkid += 15; 185 break; 186 case CLK_SPI2: 187 clkid += 18; 188 break; 189 default: 190 return 0; 191 } 192 fin = clk_get_freq(clk->parent); 193 rpre = fin / 0xf / hz; 194 r = fin / (rpre + 1) / hz; 195 exynos_cmu_set_div(_clk_regs, clkid, 1, r); 196 exynos_cmu_set_div(_clk_regs, clkid + 2, 2, rpre); 197 return clk_get_freq(clk); 198} 199 200static void 201_spi_recal(clk_t* clk) 202{ 203 assert(!"Not implemented"); 204} 205 206static clk_t* 207_spi_init(clk_t* clk) 208{ 209 /* MUX -> DIVspix -> DIVspipre */ 210 clk_t* parent; 211 int clkid; 212 int src; 213 clkid = exynos_clk_get_priv_id(clk); 214 src = exynos_cmu_get_src(_clk_regs, clkid); 215 assert(src < ARRAY_SIZE(clk_src_peri_blk) && src >= 0); 216 assert(clk_src_peri_blk[src] != -1); 217 parent = clk_get_clock(clk->clk_sys, clk_src_peri_blk[src]); 218 assert(parent); 219 clk_init(parent); 220 clk_register_child(parent, clk); 221 return clk; 222} 223 224static struct clock spi0_clk = { CLK_OPS(SPI0 , spi, CLKID_SPI0 ) }; 225static struct clock spi1_clk = { CLK_OPS(SPI1 , spi, CLKID_SPI1 ) }; 226static struct clock spi2_clk = { CLK_OPS(SPI2 , spi, CLKID_SPI2 ) }; 227static struct clock spi0_isp_clk = { CLK_OPS(SPI0_ISP, spi, CLKID_SPI0_ISP) }; 228static struct clock spi1_isp_clk = { CLK_OPS(SPI1_ISP, spi, CLKID_SPI1_ISP) }; 229 230static freq_t 231_peric_clk_get_freq(clk_t* clk) 232{ 233 freq_t fin; 234 int clkid; 235 int div; 236 clkid = exynos_clk_get_priv_id(clk); 237 /* The DIV register has an additional 2 word offset */ 238 clkid += 16; 239 div = exynos_cmu_get_div(_clk_regs, clkid, 1); 240 fin = clk_get_freq(clk->parent); 241 return fin / (div + 1); 242} 243 244static freq_t 245_peric_clk_set_freq(clk_t* clk, freq_t hz) 246{ 247 freq_t fin; 248 int clkid; 249 int div; 250 fin = clk_get_freq(clk->parent); 251 div = fin / hz; 252 clkid = exynos_clk_get_priv_id(clk); 253 /* The DIV register has an additional 2 word offset */ 254 clkid += 16; 255 exynos_cmu_set_div(_clk_regs, clkid, 1, div); 256 return clk_get_freq(clk); 257} 258 259static void 260_peric_clk_recal(clk_t* clk) 261{ 262 assert(!"Not implemented"); 263} 264 265static clk_t* 266_peric_clk_init(clk_t* clk) 267{ 268 /* MUX -> DIVuartx -> DIVuartpre */ 269 clk_t* parent; 270 int clkid; 271 int src; 272 clkid = exynos_clk_get_priv_id(clk); 273 src = exynos_cmu_get_src(_clk_regs, clkid); 274 assert(src < ARRAY_SIZE(clk_src_peri_blk) && src >= 0); 275 assert(clk_src_peri_blk[src] != -1); 276 parent = clk_get_clock(clk->clk_sys, clk_src_peri_blk[src]); 277 assert(parent); 278 clk_init(parent); 279 clk_register_child(parent, clk); 280 return clk; 281} 282 283static struct clock uart0_clk = { CLK_OPS(UART0, peric_clk, CLKID_UART0) }; 284static struct clock uart1_clk = { CLK_OPS(UART1, peric_clk, CLKID_UART1) }; 285static struct clock uart2_clk = { CLK_OPS(UART2, peric_clk, CLKID_UART2) }; 286static struct clock uart3_clk = { CLK_OPS(UART3, peric_clk, CLKID_UART3) }; 287static struct clock pwm_clk = { CLK_OPS(PWM , peric_clk, CLKID_PWM ) }; 288 289static int 290exynos5_gate_enable(clock_sys_t* clock_sys, enum clock_gate gate, enum clock_gate_mode mode) 291{ 292 return -1; 293} 294 295static int 296clock_sys_common_init(clock_sys_t* clock_sys) 297{ 298 clock_sys->priv = (void*)&_clk_regs; 299 clock_sys->get_clock = &ps_get_clock; 300 clock_sys->gate_enable = &exynos5_gate_enable; 301 return 0; 302} 303 304int 305exynos5_clock_sys_init(void* cpu, void* core, void* acp, void* isp, void* top, 306 void* lex, void* r0x, void* r1x, void* cdrex, void* mem, 307 clock_sys_t* clock_sys) 308{ 309 if (cpu) { 310 _clk_regs[CLKREGS_CPU] = cpu; 311 } 312 if (core) { 313 _clk_regs[CLKREGS_CORE] = core; 314 } 315 if (acp) { 316 _clk_regs[CLKREGS_ACP] = acp; 317 } 318 if (isp) { 319 _clk_regs[CLKREGS_ISP] = isp; 320 } 321 if (top) { 322 _clk_regs[CLKREGS_TOP] = top; 323 } 324 if (lex) { 325 _clk_regs[CLKREGS_LEX] = lex; 326 } 327 if (r0x) { 328 _clk_regs[CLKREGS_R0X] = r0x; 329 } 330 if (r1x) { 331 _clk_regs[CLKREGS_R1X] = r1x; 332 } 333 if (cdrex) { 334 _clk_regs[CLKREGS_CDREX] = cdrex; 335 } 336 if (mem) { 337 _clk_regs[CLKREGS_MEM] = mem; 338 } 339 return clock_sys_common_init(clock_sys); 340} 341 342int 343clock_sys_init(ps_io_ops_t* o, clock_sys_t* clock_sys) 344{ 345 MAP_IF_NULL(o, EXYNOS5_CMU_CPU, _clk_regs[CLKREGS_CPU]); 346 MAP_IF_NULL(o, EXYNOS5_CMU_CORE, _clk_regs[CLKREGS_CORE]); 347 MAP_IF_NULL(o, EXYNOS5_CMU_ACP, _clk_regs[CLKREGS_ACP]); 348 MAP_IF_NULL(o, EXYNOS5_CMU_ISP, _clk_regs[CLKREGS_ISP]); 349 MAP_IF_NULL(o, EXYNOS5_CMU_TOP, _clk_regs[CLKREGS_TOP]); 350 MAP_IF_NULL(o, EXYNOS5_CMU_LEX, _clk_regs[CLKREGS_LEX]); 351 MAP_IF_NULL(o, EXYNOS5_CMU_R0X, _clk_regs[CLKREGS_R0X]); 352 MAP_IF_NULL(o, EXYNOS5_CMU_R1X, _clk_regs[CLKREGS_R1X]); 353 MAP_IF_NULL(o, EXYNOS5_CMU_CDREX, _clk_regs[CLKREGS_CDREX]); 354 return clock_sys_common_init(clock_sys); 355} 356 357void 358clk_print_clock_tree(clock_sys_t* sys) 359{ 360 (void)sys; 361 clk_t* clk = ps_clocks[CLK_MASTER]; 362 clk_print_tree(clk, ""); 363} 364 365clk_t* ps_clocks[] = { 366 [CLK_MASTER ] = &master_clk, 367 [CLK_SPI0 ] = &spi0_clk, 368 [CLK_SPI1 ] = &spi1_clk, 369 [CLK_SPI2 ] = &spi2_clk, 370 [CLK_SPI0_ISP] = &spi0_isp_clk, 371 [CLK_SPI1_ISP] = &spi1_isp_clk, 372 [CLK_UART0 ] = &uart0_clk, 373 [CLK_UART1 ] = &uart1_clk, 374 [CLK_UART2 ] = &uart2_clk, 375 [CLK_UART3 ] = &uart3_clk, 376 [CLK_PWM ] = &pwm_clk, 377 [CLK_SCLKMPLL] = &sclkmpll_clk, 378 [CLK_SCLKCPLL] = &sclkcpll_clk, 379 [CLK_SCLKEPLL] = &sclkepll_clk, 380 [CLK_SCLKVPLL] = &sclkvpll_clk, 381#if !defined(CONFIG_PLAT_EXYNOS5422) 382 [CLK_SCLKBPLL] = &sclkbpll_clk, 383 [CLK_SCLKGPLL] = &sclkgpll_clk, 384#endif 385}; 386 387/* These frequencies are NOT the recommended 388 * frequencies. They are to be used when we 389 * need to make assumptions about what u-boot 390 * has left us with. */ 391freq_t ps_freq_default[] = { 392 [CLK_MASTER ] = 24 * MHZ, 393 [CLK_SCLKVPLL] = 24 * MHZ, 394 [CLK_SCLKGPLL] = 1056 * MHZ, 395 [CLK_SCLKBPLL] = 800 * MHZ, 396 [CLK_PWM ] = 24 * MHZ, 397 [CLK_SCLKCPLL] = 640 * MHZ, 398 [CLK_UART3 ] = 64 * MHZ, 399 [CLK_UART2 ] = 64 * MHZ, 400 [CLK_UART1 ] = 64 * MHZ, 401 [CLK_UART0 ] = 64 * MHZ, 402 [CLK_SPI1_ISP] = 24 * MHZ, 403 [CLK_SPI0_ISP] = 24 * MHZ, 404 [CLK_SCLKMPLL] = 532 * MHZ, 405 [CLK_SPI1 ] = 53200 * KHZ, 406 [CLK_SCLKEPLL] = 24 * MHZ, 407 [CLK_SPI2 ] = 6 * MHZ, 408 [CLK_SPI0 ] = 6 * MHZ, 409}; 410