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