2 * BCM47XX support code for some chipcommon facilities (uart, jtagm)
4 * Copyright 2007, Broadcom Corporation
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
28 #define CC_ERROR(args)
31 #define CC_MSG(args) printf args
36 /* interested chipcommon interrupt source
43 #define MAX_CC_INT_SOURCE 5
45 /* chipc secondary isr info */
47 uint intmask
; /* int mask */
48 cc_isr_fn isr
; /* secondary isr handler */
49 void *cbdata
; /* pointer to private data */
52 static cc_isr_info_t cc_isr_desc
[MAX_CC_INT_SOURCE
];
54 /* chip common intmask */
55 static uint32 cc_intmask
= 0;
57 static bool BCMINITFN(serial_exists
) (osl_t
* osh
, uint8
* regs
) {
58 uint8 save_mcr
, status1
;
60 save_mcr
= R_REG(osh
, ®s
[UART_MCR
]);
61 W_REG(osh
, ®s
[UART_MCR
], UART_MCR_LOOP
| 0x0a);
62 status1
= R_REG(osh
, ®s
[UART_MSR
]) & 0xf0;
63 W_REG(osh
, ®s
[UART_MCR
], save_mcr
);
65 return (status1
== 0x90);
68 static void __init
sb_extif_serial_init(sb_t
* sbh
, void *regs
,
69 sb_serial_init_fn add
)
71 osl_t
*osh
= sb_osh(sbh
);
72 extifregs_t
*eir
= (extifregs_t
*) regs
;
78 /* Determine external UART register base */
79 sb
= (sbconfig_t
*) ((ulong
) eir
+ SBCONFIGOFF
);
80 base
= EXTIF_CFGIF_BASE(sb_base(R_REG(osh
, &sb
->sbadmatch1
)));
85 /* Disable GPIO interrupt initially */
86 W_REG(osh
, &eir
->gpiointpolarity
, 0);
87 W_REG(osh
, &eir
->gpiointmask
, 0);
89 /* Search for external UARTs */
91 for (i
= 0; i
< 2; i
++) {
92 regs
= (void *)REG_MAP(base
+ (i
* 8), 8);
93 if (serial_exists(osh
, regs
)) {
94 /* Set GPIO 1 to be the external UART IRQ */
95 W_REG(osh
, &eir
->gpiointmask
, 2);
96 /* XXXDetermine external UART clock */
98 add(regs
, irq
, 13500000, 0);
102 /* Add internal UART if enabled */
103 if (R_REG(osh
, &eir
->corecontrol
) & CC_UE
)
105 add((void *)&eir
->uartdata
, irq
, sb_clock(sbh
), 2);
109 * Initializes UART access. The callback function will be called once
112 void BCMINITFN(sb_serial_init
) (sb_t
* sbh
, sb_serial_init_fn add
) {
116 uint32 rev
, cap
, pll
, baud_base
, div
;
122 regs
= sb_setcore(sbh
, SB_EXTIF
, 0);
124 sb_extif_serial_init(sbh
, regs
, add
);
128 cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0);
131 /* Determine core revision and capabilities */
134 pll
= cap
& CC_CAP_PLL_MASK
;
139 if (pll
== PLL_TYPE1
) {
141 baud_base
= sb_clock_rate(pll
,
142 R_REG(osh
, &cc
->clockcontrol_n
),
143 R_REG(osh
, &cc
->clockcontrol_m2
));
146 /* 5354 chip common uart uses a constant clock
147 * frequency of 25MHz */
148 if (sb_corerev(sbh
) == 20) {
149 /* Set the override bit so we don't divide it */
150 W_REG(osh
, &cc
->corecontrol
, CC_UARTCLKO
);
151 baud_base
= 25000000;
152 } else if (rev
>= 11 && rev
!= 15) {
153 /* Fixed ALP clock */
154 baud_base
= sb_alp_clock(sbh
);
156 /* Turn off UART clock before switching clock source */
158 AND_REG(osh
, &cc
->corecontrol
, ~CC_UARTCLKEN
);
159 /* Set the override bit so we don't divide it */
160 OR_REG(osh
, &cc
->corecontrol
, CC_UARTCLKO
);
162 OR_REG(osh
, &cc
->corecontrol
, CC_UARTCLKEN
);
163 } else if (rev
>= 3) {
164 /* Internal backplane clock */
165 baud_base
= sb_clock(sbh
);
166 div
= 2; /* Minimum divisor */
167 W_REG(osh
, &cc
->clkdiv
,
168 ((R_REG(osh
, &cc
->clkdiv
) & ~CLKD_UART
) | div
));
170 /* Fixed internal backplane clock */
171 baud_base
= 88000000;
175 /* Clock source depends on strapping if UartClkOverride is unset */
177 && ((R_REG(osh
, &cc
->corecontrol
) & CC_UARTCLKO
) == 0)) {
178 if ((cap
& CC_CAP_UCLKSEL
) == CC_CAP_UINTCLK
) {
179 /* Internal divided backplane clock */
182 /* Assume external clock of 1.8432 MHz */
188 /* Add internal UARTs */
189 n
= cap
& CC_CAP_UARTS_MASK
;
190 for (i
= 0; i
< n
; i
++) {
191 /* Register offset changed after revision 0 */
193 regs
= (void *)((ulong
) & cc
->uart0data
+ (i
* 256));
195 regs
= (void *)((ulong
) & cc
->uart0data
+ (i
* 8));
198 add(regs
, irq
, baud_base
, 0);
204 * Initialize jtag master and return handle for
205 * jtag_rwreg. Returns NULL on failure.
207 void *sb_jtagm_init(sb_t
* sbh
, uint clkd
, bool exttap
)
211 if ((regs
= sb_setcore(sbh
, SB_CC
, 0)) != NULL
) {
212 chipcregs_t
*cc
= (chipcregs_t
*) regs
;
216 * Determine jtagm availability from
217 * core revision and capabilities.
221 * Corerev 10 has jtagm, but the only chip
222 * with it does not have a mips, and
223 * the layout of the jtagcmd register is
224 * different. We'll only accept >= 11.
229 if ((sbh
->cccaps
& CC_CAP_JTAGP
) == 0)
232 /* Set clock divider if requested */
234 tmp
= R_REG(osh
, &cc
->clkdiv
);
236 (tmp
& ~CLKD_JTAG
) | ((clkd
<< CLKD_JTAG_SHIFT
) &
238 W_REG(osh
, &cc
->clkdiv
, tmp
);
242 tmp
= JCTRL_EN
| (exttap
? JCTRL_EXT_EN
: 0);
243 W_REG(osh
, &cc
->jtagctrl
, tmp
);
249 void sb_jtagm_disable(osl_t
* osh
, void *h
)
251 chipcregs_t
*cc
= (chipcregs_t
*) h
;
253 W_REG(osh
, &cc
->jtagctrl
, R_REG(osh
, &cc
->jtagctrl
) & ~JCTRL_EN
);
257 * Read/write a jtag register. Assumes a target with
258 * 8 bit IR and 32 bit DR.
260 #define IRWIDTH 8 /* Default Instruction Register width */
261 #define DRWIDTH 32 /* Default Data Register width */
263 uint32
jtag_rwreg(osl_t
* osh
, void *h
, uint32 ir
, uint32 dr
)
265 chipcregs_t
*cc
= (chipcregs_t
*) h
;
268 W_REG(osh
, &cc
->jtagir
, ir
);
269 W_REG(osh
, &cc
->jtagdr
, dr
);
270 tmp
= JCMD_START
| JCMD_ACC_IRDR
|
271 ((IRWIDTH
- 1) << JCMD_IRW_SHIFT
) | (DRWIDTH
- 1);
272 W_REG(osh
, &cc
->jtagcmd
, tmp
);
273 while (((tmp
= R_REG(osh
, &cc
->jtagcmd
)) & JCMD_BUSY
) == JCMD_BUSY
) {
277 tmp
= R_REG(osh
, &cc
->jtagdr
);
283 * Interface to register chipc secondary isr
286 BCMINITFN(sb_cc_register_isr
) (sb_t
* sbh
, cc_isr_fn isr
, uint32 ccintmask
,
293 /* Save the current core index */
294 origidx
= sb_coreidx(sbh
);
295 regs
= sb_setcore(sbh
, SB_CC
, 0);
298 for (i
= 0; i
< MAX_CC_INT_SOURCE
; i
++) {
299 if (cc_isr_desc
[i
].isr
== NULL
) {
300 cc_isr_desc
[i
].isr
= isr
;
301 cc_isr_desc
[i
].cbdata
= cbdata
;
302 cc_isr_desc
[i
].intmask
= ccintmask
;
309 cc_intmask
= R_REG(sb_osh(sbh
), ®s
->intmask
);
310 cc_intmask
|= ccintmask
;
311 W_REG(sb_osh(sbh
), ®s
->intmask
, cc_intmask
);
314 /* restore original coreidx */
315 sb_setcoreidx(sbh
, origidx
);
320 * chipc primary interrupt handler
322 void sb_cc_isr(sb_t
* sbh
, chipcregs_t
* regs
)
328 /* prior to rev 21 chipc interrupt means uart and gpio */
329 if (sbh
->ccrev
>= 21)
330 ccintstatus
= R_REG(sb_osh(sbh
), ®s
->intstatus
) & cc_intmask
;
332 ccintstatus
= (CI_UART
| CI_GPIO
);
334 for (i
= 0; i
< MAX_CC_INT_SOURCE
; i
++) {
335 if ((cc_isr_desc
[i
].isr
!= NULL
) &&
336 (intstatus
= (cc_isr_desc
[i
].intmask
& ccintstatus
))) {
337 (cc_isr_desc
[i
].isr
) (cc_isr_desc
[i
].cbdata
, intstatus
);