Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bcma: add mips driver

This adds a mips driver to bcma. This is only found on embedded
devices. For now the driver just initializes the irqs used on this
system.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Hauke Mehrtens and committed by
John W. Linville
21e0534a ecd177c2

+333
+9
drivers/bcma/Kconfig
··· 35 35 36 36 config BCMA_HOST_SOC 37 37 bool 38 + depends on BCMA_DRIVER_MIPS 39 + 40 + config BCMA_DRIVER_MIPS 41 + bool "BCMA Broadcom MIPS core driver" 38 42 depends on BCMA && MIPS 43 + help 44 + Driver for the Broadcom MIPS core attached to Broadcom specific 45 + Advanced Microcontroller Bus. 46 + 47 + If unsure, say N 39 48 40 49 config BCMA_DEBUG 41 50 bool "BCMA debugging"
+1
drivers/bcma/Makefile
··· 2 2 bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o 3 3 bcma-y += driver_pci.o 4 4 bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o 5 + bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o 5 6 bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o 6 7 bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o 7 8 obj-$(CONFIG_BCMA) += bcma.o
+243
drivers/bcma/driver_mips.c
··· 1 + /* 2 + * Broadcom specific AMBA 3 + * Broadcom MIPS32 74K core driver 4 + * 5 + * Copyright 2009, Broadcom Corporation 6 + * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> 7 + * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com> 8 + * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de> 9 + * 10 + * Licensed under the GNU/GPL. See COPYING for details. 11 + */ 12 + 13 + #include "bcma_private.h" 14 + 15 + #include <linux/bcma/bcma.h> 16 + 17 + #include <linux/serial.h> 18 + #include <linux/serial_core.h> 19 + #include <linux/serial_reg.h> 20 + #include <linux/time.h> 21 + 22 + /* The 47162a0 hangs when reading MIPS DMP registers registers */ 23 + static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) 24 + { 25 + return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 && 26 + dev->id.id == BCMA_CORE_MIPS_74K; 27 + } 28 + 29 + /* The 5357b0 hangs when reading USB20H DMP registers */ 30 + static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev) 31 + { 32 + return (dev->bus->chipinfo.id == 0x5357 || 33 + dev->bus->chipinfo.id == 0x4749) && 34 + dev->bus->chipinfo.pkg == 11 && 35 + dev->id.id == BCMA_CORE_USB20_HOST; 36 + } 37 + 38 + static inline u32 mips_read32(struct bcma_drv_mips *mcore, 39 + u16 offset) 40 + { 41 + return bcma_read32(mcore->core, offset); 42 + } 43 + 44 + static inline void mips_write32(struct bcma_drv_mips *mcore, 45 + u16 offset, 46 + u32 value) 47 + { 48 + bcma_write32(mcore->core, offset, value); 49 + } 50 + 51 + static const u32 ipsflag_irq_mask[] = { 52 + 0, 53 + BCMA_MIPS_IPSFLAG_IRQ1, 54 + BCMA_MIPS_IPSFLAG_IRQ2, 55 + BCMA_MIPS_IPSFLAG_IRQ3, 56 + BCMA_MIPS_IPSFLAG_IRQ4, 57 + }; 58 + 59 + static const u32 ipsflag_irq_shift[] = { 60 + 0, 61 + BCMA_MIPS_IPSFLAG_IRQ1_SHIFT, 62 + BCMA_MIPS_IPSFLAG_IRQ2_SHIFT, 63 + BCMA_MIPS_IPSFLAG_IRQ3_SHIFT, 64 + BCMA_MIPS_IPSFLAG_IRQ4_SHIFT, 65 + }; 66 + 67 + static u32 bcma_core_mips_irqflag(struct bcma_device *dev) 68 + { 69 + u32 flag; 70 + 71 + if (bcma_core_mips_bcm47162a0_quirk(dev)) 72 + return dev->core_index; 73 + if (bcma_core_mips_bcm5357b0_quirk(dev)) 74 + return dev->core_index; 75 + flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30); 76 + 77 + return flag & 0x1F; 78 + } 79 + 80 + /* Get the MIPS IRQ assignment for a specified device. 81 + * If unassigned, 0 is returned. 82 + */ 83 + unsigned int bcma_core_mips_irq(struct bcma_device *dev) 84 + { 85 + struct bcma_device *mdev = dev->bus->drv_mips.core; 86 + u32 irqflag; 87 + unsigned int irq; 88 + 89 + irqflag = bcma_core_mips_irqflag(dev); 90 + 91 + for (irq = 1; irq <= 4; irq++) 92 + if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) & 93 + (1 << irqflag)) 94 + return irq; 95 + 96 + return 0; 97 + } 98 + EXPORT_SYMBOL(bcma_core_mips_irq); 99 + 100 + static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) 101 + { 102 + unsigned int oldirq = bcma_core_mips_irq(dev); 103 + struct bcma_bus *bus = dev->bus; 104 + struct bcma_device *mdev = bus->drv_mips.core; 105 + u32 irqflag; 106 + 107 + irqflag = bcma_core_mips_irqflag(dev); 108 + BUG_ON(oldirq == 6); 109 + 110 + dev->irq = irq + 2; 111 + 112 + /* clear the old irq */ 113 + if (oldirq == 0) 114 + bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0), 115 + bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & 116 + ~(1 << irqflag)); 117 + else 118 + bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0); 119 + 120 + /* assign the new one */ 121 + if (irq == 0) { 122 + bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0), 123 + bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) | 124 + (1 << irqflag)); 125 + } else { 126 + u32 oldirqflag = bcma_read32(mdev, 127 + BCMA_MIPS_MIPS74K_INTMASK(irq)); 128 + if (oldirqflag) { 129 + struct bcma_device *core; 130 + 131 + /* backplane irq line is in use, find out who uses 132 + * it and set user to irq 0 133 + */ 134 + list_for_each_entry_reverse(core, &bus->cores, list) { 135 + if ((1 << bcma_core_mips_irqflag(core)) == 136 + oldirqflag) { 137 + bcma_core_mips_set_irq(core, 0); 138 + break; 139 + } 140 + } 141 + } 142 + bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 143 + 1 << irqflag); 144 + } 145 + 146 + pr_info("set_irq: core 0x%04x, irq %d => %d\n", 147 + dev->id.id, oldirq + 2, irq + 2); 148 + } 149 + 150 + static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq) 151 + { 152 + int i; 153 + 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); 155 + for (i = 0; i <= 6; i++) 156 + printk(" %s%s", irq_name[i], i == irq ? "*" : " "); 157 + printk("\n"); 158 + } 159 + 160 + static void bcma_core_mips_dump_irq(struct bcma_bus *bus) 161 + { 162 + struct bcma_device *core; 163 + 164 + list_for_each_entry_reverse(core, &bus->cores, list) { 165 + bcma_core_mips_print_irq(core, bcma_core_mips_irq(core)); 166 + } 167 + } 168 + 169 + static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) 170 + { 171 + struct bcma_bus *bus = mcore->core->bus; 172 + 173 + switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) { 174 + case BCMA_CC_FLASHT_STSER: 175 + case BCMA_CC_FLASHT_ATSER: 176 + pr_err("Serial flash not supported.\n"); 177 + break; 178 + case BCMA_CC_FLASHT_PARA: 179 + pr_info("found parallel flash.\n"); 180 + bus->drv_cc.pflash.window = 0x1c000000; 181 + bus->drv_cc.pflash.window_size = 0x02000000; 182 + 183 + if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) & 184 + BCMA_CC_FLASH_CFG_DS) == 0) 185 + bus->drv_cc.pflash.buswidth = 1; 186 + else 187 + bus->drv_cc.pflash.buswidth = 2; 188 + break; 189 + default: 190 + pr_err("flash not supported.\n"); 191 + } 192 + } 193 + 194 + void bcma_core_mips_init(struct bcma_drv_mips *mcore) 195 + { 196 + struct bcma_bus *bus; 197 + struct bcma_device *core; 198 + bus = mcore->core->bus; 199 + 200 + pr_info("Initializing MIPS core...\n"); 201 + 202 + if (!mcore->setup_done) 203 + mcore->assigned_irqs = 1; 204 + 205 + /* Assign IRQs to all cores on the bus */ 206 + list_for_each_entry_reverse(core, &bus->cores, list) { 207 + int mips_irq; 208 + if (core->irq) 209 + continue; 210 + 211 + mips_irq = bcma_core_mips_irq(core); 212 + if (mips_irq > 4) 213 + core->irq = 0; 214 + else 215 + core->irq = mips_irq + 2; 216 + if (core->irq > 5) 217 + continue; 218 + switch (core->id.id) { 219 + case BCMA_CORE_PCI: 220 + case BCMA_CORE_PCIE: 221 + case BCMA_CORE_ETHERNET: 222 + case BCMA_CORE_ETHERNET_GBIT: 223 + case BCMA_CORE_MAC_GBIT: 224 + case BCMA_CORE_80211: 225 + case BCMA_CORE_USB20_HOST: 226 + /* These devices get their own IRQ line if available, 227 + * the rest goes on IRQ0 228 + */ 229 + if (mcore->assigned_irqs <= 4) 230 + bcma_core_mips_set_irq(core, 231 + mcore->assigned_irqs++); 232 + break; 233 + } 234 + } 235 + pr_info("IRQ reconfiguration done\n"); 236 + bcma_core_mips_dump_irq(bus); 237 + 238 + if (mcore->setup_done) 239 + return; 240 + 241 + bcma_core_mips_flash_detect(mcore); 242 + mcore->setup_done = true; 243 + }
+15
drivers/bcma/main.c
··· 84 84 case BCMA_CORE_CHIPCOMMON: 85 85 case BCMA_CORE_PCI: 86 86 case BCMA_CORE_PCIE: 87 + case BCMA_CORE_MIPS_74K: 87 88 continue; 88 89 } 89 90 ··· 146 145 if (core) { 147 146 bus->drv_cc.core = core; 148 147 bcma_core_chipcommon_init(&bus->drv_cc); 148 + } 149 + 150 + /* Init MIPS core */ 151 + core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); 152 + if (core) { 153 + bus->drv_mips.core = core; 154 + bcma_core_mips_init(&bus->drv_mips); 149 155 } 150 156 151 157 /* Init PCIE core */ ··· 223 215 if (core) { 224 216 bus->drv_cc.core = core; 225 217 bcma_core_chipcommon_init(&bus->drv_cc); 218 + } 219 + 220 + /* Init MIPS core */ 221 + core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); 222 + if (core) { 223 + bus->drv_mips.core = core; 224 + bcma_core_mips_init(&bus->drv_mips); 226 225 } 227 226 228 227 pr_info("Early bus registered\n");
+3
include/linux/bcma/bcma.h
··· 6 6 7 7 #include <linux/bcma/bcma_driver_chipcommon.h> 8 8 #include <linux/bcma/bcma_driver_pci.h> 9 + #include <linux/bcma/bcma_driver_mips.h> 9 10 #include <linux/ssb/ssb.h> /* SPROM sharing */ 10 11 11 12 #include "bcma_regs.h" ··· 131 130 132 131 struct device dev; 133 132 struct device *dma_dev; 133 + 134 134 unsigned int irq; 135 135 bool dev_registered; 136 136 ··· 199 197 200 198 struct bcma_drv_cc drv_cc; 201 199 struct bcma_drv_pci drv_pci; 200 + struct bcma_drv_mips drv_mips; 202 201 203 202 /* We decided to share SPROM struct with SSB as long as we do not need 204 203 * any hacks for BCMA. This simplifies drivers code. */
+13
include/linux/bcma/bcma_driver_chipcommon.h
··· 24 24 #define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */ 25 25 #define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */ 26 26 #define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */ 27 + #define BCMA_CC_FLASHT_NFLASH 0x00000200 27 28 #define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */ 28 29 #define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */ 29 30 #define BCMA_PLLTYPE_NONE 0x00000000 ··· 179 178 #define BCMA_CC_PROG_CFG 0x0120 180 179 #define BCMA_CC_PROG_WAITCNT 0x0124 181 180 #define BCMA_CC_FLASH_CFG 0x0128 181 + #define BCMA_CC_FLASH_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ 182 182 #define BCMA_CC_FLASH_WAITCNT 0x012C 183 183 /* 0x1E0 is defined as shared BCMA_CLKCTLST */ 184 184 #define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ ··· 249 247 u32 crystalfreq; /* The active crystal frequency (in kHz) */ 250 248 }; 251 249 250 + #ifdef CONFIG_BCMA_DRIVER_MIPS 251 + struct bcma_pflash { 252 + u8 buswidth; 253 + u32 window; 254 + u32 window_size; 255 + }; 256 + #endif /* CONFIG_BCMA_DRIVER_MIPS */ 257 + 252 258 struct bcma_drv_cc { 253 259 struct bcma_device *core; 254 260 u32 status; ··· 266 256 /* Fast Powerup Delay constant */ 267 257 u16 fast_pwrup_delay; 268 258 struct bcma_chipcommon_pmu pmu; 259 + #ifdef CONFIG_BCMA_DRIVER_MIPS 260 + struct bcma_pflash pflash; 261 + #endif /* CONFIG_BCMA_DRIVER_MIPS */ 269 262 }; 270 263 271 264 /* Register access */
+49
include/linux/bcma/bcma_driver_mips.h
··· 1 + #ifndef LINUX_BCMA_DRIVER_MIPS_H_ 2 + #define LINUX_BCMA_DRIVER_MIPS_H_ 3 + 4 + #define BCMA_MIPS_IPSFLAG 0x0F08 5 + /* which sbflags get routed to mips interrupt 1 */ 6 + #define BCMA_MIPS_IPSFLAG_IRQ1 0x0000003F 7 + #define BCMA_MIPS_IPSFLAG_IRQ1_SHIFT 0 8 + /* which sbflags get routed to mips interrupt 2 */ 9 + #define BCMA_MIPS_IPSFLAG_IRQ2 0x00003F00 10 + #define BCMA_MIPS_IPSFLAG_IRQ2_SHIFT 8 11 + /* which sbflags get routed to mips interrupt 3 */ 12 + #define BCMA_MIPS_IPSFLAG_IRQ3 0x003F0000 13 + #define BCMA_MIPS_IPSFLAG_IRQ3_SHIFT 16 14 + /* which sbflags get routed to mips interrupt 4 */ 15 + #define BCMA_MIPS_IPSFLAG_IRQ4 0x3F000000 16 + #define BCMA_MIPS_IPSFLAG_IRQ4_SHIFT 24 17 + 18 + /* MIPS 74K core registers */ 19 + #define BCMA_MIPS_MIPS74K_CORECTL 0x0000 20 + #define BCMA_MIPS_MIPS74K_EXCEPTBASE 0x0004 21 + #define BCMA_MIPS_MIPS74K_BIST 0x000C 22 + #define BCMA_MIPS_MIPS74K_INTMASK_INT0 0x0014 23 + #define BCMA_MIPS_MIPS74K_INTMASK(int) \ 24 + ((int) * 4 + BCMA_MIPS_MIPS74K_INTMASK_INT0) 25 + #define BCMA_MIPS_MIPS74K_NMIMASK 0x002C 26 + #define BCMA_MIPS_MIPS74K_GPIOSEL 0x0040 27 + #define BCMA_MIPS_MIPS74K_GPIOOUT 0x0044 28 + #define BCMA_MIPS_MIPS74K_GPIOEN 0x0048 29 + #define BCMA_MIPS_MIPS74K_CLKCTLST 0x01E0 30 + 31 + #define BCMA_MIPS_OOBSELOUTA30 0x100 32 + 33 + struct bcma_device; 34 + 35 + struct bcma_drv_mips { 36 + struct bcma_device *core; 37 + u8 setup_done:1; 38 + unsigned int assigned_irqs; 39 + }; 40 + 41 + #ifdef CONFIG_BCMA_DRIVER_MIPS 42 + extern void bcma_core_mips_init(struct bcma_drv_mips *mcore); 43 + #else 44 + static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { } 45 + #endif 46 + 47 + extern unsigned int bcma_core_mips_irq(struct bcma_device *dev); 48 + 49 + #endif /* LINUX_BCMA_DRIVER_MIPS_H_ */