shared ARM updates
[tomato.git] / release / src-rt-6.x.4708 / shared / hndarm_ca9.c
blob5089bd11fd8c8e1cc4e2c1f23e03651abbabaa0d
1 /*
2 * BCM43XX Sonics SiliconBackplane ARM core routines
4 * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: hndarm.c 328955 2012-04-23 09:06:12Z $
21 #include <typedefs.h>
22 #include <bcmutils.h>
23 #include <siutils.h>
24 #include <hndsoc.h>
25 #include <sbchipc.h>
26 #include <bcmdevs.h>
27 #include <hndpmu.h>
28 #include <chipcommonb.h>
29 #include <armca9_core.h>
30 #include <ddr_core.h>
32 #define NO_DDRCLK_LIMIT 1
34 uint
35 BCMINITFN(si_irq)(si_t *sih)
37 return 0;
41 * Initializes clocks and interrupts. SB and NVRAM access must be
42 * initialized prior to calling.
44 void
45 BCMATTACHFN(si_arm_init)(si_t *sih)
47 return;
50 uint32
51 BCMINITFN(si_cpu_clock)(si_t *sih)
53 uint32 val;
54 osl_t *osh;
55 osh = si_osh(sih);
57 if (BCM4707_CHIP(CHIPID(sih->chip))) {
58 /* Return 100 MHz if we are in default value policy 2 */
59 val = (uint32)R_REG(osh, (uint32 *)IHOST_PROC_CLK_POLICY_FREQ);
60 if ((val & 0x7070707) == 0x2020202)
61 return 100000000;
63 val = (uint32)R_REG(osh, (uint32 *)IHOST_PROC_CLK_PLLARMA);
64 val = (val >> 8) & 0x2ff;
65 val = (val * 25 * 1000000) / 2;
67 return val;
70 return si_clock(sih);
73 uint32
74 BCMINITFN(si_mem_clock)(si_t *sih)
76 osl_t *osh;
77 uint idx;
78 chipcommonbregs_t *chipcb;
79 uint32 control1, control2, val;
80 static uint32 BCMINITDATA(pll_table)[][3] = {
81 /* DDR clock, PLLCONTROL1, PLLCONTROL2 */
82 { 333, 0x17800000, 0x1e0f1219 },
83 { 389, 0x18c00000, 0x23121219 },
84 { 400, 0x18000000, 0x20101019 },
85 { 533, 0x18000000, 0x20100c19 },
86 { 666, 0x17800000, 0x1e0f0919 },
87 { 775, 0x17c00000, 0x20100819 },
88 { 800, 0x18000000, 0x20100819 },
89 {0}
92 osh = si_osh(sih);
94 if (BCM4707_CHIP(CHIPID(sih->chip))) {
95 chipcb = si_setcore(sih, NS_CCB_CORE_ID, 0);
96 if (chipcb) {
97 control1 = R_REG(osh, &chipcb->cru_lcpll_control1);
98 control2 = R_REG(osh, &chipcb->cru_lcpll_control2);
99 for (idx = 0; pll_table[idx][0] != 0; idx++) {
100 if ((control1 == pll_table[idx][1]) &&
101 (control2 == pll_table[idx][2])) {
102 val = pll_table[idx][0];
103 return (val * 1000000);
110 return si_clock(sih);
113 bool
114 BCMINITFN(si_arm_setclock)(si_t *sih, uint32 armclock, uint32 ddrclock, uint32 axiclock)
116 osl_t *osh;
117 uint32 val;
118 bool ret = TRUE;
119 int idx;
120 int bootdev;
121 #ifdef NO_DDRCLK_LIMIT
122 uint32 *ddrclk;
123 #else
124 uint32 *ddrclk, ddrclk_limit = 0;
125 #endif
126 static uint32 BCMINITDATA(arm_pll_table)[][2] = {
127 { 600, 0x1003001 },
128 { 800, 0x1004001 },
129 { 1000, 0x1005001 },
130 { 1200, 0x1006001 },
131 { 1400, 0x1007001 },
132 { 1600, 0x1008001 },
135 static uint32 BCMINITDATA(ddr_clock_table)[] = {
136 333, 389, 400, 533, 666, 775, 800, 0
139 osh = si_osh(sih);
141 if (BCM4707_CHIP(CHIPID(sih->chip))) {
142 /* Check DDR clock */
143 if (ddrclock && si_mem_clock(sih) != ddrclock) {
144 ddrclock /= 1000000;
145 for (idx = 0; ddr_clock_table[idx] != 0; idx ++) {
146 if (ddrclock == ddr_clock_table[idx])
147 break;
149 #ifdef NO_DDRCLK_LIMIT
150 if (ddr_clock_table[idx] != 0) {
151 #else
152 if (CHIPID(sih->chip) == BCM4707_CHIP_ID &&
153 sih->chippkg != BCM4709_PKG_ID) {
154 void *regs = (void *)si_setcore(sih, NS_DDR23_CORE_ID, 0);
155 int ddrtype_ddr3 = 0;
156 if (regs) {
157 ddrtype_ddr3 = ((si_core_sflags(sih, 0, 0) & DDR_TYPE_MASK)
158 == DDR_STAT_DDR3);
160 if (ddrtype_ddr3)
161 ddrclk_limit = 533;
162 else
163 ddrclk_limit = 400;
165 if (ddr_clock_table[idx] != 0 &&
166 (ddrclk_limit == 0 || ddrclock <= ddrclk_limit)) {
167 #endif
168 ddrclk = (uint32 *)(0x1000 + BISZ_OFFSET - 4);
169 *ddrclk = ddrclock;
170 bootdev = soc_boot_dev((void *)sih);
171 if (bootdev == SOC_BOOTDEV_NANDFLASH) {
172 __asm__ __volatile__("ldr\tpc,=0x1c000000\n\t");
173 } else if (bootdev == SOC_BOOTDEV_SFLASH) {
174 __asm__ __volatile__("ldr\tpc,=0x1e000000\n\t");
179 /* Set CPU clock */
180 armclock /= 1000000;
182 /* The password */
183 W_REG(osh, (uint32 *)IHOST_PROC_CLK_WR_ACCESS, 0xa5a501);
185 /* ndiv_int */
186 for (idx = 0; arm_pll_table[idx][0] != 0; idx++) {
187 if (armclock <= arm_pll_table[idx][0])
188 break;
190 if (arm_pll_table[idx][0] == 0) {
191 ret = FALSE;
192 goto done;
194 val = arm_pll_table[idx][1];
195 W_REG(osh, (uint32 *)IHOST_PROC_CLK_PLLARMA, val);
197 do {
198 val = (uint32)R_REG(osh, (uint32 *)IHOST_PROC_CLK_PLLARMA);
199 if (val & (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK))
200 break;
201 } while (1);
204 val |= (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_POST_RESETB);
205 W_REG(osh, (uint32 *)IHOST_PROC_CLK_PLLARMA, val);
207 W_REG(osh, (uint32 *)IHOST_PROC_CLK_POLICY_FREQ, 0x87070707);
208 W_REG(osh, (uint32 *)IHOST_PROC_CLK_CORE0_CLKGATE, 0x00010303);
209 W_REG(osh, (uint32 *)IHOST_PROC_CLK_CORE1_CLKGATE, 0x00000303);
210 W_REG(osh, (uint32 *)IHOST_PROC_CLK_ARM_SWITCH_CLKGATE, 0x00010303);
211 W_REG(osh, (uint32 *)IHOST_PROC_CLK_ARM_PERIPH_CLKGATE, 0x00010303);
212 W_REG(osh, (uint32 *)IHOST_PROC_CLK_APB0_CLKGATE, 0x00010303);
214 val = (1 << IHOST_PROC_CLK_POLICY_CTL__GO) |
215 (1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC);
216 W_REG(osh, (uint32 *)IHOST_PROC_CLK_POLICY_CTL, val);
218 do {
219 val = R_REG(osh, (uint32 *)IHOST_PROC_CLK_POLICY_CTL);
220 if ((val & (1 << IHOST_PROC_CLK_POLICY_CTL__GO)) == 0)
221 break;
222 } while (1);
224 done:
225 return (ret);
228 void si_mem_setclock(si_t *sih, uint32 ddrclock)
230 osl_t *osh;
231 chipcommonbregs_t *chipcb;
232 uint32 val;
233 int idx;
234 static uint32 BCMINITDATA(pll_table)[][3] = {
235 /* DDR clock, PLLCONTROL1, PLLCONTROL2 */
236 { 333, 0x17800000, 0x1e0f1219 },
237 { 389, 0x18c00000, 0x23121219 },
238 { 400, 0x18000000, 0x20101019 },
239 { 533, 0x18000000, 0x20100c19 },
240 { 666, 0x17800000, 0x1e0f0919 },
241 { 775, 0x17c00000, 0x20100819 },
242 { 800, 0x18000000, 0x20100819 },
246 for (idx = 0; pll_table[idx][0] != 0; idx++) {
247 if (pll_table[idx][0] == ddrclock)
248 break;
250 if (pll_table[idx][0] == 0)
251 return;
253 osh = si_osh(sih);
254 chipcb = (chipcommonbregs_t *)si_setcore(sih, NS_CCB_CORE_ID, 0);
255 if (chipcb) {
256 val = 0xea68;
257 W_REG(osh, &chipcb->cru_clkset_key, val);
258 val = R_REG(osh, &chipcb->cru_lcpll_control1);
259 val &= ~0x0ff00000;
260 val |= (pll_table[idx][1] & 0x0ff00000);
261 W_REG(osh, &chipcb->cru_lcpll_control1, val);
263 val = R_REG(osh, &chipcb->cru_lcpll_control2);
264 val &= ~0xffffff00;
265 val |= (pll_table[idx][2] & 0xffffff00);
266 W_REG(osh, &chipcb->cru_lcpll_control2, val);
267 /* Enable change */
268 val = R_REG(osh, &chipcb->cru_lcpll_control0);
269 val |= 0x7;
270 W_REG(osh, &chipcb->cru_lcpll_control0, val);
271 val &= ~0x7;
272 W_REG(osh, &chipcb->cru_lcpll_control0, val);
273 val = 0;
274 W_REG(osh, &chipcb->cru_clkset_key, val);
278 /* Start chipc watchdog timer and wait till reset */
279 void
280 hnd_cpu_reset(si_t *sih)
282 si_watchdog(sih, 1);
283 while (1);
286 void
287 hnd_cpu_jumpto(void *addr)
289 void (*jumpto)(void) = addr;
291 (jumpto)();