0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/pm.h>
0015 #include <linux/pci.h>
0016 #include <linux/export.h>
0017 #include <linux/slab.h>
0018 #include <linux/ssb/ssb.h>
0019
0020
0021 #ifdef CONFIG_PM_SLEEP
0022 static int ssb_pcihost_suspend(struct device *d)
0023 {
0024 struct pci_dev *dev = to_pci_dev(d);
0025 struct ssb_bus *ssb = pci_get_drvdata(dev);
0026 int err;
0027
0028 err = ssb_bus_suspend(ssb);
0029 if (err)
0030 return err;
0031 pci_save_state(dev);
0032 pci_disable_device(dev);
0033
0034
0035
0036 device_set_wakeup_enable(d, d->power.wakeup_path);
0037
0038 pci_prepare_to_sleep(dev);
0039
0040 return 0;
0041 }
0042
0043 static int ssb_pcihost_resume(struct device *d)
0044 {
0045 struct pci_dev *dev = to_pci_dev(d);
0046 struct ssb_bus *ssb = pci_get_drvdata(dev);
0047 int err;
0048
0049 pci_back_from_sleep(dev);
0050 err = pci_enable_device(dev);
0051 if (err)
0052 return err;
0053 pci_restore_state(dev);
0054 err = ssb_bus_resume(ssb);
0055 if (err)
0056 return err;
0057
0058 return 0;
0059 }
0060
0061 static const struct dev_pm_ops ssb_pcihost_pm_ops = {
0062 SET_SYSTEM_SLEEP_PM_OPS(ssb_pcihost_suspend, ssb_pcihost_resume)
0063 };
0064
0065 #endif
0066
0067 static int ssb_pcihost_probe(struct pci_dev *dev,
0068 const struct pci_device_id *id)
0069 {
0070 struct ssb_bus *ssb;
0071 int err = -ENOMEM;
0072 u32 val;
0073
0074 ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
0075 if (!ssb)
0076 goto out;
0077 err = pci_enable_device(dev);
0078 if (err)
0079 goto err_kfree_ssb;
0080 err = pci_request_regions(dev, dev_driver_string(&dev->dev));
0081 if (err)
0082 goto err_pci_disable;
0083 pci_set_master(dev);
0084
0085
0086
0087 pci_read_config_dword(dev, 0x40, &val);
0088 if ((val & 0x0000ff00) != 0)
0089 pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
0090
0091 err = ssb_bus_pcibus_register(ssb, dev);
0092 if (err)
0093 goto err_pci_release_regions;
0094
0095 pci_set_drvdata(dev, ssb);
0096
0097 out:
0098 return err;
0099
0100 err_pci_release_regions:
0101 pci_release_regions(dev);
0102 err_pci_disable:
0103 pci_disable_device(dev);
0104 err_kfree_ssb:
0105 kfree(ssb);
0106 return err;
0107 }
0108
0109 static void ssb_pcihost_remove(struct pci_dev *dev)
0110 {
0111 struct ssb_bus *ssb = pci_get_drvdata(dev);
0112
0113 ssb_bus_unregister(ssb);
0114 pci_release_regions(dev);
0115 pci_disable_device(dev);
0116 kfree(ssb);
0117 pci_set_drvdata(dev, NULL);
0118 }
0119
0120 int ssb_pcihost_register(struct pci_driver *driver)
0121 {
0122 driver->probe = ssb_pcihost_probe;
0123 driver->remove = ssb_pcihost_remove;
0124 #ifdef CONFIG_PM_SLEEP
0125 driver->driver.pm = &ssb_pcihost_pm_ops;
0126 #endif
0127
0128 return pci_register_driver(driver);
0129 }
0130 EXPORT_SYMBOL(ssb_pcihost_register);