diff options
Diffstat (limited to 'drivers/bcma/driver_mips.c')
-rw-r--r-- | drivers/bcma/driver_mips.c | 157 |
1 files changed, 112 insertions, 45 deletions
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c index 792daad28cbc..9fe86ee16c66 100644 --- a/drivers/bcma/driver_mips.c +++ b/drivers/bcma/driver_mips.c | |||
@@ -74,28 +74,41 @@ static u32 bcma_core_mips_irqflag(struct bcma_device *dev) | |||
74 | return dev->core_index; | 74 | return dev->core_index; |
75 | flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30); | 75 | flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30); |
76 | 76 | ||
77 | return flag & 0x1F; | 77 | if (flag) |
78 | return flag & 0x1F; | ||
79 | else | ||
80 | return 0x3f; | ||
78 | } | 81 | } |
79 | 82 | ||
80 | /* Get the MIPS IRQ assignment for a specified device. | 83 | /* Get the MIPS IRQ assignment for a specified device. |
81 | * If unassigned, 0 is returned. | 84 | * If unassigned, 0 is returned. |
85 | * If disabled, 5 is returned. | ||
86 | * If not supported, 6 is returned. | ||
82 | */ | 87 | */ |
83 | unsigned int bcma_core_mips_irq(struct bcma_device *dev) | 88 | static unsigned int bcma_core_mips_irq(struct bcma_device *dev) |
84 | { | 89 | { |
85 | struct bcma_device *mdev = dev->bus->drv_mips.core; | 90 | struct bcma_device *mdev = dev->bus->drv_mips.core; |
86 | u32 irqflag; | 91 | u32 irqflag; |
87 | unsigned int irq; | 92 | unsigned int irq; |
88 | 93 | ||
89 | irqflag = bcma_core_mips_irqflag(dev); | 94 | irqflag = bcma_core_mips_irqflag(dev); |
95 | if (irqflag == 0x3f) | ||
96 | return 6; | ||
90 | 97 | ||
91 | for (irq = 1; irq <= 4; irq++) | 98 | for (irq = 0; irq <= 4; irq++) |
92 | if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) & | 99 | if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) & |
93 | (1 << irqflag)) | 100 | (1 << irqflag)) |
94 | return irq; | 101 | return irq; |
95 | 102 | ||
96 | return 0; | 103 | return 5; |
104 | } | ||
105 | |||
106 | unsigned int bcma_core_irq(struct bcma_device *dev) | ||
107 | { | ||
108 | unsigned int mips_irq = bcma_core_mips_irq(dev); | ||
109 | return mips_irq <= 4 ? mips_irq + 2 : 0; | ||
97 | } | 110 | } |
98 | EXPORT_SYMBOL(bcma_core_mips_irq); | 111 | EXPORT_SYMBOL(bcma_core_irq); |
99 | 112 | ||
100 | static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) | 113 | static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) |
101 | { | 114 | { |
@@ -114,7 +127,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) | |||
114 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0), | 127 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0), |
115 | bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & | 128 | bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & |
116 | ~(1 << irqflag)); | 129 | ~(1 << irqflag)); |
117 | else | 130 | else if (oldirq != 5) |
118 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); | 131 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); |
119 | 132 | ||
120 | /* assign the new one */ | 133 | /* assign the new one */ |
@@ -123,9 +136,9 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) | |||
123 | bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) | | 136 | bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) | |
124 | (1 << irqflag)); | 137 | (1 << irqflag)); |
125 | } else { | 138 | } else { |
126 | u32 oldirqflag = bcma_read32(mdev, | 139 | u32 irqinitmask = bcma_read32(mdev, |
127 | BCMA_MIPS_MIPS74K_INTMASK(irq)); | 140 | BCMA_MIPS_MIPS74K_INTMASK(irq)); |
128 | if (oldirqflag) { | 141 | if (irqinitmask) { |
129 | struct bcma_device *core; | 142 | struct bcma_device *core; |
130 | 143 | ||
131 | /* backplane irq line is in use, find out who uses | 144 | /* backplane irq line is in use, find out who uses |
@@ -133,7 +146,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) | |||
133 | */ | 146 | */ |
134 | list_for_each_entry(core, &bus->cores, list) { | 147 | list_for_each_entry(core, &bus->cores, list) { |
135 | if ((1 << bcma_core_mips_irqflag(core)) == | 148 | if ((1 << bcma_core_mips_irqflag(core)) == |
136 | oldirqflag) { | 149 | irqinitmask) { |
137 | bcma_core_mips_set_irq(core, 0); | 150 | bcma_core_mips_set_irq(core, 0); |
138 | break; | 151 | break; |
139 | } | 152 | } |
@@ -143,15 +156,31 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) | |||
143 | 1 << irqflag); | 156 | 1 << irqflag); |
144 | } | 157 | } |
145 | 158 | ||
146 | bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n", | 159 | bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n", |
147 | dev->id.id, oldirq + 2, irq + 2); | 160 | dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2); |
161 | } | ||
162 | |||
163 | static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq, | ||
164 | u16 coreid, u8 unit) | ||
165 | { | ||
166 | struct bcma_device *core; | ||
167 | |||
168 | core = bcma_find_core_unit(bus, coreid, unit); | ||
169 | if (!core) { | ||
170 | bcma_warn(bus, | ||
171 | "Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n", | ||
172 | coreid, unit); | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | bcma_core_mips_set_irq(core, irq); | ||
148 | } | 177 | } |
149 | 178 | ||
150 | static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq) | 179 | static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq) |
151 | { | 180 | { |
152 | int i; | 181 | int i; |
153 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; | 182 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; |
154 | printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id); | 183 | printk(KERN_DEBUG KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id); |
155 | for (i = 0; i <= 6; i++) | 184 | for (i = 0; i <= 6; i++) |
156 | printk(" %s%s", irq_name[i], i == irq ? "*" : " "); | 185 | printk(" %s%s", irq_name[i], i == irq ? "*" : " "); |
157 | printk("\n"); | 186 | printk("\n"); |
@@ -227,6 +256,32 @@ void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) | |||
227 | mcore->early_setup_done = true; | 256 | mcore->early_setup_done = true; |
228 | } | 257 | } |
229 | 258 | ||
259 | static void bcma_fix_i2s_irqflag(struct bcma_bus *bus) | ||
260 | { | ||
261 | struct bcma_device *cpu, *pcie, *i2s; | ||
262 | |||
263 | /* Fixup the interrupts in 4716/4748 for i2s core (2010 Broadcom SDK) | ||
264 | * (IRQ flags > 7 are ignored when setting the interrupt masks) | ||
265 | */ | ||
266 | if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4716 && | ||
267 | bus->chipinfo.id != BCMA_CHIP_ID_BCM4748) | ||
268 | return; | ||
269 | |||
270 | cpu = bcma_find_core(bus, BCMA_CORE_MIPS_74K); | ||
271 | pcie = bcma_find_core(bus, BCMA_CORE_PCIE); | ||
272 | i2s = bcma_find_core(bus, BCMA_CORE_I2S); | ||
273 | if (cpu && pcie && i2s && | ||
274 | bcma_aread32(cpu, BCMA_MIPS_OOBSELINA74) == 0x08060504 && | ||
275 | bcma_aread32(pcie, BCMA_MIPS_OOBSELINA74) == 0x08060504 && | ||
276 | bcma_aread32(i2s, BCMA_MIPS_OOBSELOUTA30) == 0x88) { | ||
277 | bcma_awrite32(cpu, BCMA_MIPS_OOBSELINA74, 0x07060504); | ||
278 | bcma_awrite32(pcie, BCMA_MIPS_OOBSELINA74, 0x07060504); | ||
279 | bcma_awrite32(i2s, BCMA_MIPS_OOBSELOUTA30, 0x87); | ||
280 | bcma_debug(bus, | ||
281 | "Moved i2s interrupt to oob line 7 instead of 8\n"); | ||
282 | } | ||
283 | } | ||
284 | |||
230 | void bcma_core_mips_init(struct bcma_drv_mips *mcore) | 285 | void bcma_core_mips_init(struct bcma_drv_mips *mcore) |
231 | { | 286 | { |
232 | struct bcma_bus *bus; | 287 | struct bcma_bus *bus; |
@@ -236,43 +291,55 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore) | |||
236 | if (mcore->setup_done) | 291 | if (mcore->setup_done) |
237 | return; | 292 | return; |
238 | 293 | ||
239 | bcma_info(bus, "Initializing MIPS core...\n"); | 294 | bcma_debug(bus, "Initializing MIPS core...\n"); |
240 | 295 | ||
241 | bcma_core_mips_early_init(mcore); | 296 | bcma_core_mips_early_init(mcore); |
242 | 297 | ||
243 | mcore->assigned_irqs = 1; | 298 | bcma_fix_i2s_irqflag(bus); |
244 | 299 | ||
245 | /* Assign IRQs to all cores on the bus */ | 300 | switch (bus->chipinfo.id) { |
246 | list_for_each_entry(core, &bus->cores, list) { | 301 | case BCMA_CHIP_ID_BCM4716: |
247 | int mips_irq; | 302 | case BCMA_CHIP_ID_BCM4748: |
248 | if (core->irq) | 303 | bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0); |
249 | continue; | 304 | bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0); |
250 | 305 | bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0); | |
251 | mips_irq = bcma_core_mips_irq(core); | 306 | bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0); |
252 | if (mips_irq > 4) | 307 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0); |
253 | core->irq = 0; | 308 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0); |
254 | else | 309 | break; |
255 | core->irq = mips_irq + 2; | 310 | case BCMA_CHIP_ID_BCM5356: |
256 | if (core->irq > 5) | 311 | case BCMA_CHIP_ID_BCM47162: |
257 | continue; | 312 | case BCMA_CHIP_ID_BCM53572: |
258 | switch (core->id.id) { | 313 | bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0); |
259 | case BCMA_CORE_PCI: | 314 | bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0); |
260 | case BCMA_CORE_PCIE: | 315 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0); |
261 | case BCMA_CORE_ETHERNET: | 316 | break; |
262 | case BCMA_CORE_ETHERNET_GBIT: | 317 | case BCMA_CHIP_ID_BCM5357: |
263 | case BCMA_CORE_MAC_GBIT: | 318 | case BCMA_CHIP_ID_BCM4749: |
264 | case BCMA_CORE_80211: | 319 | bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0); |
265 | case BCMA_CORE_USB20_HOST: | 320 | bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0); |
266 | /* These devices get their own IRQ line if available, | 321 | bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0); |
267 | * the rest goes on IRQ0 | 322 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0); |
268 | */ | 323 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0); |
269 | if (mcore->assigned_irqs <= 4) | 324 | break; |
270 | bcma_core_mips_set_irq(core, | 325 | case BCMA_CHIP_ID_BCM4706: |
271 | mcore->assigned_irqs++); | 326 | bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0); |
272 | break; | 327 | bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT, |
328 | 0); | ||
329 | bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1); | ||
330 | bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0); | ||
331 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON, | ||
332 | 0); | ||
333 | break; | ||
334 | default: | ||
335 | list_for_each_entry(core, &bus->cores, list) { | ||
336 | core->irq = bcma_core_irq(core); | ||
273 | } | 337 | } |
338 | bcma_err(bus, | ||
339 | "Unknown device (0x%x) found, can not configure IRQs\n", | ||
340 | bus->chipinfo.id); | ||
274 | } | 341 | } |
275 | bcma_info(bus, "IRQ reconfiguration done\n"); | 342 | bcma_debug(bus, "IRQ reconfiguration done\n"); |
276 | bcma_core_mips_dump_irq(bus); | 343 | bcma_core_mips_dump_irq(bus); |
277 | 344 | ||
278 | mcore->setup_done = true; | 345 | mcore->setup_done = true; |