Blame view
drivers/ssb/driver_mipscore.c
8.78 KB
61e115a56 [SSB]: add Sonics... |
1 2 3 4 5 |
/* * Sonics Silicon Backplane * Broadcom MIPS core driver * * Copyright 2005, Broadcom Corporation |
eb032b983 Update my e-mail ... |
6 |
* Copyright 2006, 2007, Michael Buesch <m@bues.ch> |
61e115a56 [SSB]: add Sonics... |
7 8 9 |
* * Licensed under the GNU/GPL. See COPYING for details. */ |
b8b6069cf ssb: Remove home-... |
10 |
#include "ssb_private.h" |
61e115a56 [SSB]: add Sonics... |
11 |
#include <linux/ssb/ssb.h> |
c7a4a9e38 ssb: register pla... |
12 |
#include <linux/mtd/physmap.h> |
61e115a56 [SSB]: add Sonics... |
13 14 15 16 |
#include <linux/serial.h> #include <linux/serial_core.h> #include <linux/serial_reg.h> #include <linux/time.h> |
21400f252 MIPS: BCM47XX: Ma... |
17 |
#ifdef CONFIG_BCM47XX |
138173d4e MIPS: BCM47xx: Mo... |
18 |
#include <linux/bcm47xx_nvram.h> |
21400f252 MIPS: BCM47XX: Ma... |
19 |
#endif |
61e115a56 [SSB]: add Sonics... |
20 |
|
255e9fd4b ssb: driver_mipsc... |
21 |
static const char * const part_probes[] = { "bcm47xxpart", NULL }; |
c7a4a9e38 ssb: register pla... |
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
static struct physmap_flash_data ssb_pflash_data = { .part_probe_types = part_probes, }; static struct resource ssb_pflash_resource = { .name = "ssb_pflash", .flags = IORESOURCE_MEM, }; struct platform_device ssb_pflash_dev = { .name = "physmap-flash", .dev = { .platform_data = &ssb_pflash_data, }, .resource = &ssb_pflash_resource, .num_resources = 1, }; |
61e115a56 [SSB]: add Sonics... |
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
static inline u32 mips_read32(struct ssb_mipscore *mcore, u16 offset) { return ssb_read32(mcore->dev, offset); } static inline void mips_write32(struct ssb_mipscore *mcore, u16 offset, u32 value) { ssb_write32(mcore->dev, offset, value); } static const u32 ipsflag_irq_mask[] = { 0, SSB_IPSFLAG_IRQ1, SSB_IPSFLAG_IRQ2, SSB_IPSFLAG_IRQ3, SSB_IPSFLAG_IRQ4, }; static const u32 ipsflag_irq_shift[] = { 0, SSB_IPSFLAG_IRQ1_SHIFT, SSB_IPSFLAG_IRQ2_SHIFT, SSB_IPSFLAG_IRQ3_SHIFT, SSB_IPSFLAG_IRQ4_SHIFT, }; static inline u32 ssb_irqflag(struct ssb_device *dev) { |
ea4bbfd00 MIPS: BC47xx: Fix... |
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG); if (tpsflag) return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; else /* not irq supported */ return 0x3f; } static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag) { struct ssb_bus *bus = rdev->bus; int i; for (i = 0; i < bus->nr_devices; i++) { struct ssb_device *dev; dev = &(bus->devices[i]); if (ssb_irqflag(dev) == irqflag) return dev; } return NULL; |
61e115a56 [SSB]: add Sonics... |
91 92 93 94 |
} /* Get the MIPS IRQ assignment for a specified device. * If unassigned, 0 is returned. |
ea4bbfd00 MIPS: BC47xx: Fix... |
95 96 |
* If disabled, 5 is returned. * If not supported, 6 is returned. |
61e115a56 [SSB]: add Sonics... |
97 98 99 100 |
*/ unsigned int ssb_mips_irq(struct ssb_device *dev) { struct ssb_bus *bus = dev->bus; |
ea4bbfd00 MIPS: BC47xx: Fix... |
101 |
struct ssb_device *mdev = bus->mipscore.dev; |
61e115a56 [SSB]: add Sonics... |
102 103 104 105 106 107 |
u32 irqflag; u32 ipsflag; u32 tmp; unsigned int irq; irqflag = ssb_irqflag(dev); |
ea4bbfd00 MIPS: BC47xx: Fix... |
108 109 |
if (irqflag == 0x3f) return 6; |
61e115a56 [SSB]: add Sonics... |
110 111 112 113 114 115 |
ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); for (irq = 1; irq <= 4; irq++) { tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); if (tmp == irqflag) break; } |
ea4bbfd00 MIPS: BC47xx: Fix... |
116 117 118 119 |
if (irq == 5) { if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)) irq = 0; } |
61e115a56 [SSB]: add Sonics... |
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
return irq; } static void clear_irq(struct ssb_bus *bus, unsigned int irq) { struct ssb_device *dev = bus->mipscore.dev; /* Clear the IRQ in the MIPScore backplane registers */ if (irq == 0) { ssb_write32(dev, SSB_INTVEC, 0); } else { ssb_write32(dev, SSB_IPSFLAG, ssb_read32(dev, SSB_IPSFLAG) | ipsflag_irq_mask[irq]); } } static void set_irq(struct ssb_device *dev, unsigned int irq) { unsigned int oldirq = ssb_mips_irq(dev); struct ssb_bus *bus = dev->bus; struct ssb_device *mdev = bus->mipscore.dev; u32 irqflag = ssb_irqflag(dev); |
ea4bbfd00 MIPS: BC47xx: Fix... |
144 |
BUG_ON(oldirq == 6); |
61e115a56 [SSB]: add Sonics... |
145 |
dev->irq = irq + 2; |
61e115a56 [SSB]: add Sonics... |
146 147 148 |
/* clear the old irq */ if (oldirq == 0) ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); |
ea4bbfd00 MIPS: BC47xx: Fix... |
149 |
else if (oldirq != 5) |
61e115a56 [SSB]: add Sonics... |
150 151 152 |
clear_irq(bus, oldirq); /* assign the new one */ |
2633da237 ssb-mipscore: Fix... |
153 154 155 |
if (irq == 0) { ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); } else { |
ea4bbfd00 MIPS: BC47xx: Fix... |
156 157 158 159 160 161 162 |
u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG); if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) { u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]; struct ssb_device *olddev = find_device(dev, oldipsflag); if (olddev) set_irq(olddev, 0); } |
2633da237 ssb-mipscore: Fix... |
163 |
irqflag <<= ipsflag_irq_shift[irq]; |
ea4bbfd00 MIPS: BC47xx: Fix... |
164 |
irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); |
2633da237 ssb-mipscore: Fix... |
165 166 |
ssb_write32(mdev, SSB_IPSFLAG, irqflag); } |
b8b6069cf ssb: Remove home-... |
167 168 |
dev_dbg(dev->dev, "set_irq: core 0x%04x, irq %d => %d ", |
33a606ac8 ssb: Convert ssb_... |
169 |
dev->id.coreid, oldirq+2, irq+2); |
ea4bbfd00 MIPS: BC47xx: Fix... |
170 171 172 173 |
} static void print_irq(struct ssb_device *dev, unsigned int irq) { |
ea4bbfd00 MIPS: BC47xx: Fix... |
174 |
static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; |
b8b6069cf ssb: Remove home-... |
175 176 177 |
dev_dbg(dev->dev, "core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s ", |
33a606ac8 ssb: Convert ssb_... |
178 179 180 181 182 183 184 185 |
dev->id.coreid, irq_name[0], irq == 0 ? "*" : " ", irq_name[1], irq == 1 ? "*" : " ", irq_name[2], irq == 2 ? "*" : " ", irq_name[3], irq == 3 ? "*" : " ", irq_name[4], irq == 4 ? "*" : " ", irq_name[5], irq == 5 ? "*" : " ", irq_name[6], irq == 6 ? "*" : " "); |
ea4bbfd00 MIPS: BC47xx: Fix... |
186 187 188 189 190 191 192 193 194 195 |
} static void dump_irq(struct ssb_bus *bus) { int i; for (i = 0; i < bus->nr_devices; i++) { struct ssb_device *dev; dev = &(bus->devices[i]); print_irq(dev, ssb_mips_irq(dev)); } |
61e115a56 [SSB]: add Sonics... |
196 197 198 199 200 |
} static void ssb_mips_serial_init(struct ssb_mipscore *mcore) { struct ssb_bus *bus = mcore->dev->bus; |
0362063b7 ssb: extif: fix c... |
201 |
if (ssb_extif_available(&bus->extif)) |
61e115a56 [SSB]: add Sonics... |
202 |
mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports); |
0362063b7 ssb: extif: fix c... |
203 |
else if (ssb_chipco_available(&bus->chipco)) |
61e115a56 [SSB]: add Sonics... |
204 205 206 207 208 209 210 211 |
mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports); else mcore->nr_serial_ports = 0; } static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) { struct ssb_bus *bus = mcore->dev->bus; |
21400f252 MIPS: BCM47XX: Ma... |
212 |
struct ssb_sflash *sflash = &mcore->sflash; |
f1ab57e3a ssb: trivial: use... |
213 |
struct ssb_pflash *pflash = &mcore->pflash; |
61e115a56 [SSB]: add Sonics... |
214 |
|
902d9e0f4 ssb: check for fl... |
215 |
/* When there is no chipcommon on the bus there is 4MB flash */ |
0362063b7 ssb: extif: fix c... |
216 |
if (!ssb_chipco_available(&bus->chipco)) { |
f1ab57e3a ssb: trivial: use... |
217 218 219 220 |
pflash->present = true; pflash->buswidth = 2; pflash->window = SSB_FLASH1; pflash->window_size = SSB_FLASH1_SZ; |
c7a4a9e38 ssb: register pla... |
221 |
goto ssb_pflash; |
902d9e0f4 ssb: check for fl... |
222 223 224 225 226 227 |
} /* There is ChipCommon, so use it to read info about flash */ switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) { case SSB_CHIPCO_FLASHT_STSER: case SSB_CHIPCO_FLASHT_ATSER: |
b8b6069cf ssb: Remove home-... |
228 229 |
dev_dbg(mcore->dev->dev, "Found serial flash "); |
72a525cbb ssb: add place fo... |
230 |
ssb_sflash_init(&bus->chipco); |
902d9e0f4 ssb: check for fl... |
231 232 |
break; case SSB_CHIPCO_FLASHT_PARA: |
b8b6069cf ssb: Remove home-... |
233 234 |
dev_dbg(mcore->dev->dev, "Found parallel flash "); |
f1ab57e3a ssb: trivial: use... |
235 236 237 |
pflash->present = true; pflash->window = SSB_FLASH2; pflash->window_size = SSB_FLASH2_SZ; |
61e115a56 [SSB]: add Sonics... |
238 239 |
if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) & SSB_CHIPCO_CFG_DS16) == 0) |
f1ab57e3a ssb: trivial: use... |
240 |
pflash->buswidth = 1; |
902d9e0f4 ssb: check for fl... |
241 |
else |
f1ab57e3a ssb: trivial: use... |
242 |
pflash->buswidth = 2; |
902d9e0f4 ssb: check for fl... |
243 |
break; |
61e115a56 [SSB]: add Sonics... |
244 |
} |
c7a4a9e38 ssb: register pla... |
245 246 |
ssb_pflash: |
21400f252 MIPS: BCM47XX: Ma... |
247 248 249 250 251 252 253 254 |
if (sflash->present) { #ifdef CONFIG_BCM47XX bcm47xx_nvram_init_from_mem(sflash->window, sflash->size); #endif } else if (pflash->present) { #ifdef CONFIG_BCM47XX bcm47xx_nvram_init_from_mem(pflash->window, pflash->window_size); #endif |
c7a4a9e38 ssb: register pla... |
255 256 257 258 |
ssb_pflash_data.width = pflash->buswidth; ssb_pflash_resource.start = pflash->window; ssb_pflash_resource.end = pflash->window + pflash->window_size; } |
61e115a56 [SSB]: add Sonics... |
259 260 261 262 263 264 |
} u32 ssb_cpu_clock(struct ssb_mipscore *mcore) { struct ssb_bus *bus = mcore->dev->bus; u32 pll_type, n, m, rate = 0; |
d486a5b49 ssb: add support ... |
265 266 |
if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) return ssb_pmu_get_cpu_clock(&bus->chipco); |
0362063b7 ssb: extif: fix c... |
267 |
if (ssb_extif_available(&bus->extif)) { |
61e115a56 [SSB]: add Sonics... |
268 |
ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); |
0362063b7 ssb: extif: fix c... |
269 |
} else if (ssb_chipco_available(&bus->chipco)) { |
61e115a56 [SSB]: add Sonics... |
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); } else return 0; if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) { rate = 200000000; } else { rate = ssb_calc_clock_rate(pll_type, n, m); } if (pll_type == SSB_PLLTYPE_6) { rate *= 2; } return rate; } void ssb_mipscore_init(struct ssb_mipscore *mcore) { |
7007d00ca [PATCH] ssb: Fix ... |
289 |
struct ssb_bus *bus; |
61e115a56 [SSB]: add Sonics... |
290 291 292 293 294 295 |
struct ssb_device *dev; unsigned long hz, ns; unsigned int irq, i; if (!mcore->dev) return; /* We don't have a MIPS core */ |
b8b6069cf ssb: Remove home-... |
296 297 |
dev_dbg(mcore->dev->dev, "Initializing MIPS core... "); |
61e115a56 [SSB]: add Sonics... |
298 |
|
7007d00ca [PATCH] ssb: Fix ... |
299 |
bus = mcore->dev->bus; |
61e115a56 [SSB]: add Sonics... |
300 301 302 303 |
hz = ssb_clockspeed(bus); if (!hz) hz = 100000000; ns = 1000000000 / hz; |
0362063b7 ssb: extif: fix c... |
304 |
if (ssb_extif_available(&bus->extif)) |
61e115a56 [SSB]: add Sonics... |
305 |
ssb_extif_timing_init(&bus->extif, ns); |
0362063b7 ssb: extif: fix c... |
306 |
else if (ssb_chipco_available(&bus->chipco)) |
61e115a56 [SSB]: add Sonics... |
307 308 309 310 |
ssb_chipco_timing_init(&bus->chipco, ns); /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ for (irq = 2, i = 0; i < bus->nr_devices; i++) { |
ea4bbfd00 MIPS: BC47xx: Fix... |
311 |
int mips_irq; |
61e115a56 [SSB]: add Sonics... |
312 |
dev = &(bus->devices[i]); |
ea4bbfd00 MIPS: BC47xx: Fix... |
313 314 315 316 317 318 319 |
mips_irq = ssb_mips_irq(dev); if (mips_irq > 4) dev->irq = 0; else dev->irq = mips_irq + 2; if (dev->irq > 5) continue; |
61e115a56 [SSB]: add Sonics... |
320 321 322 323 324 325 |
switch (dev->id.coreid) { case SSB_DEV_USB11_HOST: /* shouldn't need a separate irq line for non-4710, most of them have a proper * external usb controller on the pci */ if ((bus->chip_id == 0x4710) && (irq <= 4)) { set_irq(dev, irq++); |
61e115a56 [SSB]: add Sonics... |
326 |
} |
ea4bbfd00 MIPS: BC47xx: Fix... |
327 |
break; |
61e115a56 [SSB]: add Sonics... |
328 329 |
case SSB_DEV_PCI: case SSB_DEV_ETHERNET: |
aab547ce0 ssb: Add Gigabit ... |
330 |
case SSB_DEV_ETHERNET_GBIT: |
61e115a56 [SSB]: add Sonics... |
331 332 333 334 335 336 337 |
case SSB_DEV_80211: case SSB_DEV_USB20_HOST: /* These devices get their own IRQ line if available, the rest goes on IRQ0 */ if (irq <= 4) { set_irq(dev, irq++); break; } |
83e34f03e ssb: fix interrup... |
338 339 340 341 |
/* fallthrough */ case SSB_DEV_EXTIF: set_irq(dev, 0); break; |
61e115a56 [SSB]: add Sonics... |
342 343 |
} } |
b8b6069cf ssb: Remove home-... |
344 345 |
dev_dbg(mcore->dev->dev, "after irq reconfiguration "); |
ea4bbfd00 MIPS: BC47xx: Fix... |
346 |
dump_irq(bus); |
61e115a56 [SSB]: add Sonics... |
347 348 349 350 |
ssb_mips_serial_init(mcore); ssb_mips_flash_detect(mcore); } |