p2sb-uclass.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Uclass for Primary-to-sideband bus, used to access various peripherals
  4. *
  5. * Copyright 2019 Google LLC
  6. * Written by Simon Glass <sjg@chromium.org>
  7. */
  8. #define LOG_CATEGORY UCLASS_P2SB
  9. #include <common.h>
  10. #include <dm.h>
  11. #include <log.h>
  12. #include <malloc.h>
  13. #include <mapmem.h>
  14. #include <p2sb.h>
  15. #include <spl.h>
  16. #include <asm/io.h>
  17. #include <dm/uclass-internal.h>
  18. #define PCR_COMMON_IOSF_1_0 1
  19. int p2sb_set_hide(struct udevice *dev, bool hide)
  20. {
  21. struct p2sb_ops *ops = p2sb_get_ops(dev);
  22. if (!ops->set_hide)
  23. return -ENOSYS;
  24. return ops->set_hide(dev, hide);
  25. }
  26. void *pcr_reg_address(struct udevice *dev, uint offset)
  27. {
  28. struct p2sb_child_plat *pplat = dev_get_parent_plat(dev);
  29. struct udevice *p2sb = dev_get_parent(dev);
  30. struct p2sb_uc_priv *upriv = dev_get_uclass_priv(p2sb);
  31. uintptr_t reg_addr;
  32. /* Create an address based off of port id and offset */
  33. reg_addr = upriv->mmio_base;
  34. reg_addr += pplat->pid << PCR_PORTID_SHIFT;
  35. reg_addr += offset;
  36. return map_sysmem(reg_addr, 4);
  37. }
  38. /*
  39. * The mapping of addresses via the SBREG_BAR assumes the IOSF-SB
  40. * agents are using 32-bit aligned accesses for their configuration
  41. * registers. For IOSF versions greater than 1_0, IOSF-SB
  42. * agents can use any access (8/16/32 bit aligned) for their
  43. * configuration registers
  44. */
  45. static inline void check_pcr_offset_align(uint offset, uint size)
  46. {
  47. const size_t align = PCR_COMMON_IOSF_1_0 ? sizeof(uint32_t) : size;
  48. assert(IS_ALIGNED(offset, align));
  49. }
  50. uint pcr_read32(struct udevice *dev, uint offset)
  51. {
  52. void *ptr;
  53. uint val;
  54. /* Ensure the PCR offset is correctly aligned */
  55. assert(IS_ALIGNED(offset, sizeof(uint32_t)));
  56. ptr = pcr_reg_address(dev, offset);
  57. val = readl(ptr);
  58. unmap_sysmem(ptr);
  59. return val;
  60. }
  61. uint pcr_read16(struct udevice *dev, uint offset)
  62. {
  63. /* Ensure the PCR offset is correctly aligned */
  64. check_pcr_offset_align(offset, sizeof(uint16_t));
  65. return readw(pcr_reg_address(dev, offset));
  66. }
  67. uint pcr_read8(struct udevice *dev, uint offset)
  68. {
  69. /* Ensure the PCR offset is correctly aligned */
  70. check_pcr_offset_align(offset, sizeof(uint8_t));
  71. return readb(pcr_reg_address(dev, offset));
  72. }
  73. /*
  74. * After every write one needs to perform a read an innocuous register to
  75. * ensure the writes are completed for certain ports. This is done for
  76. * all ports so that the callers don't need the per-port knowledge for
  77. * each transaction.
  78. */
  79. static void write_completion(struct udevice *dev, uint offset)
  80. {
  81. readl(pcr_reg_address(dev, ALIGN_DOWN(offset, sizeof(uint32_t))));
  82. }
  83. void pcr_write32(struct udevice *dev, uint offset, uint indata)
  84. {
  85. /* Ensure the PCR offset is correctly aligned */
  86. assert(IS_ALIGNED(offset, sizeof(indata)));
  87. writel(indata, pcr_reg_address(dev, offset));
  88. /* Ensure the writes complete */
  89. write_completion(dev, offset);
  90. }
  91. void pcr_write16(struct udevice *dev, uint offset, uint indata)
  92. {
  93. /* Ensure the PCR offset is correctly aligned */
  94. check_pcr_offset_align(offset, sizeof(uint16_t));
  95. writew(indata, pcr_reg_address(dev, offset));
  96. /* Ensure the writes complete */
  97. write_completion(dev, offset);
  98. }
  99. void pcr_write8(struct udevice *dev, uint offset, uint indata)
  100. {
  101. /* Ensure the PCR offset is correctly aligned */
  102. check_pcr_offset_align(offset, sizeof(uint8_t));
  103. writeb(indata, pcr_reg_address(dev, offset));
  104. /* Ensure the writes complete */
  105. write_completion(dev, offset);
  106. }
  107. void pcr_clrsetbits32(struct udevice *dev, uint offset, uint clr, uint set)
  108. {
  109. uint data32;
  110. data32 = pcr_read32(dev, offset);
  111. data32 &= ~clr;
  112. data32 |= set;
  113. pcr_write32(dev, offset, data32);
  114. }
  115. void pcr_clrsetbits16(struct udevice *dev, uint offset, uint clr, uint set)
  116. {
  117. uint data16;
  118. data16 = pcr_read16(dev, offset);
  119. data16 &= ~clr;
  120. data16 |= set;
  121. pcr_write16(dev, offset, data16);
  122. }
  123. void pcr_clrsetbits8(struct udevice *dev, uint offset, uint clr, uint set)
  124. {
  125. uint data8;
  126. data8 = pcr_read8(dev, offset);
  127. data8 &= ~clr;
  128. data8 |= set;
  129. pcr_write8(dev, offset, data8);
  130. }
  131. int p2sb_get_port_id(struct udevice *dev)
  132. {
  133. struct p2sb_child_plat *pplat = dev_get_parent_plat(dev);
  134. return pplat->pid;
  135. }
  136. int p2sb_set_port_id(struct udevice *dev, int portid)
  137. {
  138. struct p2sb_child_plat *pplat;
  139. if (!CONFIG_IS_ENABLED(OF_PLATDATA))
  140. return -ENOSYS;
  141. pplat = dev_get_parent_plat(dev);
  142. pplat->pid = portid;
  143. return 0;
  144. }
  145. static int p2sb_child_post_bind(struct udevice *dev)
  146. {
  147. #if !CONFIG_IS_ENABLED(OF_PLATDATA)
  148. struct p2sb_child_plat *pplat = dev_get_parent_plat(dev);
  149. int ret;
  150. u32 pid;
  151. ret = dev_read_u32(dev, "intel,p2sb-port-id", &pid);
  152. if (ret)
  153. return ret;
  154. pplat->pid = pid;
  155. #endif
  156. return 0;
  157. }
  158. static int p2sb_post_bind(struct udevice *dev)
  159. {
  160. if (spl_phase() > PHASE_TPL && !CONFIG_IS_ENABLED(OF_PLATDATA))
  161. return dm_scan_fdt_dev(dev);
  162. return 0;
  163. }
  164. UCLASS_DRIVER(p2sb) = {
  165. .id = UCLASS_P2SB,
  166. .name = "p2sb",
  167. .per_device_auto = sizeof(struct p2sb_uc_priv),
  168. .post_bind = p2sb_post_bind,
  169. .child_post_bind = p2sb_child_post_bind,
  170. .per_child_plat_auto = sizeof(struct p2sb_child_plat),
  171. };