0001
0002
0003
0004
0005
0006
0007
0008 #include "bcma_private.h"
0009 #include <linux/slab.h>
0010 #include <linux/bcma/bcma.h>
0011 #include <linux/pci.h>
0012 #include <linux/module.h>
0013
0014 static void bcma_host_pci_switch_core(struct bcma_device *core)
0015 {
0016 int win2 = core->bus->host_is_pcie2 ?
0017 BCMA_PCIE2_BAR0_WIN2 : BCMA_PCI_BAR0_WIN2;
0018
0019 pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN,
0020 core->addr);
0021 pci_write_config_dword(core->bus->host_pci, win2, core->wrap);
0022 core->bus->mapped_core = core;
0023 bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id);
0024 }
0025
0026
0027
0028 static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core)
0029 {
0030 switch (core->id.id) {
0031 case BCMA_CORE_CHIPCOMMON:
0032 return 3 * BCMA_CORE_SIZE;
0033 case BCMA_CORE_PCIE:
0034 return 2 * BCMA_CORE_SIZE;
0035 }
0036
0037 if (core->bus->mapped_core != core)
0038 bcma_host_pci_switch_core(core);
0039 return 0;
0040 }
0041
0042 static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
0043 {
0044 offset += bcma_host_pci_provide_access_to_core(core);
0045 return ioread8(core->bus->mmio + offset);
0046 }
0047
0048 static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
0049 {
0050 offset += bcma_host_pci_provide_access_to_core(core);
0051 return ioread16(core->bus->mmio + offset);
0052 }
0053
0054 static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
0055 {
0056 offset += bcma_host_pci_provide_access_to_core(core);
0057 return ioread32(core->bus->mmio + offset);
0058 }
0059
0060 static void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
0061 u8 value)
0062 {
0063 offset += bcma_host_pci_provide_access_to_core(core);
0064 iowrite8(value, core->bus->mmio + offset);
0065 }
0066
0067 static void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
0068 u16 value)
0069 {
0070 offset += bcma_host_pci_provide_access_to_core(core);
0071 iowrite16(value, core->bus->mmio + offset);
0072 }
0073
0074 static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
0075 u32 value)
0076 {
0077 offset += bcma_host_pci_provide_access_to_core(core);
0078 iowrite32(value, core->bus->mmio + offset);
0079 }
0080
0081 #ifdef CONFIG_BCMA_BLOCKIO
0082 static void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
0083 size_t count, u16 offset, u8 reg_width)
0084 {
0085 void __iomem *addr = core->bus->mmio + offset;
0086 if (core->bus->mapped_core != core)
0087 bcma_host_pci_switch_core(core);
0088 switch (reg_width) {
0089 case sizeof(u8):
0090 ioread8_rep(addr, buffer, count);
0091 break;
0092 case sizeof(u16):
0093 WARN_ON(count & 1);
0094 ioread16_rep(addr, buffer, count >> 1);
0095 break;
0096 case sizeof(u32):
0097 WARN_ON(count & 3);
0098 ioread32_rep(addr, buffer, count >> 2);
0099 break;
0100 default:
0101 WARN_ON(1);
0102 }
0103 }
0104
0105 static void bcma_host_pci_block_write(struct bcma_device *core,
0106 const void *buffer, size_t count,
0107 u16 offset, u8 reg_width)
0108 {
0109 void __iomem *addr = core->bus->mmio + offset;
0110 if (core->bus->mapped_core != core)
0111 bcma_host_pci_switch_core(core);
0112 switch (reg_width) {
0113 case sizeof(u8):
0114 iowrite8_rep(addr, buffer, count);
0115 break;
0116 case sizeof(u16):
0117 WARN_ON(count & 1);
0118 iowrite16_rep(addr, buffer, count >> 1);
0119 break;
0120 case sizeof(u32):
0121 WARN_ON(count & 3);
0122 iowrite32_rep(addr, buffer, count >> 2);
0123 break;
0124 default:
0125 WARN_ON(1);
0126 }
0127 }
0128 #endif
0129
0130 static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
0131 {
0132 if (core->bus->mapped_core != core)
0133 bcma_host_pci_switch_core(core);
0134 return ioread32(core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
0135 }
0136
0137 static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset,
0138 u32 value)
0139 {
0140 if (core->bus->mapped_core != core)
0141 bcma_host_pci_switch_core(core);
0142 iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
0143 }
0144
0145 static const struct bcma_host_ops bcma_host_pci_ops = {
0146 .read8 = bcma_host_pci_read8,
0147 .read16 = bcma_host_pci_read16,
0148 .read32 = bcma_host_pci_read32,
0149 .write8 = bcma_host_pci_write8,
0150 .write16 = bcma_host_pci_write16,
0151 .write32 = bcma_host_pci_write32,
0152 #ifdef CONFIG_BCMA_BLOCKIO
0153 .block_read = bcma_host_pci_block_read,
0154 .block_write = bcma_host_pci_block_write,
0155 #endif
0156 .aread32 = bcma_host_pci_aread32,
0157 .awrite32 = bcma_host_pci_awrite32,
0158 };
0159
0160 static int bcma_host_pci_probe(struct pci_dev *dev,
0161 const struct pci_device_id *id)
0162 {
0163 struct bcma_bus *bus;
0164 int err = -ENOMEM;
0165 u32 val;
0166
0167
0168 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
0169 if (!bus)
0170 goto out;
0171
0172
0173 err = pci_enable_device(dev);
0174 if (err)
0175 goto err_kfree_bus;
0176
0177 err = pci_request_regions(dev, "bcma-pci-bridge");
0178 if (err)
0179 goto err_pci_disable;
0180 pci_set_master(dev);
0181
0182
0183
0184 pci_read_config_dword(dev, 0x40, &val);
0185 if ((val & 0x0000ff00) != 0)
0186 pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
0187
0188
0189 if (!pci_is_pcie(dev)) {
0190 bcma_err(bus, "PCI card detected, they are not supported.\n");
0191 err = -ENXIO;
0192 goto err_pci_release_regions;
0193 }
0194
0195 bus->dev = &dev->dev;
0196
0197
0198 err = -ENOMEM;
0199 bus->mmio = pci_iomap(dev, 0, ~0UL);
0200 if (!bus->mmio)
0201 goto err_pci_release_regions;
0202
0203
0204 bus->host_pci = dev;
0205 bus->hosttype = BCMA_HOSTTYPE_PCI;
0206 bus->ops = &bcma_host_pci_ops;
0207
0208 bus->boardinfo.vendor = bus->host_pci->subsystem_vendor;
0209 bus->boardinfo.type = bus->host_pci->subsystem_device;
0210
0211
0212 bcma_init_bus(bus);
0213
0214
0215 err = bcma_bus_scan(bus);
0216 if (err)
0217 goto err_pci_unmap_mmio;
0218
0219 if (bcma_find_core(bus, BCMA_CORE_PCIE2))
0220 bus->host_is_pcie2 = true;
0221
0222
0223 err = bcma_bus_register(bus);
0224 if (err)
0225 goto err_unregister_cores;
0226
0227 pci_set_drvdata(dev, bus);
0228
0229 out:
0230 return err;
0231
0232 err_unregister_cores:
0233 bcma_unregister_cores(bus);
0234 err_pci_unmap_mmio:
0235 pci_iounmap(dev, bus->mmio);
0236 err_pci_release_regions:
0237 pci_release_regions(dev);
0238 err_pci_disable:
0239 pci_disable_device(dev);
0240 err_kfree_bus:
0241 kfree(bus);
0242 return err;
0243 }
0244
0245 static void bcma_host_pci_remove(struct pci_dev *dev)
0246 {
0247 struct bcma_bus *bus = pci_get_drvdata(dev);
0248
0249 bcma_bus_unregister(bus);
0250 pci_iounmap(dev, bus->mmio);
0251 pci_release_regions(dev);
0252 pci_disable_device(dev);
0253 kfree(bus);
0254 }
0255
0256 #ifdef CONFIG_PM_SLEEP
0257 static int bcma_host_pci_suspend(struct device *dev)
0258 {
0259 struct bcma_bus *bus = dev_get_drvdata(dev);
0260
0261 bus->mapped_core = NULL;
0262
0263 return bcma_bus_suspend(bus);
0264 }
0265
0266 static int bcma_host_pci_resume(struct device *dev)
0267 {
0268 struct bcma_bus *bus = dev_get_drvdata(dev);
0269
0270 return bcma_bus_resume(bus);
0271 }
0272
0273 static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
0274 bcma_host_pci_resume);
0275 #define BCMA_PM_OPS (&bcma_pm_ops)
0276
0277 #else
0278
0279 #define BCMA_PM_OPS NULL
0280
0281 #endif
0282
0283 static const struct pci_device_id bcma_pci_bridge_tbl[] = {
0284 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
0285 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) },
0286 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
0287 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
0288 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
0289 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
0290 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) },
0291 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
0292 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) },
0293 { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0016) },
0294 { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0018) },
0295 { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_FOXCONN, 0xe092) },
0296 { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_HP, 0x804a) },
0297 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) },
0298 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
0299 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
0300 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43b1) },
0301 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
0302 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) },
0303 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43228) },
0304 { 0, },
0305 };
0306 MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
0307
0308 static struct pci_driver bcma_pci_bridge_driver = {
0309 .name = "bcma-pci-bridge",
0310 .id_table = bcma_pci_bridge_tbl,
0311 .probe = bcma_host_pci_probe,
0312 .remove = bcma_host_pci_remove,
0313 .driver.pm = BCMA_PM_OPS,
0314 };
0315
0316 int __init bcma_host_pci_init(void)
0317 {
0318 return pci_register_driver(&bcma_pci_bridge_driver);
0319 }
0320
0321 void __exit bcma_host_pci_exit(void)
0322 {
0323 pci_unregister_driver(&bcma_pci_bridge_driver);
0324 }
0325
0326
0327
0328
0329
0330
0331 void bcma_host_pci_up(struct bcma_bus *bus)
0332 {
0333 if (bus->hosttype != BCMA_HOSTTYPE_PCI)
0334 return;
0335
0336 if (bus->host_is_pcie2)
0337 bcma_core_pcie2_up(&bus->drv_pcie2);
0338 else
0339 bcma_core_pci_up(&bus->drv_pci[0]);
0340 }
0341 EXPORT_SYMBOL_GPL(bcma_host_pci_up);
0342
0343
0344 void bcma_host_pci_down(struct bcma_bus *bus)
0345 {
0346 if (bus->hosttype != BCMA_HOSTTYPE_PCI)
0347 return;
0348
0349 if (!bus->host_is_pcie2)
0350 bcma_core_pci_down(&bus->drv_pci[0]);
0351 }
0352 EXPORT_SYMBOL_GPL(bcma_host_pci_down);
0353
0354
0355 int bcma_host_pci_irq_ctl(struct bcma_bus *bus, struct bcma_device *core,
0356 bool enable)
0357 {
0358 struct pci_dev *pdev;
0359 u32 coremask, tmp;
0360 int err = 0;
0361
0362 if (bus->hosttype != BCMA_HOSTTYPE_PCI) {
0363
0364
0365
0366 goto out;
0367 }
0368
0369 pdev = bus->host_pci;
0370
0371 err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
0372 if (err)
0373 goto out;
0374
0375 coremask = BIT(core->core_index) << 8;
0376 if (enable)
0377 tmp |= coremask;
0378 else
0379 tmp &= ~coremask;
0380
0381 err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
0382
0383 out:
0384 return err;
0385 }
0386 EXPORT_SYMBOL_GPL(bcma_host_pci_irq_ctl);