logic_pio.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2017 HiSilicon Limited, All Rights Reserved.
  4. * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>
  5. * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
  6. */
  7. #define pr_fmt(fmt) "LOGIC PIO: " fmt
  8. #include <linux/of.h>
  9. #include <linux/io.h>
  10. #include <linux/logic_pio.h>
  11. #include <linux/mm.h>
  12. #include <linux/rculist.h>
  13. #include <linux/sizes.h>
  14. #include <linux/slab.h>
  15. /* The unique hardware address list */
  16. static LIST_HEAD(io_range_list);
  17. static DEFINE_MUTEX(io_range_mutex);
  18. /* Consider a kernel general helper for this */
  19. #define in_range(b, first, len) ((b) >= (first) && (b) < (first) + (len))
  20. /**
  21. * logic_pio_register_range - register logical PIO range for a host
  22. * @new_range: pointer to the IO range to be registered.
  23. *
  24. * Returns 0 on success, the error code in case of failure.
  25. *
  26. * Register a new IO range node in the IO range list.
  27. */
  28. int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
  29. {
  30. struct logic_pio_hwaddr *range;
  31. resource_size_t start;
  32. resource_size_t end;
  33. resource_size_t mmio_sz = 0;
  34. resource_size_t iio_sz = MMIO_UPPER_LIMIT;
  35. int ret = 0;
  36. if (!new_range || !new_range->fwnode || !new_range->size)
  37. return -EINVAL;
  38. start = new_range->hw_start;
  39. end = new_range->hw_start + new_range->size;
  40. mutex_lock(&io_range_mutex);
  41. list_for_each_entry_rcu(range, &io_range_list, list) {
  42. if (range->fwnode == new_range->fwnode) {
  43. /* range already there */
  44. goto end_register;
  45. }
  46. if (range->flags == LOGIC_PIO_CPU_MMIO &&
  47. new_range->flags == LOGIC_PIO_CPU_MMIO) {
  48. /* for MMIO ranges we need to check for overlap */
  49. if (start >= range->hw_start + range->size ||
  50. end < range->hw_start) {
  51. mmio_sz += range->size;
  52. } else {
  53. ret = -EFAULT;
  54. goto end_register;
  55. }
  56. } else if (range->flags == LOGIC_PIO_INDIRECT &&
  57. new_range->flags == LOGIC_PIO_INDIRECT) {
  58. iio_sz += range->size;
  59. }
  60. }
  61. /* range not registered yet, check for available space */
  62. if (new_range->flags == LOGIC_PIO_CPU_MMIO) {
  63. if (mmio_sz + new_range->size - 1 > MMIO_UPPER_LIMIT) {
  64. /* if it's too big check if 64K space can be reserved */
  65. if (mmio_sz + SZ_64K - 1 > MMIO_UPPER_LIMIT) {
  66. ret = -E2BIG;
  67. goto end_register;
  68. }
  69. new_range->size = SZ_64K;
  70. pr_warn("Requested IO range too big, new size set to 64K\n");
  71. }
  72. new_range->io_start = mmio_sz;
  73. } else if (new_range->flags == LOGIC_PIO_INDIRECT) {
  74. if (iio_sz + new_range->size - 1 > IO_SPACE_LIMIT) {
  75. ret = -E2BIG;
  76. goto end_register;
  77. }
  78. new_range->io_start = iio_sz;
  79. } else {
  80. /* invalid flag */
  81. ret = -EINVAL;
  82. goto end_register;
  83. }
  84. list_add_tail_rcu(&new_range->list, &io_range_list);
  85. end_register:
  86. mutex_unlock(&io_range_mutex);
  87. return ret;
  88. }
  89. /**
  90. * find_io_range_by_fwnode - find logical PIO range for given FW node
  91. * @fwnode: FW node handle associated with logical PIO range
  92. *
  93. * Returns pointer to node on success, NULL otherwise.
  94. *
  95. * Traverse the io_range_list to find the registered node for @fwnode.
  96. */
  97. struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode)
  98. {
  99. struct logic_pio_hwaddr *range;
  100. list_for_each_entry_rcu(range, &io_range_list, list) {
  101. if (range->fwnode == fwnode)
  102. return range;
  103. }
  104. return NULL;
  105. }
  106. /* Return a registered range given an input PIO token */
  107. static struct logic_pio_hwaddr *find_io_range(unsigned long pio)
  108. {
  109. struct logic_pio_hwaddr *range;
  110. list_for_each_entry_rcu(range, &io_range_list, list) {
  111. if (in_range(pio, range->io_start, range->size))
  112. return range;
  113. }
  114. pr_err("PIO entry token %lx invalid\n", pio);
  115. return NULL;
  116. }
  117. /**
  118. * logic_pio_to_hwaddr - translate logical PIO to HW address
  119. * @pio: logical PIO value
  120. *
  121. * Returns HW address if valid, ~0 otherwise.
  122. *
  123. * Translate the input logical PIO to the corresponding hardware address.
  124. * The input PIO should be unique in the whole logical PIO space.
  125. */
  126. resource_size_t logic_pio_to_hwaddr(unsigned long pio)
  127. {
  128. struct logic_pio_hwaddr *range;
  129. range = find_io_range(pio);
  130. if (range)
  131. return range->hw_start + pio - range->io_start;
  132. return (resource_size_t)~0;
  133. }
  134. /**
  135. * logic_pio_trans_hwaddr - translate HW address to logical PIO
  136. * @fwnode: FW node reference for the host
  137. * @addr: Host-relative HW address
  138. * @size: size to translate
  139. *
  140. * Returns Logical PIO value if successful, ~0UL otherwise
  141. */
  142. unsigned long logic_pio_trans_hwaddr(struct fwnode_handle *fwnode,
  143. resource_size_t addr, resource_size_t size)
  144. {
  145. struct logic_pio_hwaddr *range;
  146. range = find_io_range_by_fwnode(fwnode);
  147. if (!range || range->flags == LOGIC_PIO_CPU_MMIO) {
  148. pr_err("IO range not found or invalid\n");
  149. return ~0UL;
  150. }
  151. if (range->size < size) {
  152. pr_err("resource size %pa cannot fit in IO range size %pa\n",
  153. &size, &range->size);
  154. return ~0UL;
  155. }
  156. return addr - range->hw_start + range->io_start;
  157. }
  158. unsigned long logic_pio_trans_cpuaddr(resource_size_t addr)
  159. {
  160. struct logic_pio_hwaddr *range;
  161. list_for_each_entry_rcu(range, &io_range_list, list) {
  162. if (range->flags != LOGIC_PIO_CPU_MMIO)
  163. continue;
  164. if (in_range(addr, range->hw_start, range->size))
  165. return addr - range->hw_start + range->io_start;
  166. }
  167. pr_err("addr %llx not registered in io_range_list\n",
  168. (unsigned long long) addr);
  169. return ~0UL;
  170. }
  171. #if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE)
  172. #define BUILD_LOGIC_IO(bw, type) \
  173. type logic_in##bw(unsigned long addr) \
  174. { \
  175. type ret = (type)~0; \
  176. \
  177. if (addr < MMIO_UPPER_LIMIT) { \
  178. ret = read##bw(PCI_IOBASE + addr); \
  179. } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \
  180. struct logic_pio_hwaddr *entry = find_io_range(addr); \
  181. \
  182. if (entry && entry->ops) \
  183. ret = entry->ops->in(entry->hostdata, \
  184. addr, sizeof(type)); \
  185. else \
  186. WARN_ON_ONCE(1); \
  187. } \
  188. return ret; \
  189. } \
  190. \
  191. void logic_out##bw(type value, unsigned long addr) \
  192. { \
  193. if (addr < MMIO_UPPER_LIMIT) { \
  194. write##bw(value, PCI_IOBASE + addr); \
  195. } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \
  196. struct logic_pio_hwaddr *entry = find_io_range(addr); \
  197. \
  198. if (entry && entry->ops) \
  199. entry->ops->out(entry->hostdata, \
  200. addr, value, sizeof(type)); \
  201. else \
  202. WARN_ON_ONCE(1); \
  203. } \
  204. } \
  205. \
  206. void logic_ins##bw(unsigned long addr, void *buffer, \
  207. unsigned int count) \
  208. { \
  209. if (addr < MMIO_UPPER_LIMIT) { \
  210. reads##bw(PCI_IOBASE + addr, buffer, count); \
  211. } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \
  212. struct logic_pio_hwaddr *entry = find_io_range(addr); \
  213. \
  214. if (entry && entry->ops) \
  215. entry->ops->ins(entry->hostdata, \
  216. addr, buffer, sizeof(type), count); \
  217. else \
  218. WARN_ON_ONCE(1); \
  219. } \
  220. \
  221. } \
  222. \
  223. void logic_outs##bw(unsigned long addr, const void *buffer, \
  224. unsigned int count) \
  225. { \
  226. if (addr < MMIO_UPPER_LIMIT) { \
  227. writes##bw(PCI_IOBASE + addr, buffer, count); \
  228. } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \
  229. struct logic_pio_hwaddr *entry = find_io_range(addr); \
  230. \
  231. if (entry && entry->ops) \
  232. entry->ops->outs(entry->hostdata, \
  233. addr, buffer, sizeof(type), count); \
  234. else \
  235. WARN_ON_ONCE(1); \
  236. } \
  237. }
  238. BUILD_LOGIC_IO(b, u8)
  239. EXPORT_SYMBOL(logic_inb);
  240. EXPORT_SYMBOL(logic_insb);
  241. EXPORT_SYMBOL(logic_outb);
  242. EXPORT_SYMBOL(logic_outsb);
  243. BUILD_LOGIC_IO(w, u16)
  244. EXPORT_SYMBOL(logic_inw);
  245. EXPORT_SYMBOL(logic_insw);
  246. EXPORT_SYMBOL(logic_outw);
  247. EXPORT_SYMBOL(logic_outsw);
  248. BUILD_LOGIC_IO(l, u32)
  249. EXPORT_SYMBOL(logic_inl);
  250. EXPORT_SYMBOL(logic_insl);
  251. EXPORT_SYMBOL(logic_outl);
  252. EXPORT_SYMBOL(logic_outsl);
  253. #endif /* CONFIG_INDIRECT_PIO && PCI_IOBASE */