aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/legacy_serial.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-11-23 01:56:06 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-08 22:49:50 -0500
commit463ce0e103f419f51b1769111e73fe8bb305d0ec (patch)
treeb4ffced87b886d81b518790fcaf841dd006e8068 /arch/powerpc/kernel/legacy_serial.c
parentd1405b869850982f05c7ec0d3f137ca27588192f (diff)
[PATCH] powerpc: serial port discovery (#2)
This moves the discovery of legacy serial ports to a separate file, makes it common to ppc32 and ppc64, and reworks it to use the new OF address translators to get to the ports early. This new version can also detect some PCI serial cards using legacy chips and will probably match those discovered port with the default console choice. Only ppc64 gets udbg still yet, unifying udbg isn't finished yet. It also adds some speed-probing code to udbg so that the default console can come up at the same speed it was set to by the firmware. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/legacy_serial.c')
-rw-r--r--arch/powerpc/kernel/legacy_serial.c478
1 files changed, 478 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
new file mode 100644
index 000000000000..28ad50e424a9
--- /dev/null
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -0,0 +1,478 @@
1#include <linux/config.h>
2#include <linux/kernel.h>
3#include <linux/serial.h>
4#include <linux/serial_8250.h>
5#include <linux/serial_core.h>
6#include <linux/console.h>
7#include <linux/pci.h>
8#include <asm/io.h>
9#include <asm/mmu.h>
10#include <asm/prom.h>
11#include <asm/serial.h>
12#include <asm/udbg.h>
13#include <asm/pci-bridge.h>
14#include <asm/ppc-pci.h>
15
16#undef DEBUG
17
18#ifdef DEBUG
19#define DBG(fmt...) do { printk(fmt); } while(0)
20#else
21#define DBG(fmt...) do { } while(0)
22#endif
23
24#define MAX_LEGACY_SERIAL_PORTS 8
25
26static struct plat_serial8250_port
27legacy_serial_ports[MAX_LEGACY_SERIAL_PORTS+1];
28static struct legacy_serial_info {
29 struct device_node *np;
30 unsigned int speed;
31 unsigned int clock;
32 phys_addr_t taddr;
33} legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS];
34static unsigned int legacy_serial_count;
35static int legacy_serial_console = -1;
36
37static int __init add_legacy_port(struct device_node *np, int want_index,
38 int iotype, phys_addr_t base,
39 phys_addr_t taddr, unsigned long irq)
40{
41 u32 *clk, *spd, clock;
42 int index;
43
44 /* get clock freq. if present */
45 clk = (u32 *)get_property(np, "clock-frequency", NULL);
46 clock = clk ? *clk : BASE_BAUD * 16;
47
48 /* get default speed if present */
49 spd = (u32 *)get_property(np, "current-speed", NULL);
50
51 /* If we have a location index, then try to use it */
52 if (want_index >= 0 && want_index < MAX_LEGACY_SERIAL_PORTS)
53 index = want_index;
54 else
55 index = legacy_serial_count;
56
57 /* if our index is still out of range, that mean that
58 * array is full, we could scan for a free slot but that
59 * make little sense to bother, just skip the port
60 */
61 if (index >= MAX_LEGACY_SERIAL_PORTS)
62 return -1;
63 if (index >= legacy_serial_count)
64 legacy_serial_count = index + 1;
65
66 /* Check if there is a port who already claimed our slot */
67 if (legacy_serial_infos[index].np != 0) {
68 /* if we still have some room, move it, else override */
69 if (legacy_serial_count < MAX_LEGACY_SERIAL_PORTS) {
70 printk(KERN_INFO "Moved legacy port %d -> %d\n",
71 index, legacy_serial_count);
72 legacy_serial_ports[legacy_serial_count] =
73 legacy_serial_ports[index];
74 legacy_serial_infos[legacy_serial_count] =
75 legacy_serial_infos[index];
76 legacy_serial_count++;
77 } else {
78 printk(KERN_INFO "Replacing legacy port %d\n", index);
79 }
80 }
81
82 /* Now fill the entry */
83 memset(&legacy_serial_ports[index], 0,
84 sizeof(struct plat_serial8250_port));
85 if (iotype == UPIO_PORT)
86 legacy_serial_ports[index].iobase = base;
87 else
88 legacy_serial_ports[index].membase = (void __iomem *)base;
89 legacy_serial_ports[index].iotype = iotype;
90 legacy_serial_ports[index].uartclk = clock;
91 legacy_serial_ports[index].irq = irq;
92 legacy_serial_ports[index].flags = ASYNC_BOOT_AUTOCONF;
93 legacy_serial_infos[index].taddr = taddr;
94 legacy_serial_infos[index].np = of_node_get(np);
95 legacy_serial_infos[index].clock = clock;
96 legacy_serial_infos[index].speed = spd ? *spd : 0;
97
98 printk(KERN_INFO "Found legacy serial port %d for %s\n",
99 index, np->full_name);
100 printk(KERN_INFO " %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n",
101 (iotype == UPIO_PORT) ? "port" : "mem",
102 (unsigned long long)base, (unsigned long long)taddr, irq,
103 legacy_serial_ports[index].uartclk,
104 legacy_serial_infos[index].speed);
105
106 return index;
107}
108
109static int __init add_legacy_isa_port(struct device_node *np,
110 struct device_node *isa_bridge)
111{
112 u32 *reg;
113 char *typep;
114 int index = -1;
115 phys_addr_t taddr;
116
117 /* Get the ISA port number */
118 reg = (u32 *)get_property(np, "reg", NULL);
119 if (reg == NULL)
120 return -1;
121
122 /* Verify it's an IO port, we don't support anything else */
123 if (!(reg[0] & 0x00000001))
124 return -1;
125
126 /* Now look for an "ibm,aix-loc" property that gives us ordering
127 * if any...
128 */
129 typep = (char *)get_property(np, "ibm,aix-loc", NULL);
130
131 /* If we have a location index, then use it */
132 if (typep && *typep == 'S')
133 index = simple_strtol(typep+1, NULL, 0) - 1;
134
135 /* Translate ISA address */
136 taddr = of_translate_address(np, reg);
137
138 /* Add port, irq will be dealt with later */
139 return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, NO_IRQ);
140
141}
142
143static int __init add_legacy_pci_port(struct device_node *np,
144 struct device_node *pci_dev)
145{
146 phys_addr_t addr, base;
147 u32 *addrp;
148 int iotype, index = -1;
149
150#if 0
151 /* We only support ports that have a clock frequency properly
152 * encoded in the device-tree (that is have an fcode). Anything
153 * else can't be used that early and will be normally probed by
154 * the generic 8250_pci driver later on.
155 */
156 if (get_property(np, "clock-frequency", NULL) == NULL)
157 return -1;
158#endif
159
160 /* Get the PCI address. Assume BAR 0 */
161 addrp = of_get_pci_address(pci_dev, 0, NULL);
162 if (addrp == NULL)
163 return -1;
164
165 /* We only support BAR 0 for now */
166 iotype = (addrp[0] & 0x02000000) ? UPIO_MEM : UPIO_PORT;
167 addr = of_translate_address(pci_dev, addrp);
168
169 /* Set the IO base to the same as the translated address for MMIO,
170 * or to the domain local IO base for PIO (it will be fixed up later)
171 */
172 if (iotype == UPIO_MEM)
173 base = addr;
174 else
175 base = addrp[2];
176
177 /* Try to guess an index... If we have subdevices of the pci dev,
178 * we get to their "reg" property
179 */
180 if (np != pci_dev) {
181 u32 *reg = (u32 *)get_property(np, "reg", NULL);
182 if (reg && (*reg < 4))
183 index = legacy_serial_count + *reg;
184 }
185
186 /* Add port, irq will be dealt with later. We passed a translated
187 * IO port value. It will be fixed up later along with the irq
188 */
189 return add_legacy_port(np, index, iotype, base, addr, NO_IRQ);
190}
191
192/*
193 * This is called very early, as part of setup_system() or eventually
194 * setup_arch(), basically before anything else in this file. This function
195 * will try to build a list of all the available 8250-compatible serial ports
196 * in the machine using the Open Firmware device-tree. It currently only deals
197 * with ISA and PCI busses but could be extended. It allows a very early boot
198 * console to be initialized, that list is also used later to provide 8250 with
199 * the machine non-PCI ports and to properly pick the default console port
200 */
201void __init find_legacy_serial_ports(void)
202{
203 struct device_node *np, *stdout;
204 char *path;
205 int index;
206
207 DBG(" -> find_legacy_serial_port()\n");
208
209 /* Now find out if one of these is out firmware console */
210 path = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
211 if (path == NULL) {
212 DBG(" no linux,stdout-path !\n");
213 return;
214 }
215 stdout = of_find_node_by_path(path);
216 if (stdout) {
217 DBG("stdout is %s\n", stdout->full_name);
218 }
219
220 /* First fill our array with ISA ports */
221 for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
222 struct device_node *isa = of_get_parent(np);
223 if (isa && !strcmp(isa->name, "isa")) {
224 index = add_legacy_isa_port(np, isa);
225 if (index >= 0 && np == stdout)
226 legacy_serial_console = index;
227 }
228 of_node_put(isa);
229 }
230
231 /* Next, try to locate PCI ports */
232 for (np = NULL; (np = of_find_all_nodes(np));) {
233 struct device_node *pci, *parent = of_get_parent(np);
234 if (parent && !strcmp(parent->name, "isa")) {
235 of_node_put(parent);
236 continue;
237 }
238 if (strcmp(np->name, "serial") && strcmp(np->type, "serial")) {
239 of_node_put(parent);
240 continue;
241 }
242 /* Check for known pciclass, and also check wether we have
243 * a device with child nodes for ports or not
244 */
245 if (device_is_compatible(np, "pciclass,0700") ||
246 device_is_compatible(np, "pciclass,070002"))
247 pci = np;
248 else if (device_is_compatible(parent, "pciclass,0700") ||
249 device_is_compatible(parent, "pciclass,070002"))
250 pci = parent;
251 else {
252 of_node_put(parent);
253 continue;
254 }
255 index = add_legacy_pci_port(np, pci);
256 if (index >= 0 && np == stdout)
257 legacy_serial_console = index;
258 of_node_put(parent);
259 }
260
261 DBG("legacy_serial_console = %d\n", legacy_serial_console);
262
263 /* udbg is 64 bits only for now, that will change soon though ... */
264#ifdef CONFIG_PPC64
265 while (legacy_serial_console >= 0) {
266 struct legacy_serial_info *info =
267 &legacy_serial_infos[legacy_serial_console];
268 void __iomem *addr;
269
270 if (info->taddr == 0)
271 break;
272 addr = ioremap(info->taddr, 0x1000);
273 if (addr == NULL)
274 break;
275 if (info->speed == 0)
276 info->speed = udbg_probe_uart_speed(addr, info->clock);
277 DBG("default console speed = %d\n", info->speed);
278 udbg_init_uart(addr, info->speed, info->clock);
279 break;
280 }
281#endif /* CONFIG_PPC64 */
282
283 DBG(" <- find_legacy_serial_port()\n");
284}
285
286static struct platform_device serial_device = {
287 .name = "serial8250",
288 .id = PLAT8250_DEV_PLATFORM,
289 .dev = {
290 .platform_data = legacy_serial_ports,
291 },
292};
293
294static void __init fixup_port_irq(int index,
295 struct device_node *np,
296 struct plat_serial8250_port *port)
297{
298 DBG("fixup_port_irq(%d)\n", index);
299
300 /* Check for interrupts in that node */
301 if (np->n_intrs > 0) {
302 port->irq = np->intrs[0].line;
303 DBG(" port %d (%s), irq=%d\n",
304 index, np->full_name, port->irq);
305 return;
306 }
307
308 /* Check for interrupts in the parent */
309 np = of_get_parent(np);
310 if (np == NULL)
311 return;
312
313 if (np->n_intrs > 0) {
314 port->irq = np->intrs[0].line;
315 DBG(" port %d (%s), irq=%d\n",
316 index, np->full_name, port->irq);
317 }
318 of_node_put(np);
319}
320
321static void __init fixup_port_pio(int index,
322 struct device_node *np,
323 struct plat_serial8250_port *port)
324{
325 struct pci_controller *hose;
326
327 DBG("fixup_port_pio(%d)\n", index);
328
329 hose = pci_find_hose_for_OF_device(np);
330 if (hose) {
331 unsigned long offset = (unsigned long)hose->io_base_virt -
332#ifdef CONFIG_PPC64
333 pci_io_base;
334#else
335 isa_io_base;
336#endif
337 DBG("port %d, IO %lx -> %lx\n",
338 index, port->iobase, port->iobase + offset);
339 port->iobase += offset;
340 }
341}
342
343/*
344 * This is called as an arch initcall, hopefully before the PCI bus is
345 * probed and/or the 8250 driver loaded since we need to register our
346 * platform devices before 8250 PCI ones are detected as some of them
347 * must properly "override" the platform ones.
348 *
349 * This function fixes up the interrupt value for platform ports as it
350 * couldn't be done earlier before interrupt maps have been parsed. It
351 * also "corrects" the IO address for PIO ports for the same reason,
352 * since earlier, the PHBs virtual IO space wasn't assigned yet. It then
353 * registers all those platform ports for use by the 8250 driver when it
354 * finally loads.
355 */
356static int __init serial_dev_init(void)
357{
358 int i;
359
360 if (legacy_serial_count == 0)
361 return -ENODEV;
362
363 /*
364 * Before we register the platfrom serial devices, we need
365 * to fixup their interrutps and their IO ports.
366 */
367 DBG("Fixing serial ports interrupts and IO ports ...\n");
368
369 for (i = 0; i < legacy_serial_count; i++) {
370 struct plat_serial8250_port *port = &legacy_serial_ports[i];
371 struct device_node *np = legacy_serial_infos[i].np;
372
373 if (port->irq == NO_IRQ)
374 fixup_port_irq(i, np, port);
375 if (port->iotype == UPIO_PORT)
376 fixup_port_pio(i, np, port);
377 }
378
379 DBG("Registering platform serial ports\n");
380
381 return platform_device_register(&serial_device);
382}
383arch_initcall(serial_dev_init);
384
385
386/*
387 * This is called very early, as part of console_init() (typically just after
388 * time_init()). This function is respondible for trying to find a good
389 * default console on serial ports. It tries to match the open firmware
390 * default output with one of the available serial console drivers, either
391 * one of the platform serial ports that have been probed earlier by
392 * find_legacy_serial_ports() or some more platform specific ones.
393 */
394static int __init check_legacy_serial_console(void)
395{
396 struct device_node *prom_stdout = NULL;
397 int speed = 0, offset = 0;
398 char *name;
399 u32 *spd;
400
401 DBG(" -> check_legacy_serial_console()\n");
402
403 /* The user has requested a console so this is already set up. */
404 if (strstr(saved_command_line, "console=")) {
405 DBG(" console was specified !\n");
406 return -EBUSY;
407 }
408
409 if (!of_chosen) {
410 DBG(" of_chosen is NULL !\n");
411 return -ENODEV;
412 }
413 /* We are getting a weird phandle from OF ... */
414 /* ... So use the full path instead */
415 name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
416 if (name == NULL) {
417 DBG(" no linux,stdout-path !\n");
418 return -ENODEV;
419 }
420 prom_stdout = of_find_node_by_path(name);
421 if (!prom_stdout) {
422 DBG(" can't find stdout package %s !\n", name);
423 return -ENODEV;
424 }
425 DBG("stdout is %s\n", prom_stdout->full_name);
426
427 name = (char *)get_property(prom_stdout, "name", NULL);
428 if (!name) {
429 DBG(" stdout package has no name !\n");
430 goto not_found;
431 }
432 spd = (u32 *)get_property(prom_stdout, "current-speed", NULL);
433 if (spd)
434 speed = *spd;
435
436 if (0)
437 ;
438#ifdef CONFIG_SERIAL_8250_CONSOLE
439 else if (strcmp(name, "serial") == 0) {
440 int i;
441 /* Look for it in probed array */
442 for (i = 0; i < legacy_serial_count; i++) {
443 if (prom_stdout != legacy_serial_infos[i].np)
444 continue;
445 offset = i;
446 speed = legacy_serial_infos[i].speed;
447 break;
448 }
449 if (i >= legacy_serial_count)
450 goto not_found;
451 }
452#endif /* CONFIG_SERIAL_8250_CONSOLE */
453#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
454 else if (strcmp(name, "ch-a") == 0)
455 offset = 0;
456 else if (strcmp(name, "ch-b") == 0)
457 offset = 1;
458#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
459 else
460 goto not_found;
461 of_node_put(prom_stdout);
462
463 DBG("Found serial console at ttyS%d\n", offset);
464
465 if (speed) {
466 static char __initdata opt[16];
467 sprintf(opt, "%d", speed);
468 return add_preferred_console("ttyS", offset, opt);
469 } else
470 return add_preferred_console("ttyS", offset, NULL);
471
472 not_found:
473 DBG("No preferred console found !\n");
474 of_node_put(prom_stdout);
475 return -ENODEV;
476}
477console_initcall(check_legacy_serial_console);
478