1 /* $NetBSD: exynos_soc.c,v 1.41 2022/10/29 13:29:46 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Reinoud Zandijk. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "opt_arm_debug.h" 33 #include "opt_exynos.h" 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(1, "$NetBSD: exynos_soc.c,v 1.41 2022/10/29 13:29:46 jmcneill Exp $"); 37 38 #include <sys/param.h> 39 #include <sys/bus.h> 40 #include <sys/cpu.h> 41 #include <sys/device.h> 42 43 #include <prop/proplib.h> 44 45 #include <net/if.h> 46 #include <net/if_ether.h> 47 48 #include <arm/locore.h> 49 50 #include <arm/mainbus/mainbus.h> 51 #include <arm/cortex/mpcore_var.h> 52 53 #include <arm/samsung/exynos_reg.h> 54 #include <arm/samsung/exynos_var.h> 55 #include <arm/samsung/mct_reg.h> 56 #include <arm/samsung/smc.h> 57 58 #include <arm/cortex/pl310_var.h> 59 #include <arm/cortex/pl310_reg.h> 60 61 #include <evbarm/fdt/platform.h> 62 63 #define EXYNOS_CORE_VBASE KERNEL_IO_VBASE 64 65 66 /* these variables are retrieved in start.S and stored in .data */ 67 uint32_t exynos_soc_id = 0; 68 uint32_t exynos_pop_id = 0; 69 70 /* cpu frequencies */ 71 struct cpu_freq { 72 uint64_t freq; 73 int P; 74 int M; 75 int S; 76 }; 77 78 79 #ifdef SOC_EXYNOS4 80 int exynos4_l2cc_init(void); 81 82 const struct cpu_freq cpu_freq_settings_exynos4[] = { 83 { 200, 3, 100, 2}, 84 { 300, 4, 200, 2}, 85 { 400, 3, 100, 1}, 86 { 500, 3, 125, 1}, 87 { 600, 4, 200, 1}, 88 { 700, 3, 175, 1}, 89 { 800, 3, 100, 0}, 90 { 900, 4, 150, 0}, 91 {1000, 3, 125, 0}, 92 {1100, 6, 275, 0}, 93 {1200, 4, 200, 0}, 94 {1300, 6, 325, 0}, 95 {1400, 3, 175, 0}, 96 {1600, 3, 200, 0}, 97 // {1704, 3, 213, 0}, 98 // {1800, 4, 300, 0}, 99 // {1920, 3, 240, 0}, 100 // {2000, 3, 250, 0}, 101 }; 102 #endif 103 104 105 #ifdef SOC_EXYNOS5 106 #define EXYNOS5_DEFAULT_ENTRY 7 107 const struct cpu_freq cpu_freq_settings_exynos5[] = { 108 { 200, 3, 100, 2}, 109 { 333, 4, 222, 2}, 110 { 400, 3, 100, 1}, 111 { 533, 12, 533, 1}, 112 { 600, 4, 200, 1}, 113 { 667, 7, 389, 1}, 114 { 800, 3, 100, 0}, 115 { 900, 4, 150, 0}, 116 {1000, 3, 125, 0}, 117 {1066, 12, 533, 0}, 118 {1200, 3, 150, 0}, 119 {1400, 3, 175, 0}, 120 {1600, 3, 200, 0}, 121 }; 122 #endif 123 124 static struct cpu_freq const *cpu_freq_settings = NULL; 125 static int ncpu_freq_settings = 0; 126 127 static int cpu_freq_target = 0; 128 #define NFRQS 18 129 static char sysctl_cpu_freqs_txt[NFRQS*5]; 130 131 bus_space_handle_t exynos_core_bsh; 132 bus_space_handle_t exynos_audiocore_bsh; 133 134 bus_space_handle_t exynos_wdt_bsh; 135 bus_space_handle_t exynos_pmu_bsh; 136 bus_space_handle_t exynos_cmu_bsh; 137 bus_space_handle_t exynos_cmu_apll_bsh; 138 bus_space_handle_t exynos_sysreg_bsh; 139 140 141 static int sysctl_cpufreq_target(SYSCTLFN_ARGS); 142 static int sysctl_cpufreq_current(SYSCTLFN_ARGS); 143 144 #ifdef ARM_TRUSTZONE_FIRMWARE 145 int 146 exynos_do_idle(void) 147 { 148 exynos_smc(SMC_CMD_SLEEP, 0, 0, 0); 149 150 return 0; 151 } 152 153 154 int 155 exynos_set_cpu_boot_addr(int cpu, vaddr_t boot_addr) 156 { 157 /* XXX we need to map in iRAM space for this XXX */ 158 return 0; 159 } 160 161 162 int 163 exynos_cpu_boot(int cpu) 164 { 165 exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0); 166 167 return 0; 168 } 169 170 171 #ifdef SOC_EXYNOS4 172 /* 173 * The latency values used below are `magic' and probably chosen empirically. 174 * For the 4210 variant the data latency is lower, a 0x110. This is currently 175 * not enforced. 176 * 177 * The prefetch values are also different for the revision 0 of the 178 * Exynos4412, but why? 179 */ 180 181 int 182 exynos4_l2cc_init(void) 183 { 184 const uint32_t tag_latency = 0x110; 185 const uint32_t data_latency = IS_EXYNOS4410_P() ? 0x110 : 0x120; 186 const uint32_t prefetch4412 = /* 0111 0001 0000 0000 0000 0000 0000 0111 */ 187 PREFETCHCTL_DBLLINEF_EN | 188 PREFETCHCTL_INSTRPREF_EN | 189 PREFETCHCTL_DATAPREF_EN | 190 PREFETCHCTL_PREF_DROP_EN | 191 PREFETCHCTL_PREFETCH_OFFSET_7; 192 const uint32_t prefetch4412_r0 = /* 0011 0000 0000 0000 0000 0000 0000 0111 */ 193 PREFETCHCTL_INSTRPREF_EN | 194 PREFETCHCTL_DATAPREF_EN | 195 PREFETCHCTL_PREFETCH_OFFSET_7; 196 const uint32_t aux_val = /* 0111 1100 0100 0111 0000 0000 0000 0001 */ 197 AUXCTL_EARLY_BRESP_EN | 198 AUXCTL_I_PREFETCH | 199 AUXCTL_D_PREFETCH | 200 AUXCTL_NS_INT_ACC_CTL | 201 AUXCTL_NS_INT_LOCK_EN | 202 AUXCTL_SHARED_ATT_OVR | 203 AUXCTL_WAY_SIZE_RSVD7 << 16 | /* why rsvd7 ??? */ 204 AUXCTL_FULL_LINE_WR0; 205 const uint32_t aux_keepmask = /* 1100 0010 0000 0000 1111 1111 1111 1111 */ 206 AUXCTL_RSVD31 | 207 AUXCTL_EARLY_BRESP_EN | 208 AUXCTL_CACHE_REPL_RR | 209 210 AUXCTL_SH_ATTR_INV_ENA| 211 AUXCTL_EXCL_CACHE_CFG | 212 AUXCTL_ST_BUF_DEV_LIM_EN | 213 AUXCTL_HIPRO_SO_DEV_EN | 214 AUXCTL_FULL_LINE_WR0 | 215 0xffff; 216 uint32_t prefetch; 217 218 /* check the bitmaps are the same as the linux implementation uses */ 219 KASSERT(prefetch4412 == 0x71000007); 220 KASSERT(prefetch4412_r0 == 0x30000007); 221 KASSERT(aux_val == 0x7C470001); 222 KASSERT(aux_keepmask == 0xC200FFFF); 223 224 if (IS_EXYNOS4412_R0_P()) 225 prefetch = prefetch4412_r0; 226 else 227 prefetch = prefetch4412; /* newer than >= r1_0 */ 228 ; 229 230 exynos_smc(SMC_CMD_L2X0SETUP1, tag_latency, data_latency, prefetch); 231 exynos_smc(SMC_CMD_L2X0SETUP2, 232 POWERCTL_DYNCLKGATE | POWERCTL_STANDBY, 233 aux_val, aux_keepmask); 234 exynos_smc(SMC_CMD_L2X0INVALL, 0, 0, 0); 235 exynos_smc(SMC_CMD_L2X0CTRL, 1, 0, 0); 236 237 return 0; 238 } 239 #endif 240 #endif /* ARM_TRUSTZONE_FIRMWARE */ 241 242 243 void 244 exynos_sysctl_cpufreq_init(void) 245 { 246 const struct sysctlnode *node, *cpunode, *freqnode; 247 char *cpos; 248 int i, val; 249 int error; 250 251 memset(sysctl_cpu_freqs_txt, (int) ' ', sizeof(sysctl_cpu_freqs_txt)); 252 cpos = sysctl_cpu_freqs_txt; 253 for (i = 0; i < ncpu_freq_settings; i++) { 254 val = cpu_freq_settings[i].freq; 255 snprintf(cpos, 6, "%d ", val); 256 cpos += (val < 1000) ? 4 : 5; 257 } 258 *cpos = 0; 259 260 error = sysctl_createv(NULL, 0, NULL, &node, 261 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, 262 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL); 263 if (error) 264 printf("couldn't create `machdep' node\n"); 265 266 error = sysctl_createv(NULL, 0, &node, &cpunode, 267 0, CTLTYPE_NODE, "cpu", NULL, 268 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); 269 if (error) 270 printf("couldn't create `cpu' node\n"); 271 272 error = sysctl_createv(NULL, 0, &cpunode, &freqnode, 273 0, CTLTYPE_NODE, "frequency", NULL, 274 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); 275 if (error) 276 printf("couldn't create `frequency' node\n"); 277 278 error = sysctl_createv(NULL, 0, &freqnode, &node, 279 CTLFLAG_READWRITE, CTLTYPE_INT, "target", NULL, 280 sysctl_cpufreq_target, 0, &cpu_freq_target, 0, 281 CTL_CREATE, CTL_EOL); 282 if (error) 283 printf("couldn't create `target' node\n"); 284 285 error = sysctl_createv(NULL, 0, &freqnode, &node, 286 0, CTLTYPE_INT, "current", NULL, 287 sysctl_cpufreq_current, 0, NULL, 0, 288 CTL_CREATE, CTL_EOL); 289 if (error) 290 printf("couldn't create `current' node\n"); 291 292 error = sysctl_createv(NULL, 0, &freqnode, &node, 293 CTLFLAG_READONLY, CTLTYPE_STRING, "available", NULL, 294 NULL, 0, sysctl_cpu_freqs_txt, 0, 295 CTL_CREATE, CTL_EOL); 296 if (error) 297 printf("couldn't create `available' node\b"); 298 } 299 300 301 uint64_t 302 exynos_get_cpufreq(void) 303 { 304 uint32_t regval; 305 uint32_t freq; 306 307 regval = bus_space_read_4(&armv7_generic_bs_tag, exynos_cmu_apll_bsh, 308 PLL_CON0_OFFSET); 309 freq = PLL_FREQ(EXYNOS_F_IN_FREQ, regval); 310 311 return freq; 312 } 313 314 315 static void 316 exynos_set_cpufreq(const struct cpu_freq *freqreq) 317 { 318 struct cpu_info *ci; 319 uint32_t regval; 320 int M, P, S; 321 int cii; 322 323 M = freqreq->M; 324 P = freqreq->P; 325 S = freqreq->S; 326 327 regval = __SHIFTIN(M, PLL_CON0_M) | 328 __SHIFTIN(P, PLL_CON0_P) | 329 __SHIFTIN(S, PLL_CON0_S); 330 331 /* enable PPL and write config */ 332 regval |= PLL_CON0_ENABLE; 333 bus_space_write_4(&armv7_generic_bs_tag, exynos_cmu_apll_bsh, PLL_CON0_OFFSET, 334 regval); 335 336 /* update our cycle counter i.e. our CPU frequency for all CPUs */ 337 for (CPU_INFO_FOREACH(cii, ci)) { 338 ci->ci_data.cpu_cc_freq = exynos_get_cpufreq(); 339 } 340 } 341 342 343 static int 344 sysctl_cpufreq_target(SYSCTLFN_ARGS) 345 { 346 struct sysctlnode node; 347 uint32_t t, curfreq, minfreq, maxfreq; 348 int i, best_i, diff; 349 int error; 350 351 curfreq = exynos_get_cpufreq() / (1000*1000); 352 t = *(int *)rnode->sysctl_data; 353 if (t == 0) 354 t = curfreq; 355 356 node = *rnode; 357 node.sysctl_data = &t; 358 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 359 if (error || newp == NULL) 360 return error; 361 362 minfreq = cpu_freq_settings[0].freq; 363 maxfreq = cpu_freq_settings[ncpu_freq_settings-1].freq; 364 365 if ((t < minfreq) || (t > maxfreq)) 366 return EINVAL; 367 368 if (t == curfreq) { 369 *(int *)rnode->sysctl_data = t; 370 return 0; 371 } 372 373 diff = maxfreq; 374 best_i = -1; 375 for (i = 0; i < ncpu_freq_settings; i++) { 376 if (abs(t - cpu_freq_settings[i].freq) <= diff) { 377 diff = labs(t - cpu_freq_settings[i].freq); 378 best_i = i; 379 } 380 } 381 if (best_i < 0) 382 return EINVAL; 383 384 exynos_set_cpufreq(&cpu_freq_settings[best_i]); 385 386 *(int *)rnode->sysctl_data = t; 387 return 0; 388 } 389 390 391 static int 392 sysctl_cpufreq_current(SYSCTLFN_ARGS) 393 { 394 struct sysctlnode node = *rnode; 395 uint32_t freq; 396 397 freq = exynos_get_cpufreq() / (1000*1000); 398 node.sysctl_data = &freq; 399 400 return sysctl_lookup(SYSCTLFN_CALL(&node)); 401 } 402 403 404 #ifdef VERBOSE_INIT_ARM 405 #define VPRINTF(...) printf(__VA_ARGS__) 406 407 #define DUMP_PLL(v, var) \ 408 reg = EXYNOS##v##_CMU_##var + PLL_CON0_OFFSET;\ 409 regval = bus_space_read_4(&armv7_generic_bs_tag, exynos_cmu_bsh, reg); \ 410 freq = PLL_FREQ(EXYNOS_F_IN_FREQ, regval); \ 411 printf("%8s at %d Mhz\n", #var, freq/(1000*1000)); 412 413 414 static void 415 exynos_dump_clocks(void) 416 { 417 uint32_t reg = 0; 418 uint32_t regval; 419 uint32_t freq; 420 421 printf("Initial PLL settings\n"); 422 #ifdef SOC_EXYNOS4 423 DUMP_PLL(4, APLL); 424 DUMP_PLL(4, MPLL); 425 DUMP_PLL(4, EPLL); 426 DUMP_PLL(4, VPLL); 427 #endif 428 #ifdef SOC_EXYNOS5 429 DUMP_PLL(5, APLL); 430 DUMP_PLL(5, MPLL); 431 DUMP_PLL(5, KPLL); 432 DUMP_PLL(5, DPLL); 433 DUMP_PLL(5, VPLL); 434 DUMP_PLL(5, CPLL); 435 DUMP_PLL(5, GPLL); 436 DUMP_PLL(5, BPLL); 437 #endif 438 } 439 #undef DUMP_PLL 440 #else 441 #define VPRINTF(...) __nothing 442 #endif 443 444 445 /* XXX clock stuff needs major work XXX */ 446 447 void 448 exynos_init_clkout_for_usb(void) 449 { 450 /* Select XUSBXTI as source for CLKOUT */ 451 bus_space_write_4(&armv7_generic_bs_tag, exynos_pmu_bsh, 452 EXYNOS_PMU_DEBUG_CLKOUT, 0x1000); 453 } 454 455 456 void 457 exynos_clocks_bootstrap(void) 458 { 459 KASSERT(ncpu_freq_settings != 0); 460 KASSERT(ncpu_freq_settings < NFRQS); 461 int fsel; 462 463 #ifdef VERBOSE_INIT_ARM 464 exynos_dump_clocks(); 465 #endif 466 467 /* set (max) cpufreq */ 468 fsel = ncpu_freq_settings-1; 469 470 #ifdef SOC_EXYNOS5 471 /* XXX BUGFIX selecting freq on E5 goes wrong for now XXX */ 472 fsel = EXYNOS5_DEFAULT_ENTRY; 473 #endif 474 475 exynos_set_cpufreq(&cpu_freq_settings[fsel]); 476 477 /* set external USB frequency to XCLKOUT */ 478 exynos_init_clkout_for_usb(); 479 } 480 481 482 void 483 exynos_bootstrap(int soc) 484 { 485 int error; 486 size_t core_size, audiocore_size; 487 bus_addr_t audiocore_pbase; 488 bus_addr_t audiocore_vbase __diagused; 489 bus_addr_t exynos_wdt_offset; 490 bus_addr_t exynos_pmu_offset; 491 bus_addr_t exynos_sysreg_offset; 492 bus_addr_t exynos_cmu_apll_offset; 493 494 switch (soc) { 495 #ifdef SOC_EXYNOS4 496 case 4: 497 core_size = EXYNOS4_CORE_SIZE; 498 audiocore_size = EXYNOS4_AUDIOCORE_SIZE; 499 audiocore_pbase = EXYNOS4_AUDIOCORE_PBASE; 500 audiocore_vbase = EXYNOS4_AUDIOCORE_VBASE; 501 exynos_wdt_offset = EXYNOS4_WDT_OFFSET; 502 exynos_pmu_offset = EXYNOS4_PMU_OFFSET; 503 exynos_sysreg_offset = EXYNOS4_SYSREG_OFFSET; 504 exynos_cmu_apll_offset = EXYNOS4_CMU_APLL; 505 506 cpu_freq_settings = cpu_freq_settings_exynos4; 507 ncpu_freq_settings = __arraycount(cpu_freq_settings_exynos4); 508 break; 509 #endif 510 #ifdef SOC_EXYNOS5 511 case 5: 512 core_size = EXYNOS5_CORE_SIZE; 513 audiocore_size = EXYNOS5_AUDIOCORE_SIZE; 514 audiocore_pbase = EXYNOS5_AUDIOCORE_PBASE; 515 audiocore_vbase = EXYNOS5_AUDIOCORE_VBASE; 516 exynos_wdt_offset = EXYNOS5_WDT_OFFSET; 517 exynos_pmu_offset = EXYNOS5_PMU_OFFSET; 518 exynos_sysreg_offset = EXYNOS5_SYSREG_OFFSET; 519 exynos_cmu_apll_offset = EXYNOS5_CMU_APLL; 520 521 cpu_freq_settings = cpu_freq_settings_exynos5; 522 ncpu_freq_settings = __arraycount(cpu_freq_settings_exynos5); 523 break; 524 #endif 525 default: 526 panic("%s: unknown soc version", __func__); 527 } 528 529 /* map in the exynos io registers */ 530 error = bus_space_map(&armv7_generic_bs_tag, EXYNOS_CORE_PBASE, 531 core_size, 0, &exynos_core_bsh); 532 if (error) 533 panic("%s: failed to map in Exynos SFR registers: %d", 534 __func__, error); 535 KASSERT(exynos_core_bsh == EXYNOS_CORE_VBASE); 536 537 error = bus_space_map(&armv7_generic_bs_tag, audiocore_pbase, 538 audiocore_size, 0, &exynos_audiocore_bsh); 539 if (error) 540 panic("%s: failed to map in Exynos audio SFR registers: %d", 541 __func__, error); 542 KASSERT(exynos_audiocore_bsh == audiocore_vbase); 543 544 /* map in commonly used subregions and common used register banks */ 545 error = bus_space_subregion(&armv7_generic_bs_tag, exynos_core_bsh, 546 exynos_wdt_offset, EXYNOS_BLOCK_SIZE, &exynos_wdt_bsh); 547 if (error) 548 panic("%s: failed to subregion wdt registers: %d", 549 __func__, error); 550 551 error = bus_space_subregion(&armv7_generic_bs_tag, exynos_core_bsh, 552 exynos_pmu_offset, EXYNOS_BLOCK_SIZE, &exynos_pmu_bsh); 553 if (error) 554 panic("%s: failed to subregion pmu registers: %d", 555 __func__, error); 556 557 exynos_cmu_bsh = exynos_core_bsh; 558 bus_space_subregion(&armv7_generic_bs_tag, exynos_core_bsh, 559 exynos_sysreg_offset, EXYNOS_BLOCK_SIZE, 560 &exynos_sysreg_bsh); 561 if (error) 562 panic("%s: failed to subregion sysreg registers: %d", 563 __func__, error); 564 565 error = bus_space_subregion(&armv7_generic_bs_tag, exynos_cmu_bsh, 566 exynos_cmu_apll_offset, 0xfff, &exynos_cmu_apll_bsh); 567 if (error) 568 panic("%s: failed to subregion cmu apll registers: %d", 569 __func__, error); 570 571 /* gpio bootstrapping delayed */ 572 } 573 574 575 void 576 exynos_device_register(device_t self, void *aux) 577 { 578 if (device_is_a(self, "armperiph") 579 && device_is_a(device_parent(self), "mainbus")) { 580 /* 581 * XXX KLUDGE ALERT XXX 582 * The iot mainbus supplies is completely wrong since it scales 583 * addresses by 2. The simplest remedy is to replace with our 584 * bus space used for the armcore registers (which armperiph uses). 585 */ 586 struct mainbus_attach_args * const mb = aux; 587 mb->mb_iot = &armv7_generic_bs_tag; 588 return; 589 } 590 if (device_is_a(self, "armgic") 591 && device_is_a(device_parent(self), "armperiph")) { 592 /* 593 * The Exynos4420 armgic is located at a different location! 594 */ 595 596 extern uint32_t exynos_soc_id; 597 598 switch (EXYNOS_PRODUCT_ID(exynos_soc_id)) { 599 #ifdef SOC_EXYNOS5 600 case 0xe5410: 601 /* offsets not changed on matt's request */ 602 #if 0 603 mpcaa->mpcaa_memh = EXYNOS_CORE_VBASE; 604 mpcaa->mpcaa_off1 = EXYNOS5_GIC_IOP_DISTRIBUTOR_OFFSET; 605 mpcaa->mpcaa_off2 = EXYNOS5_GIC_IOP_CONTROLLER_OFFSET; 606 #endif 607 break; 608 case 0xe5422: { 609 struct mpcore_attach_args * const mpcaa = aux; 610 611 mpcaa->mpcaa_memh = EXYNOS_CORE_VBASE; 612 mpcaa->mpcaa_off1 = EXYNOS5_GIC_IOP_DISTRIBUTOR_OFFSET; 613 mpcaa->mpcaa_off2 = EXYNOS5_GIC_IOP_CONTROLLER_OFFSET; 614 break; 615 } 616 #endif 617 #ifdef SOC_EXYNOS4 618 case 0xe4410: 619 case 0xe4412: { 620 struct mpcore_attach_args * const mpcaa = aux; 621 622 mpcaa->mpcaa_memh = EXYNOS_CORE_VBASE; 623 mpcaa->mpcaa_off1 = EXYNOS4_GIC_DISTRIBUTOR_OFFSET; 624 mpcaa->mpcaa_off2 = EXYNOS4_GIC_CNTR_OFFSET; 625 break; 626 } 627 #endif 628 default: 629 panic("%s: unknown SoC product id %#x", __func__, 630 (u_int)EXYNOS_PRODUCT_ID(exynos_soc_id)); 631 } 632 return; 633 } 634 if (device_is_a(self, "armgtmr") || device_is_a(self, "mct")) { 635 #ifdef SOC_EXYNOS5 636 /* 637 * The global timer is dependent on the MCT running. 638 */ 639 bus_size_t o = EXYNOS5_MCT_OFFSET + MCT_G_TCON; 640 uint32_t v = bus_space_read_4(&armv7_generic_bs_tag, exynos_core_bsh, 641 o); 642 v |= G_TCON_START; 643 bus_space_write_4(&armv7_generic_bs_tag, exynos_core_bsh, o, v); 644 #endif 645 /* 646 * The frequencies of the timers are the reference 647 * frequency. 648 */ 649 prop_dictionary_set_uint32(device_properties(self), 650 "frequency", EXYNOS_F_IN_FREQ); 651 return; 652 } 653 } 654 655 656 void 657 exynos_device_register_post_config(device_t self, void *aux) 658 { 659 } 660 661 void 662 exynos_usb_soc_powerup(void) 663 { 664 /* XXX 5422 XXX */ 665 } 666 667 668 /* 669 * USB Phy SoC dependent handling 670 */ 671 672 /* XXX 5422 not handled since its unknown how it handles this XXX*/ 673 static void 674 exynos_usb2_set_isolation(bool on) 675 { 676 uint32_t en_mask, regval; 677 bus_addr_t reg; 678 679 /* enable PHY */ 680 reg = EXYNOS_PMU_USB_PHY_CTRL; 681 682 if (IS_EXYNOS5_P() || IS_EXYNOS4410_P()) { 683 /* set usbhost mode */ 684 regval = on ? 0 : USB20_PHY_HOST_LINK_EN; 685 bus_space_write_4(&armv7_generic_bs_tag, exynos_sysreg_bsh, 686 EXYNOS5_SYSREG_USB20_PHY_TYPE, regval); 687 reg = EXYNOS_PMU_USBHOST_PHY_CTRL; 688 } 689 690 /* do enable PHY */ 691 en_mask = PMU_PHY_ENABLE; 692 regval = bus_space_read_4(&armv7_generic_bs_tag, exynos_pmu_bsh, reg); 693 regval = on ? regval & ~en_mask : regval | en_mask; 694 695 bus_space_write_4(&armv7_generic_bs_tag, exynos_pmu_bsh, 696 reg, regval); 697 698 if (IS_EXYNOS4X12_P()) { 699 bus_space_write_4(&armv7_generic_bs_tag, exynos_pmu_bsh, 700 EXYNOS_PMU_USB_HSIC_1_PHY_CTRL, regval); 701 bus_space_write_4(&armv7_generic_bs_tag, exynos_pmu_bsh, 702 EXYNOS_PMU_USB_HSIC_2_PHY_CTRL, regval); 703 } 704 } 705 706 707 #ifdef SOC_EXYNOS4 708 static void 709 exynos4_usb2phy_enable(bus_space_handle_t usb2phy_bsh) 710 { 711 uint32_t phypwr, rstcon, clkreg; 712 713 /* write clock value */ 714 clkreg = FSEL_CLKSEL_24M; 715 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 716 USB_PHYCLK, clkreg); 717 718 /* set device and host to normal */ 719 phypwr = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 720 USB_PHYPWR); 721 722 /* enable analog, enable otg, unsleep phy0 (host) */ 723 phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; 724 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 725 USB_PHYPWR, phypwr); 726 727 if (IS_EXYNOS4X12_P()) { 728 /* enable hsic0 (host), enable hsic1 and phy1 (otg) */ 729 phypwr = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 730 USB_PHYPWR); 731 phypwr &= ~(PHYPWR_NORMAL_MASK_HSIC0 | 732 PHYPWR_NORMAL_MASK_HSIC1 | 733 PHYPWR_NORMAL_MASK_PHY1); 734 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 735 USB_PHYPWR, phypwr); 736 } 737 738 /* reset both phy and link of device */ 739 rstcon = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 740 USB_RSTCON); 741 rstcon |= RSTCON_DEVPHY_SWRST; 742 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 743 USB_RSTCON, rstcon); 744 DELAY(10000); 745 rstcon &= ~RSTCON_DEVPHY_SWRST; 746 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 747 USB_RSTCON, rstcon); 748 749 if (IS_EXYNOS4X12_P()) { 750 /* reset both phy and link of host */ 751 rstcon = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 752 USB_RSTCON); 753 rstcon |= RSTCON_HOSTPHY_SWRST | RSTCON_HOSTPHYLINK_SWRST; 754 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 755 USB_RSTCON, rstcon); 756 DELAY(10000); 757 rstcon &= ~(RSTCON_HOSTPHY_SWRST | RSTCON_HOSTPHYLINK_SWRST); 758 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 759 USB_RSTCON, rstcon); 760 } 761 762 /* wait for everything to be initialized */ 763 DELAY(80000); 764 } 765 #endif 766 767 768 #ifdef SOC_EXYNOS5 769 static void 770 exynos5410_usb2phy_enable(bus_space_handle_t usb2phy_bsh) 771 { 772 uint32_t phyhost; //, phyotg; 773 uint32_t phyhsic; 774 uint32_t ehcictrl, ohcictrl; 775 776 /* host configuration: */ 777 phyhost = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 778 USB_PHY_HOST_CTRL0); 779 780 /* host phy reference clock; assumption its 24 MHz now */ 781 phyhost &= ~HOST_CTRL0_FSEL_MASK; 782 phyhost |= __SHIFTIN(FSEL_CLKSEL_24M, HOST_CTRL0_FSEL_MASK); 783 784 /* enable normal mode of operation */ 785 phyhost &= ~(HOST_CTRL0_FORCESUSPEND | HOST_CTRL0_FORCESLEEP); 786 787 /* host phy reset */ 788 phyhost &= ~(HOST_CTRL0_PHY_SWRST | HOST_CTRL0_PHY_SWRST_ALL | 789 HOST_CTRL0_SIDDQ | HOST_CTRL0_FORCESUSPEND | 790 HOST_CTRL0_FORCESLEEP); 791 792 /* host link reset */ 793 phyhost |= HOST_CTRL0_LINK_SWRST | HOST_CTRL0_UTMI_SWRST | 794 HOST_CTRL0_COMMONON_N; 795 /* do the reset */ 796 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HOST_CTRL0, 797 phyhost); 798 DELAY(10000); 799 800 phyhost &= ~(HOST_CTRL0_LINK_SWRST | HOST_CTRL0_UTMI_SWRST); 801 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HOST_CTRL0, 802 phyhost); 803 804 /* HSIC control */ 805 phyhsic = 806 __SHIFTIN(HSIC_CTRL_REFCLKDIV_12, HSIC_CTRL_REFCLKDIV_MASK) | 807 __SHIFTIN(HSIC_CTRL_REFCLKSEL_DEFAULT, HSIC_CTRL_REFCLKSEL_MASK) | 808 HSIC_CTRL_PHY_SWRST; 809 810 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HSIC_CTRL1, 811 phyhsic); 812 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HSIC_CTRL2, 813 phyhsic); 814 DELAY(10); 815 816 phyhsic &= ~HSIC_CTRL_PHY_SWRST; 817 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HSIC_CTRL1, 818 phyhsic); 819 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HSIC_CTRL2, 820 phyhsic); 821 DELAY(80); 822 823 #if 0 824 /* otg configuration: */ 825 phyotg = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 826 USB_PHY_OTG_SYS); 827 828 /* otg phy reference clock: assumption its 24 Mhz now */ 829 phyotg &= ~OTG_SYS_FSEL_MASK; 830 phyotg |= __SHIFTIN(OTG_SYS_FSEL_MASK, FSEL_CLKSEL_24M); 831 832 /* enable normal mode of operation */ 833 phyotg &= ~(OTG_SYS_FORCESUSPEND | OTG_SYS_FORCESLEEP | 834 OTG_SYS_SIDDQ_UOTG | OTG_SYS_REFCLKSEL_MASK | 835 OTG_SYS_COMMON_ON); 836 837 /* OTG phy and link reset */ 838 phyotg |= OTG_SYS_PHY0_SWRST | OTG_SYS_PHYLINK_SWRST | 839 OTG_SYS_OTGDISABLE | OTG_SYS_REFCLKSEL_MASK; 840 841 /* do the reset */ 842 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 843 USB_PHY_OTG_SYS, phyotg); 844 DELAY(10000); 845 phyotg &= ~(OTG_SYS_PHY0_SWRST | OTG_SYS_LINK_SWRST_UOTG | 846 OTG_SYS_PHYLINK_SWRST); 847 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 848 USB_PHY_OTG_SYS, phyotg); 849 #endif 850 851 /* enable EHCI DMA burst: */ 852 ehcictrl = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 853 USB_PHY_HOST_EHCICTRL); 854 ehcictrl |= HOST_EHCICTRL_ENA_INCRXALIGN | 855 HOST_EHCICTRL_ENA_INCR4 | HOST_EHCICTRL_ENA_INCR8 | 856 HOST_EHCICTRL_ENA_INCR16; 857 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 858 USB_PHY_HOST_EHCICTRL, ehcictrl); 859 860 /* Set OHCI suspend */ 861 ohcictrl = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 862 USB_PHY_HOST_OHCICTRL); 863 ohcictrl |= HOST_OHCICTRL_SUSPLGCY; 864 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 865 USB_PHY_HOST_OHCICTRL, ohcictrl); 866 } 867 868 869 static void 870 exynos5422_usb2phy_enable(bus_space_handle_t usb2phy_bsh) 871 { 872 aprint_error("%s not implemented\n", __func__); 873 } 874 #endif 875 876 877 void 878 exynos_usb_phy_init(bus_space_handle_t usb2phy_bsh) 879 { 880 /* disable phy isolation */ 881 exynos_usb2_set_isolation(false); 882 883 #ifdef SOC_EXYNOS4 884 exynos4_usb2phy_enable(usb2phy_bsh); 885 #endif 886 #ifdef SOC_EXYNOS5 887 if (IS_EXYNOS5410_P()) { 888 exynos5410_usb2phy_enable(usb2phy_bsh); 889 /* TBD: USB3 phy init */ 890 } else if (IS_EXYNOS5422_P()) { 891 exynos5422_usb2phy_enable(usb2phy_bsh); 892 /* TBD: USB3 phy init */ 893 } 894 #endif 895 } 896 897 898