1 /*
2  * Broadcom specific AMBA
3  * ChipCommon core driver
4  *
5  * Copyright 2005, Broadcom Corporation
6  * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
7  * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
8  *
9  * Licensed under the GNU/GPL. See COPYING for details.
10  */
11 
12 #include "bcma_private.h"
13 #include <linux/bcm47xx_wdt.h>
14 #include <linux/export.h>
15 #include <linux/platform_device.h>
16 #include <linux/bcma/bcma.h>
17 
18 static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
19 					 u32 mask, u32 value)
20 {
21 	value &= mask;
22 	value |= bcma_cc_read32(cc, offset) & ~mask;
23 	bcma_cc_write32(cc, offset, value);
24 
25 	return value;
26 }
27 
28 static u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
29 {
30 	if (cc->capabilities & BCMA_CC_CAP_PMU)
31 		return bcma_pmu_get_alp_clock(cc);
32 
33 	return 20000000;
34 }
35 
36 static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
37 {
38 	struct bcma_bus *bus = cc->core->bus;
39 	u32 nb;
40 
41 	if (cc->capabilities & BCMA_CC_CAP_PMU) {
42 		if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
43 			nb = 32;
44 		else if (cc->core->id.rev < 26)
45 			nb = 16;
46 		else
47 			nb = (cc->core->id.rev >= 37) ? 32 : 24;
48 	} else {
49 		nb = 28;
50 	}
51 	if (nb == 32)
52 		return 0xffffffff;
53 	else
54 		return (1 << nb) - 1;
55 }
56 
57 static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
58 					      u32 ticks)
59 {
60 	struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
61 
62 	return bcma_chipco_watchdog_timer_set(cc, ticks);
63 }
64 
65 static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt,
66 						 u32 ms)
67 {
68 	struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
69 	u32 ticks;
70 
71 	ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
72 	return ticks / cc->ticks_per_ms;
73 }
74 
75 static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc)
76 {
77 	struct bcma_bus *bus = cc->core->bus;
78 
79 	if (cc->capabilities & BCMA_CC_CAP_PMU) {
80 		if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
81 			/* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
82 			return bcma_chipco_get_alp_clock(cc) / 4000;
83 		else
84 			/* based on 32KHz ILP clock */
85 			return 32;
86 	} else {
87 		return bcma_chipco_get_alp_clock(cc) / 1000;
88 	}
89 }
90 
91 int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc)
92 {
93 	struct bcm47xx_wdt wdt = {};
94 	struct platform_device *pdev;
95 
96 	wdt.driver_data = cc;
97 	wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt;
98 	wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt;
99 	wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
100 
101 	pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
102 					     cc->core->bus->num, &wdt,
103 					     sizeof(wdt));
104 	if (IS_ERR(pdev))
105 		return PTR_ERR(pdev);
106 
107 	cc->watchdog = pdev;
108 
109 	return 0;
110 }
111 
112 void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
113 {
114 	if (cc->early_setup_done)
115 		return;
116 
117 	spin_lock_init(&cc->gpio_lock);
118 
119 	if (cc->core->id.rev >= 11)
120 		cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
121 	cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
122 	if (cc->core->id.rev >= 35)
123 		cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
124 
125 	if (cc->capabilities & BCMA_CC_CAP_PMU)
126 		bcma_pmu_early_init(cc);
127 
128 	cc->early_setup_done = true;
129 }
130 
131 void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
132 {
133 	u32 leddc_on = 10;
134 	u32 leddc_off = 90;
135 
136 	if (cc->setup_done)
137 		return;
138 
139 	bcma_core_chipcommon_early_init(cc);
140 
141 	if (cc->core->id.rev >= 20) {
142 		bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
143 		bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0);
144 	}
145 
146 	if (cc->capabilities & BCMA_CC_CAP_PMU)
147 		bcma_pmu_init(cc);
148 	if (cc->capabilities & BCMA_CC_CAP_PCTL)
149 		bcma_err(cc->core->bus, "Power control not implemented!\n");
150 
151 	if (cc->core->id.rev >= 16) {
152 		if (cc->core->bus->sprom.leddc_on_time &&
153 		    cc->core->bus->sprom.leddc_off_time) {
154 			leddc_on = cc->core->bus->sprom.leddc_on_time;
155 			leddc_off = cc->core->bus->sprom.leddc_off_time;
156 		}
157 		bcma_cc_write32(cc, BCMA_CC_GPIOTIMER,
158 			((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
159 			 (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
160 	}
161 	cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc);
162 
163 	cc->setup_done = true;
164 }
165 
166 /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
167 u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
168 {
169 	u32 maxt;
170 	enum bcma_clkmode clkmode;
171 
172 	maxt = bcma_chipco_watchdog_get_max_timer(cc);
173 	if (cc->capabilities & BCMA_CC_CAP_PMU) {
174 		if (ticks == 1)
175 			ticks = 2;
176 		else if (ticks > maxt)
177 			ticks = maxt;
178 		bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks);
179 	} else {
180 		clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC;
181 		bcma_core_set_clockmode(cc->core, clkmode);
182 		if (ticks > maxt)
183 			ticks = maxt;
184 		/* instant NMI */
185 		bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
186 	}
187 	return ticks;
188 }
189 
190 void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value)
191 {
192 	bcma_cc_write32_masked(cc, BCMA_CC_IRQMASK, mask, value);
193 }
194 
195 u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask)
196 {
197 	return bcma_cc_read32(cc, BCMA_CC_IRQSTAT) & mask;
198 }
199 
200 u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
201 {
202 	return bcma_cc_read32(cc, BCMA_CC_GPIOIN) & mask;
203 }
204 
205 u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
206 {
207 	unsigned long flags;
208 	u32 res;
209 
210 	spin_lock_irqsave(&cc->gpio_lock, flags);
211 	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
212 	spin_unlock_irqrestore(&cc->gpio_lock, flags);
213 
214 	return res;
215 }
216 
217 u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
218 {
219 	unsigned long flags;
220 	u32 res;
221 
222 	spin_lock_irqsave(&cc->gpio_lock, flags);
223 	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
224 	spin_unlock_irqrestore(&cc->gpio_lock, flags);
225 
226 	return res;
227 }
228 
229 /*
230  * If the bit is set to 0, chipcommon controlls this GPIO,
231  * if the bit is set to 1, it is used by some part of the chip and not our code.
232  */
233 u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
234 {
235 	unsigned long flags;
236 	u32 res;
237 
238 	spin_lock_irqsave(&cc->gpio_lock, flags);
239 	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
240 	spin_unlock_irqrestore(&cc->gpio_lock, flags);
241 
242 	return res;
243 }
244 EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
245 
246 u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
247 {
248 	unsigned long flags;
249 	u32 res;
250 
251 	spin_lock_irqsave(&cc->gpio_lock, flags);
252 	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
253 	spin_unlock_irqrestore(&cc->gpio_lock, flags);
254 
255 	return res;
256 }
257 
258 u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
259 {
260 	unsigned long flags;
261 	u32 res;
262 
263 	spin_lock_irqsave(&cc->gpio_lock, flags);
264 	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
265 	spin_unlock_irqrestore(&cc->gpio_lock, flags);
266 
267 	return res;
268 }
269 
270 u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value)
271 {
272 	unsigned long flags;
273 	u32 res;
274 
275 	if (cc->core->id.rev < 20)
276 		return 0;
277 
278 	spin_lock_irqsave(&cc->gpio_lock, flags);
279 	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value);
280 	spin_unlock_irqrestore(&cc->gpio_lock, flags);
281 
282 	return res;
283 }
284 
285 u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
286 {
287 	unsigned long flags;
288 	u32 res;
289 
290 	if (cc->core->id.rev < 20)
291 		return 0;
292 
293 	spin_lock_irqsave(&cc->gpio_lock, flags);
294 	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value);
295 	spin_unlock_irqrestore(&cc->gpio_lock, flags);
296 
297 	return res;
298 }
299 
300 #ifdef CONFIG_BCMA_DRIVER_MIPS
301 void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
302 {
303 	unsigned int irq;
304 	u32 baud_base;
305 	u32 i;
306 	unsigned int ccrev = cc->core->id.rev;
307 	struct bcma_serial_port *ports = cc->serial_ports;
308 
309 	if (ccrev >= 11 && ccrev != 15) {
310 		baud_base = bcma_chipco_get_alp_clock(cc);
311 		if (ccrev >= 21) {
312 			/* Turn off UART clock before switching clocksource. */
313 			bcma_cc_write32(cc, BCMA_CC_CORECTL,
314 				       bcma_cc_read32(cc, BCMA_CC_CORECTL)
315 				       & ~BCMA_CC_CORECTL_UARTCLKEN);
316 		}
317 		/* Set the override bit so we don't divide it */
318 		bcma_cc_write32(cc, BCMA_CC_CORECTL,
319 			       bcma_cc_read32(cc, BCMA_CC_CORECTL)
320 			       | BCMA_CC_CORECTL_UARTCLK0);
321 		if (ccrev >= 21) {
322 			/* Re-enable the UART clock. */
323 			bcma_cc_write32(cc, BCMA_CC_CORECTL,
324 				       bcma_cc_read32(cc, BCMA_CC_CORECTL)
325 				       | BCMA_CC_CORECTL_UARTCLKEN);
326 		}
327 	} else {
328 		bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev);
329 		return;
330 	}
331 
332 	irq = bcma_core_irq(cc->core);
333 
334 	/* Determine the registers of the UARTs */
335 	cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
336 	for (i = 0; i < cc->nr_serial_ports; i++) {
337 		ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
338 				(i * 256);
339 		ports[i].irq = irq;
340 		ports[i].baud_base = baud_base;
341 		ports[i].reg_shift = 0;
342 	}
343 }
344 #endif /* CONFIG_BCMA_DRIVER_MIPS */
345