GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / shared / hndchipc.c
blob33e2c387bf04349cf8267da5954870e2a1832e66
1 /*
2 * BCM47XX support code for some chipcommon facilities (uart, jtagm)
4 * Copyright (C) 2012, 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: hndchipc.c 300516 2011-12-04 17:39:44Z $
21 #include <bcm_cfg.h>
22 #include <typedefs.h>
23 #include <bcmdefs.h>
24 #include <osl.h>
25 #include <bcmutils.h>
26 #include <siutils.h>
27 #include <bcmnvram.h>
28 #include <hndsoc.h>
29 #include <sbchipc.h>
30 #include <hndchipc.h>
31 #include <hndcpu.h>
33 /* debug/trace */
34 #ifdef BCMDBG_ERR
35 #define CC_ERROR(args) printf args
36 #else
37 #define CC_ERROR(args)
38 #endif /* BCMDBG_ERR */
40 #ifdef BCMDBG
41 #define CC_MSG(args) printf args
42 #else
43 #define CC_MSG(args)
44 #endif /* BCMDBG */
46 /* interested chipcommon interrupt source
47 * - GPIO
48 * - EXTIF
49 * - ECI
50 * - PMU
51 * - UART
53 #define MAX_CC_INT_SOURCE 5
55 /* chipc secondary isr info */
56 typedef struct {
57 uint intmask; /* int mask */
58 cc_isr_fn isr; /* secondary isr handler */
59 void *cbdata; /* pointer to private data */
60 } cc_isr_info_t;
62 static cc_isr_info_t cc_isr_desc[MAX_CC_INT_SOURCE];
64 /* chip common intmask */
65 static uint32 cc_intmask = 0;
68 * ROM accessor to avoid struct in shdat
70 static cc_isr_info_t *
71 get_cc_isr_desc(void)
73 return cc_isr_desc;
77 * Initializes UART access. The callback function will be called once
78 * per found UART.
80 void
81 BCMATTACHFN(si_serial_init)(si_t *sih, si_serial_init_fn add)
83 osl_t *osh;
84 void *regs;
85 chipcregs_t *cc;
86 uint32 rev, cap, pll, baud_base, div;
87 uint irq;
88 int i, n;
90 osh = si_osh(sih);
92 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX);
93 ASSERT(cc);
95 /* Determine core revision and capabilities */
96 rev = sih->ccrev;
97 cap = sih->cccaps;
98 pll = cap & CC_CAP_PLL_MASK;
100 /* Determine IRQ */
101 irq = si_irq(sih);
103 if (CCPLL_ENAB(sih) && pll == PLL_TYPE1) {
104 /* PLL clock */
105 baud_base = si_clock_rate(pll,
106 R_REG(osh, &cc->clockcontrol_n),
107 R_REG(osh, &cc->clockcontrol_m2));
108 div = 1;
109 } else {
110 /* Fixed ALP clock */
111 if (rev >= 11 && rev != 15) {
112 baud_base = si_alp_clock(sih);
113 div = 1;
114 /* Turn off UART clock before switching clock source */
115 if (rev >= 21)
116 AND_REG(osh, &cc->corecontrol, ~CC_UARTCLKEN);
117 /* Set the override bit so we don't divide it */
118 OR_REG(osh, &cc->corecontrol, CC_UARTCLKO);
119 if (rev >= 21)
120 OR_REG(osh, &cc->corecontrol, CC_UARTCLKEN);
121 } else if (rev >= 3) {
122 /* Internal backplane clock */
123 baud_base = si_clock(sih);
124 div = 2; /* Minimum divisor */
125 W_REG(osh, &cc->clkdiv,
126 ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div));
127 } else {
128 /* Fixed internal backplane clock */
129 baud_base = 88000000;
130 div = 48;
133 /* Clock source depends on strapping if UartClkOverride is unset */
134 if ((R_REG(osh, &cc->corecontrol) & CC_UARTCLKO) == 0) {
135 if ((cap & CC_CAP_UCLKSEL) == CC_CAP_UINTCLK) {
136 /* Internal divided backplane clock */
137 baud_base /= div;
138 } else {
139 /* Assume external clock of 1.8432 MHz */
140 baud_base = 1843200;
145 /* Add internal UARTs */
146 n = cap & CC_CAP_UARTS_MASK;
147 for (i = 0; i < n; i++) {
148 regs = (void *)((ulong) &cc->uart0data + (i * 256));
149 if (add)
150 add(regs, irq, baud_base, 0);
154 #define JTAG_RETRIES 10000
157 * Initialize jtag master and return handle for
158 * jtag_rwreg. Returns NULL on failure.
160 void *
161 hnd_jtagm_init(si_t *sih, uint clkd, bool exttap)
163 void *regs;
165 if ((regs = si_setcoreidx(sih, SI_CC_IDX)) != NULL) {
166 chipcregs_t *cc = (chipcregs_t *) regs;
167 uint32 tmp;
170 * Determine jtagm availability from
171 * core revision and capabilities.
175 * Corerev 10 has jtagm, but the only chip
176 * with it does not have a mips, and
177 * the layout of the jtagcmd register is
178 * different. We'll only accept >= 11.
180 if (sih->ccrev < 11)
181 return (NULL);
183 if ((sih->cccaps & CC_CAP_JTAGP) == 0)
184 return (NULL);
186 /* Set clock divider if requested */
187 if (clkd != 0) {
188 tmp = R_REG(NULL, &cc->clkdiv);
189 tmp = (tmp & ~CLKD_JTAG) |
190 ((clkd << CLKD_JTAG_SHIFT) & CLKD_JTAG);
191 W_REG(NULL, &cc->clkdiv, tmp);
194 /* Enable jtagm */
195 tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0);
196 W_REG(NULL, &cc->jtagctrl, tmp);
199 return (regs);
202 void
203 hnd_jtagm_disable(si_t *sih, void *h)
205 chipcregs_t *cc = (chipcregs_t *)h;
207 W_REG(NULL, &cc->jtagctrl, R_REG(NULL, &cc->jtagctrl) & ~JCTRL_EN);
211 static uint32
212 jtm_wait(chipcregs_t *cc, bool readdr)
214 uint i;
216 i = 0;
217 while (((R_REG(NULL, &cc->jtagcmd) & JCMD_BUSY) == JCMD_BUSY) &&
218 (i < JTAG_RETRIES)) {
219 i++;
222 if (i >= JTAG_RETRIES)
223 return 0xbadbad03;
225 if (readdr)
226 return R_REG(NULL, &cc->jtagdr);
227 else
228 return 0xffffffff;
231 /* Read/write a jtag register. Assumes both ir and dr <= 64bits. */
233 uint32
234 jtag_scan(si_t *sih, void *h, uint irsz, uint32 ir0, uint32 ir1,
235 uint drsz, uint32 dr0, uint32 *dr1, bool rti)
237 chipcregs_t *cc = (chipcregs_t *) h;
238 uint32 acc_dr, acc_irdr;
239 uint32 tmp;
241 if ((irsz > 64) || (drsz > 64)) {
242 return 0xbadbad00;
244 if (rti) {
245 if (sih->ccrev < 28)
246 return 0xbadbad01;
247 acc_irdr = JCMD_ACC_IRDR_I;
248 acc_dr = JCMD_ACC_DR_I;
249 } else {
250 acc_irdr = JCMD_ACC_IRDR;
251 acc_dr = JCMD_ACC_DR;
253 if (irsz == 0) {
254 /* scan in the first (or only) DR word with a dr-only command */
255 W_REG(NULL, &cc->jtagdr, dr0);
256 if (drsz > 32) {
257 W_REG(NULL, &cc->jtagcmd, JCMD_START | JCMD_ACC_PDR | 31);
258 drsz -= 32;
259 } else
260 W_REG(NULL, &cc->jtagcmd, JCMD_START | acc_dr | (drsz - 1));
261 } else {
262 W_REG(NULL, &cc->jtagir, ir0);
263 if (irsz > 32) {
264 /* Use Partial IR for first IR word */
265 W_REG(NULL, &cc->jtagcmd, JCMD_START | JCMD_ACC_PIR |
266 (31 << JCMD_IRW_SHIFT));
267 jtm_wait(cc, FALSE);
268 W_REG(NULL, &cc->jtagir, ir1);
269 irsz -= 32;
271 if (drsz == 0) {
272 /* If drsz is 0, do an IR-only scan and that's it */
273 W_REG(NULL, &cc->jtagcmd, JCMD_START | JCMD_ACC_IR |
274 ((irsz - 1) << JCMD_IRW_SHIFT));
275 return jtm_wait(cc, FALSE);
277 /* Now scan in the IR word and the first (or only) DR word */
278 W_REG(NULL, &cc->jtagdr, dr0);
279 if (drsz <= 32)
280 W_REG(NULL, &cc->jtagcmd, JCMD_START | acc_irdr |
281 ((irsz - 1) << JCMD_IRW_SHIFT) | (drsz - 1));
282 else
283 W_REG(NULL, &cc->jtagcmd, JCMD_START | JCMD_ACC_IRPDR |
284 ((irsz - 1) << JCMD_IRW_SHIFT) | 31);
286 /* Now scan out the DR and scan in & out the second DR word if needed */
287 tmp = jtm_wait(cc, TRUE);
288 if (drsz > 32) {
289 if (dr1 == NULL)
290 return 0xbadbad04;
291 W_REG(NULL, &cc->jtagdr, *dr1);
292 W_REG(NULL, &cc->jtagcmd, JCMD_START | acc_dr | (drsz - 33));
293 *dr1 = jtm_wait(cc, TRUE);
295 return (tmp);
300 * Interface to register chipc secondary isr
303 bool
304 BCMATTACHFN(si_cc_register_isr)(si_t *sih, cc_isr_fn isr, uint32 ccintmask, void *cbdata)
306 bool done = FALSE;
307 chipcregs_t *regs;
308 uint origidx;
309 uint i;
311 /* Save the current core index */
312 origidx = si_coreidx(sih);
313 regs = si_setcoreidx(sih, SI_CC_IDX);
314 ASSERT(regs);
316 for (i = 0; i < MAX_CC_INT_SOURCE; i++) {
317 if (cc_isr_desc[i].isr == NULL) {
318 cc_isr_desc[i].isr = isr;
319 cc_isr_desc[i].cbdata = cbdata;
320 cc_isr_desc[i].intmask = ccintmask;
321 done = TRUE;
322 break;
326 if (done) {
327 cc_intmask = R_REG(si_osh(sih), &regs->intmask);
328 cc_intmask |= ccintmask;
329 W_REG(si_osh(sih), &regs->intmask, cc_intmask);
332 /* restore original coreidx */
333 si_setcoreidx(sih, origidx);
334 return done;
338 * chipc primary interrupt handler
342 void
343 si_cc_isr(si_t *sih, chipcregs_t *regs)
345 uint32 ccintstatus;
346 uint32 intstatus;
347 uint32 i;
348 cc_isr_info_t *desc;
350 /* prior to rev 21 chipc interrupt means uart and gpio */
351 if (sih->ccrev >= 21)
352 ccintstatus = R_REG(si_osh(sih), &regs->intstatus) & cc_intmask;
353 else
354 ccintstatus = (CI_UART | CI_GPIO);
356 desc = get_cc_isr_desc();
357 ASSERT(desc);
358 for (i = 0; i < MAX_CC_INT_SOURCE; i++, desc++) {
359 if ((desc->isr != NULL) &&
360 (intstatus = (desc->intmask & ccintstatus))) {
361 (desc->isr)(desc->cbdata, intstatus);