diff options
Diffstat (limited to 'arch/powerpc/kernel/udbg_16550.c')
-rw-r--r-- | arch/powerpc/kernel/udbg_16550.c | 63 |
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 | |||
46 | static volatile struct NS16550 __iomem *udbg_comport; | 48 | static volatile struct NS16550 __iomem *udbg_comport; |
47 | 49 | ||
48 | static void udbg_550_putc(unsigned char c) | 50 | static 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 | ||
80 | void udbg_init_uart(void __iomem *comport, unsigned int speed) | 82 | void 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 | ||
111 | unsigned 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 |
104 | void udbg_maple_real_putc(unsigned char c) | 147 | void udbg_maple_real_putc(unsigned char c) |
105 | { | 148 | { |