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)
32 /* interested chipcommon interrupt source
39 #define MAX_CC_INT_SOURCE 5
41 /* chipc secondary isr info */
43 uint intmask
; /* int mask */
44 cc_isr_fn isr
; /* secondary isr handler */
45 void *cbdata
; /* pointer to private data */
48 static cc_isr_info_t cc_isr_desc
[MAX_CC_INT_SOURCE
];
50 /* chip common intmask */
51 static uint32 cc_intmask
= 0;
54 * Initializes UART access. The callback function will be called once
58 BCMINITFN(sb_serial_init
)(sb_t
*sbh
, sb_serial_init_fn add
)
63 uint32 rev
, cap
, pll
, baud_base
, div
;
69 cc
= (chipcregs_t
*)sb_setcore(sbh
, SB_CC
, 0);
75 /* Determine core revision and capabilities */
78 pll
= cap
& CC_CAP_PLL_MASK
;
83 if (pll
== PLL_TYPE1
) {
85 baud_base
= sb_clock_rate(pll
,
86 R_REG(osh
, &cc
->clockcontrol_n
),
87 R_REG(osh
, &cc
->clockcontrol_m2
));
90 /* 5354 chip common uart uses a constant clock
91 * frequency of 25MHz */
92 if (sb_corerev(sbh
) == 20) {
93 /* Set the override bit so we don't divide it */
94 W_REG(osh
, &cc
->corecontrol
, CC_UARTCLKO
);
96 } else if (rev
>= 11 && rev
!= 15) {
98 baud_base
= sb_alp_clock(sbh
);
100 /* Turn off UART clock before switching clock source */
102 AND_REG(osh
, &cc
->corecontrol
, ~CC_UARTCLKEN
);
103 /* Set the override bit so we don't divide it */
104 OR_REG(osh
, &cc
->corecontrol
, CC_UARTCLKO
);
106 OR_REG(osh
, &cc
->corecontrol
, CC_UARTCLKEN
);
107 } else if (rev
>= 3) {
108 /* Internal backplane clock */
109 baud_base
= sb_clock(sbh
);
110 div
= 2; /* Minimum divisor */
111 W_REG(osh
, &cc
->clkdiv
,
112 ((R_REG(osh
, &cc
->clkdiv
) & ~CLKD_UART
) | div
));
114 /* Fixed internal backplane clock */
115 baud_base
= 88000000;
119 /* Clock source depends on strapping if UartClkOverride is unset */
121 ((R_REG(osh
, &cc
->corecontrol
) & CC_UARTCLKO
) == 0)) {
122 if ((cap
& CC_CAP_UCLKSEL
) == CC_CAP_UINTCLK
) {
123 /* Internal divided backplane clock */
126 /* Assume external clock of 1.8432 MHz */
132 /* Add internal UARTs */
133 n
= cap
& CC_CAP_UARTS_MASK
;
134 for (i
= 0; i
< n
; i
++) {
135 /* Register offset changed after revision 0 */
137 regs
= (void *)((ulong
) &cc
->uart0data
+ (i
* 256));
139 regs
= (void *)((ulong
) &cc
->uart0data
+ (i
* 8));
142 add(regs
, irq
, baud_base
, 0);
147 * Initialize jtag master and return handle for
148 * jtag_rwreg. Returns NULL on failure.
151 sb_jtagm_init(sb_t
*sbh
, uint clkd
, bool exttap
)
155 if ((regs
= sb_setcore(sbh
, SB_CC
, 0)) != NULL
) {
156 chipcregs_t
*cc
= (chipcregs_t
*) regs
;
160 * Determine jtagm availability from
161 * core revision and capabilities.
165 * Corerev 10 has jtagm, but the only chip
166 * with it does not have a mips, and
167 * the layout of the jtagcmd register is
168 * different. We'll only accept >= 11.
173 if ((sbh
->cccaps
& CC_CAP_JTAGP
) == 0)
176 /* Set clock divider if requested */
178 tmp
= R_REG(osh
, &cc
->clkdiv
);
179 tmp
= (tmp
& ~CLKD_JTAG
) |
180 ((clkd
<< CLKD_JTAG_SHIFT
) & CLKD_JTAG
);
181 W_REG(osh
, &cc
->clkdiv
, tmp
);
185 tmp
= JCTRL_EN
| (exttap
? JCTRL_EXT_EN
: 0);
186 W_REG(osh
, &cc
->jtagctrl
, tmp
);
193 sb_jtagm_disable(osl_t
*osh
, void *h
)
195 chipcregs_t
*cc
= (chipcregs_t
*)h
;
197 W_REG(osh
, &cc
->jtagctrl
, R_REG(osh
, &cc
->jtagctrl
) & ~JCTRL_EN
);
201 * Read/write a jtag register. Assumes a target with
202 * 8 bit IR and 32 bit DR.
204 #define IRWIDTH 8 /* Default Instruction Register width */
205 #define DRWIDTH 32 /* Default Data Register width */
208 jtag_rwreg(osl_t
*osh
, void *h
, uint32 ir
, uint32 dr
)
210 chipcregs_t
*cc
= (chipcregs_t
*) h
;
213 W_REG(osh
, &cc
->jtagir
, ir
);
214 W_REG(osh
, &cc
->jtagdr
, dr
);
215 tmp
= JCMD_START
| JCMD_ACC_IRDR
|
216 ((IRWIDTH
- 1) << JCMD_IRW_SHIFT
) |
218 W_REG(osh
, &cc
->jtagcmd
, tmp
);
219 while (((tmp
= R_REG(osh
, &cc
->jtagcmd
)) & JCMD_BUSY
) == JCMD_BUSY
) {
223 tmp
= R_REG(osh
, &cc
->jtagdr
);
229 * Interface to register chipc secondary isr
233 BCMINITFN(sb_cc_register_isr
)(sb_t
*sbh
, cc_isr_fn isr
, uint32 ccintmask
, void *cbdata
)
240 /* Save the current core index */
241 origidx
= sb_coreidx(sbh
);
242 regs
= sb_setcore(sbh
, SB_CC
, 0);
245 for (i
= 0; i
< MAX_CC_INT_SOURCE
; i
++) {
246 if (cc_isr_desc
[i
].isr
== NULL
) {
247 cc_isr_desc
[i
].isr
= isr
;
248 cc_isr_desc
[i
].cbdata
= cbdata
;
249 cc_isr_desc
[i
].intmask
= ccintmask
;
256 cc_intmask
= R_REG(sb_osh(sbh
), ®s
->intmask
);
257 cc_intmask
|= ccintmask
;
258 W_REG(sb_osh(sbh
), ®s
->intmask
, cc_intmask
);
261 /* restore original coreidx */
262 sb_setcoreidx(sbh
, origidx
);
267 * chipc primary interrupt handler
272 sb_cc_isr(sb_t
*sbh
, chipcregs_t
*regs
)
278 /* prior to rev 21 chipc interrupt means uart and gpio */
279 if (sbh
->ccrev
>= 21)
280 ccintstatus
= R_REG(sb_osh(sbh
), ®s
->intstatus
) & cc_intmask
;
282 ccintstatus
= (CI_UART
| CI_GPIO
);
284 for (i
= 0; i
< MAX_CC_INT_SOURCE
; i
++) {
285 if ((cc_isr_desc
[i
].isr
!= NULL
) &&
286 (intstatus
= (cc_isr_desc
[i
].intmask
& ccintstatus
))) {
287 (cc_isr_desc
[i
].isr
)(cc_isr_desc
[i
].cbdata
, intstatus
);