aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
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
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')
-rw-r--r--arch/powerpc/kernel/Makefile9
-rw-r--r--arch/powerpc/kernel/legacy_serial.c478
-rw-r--r--arch/powerpc/kernel/pci_64.c15
-rw-r--r--arch/powerpc/kernel/setup-common.c123
-rw-r--r--arch/powerpc/kernel/setup_32.c8
-rw-r--r--arch/powerpc/kernel/setup_64.c190
-rw-r--r--arch/powerpc/kernel/udbg.c2
-rw-r--r--arch/powerpc/kernel/udbg_16550.c63
8 files changed, 567 insertions, 321 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index aab0ae33a42a..bf3fd6f02249 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -33,10 +33,6 @@ obj-$(CONFIG_LPARCFG) += lparcfg.o
33obj-$(CONFIG_IBMVIO) += vio.o 33obj-$(CONFIG_IBMVIO) += vio.o
34obj-$(CONFIG_IBMEBUS) += ibmebus.o 34obj-$(CONFIG_IBMEBUS) += ibmebus.o
35obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o 35obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
36obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o
37obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o
38udbgscc-$(CONFIG_PPC64) := udbg_scc.o
39obj-$(CONFIG_PPC_PMAC) += $(udbgscc-y)
40obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o 36obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
41 37
42ifeq ($(CONFIG_PPC_MERGE),y) 38ifeq ($(CONFIG_PPC_MERGE),y)
@@ -59,14 +55,15 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o
59obj-$(CONFIG_6xx) += idle_6xx.o 55obj-$(CONFIG_6xx) += idle_6xx.o
60obj-$(CONFIG_SMP) += smp.o 56obj-$(CONFIG_SMP) += smp.o
61obj-$(CONFIG_KPROBES) += kprobes.o 57obj-$(CONFIG_KPROBES) += kprobes.o
62 58obj-$(CONFIG_PPC_MULTIPLATFORM) += legacy_serial.o
59obj64-$(CONFIG_PPC_MULTIPLATFORM) += udbg_16550.o
60obj64-$(CONFIG_PPC_PMAC) += udbg_scc.o
63module-$(CONFIG_PPC64) += module_64.o 61module-$(CONFIG_PPC64) += module_64.o
64obj-$(CONFIG_MODULES) += $(module-y) 62obj-$(CONFIG_MODULES) += $(module-y)
65 63
66pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ 64pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \
67 pci_direct_iommu.o iomap.o 65 pci_direct_iommu.o iomap.o
68obj-$(CONFIG_PCI) += $(pci64-y) 66obj-$(CONFIG_PCI) += $(pci64-y)
69
70kexec-$(CONFIG_PPC64) := machine_kexec_64.o 67kexec-$(CONFIG_PPC64) := machine_kexec_64.o
71kexec-$(CONFIG_PPC32) := machine_kexec_32.o 68kexec-$(CONFIG_PPC32) := machine_kexec_32.o
72obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y) 69obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y)
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
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 8b6008ab217d..9a80cdf9efeb 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -1223,6 +1223,7 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
1223} 1223}
1224EXPORT_SYMBOL(pcibios_fixup_device_resources); 1224EXPORT_SYMBOL(pcibios_fixup_device_resources);
1225 1225
1226
1226static void __devinit do_bus_setup(struct pci_bus *bus) 1227static void __devinit do_bus_setup(struct pci_bus *bus)
1227{ 1228{
1228 struct pci_dev *dev; 1229 struct pci_dev *dev;
@@ -1306,6 +1307,20 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
1306 *end = rsrc->end + offset; 1307 *end = rsrc->end + offset;
1307} 1308}
1308 1309
1310struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
1311{
1312 if (!have_of)
1313 return NULL;
1314 while(node) {
1315 struct pci_controller *hose, *tmp;
1316 list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
1317 if (hose->arch_data == node)
1318 return hose;
1319 node = node->parent;
1320 }
1321 return NULL;
1322}
1323
1309#endif /* CONFIG_PPC_MULTIPLATFORM */ 1324#endif /* CONFIG_PPC_MULTIPLATFORM */
1310 1325
1311 1326
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 6088a39edc26..a6d8aebf2bc6 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -294,129 +294,6 @@ struct seq_operations cpuinfo_op = {
294 .show = show_cpuinfo, 294 .show = show_cpuinfo,
295}; 295};
296 296
297#ifdef CONFIG_PPC_MULTIPLATFORM
298static int __init set_preferred_console(void)
299{
300 struct device_node *prom_stdout = NULL;
301 char *name;
302 u32 *spd;
303 int offset = 0;
304
305 DBG(" -> set_preferred_console()\n");
306
307 /* The user has requested a console so this is already set up. */
308 if (strstr(saved_command_line, "console=")) {
309 DBG(" console was specified !\n");
310 return -EBUSY;
311 }
312
313 if (!of_chosen) {
314 DBG(" of_chosen is NULL !\n");
315 return -ENODEV;
316 }
317 /* We are getting a weird phandle from OF ... */
318 /* ... So use the full path instead */
319 name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
320 if (name == NULL) {
321 DBG(" no linux,stdout-path !\n");
322 return -ENODEV;
323 }
324 prom_stdout = of_find_node_by_path(name);
325 if (!prom_stdout) {
326 DBG(" can't find stdout package %s !\n", name);
327 return -ENODEV;
328 }
329 DBG("stdout is %s\n", prom_stdout->full_name);
330
331 name = (char *)get_property(prom_stdout, "name", NULL);
332 if (!name) {
333 DBG(" stdout package has no name !\n");
334 goto not_found;
335 }
336 spd = (u32 *)get_property(prom_stdout, "current-speed", NULL);
337
338 if (0)
339 ;
340#ifdef CONFIG_SERIAL_8250_CONSOLE
341 else if (strcmp(name, "serial") == 0) {
342 int i;
343 u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
344 if (i > 8) {
345 switch (reg[1]) {
346 case 0x3f8:
347 offset = 0;
348 break;
349 case 0x2f8:
350 offset = 1;
351 break;
352 case 0x898:
353 offset = 2;
354 break;
355 case 0x890:
356 offset = 3;
357 break;
358 default:
359 /* We dont recognise the serial port */
360 goto not_found;
361 }
362 }
363 }
364#endif /* CONFIG_SERIAL_8250_CONSOLE */
365#ifdef CONFIG_PPC_PSERIES
366 else if (strcmp(name, "vty") == 0) {
367 u32 *reg = (u32 *)get_property(prom_stdout, "reg", NULL);
368 char *compat = (char *)get_property(prom_stdout, "compatible", NULL);
369
370 if (reg && compat && (strcmp(compat, "hvterm-protocol") == 0)) {
371 /* Host Virtual Serial Interface */
372 switch (reg[0]) {
373 case 0x30000000:
374 offset = 0;
375 break;
376 case 0x30000001:
377 offset = 1;
378 break;
379 default:
380 goto not_found;
381 }
382 of_node_put(prom_stdout);
383 DBG("Found hvsi console at offset %d\n", offset);
384 return add_preferred_console("hvsi", offset, NULL);
385 } else {
386 /* pSeries LPAR virtual console */
387 of_node_put(prom_stdout);
388 DBG("Found hvc console\n");
389 return add_preferred_console("hvc", 0, NULL);
390 }
391 }
392#endif /* CONFIG_PPC_PSERIES */
393#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
394 else if (strcmp(name, "ch-a") == 0)
395 offset = 0;
396 else if (strcmp(name, "ch-b") == 0)
397 offset = 1;
398#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
399 else
400 goto not_found;
401 of_node_put(prom_stdout);
402
403 DBG("Found serial console at ttyS%d\n", offset);
404
405 if (spd) {
406 static char __initdata opt[16];
407 sprintf(opt, "%d", *spd);
408 return add_preferred_console("ttyS", offset, opt);
409 } else
410 return add_preferred_console("ttyS", offset, NULL);
411
412 not_found:
413 DBG("No preferred console found !\n");
414 of_node_put(prom_stdout);
415 return -ENODEV;
416}
417console_initcall(set_preferred_console);
418#endif /* CONFIG_PPC_MULTIPLATFORM */
419
420void __init check_for_initrd(void) 297void __init check_for_initrd(void)
421{ 298{
422#ifdef CONFIG_BLK_DEV_INITRD 299#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index e5694335bf10..02baacf04366 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -39,6 +39,7 @@
39#include <asm/nvram.h> 39#include <asm/nvram.h>
40#include <asm/xmon.h> 40#include <asm/xmon.h>
41#include <asm/time.h> 41#include <asm/time.h>
42#include <asm/serial.h>
42 43
43#include "setup.h" 44#include "setup.h"
44 45
@@ -282,6 +283,13 @@ void __init setup_arch(char **cmdline_p)
282 283
283 unflatten_device_tree(); 284 unflatten_device_tree();
284 check_for_initrd(); 285 check_for_initrd();
286
287 if (ppc_md.init_early)
288 ppc_md.init_early();
289
290#ifdef CONFIG_PPC_MULTIPLATFORM
291 find_legacy_serial_ports();
292#endif
285 finish_device_tree(); 293 finish_device_tree();
286 294
287 smp_setup_cpu_maps(); 295 smp_setup_cpu_maps();
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index e3fb78397dc6..0fc442ad1d26 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -459,6 +459,15 @@ void __init setup_system(void)
459 */ 459 */
460 ppc_md.init_early(); 460 ppc_md.init_early();
461 461
462 /*
463 * We can discover serial ports now since the above did setup the
464 * hash table management for us, thus ioremap works. We do that early
465 * so that further code can be debugged
466 */
467#ifdef CONFIG_PPC_MULTIPLATFORM
468 find_legacy_serial_ports();
469#endif
470
462 /* 471 /*
463 * "Finish" the device-tree, that is do the actual parsing of 472 * "Finish" the device-tree, that is do the actual parsing of
464 * some of the properties like the interrupt map 473 * some of the properties like the interrupt map
@@ -657,187 +666,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
657 printk("[terminate]%04x %s\n", src, msg); 666 printk("[terminate]%04x %s\n", src, msg);
658} 667}
659 668
660#ifndef CONFIG_PPC_ISERIES
661/*
662 * This function can be used by platforms to "find" legacy serial ports.
663 * It works for "serial" nodes under an "isa" node, and will try to
664 * respect the "ibm,aix-loc" property if any. It works with up to 8
665 * ports.
666 */
667
668#define MAX_LEGACY_SERIAL_PORTS 8
669static struct plat_serial8250_port serial_ports[MAX_LEGACY_SERIAL_PORTS+1];
670static unsigned int old_serial_count;
671
672void __init generic_find_legacy_serial_ports(u64 *physport,
673 unsigned int *default_speed)
674{
675 struct device_node *np;
676 u32 *sizeprop;
677
678 struct isa_reg_property {
679 u32 space;
680 u32 address;
681 u32 size;
682 };
683 struct pci_reg_property {
684 struct pci_address addr;
685 u32 size_hi;
686 u32 size_lo;
687 };
688
689 DBG(" -> generic_find_legacy_serial_port()\n");
690
691 *physport = 0;
692 if (default_speed)
693 *default_speed = 0;
694
695 np = of_find_node_by_path("/");
696 if (!np)
697 return;
698
699 /* First fill our array */
700 for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
701 struct device_node *isa, *pci;
702 struct isa_reg_property *reg;
703 unsigned long phys_size, addr_size, io_base;
704 u32 *rangesp;
705 u32 *interrupts, *clk, *spd;
706 char *typep;
707 int index, rlen, rentsize;
708
709 /* Ok, first check if it's under an "isa" parent */
710 isa = of_get_parent(np);
711 if (!isa || strcmp(isa->name, "isa")) {
712 DBG("%s: no isa parent found\n", np->full_name);
713 continue;
714 }
715
716 /* Now look for an "ibm,aix-loc" property that gives us ordering
717 * if any...
718 */
719 typep = (char *)get_property(np, "ibm,aix-loc", NULL);
720
721 /* Get the ISA port number */
722 reg = (struct isa_reg_property *)get_property(np, "reg", NULL);
723 if (reg == NULL)
724 goto next_port;
725 /* We assume the interrupt number isn't translated ... */
726 interrupts = (u32 *)get_property(np, "interrupts", NULL);
727 /* get clock freq. if present */
728 clk = (u32 *)get_property(np, "clock-frequency", NULL);
729 /* get default speed if present */
730 spd = (u32 *)get_property(np, "current-speed", NULL);
731 /* Default to locate at end of array */
732 index = old_serial_count; /* end of the array by default */
733
734 /* If we have a location index, then use it */
735 if (typep && *typep == 'S') {
736 index = simple_strtol(typep+1, NULL, 0) - 1;
737 /* if index is out of range, use end of array instead */
738 if (index >= MAX_LEGACY_SERIAL_PORTS)
739 index = old_serial_count;
740 /* if our index is still out of range, that mean that
741 * array is full, we could scan for a free slot but that
742 * make little sense to bother, just skip the port
743 */
744 if (index >= MAX_LEGACY_SERIAL_PORTS)
745 goto next_port;
746 if (index >= old_serial_count)
747 old_serial_count = index + 1;
748 /* Check if there is a port who already claimed our slot */
749 if (serial_ports[index].iobase != 0) {
750 /* if we still have some room, move it, else override */
751 if (old_serial_count < MAX_LEGACY_SERIAL_PORTS) {
752 DBG("Moved legacy port %d -> %d\n", index,
753 old_serial_count);
754 serial_ports[old_serial_count++] =
755 serial_ports[index];
756 } else {
757 DBG("Replacing legacy port %d\n", index);
758 }
759 }
760 }
761 if (index >= MAX_LEGACY_SERIAL_PORTS)
762 goto next_port;
763 if (index >= old_serial_count)
764 old_serial_count = index + 1;
765
766 /* Now fill the entry */
767 memset(&serial_ports[index], 0, sizeof(struct plat_serial8250_port));
768 serial_ports[index].uartclk = clk ? *clk : BASE_BAUD * 16;
769 serial_ports[index].iobase = reg->address;
770 serial_ports[index].irq = interrupts ? interrupts[0] : 0;
771 serial_ports[index].flags = ASYNC_BOOT_AUTOCONF;
772
773 DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n",
774 index,
775 serial_ports[index].iobase,
776 serial_ports[index].irq,
777 serial_ports[index].uartclk);
778
779 /* Get phys address of IO reg for port 1 */
780 if (index != 0)
781 goto next_port;
782
783 pci = of_get_parent(isa);
784 if (!pci) {
785 DBG("%s: no pci parent found\n", np->full_name);
786 goto next_port;
787 }
788
789 rangesp = (u32 *)get_property(pci, "ranges", &rlen);
790 if (rangesp == NULL) {
791 of_node_put(pci);
792 goto next_port;
793 }
794 rlen /= 4;
795
796 /* we need the #size-cells of the PCI bridge node itself */
797 phys_size = 1;
798 sizeprop = (u32 *)get_property(pci, "#size-cells", NULL);
799 if (sizeprop != NULL)
800 phys_size = *sizeprop;
801 /* we need the parent #addr-cells */
802 addr_size = prom_n_addr_cells(pci);
803 rentsize = 3 + addr_size + phys_size;
804 io_base = 0;
805 for (;rlen >= rentsize; rlen -= rentsize,rangesp += rentsize) {
806 if (((rangesp[0] >> 24) & 0x3) != 1)
807 continue; /* not IO space */
808 io_base = rangesp[3];
809 if (addr_size == 2)
810 io_base = (io_base << 32) | rangesp[4];
811 }
812 if (io_base != 0) {
813 *physport = io_base + reg->address;
814 if (default_speed && spd)
815 *default_speed = *spd;
816 }
817 of_node_put(pci);
818 next_port:
819 of_node_put(isa);
820 }
821
822 DBG(" <- generic_find_legacy_serial_port()\n");
823}
824
825static struct platform_device serial_device = {
826 .name = "serial8250",
827 .id = PLAT8250_DEV_PLATFORM,
828 .dev = {
829 .platform_data = serial_ports,
830 },
831};
832
833static int __init serial_dev_init(void)
834{
835 return platform_device_register(&serial_device);
836}
837arch_initcall(serial_dev_init);
838
839#endif /* CONFIG_PPC_ISERIES */
840
841int check_legacy_ioport(unsigned long base_port) 669int check_legacy_ioport(unsigned long base_port)
842{ 670{
843 if (ppc_md.check_legacy_ioport == NULL) 671 if (ppc_md.check_legacy_ioport == NULL)
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 0d878e72fc44..2e372477d22a 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -99,7 +99,7 @@ static void udbg_console_write(struct console *con, const char *s,
99static struct console udbg_console = { 99static struct console udbg_console = {
100 .name = "udbg", 100 .name = "udbg",
101 .write = udbg_console_write, 101 .write = udbg_console_write,
102 .flags = CON_PRINTBUFFER, 102 .flags = CON_PRINTBUFFER | CON_ENABLED,
103 .index = -1, 103 .index = -1,
104}; 104};
105 105
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{