]> Pileus Git - ~andy/linux/blobdiff - drivers/bcma/host_pci.c
Merge branch 'wire-accept4' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl...
[~andy/linux] / drivers / bcma / host_pci.c
index 1b51d8b7ac8024698bc9b053322a2b82ddbe47ab..443b83a2fd7aa012c1c6835137e2642a79499b41 100644 (file)
@@ -21,48 +21,58 @@ static void bcma_host_pci_switch_core(struct bcma_device *core)
        pr_debug("Switched to core: 0x%X\n", core->id.id);
 }
 
-static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
+/* Provides access to the requested core. Returns base offset that has to be
+ * used. It makes use of fixed windows when possible. */
+static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core)
 {
+       switch (core->id.id) {
+       case BCMA_CORE_CHIPCOMMON:
+               return 3 * BCMA_CORE_SIZE;
+       case BCMA_CORE_PCIE:
+               return 2 * BCMA_CORE_SIZE;
+       }
+
        if (core->bus->mapped_core != core)
                bcma_host_pci_switch_core(core);
+       return 0;
+}
+
+static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
+{
+       offset += bcma_host_pci_provide_access_to_core(core);
        return ioread8(core->bus->mmio + offset);
 }
 
 static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
 {
-       if (core->bus->mapped_core != core)
-               bcma_host_pci_switch_core(core);
+       offset += bcma_host_pci_provide_access_to_core(core);
        return ioread16(core->bus->mmio + offset);
 }
 
 static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
 {
-       if (core->bus->mapped_core != core)
-               bcma_host_pci_switch_core(core);
+       offset += bcma_host_pci_provide_access_to_core(core);
        return ioread32(core->bus->mmio + offset);
 }
 
 static void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
                                 u8 value)
 {
-       if (core->bus->mapped_core != core)
-               bcma_host_pci_switch_core(core);
+       offset += bcma_host_pci_provide_access_to_core(core);
        iowrite8(value, core->bus->mmio + offset);
 }
 
 static void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
                                 u16 value)
 {
-       if (core->bus->mapped_core != core)
-               bcma_host_pci_switch_core(core);
+       offset += bcma_host_pci_provide_access_to_core(core);
        iowrite16(value, core->bus->mmio + offset);
 }
 
 static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
                                 u32 value)
 {
-       if (core->bus->mapped_core != core)
-               bcma_host_pci_switch_core(core);
+       offset += bcma_host_pci_provide_access_to_core(core);
        iowrite32(value, core->bus->mmio + offset);
 }
 
@@ -224,6 +234,41 @@ static void bcma_host_pci_remove(struct pci_dev *dev)
        pci_set_drvdata(dev, NULL);
 }
 
+#ifdef CONFIG_PM
+static int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+       /* Host specific */
+       pci_save_state(dev);
+       pci_disable_device(dev);
+       pci_set_power_state(dev, pci_choose_state(dev, state));
+
+       return 0;
+}
+
+static int bcma_host_pci_resume(struct pci_dev *dev)
+{
+       struct bcma_bus *bus = pci_get_drvdata(dev);
+       int err;
+
+       /* Host specific */
+       pci_set_power_state(dev, 0);
+       err = pci_enable_device(dev);
+       if (err)
+               return err;
+       pci_restore_state(dev);
+
+       /* Bus specific */
+       err = bcma_bus_resume(bus);
+       if (err)
+               return err;
+
+       return 0;
+}
+#else /* CONFIG_PM */
+# define bcma_host_pci_suspend NULL
+# define bcma_host_pci_resume  NULL
+#endif /* CONFIG_PM */
+
 static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
@@ -239,6 +284,8 @@ static struct pci_driver bcma_pci_bridge_driver = {
        .id_table = bcma_pci_bridge_tbl,
        .probe = bcma_host_pci_probe,
        .remove = bcma_host_pci_remove,
+       .suspend = bcma_host_pci_suspend,
+       .resume = bcma_host_pci_resume,
 };
 
 int __init bcma_host_pci_init(void)