ahci-pci.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-02-25 GuEe-GUI the first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #define AHCI_REG_BAR 5
  13. struct pci_ahci_quirk
  14. {
  15. int bar_idx;
  16. rt_bool_t bar_offset;
  17. const struct rt_ahci_ops *ops;
  18. };
  19. struct pci_ahci_host
  20. {
  21. struct rt_ahci_host parent;
  22. const struct pci_ahci_quirk *quirk;
  23. rt_bool_t is_msi;
  24. };
  25. #define raw_to_pci_ahci_host(raw) rt_container_of(raw, struct pci_ahci_host, parent)
  26. static rt_err_t pci_ahci_init(struct rt_ahci_host *host)
  27. {
  28. struct rt_pci_device *pdev;
  29. pdev = rt_container_of(host->parent.dev, struct rt_pci_device, parent);
  30. if (pdev->vendor == PCI_VENDOR_ID_JMICRON)
  31. {
  32. rt_pci_write_config_u8(pdev, 0x41, 0xa1);
  33. }
  34. return RT_EOK;
  35. }
  36. static const struct rt_ahci_ops pci_ahci_ops =
  37. {
  38. .host_init = pci_ahci_init,
  39. };
  40. static rt_err_t pci_ahci_intel_init(struct rt_ahci_host *host)
  41. {
  42. rt_uint16_t val;
  43. struct rt_pci_device *pdev;
  44. pdev = rt_container_of(host->parent.dev, struct rt_pci_device, parent);
  45. rt_pci_read_config_u16(pdev, 0x92, &val);
  46. rt_pci_write_config_u16(pdev, 0x92, val & ~0xf);
  47. rt_thread_mdelay(10);
  48. rt_pci_write_config_u16(pdev, 0x92, val | 0xf);
  49. return RT_EOK;
  50. }
  51. static const struct rt_ahci_ops pci_ahci_intel_ops =
  52. {
  53. .host_init = pci_ahci_intel_init,
  54. };
  55. static rt_err_t pci_ahci_probe(struct rt_pci_device *pdev)
  56. {
  57. rt_err_t err;
  58. int bar_idx;
  59. struct rt_ahci_host *ahci;
  60. struct pci_ahci_host *pci_ahci = rt_calloc(1, sizeof(*pci_ahci));
  61. const struct pci_ahci_quirk *quirk = pdev->id->data;
  62. if (!pci_ahci)
  63. {
  64. return -RT_ENOMEM;
  65. }
  66. pci_ahci->quirk = quirk;
  67. ahci = &pci_ahci->parent;
  68. ahci->parent.dev = &pdev->parent;
  69. bar_idx = quirk && quirk->bar_offset ? quirk->bar_idx : AHCI_REG_BAR;
  70. ahci->regs = rt_pci_iomap(pdev, bar_idx);
  71. if (!ahci->regs)
  72. {
  73. err = -RT_EIO;
  74. goto _fail;
  75. }
  76. ahci->ops = quirk && quirk->ops ? quirk->ops : &pci_ahci_ops;
  77. if (rt_pci_msi_enable(pdev) > 0)
  78. {
  79. pci_ahci->is_msi = RT_TRUE;
  80. }
  81. else
  82. {
  83. rt_pci_irq_unmask(pdev);
  84. }
  85. ahci->irq = pdev->irq;
  86. rt_pci_set_master(pdev);
  87. if ((err = rt_ahci_host_register(ahci)))
  88. {
  89. goto _disable;
  90. }
  91. pdev->parent.user_data = pci_ahci;
  92. return RT_EOK;
  93. _disable:
  94. if (pci_ahci->is_msi)
  95. {
  96. rt_pci_msix_disable(pdev);
  97. }
  98. else
  99. {
  100. rt_pci_irq_mask(pdev);
  101. }
  102. rt_pci_clear_master(pdev);
  103. rt_iounmap(ahci->regs);
  104. _fail:
  105. rt_free(pci_ahci);
  106. return err;
  107. }
  108. static rt_err_t pci_ahci_remove(struct rt_pci_device *pdev)
  109. {
  110. struct rt_ahci_host *ahci;
  111. struct pci_ahci_host *pci_ahci = pdev->parent.user_data;
  112. ahci = &pci_ahci->parent;
  113. rt_ahci_host_unregister(ahci);
  114. if (pci_ahci->is_msi)
  115. {
  116. rt_pci_msi_disable(pdev);
  117. }
  118. else
  119. {
  120. /* INTx is shared, don't mask all */
  121. rt_hw_interrupt_umask(pdev->irq);
  122. rt_pci_irq_mask(pdev);
  123. }
  124. rt_pci_clear_master(pdev);
  125. rt_iounmap(ahci->regs);
  126. rt_free(pci_ahci);
  127. return RT_EOK;
  128. }
  129. static rt_err_t pci_ahci_shutdown(struct rt_pci_device *pdev)
  130. {
  131. return pci_ahci_remove(pdev);
  132. }
  133. static struct pci_ahci_quirk intel_quirk =
  134. {
  135. .ops = &pci_ahci_intel_ops,
  136. };
  137. static struct pci_ahci_quirk cavium_sata_quirk =
  138. {
  139. .bar_idx = 0,
  140. .bar_offset = RT_TRUE,
  141. };
  142. static const struct rt_pci_device_id pci_ahci_ids[] =
  143. {
  144. { RT_PCI_DEVICE_ID(PCI_VENDOR_ID_INTEL, 0x2922), .data = &intel_quirk },
  145. { RT_PCI_DEVICE_ID(PCI_VENDOR_ID_ASMEDIA, 0x0611) },
  146. { RT_PCI_DEVICE_ID(PCI_VENDOR_ID_MARVELL, 0x6121) },
  147. { RT_PCI_DEVICE_ID(PCI_VENDOR_ID_MARVELL, 0x6145) },
  148. { RT_PCI_DEVICE_ID(PCI_VENDOR_ID_CAVIUM, 0xa01c), .data = &cavium_sata_quirk },
  149. { RT_PCI_DEVICE_CLASS(PCIS_STORAGE_SATA_AHCI, ~0) },
  150. { /* sentinel */ }
  151. };
  152. static struct rt_pci_driver pci_ahci_driver =
  153. {
  154. .name = "ahci-pci",
  155. .ids = pci_ahci_ids,
  156. .probe = pci_ahci_probe,
  157. .remove = pci_ahci_remove,
  158. .shutdown = pci_ahci_shutdown,
  159. };
  160. RT_PCI_DRIVER_EXPORT(pci_ahci_driver);