aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/udbg_16550.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/udbg_16550.c')
-rw-r--r--arch/powerpc/kernel/udbg_16550.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 9313574ab935..50fd376446c9 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -43,6 +43,8 @@ struct NS16550 {
43#define LSR_TEMT 0x40 /* Xmitter empty */ 43#define LSR_TEMT 0x40 /* Xmitter empty */
44#define LSR_ERR 0x80 /* Error */ 44#define LSR_ERR 0x80 /* Error */
45 45
46#define LCR_DLAB 0x80
47
46static volatile struct NS16550 __iomem *udbg_comport; 48static volatile struct NS16550 __iomem *udbg_comport;
47 49
48static void udbg_550_putc(unsigned char c) 50static void udbg_550_putc(unsigned char c)
@@ -77,29 +79,70 @@ static unsigned char udbg_550_getc(void)
77 return 0; 79 return 0;
78} 80}
79 81
80void udbg_init_uart(void __iomem *comport, unsigned int speed) 82void udbg_init_uart(void __iomem *comport, unsigned int speed,
83 unsigned int clock)
81{ 84{
82 u16 dll = speed ? (115200 / speed) : 12; 85 unsigned int dll, base_bauds = clock / 16;
86
87 if (speed == 0)
88 speed = 9600;
89 dll = base_bauds / speed;
83 90
84 if (comport) { 91 if (comport) {
85 udbg_comport = (struct NS16550 __iomem *)comport; 92 udbg_comport = (struct NS16550 __iomem *)comport;
86 out_8(&udbg_comport->lcr, 0x00); 93 out_8(&udbg_comport->lcr, 0x00);
87 out_8(&udbg_comport->ier, 0xff); 94 out_8(&udbg_comport->ier, 0xff);
88 out_8(&udbg_comport->ier, 0x00); 95 out_8(&udbg_comport->ier, 0x00);
89 out_8(&udbg_comport->lcr, 0x80); /* Access baud rate */ 96 out_8(&udbg_comport->lcr, LCR_DLAB);
90 out_8(&udbg_comport->dll, dll & 0xff); /* 1 = 115200, 2 = 57600, 97 out_8(&udbg_comport->dll, dll & 0xff);
91 3 = 38400, 12 = 9600 baud */ 98 out_8(&udbg_comport->dlm, dll >> 8);
92 out_8(&udbg_comport->dlm, dll >> 8); /* dll >> 8 which should be zero 99 /* 8 data, 1 stop, no parity */
93 for fast rates; */ 100 out_8(&udbg_comport->lcr, 0x03);
94 out_8(&udbg_comport->lcr, 0x03); /* 8 data, 1 stop, no parity */ 101 /* RTS/DTR */
95 out_8(&udbg_comport->mcr, 0x03); /* RTS/DTR */ 102 out_8(&udbg_comport->mcr, 0x03);
96 out_8(&udbg_comport->fcr ,0x07); /* Clear & enable FIFOs */ 103 /* Clear & enable FIFOs */
104 out_8(&udbg_comport->fcr ,0x07);
97 udbg_putc = udbg_550_putc; 105 udbg_putc = udbg_550_putc;
98 udbg_getc = udbg_550_getc; 106 udbg_getc = udbg_550_getc;
99 udbg_getc_poll = udbg_550_getc_poll; 107 udbg_getc_poll = udbg_550_getc_poll;
100 } 108 }
101} 109}
102 110
111unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock)
112{
113 unsigned int dll, dlm, divisor, prescaler, speed;
114 u8 old_lcr;
115 volatile struct NS16550 __iomem *port = comport;
116
117 old_lcr = in_8(&port->lcr);
118
119 /* select divisor latch registers. */
120 out_8(&port->lcr, LCR_DLAB);
121
122 /* now, read the divisor */
123 dll = in_8(&port->dll);
124 dlm = in_8(&port->dlm);
125 divisor = dlm << 8 | dll;
126
127 /* check prescaling */
128 if (in_8(&port->mcr) & 0x80)
129 prescaler = 4;
130 else
131 prescaler = 1;
132
133 /* restore the LCR */
134 out_8(&port->lcr, old_lcr);
135
136 /* calculate speed */
137 speed = (clock / prescaler) / (divisor * 16);
138
139 /* sanity check */
140 if (speed < 9600 || speed > 115200)
141 speed = 9600;
142
143 return speed;
144}
145
103#ifdef CONFIG_PPC_MAPLE 146#ifdef CONFIG_PPC_MAPLE
104void udbg_maple_real_putc(unsigned char c) 147void udbg_maple_real_putc(unsigned char c)
105{ 148{