1 /*
2 * xen/arch/arm/platforms/omap5.c
3 *
4 * OMAP5 specific settings
5 *
6 * Chen Baozi <baozich@gmail.com>
7 * Copyright (c) 2013
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20 #include <asm/p2m.h>
21 #include <asm/platform.h>
22 #include <asm/platforms/omap5.h>
23 #include <xen/mm.h>
24 #include <xen/vmap.h>
25 #include <asm/io.h>
26
27 static uint16_t num_den[8][2] = {
28 { 0, 0 }, /* not used */
29 { 26 * 64, 26 * 125 }, /* 12.0 Mhz */
30 { 2 * 768, 2 * 1625 }, /* 13.0 Mhz */
31 { 0, 0 }, /* not used */
32 { 130 * 8, 130 * 25 }, /* 19.2 Mhz */
33 { 2 * 384, 2 * 1625 }, /* 26.0 Mhz */
34 { 3 * 256, 3 * 1125 }, /* 27.0 Mhz */
35 { 130 * 4, 130 * 25 }, /* 38.4 Mhz */
36 };
37
38 /*
39 * The realtime counter also called master counter, is a free-running
40 * counter, which is related to real time. It produces the count used
41 * by the CPU local timer peripherals in the MPU cluster. The timer counts
42 * at a rate of 6.144 MHz. Because the device operates on different clocks
43 * in different power modes, the master counter shifts operation between
44 * clocks, adjusting the increment per clock in hardware accordingly to
45 * maintain a constant count rate.
46 */
omap5_init_time(void)47 static int omap5_init_time(void)
48 {
49 void __iomem *ckgen_prm_base;
50 void __iomem *rt_ct_base;
51 unsigned int sys_clksel;
52 unsigned int num, den, frac1, frac2;
53
54 ckgen_prm_base = ioremap_nocache(OMAP5_CKGEN_PRM_BASE, 0x20);
55 if ( !ckgen_prm_base )
56 {
57 dprintk(XENLOG_ERR, "%s: PRM_BASE ioremap failed\n", __func__);
58 return -ENOMEM;
59 }
60
61 sys_clksel = readl(ckgen_prm_base + OMAP5_CM_CLKSEL_SYS) &
62 ~SYS_CLKSEL_MASK;
63
64 iounmap(ckgen_prm_base);
65
66 rt_ct_base = ioremap_nocache(REALTIME_COUNTER_BASE, 0x20);
67 if ( !rt_ct_base )
68 {
69 dprintk(XENLOG_ERR, "%s: REALTIME_COUNTER_BASE ioremap failed\n", __func__);
70 return -ENOMEM;
71 }
72
73 frac1 = readl(rt_ct_base + INCREMENTER_NUMERATOR_OFFSET);
74 num = frac1 & ~NUMERATOR_DENUMERATOR_MASK;
75 if ( num_den[sys_clksel][0] != num )
76 {
77 frac1 &= NUMERATOR_DENUMERATOR_MASK;
78 frac1 |= num_den[sys_clksel][0];
79 }
80
81 frac2 = readl(rt_ct_base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
82 den = frac2 & ~NUMERATOR_DENUMERATOR_MASK;
83 if ( num_den[sys_clksel][1] != num )
84 {
85 frac2 &= NUMERATOR_DENUMERATOR_MASK;
86 frac2 |= num_den[sys_clksel][1];
87 }
88
89 writel(frac1, rt_ct_base + INCREMENTER_NUMERATOR_OFFSET);
90 writel(frac2 | PRM_FRAC_INCREMENTER_DENUMERATOR_RELOAD,
91 rt_ct_base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
92
93 iounmap(rt_ct_base);
94
95 return 0;
96 }
97
98 /* Additional mappings for dom0 (not in the DTS) */
omap5_specific_mapping(struct domain * d)99 static int omap5_specific_mapping(struct domain *d)
100 {
101 /* Map the PRM module */
102 map_mmio_regions(d, gaddr_to_gfn(OMAP5_PRM_BASE), 2,
103 maddr_to_mfn(OMAP5_PRM_BASE));
104
105 /* Map the PRM_MPU */
106 map_mmio_regions(d, gaddr_to_gfn(OMAP5_PRCM_MPU_BASE), 1,
107 maddr_to_mfn(OMAP5_PRCM_MPU_BASE));
108
109 /* Map the Wakeup Gen */
110 map_mmio_regions(d, gaddr_to_gfn(OMAP5_WKUPGEN_BASE), 1,
111 maddr_to_mfn(OMAP5_WKUPGEN_BASE));
112
113 /* Map the on-chip SRAM */
114 map_mmio_regions(d, gaddr_to_gfn(OMAP5_SRAM_PA), 32,
115 maddr_to_mfn(OMAP5_SRAM_PA));
116
117 return 0;
118 }
119
omap5_smp_init(void)120 static int __init omap5_smp_init(void)
121 {
122 void __iomem *wugen_base;
123
124 wugen_base = ioremap_nocache(OMAP5_WKUPGEN_BASE, PAGE_SIZE);
125 if ( !wugen_base )
126 {
127 dprintk(XENLOG_ERR, "Unable to map omap5 MMIO\n");
128 return -EFAULT;
129 }
130
131 printk("Set AuxCoreBoot1 to %"PRIpaddr" (%p)\n",
132 __pa(init_secondary), init_secondary);
133 writel(__pa(init_secondary), wugen_base + OMAP_AUX_CORE_BOOT_1_OFFSET);
134
135 printk("Set AuxCoreBoot0 to 0x20\n");
136 writel(0x20, wugen_base + OMAP_AUX_CORE_BOOT_0_OFFSET);
137
138 iounmap(wugen_base);
139
140 return 0;
141 }
142
143 static const char * const omap5_dt_compat[] __initconst =
144 {
145 "ti,omap5",
146 NULL
147 };
148
149 static const char * const dra7_dt_compat[] __initconst =
150 {
151 "ti,dra7",
152 NULL
153 };
154
155 PLATFORM_START(omap5, "TI OMAP5")
156 .compatible = omap5_dt_compat,
157 .init_time = omap5_init_time,
158 .specific_mapping = omap5_specific_mapping,
159 .smp_init = omap5_smp_init,
160 .cpu_up = cpu_up_send_sgi,
161 PLATFORM_END
162
163 PLATFORM_START(dra7, "TI DRA7")
164 .compatible = dra7_dt_compat,
165 .init_time = omap5_init_time,
166 .cpu_up = cpu_up_send_sgi,
167 .smp_init = omap5_smp_init,
168 PLATFORM_END
169
170 /*
171 * Local variables:
172 * mode: C
173 * c-file-style: "BSD"
174 * c-basic-offset: 4
175 * indent-tabs-mode: nil
176 * End:
177 */
178