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