iomap.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * iomap.c - Implement iomap interface for PA-RISC
  4. * Copyright (c) 2004 Matthew Wilcox
  5. */
  6. #include <linux/ioport.h>
  7. #include <linux/pci.h>
  8. #include <linux/export.h>
  9. #include <asm/io.h>
  10. /*
  11. * The iomap space on 32-bit PA-RISC is intended to look like this:
  12. * 00000000-7fffffff virtual mapped IO
  13. * 80000000-8fffffff ISA/EISA port space that can't be virtually mapped
  14. * 90000000-9fffffff Dino port space
  15. * a0000000-afffffff Astro port space
  16. * b0000000-bfffffff PAT port space
  17. * c0000000-cfffffff non-swapped memory IO
  18. * f0000000-ffffffff legacy IO memory pointers
  19. *
  20. * For the moment, here's what it looks like:
  21. * 80000000-8fffffff All ISA/EISA port space
  22. * f0000000-ffffffff legacy IO memory pointers
  23. *
  24. * On 64-bit, everything is extended, so:
  25. * 8000000000000000-8fffffffffffffff All ISA/EISA port space
  26. * f000000000000000-ffffffffffffffff legacy IO memory pointers
  27. */
  28. /*
  29. * Technically, this should be 'if (VMALLOC_START < addr < VMALLOC_END),
  30. * but that's slow and we know it'll be within the first 2GB.
  31. */
  32. #ifdef CONFIG_64BIT
  33. #define INDIRECT_ADDR(addr) (((unsigned long)(addr) & 1UL<<63) != 0)
  34. #define ADDR_TO_REGION(addr) (((unsigned long)addr >> 60) & 7)
  35. #define IOPORT_MAP_BASE (8UL << 60)
  36. #else
  37. #define INDIRECT_ADDR(addr) (((unsigned long)(addr) & 1UL<<31) != 0)
  38. #define ADDR_TO_REGION(addr) (((unsigned long)addr >> 28) & 7)
  39. #define IOPORT_MAP_BASE (8UL << 28)
  40. #endif
  41. struct iomap_ops {
  42. unsigned int (*read8)(void __iomem *);
  43. unsigned int (*read16)(void __iomem *);
  44. unsigned int (*read16be)(void __iomem *);
  45. unsigned int (*read32)(void __iomem *);
  46. unsigned int (*read32be)(void __iomem *);
  47. void (*write8)(u8, void __iomem *);
  48. void (*write16)(u16, void __iomem *);
  49. void (*write16be)(u16, void __iomem *);
  50. void (*write32)(u32, void __iomem *);
  51. void (*write32be)(u32, void __iomem *);
  52. void (*read8r)(void __iomem *, void *, unsigned long);
  53. void (*read16r)(void __iomem *, void *, unsigned long);
  54. void (*read32r)(void __iomem *, void *, unsigned long);
  55. void (*write8r)(void __iomem *, const void *, unsigned long);
  56. void (*write16r)(void __iomem *, const void *, unsigned long);
  57. void (*write32r)(void __iomem *, const void *, unsigned long);
  58. };
  59. /* Generic ioport ops. To be replaced later by specific dino/elroy/wax code */
  60. #define ADDR2PORT(addr) ((unsigned long __force)(addr) & 0xffffff)
  61. static unsigned int ioport_read8(void __iomem *addr)
  62. {
  63. return inb(ADDR2PORT(addr));
  64. }
  65. static unsigned int ioport_read16(void __iomem *addr)
  66. {
  67. return inw(ADDR2PORT(addr));
  68. }
  69. static unsigned int ioport_read32(void __iomem *addr)
  70. {
  71. return inl(ADDR2PORT(addr));
  72. }
  73. static void ioport_write8(u8 datum, void __iomem *addr)
  74. {
  75. outb(datum, ADDR2PORT(addr));
  76. }
  77. static void ioport_write16(u16 datum, void __iomem *addr)
  78. {
  79. outw(datum, ADDR2PORT(addr));
  80. }
  81. static void ioport_write32(u32 datum, void __iomem *addr)
  82. {
  83. outl(datum, ADDR2PORT(addr));
  84. }
  85. static void ioport_read8r(void __iomem *addr, void *dst, unsigned long count)
  86. {
  87. insb(ADDR2PORT(addr), dst, count);
  88. }
  89. static void ioport_read16r(void __iomem *addr, void *dst, unsigned long count)
  90. {
  91. insw(ADDR2PORT(addr), dst, count);
  92. }
  93. static void ioport_read32r(void __iomem *addr, void *dst, unsigned long count)
  94. {
  95. insl(ADDR2PORT(addr), dst, count);
  96. }
  97. static void ioport_write8r(void __iomem *addr, const void *s, unsigned long n)
  98. {
  99. outsb(ADDR2PORT(addr), s, n);
  100. }
  101. static void ioport_write16r(void __iomem *addr, const void *s, unsigned long n)
  102. {
  103. outsw(ADDR2PORT(addr), s, n);
  104. }
  105. static void ioport_write32r(void __iomem *addr, const void *s, unsigned long n)
  106. {
  107. outsl(ADDR2PORT(addr), s, n);
  108. }
  109. static const struct iomap_ops ioport_ops = {
  110. .read8 = ioport_read8,
  111. .read16 = ioport_read16,
  112. .read16be = ioport_read16,
  113. .read32 = ioport_read32,
  114. .read32be = ioport_read32,
  115. .write8 = ioport_write8,
  116. .write16 = ioport_write16,
  117. .write16be = ioport_write16,
  118. .write32 = ioport_write32,
  119. .write32be = ioport_write32,
  120. .read8r = ioport_read8r,
  121. .read16r = ioport_read16r,
  122. .read32r = ioport_read32r,
  123. .write8r = ioport_write8r,
  124. .write16r = ioport_write16r,
  125. .write32r = ioport_write32r,
  126. };
  127. /* Legacy I/O memory ops */
  128. static unsigned int iomem_read8(void __iomem *addr)
  129. {
  130. return readb(addr);
  131. }
  132. static unsigned int iomem_read16(void __iomem *addr)
  133. {
  134. return readw(addr);
  135. }
  136. static unsigned int iomem_read16be(void __iomem *addr)
  137. {
  138. return __raw_readw(addr);
  139. }
  140. static unsigned int iomem_read32(void __iomem *addr)
  141. {
  142. return readl(addr);
  143. }
  144. static unsigned int iomem_read32be(void __iomem *addr)
  145. {
  146. return __raw_readl(addr);
  147. }
  148. static void iomem_write8(u8 datum, void __iomem *addr)
  149. {
  150. writeb(datum, addr);
  151. }
  152. static void iomem_write16(u16 datum, void __iomem *addr)
  153. {
  154. writew(datum, addr);
  155. }
  156. static void iomem_write16be(u16 datum, void __iomem *addr)
  157. {
  158. __raw_writew(datum, addr);
  159. }
  160. static void iomem_write32(u32 datum, void __iomem *addr)
  161. {
  162. writel(datum, addr);
  163. }
  164. static void iomem_write32be(u32 datum, void __iomem *addr)
  165. {
  166. __raw_writel(datum, addr);
  167. }
  168. static void iomem_read8r(void __iomem *addr, void *dst, unsigned long count)
  169. {
  170. while (count--) {
  171. *(u8 *)dst = __raw_readb(addr);
  172. dst++;
  173. }
  174. }
  175. static void iomem_read16r(void __iomem *addr, void *dst, unsigned long count)
  176. {
  177. while (count--) {
  178. *(u16 *)dst = __raw_readw(addr);
  179. dst += 2;
  180. }
  181. }
  182. static void iomem_read32r(void __iomem *addr, void *dst, unsigned long count)
  183. {
  184. while (count--) {
  185. *(u32 *)dst = __raw_readl(addr);
  186. dst += 4;
  187. }
  188. }
  189. static void iomem_write8r(void __iomem *addr, const void *s, unsigned long n)
  190. {
  191. while (n--) {
  192. __raw_writeb(*(u8 *)s, addr);
  193. s++;
  194. }
  195. }
  196. static void iomem_write16r(void __iomem *addr, const void *s, unsigned long n)
  197. {
  198. while (n--) {
  199. __raw_writew(*(u16 *)s, addr);
  200. s += 2;
  201. }
  202. }
  203. static void iomem_write32r(void __iomem *addr, const void *s, unsigned long n)
  204. {
  205. while (n--) {
  206. __raw_writel(*(u32 *)s, addr);
  207. s += 4;
  208. }
  209. }
  210. static const struct iomap_ops iomem_ops = {
  211. .read8 = iomem_read8,
  212. .read16 = iomem_read16,
  213. .read16be = iomem_read16be,
  214. .read32 = iomem_read32,
  215. .read32be = iomem_read32be,
  216. .write8 = iomem_write8,
  217. .write16 = iomem_write16,
  218. .write16be = iomem_write16be,
  219. .write32 = iomem_write32,
  220. .write32be = iomem_write32be,
  221. .read8r = iomem_read8r,
  222. .read16r = iomem_read16r,
  223. .read32r = iomem_read32r,
  224. .write8r = iomem_write8r,
  225. .write16r = iomem_write16r,
  226. .write32r = iomem_write32r,
  227. };
  228. static const struct iomap_ops *iomap_ops[8] = {
  229. [0] = &ioport_ops,
  230. [7] = &iomem_ops
  231. };
  232. unsigned int ioread8(void __iomem *addr)
  233. {
  234. if (unlikely(INDIRECT_ADDR(addr)))
  235. return iomap_ops[ADDR_TO_REGION(addr)]->read8(addr);
  236. return *((u8 *)addr);
  237. }
  238. unsigned int ioread16(void __iomem *addr)
  239. {
  240. if (unlikely(INDIRECT_ADDR(addr)))
  241. return iomap_ops[ADDR_TO_REGION(addr)]->read16(addr);
  242. return le16_to_cpup((u16 *)addr);
  243. }
  244. unsigned int ioread16be(void __iomem *addr)
  245. {
  246. if (unlikely(INDIRECT_ADDR(addr)))
  247. return iomap_ops[ADDR_TO_REGION(addr)]->read16be(addr);
  248. return *((u16 *)addr);
  249. }
  250. unsigned int ioread32(void __iomem *addr)
  251. {
  252. if (unlikely(INDIRECT_ADDR(addr)))
  253. return iomap_ops[ADDR_TO_REGION(addr)]->read32(addr);
  254. return le32_to_cpup((u32 *)addr);
  255. }
  256. unsigned int ioread32be(void __iomem *addr)
  257. {
  258. if (unlikely(INDIRECT_ADDR(addr)))
  259. return iomap_ops[ADDR_TO_REGION(addr)]->read32be(addr);
  260. return *((u32 *)addr);
  261. }
  262. void iowrite8(u8 datum, void __iomem *addr)
  263. {
  264. if (unlikely(INDIRECT_ADDR(addr))) {
  265. iomap_ops[ADDR_TO_REGION(addr)]->write8(datum, addr);
  266. } else {
  267. *((u8 *)addr) = datum;
  268. }
  269. }
  270. void iowrite16(u16 datum, void __iomem *addr)
  271. {
  272. if (unlikely(INDIRECT_ADDR(addr))) {
  273. iomap_ops[ADDR_TO_REGION(addr)]->write16(datum, addr);
  274. } else {
  275. *((u16 *)addr) = cpu_to_le16(datum);
  276. }
  277. }
  278. void iowrite16be(u16 datum, void __iomem *addr)
  279. {
  280. if (unlikely(INDIRECT_ADDR(addr))) {
  281. iomap_ops[ADDR_TO_REGION(addr)]->write16be(datum, addr);
  282. } else {
  283. *((u16 *)addr) = datum;
  284. }
  285. }
  286. void iowrite32(u32 datum, void __iomem *addr)
  287. {
  288. if (unlikely(INDIRECT_ADDR(addr))) {
  289. iomap_ops[ADDR_TO_REGION(addr)]->write32(datum, addr);
  290. } else {
  291. *((u32 *)addr) = cpu_to_le32(datum);
  292. }
  293. }
  294. void iowrite32be(u32 datum, void __iomem *addr)
  295. {
  296. if (unlikely(INDIRECT_ADDR(addr))) {
  297. iomap_ops[ADDR_TO_REGION(addr)]->write32be(datum, addr);
  298. } else {
  299. *((u32 *)addr) = datum;
  300. }
  301. }
  302. /* Repeating interfaces */
  303. void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
  304. {
  305. if (unlikely(INDIRECT_ADDR(addr))) {
  306. iomap_ops[ADDR_TO_REGION(addr)]->read8r(addr, dst, count);
  307. } else {
  308. while (count--) {
  309. *(u8 *)dst = *(u8 *)addr;
  310. dst++;
  311. }
  312. }
  313. }
  314. void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
  315. {
  316. if (unlikely(INDIRECT_ADDR(addr))) {
  317. iomap_ops[ADDR_TO_REGION(addr)]->read16r(addr, dst, count);
  318. } else {
  319. while (count--) {
  320. *(u16 *)dst = *(u16 *)addr;
  321. dst += 2;
  322. }
  323. }
  324. }
  325. void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
  326. {
  327. if (unlikely(INDIRECT_ADDR(addr))) {
  328. iomap_ops[ADDR_TO_REGION(addr)]->read32r(addr, dst, count);
  329. } else {
  330. while (count--) {
  331. *(u32 *)dst = *(u32 *)addr;
  332. dst += 4;
  333. }
  334. }
  335. }
  336. void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
  337. {
  338. if (unlikely(INDIRECT_ADDR(addr))) {
  339. iomap_ops[ADDR_TO_REGION(addr)]->write8r(addr, src, count);
  340. } else {
  341. while (count--) {
  342. *(u8 *)addr = *(u8 *)src;
  343. src++;
  344. }
  345. }
  346. }
  347. void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
  348. {
  349. if (unlikely(INDIRECT_ADDR(addr))) {
  350. iomap_ops[ADDR_TO_REGION(addr)]->write16r(addr, src, count);
  351. } else {
  352. while (count--) {
  353. *(u16 *)addr = *(u16 *)src;
  354. src += 2;
  355. }
  356. }
  357. }
  358. void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
  359. {
  360. if (unlikely(INDIRECT_ADDR(addr))) {
  361. iomap_ops[ADDR_TO_REGION(addr)]->write32r(addr, src, count);
  362. } else {
  363. while (count--) {
  364. *(u32 *)addr = *(u32 *)src;
  365. src += 4;
  366. }
  367. }
  368. }
  369. /* Mapping interfaces */
  370. void __iomem *ioport_map(unsigned long port, unsigned int nr)
  371. {
  372. return (void __iomem *)(IOPORT_MAP_BASE | port);
  373. }
  374. void ioport_unmap(void __iomem *addr)
  375. {
  376. if (!INDIRECT_ADDR(addr)) {
  377. iounmap(addr);
  378. }
  379. }
  380. void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
  381. {
  382. if (!INDIRECT_ADDR(addr)) {
  383. iounmap(addr);
  384. }
  385. }
  386. EXPORT_SYMBOL(ioread8);
  387. EXPORT_SYMBOL(ioread16);
  388. EXPORT_SYMBOL(ioread16be);
  389. EXPORT_SYMBOL(ioread32);
  390. EXPORT_SYMBOL(ioread32be);
  391. EXPORT_SYMBOL(iowrite8);
  392. EXPORT_SYMBOL(iowrite16);
  393. EXPORT_SYMBOL(iowrite16be);
  394. EXPORT_SYMBOL(iowrite32);
  395. EXPORT_SYMBOL(iowrite32be);
  396. EXPORT_SYMBOL(ioread8_rep);
  397. EXPORT_SYMBOL(ioread16_rep);
  398. EXPORT_SYMBOL(ioread32_rep);
  399. EXPORT_SYMBOL(iowrite8_rep);
  400. EXPORT_SYMBOL(iowrite16_rep);
  401. EXPORT_SYMBOL(iowrite32_rep);
  402. EXPORT_SYMBOL(ioport_map);
  403. EXPORT_SYMBOL(ioport_unmap);
  404. EXPORT_SYMBOL(pci_iounmap);