^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Sonics Silicon Backplane
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * PCI Hostdevice wrapper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Licensed under the GNU/GPL. See COPYING for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/ssb/ssb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static int ssb_pcihost_suspend(struct device *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct pci_dev *dev = to_pci_dev(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct ssb_bus *ssb = pci_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) err = ssb_bus_suspend(ssb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) pci_save_state(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* if there is a wakeup enabled child device on ssb bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) enable pci wakeup posibility. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) device_set_wakeup_enable(d, d->power.wakeup_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) pci_prepare_to_sleep(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int ssb_pcihost_resume(struct device *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct pci_dev *dev = to_pci_dev(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct ssb_bus *ssb = pci_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) pci_back_from_sleep(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) err = pci_enable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) pci_restore_state(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) err = ssb_bus_resume(ssb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static const struct dev_pm_ops ssb_pcihost_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) SET_SYSTEM_SLEEP_PM_OPS(ssb_pcihost_suspend, ssb_pcihost_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #endif /* CONFIG_PM_SLEEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int ssb_pcihost_probe(struct pci_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct ssb_bus *ssb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (!ssb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) err = pci_enable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) goto err_kfree_ssb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) name = dev_name(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (dev->driver && dev->driver->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) name = dev->driver->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) err = pci_request_regions(dev, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) goto err_pci_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) pci_set_master(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* Disable the RETRY_TIMEOUT register (0x41) to keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * PCI Tx retries from interfering with C3 CPU state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) pci_read_config_dword(dev, 0x40, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if ((val & 0x0000ff00) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) err = ssb_bus_pcibus_register(ssb, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) goto err_pci_release_regions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) pci_set_drvdata(dev, ssb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) err_pci_release_regions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) err_pci_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) err_kfree_ssb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) kfree(ssb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static void ssb_pcihost_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct ssb_bus *ssb = pci_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ssb_bus_unregister(ssb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) kfree(ssb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) pci_set_drvdata(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int ssb_pcihost_register(struct pci_driver *driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) driver->probe = ssb_pcihost_probe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) driver->remove = ssb_pcihost_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) driver->driver.pm = &ssb_pcihost_pm_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return pci_register_driver(driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) EXPORT_SYMBOL(ssb_pcihost_register);