OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [ssb/] [driver_chipcommon.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Sonics Silicon Backplane
3
 * Broadcom ChipCommon core driver
4
 *
5
 * Copyright 2005, Broadcom Corporation
6
 * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
7
 *
8
 * Licensed under the GNU/GPL. See COPYING for details.
9
 */
10
 
11
#include <linux/ssb/ssb.h>
12
#include <linux/ssb/ssb_regs.h>
13
#include <linux/pci.h>
14
 
15
#include "ssb_private.h"
16
 
17
 
18
/* Clock sources */
19
enum ssb_clksrc {
20
        /* PCI clock */
21
        SSB_CHIPCO_CLKSRC_PCI,
22
        /* Crystal slow clock oscillator */
23
        SSB_CHIPCO_CLKSRC_XTALOS,
24
        /* Low power oscillator */
25
        SSB_CHIPCO_CLKSRC_LOPWROS,
26
};
27
 
28
 
29
static inline u32 chipco_read32(struct ssb_chipcommon *cc,
30
                                u16 offset)
31
{
32
        return ssb_read32(cc->dev, offset);
33
}
34
 
35
static inline void chipco_write32(struct ssb_chipcommon *cc,
36
                                  u16 offset,
37
                                  u32 value)
38
{
39
        ssb_write32(cc->dev, offset, value);
40
}
41
 
42
static inline void chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset,
43
                                         u32 mask, u32 value)
44
{
45
        value &= mask;
46
        value |= chipco_read32(cc, offset) & ~mask;
47
        chipco_write32(cc, offset, value);
48
}
49
 
50
void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
51
                              enum ssb_clkmode mode)
52
{
53
        struct ssb_device *ccdev = cc->dev;
54
        struct ssb_bus *bus;
55
        u32 tmp;
56
 
57
        if (!ccdev)
58
                return;
59
        bus = ccdev->bus;
60
        /* chipcommon cores prior to rev6 don't support dynamic clock control */
61
        if (ccdev->id.revision < 6)
62
                return;
63
        /* chipcommon cores rev10 are a whole new ball game */
64
        if (ccdev->id.revision >= 10)
65
                return;
66
        if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL))
67
                return;
68
 
69
        switch (mode) {
70
        case SSB_CLKMODE_SLOW:
71
                tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
72
                tmp |= SSB_CHIPCO_SLOWCLKCTL_FSLOW;
73
                chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp);
74
                break;
75
        case SSB_CLKMODE_FAST:
76
                ssb_pci_xtal(bus, SSB_GPIO_XTAL, 1); /* Force crystal on */
77
                tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
78
                tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW;
79
                tmp |= SSB_CHIPCO_SLOWCLKCTL_IPLL;
80
                chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp);
81
                break;
82
        case SSB_CLKMODE_DYNAMIC:
83
                tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
84
                tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW;
85
                tmp &= ~SSB_CHIPCO_SLOWCLKCTL_IPLL;
86
                tmp &= ~SSB_CHIPCO_SLOWCLKCTL_ENXTAL;
87
                if ((tmp & SSB_CHIPCO_SLOWCLKCTL_SRC) != SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL)
88
                        tmp |= SSB_CHIPCO_SLOWCLKCTL_ENXTAL;
89
                chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp);
90
 
91
                /* for dynamic control, we have to release our xtal_pu "force on" */
92
                if (tmp & SSB_CHIPCO_SLOWCLKCTL_ENXTAL)
93
                        ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0);
94
                break;
95
        default:
96
                SSB_WARN_ON(1);
97
        }
98
}
99
 
100
/* Get the Slow Clock Source */
101
static enum ssb_clksrc chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc)
102
{
103
        struct ssb_bus *bus = cc->dev->bus;
104
        u32 uninitialized_var(tmp);
105
 
106
        if (cc->dev->id.revision < 6) {
107
                if (bus->bustype == SSB_BUSTYPE_SSB ||
108
                    bus->bustype == SSB_BUSTYPE_PCMCIA)
109
                        return SSB_CHIPCO_CLKSRC_XTALOS;
110
                if (bus->bustype == SSB_BUSTYPE_PCI) {
111
                        pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &tmp);
112
                        if (tmp & 0x10)
113
                                return SSB_CHIPCO_CLKSRC_PCI;
114
                        return SSB_CHIPCO_CLKSRC_XTALOS;
115
                }
116
        }
117
        if (cc->dev->id.revision < 10) {
118
                tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
119
                tmp &= 0x7;
120
                if (tmp == 0)
121
                        return SSB_CHIPCO_CLKSRC_LOPWROS;
122
                if (tmp == 1)
123
                        return SSB_CHIPCO_CLKSRC_XTALOS;
124
                if (tmp == 2)
125
                        return SSB_CHIPCO_CLKSRC_PCI;
126
        }
127
 
128
        return SSB_CHIPCO_CLKSRC_XTALOS;
129
}
130
 
131
/* Get maximum or minimum (depending on get_max flag) slowclock frequency. */
132
static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max)
133
{
134
        int uninitialized_var(limit);
135
        enum ssb_clksrc clocksrc;
136
        int divisor = 1;
137
        u32 tmp;
138
 
139
        clocksrc = chipco_pctl_get_slowclksrc(cc);
140
        if (cc->dev->id.revision < 6) {
141
                switch (clocksrc) {
142
                case SSB_CHIPCO_CLKSRC_PCI:
143
                        divisor = 64;
144
                        break;
145
                case SSB_CHIPCO_CLKSRC_XTALOS:
146
                        divisor = 32;
147
                        break;
148
                default:
149
                        SSB_WARN_ON(1);
150
                }
151
        } else if (cc->dev->id.revision < 10) {
152
                switch (clocksrc) {
153
                case SSB_CHIPCO_CLKSRC_LOPWROS:
154
                        break;
155
                case SSB_CHIPCO_CLKSRC_XTALOS:
156
                case SSB_CHIPCO_CLKSRC_PCI:
157
                        tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL);
158
                        divisor = (tmp >> 16) + 1;
159
                        divisor *= 4;
160
                        break;
161
                }
162
        } else {
163
                tmp = chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL);
164
                divisor = (tmp >> 16) + 1;
165
                divisor *= 4;
166
        }
167
 
168
        switch (clocksrc) {
169
        case SSB_CHIPCO_CLKSRC_LOPWROS:
170
                if (get_max)
171
                        limit = 43000;
172
                else
173
                        limit = 25000;
174
                break;
175
        case SSB_CHIPCO_CLKSRC_XTALOS:
176
                if (get_max)
177
                        limit = 20200000;
178
                else
179
                        limit = 19800000;
180
                break;
181
        case SSB_CHIPCO_CLKSRC_PCI:
182
                if (get_max)
183
                        limit = 34000000;
184
                else
185
                        limit = 25000000;
186
                break;
187
        }
188
        limit /= divisor;
189
 
190
        return limit;
191
}
192
 
193
static void chipco_powercontrol_init(struct ssb_chipcommon *cc)
194
{
195
        struct ssb_bus *bus = cc->dev->bus;
196
 
197
        if (bus->chip_id == 0x4321) {
198
                if (bus->chip_rev == 0)
199
                        chipco_write32(cc, SSB_CHIPCO_CHIPCTL, 0x3A4);
200
                else if (bus->chip_rev == 1)
201
                        chipco_write32(cc, SSB_CHIPCO_CHIPCTL, 0xA4);
202
        }
203
 
204
        if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL))
205
                return;
206
 
207
        if (cc->dev->id.revision >= 10) {
208
                /* Set Idle Power clock rate to 1Mhz */
209
                chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL,
210
                               (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) &
211
                                0x0000FFFF) | 0x00040000);
212
        } else {
213
                int maxfreq;
214
 
215
                maxfreq = chipco_pctl_clockfreqlimit(cc, 1);
216
                chipco_write32(cc, SSB_CHIPCO_PLLONDELAY,
217
                               (maxfreq * 150 + 999999) / 1000000);
218
                chipco_write32(cc, SSB_CHIPCO_FREFSELDELAY,
219
                               (maxfreq * 15 + 999999) / 1000000);
220
        }
221
}
222
 
223
static void calc_fast_powerup_delay(struct ssb_chipcommon *cc)
224
{
225
        struct ssb_bus *bus = cc->dev->bus;
226
        int minfreq;
227
        unsigned int tmp;
228
        u32 pll_on_delay;
229
 
230
        if (bus->bustype != SSB_BUSTYPE_PCI)
231
                return;
232
        if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL))
233
                return;
234
 
235
        minfreq = chipco_pctl_clockfreqlimit(cc, 0);
236
        pll_on_delay = chipco_read32(cc, SSB_CHIPCO_PLLONDELAY);
237
        tmp = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq;
238
        SSB_WARN_ON(tmp & ~0xFFFF);
239
 
240
        cc->fast_pwrup_delay = tmp;
241
}
242
 
243
void ssb_chipcommon_init(struct ssb_chipcommon *cc)
244
{
245
        if (!cc->dev)
246
                return; /* We don't have a ChipCommon */
247
        chipco_powercontrol_init(cc);
248
        ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
249
        calc_fast_powerup_delay(cc);
250
}
251
 
252
void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state)
253
{
254
        if (!cc->dev)
255
                return;
256
        ssb_chipco_set_clockmode(cc, SSB_CLKMODE_SLOW);
257
}
258
 
259
void ssb_chipco_resume(struct ssb_chipcommon *cc)
260
{
261
        if (!cc->dev)
262
                return;
263
        chipco_powercontrol_init(cc);
264
        ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
265
}
266
 
267
/* Get the processor clock */
268
void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
269
                             u32 *plltype, u32 *n, u32 *m)
270
{
271
        *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
272
        *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
273
        switch (*plltype) {
274
        case SSB_PLLTYPE_2:
275
        case SSB_PLLTYPE_4:
276
        case SSB_PLLTYPE_6:
277
        case SSB_PLLTYPE_7:
278
                *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS);
279
                break;
280
        case SSB_PLLTYPE_3:
281
                /* 5350 uses m2 to control mips */
282
                *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2);
283
                break;
284
        default:
285
                *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB);
286
                break;
287
        }
288
}
289
 
290
/* Get the bus clock */
291
void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
292
                                 u32 *plltype, u32 *n, u32 *m)
293
{
294
        *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
295
        *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
296
        switch (*plltype) {
297
        case SSB_PLLTYPE_6: /* 100/200 or 120/240 only */
298
                *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS);
299
                break;
300
        case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */
301
                if (cc->dev->bus->chip_id != 0x5365) {
302
                        *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2);
303
                        break;
304
                }
305
                /* Fallthough */
306
        default:
307
                *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB);
308
        }
309
}
310
 
311
void ssb_chipco_timing_init(struct ssb_chipcommon *cc,
312
                            unsigned long ns)
313
{
314
        struct ssb_device *dev = cc->dev;
315
        struct ssb_bus *bus = dev->bus;
316
        u32 tmp;
317
 
318
        /* set register for external IO to control LED. */
319
        chipco_write32(cc, SSB_CHIPCO_PROG_CFG, 0x11);
320
        tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;            /* Waitcount-3 = 10ns */
321
        tmp |= DIV_ROUND_UP(40, ns) << SSB_PROG_WCNT_1_SHIFT;   /* Waitcount-1 = 40ns */
322
        tmp |= DIV_ROUND_UP(240, ns);                           /* Waitcount-0 = 240ns */
323
        chipco_write32(cc, SSB_CHIPCO_PROG_WAITCNT, tmp);       /* 0x01020a0c for a 100Mhz clock */
324
 
325
        /* Set timing for the flash */
326
        tmp = DIV_ROUND_UP(10, ns) << SSB_FLASH_WCNT_3_SHIFT;   /* Waitcount-3 = 10nS */
327
        tmp |= DIV_ROUND_UP(10, ns) << SSB_FLASH_WCNT_1_SHIFT;  /* Waitcount-1 = 10nS */
328
        tmp |= DIV_ROUND_UP(120, ns);                           /* Waitcount-0 = 120nS */
329
        if ((bus->chip_id == 0x5365) ||
330
            (dev->id.revision < 9))
331
                chipco_write32(cc, SSB_CHIPCO_FLASH_WAITCNT, tmp);
332
        if ((bus->chip_id == 0x5365) ||
333
            (dev->id.revision < 9) ||
334
            ((bus->chip_id == 0x5350) && (bus->chip_rev == 0)))
335
                chipco_write32(cc, SSB_CHIPCO_PCMCIA_MEMWAIT, tmp);
336
 
337
        if (bus->chip_id == 0x5350) {
338
                /* Enable EXTIF */
339
                tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;      /* Waitcount-3 = 10ns */
340
                tmp |= DIV_ROUND_UP(20, ns) << SSB_PROG_WCNT_2_SHIFT;  /* Waitcount-2 = 20ns */
341
                tmp |= DIV_ROUND_UP(100, ns) << SSB_PROG_WCNT_1_SHIFT; /* Waitcount-1 = 100ns */
342
                tmp |= DIV_ROUND_UP(120, ns);                     /* Waitcount-0 = 120ns */
343
                chipco_write32(cc, SSB_CHIPCO_PROG_WAITCNT, tmp); /* 0x01020a0c for a 100Mhz clock */
344
        }
345
}
346
 
347
/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
348
void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
349
{
350
        /* instant NMI */
351
        chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
352
}
353
 
354
u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
355
{
356
        return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask;
357
}
358
 
359
void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
360
{
361
        chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
362
}
363
 
364
void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
365
{
366
        chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
367
}
368
 
369
#ifdef CONFIG_SSB_SERIAL
370
int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
371
                           struct ssb_serial_port *ports)
372
{
373
        struct ssb_bus *bus = cc->dev->bus;
374
        int nr_ports = 0;
375
        u32 plltype;
376
        unsigned int irq;
377
        u32 baud_base, div;
378
        u32 i, n;
379
 
380
        plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
381
        irq = ssb_mips_irq(cc->dev);
382
 
383
        if (plltype == SSB_PLLTYPE_1) {
384
                /* PLL clock */
385
                baud_base = ssb_calc_clock_rate(plltype,
386
                                                chipco_read32(cc, SSB_CHIPCO_CLOCK_N),
387
                                                chipco_read32(cc, SSB_CHIPCO_CLOCK_M2));
388
                div = 1;
389
        } else {
390
                if (cc->dev->id.revision >= 11) {
391
                        /* Fixed ALP clock */
392
                        baud_base = 20000000;
393
                        div = 1;
394
                        /* Set the override bit so we don't divide it */
395
                        chipco_write32(cc, SSB_CHIPCO_CORECTL,
396
                                       SSB_CHIPCO_CORECTL_UARTCLK0);
397
                } else if (cc->dev->id.revision >= 3) {
398
                        /* Internal backplane clock */
399
                        baud_base = ssb_clockspeed(bus);
400
                        div = chipco_read32(cc, SSB_CHIPCO_CLKDIV)
401
                              & SSB_CHIPCO_CLKDIV_UART;
402
                } else {
403
                        /* Fixed internal backplane clock */
404
                        baud_base = 88000000;
405
                        div = 48;
406
                }
407
 
408
                /* Clock source depends on strapping if UartClkOverride is unset */
409
                if ((cc->dev->id.revision > 0) &&
410
                    !(chipco_read32(cc, SSB_CHIPCO_CORECTL) & SSB_CHIPCO_CORECTL_UARTCLK0)) {
411
                        if ((cc->capabilities & SSB_CHIPCO_CAP_UARTCLK) ==
412
                            SSB_CHIPCO_CAP_UARTCLK_INT) {
413
                                /* Internal divided backplane clock */
414
                                baud_base /= div;
415
                        } else {
416
                                /* Assume external clock of 1.8432 MHz */
417
                                baud_base = 1843200;
418
                        }
419
                }
420
        }
421
 
422
        /* Determine the registers of the UARTs */
423
        n = (cc->capabilities & SSB_CHIPCO_CAP_NRUART);
424
        for (i = 0; i < n; i++) {
425
                void __iomem *cc_mmio;
426
                void __iomem *uart_regs;
427
 
428
                cc_mmio = cc->dev->bus->mmio + (cc->dev->core_index * SSB_CORE_SIZE);
429
                uart_regs = cc_mmio + SSB_CHIPCO_UART0_DATA;
430
                /* Offset changed at after rev 0 */
431
                if (cc->dev->id.revision == 0)
432
                        uart_regs += (i * 8);
433
                else
434
                        uart_regs += (i * 256);
435
 
436
                nr_ports++;
437
                ports[i].regs = uart_regs;
438
                ports[i].irq = irq;
439
                ports[i].baud_base = baud_base;
440
                ports[i].reg_shift = 0;
441
        }
442
 
443
        return nr_ports;
444
}
445
#endif /* CONFIG_SSB_SERIAL */

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.