Broadcom SDK and wireless driver: another attempt to update to ver. 5.10.147.0
[tomato.git] / release / src-rt / shared / hndchipc.c
blob1a7f2724df556337048bc65f4a2eb639244fdac9
1 /*
2 * BCM47XX support code for some chipcommon facilities (uart, jtagm)
4 * Copyright (C) 2009, Broadcom Corporation
5 * All Rights Reserved.
6 *
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.
12 * $Id: hndchipc.c,v 1.23 2008/03/28 19:30:38 Exp $
15 #include <typedefs.h>
16 #include <bcmdefs.h>
17 #include <osl.h>
18 #include <bcmutils.h>
19 #include <siutils.h>
20 #include <bcmnvram.h>
21 #include <hndsoc.h>
22 #include <sbchipc.h>
23 #include <hndchipc.h>
24 #include <hndcpu.h>
26 /* debug/trace */
27 #define CC_ERROR(args)
29 #define CC_MSG(args)
31 /* interested chipcommon interrupt source
32 * - GPIO
33 * - EXTIF
34 * - ECI
35 * - PMU
36 * - UART
38 #define MAX_CC_INT_SOURCE 5
40 /* chipc secondary isr info */
41 typedef struct {
42 uint intmask; /* int mask */
43 cc_isr_fn isr; /* secondary isr handler */
44 void *cbdata; /* pointer to private data */
45 } cc_isr_info_t;
47 static cc_isr_info_t cc_isr_desc[MAX_CC_INT_SOURCE];
49 /* chip common intmask */
50 static uint32 cc_intmask = 0;
53 * Initializes UART access. The callback function will be called once
54 * per found UART.
56 void
57 BCMINITFN(si_serial_init)(si_t *sih, si_serial_init_fn add)
59 osl_t *osh;
60 void *regs;
61 chipcregs_t *cc;
62 uint32 rev, cap, pll, baud_base, div;
63 uint irq;
64 int i, n;
66 osh = si_osh(sih);
68 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX);
69 ASSERT(cc);
71 /* Default value */
72 div = 48;
74 /* Determine core revision and capabilities */
75 rev = sih->ccrev;
76 cap = sih->cccaps;
77 pll = cap & CC_CAP_PLL_MASK;
79 /* Determine IRQ */
80 irq = si_irq(sih);
82 if (CCPLL_ENAB(sih) && pll == PLL_TYPE1) {
83 /* PLL clock */
84 baud_base = si_clock_rate(pll,
85 R_REG(osh, &cc->clockcontrol_n),
86 R_REG(osh, &cc->clockcontrol_m2));
87 div = 1;
88 } else {
89 /* 5354 chip common uart uses a constant clock
90 * frequency of 25MHz */
91 if (rev == 20) {
92 /* Set the override bit so we don't divide it */
93 W_REG(osh, &cc->corecontrol, CC_UARTCLKO);
94 baud_base = 25000000;
95 } else if (rev >= 11 && rev != 15) {
96 /* Fixed ALP clock */
97 baud_base = si_alp_clock(sih);
98 div = 1;
99 /* Turn off UART clock before switching clock source */
100 if (rev >= 21)
101 AND_REG(osh, &cc->corecontrol, ~CC_UARTCLKEN);
102 /* Set the override bit so we don't divide it */
103 OR_REG(osh, &cc->corecontrol, CC_UARTCLKO);
104 if (rev >= 21)
105 OR_REG(osh, &cc->corecontrol, CC_UARTCLKEN);
106 } else if (rev >= 3) {
107 /* Internal backplane clock */
108 baud_base = si_clock(sih);
109 div = 2; /* Minimum divisor */
110 W_REG(osh, &cc->clkdiv,
111 ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div));
112 } else {
113 /* Fixed internal backplane clock */
114 baud_base = 88000000;
115 div = 48;
118 /* Clock source depends on strapping if UartClkOverride is unset */
119 if ((rev > 0) &&
120 ((R_REG(osh, &cc->corecontrol) & CC_UARTCLKO) == 0)) {
121 if ((cap & CC_CAP_UCLKSEL) == CC_CAP_UINTCLK) {
122 /* Internal divided backplane clock */
123 baud_base /= div;
124 } else {
125 /* Assume external clock of 1.8432 MHz */
126 baud_base = 1843200;
131 /* Add internal UARTs */
132 n = cap & CC_CAP_UARTS_MASK;
133 for (i = 0; i < n; i++) {
134 /* Register offset changed after revision 0 */
135 if (rev)
136 regs = (void *)((ulong) &cc->uart0data + (i * 256));
137 else
138 regs = (void *)((ulong) &cc->uart0data + (i * 8));
140 if (add)
141 add(regs, irq, baud_base, 0);
146 * Initialize jtag master and return handle for
147 * jtag_rwreg. Returns NULL on failure.
149 void *
150 hnd_jtagm_init(si_t *sih, uint clkd, bool exttap)
152 void *regs;
154 if ((regs = si_setcoreidx(sih, SI_CC_IDX)) != NULL) {
155 chipcregs_t *cc = (chipcregs_t *) regs;
156 uint32 tmp;
159 * Determine jtagm availability from
160 * core revision and capabilities.
164 * Corerev 10 has jtagm, but the only chip
165 * with it does not have a mips, and
166 * the layout of the jtagcmd register is
167 * different. We'll only accept >= 11.
169 if (sih->ccrev < 11)
170 return (NULL);
172 if ((sih->cccaps & CC_CAP_JTAGP) == 0)
173 return (NULL);
175 /* Set clock divider if requested */
176 if (clkd != 0) {
177 tmp = R_REG(osh, &cc->clkdiv);
178 tmp = (tmp & ~CLKD_JTAG) |
179 ((clkd << CLKD_JTAG_SHIFT) & CLKD_JTAG);
180 W_REG(osh, &cc->clkdiv, tmp);
183 /* Enable jtagm */
184 tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0);
185 W_REG(osh, &cc->jtagctrl, tmp);
188 return (regs);
191 void
192 hnd_jtagm_disable(osl_t *osh, void *h)
194 chipcregs_t *cc = (chipcregs_t *)h;
196 W_REG(osh, &cc->jtagctrl, R_REG(osh, &cc->jtagctrl) & ~JCTRL_EN);
200 * Read/write a jtag register. Assumes a target with
201 * 8 bit IR and 32 bit DR.
203 #define IRWIDTH 8 /* Default Instruction Register width */
204 #define DRWIDTH 32 /* Default Data Register width */
206 uint32
207 jtag_rwreg(osl_t *osh, void *h, uint32 ir, uint32 dr)
209 chipcregs_t *cc = (chipcregs_t *) h;
210 uint32 tmp;
212 W_REG(osh, &cc->jtagir, ir);
213 W_REG(osh, &cc->jtagdr, dr);
214 tmp = JCMD_START | JCMD_ACC_IRDR |
215 ((IRWIDTH - 1) << JCMD_IRW_SHIFT) |
216 (DRWIDTH - 1);
217 W_REG(osh, &cc->jtagcmd, tmp);
218 while (((tmp = R_REG(osh, &cc->jtagcmd)) & JCMD_BUSY) == JCMD_BUSY) {
219 /* OSL_DELAY(1); */
222 tmp = R_REG(osh, &cc->jtagdr);
223 return (tmp);
228 * Interface to register chipc secondary isr
231 bool
232 BCMINITFN(si_cc_register_isr)(si_t *sih, cc_isr_fn isr, uint32 ccintmask, void *cbdata)
234 bool done = FALSE;
235 chipcregs_t *regs;
236 uint origidx;
237 uint i;
239 /* Save the current core index */
240 origidx = si_coreidx(sih);
241 regs = si_setcoreidx(sih, SI_CC_IDX);
242 ASSERT(regs);
244 for (i = 0; i < MAX_CC_INT_SOURCE; i++) {
245 if (cc_isr_desc[i].isr == NULL) {
246 cc_isr_desc[i].isr = isr;
247 cc_isr_desc[i].cbdata = cbdata;
248 cc_isr_desc[i].intmask = ccintmask;
249 done = TRUE;
250 break;
254 if (done) {
255 cc_intmask = R_REG(si_osh(sih), &regs->intmask);
256 cc_intmask |= ccintmask;
257 W_REG(si_osh(sih), &regs->intmask, cc_intmask);
260 /* restore original coreidx */
261 si_setcoreidx(sih, origidx);
262 return done;
266 * chipc primary interrupt handler
270 void
271 si_cc_isr(si_t *sih, chipcregs_t *regs)
273 uint32 ccintstatus;
274 uint32 intstatus;
275 uint32 i;
277 /* prior to rev 21 chipc interrupt means uart and gpio */
278 if (sih->ccrev >= 21)
279 ccintstatus = R_REG(si_osh(sih), &regs->intstatus) & cc_intmask;
280 else
281 ccintstatus = (CI_UART | CI_GPIO);
283 for (i = 0; i < MAX_CC_INT_SOURCE; i ++) {
284 if ((cc_isr_desc[i].isr != NULL) &&
285 (intstatus = (cc_isr_desc[i].intmask & ccintstatus))) {
286 (cc_isr_desc[i].isr)(cc_isr_desc[i].cbdata, intstatus);