135cd8785SDavid Gibson /* 235cd8785SDavid Gibson * udbg for for NS16550 compatable serial ports 335cd8785SDavid Gibson * 435cd8785SDavid Gibson * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp 535cd8785SDavid Gibson * 635cd8785SDavid Gibson * This program is free software; you can redistribute it and/or 735cd8785SDavid Gibson * modify it under the terms of the GNU General Public License 835cd8785SDavid Gibson * as published by the Free Software Foundation; either version 935cd8785SDavid Gibson * 2 of the License, or (at your option) any later version. 1035cd8785SDavid Gibson */ 1135cd8785SDavid Gibson #include <linux/config.h> 1235cd8785SDavid Gibson #include <linux/types.h> 1335cd8785SDavid Gibson #include <asm/udbg.h> 1435cd8785SDavid Gibson #include <asm/io.h> 1535cd8785SDavid Gibson 1635cd8785SDavid Gibson extern u8 real_readb(volatile u8 __iomem *addr); 1735cd8785SDavid Gibson extern void real_writeb(u8 data, volatile u8 __iomem *addr); 1835cd8785SDavid Gibson 1935cd8785SDavid Gibson struct NS16550 { 2035cd8785SDavid Gibson /* this struct must be packed */ 2135cd8785SDavid Gibson unsigned char rbr; /* 0 */ 2235cd8785SDavid Gibson unsigned char ier; /* 1 */ 2335cd8785SDavid Gibson unsigned char fcr; /* 2 */ 2435cd8785SDavid Gibson unsigned char lcr; /* 3 */ 2535cd8785SDavid Gibson unsigned char mcr; /* 4 */ 2635cd8785SDavid Gibson unsigned char lsr; /* 5 */ 2735cd8785SDavid Gibson unsigned char msr; /* 6 */ 2835cd8785SDavid Gibson unsigned char scr; /* 7 */ 2935cd8785SDavid Gibson }; 3035cd8785SDavid Gibson 3135cd8785SDavid Gibson #define thr rbr 3235cd8785SDavid Gibson #define iir fcr 3335cd8785SDavid Gibson #define dll rbr 3435cd8785SDavid Gibson #define dlm ier 3535cd8785SDavid Gibson #define dlab lcr 3635cd8785SDavid Gibson 3735cd8785SDavid Gibson #define LSR_DR 0x01 /* Data ready */ 3835cd8785SDavid Gibson #define LSR_OE 0x02 /* Overrun */ 3935cd8785SDavid Gibson #define LSR_PE 0x04 /* Parity error */ 4035cd8785SDavid Gibson #define LSR_FE 0x08 /* Framing error */ 4135cd8785SDavid Gibson #define LSR_BI 0x10 /* Break */ 4235cd8785SDavid Gibson #define LSR_THRE 0x20 /* Xmit holding register empty */ 4335cd8785SDavid Gibson #define LSR_TEMT 0x40 /* Xmitter empty */ 4435cd8785SDavid Gibson #define LSR_ERR 0x80 /* Error */ 4535cd8785SDavid Gibson 4635cd8785SDavid Gibson static volatile struct NS16550 __iomem *udbg_comport; 4735cd8785SDavid Gibson 4835cd8785SDavid Gibson static void udbg_550_putc(unsigned char c) 4935cd8785SDavid Gibson { 5035cd8785SDavid Gibson if (udbg_comport) { 5135cd8785SDavid Gibson while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0) 5235cd8785SDavid Gibson /* wait for idle */; 5335cd8785SDavid Gibson out_8(&udbg_comport->thr, c); 5435cd8785SDavid Gibson if (c == '\n') 5535cd8785SDavid Gibson udbg_550_putc('\r'); 5635cd8785SDavid Gibson } 5735cd8785SDavid Gibson } 5835cd8785SDavid Gibson 5935cd8785SDavid Gibson static int udbg_550_getc_poll(void) 6035cd8785SDavid Gibson { 6135cd8785SDavid Gibson if (udbg_comport) { 6235cd8785SDavid Gibson if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0) 6335cd8785SDavid Gibson return in_8(&udbg_comport->rbr); 6435cd8785SDavid Gibson else 6535cd8785SDavid Gibson return -1; 6635cd8785SDavid Gibson } 6735cd8785SDavid Gibson return -1; 6835cd8785SDavid Gibson } 6935cd8785SDavid Gibson 7035cd8785SDavid Gibson static unsigned char udbg_550_getc(void) 7135cd8785SDavid Gibson { 7235cd8785SDavid Gibson if (udbg_comport) { 7335cd8785SDavid Gibson while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0) 7435cd8785SDavid Gibson /* wait for char */; 7535cd8785SDavid Gibson return in_8(&udbg_comport->rbr); 7635cd8785SDavid Gibson } 7735cd8785SDavid Gibson return 0; 7835cd8785SDavid Gibson } 7935cd8785SDavid Gibson 8035cd8785SDavid Gibson void udbg_init_uart(void __iomem *comport, unsigned int speed) 8135cd8785SDavid Gibson { 8235cd8785SDavid Gibson u16 dll = speed ? (115200 / speed) : 12; 8335cd8785SDavid Gibson 8435cd8785SDavid Gibson if (comport) { 8535cd8785SDavid Gibson udbg_comport = (struct NS16550 __iomem *)comport; 8635cd8785SDavid Gibson out_8(&udbg_comport->lcr, 0x00); 8735cd8785SDavid Gibson out_8(&udbg_comport->ier, 0xff); 8835cd8785SDavid Gibson out_8(&udbg_comport->ier, 0x00); 8935cd8785SDavid Gibson out_8(&udbg_comport->lcr, 0x80); /* Access baud rate */ 9035cd8785SDavid Gibson out_8(&udbg_comport->dll, dll & 0xff); /* 1 = 115200, 2 = 57600, 9135cd8785SDavid Gibson 3 = 38400, 12 = 9600 baud */ 9235cd8785SDavid Gibson out_8(&udbg_comport->dlm, dll >> 8); /* dll >> 8 which should be zero 9335cd8785SDavid Gibson for fast rates; */ 9435cd8785SDavid Gibson out_8(&udbg_comport->lcr, 0x03); /* 8 data, 1 stop, no parity */ 9535cd8785SDavid Gibson out_8(&udbg_comport->mcr, 0x03); /* RTS/DTR */ 9635cd8785SDavid Gibson out_8(&udbg_comport->fcr ,0x07); /* Clear & enable FIFOs */ 9735cd8785SDavid Gibson udbg_putc = udbg_550_putc; 9835cd8785SDavid Gibson udbg_getc = udbg_550_getc; 9935cd8785SDavid Gibson udbg_getc_poll = udbg_550_getc_poll; 10035cd8785SDavid Gibson } 10135cd8785SDavid Gibson } 10235cd8785SDavid Gibson 10335cd8785SDavid Gibson #ifdef CONFIG_PPC_MAPLE 10435cd8785SDavid Gibson void udbg_maple_real_putc(unsigned char c) 10535cd8785SDavid Gibson { 10635cd8785SDavid Gibson if (udbg_comport) { 10735cd8785SDavid Gibson while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) 10835cd8785SDavid Gibson /* wait for idle */; 10935cd8785SDavid Gibson real_writeb(c, &udbg_comport->thr); eieio(); 11035cd8785SDavid Gibson if (c == '\n') 11135cd8785SDavid Gibson udbg_maple_real_putc('\r'); 11235cd8785SDavid Gibson } 11335cd8785SDavid Gibson } 11435cd8785SDavid Gibson 11535cd8785SDavid Gibson void udbg_init_maple_realmode(void) 11635cd8785SDavid Gibson { 11735cd8785SDavid Gibson udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8; 11835cd8785SDavid Gibson 11935cd8785SDavid Gibson udbg_putc = udbg_maple_real_putc; 12035cd8785SDavid Gibson udbg_getc = NULL; 12135cd8785SDavid Gibson udbg_getc_poll = NULL; 12235cd8785SDavid Gibson } 12335cd8785SDavid Gibson #endif /* CONFIG_PPC_MAPLE */ 124