2 * BCM43XX Sonics SiliconBackplane ARM core routines
4 * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved.
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.
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 $
28 #include <chipcommonb.h>
29 #include <armca9_core.h>
32 #define NO_DDRCLK_LIMIT 1
35 BCMINITFN(si_irq
)(si_t
*sih
)
41 * Initializes clocks and interrupts. SB and NVRAM access must be
42 * initialized prior to calling.
45 BCMATTACHFN(si_arm_init
)(si_t
*sih
)
51 BCMINITFN(si_cpu_clock
)(si_t
*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)
63 val
= (uint32
)R_REG(osh
, (uint32
*)IHOST_PROC_CLK_PLLARMA
);
64 val
= (val
>> 8) & 0x2ff;
65 val
= (val
* 25 * 1000000) / 2;
74 BCMINITFN(si_mem_clock
)(si_t
*sih
)
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 },
94 if (BCM4707_CHIP(CHIPID(sih
->chip
))) {
95 chipcb
= si_setcore(sih
, NS_CCB_CORE_ID
, 0);
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
);
114 BCMINITFN(si_arm_setclock
)(si_t
*sih
, uint32 armclock
, uint32 ddrclock
, uint32 axiclock
)
121 #ifdef NO_DDRCLK_LIMIT
124 uint32
*ddrclk
, ddrclk_limit
= 0;
126 static uint32
BCMINITDATA(arm_pll_table
)[][2] = {
135 static uint32
BCMINITDATA(ddr_clock_table
)[] = {
136 333, 389, 400, 533, 666, 775, 800, 0
141 if (BCM4707_CHIP(CHIPID(sih
->chip
))) {
142 /* Check DDR clock */
143 if (ddrclock
&& si_mem_clock(sih
) != ddrclock
) {
145 for (idx
= 0; ddr_clock_table
[idx
] != 0; idx
++) {
146 if (ddrclock
== ddr_clock_table
[idx
])
149 #ifdef NO_DDRCLK_LIMIT
150 if (ddr_clock_table
[idx
] != 0) {
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;
157 ddrtype_ddr3
= ((si_core_sflags(sih
, 0, 0) & DDR_TYPE_MASK
)
165 if (ddr_clock_table
[idx
] != 0 &&
166 (ddrclk_limit
== 0 || ddrclock
<= ddrclk_limit
)) {
168 ddrclk
= (uint32
*)(0x1000 + BISZ_OFFSET
- 4);
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");
183 W_REG(osh
, (uint32
*)IHOST_PROC_CLK_WR_ACCESS
, 0xa5a501);
186 for (idx
= 0; arm_pll_table
[idx
][0] != 0; idx
++) {
187 if (armclock
<= arm_pll_table
[idx
][0])
190 if (arm_pll_table
[idx
][0] == 0) {
194 val
= arm_pll_table
[idx
][1];
195 W_REG(osh
, (uint32
*)IHOST_PROC_CLK_PLLARMA
, val
);
198 val
= (uint32
)R_REG(osh
, (uint32
*)IHOST_PROC_CLK_PLLARMA
);
199 if (val
& (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK
))
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
);
219 val
= R_REG(osh
, (uint32
*)IHOST_PROC_CLK_POLICY_CTL
);
220 if ((val
& (1 << IHOST_PROC_CLK_POLICY_CTL__GO
)) == 0)
228 void si_mem_setclock(si_t
*sih
, uint32 ddrclock
)
231 chipcommonbregs_t
*chipcb
;
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
)
250 if (pll_table
[idx
][0] == 0)
254 chipcb
= (chipcommonbregs_t
*)si_setcore(sih
, NS_CCB_CORE_ID
, 0);
257 W_REG(osh
, &chipcb
->cru_clkset_key
, val
);
258 val
= R_REG(osh
, &chipcb
->cru_lcpll_control1
);
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
);
265 val
|= (pll_table
[idx
][2] & 0xffffff00);
266 W_REG(osh
, &chipcb
->cru_lcpll_control2
, val
);
268 val
= R_REG(osh
, &chipcb
->cru_lcpll_control0
);
270 W_REG(osh
, &chipcb
->cru_lcpll_control0
, val
);
272 W_REG(osh
, &chipcb
->cru_lcpll_control0
, val
);
274 W_REG(osh
, &chipcb
->cru_clkset_key
, val
);
278 /* Start chipc watchdog timer and wait till reset */
280 hnd_cpu_reset(si_t
*sih
)
287 hnd_cpu_jumpto(void *addr
)
289 void (*jumpto
)(void) = addr
;