host-bridge.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-10-24 GuEe-GUI first version
  9. */
  10. #include <rtthread.h>
  11. #include <drivers/pm.h>
  12. #include <drivers/pci.h>
  13. #ifdef RT_USING_PM
  14. struct host_bridge_pm_status
  15. {
  16. rt_uint8_t mode;
  17. rt_bool_t enable;
  18. };
  19. static const enum rt_pci_power system_pci_pm_mode[] =
  20. {
  21. [PM_SLEEP_MODE_NONE] = RT_PCI_D0,
  22. [PM_SLEEP_MODE_IDLE] = RT_PCI_D3HOT,
  23. [PM_SLEEP_MODE_LIGHT] = RT_PCI_D1,
  24. [PM_SLEEP_MODE_DEEP] = RT_PCI_D1,
  25. [PM_SLEEP_MODE_STANDBY] = RT_PCI_D2,
  26. [PM_SLEEP_MODE_SHUTDOWN] = RT_PCI_D3COLD,
  27. };
  28. static rt_bool_t pci_device_pm_ops(struct rt_pci_device *pdev, void *data)
  29. {
  30. struct host_bridge_pm_status *status = data;
  31. rt_pci_enable_wake(pdev, system_pci_pm_mode[status->mode], status->enable);
  32. /* To find all devices, always return false */
  33. return RT_FALSE;
  34. }
  35. static rt_err_t host_bridge_pm_suspend(const struct rt_device *device, rt_uint8_t mode)
  36. {
  37. struct host_bridge_pm_status status;
  38. struct rt_pci_device *pdev = rt_container_of(device, struct rt_pci_device, parent);
  39. status.mode = mode;
  40. status.enable = RT_FALSE;
  41. rt_pci_enum_device(pdev->bus, pci_device_pm_ops, &status);
  42. return RT_EOK;
  43. }
  44. static void host_bridge_pm_resume(const struct rt_device *device, rt_uint8_t mode)
  45. {
  46. struct host_bridge_pm_status status;
  47. struct rt_pci_device *pdev = rt_container_of(device, struct rt_pci_device, parent);
  48. status.mode = mode;
  49. status.enable = RT_TRUE;
  50. rt_pci_enum_device(pdev->bus, pci_device_pm_ops, &status);
  51. }
  52. static const struct rt_device_pm_ops host_bridge_pm_ops =
  53. {
  54. .suspend = host_bridge_pm_suspend,
  55. .resume = host_bridge_pm_resume,
  56. };
  57. #endif /* RT_USING_PM */
  58. static void host_bridge_free(struct rt_pci_device *pdev)
  59. {
  60. #ifdef RT_USING_PM
  61. rt_pm_device_unregister(&pdev->parent);
  62. #endif
  63. }
  64. static rt_err_t host_bridge_probe(struct rt_pci_device *pdev)
  65. {
  66. rt_err_t err = RT_EOK;
  67. rt_pci_set_master(pdev);
  68. #ifdef RT_USING_PM
  69. rt_pm_device_register(&pdev->parent, &host_bridge_pm_ops);
  70. #endif
  71. return err;
  72. }
  73. static rt_err_t host_bridge_remove(struct rt_pci_device *pdev)
  74. {
  75. host_bridge_free(pdev);
  76. rt_pci_clear_master(pdev);
  77. return RT_EOK;
  78. }
  79. static rt_err_t host_bridge_shutdown(struct rt_pci_device *pdev)
  80. {
  81. host_bridge_free(pdev);
  82. return RT_EOK;
  83. }
  84. static const struct rt_pci_device_id host_bridge_pci_ids[] =
  85. {
  86. /* PCI host bridges */
  87. { RT_PCI_DEVICE_ID(PCI_VENDOR_ID_REDHAT, 0x0008) },
  88. /* Any PCI-Express port */
  89. { RT_PCI_DEVICE_CLASS(PCIS_BRIDGE_PCI_NORMAL, ~0) },
  90. /* PCI-to-PCI bridge */
  91. { RT_PCI_DEVICE_CLASS(PCIS_BRIDGE_PCI_SUBTRACTIVE, ~0) },
  92. /* Any Root Complex Event Collector */
  93. { RT_PCI_DEVICE_CLASS(((PCIS_SYSTEM_RCEC << 8) | 0x00), ~0) },
  94. { /* sentinel */ }
  95. };
  96. static struct rt_pci_driver host_bridge_driver =
  97. {
  98. .name = "host-bridge",
  99. .ids = host_bridge_pci_ids,
  100. .probe = host_bridge_probe,
  101. .remove = host_bridge_remove,
  102. .shutdown = host_bridge_shutdown,
  103. };
  104. RT_PCI_DRIVER_EXPORT(host_bridge_driver);