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