Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/bcma/driver_chipcommon.c
26278 views
1
/*
2
* Broadcom specific AMBA
3
* ChipCommon core driver
4
*
5
* Copyright 2005, Broadcom Corporation
6
* Copyright 2006, 2007, Michael Buesch <[email protected]>
7
* Copyright 2012, Hauke Mehrtens <[email protected]>
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
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
EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock);
36
37
static bool bcma_core_cc_has_pmu_watchdog(struct bcma_drv_cc *cc)
38
{
39
struct bcma_bus *bus = cc->core->bus;
40
41
if (cc->capabilities & BCMA_CC_CAP_PMU) {
42
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53573) {
43
WARN(bus->chipinfo.rev <= 1, "No watchdog available\n");
44
/* 53573B0 and 53573B1 have bugged PMU watchdog. It can
45
* be enabled but timer can't be bumped. Use CC one
46
* instead.
47
*/
48
return false;
49
}
50
return true;
51
} else {
52
return false;
53
}
54
}
55
56
static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
57
{
58
struct bcma_bus *bus = cc->core->bus;
59
u32 nb;
60
61
if (bcma_core_cc_has_pmu_watchdog(cc)) {
62
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
63
nb = 32;
64
else if (cc->core->id.rev < 26)
65
nb = 16;
66
else
67
nb = (cc->core->id.rev >= 37) ? 32 : 24;
68
} else {
69
nb = 28;
70
}
71
if (nb == 32)
72
return 0xffffffff;
73
else
74
return (1 << nb) - 1;
75
}
76
77
static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
78
u32 ticks)
79
{
80
struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
81
82
return bcma_chipco_watchdog_timer_set(cc, ticks);
83
}
84
85
static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt,
86
u32 ms)
87
{
88
struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
89
u32 ticks;
90
91
ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
92
return ticks / cc->ticks_per_ms;
93
}
94
95
static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc)
96
{
97
struct bcma_bus *bus = cc->core->bus;
98
99
if (cc->capabilities & BCMA_CC_CAP_PMU) {
100
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
101
/* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP
102
* clock
103
*/
104
return bcma_chipco_get_alp_clock(cc) / 4000;
105
else
106
/* based on 32KHz ILP clock */
107
return 32;
108
} else {
109
return bcma_chipco_get_alp_clock(cc) / 1000;
110
}
111
}
112
113
int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc)
114
{
115
struct bcma_bus *bus = cc->core->bus;
116
struct bcm47xx_wdt wdt = {};
117
struct platform_device *pdev;
118
119
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53573 &&
120
bus->chipinfo.rev <= 1) {
121
pr_debug("No watchdog on 53573A0 / 53573A1\n");
122
return 0;
123
}
124
125
wdt.driver_data = cc;
126
wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt;
127
wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt;
128
wdt.max_timer_ms =
129
bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
130
131
pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
132
bus->num, &wdt,
133
sizeof(wdt));
134
if (IS_ERR(pdev))
135
return PTR_ERR(pdev);
136
137
cc->watchdog = pdev;
138
139
return 0;
140
}
141
142
static void bcma_core_chipcommon_flash_detect(struct bcma_drv_cc *cc)
143
{
144
struct bcma_bus *bus = cc->core->bus;
145
146
switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
147
case BCMA_CC_FLASHT_STSER:
148
case BCMA_CC_FLASHT_ATSER:
149
bcma_debug(bus, "Found serial flash\n");
150
bcma_sflash_init(cc);
151
break;
152
case BCMA_CC_FLASHT_PARA:
153
bcma_debug(bus, "Found parallel flash\n");
154
bcma_pflash_init(cc);
155
break;
156
default:
157
bcma_err(bus, "Flash type not supported\n");
158
}
159
160
if (cc->core->id.rev == 38 ||
161
bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
162
if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
163
bcma_debug(bus, "Found NAND flash\n");
164
bcma_nflash_init(cc);
165
}
166
}
167
}
168
169
void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
170
{
171
struct bcma_bus *bus = cc->core->bus;
172
173
if (cc->early_setup_done)
174
return;
175
176
spin_lock_init(&cc->gpio_lock);
177
178
if (cc->core->id.rev >= 11)
179
cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
180
cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
181
if (cc->core->id.rev >= 35)
182
cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
183
184
if (cc->capabilities & BCMA_CC_CAP_PMU)
185
bcma_pmu_early_init(cc);
186
187
if (bus->hosttype == BCMA_HOSTTYPE_SOC)
188
bcma_core_chipcommon_flash_detect(cc);
189
190
cc->early_setup_done = true;
191
}
192
193
void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
194
{
195
u32 leddc_on = 10;
196
u32 leddc_off = 90;
197
198
if (cc->setup_done)
199
return;
200
201
bcma_core_chipcommon_early_init(cc);
202
203
if (cc->core->id.rev >= 20) {
204
u32 pullup = 0, pulldown = 0;
205
206
if (cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM43142) {
207
pullup = 0x402e0;
208
pulldown = 0x20500;
209
}
210
211
bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, pullup);
212
bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, pulldown);
213
}
214
215
if (cc->capabilities & BCMA_CC_CAP_PMU)
216
bcma_pmu_init(cc);
217
if (cc->capabilities & BCMA_CC_CAP_PCTL)
218
bcma_err(cc->core->bus, "Power control not implemented!\n");
219
220
if (cc->core->id.rev >= 16) {
221
if (cc->core->bus->sprom.leddc_on_time &&
222
cc->core->bus->sprom.leddc_off_time) {
223
leddc_on = cc->core->bus->sprom.leddc_on_time;
224
leddc_off = cc->core->bus->sprom.leddc_off_time;
225
}
226
bcma_cc_write32(cc, BCMA_CC_GPIOTIMER,
227
((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
228
(leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
229
}
230
cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc);
231
232
cc->setup_done = true;
233
}
234
235
/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
236
u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
237
{
238
u32 maxt;
239
240
maxt = bcma_chipco_watchdog_get_max_timer(cc);
241
if (bcma_core_cc_has_pmu_watchdog(cc)) {
242
if (ticks == 1)
243
ticks = 2;
244
else if (ticks > maxt)
245
ticks = maxt;
246
bcma_pmu_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks);
247
} else {
248
struct bcma_bus *bus = cc->core->bus;
249
250
if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4707 &&
251
bus->chipinfo.id != BCMA_CHIP_ID_BCM47094 &&
252
bus->chipinfo.id != BCMA_CHIP_ID_BCM53018)
253
bcma_core_set_clockmode(cc->core,
254
ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC);
255
256
if (ticks > maxt)
257
ticks = maxt;
258
/* instant NMI */
259
bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
260
}
261
return ticks;
262
}
263
264
void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value)
265
{
266
bcma_cc_write32_masked(cc, BCMA_CC_IRQMASK, mask, value);
267
}
268
269
u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask)
270
{
271
return bcma_cc_read32(cc, BCMA_CC_IRQSTAT) & mask;
272
}
273
274
u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
275
{
276
return bcma_cc_read32(cc, BCMA_CC_GPIOIN) & mask;
277
}
278
279
u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
280
{
281
unsigned long flags;
282
u32 res;
283
284
spin_lock_irqsave(&cc->gpio_lock, flags);
285
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
286
spin_unlock_irqrestore(&cc->gpio_lock, flags);
287
288
return res;
289
}
290
EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out);
291
292
u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
293
{
294
unsigned long flags;
295
u32 res;
296
297
spin_lock_irqsave(&cc->gpio_lock, flags);
298
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
299
spin_unlock_irqrestore(&cc->gpio_lock, flags);
300
301
return res;
302
}
303
EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen);
304
305
/*
306
* If the bit is set to 0, chipcommon controls this GPIO,
307
* if the bit is set to 1, it is used by some part of the chip and not our code.
308
*/
309
u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
310
{
311
unsigned long flags;
312
u32 res;
313
314
spin_lock_irqsave(&cc->gpio_lock, flags);
315
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
316
spin_unlock_irqrestore(&cc->gpio_lock, flags);
317
318
return res;
319
}
320
EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
321
322
u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
323
{
324
unsigned long flags;
325
u32 res;
326
327
spin_lock_irqsave(&cc->gpio_lock, flags);
328
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
329
spin_unlock_irqrestore(&cc->gpio_lock, flags);
330
331
return res;
332
}
333
334
u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
335
{
336
unsigned long flags;
337
u32 res;
338
339
spin_lock_irqsave(&cc->gpio_lock, flags);
340
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
341
spin_unlock_irqrestore(&cc->gpio_lock, flags);
342
343
return res;
344
}
345
346
u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value)
347
{
348
unsigned long flags;
349
u32 res;
350
351
if (cc->core->id.rev < 20)
352
return 0;
353
354
spin_lock_irqsave(&cc->gpio_lock, flags);
355
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value);
356
spin_unlock_irqrestore(&cc->gpio_lock, flags);
357
358
return res;
359
}
360
361
u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
362
{
363
unsigned long flags;
364
u32 res;
365
366
if (cc->core->id.rev < 20)
367
return 0;
368
369
spin_lock_irqsave(&cc->gpio_lock, flags);
370
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value);
371
spin_unlock_irqrestore(&cc->gpio_lock, flags);
372
373
return res;
374
}
375
376
#ifdef CONFIG_BCMA_DRIVER_MIPS
377
void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
378
{
379
unsigned int irq;
380
u32 baud_base;
381
u32 i;
382
unsigned int ccrev = cc->core->id.rev;
383
struct bcma_serial_port *ports = cc->serial_ports;
384
385
if (ccrev >= 11 && ccrev != 15) {
386
baud_base = bcma_chipco_get_alp_clock(cc);
387
if (ccrev >= 21) {
388
/* Turn off UART clock before switching clocksource. */
389
bcma_cc_write32(cc, BCMA_CC_CORECTL,
390
bcma_cc_read32(cc, BCMA_CC_CORECTL)
391
& ~BCMA_CC_CORECTL_UARTCLKEN);
392
}
393
/* Set the override bit so we don't divide it */
394
bcma_cc_write32(cc, BCMA_CC_CORECTL,
395
bcma_cc_read32(cc, BCMA_CC_CORECTL)
396
| BCMA_CC_CORECTL_UARTCLK0);
397
if (ccrev >= 21) {
398
/* Re-enable the UART clock. */
399
bcma_cc_write32(cc, BCMA_CC_CORECTL,
400
bcma_cc_read32(cc, BCMA_CC_CORECTL)
401
| BCMA_CC_CORECTL_UARTCLKEN);
402
}
403
} else {
404
bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n",
405
ccrev);
406
return;
407
}
408
409
irq = bcma_core_irq(cc->core, 0);
410
411
/* Determine the registers of the UARTs */
412
cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
413
for (i = 0; i < cc->nr_serial_ports; i++) {
414
ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
415
(i * 256);
416
ports[i].irq = irq;
417
ports[i].baud_base = baud_base;
418
ports[i].reg_shift = 0;
419
}
420
}
421
#endif /* CONFIG_BCMA_DRIVER_MIPS */
422
423