| /* |
| * include/asm-arm/arch-ns9xxx/uncompress.h |
| * |
| * Copyright (C) 2006 by Digi International Inc. |
| * All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 as published by |
| * the Free Software Foundation. |
| */ |
| #ifndef __ASM_ARCH_UNCOMPRESS_H |
| #define __ASM_ARCH_UNCOMPRESS_H |
| |
| #include <asm/io.h> |
| |
| #define __REG(x) ((void __iomem __force *)(x)) |
| |
| static void putc_dummy(char c, void __iomem *base) |
| { |
| /* nothing */ |
| } |
| |
| static void putc_ns9360(char c, void __iomem *base) |
| { |
| static int t = 0x10000; |
| do { |
| if (t) |
| --t; |
| |
| if (__raw_readl(base + 8) & (1 << 3)) { |
| __raw_writeb(c, base + 16); |
| t = 0x10000; |
| break; |
| } |
| } while (t); |
| } |
| |
| static void putc_a9m9750dev(char c, void __iomem *base) |
| { |
| static int t = 0x10000; |
| do { |
| if (t) |
| --t; |
| |
| if (__raw_readb(base + 5) & (1 << 5)) { |
| __raw_writeb(c, base); |
| t = 0x10000; |
| break; |
| } |
| } while (t); |
| |
| } |
| |
| static void putc_ns921x(char c, void __iomem *base) |
| { |
| static int t = 0x10000; |
| do { |
| if (t) |
| --t; |
| |
| if (!(__raw_readl(base) & (1 << 11))) { |
| __raw_writeb(c, base + 0x0028); |
| t = 0x10000; |
| break; |
| } |
| } while (t); |
| } |
| |
| #define MSCS __REG(0xA0900184) |
| |
| #define NS9360_UARTA __REG(0x90200040) |
| #define NS9360_UARTB __REG(0x90200000) |
| #define NS9360_UARTC __REG(0x90300000) |
| #define NS9360_UARTD __REG(0x90300040) |
| |
| #define NS9360_UART_ENABLED(base) \ |
| (__raw_readl(NS9360_UARTA) & (1 << 31)) |
| |
| #define A9M9750DEV_UARTA __REG(0x40000000) |
| |
| #define NS921XSYS_CLOCK __REG(0xa090017c) |
| #define NS921X_UARTA __REG(0x90010000) |
| #define NS921X_UARTB __REG(0x90018000) |
| #define NS921X_UARTC __REG(0x90020000) |
| #define NS921X_UARTD __REG(0x90028000) |
| |
| #define NS921X_UART_ENABLED(base) \ |
| (__raw_readl((base) + 0x1000) & (1 << 29)) |
| |
| static void autodetect(void (**putc)(char, void __iomem *), void __iomem **base) |
| { |
| if (((__raw_readl(MSCS) >> 16) & 0xfe) == 0x00) { |
| /* ns9360 or ns9750 */ |
| if (NS9360_UART_ENABLED(NS9360_UARTA)) { |
| *putc = putc_ns9360; |
| *base = NS9360_UARTA; |
| return; |
| } else if (NS9360_UART_ENABLED(NS9360_UARTB)) { |
| *putc = putc_ns9360; |
| *base = NS9360_UARTB; |
| return; |
| } else if (NS9360_UART_ENABLED(NS9360_UARTC)) { |
| *putc = putc_ns9360; |
| *base = NS9360_UARTC; |
| return; |
| } else if (NS9360_UART_ENABLED(NS9360_UARTD)) { |
| *putc = putc_ns9360; |
| *base = NS9360_UARTD; |
| return; |
| } else if (__raw_readl(__REG(0xa09001f4)) == 0xfffff001) { |
| *putc = putc_a9m9750dev; |
| *base = A9M9750DEV_UARTA; |
| return; |
| } |
| } else if (((__raw_readl(MSCS) >> 16) & 0xfe) == 0x02) { |
| /* ns921x */ |
| u32 clock = __raw_readl(NS921XSYS_CLOCK); |
| |
| if ((clock & (1 << 1)) && |
| NS921X_UART_ENABLED(NS921X_UARTA)) { |
| *putc = putc_ns921x; |
| *base = NS921X_UARTA; |
| return; |
| } else if ((clock & (1 << 2)) && |
| NS921X_UART_ENABLED(NS921X_UARTB)) { |
| *putc = putc_ns921x; |
| *base = NS921X_UARTB; |
| return; |
| } else if ((clock & (1 << 3)) && |
| NS921X_UART_ENABLED(NS921X_UARTC)) { |
| *putc = putc_ns921x; |
| *base = NS921X_UARTC; |
| return; |
| } else if ((clock & (1 << 4)) && |
| NS921X_UART_ENABLED(NS921X_UARTD)) { |
| *putc = putc_ns921x; |
| *base = NS921X_UARTD; |
| return; |
| } |
| } |
| |
| *putc = putc_dummy; |
| } |
| |
| void (*myputc)(char, void __iomem *); |
| void __iomem *base; |
| |
| static void putc(char c) |
| { |
| myputc(c, base); |
| } |
| |
| static void arch_decomp_setup(void) |
| { |
| autodetect(&myputc, &base); |
| } |
| #define arch_decomp_wdog() |
| |
| static void flush(void) |
| { |
| /* nothing */ |
| } |
| |
| #endif /* ifndef __ASM_ARCH_UNCOMPRESS_H */ |