0001
0002
0003
0004
0005
0006
0007 #include <linux/types.h>
0008 #include <asm/udbg.h>
0009 #include <asm/io.h>
0010 #include <asm/reg_a2.h>
0011
0012 extern u8 real_readb(volatile u8 __iomem *addr);
0013 extern void real_writeb(u8 data, volatile u8 __iomem *addr);
0014 extern u8 real_205_readb(volatile u8 __iomem *addr);
0015 extern void real_205_writeb(u8 data, volatile u8 __iomem *addr);
0016
0017 #define UART_RBR 0
0018 #define UART_IER 1
0019 #define UART_FCR 2
0020 #define UART_LCR 3
0021 #define UART_MCR 4
0022 #define UART_LSR 5
0023 #define UART_MSR 6
0024 #define UART_SCR 7
0025 #define UART_THR UART_RBR
0026 #define UART_IIR UART_FCR
0027 #define UART_DLL UART_RBR
0028 #define UART_DLM UART_IER
0029 #define UART_DLAB UART_LCR
0030
0031 #define LSR_DR 0x01
0032 #define LSR_OE 0x02
0033 #define LSR_PE 0x04
0034 #define LSR_FE 0x08
0035 #define LSR_BI 0x10
0036 #define LSR_THRE 0x20
0037 #define LSR_TEMT 0x40
0038 #define LSR_ERR 0x80
0039
0040 #define LCR_DLAB 0x80
0041
0042 static u8 (*udbg_uart_in)(unsigned int reg);
0043 static void (*udbg_uart_out)(unsigned int reg, u8 data);
0044
0045 static void udbg_uart_flush(void)
0046 {
0047 if (!udbg_uart_in)
0048 return;
0049
0050
0051 while ((udbg_uart_in(UART_LSR) & LSR_THRE) == 0)
0052 cpu_relax();
0053 }
0054
0055 static void udbg_uart_putc(char c)
0056 {
0057 if (!udbg_uart_out)
0058 return;
0059
0060 if (c == '\n')
0061 udbg_uart_putc('\r');
0062 udbg_uart_flush();
0063 udbg_uart_out(UART_THR, c);
0064 }
0065
0066 static int udbg_uart_getc_poll(void)
0067 {
0068 if (!udbg_uart_in)
0069 return -1;
0070
0071 if (!(udbg_uart_in(UART_LSR) & LSR_DR))
0072 return udbg_uart_in(UART_RBR);
0073
0074 return -1;
0075 }
0076
0077 static int udbg_uart_getc(void)
0078 {
0079 if (!udbg_uart_in)
0080 return -1;
0081
0082 while (!(udbg_uart_in(UART_LSR) & LSR_DR))
0083 cpu_relax();
0084 return udbg_uart_in(UART_RBR);
0085 }
0086
0087 static void __init udbg_use_uart(void)
0088 {
0089 udbg_putc = udbg_uart_putc;
0090 udbg_flush = udbg_uart_flush;
0091 udbg_getc = udbg_uart_getc;
0092 udbg_getc_poll = udbg_uart_getc_poll;
0093 }
0094
0095 void __init udbg_uart_setup(unsigned int speed, unsigned int clock)
0096 {
0097 unsigned int dll, base_bauds;
0098
0099 if (!udbg_uart_out)
0100 return;
0101
0102 if (clock == 0)
0103 clock = 1843200;
0104 if (speed == 0)
0105 speed = 9600;
0106
0107 base_bauds = clock / 16;
0108 dll = base_bauds / speed;
0109
0110 udbg_uart_out(UART_LCR, 0x00);
0111 udbg_uart_out(UART_IER, 0xff);
0112 udbg_uart_out(UART_IER, 0x00);
0113 udbg_uart_out(UART_LCR, LCR_DLAB);
0114 udbg_uart_out(UART_DLL, dll & 0xff);
0115 udbg_uart_out(UART_DLM, dll >> 8);
0116
0117 udbg_uart_out(UART_LCR, 0x3);
0118
0119 udbg_uart_out(UART_MCR, 0x3);
0120
0121 udbg_uart_out(UART_FCR, 0x7);
0122 }
0123
0124 unsigned int __init udbg_probe_uart_speed(unsigned int clock)
0125 {
0126 unsigned int dll, dlm, divisor, prescaler, speed;
0127 u8 old_lcr;
0128
0129 old_lcr = udbg_uart_in(UART_LCR);
0130
0131
0132 udbg_uart_out(UART_LCR, old_lcr | LCR_DLAB);
0133
0134
0135 dll = udbg_uart_in(UART_DLL);
0136 dlm = udbg_uart_in(UART_DLM);
0137 divisor = dlm << 8 | dll;
0138
0139
0140 if (udbg_uart_in(UART_MCR) & 0x80)
0141 prescaler = 4;
0142 else
0143 prescaler = 1;
0144
0145
0146 udbg_uart_out(UART_LCR, old_lcr);
0147
0148
0149 speed = (clock / prescaler) / (divisor * 16);
0150
0151
0152 if (speed > (clock / 16))
0153 speed = 9600;
0154
0155 return speed;
0156 }
0157
0158 static union {
0159 unsigned char __iomem *mmio_base;
0160 unsigned long pio_base;
0161 } udbg_uart;
0162
0163 static unsigned int udbg_uart_stride = 1;
0164
0165 static u8 udbg_uart_in_pio(unsigned int reg)
0166 {
0167 return inb(udbg_uart.pio_base + (reg * udbg_uart_stride));
0168 }
0169
0170 static void udbg_uart_out_pio(unsigned int reg, u8 data)
0171 {
0172 outb(data, udbg_uart.pio_base + (reg * udbg_uart_stride));
0173 }
0174
0175 void __init udbg_uart_init_pio(unsigned long port, unsigned int stride)
0176 {
0177 if (!port)
0178 return;
0179 udbg_uart.pio_base = port;
0180 udbg_uart_stride = stride;
0181 udbg_uart_in = udbg_uart_in_pio;
0182 udbg_uart_out = udbg_uart_out_pio;
0183 udbg_use_uart();
0184 }
0185
0186 static u8 udbg_uart_in_mmio(unsigned int reg)
0187 {
0188 return in_8(udbg_uart.mmio_base + (reg * udbg_uart_stride));
0189 }
0190
0191 static void udbg_uart_out_mmio(unsigned int reg, u8 data)
0192 {
0193 out_8(udbg_uart.mmio_base + (reg * udbg_uart_stride), data);
0194 }
0195
0196
0197 void __init udbg_uart_init_mmio(void __iomem *addr, unsigned int stride)
0198 {
0199 if (!addr)
0200 return;
0201 udbg_uart.mmio_base = addr;
0202 udbg_uart_stride = stride;
0203 udbg_uart_in = udbg_uart_in_mmio;
0204 udbg_uart_out = udbg_uart_out_mmio;
0205 udbg_use_uart();
0206 }
0207
0208 #ifdef CONFIG_PPC_MAPLE
0209
0210 #define UDBG_UART_MAPLE_ADDR ((void __iomem *)0xf40003f8)
0211
0212 static u8 udbg_uart_in_maple(unsigned int reg)
0213 {
0214 return real_readb(UDBG_UART_MAPLE_ADDR + reg);
0215 }
0216
0217 static void udbg_uart_out_maple(unsigned int reg, u8 val)
0218 {
0219 real_writeb(val, UDBG_UART_MAPLE_ADDR + reg);
0220 }
0221
0222 void __init udbg_init_maple_realmode(void)
0223 {
0224 udbg_uart_in = udbg_uart_in_maple;
0225 udbg_uart_out = udbg_uart_out_maple;
0226 udbg_use_uart();
0227 }
0228
0229 #endif
0230
0231 #ifdef CONFIG_PPC_PASEMI
0232
0233 #define UDBG_UART_PAS_ADDR ((void __iomem *)0xfcff03f8UL)
0234
0235 static u8 udbg_uart_in_pas(unsigned int reg)
0236 {
0237 return real_205_readb(UDBG_UART_PAS_ADDR + reg);
0238 }
0239
0240 static void udbg_uart_out_pas(unsigned int reg, u8 val)
0241 {
0242 real_205_writeb(val, UDBG_UART_PAS_ADDR + reg);
0243 }
0244
0245 void __init udbg_init_pas_realmode(void)
0246 {
0247 udbg_uart_in = udbg_uart_in_pas;
0248 udbg_uart_out = udbg_uart_out_pas;
0249 udbg_use_uart();
0250 }
0251
0252 #endif
0253
0254 #ifdef CONFIG_PPC_EARLY_DEBUG_44x
0255
0256 #include <platforms/44x/44x.h>
0257
0258 static u8 udbg_uart_in_44x_as1(unsigned int reg)
0259 {
0260 return as1_readb((void __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR + reg);
0261 }
0262
0263 static void udbg_uart_out_44x_as1(unsigned int reg, u8 val)
0264 {
0265 as1_writeb(val, (void __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR + reg);
0266 }
0267
0268 void __init udbg_init_44x_as1(void)
0269 {
0270 udbg_uart_in = udbg_uart_in_44x_as1;
0271 udbg_uart_out = udbg_uart_out_44x_as1;
0272 udbg_use_uart();
0273 }
0274
0275 #endif
0276
0277 #ifdef CONFIG_PPC_EARLY_DEBUG_40x
0278
0279 static u8 udbg_uart_in_40x(unsigned int reg)
0280 {
0281 return real_readb((void __iomem *)CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR
0282 + reg);
0283 }
0284
0285 static void udbg_uart_out_40x(unsigned int reg, u8 val)
0286 {
0287 real_writeb(val, (void __iomem *)CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR
0288 + reg);
0289 }
0290
0291 void __init udbg_init_40x_realmode(void)
0292 {
0293 udbg_uart_in = udbg_uart_in_40x;
0294 udbg_uart_out = udbg_uart_out_40x;
0295 udbg_use_uart();
0296 }
0297
0298 #endif
0299
0300 #ifdef CONFIG_PPC_EARLY_DEBUG_MICROWATT
0301
0302 #define UDBG_UART_MW_ADDR ((void __iomem *)0xc0002000)
0303
0304 static u8 udbg_uart_in_isa300_rm(unsigned int reg)
0305 {
0306 uint64_t msr = mfmsr();
0307 uint8_t c;
0308
0309 mtmsr(msr & ~(MSR_EE|MSR_DR));
0310 isync();
0311 eieio();
0312 c = __raw_rm_readb(UDBG_UART_MW_ADDR + (reg << 2));
0313 mtmsr(msr);
0314 isync();
0315 return c;
0316 }
0317
0318 static void udbg_uart_out_isa300_rm(unsigned int reg, u8 val)
0319 {
0320 uint64_t msr = mfmsr();
0321
0322 mtmsr(msr & ~(MSR_EE|MSR_DR));
0323 isync();
0324 eieio();
0325 __raw_rm_writeb(val, UDBG_UART_MW_ADDR + (reg << 2));
0326 mtmsr(msr);
0327 isync();
0328 }
0329
0330 void __init udbg_init_debug_microwatt(void)
0331 {
0332 udbg_uart_in = udbg_uart_in_isa300_rm;
0333 udbg_uart_out = udbg_uart_out_isa300_rm;
0334 udbg_use_uart();
0335 }
0336
0337 #endif