/arch/alpha/kernel/io.c

http://github.com/mirrors/linux · C · 631 lines · 466 code · 94 blank · 71 comment · 63 complexity · d7ad436b0e6d6fdab633713eddf4242d MD5 · raw file

  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Alpha IO and memory functions.
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/types.h>
  7. #include <linux/string.h>
  8. #include <linux/module.h>
  9. #include <asm/io.h>
  10. /* Out-of-line versions of the i/o routines that redirect into the
  11. platform-specific version. Note that "platform-specific" may mean
  12. "generic", which bumps through the machine vector. */
  13. unsigned int
  14. ioread8(void __iomem *addr)
  15. {
  16. unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
  17. mb();
  18. return ret;
  19. }
  20. unsigned int ioread16(void __iomem *addr)
  21. {
  22. unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
  23. mb();
  24. return ret;
  25. }
  26. unsigned int ioread32(void __iomem *addr)
  27. {
  28. unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
  29. mb();
  30. return ret;
  31. }
  32. void iowrite8(u8 b, void __iomem *addr)
  33. {
  34. mb();
  35. IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr);
  36. }
  37. void iowrite16(u16 b, void __iomem *addr)
  38. {
  39. mb();
  40. IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr);
  41. }
  42. void iowrite32(u32 b, void __iomem *addr)
  43. {
  44. mb();
  45. IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr);
  46. }
  47. EXPORT_SYMBOL(ioread8);
  48. EXPORT_SYMBOL(ioread16);
  49. EXPORT_SYMBOL(ioread32);
  50. EXPORT_SYMBOL(iowrite8);
  51. EXPORT_SYMBOL(iowrite16);
  52. EXPORT_SYMBOL(iowrite32);
  53. u8 inb(unsigned long port)
  54. {
  55. return ioread8(ioport_map(port, 1));
  56. }
  57. u16 inw(unsigned long port)
  58. {
  59. return ioread16(ioport_map(port, 2));
  60. }
  61. u32 inl(unsigned long port)
  62. {
  63. return ioread32(ioport_map(port, 4));
  64. }
  65. void outb(u8 b, unsigned long port)
  66. {
  67. iowrite8(b, ioport_map(port, 1));
  68. }
  69. void outw(u16 b, unsigned long port)
  70. {
  71. iowrite16(b, ioport_map(port, 2));
  72. }
  73. void outl(u32 b, unsigned long port)
  74. {
  75. iowrite32(b, ioport_map(port, 4));
  76. }
  77. EXPORT_SYMBOL(inb);
  78. EXPORT_SYMBOL(inw);
  79. EXPORT_SYMBOL(inl);
  80. EXPORT_SYMBOL(outb);
  81. EXPORT_SYMBOL(outw);
  82. EXPORT_SYMBOL(outl);
  83. u8 __raw_readb(const volatile void __iomem *addr)
  84. {
  85. return IO_CONCAT(__IO_PREFIX,readb)(addr);
  86. }
  87. u16 __raw_readw(const volatile void __iomem *addr)
  88. {
  89. return IO_CONCAT(__IO_PREFIX,readw)(addr);
  90. }
  91. u32 __raw_readl(const volatile void __iomem *addr)
  92. {
  93. return IO_CONCAT(__IO_PREFIX,readl)(addr);
  94. }
  95. u64 __raw_readq(const volatile void __iomem *addr)
  96. {
  97. return IO_CONCAT(__IO_PREFIX,readq)(addr);
  98. }
  99. void __raw_writeb(u8 b, volatile void __iomem *addr)
  100. {
  101. IO_CONCAT(__IO_PREFIX,writeb)(b, addr);
  102. }
  103. void __raw_writew(u16 b, volatile void __iomem *addr)
  104. {
  105. IO_CONCAT(__IO_PREFIX,writew)(b, addr);
  106. }
  107. void __raw_writel(u32 b, volatile void __iomem *addr)
  108. {
  109. IO_CONCAT(__IO_PREFIX,writel)(b, addr);
  110. }
  111. void __raw_writeq(u64 b, volatile void __iomem *addr)
  112. {
  113. IO_CONCAT(__IO_PREFIX,writeq)(b, addr);
  114. }
  115. EXPORT_SYMBOL(__raw_readb);
  116. EXPORT_SYMBOL(__raw_readw);
  117. EXPORT_SYMBOL(__raw_readl);
  118. EXPORT_SYMBOL(__raw_readq);
  119. EXPORT_SYMBOL(__raw_writeb);
  120. EXPORT_SYMBOL(__raw_writew);
  121. EXPORT_SYMBOL(__raw_writel);
  122. EXPORT_SYMBOL(__raw_writeq);
  123. u8 readb(const volatile void __iomem *addr)
  124. {
  125. u8 ret = __raw_readb(addr);
  126. mb();
  127. return ret;
  128. }
  129. u16 readw(const volatile void __iomem *addr)
  130. {
  131. u16 ret = __raw_readw(addr);
  132. mb();
  133. return ret;
  134. }
  135. u32 readl(const volatile void __iomem *addr)
  136. {
  137. u32 ret = __raw_readl(addr);
  138. mb();
  139. return ret;
  140. }
  141. u64 readq(const volatile void __iomem *addr)
  142. {
  143. u64 ret = __raw_readq(addr);
  144. mb();
  145. return ret;
  146. }
  147. void writeb(u8 b, volatile void __iomem *addr)
  148. {
  149. mb();
  150. __raw_writeb(b, addr);
  151. }
  152. void writew(u16 b, volatile void __iomem *addr)
  153. {
  154. mb();
  155. __raw_writew(b, addr);
  156. }
  157. void writel(u32 b, volatile void __iomem *addr)
  158. {
  159. mb();
  160. __raw_writel(b, addr);
  161. }
  162. void writeq(u64 b, volatile void __iomem *addr)
  163. {
  164. mb();
  165. __raw_writeq(b, addr);
  166. }
  167. EXPORT_SYMBOL(readb);
  168. EXPORT_SYMBOL(readw);
  169. EXPORT_SYMBOL(readl);
  170. EXPORT_SYMBOL(readq);
  171. EXPORT_SYMBOL(writeb);
  172. EXPORT_SYMBOL(writew);
  173. EXPORT_SYMBOL(writel);
  174. EXPORT_SYMBOL(writeq);
  175. /*
  176. * Read COUNT 8-bit bytes from port PORT into memory starting at SRC.
  177. */
  178. void ioread8_rep(void __iomem *port, void *dst, unsigned long count)
  179. {
  180. while ((unsigned long)dst & 0x3) {
  181. if (!count)
  182. return;
  183. count--;
  184. *(unsigned char *)dst = ioread8(port);
  185. dst += 1;
  186. }
  187. while (count >= 4) {
  188. unsigned int w;
  189. count -= 4;
  190. w = ioread8(port);
  191. w |= ioread8(port) << 8;
  192. w |= ioread8(port) << 16;
  193. w |= ioread8(port) << 24;
  194. *(unsigned int *)dst = w;
  195. dst += 4;
  196. }
  197. while (count) {
  198. --count;
  199. *(unsigned char *)dst = ioread8(port);
  200. dst += 1;
  201. }
  202. }
  203. void insb(unsigned long port, void *dst, unsigned long count)
  204. {
  205. ioread8_rep(ioport_map(port, 1), dst, count);
  206. }
  207. EXPORT_SYMBOL(ioread8_rep);
  208. EXPORT_SYMBOL(insb);
  209. /*
  210. * Read COUNT 16-bit words from port PORT into memory starting at
  211. * SRC. SRC must be at least short aligned. This is used by the
  212. * IDE driver to read disk sectors. Performance is important, but
  213. * the interfaces seems to be slow: just using the inlined version
  214. * of the inw() breaks things.
  215. */
  216. void ioread16_rep(void __iomem *port, void *dst, unsigned long count)
  217. {
  218. if (unlikely((unsigned long)dst & 0x3)) {
  219. if (!count)
  220. return;
  221. BUG_ON((unsigned long)dst & 0x1);
  222. count--;
  223. *(unsigned short *)dst = ioread16(port);
  224. dst += 2;
  225. }
  226. while (count >= 2) {
  227. unsigned int w;
  228. count -= 2;
  229. w = ioread16(port);
  230. w |= ioread16(port) << 16;
  231. *(unsigned int *)dst = w;
  232. dst += 4;
  233. }
  234. if (count) {
  235. *(unsigned short*)dst = ioread16(port);
  236. }
  237. }
  238. void insw(unsigned long port, void *dst, unsigned long count)
  239. {
  240. ioread16_rep(ioport_map(port, 2), dst, count);
  241. }
  242. EXPORT_SYMBOL(ioread16_rep);
  243. EXPORT_SYMBOL(insw);
  244. /*
  245. * Read COUNT 32-bit words from port PORT into memory starting at
  246. * SRC. Now works with any alignment in SRC. Performance is important,
  247. * but the interfaces seems to be slow: just using the inlined version
  248. * of the inl() breaks things.
  249. */
  250. void ioread32_rep(void __iomem *port, void *dst, unsigned long count)
  251. {
  252. if (unlikely((unsigned long)dst & 0x3)) {
  253. while (count--) {
  254. struct S { int x __attribute__((packed)); };
  255. ((struct S *)dst)->x = ioread32(port);
  256. dst += 4;
  257. }
  258. } else {
  259. /* Buffer 32-bit aligned. */
  260. while (count--) {
  261. *(unsigned int *)dst = ioread32(port);
  262. dst += 4;
  263. }
  264. }
  265. }
  266. void insl(unsigned long port, void *dst, unsigned long count)
  267. {
  268. ioread32_rep(ioport_map(port, 4), dst, count);
  269. }
  270. EXPORT_SYMBOL(ioread32_rep);
  271. EXPORT_SYMBOL(insl);
  272. /*
  273. * Like insb but in the opposite direction.
  274. * Don't worry as much about doing aligned memory transfers:
  275. * doing byte reads the "slow" way isn't nearly as slow as
  276. * doing byte writes the slow way (no r-m-w cycle).
  277. */
  278. void iowrite8_rep(void __iomem *port, const void *xsrc, unsigned long count)
  279. {
  280. const unsigned char *src = xsrc;
  281. while (count--)
  282. iowrite8(*src++, port);
  283. }
  284. void outsb(unsigned long port, const void *src, unsigned long count)
  285. {
  286. iowrite8_rep(ioport_map(port, 1), src, count);
  287. }
  288. EXPORT_SYMBOL(iowrite8_rep);
  289. EXPORT_SYMBOL(outsb);
  290. /*
  291. * Like insw but in the opposite direction. This is used by the IDE
  292. * driver to write disk sectors. Performance is important, but the
  293. * interfaces seems to be slow: just using the inlined version of the
  294. * outw() breaks things.
  295. */
  296. void iowrite16_rep(void __iomem *port, const void *src, unsigned long count)
  297. {
  298. if (unlikely((unsigned long)src & 0x3)) {
  299. if (!count)
  300. return;
  301. BUG_ON((unsigned long)src & 0x1);
  302. iowrite16(*(unsigned short *)src, port);
  303. src += 2;
  304. --count;
  305. }
  306. while (count >= 2) {
  307. unsigned int w;
  308. count -= 2;
  309. w = *(unsigned int *)src;
  310. src += 4;
  311. iowrite16(w >> 0, port);
  312. iowrite16(w >> 16, port);
  313. }
  314. if (count) {
  315. iowrite16(*(unsigned short *)src, port);
  316. }
  317. }
  318. void outsw(unsigned long port, const void *src, unsigned long count)
  319. {
  320. iowrite16_rep(ioport_map(port, 2), src, count);
  321. }
  322. EXPORT_SYMBOL(iowrite16_rep);
  323. EXPORT_SYMBOL(outsw);
  324. /*
  325. * Like insl but in the opposite direction. This is used by the IDE
  326. * driver to write disk sectors. Works with any alignment in SRC.
  327. * Performance is important, but the interfaces seems to be slow:
  328. * just using the inlined version of the outl() breaks things.
  329. */
  330. void iowrite32_rep(void __iomem *port, const void *src, unsigned long count)
  331. {
  332. if (unlikely((unsigned long)src & 0x3)) {
  333. while (count--) {
  334. struct S { int x __attribute__((packed)); };
  335. iowrite32(((struct S *)src)->x, port);
  336. src += 4;
  337. }
  338. } else {
  339. /* Buffer 32-bit aligned. */
  340. while (count--) {
  341. iowrite32(*(unsigned int *)src, port);
  342. src += 4;
  343. }
  344. }
  345. }
  346. void outsl(unsigned long port, const void *src, unsigned long count)
  347. {
  348. iowrite32_rep(ioport_map(port, 4), src, count);
  349. }
  350. EXPORT_SYMBOL(iowrite32_rep);
  351. EXPORT_SYMBOL(outsl);
  352. /*
  353. * Copy data from IO memory space to "real" memory space.
  354. * This needs to be optimized.
  355. */
  356. void memcpy_fromio(void *to, const volatile void __iomem *from, long count)
  357. {
  358. /* Optimize co-aligned transfers. Everything else gets handled
  359. a byte at a time. */
  360. if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
  361. count -= 8;
  362. do {
  363. *(u64 *)to = __raw_readq(from);
  364. count -= 8;
  365. to += 8;
  366. from += 8;
  367. } while (count >= 0);
  368. count += 8;
  369. }
  370. if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
  371. count -= 4;
  372. do {
  373. *(u32 *)to = __raw_readl(from);
  374. count -= 4;
  375. to += 4;
  376. from += 4;
  377. } while (count >= 0);
  378. count += 4;
  379. }
  380. if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
  381. count -= 2;
  382. do {
  383. *(u16 *)to = __raw_readw(from);
  384. count -= 2;
  385. to += 2;
  386. from += 2;
  387. } while (count >= 0);
  388. count += 2;
  389. }
  390. while (count > 0) {
  391. *(u8 *) to = __raw_readb(from);
  392. count--;
  393. to++;
  394. from++;
  395. }
  396. mb();
  397. }
  398. EXPORT_SYMBOL(memcpy_fromio);
  399. /*
  400. * Copy data from "real" memory space to IO memory space.
  401. * This needs to be optimized.
  402. */
  403. void memcpy_toio(volatile void __iomem *to, const void *from, long count)
  404. {
  405. /* Optimize co-aligned transfers. Everything else gets handled
  406. a byte at a time. */
  407. /* FIXME -- align FROM. */
  408. if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
  409. count -= 8;
  410. do {
  411. __raw_writeq(*(const u64 *)from, to);
  412. count -= 8;
  413. to += 8;
  414. from += 8;
  415. } while (count >= 0);
  416. count += 8;
  417. }
  418. if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
  419. count -= 4;
  420. do {
  421. __raw_writel(*(const u32 *)from, to);
  422. count -= 4;
  423. to += 4;
  424. from += 4;
  425. } while (count >= 0);
  426. count += 4;
  427. }
  428. if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
  429. count -= 2;
  430. do {
  431. __raw_writew(*(const u16 *)from, to);
  432. count -= 2;
  433. to += 2;
  434. from += 2;
  435. } while (count >= 0);
  436. count += 2;
  437. }
  438. while (count > 0) {
  439. __raw_writeb(*(const u8 *) from, to);
  440. count--;
  441. to++;
  442. from++;
  443. }
  444. mb();
  445. }
  446. EXPORT_SYMBOL(memcpy_toio);
  447. /*
  448. * "memset" on IO memory space.
  449. */
  450. void _memset_c_io(volatile void __iomem *to, unsigned long c, long count)
  451. {
  452. /* Handle any initial odd byte */
  453. if (count > 0 && ((u64)to & 1)) {
  454. __raw_writeb(c, to);
  455. to++;
  456. count--;
  457. }
  458. /* Handle any initial odd halfword */
  459. if (count >= 2 && ((u64)to & 2)) {
  460. __raw_writew(c, to);
  461. to += 2;
  462. count -= 2;
  463. }
  464. /* Handle any initial odd word */
  465. if (count >= 4 && ((u64)to & 4)) {
  466. __raw_writel(c, to);
  467. to += 4;
  468. count -= 4;
  469. }
  470. /* Handle all full-sized quadwords: we're aligned
  471. (or have a small count) */
  472. count -= 8;
  473. if (count >= 0) {
  474. do {
  475. __raw_writeq(c, to);
  476. to += 8;
  477. count -= 8;
  478. } while (count >= 0);
  479. }
  480. count += 8;
  481. /* The tail is word-aligned if we still have count >= 4 */
  482. if (count >= 4) {
  483. __raw_writel(c, to);
  484. to += 4;
  485. count -= 4;
  486. }
  487. /* The tail is half-word aligned if we have count >= 2 */
  488. if (count >= 2) {
  489. __raw_writew(c, to);
  490. to += 2;
  491. count -= 2;
  492. }
  493. /* And finally, one last byte.. */
  494. if (count) {
  495. __raw_writeb(c, to);
  496. }
  497. mb();
  498. }
  499. EXPORT_SYMBOL(_memset_c_io);
  500. /* A version of memcpy used by the vga console routines to move data around
  501. arbitrarily between screen and main memory. */
  502. void
  503. scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
  504. {
  505. const u16 __iomem *ios = (const u16 __iomem *) s;
  506. u16 __iomem *iod = (u16 __iomem *) d;
  507. int s_isio = __is_ioaddr(s);
  508. int d_isio = __is_ioaddr(d);
  509. if (s_isio) {
  510. if (d_isio) {
  511. /* FIXME: Should handle unaligned ops and
  512. operation widening. */
  513. count /= 2;
  514. while (count--) {
  515. u16 tmp = __raw_readw(ios++);
  516. __raw_writew(tmp, iod++);
  517. }
  518. }
  519. else
  520. memcpy_fromio(d, ios, count);
  521. } else {
  522. if (d_isio)
  523. memcpy_toio(iod, s, count);
  524. else
  525. memcpy(d, s, count);
  526. }
  527. }
  528. EXPORT_SYMBOL(scr_memcpyw);
  529. void __iomem *ioport_map(unsigned long port, unsigned int size)
  530. {
  531. return IO_CONCAT(__IO_PREFIX,ioportmap) (port);
  532. }
  533. void ioport_unmap(void __iomem *addr)
  534. {
  535. }
  536. EXPORT_SYMBOL(ioport_map);
  537. EXPORT_SYMBOL(ioport_unmap);