Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / arch / powerpc / kernel / io.c
index e981806..1882bf4 100644 (file)
 #include <asm/firmware.h>
 #include <asm/bug.h>
 
-void _insb(volatile u8 __iomem *port, void *buf, long count)
+void _insb(const volatile u8 __iomem *port, void *buf, long count)
 {
        u8 *tbuf = buf;
        u8 tmp;
 
-       BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
        if (unlikely(count <= 0))
                return;
        asm volatile("sync");
        do {
                tmp = *port;
-               asm volatile("eieio");
+               eieio();
                *tbuf++ = tmp;
        } while (--count != 0);
        asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -48,8 +46,6 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count)
 {
        const u8 *tbuf = buf;
 
-       BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
        if (unlikely(count <= 0))
                return;
        asm volatile("sync");
@@ -60,19 +56,17 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count)
 }
 EXPORT_SYMBOL(_outsb);
 
-void _insw_ns(volatile u16 __iomem *port, void *buf, long count)
+void _insw_ns(const volatile u16 __iomem *port, void *buf, long count)
 {
        u16 *tbuf = buf;
        u16 tmp;
 
-       BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
        if (unlikely(count <= 0))
                return;
        asm volatile("sync");
        do {
                tmp = *port;
-               asm volatile("eieio");
+               eieio();
                *tbuf++ = tmp;
        } while (--count != 0);
        asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -83,8 +77,6 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count)
 {
        const u16 *tbuf = buf;
 
-       BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
        if (unlikely(count <= 0))
                return;
        asm volatile("sync");
@@ -95,19 +87,17 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count)
 }
 EXPORT_SYMBOL(_outsw_ns);
 
-void _insl_ns(volatile u32 __iomem *port, void *buf, long count)
+void _insl_ns(const volatile u32 __iomem *port, void *buf, long count)
 {
        u32 *tbuf = buf;
        u32 tmp;
 
-       BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
        if (unlikely(count <= 0))
                return;
        asm volatile("sync");
        do {
                tmp = *port;
-               asm volatile("eieio");
+               eieio();
                *tbuf++ = tmp;
        } while (--count != 0);
        asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -118,8 +108,6 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count)
 {
        const u32 *tbuf = buf;
 
-       BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
        if (unlikely(count <= 0))
                return;
        asm volatile("sync");
@@ -129,3 +117,91 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count)
        asm volatile("sync");
 }
 EXPORT_SYMBOL(_outsl_ns);
+
+#define IO_CHECK_ALIGN(v,a) ((((unsigned long)(v)) & ((a) - 1)) == 0)
+
+notrace void
+_memset_io(volatile void __iomem *addr, int c, unsigned long n)
+{
+       void *p = (void __force *)addr;
+       u32 lc = c;
+       lc |= lc << 8;
+       lc |= lc << 16;
+
+       __asm__ __volatile__ ("sync" : : : "memory");
+       while(n && !IO_CHECK_ALIGN(p, 4)) {
+               *((volatile u8 *)p) = c;
+               p++;
+               n--;
+       }
+       while(n >= 4) {
+               *((volatile u32 *)p) = lc;
+               p += 4;
+               n -= 4;
+       }
+       while(n) {
+               *((volatile u8 *)p) = c;
+               p++;
+               n--;
+       }
+       __asm__ __volatile__ ("sync" : : : "memory");
+}
+EXPORT_SYMBOL(_memset_io);
+
+void _memcpy_fromio(void *dest, const volatile void __iomem *src,
+                   unsigned long n)
+{
+       void *vsrc = (void __force *) src;
+
+       __asm__ __volatile__ ("sync" : : : "memory");
+       while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) {
+               *((u8 *)dest) = *((volatile u8 *)vsrc);
+               eieio();
+               vsrc++;
+               dest++;
+               n--;
+       }
+       while(n > 4) {
+               *((u32 *)dest) = *((volatile u32 *)vsrc);
+               eieio();
+               vsrc += 4;
+               dest += 4;
+               n -= 4;
+       }
+       while(n) {
+               *((u8 *)dest) = *((volatile u8 *)vsrc);
+               eieio();
+               vsrc++;
+               dest++;
+               n--;
+       }
+       __asm__ __volatile__ ("sync" : : : "memory");
+}
+EXPORT_SYMBOL(_memcpy_fromio);
+
+void _memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n)
+{
+       void *vdest = (void __force *) dest;
+
+       __asm__ __volatile__ ("sync" : : : "memory");
+       while(n && (!IO_CHECK_ALIGN(vdest, 4) || !IO_CHECK_ALIGN(src, 4))) {
+               *((volatile u8 *)vdest) = *((u8 *)src);
+               src++;
+               vdest++;
+               n--;
+       }
+       while(n > 4) {
+               *((volatile u32 *)vdest) = *((volatile u32 *)src);
+               src += 4;
+               vdest += 4;
+               n-=4;
+       }
+       while(n) {
+               *((volatile u8 *)vdest) = *((u8 *)src);
+               src++;
+               vdest++;
+               n--;
+       }
+       __asm__ __volatile__ ("sync" : : : "memory");
+}
+EXPORT_SYMBOL(_memcpy_toio);