exynos_soc.c revision 1.32.4.2
1/* $NetBSD: exynos_soc.c,v 1.32.4.2 2018/09/06 06:55:27 pgoyette 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.32.4.2 2018/09/06 06:55:27 pgoyette 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 */ 66uint32_t exynos_soc_id = 0; 67uint32_t exynos_pop_id = 0; 68 69/* cpu frequencies */ 70struct cpu_freq { 71 uint64_t freq; 72 int P; 73 int M; 74 int S; 75}; 76 77 78#ifdef SOC_EXYNOS4 79int exynos4_l2cc_init(void); 80 81const 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 106const 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 123static struct cpu_freq const *cpu_freq_settings = NULL; 124static int ncpu_freq_settings = 0; 125 126static int cpu_freq_target = 0; 127#define NFRQS 18 128static char sysctl_cpu_freqs_txt[NFRQS*5]; 129 130bus_space_handle_t exynos_core_bsh; 131bus_space_handle_t exynos_audiocore_bsh; 132 133bus_space_handle_t exynos_wdt_bsh; 134bus_space_handle_t exynos_pmu_bsh; 135bus_space_handle_t exynos_cmu_bsh; 136bus_space_handle_t exynos_cmu_apll_bsh; 137bus_space_handle_t exynos_sysreg_bsh; 138 139 140static int sysctl_cpufreq_target(SYSCTLFN_ARGS); 141static int sysctl_cpufreq_current(SYSCTLFN_ARGS); 142 143#ifdef ARM_TRUSTZONE_FIRMWARE 144int 145exynos_do_idle(void) 146{ 147 exynos_smc(SMC_CMD_SLEEP, 0, 0, 0); 148 149 return 0; 150} 151 152 153int 154exynos_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 161int 162exynos_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 180int 181exynos4_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 242void 243exynos_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 300uint64_t 301exynos_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 314static void 315exynos_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 342static int 343sysctl_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 390static int 391sysctl_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 DUMP_PLL(v, var) \ 405 reg = EXYNOS##v##_CMU_##var + PLL_CON0_OFFSET;\ 406 regval = bus_space_read_4(&armv7_generic_bs_tag, exynos_cmu_bsh, reg); \ 407 freq = PLL_FREQ(EXYNOS_F_IN_FREQ, regval); \ 408 printf("%8s at %d Mhz\n", #var, freq/(1000*1000)); 409 410 411static void 412exynos_dump_clocks(void) 413{ 414 uint32_t reg = 0; 415 uint32_t regval; 416 uint32_t freq; 417 418 printf("Initial PLL settings\n"); 419#ifdef SOC_EXYNOS4 420 DUMP_PLL(4, APLL); 421 DUMP_PLL(4, MPLL); 422 DUMP_PLL(4, EPLL); 423 DUMP_PLL(4, VPLL); 424#endif 425#ifdef SOC_EXYNOS5 426 DUMP_PLL(5, APLL); 427 DUMP_PLL(5, MPLL); 428 DUMP_PLL(5, KPLL); 429 DUMP_PLL(5, DPLL); 430 DUMP_PLL(5, VPLL); 431 DUMP_PLL(5, CPLL); 432 DUMP_PLL(5, GPLL); 433 DUMP_PLL(5, BPLL); 434#endif 435} 436#undef DUMP_PLL 437#endif 438 439 440/* XXX clock stuff needs major work XXX */ 441 442void 443exynos_init_clkout_for_usb(void) 444{ 445 /* Select XUSBXTI as source for CLKOUT */ 446 bus_space_write_4(&armv7_generic_bs_tag, exynos_pmu_bsh, 447 EXYNOS_PMU_DEBUG_CLKOUT, 0x1000); 448} 449 450 451void 452exynos_clocks_bootstrap(void) 453{ 454 KASSERT(ncpu_freq_settings != 0); 455 KASSERT(ncpu_freq_settings < NFRQS); 456 int fsel; 457 458#ifdef VERBOSE_INIT_ARM 459 exynos_dump_clocks(); 460#endif 461 462 /* set (max) cpufreq */ 463 fsel = ncpu_freq_settings-1; 464 465#ifdef SOC_EXYNOS5 466 /* XXX BUGFIX selecting freq on E5 goes wrong for now XXX */ 467 fsel = EXYNOS5_DEFAULT_ENTRY; 468#endif 469 470 exynos_set_cpufreq(&cpu_freq_settings[fsel]); 471 472 /* set external USB frequency to XCLKOUT */ 473 exynos_init_clkout_for_usb(); 474} 475 476 477void 478exynos_bootstrap(vaddr_t iobase) 479{ 480 int error; 481 size_t core_size, audiocore_size; 482 bus_addr_t audiocore_pbase; 483 bus_addr_t audiocore_vbase __diagused; 484 bus_addr_t exynos_wdt_offset; 485 bus_addr_t exynos_pmu_offset; 486 bus_addr_t exynos_sysreg_offset; 487 bus_addr_t exynos_cmu_apll_offset; 488 489#ifdef SOC_EXYNOS4 490 core_size = EXYNOS4_CORE_SIZE; 491 audiocore_size = EXYNOS4_AUDIOCORE_SIZE; 492 audiocore_pbase = EXYNOS4_AUDIOCORE_PBASE; 493 audiocore_vbase = EXYNOS4_AUDIOCORE_VBASE; 494 exynos_wdt_offset = EXYNOS4_WDT_OFFSET; 495 exynos_pmu_offset = EXYNOS4_PMU_OFFSET; 496 exynos_sysreg_offset = EXYNOS4_SYSREG_OFFSET; 497 exynos_cmu_apll_offset = EXYNOS4_CMU_APLL; 498 499 cpu_freq_settings = cpu_freq_settings_exynos4; 500 ncpu_freq_settings = __arraycount(cpu_freq_settings_exynos4); 501#endif 502 503#ifdef SOC_EXYNOS5 504 core_size = EXYNOS5_CORE_SIZE; 505 audiocore_size = EXYNOS5_AUDIOCORE_SIZE; 506 audiocore_pbase = EXYNOS5_AUDIOCORE_PBASE; 507 audiocore_vbase = EXYNOS5_AUDIOCORE_VBASE; 508 exynos_wdt_offset = EXYNOS5_WDT_OFFSET; 509 exynos_pmu_offset = EXYNOS5_PMU_OFFSET; 510 exynos_sysreg_offset = EXYNOS5_SYSREG_OFFSET; 511 exynos_cmu_apll_offset = EXYNOS5_CMU_APLL; 512 513 cpu_freq_settings = cpu_freq_settings_exynos5; 514 ncpu_freq_settings = __arraycount(cpu_freq_settings_exynos5); 515#endif 516 517 /* map in the exynos io registers */ 518 error = bus_space_map(&armv7_generic_bs_tag, EXYNOS_CORE_PBASE, 519 core_size, 0, &exynos_core_bsh); 520 if (error) 521 panic("%s: failed to map in Exynos SFR registers: %d", 522 __func__, error); 523 KASSERT(exynos_core_bsh == iobase); 524 525 error = bus_space_map(&armv7_generic_bs_tag, audiocore_pbase, 526 audiocore_size, 0, &exynos_audiocore_bsh); 527 if (error) 528 panic("%s: failed to map in Exynos audio SFR registers: %d", 529 __func__, error); 530 KASSERT(exynos_audiocore_bsh == audiocore_vbase); 531 532 /* map in commonly used subregions and common used register banks */ 533 error = bus_space_subregion(&armv7_generic_bs_tag, exynos_core_bsh, 534 exynos_wdt_offset, EXYNOS_BLOCK_SIZE, &exynos_wdt_bsh); 535 if (error) 536 panic("%s: failed to subregion wdt registers: %d", 537 __func__, error); 538 539 error = bus_space_subregion(&armv7_generic_bs_tag, exynos_core_bsh, 540 exynos_pmu_offset, EXYNOS_BLOCK_SIZE, &exynos_pmu_bsh); 541 if (error) 542 panic("%s: failed to subregion pmu registers: %d", 543 __func__, error); 544 545 exynos_cmu_bsh = exynos_core_bsh; 546 bus_space_subregion(&armv7_generic_bs_tag, exynos_core_bsh, 547 exynos_sysreg_offset, EXYNOS_BLOCK_SIZE, 548 &exynos_sysreg_bsh); 549 if (error) 550 panic("%s: failed to subregion sysreg registers: %d", 551 __func__, error); 552 553 error = bus_space_subregion(&armv7_generic_bs_tag, exynos_cmu_bsh, 554 exynos_cmu_apll_offset, 0xfff, &exynos_cmu_apll_bsh); 555 if (error) 556 panic("%s: failed to subregion cmu apll registers: %d", 557 __func__, error); 558 559 /* gpio bootstrapping delayed */ 560} 561 562 563void 564exynos_device_register(device_t self, void *aux) 565{ 566 if (device_is_a(self, "armperiph") 567 && device_is_a(device_parent(self), "mainbus")) { 568 /* 569 * XXX KLUDGE ALERT XXX 570 * The iot mainbus supplies is completely wrong since it scales 571 * addresses by 2. The simplest remedy is to replace with our 572 * bus space used for the armcore registers (which armperiph uses). 573 */ 574 struct mainbus_attach_args * const mb = aux; 575 mb->mb_iot = &armv7_generic_bs_tag; 576 return; 577 } 578 if (device_is_a(self, "armgic") 579 && device_is_a(device_parent(self), "armperiph")) { 580 /* 581 * The Exynos4420 armgic is located at a different location! 582 */ 583 584 extern uint32_t exynos_soc_id; 585 586 switch (EXYNOS_PRODUCT_ID(exynos_soc_id)) { 587#ifdef SOC_EXYNOS5 588 case 0xe5410: 589 /* offsets not changed on matt's request */ 590#if 0 591 mpcaa->mpcaa_memh = EXYNOS_CORE_VBASE; 592 mpcaa->mpcaa_off1 = EXYNOS5_GIC_IOP_DISTRIBUTOR_OFFSET; 593 mpcaa->mpcaa_off2 = EXYNOS5_GIC_IOP_CONTROLLER_OFFSET; 594#endif 595 break; 596 case 0xe5422: { 597 struct mpcore_attach_args * const mpcaa = aux; 598 599 mpcaa->mpcaa_memh = EXYNOS_CORE_VBASE; 600 mpcaa->mpcaa_off1 = EXYNOS5_GIC_IOP_DISTRIBUTOR_OFFSET; 601 mpcaa->mpcaa_off2 = EXYNOS5_GIC_IOP_CONTROLLER_OFFSET; 602 break; 603 } 604#endif 605#ifdef SOC_EXYNOS4 606 case 0xe4410: 607 case 0xe4412: { 608 struct mpcore_attach_args * const mpcaa = aux; 609 610 mpcaa->mpcaa_memh = EXYNOS_CORE_VBASE; 611 mpcaa->mpcaa_off1 = EXYNOS4_GIC_DISTRIBUTOR_OFFSET; 612 mpcaa->mpcaa_off2 = EXYNOS4_GIC_CNTR_OFFSET; 613 break; 614 } 615#endif 616 default: 617 panic("%s: unknown SoC product id %#x", __func__, 618 (u_int)EXYNOS_PRODUCT_ID(exynos_soc_id)); 619 } 620 return; 621 } 622 if (device_is_a(self, "armgtmr") || device_is_a(self, "mct")) { 623#ifdef SOC_EXYNOS5 624 /* 625 * The global timer is dependent on the MCT running. 626 */ 627 bus_size_t o = EXYNOS5_MCT_OFFSET + MCT_G_TCON; 628 uint32_t v = bus_space_read_4(&armv7_generic_bs_tag, exynos_core_bsh, 629 o); 630 v |= G_TCON_START; 631 bus_space_write_4(&armv7_generic_bs_tag, exynos_core_bsh, o, v); 632#endif 633 /* 634 * The frequencies of the timers are the reference 635 * frequency. 636 */ 637 prop_dictionary_set_uint32(device_properties(self), 638 "frequency", EXYNOS_F_IN_FREQ); 639 return; 640 } 641} 642 643 644void 645exynos_device_register_post_config(device_t self, void *aux) 646{ 647} 648 649void 650exynos_usb_soc_powerup(void) 651{ 652 /* XXX 5422 XXX */ 653} 654 655 656/* 657 * USB Phy SoC dependent handling 658 */ 659 660/* XXX 5422 not handled since its unknown how it handles this XXX*/ 661static void 662exynos_usb2_set_isolation(bool on) 663{ 664 uint32_t en_mask, regval; 665 bus_addr_t reg; 666 667 /* enable PHY */ 668 reg = EXYNOS_PMU_USB_PHY_CTRL; 669 670 if (IS_EXYNOS5_P() || IS_EXYNOS4410_P()) { 671 /* set usbhost mode */ 672 regval = on ? 0 : USB20_PHY_HOST_LINK_EN; 673 bus_space_write_4(&armv7_generic_bs_tag, exynos_sysreg_bsh, 674 EXYNOS5_SYSREG_USB20_PHY_TYPE, regval); 675 reg = EXYNOS_PMU_USBHOST_PHY_CTRL; 676 } 677 678 /* do enable PHY */ 679 en_mask = PMU_PHY_ENABLE; 680 regval = bus_space_read_4(&armv7_generic_bs_tag, exynos_pmu_bsh, reg); 681 regval = on ? regval & ~en_mask : regval | en_mask; 682 683 bus_space_write_4(&armv7_generic_bs_tag, exynos_pmu_bsh, 684 reg, regval); 685 686 if (IS_EXYNOS4X12_P()) { 687 bus_space_write_4(&armv7_generic_bs_tag, exynos_pmu_bsh, 688 EXYNOS_PMU_USB_HSIC_1_PHY_CTRL, regval); 689 bus_space_write_4(&armv7_generic_bs_tag, exynos_pmu_bsh, 690 EXYNOS_PMU_USB_HSIC_2_PHY_CTRL, regval); 691 } 692} 693 694 695#ifdef SOC_EXYNOS4 696static void 697exynos4_usb2phy_enable(bus_space_handle_t usb2phy_bsh) 698{ 699 uint32_t phypwr, rstcon, clkreg; 700 701 /* write clock value */ 702 clkreg = FSEL_CLKSEL_24M; 703 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 704 USB_PHYCLK, clkreg); 705 706 /* set device and host to normal */ 707 phypwr = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 708 USB_PHYPWR); 709 710 /* enable analog, enable otg, unsleep phy0 (host) */ 711 phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; 712 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 713 USB_PHYPWR, phypwr); 714 715 if (IS_EXYNOS4X12_P()) { 716 /* enable hsic0 (host), enable hsic1 and phy1 (otg) */ 717 phypwr = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 718 USB_PHYPWR); 719 phypwr &= ~(PHYPWR_NORMAL_MASK_HSIC0 | 720 PHYPWR_NORMAL_MASK_HSIC1 | 721 PHYPWR_NORMAL_MASK_PHY1); 722 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 723 USB_PHYPWR, phypwr); 724 } 725 726 /* reset both phy and link of device */ 727 rstcon = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 728 USB_RSTCON); 729 rstcon |= RSTCON_DEVPHY_SWRST; 730 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 731 USB_RSTCON, rstcon); 732 DELAY(10000); 733 rstcon &= ~RSTCON_DEVPHY_SWRST; 734 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 735 USB_RSTCON, rstcon); 736 737 if (IS_EXYNOS4X12_P()) { 738 /* reset both phy and link of host */ 739 rstcon = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 740 USB_RSTCON); 741 rstcon |= RSTCON_HOSTPHY_SWRST | RSTCON_HOSTPHYLINK_SWRST; 742 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 743 USB_RSTCON, rstcon); 744 DELAY(10000); 745 rstcon &= ~(RSTCON_HOSTPHY_SWRST | RSTCON_HOSTPHYLINK_SWRST); 746 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 747 USB_RSTCON, rstcon); 748 } 749 750 /* wait for everything to be initialized */ 751 DELAY(80000); 752} 753#endif 754 755 756#ifdef SOC_EXYNOS5 757static void 758exynos5410_usb2phy_enable(bus_space_handle_t usb2phy_bsh) 759{ 760 uint32_t phyhost; //, phyotg; 761 uint32_t phyhsic; 762 uint32_t ehcictrl, ohcictrl; 763 764 /* host configuration: */ 765 phyhost = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 766 USB_PHY_HOST_CTRL0); 767 768 /* host phy reference clock; assumption its 24 MHz now */ 769 phyhost &= ~HOST_CTRL0_FSEL_MASK; 770 phyhost |= __SHIFTIN(FSEL_CLKSEL_24M, HOST_CTRL0_FSEL_MASK); 771 772 /* enable normal mode of operation */ 773 phyhost &= ~(HOST_CTRL0_FORCESUSPEND | HOST_CTRL0_FORCESLEEP); 774 775 /* host phy reset */ 776 phyhost &= ~(HOST_CTRL0_PHY_SWRST | HOST_CTRL0_PHY_SWRST_ALL | 777 HOST_CTRL0_SIDDQ | HOST_CTRL0_FORCESUSPEND | 778 HOST_CTRL0_FORCESLEEP); 779 780 /* host link reset */ 781 phyhost |= HOST_CTRL0_LINK_SWRST | HOST_CTRL0_UTMI_SWRST | 782 HOST_CTRL0_COMMONON_N; 783 /* do the reset */ 784 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HOST_CTRL0, 785 phyhost); 786 DELAY(10000); 787 788 phyhost &= ~(HOST_CTRL0_LINK_SWRST | HOST_CTRL0_UTMI_SWRST); 789 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HOST_CTRL0, 790 phyhost); 791 792 /* HSIC control */ 793 phyhsic = 794 __SHIFTIN(HSIC_CTRL_REFCLKDIV_12, HSIC_CTRL_REFCLKDIV_MASK) | 795 __SHIFTIN(HSIC_CTRL_REFCLKSEL_DEFAULT, HSIC_CTRL_REFCLKSEL_MASK) | 796 HSIC_CTRL_PHY_SWRST; 797 798 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HSIC_CTRL1, 799 phyhsic); 800 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HSIC_CTRL2, 801 phyhsic); 802 DELAY(10); 803 804 phyhsic &= ~HSIC_CTRL_PHY_SWRST; 805 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HSIC_CTRL1, 806 phyhsic); 807 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, USB_PHY_HSIC_CTRL2, 808 phyhsic); 809 DELAY(80); 810 811#if 0 812 /* otg configuration: */ 813 phyotg = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 814 USB_PHY_OTG_SYS); 815 816 /* otg phy refrence clock: assumption its 24 Mhz now */ 817 phyotg &= ~OTG_SYS_FSEL_MASK; 818 phyotg |= __SHIFTIN(OTG_SYS_FSEL_MASK, FSEL_CLKSEL_24M); 819 820 /* enable normal mode of operation */ 821 phyotg &= ~(OTG_SYS_FORCESUSPEND | OTG_SYS_FORCESLEEP | 822 OTG_SYS_SIDDQ_UOTG | OTG_SYS_REFCLKSEL_MASK | 823 OTG_SYS_COMMON_ON); 824 825 /* OTG phy and link reset */ 826 phyotg |= OTG_SYS_PHY0_SWRST | OTG_SYS_PHYLINK_SWRST | 827 OTG_SYS_OTGDISABLE | OTG_SYS_REFCLKSEL_MASK; 828 829 /* do the reset */ 830 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 831 USB_PHY_OTG_SYS, phyotg); 832 DELAY(10000); 833 phyotg &= ~(OTG_SYS_PHY0_SWRST | OTG_SYS_LINK_SWRST_UOTG | 834 OTG_SYS_PHYLINK_SWRST); 835 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 836 USB_PHY_OTG_SYS, phyotg); 837#endif 838 839 /* enable EHCI DMA burst: */ 840 ehcictrl = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 841 USB_PHY_HOST_EHCICTRL); 842 ehcictrl |= HOST_EHCICTRL_ENA_INCRXALIGN | 843 HOST_EHCICTRL_ENA_INCR4 | HOST_EHCICTRL_ENA_INCR8 | 844 HOST_EHCICTRL_ENA_INCR16; 845 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 846 USB_PHY_HOST_EHCICTRL, ehcictrl); 847 848 /* Set OHCI suspend */ 849 ohcictrl = bus_space_read_4(&armv7_generic_bs_tag, usb2phy_bsh, 850 USB_PHY_HOST_OHCICTRL); 851 ohcictrl |= HOST_OHCICTRL_SUSPLGCY; 852 bus_space_write_4(&armv7_generic_bs_tag, usb2phy_bsh, 853 USB_PHY_HOST_OHCICTRL, ohcictrl); 854} 855 856 857static void 858exynos5422_usb2phy_enable(bus_space_handle_t usb2phy_bsh) 859{ 860 aprint_error("%s not implemented\n", __func__); 861} 862#endif 863 864 865void 866exynos_usb_phy_init(bus_space_handle_t usb2phy_bsh) 867{ 868 /* disable phy isolation */ 869 exynos_usb2_set_isolation(false); 870 871#ifdef SOC_EXYNOS4 872 exynos4_usb2phy_enable(usb2phy_bsh); 873#endif 874#ifdef SOC_EXYNOS5 875 if (IS_EXYNOS5410_P()) { 876 exynos5410_usb2phy_enable(usb2phy_bsh); 877 /* TBD: USB3 phy init */ 878 } else if (IS_EXYNOS5422_P()) { 879 exynos5422_usb2phy_enable(usb2phy_bsh); 880 /* TBD: USB3 phy init */ 881 } 882#endif 883} 884 885 886