^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * arch/sh/kernel/io.c - Machine independent I/O functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2000 - 2009 Stuart Menefy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2005 Paul Mundt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/machvec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copy data from IO memory space to "real" memory space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned long count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Would it be worthwhile doing byte and long transfers first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * to try and get aligned?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #ifdef CONFIG_CPU_SH4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if ((count >= 0x20) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) (((u32)to & 0x1f) == 0) && (((u32)from & 0x3) == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) int tmp2, tmp3, tmp4, tmp5, tmp6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) "1: \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) "mov.l @%7+, r0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) "mov.l @%7+, %2 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) "movca.l r0, @%0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) "mov.l @%7+, %3 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) "mov.l @%7+, %4 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) "mov.l @%7+, %5 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) "mov.l @%7+, %6 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) "mov.l @%7+, r7 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) "mov.l @%7+, r0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) "mov.l %2, @(0x04,%0) \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) "mov #0x20, %2 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) "mov.l %3, @(0x08,%0) \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) "sub %2, %1 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) "mov.l %4, @(0x0c,%0) \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) "cmp/hi %1, %2 ! T if 32 > count \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) "mov.l %5, @(0x10,%0) \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) "mov.l %6, @(0x14,%0) \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) "mov.l r7, @(0x18,%0) \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) "mov.l r0, @(0x1c,%0) \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) "bf.s 1b \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) " add #0x20, %0 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) : "=&r" (to), "=&r" (count),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) "=&r" (tmp5), "=&r" (tmp6), "=&r" (from)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) : "7"(from), "0" (to), "1" (count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) : "r0", "r7", "t", "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if ((((u32)to | (u32)from) & 0x3) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) for (; count > 3; count -= 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *(u32 *)to = *(volatile u32 *)from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) to += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) from += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) for (; count > 0; count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *(u8 *)to = *(volatile u8 *)from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) to++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) from++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) EXPORT_SYMBOL(memcpy_fromio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * Copy data from "real" memory space to IO memory space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void memcpy_toio(volatile void __iomem *to, const void *from, unsigned long count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if ((((u32)to | (u32)from) & 0x3) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) for ( ; count > 3; count -= 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) *(volatile u32 *)to = *(u32 *)from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) to += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) from += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) for (; count > 0; count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) *(volatile u8 *)to = *(u8 *)from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) to++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) from++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) EXPORT_SYMBOL(memcpy_toio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * "memset" on IO memory space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * This needs to be optimized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) void memset_io(volatile void __iomem *dst, int c, unsigned long count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) while (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) writeb(c, dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) dst++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) EXPORT_SYMBOL(memset_io);