access.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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 <rthw.h>
  11. #include <rtthread.h>
  12. #include <drivers/pci.h>
  13. struct rt_spinlock rt_pci_lock = { 0 };
  14. #ifdef RT_PCI_LOCKLESS
  15. #define pci_lock_config(l) do { (void)(l); } while (0)
  16. #define pci_unlock_config(l) do { (void)(l); } while (0)
  17. #else
  18. #define pci_lock_config(l) l = rt_spin_lock_irqsave(&rt_pci_lock)
  19. #define pci_unlock_config(l) rt_spin_unlock_irqrestore(&rt_pci_lock, l)
  20. #endif
  21. #define PCI_OPS_READ(name, type) \
  22. rt_err_t rt_pci_bus_read_config_##name(struct rt_pci_bus *bus, rt_uint32_t devfn, int reg, type *value) \
  23. { \
  24. rt_err_t err; \
  25. rt_ubase_t level; \
  26. rt_uint32_t data = 0; \
  27. pci_lock_config(level); \
  28. err = bus->ops->read(bus, devfn, reg, sizeof(type), &data); \
  29. *value = err ? (type)(~0) : (type)data; \
  30. pci_unlock_config(level); \
  31. return err; \
  32. }
  33. #define PCI_OPS_WRITE(name, type) \
  34. rt_err_t rt_pci_bus_write_config_##name(struct rt_pci_bus *bus, rt_uint32_t devfn, int reg, type value) \
  35. { \
  36. rt_err_t err; \
  37. rt_ubase_t level; \
  38. pci_lock_config(level); \
  39. err = bus->ops->write(bus, devfn, reg, sizeof(type), value); \
  40. pci_unlock_config(level); \
  41. return err; \
  42. }
  43. #define PCI_OPS(name, type) \
  44. PCI_OPS_READ(name, type) \
  45. PCI_OPS_WRITE(name, type)
  46. PCI_OPS(u8, rt_uint8_t)
  47. PCI_OPS(u16, rt_uint16_t)
  48. PCI_OPS(u32, rt_uint32_t)
  49. #undef PCI_OP_WRITE
  50. #undef PCI_OP_READ
  51. #undef PCI_OPS
  52. rt_err_t rt_pci_bus_read_config_uxx(struct rt_pci_bus *bus,
  53. rt_uint32_t devfn, int reg, int width, rt_uint32_t *value)
  54. {
  55. void *base;
  56. if ((base = bus->ops->map(bus, devfn, reg)))
  57. {
  58. if (width == 1)
  59. {
  60. *value = HWREG8(base);
  61. }
  62. else if (width == 2)
  63. {
  64. *value = HWREG16(base);
  65. }
  66. else
  67. {
  68. *value = HWREG32(base);
  69. }
  70. return RT_EOK;
  71. }
  72. return -RT_ERROR;
  73. }
  74. rt_err_t rt_pci_bus_write_config_uxx(struct rt_pci_bus *bus,
  75. rt_uint32_t devfn, int reg, int width, rt_uint32_t value)
  76. {
  77. void *base;
  78. if ((base = bus->ops->map(bus, devfn, reg)))
  79. {
  80. if (width == 1)
  81. {
  82. HWREG8(base) = value;
  83. }
  84. else if (width == 2)
  85. {
  86. HWREG16(base) = value;
  87. }
  88. else
  89. {
  90. HWREG32(base) = value;
  91. }
  92. return RT_EOK;
  93. }
  94. return -RT_ERROR;
  95. }
  96. rt_err_t rt_pci_bus_read_config_generic_u32(struct rt_pci_bus *bus,
  97. rt_uint32_t devfn, int reg, int width, rt_uint32_t *value)
  98. {
  99. void *base;
  100. if ((base = bus->ops->map(bus, devfn, reg)))
  101. {
  102. *value = HWREG32(base);
  103. if (width <= 2)
  104. {
  105. *value = (*value >> (8 * (reg & 3))) & ((1 << (width * 8)) - 1);
  106. }
  107. return RT_EOK;
  108. }
  109. return -RT_ERROR;
  110. }
  111. rt_err_t rt_pci_bus_write_config_generic_u32(struct rt_pci_bus *bus,
  112. rt_uint32_t devfn, int reg, int width, rt_uint32_t value)
  113. {
  114. void *base;
  115. if ((base = bus->ops->map(bus, devfn, reg & ~0x3)))
  116. {
  117. if (width == 4)
  118. {
  119. HWREG32(base) = value;
  120. }
  121. else
  122. {
  123. rt_uint32_t mask, tmp;
  124. mask = ~(((1 << (width * 8)) - 1) << ((reg & 0x3) * 8));
  125. tmp = HWREG32(base) & mask;
  126. tmp |= value << ((reg & 0x3) * 8);
  127. HWREG32(base) = tmp;
  128. }
  129. return RT_EOK;
  130. }
  131. return -RT_ERROR;
  132. }