Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Benjamin Herrenschmidt and committed by
Paul Mackerras
463ce0e1 d1405b86

+607 -390
+3 -6
arch/powerpc/kernel/Makefile
··· 33 33 obj-$(CONFIG_IBMVIO) += vio.o 34 34 obj-$(CONFIG_IBMEBUS) += ibmebus.o 35 35 obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o 36 - obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o 37 - obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o 38 - udbgscc-$(CONFIG_PPC64) := udbg_scc.o 39 - obj-$(CONFIG_PPC_PMAC) += $(udbgscc-y) 40 36 obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o 41 37 42 38 ifeq ($(CONFIG_PPC_MERGE),y) ··· 55 59 obj-$(CONFIG_6xx) += idle_6xx.o 56 60 obj-$(CONFIG_SMP) += smp.o 57 61 obj-$(CONFIG_KPROBES) += kprobes.o 58 - 62 + obj-$(CONFIG_PPC_MULTIPLATFORM) += legacy_serial.o 63 + obj64-$(CONFIG_PPC_MULTIPLATFORM) += udbg_16550.o 64 + obj64-$(CONFIG_PPC_PMAC) += udbg_scc.o 59 65 module-$(CONFIG_PPC64) += module_64.o 60 66 obj-$(CONFIG_MODULES) += $(module-y) 61 67 62 68 pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ 63 69 pci_direct_iommu.o iomap.o 64 70 obj-$(CONFIG_PCI) += $(pci64-y) 65 - 66 71 kexec-$(CONFIG_PPC64) := machine_kexec_64.o 67 72 kexec-$(CONFIG_PPC32) := machine_kexec_32.o 68 73 obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y)
+478
arch/powerpc/kernel/legacy_serial.c
··· 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 + 26 + static struct plat_serial8250_port 27 + legacy_serial_ports[MAX_LEGACY_SERIAL_PORTS+1]; 28 + static 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]; 34 + static unsigned int legacy_serial_count; 35 + static int legacy_serial_console = -1; 36 + 37 + static 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 + 109 + static 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 + 143 + static 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 + */ 201 + void __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 + 286 + static struct platform_device serial_device = { 287 + .name = "serial8250", 288 + .id = PLAT8250_DEV_PLATFORM, 289 + .dev = { 290 + .platform_data = legacy_serial_ports, 291 + }, 292 + }; 293 + 294 + static 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 + 321 + static 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 + */ 356 + static 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 + } 383 + arch_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 + */ 394 + static 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 + } 477 + console_initcall(check_legacy_serial_console); 478 +
+15
arch/powerpc/kernel/pci_64.c
··· 1223 1223 } 1224 1224 EXPORT_SYMBOL(pcibios_fixup_device_resources); 1225 1225 1226 + 1226 1227 static void __devinit do_bus_setup(struct pci_bus *bus) 1227 1228 { 1228 1229 struct pci_dev *dev; ··· 1305 1304 1306 1305 *start = rsrc->start + offset; 1307 1306 *end = rsrc->end + offset; 1307 + } 1308 + 1309 + struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) 1310 + { 1311 + if (!have_of) 1312 + return NULL; 1313 + while(node) { 1314 + struct pci_controller *hose, *tmp; 1315 + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) 1316 + if (hose->arch_data == node) 1317 + return hose; 1318 + node = node->parent; 1319 + } 1320 + return NULL; 1308 1321 } 1309 1322 1310 1323 #endif /* CONFIG_PPC_MULTIPLATFORM */
-123
arch/powerpc/kernel/setup-common.c
··· 294 294 .show = show_cpuinfo, 295 295 }; 296 296 297 - #ifdef CONFIG_PPC_MULTIPLATFORM 298 - static 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 - } 417 - console_initcall(set_preferred_console); 418 - #endif /* CONFIG_PPC_MULTIPLATFORM */ 419 - 420 297 void __init check_for_initrd(void) 421 298 { 422 299 #ifdef CONFIG_BLK_DEV_INITRD
+8
arch/powerpc/kernel/setup_32.c
··· 39 39 #include <asm/nvram.h> 40 40 #include <asm/xmon.h> 41 41 #include <asm/time.h> 42 + #include <asm/serial.h> 42 43 43 44 #include "setup.h" 44 45 ··· 283 282 284 283 unflatten_device_tree(); 285 284 check_for_initrd(); 285 + 286 + if (ppc_md.init_early) 287 + ppc_md.init_early(); 288 + 289 + #ifdef CONFIG_PPC_MULTIPLATFORM 290 + find_legacy_serial_ports(); 291 + #endif 286 292 finish_device_tree(); 287 293 288 294 smp_setup_cpu_maps();
+9 -181
arch/powerpc/kernel/setup_64.c
··· 459 459 */ 460 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 472 * "Finish" the device-tree, that is do the actual parsing of 464 473 * some of the properties like the interrupt map ··· 665 656 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg); 666 657 printk("[terminate]%04x %s\n", src, msg); 667 658 } 668 - 669 - #ifndef CONFIG_PPC_ISERIES 670 - /* 671 - * This function can be used by platforms to "find" legacy serial ports. 672 - * It works for "serial" nodes under an "isa" node, and will try to 673 - * respect the "ibm,aix-loc" property if any. It works with up to 8 674 - * ports. 675 - */ 676 - 677 - #define MAX_LEGACY_SERIAL_PORTS 8 678 - static struct plat_serial8250_port serial_ports[MAX_LEGACY_SERIAL_PORTS+1]; 679 - static unsigned int old_serial_count; 680 - 681 - void __init generic_find_legacy_serial_ports(u64 *physport, 682 - unsigned int *default_speed) 683 - { 684 - struct device_node *np; 685 - u32 *sizeprop; 686 - 687 - struct isa_reg_property { 688 - u32 space; 689 - u32 address; 690 - u32 size; 691 - }; 692 - struct pci_reg_property { 693 - struct pci_address addr; 694 - u32 size_hi; 695 - u32 size_lo; 696 - }; 697 - 698 - DBG(" -> generic_find_legacy_serial_port()\n"); 699 - 700 - *physport = 0; 701 - if (default_speed) 702 - *default_speed = 0; 703 - 704 - np = of_find_node_by_path("/"); 705 - if (!np) 706 - return; 707 - 708 - /* First fill our array */ 709 - for (np = NULL; (np = of_find_node_by_type(np, "serial"));) { 710 - struct device_node *isa, *pci; 711 - struct isa_reg_property *reg; 712 - unsigned long phys_size, addr_size, io_base; 713 - u32 *rangesp; 714 - u32 *interrupts, *clk, *spd; 715 - char *typep; 716 - int index, rlen, rentsize; 717 - 718 - /* Ok, first check if it's under an "isa" parent */ 719 - isa = of_get_parent(np); 720 - if (!isa || strcmp(isa->name, "isa")) { 721 - DBG("%s: no isa parent found\n", np->full_name); 722 - continue; 723 - } 724 - 725 - /* Now look for an "ibm,aix-loc" property that gives us ordering 726 - * if any... 727 - */ 728 - typep = (char *)get_property(np, "ibm,aix-loc", NULL); 729 - 730 - /* Get the ISA port number */ 731 - reg = (struct isa_reg_property *)get_property(np, "reg", NULL); 732 - if (reg == NULL) 733 - goto next_port; 734 - /* We assume the interrupt number isn't translated ... */ 735 - interrupts = (u32 *)get_property(np, "interrupts", NULL); 736 - /* get clock freq. if present */ 737 - clk = (u32 *)get_property(np, "clock-frequency", NULL); 738 - /* get default speed if present */ 739 - spd = (u32 *)get_property(np, "current-speed", NULL); 740 - /* Default to locate at end of array */ 741 - index = old_serial_count; /* end of the array by default */ 742 - 743 - /* If we have a location index, then use it */ 744 - if (typep && *typep == 'S') { 745 - index = simple_strtol(typep+1, NULL, 0) - 1; 746 - /* if index is out of range, use end of array instead */ 747 - if (index >= MAX_LEGACY_SERIAL_PORTS) 748 - index = old_serial_count; 749 - /* if our index is still out of range, that mean that 750 - * array is full, we could scan for a free slot but that 751 - * make little sense to bother, just skip the port 752 - */ 753 - if (index >= MAX_LEGACY_SERIAL_PORTS) 754 - goto next_port; 755 - if (index >= old_serial_count) 756 - old_serial_count = index + 1; 757 - /* Check if there is a port who already claimed our slot */ 758 - if (serial_ports[index].iobase != 0) { 759 - /* if we still have some room, move it, else override */ 760 - if (old_serial_count < MAX_LEGACY_SERIAL_PORTS) { 761 - DBG("Moved legacy port %d -> %d\n", index, 762 - old_serial_count); 763 - serial_ports[old_serial_count++] = 764 - serial_ports[index]; 765 - } else { 766 - DBG("Replacing legacy port %d\n", index); 767 - } 768 - } 769 - } 770 - if (index >= MAX_LEGACY_SERIAL_PORTS) 771 - goto next_port; 772 - if (index >= old_serial_count) 773 - old_serial_count = index + 1; 774 - 775 - /* Now fill the entry */ 776 - memset(&serial_ports[index], 0, sizeof(struct plat_serial8250_port)); 777 - serial_ports[index].uartclk = clk ? *clk : BASE_BAUD * 16; 778 - serial_ports[index].iobase = reg->address; 779 - serial_ports[index].irq = interrupts ? interrupts[0] : 0; 780 - serial_ports[index].flags = ASYNC_BOOT_AUTOCONF; 781 - 782 - DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n", 783 - index, 784 - serial_ports[index].iobase, 785 - serial_ports[index].irq, 786 - serial_ports[index].uartclk); 787 - 788 - /* Get phys address of IO reg for port 1 */ 789 - if (index != 0) 790 - goto next_port; 791 - 792 - pci = of_get_parent(isa); 793 - if (!pci) { 794 - DBG("%s: no pci parent found\n", np->full_name); 795 - goto next_port; 796 - } 797 - 798 - rangesp = (u32 *)get_property(pci, "ranges", &rlen); 799 - if (rangesp == NULL) { 800 - of_node_put(pci); 801 - goto next_port; 802 - } 803 - rlen /= 4; 804 - 805 - /* we need the #size-cells of the PCI bridge node itself */ 806 - phys_size = 1; 807 - sizeprop = (u32 *)get_property(pci, "#size-cells", NULL); 808 - if (sizeprop != NULL) 809 - phys_size = *sizeprop; 810 - /* we need the parent #addr-cells */ 811 - addr_size = prom_n_addr_cells(pci); 812 - rentsize = 3 + addr_size + phys_size; 813 - io_base = 0; 814 - for (;rlen >= rentsize; rlen -= rentsize,rangesp += rentsize) { 815 - if (((rangesp[0] >> 24) & 0x3) != 1) 816 - continue; /* not IO space */ 817 - io_base = rangesp[3]; 818 - if (addr_size == 2) 819 - io_base = (io_base << 32) | rangesp[4]; 820 - } 821 - if (io_base != 0) { 822 - *physport = io_base + reg->address; 823 - if (default_speed && spd) 824 - *default_speed = *spd; 825 - } 826 - of_node_put(pci); 827 - next_port: 828 - of_node_put(isa); 829 - } 830 - 831 - DBG(" <- generic_find_legacy_serial_port()\n"); 832 - } 833 - 834 - static struct platform_device serial_device = { 835 - .name = "serial8250", 836 - .id = PLAT8250_DEV_PLATFORM, 837 - .dev = { 838 - .platform_data = serial_ports, 839 - }, 840 - }; 841 - 842 - static int __init serial_dev_init(void) 843 - { 844 - return platform_device_register(&serial_device); 845 - } 846 - arch_initcall(serial_dev_init); 847 - 848 - #endif /* CONFIG_PPC_ISERIES */ 849 659 850 660 int check_legacy_ioport(unsigned long base_port) 851 661 {
+1 -1
arch/powerpc/kernel/udbg.c
··· 99 99 static struct console udbg_console = { 100 100 .name = "udbg", 101 101 .write = udbg_console_write, 102 - .flags = CON_PRINTBUFFER, 102 + .flags = CON_PRINTBUFFER | CON_ENABLED, 103 103 .index = -1, 104 104 }; 105 105
+53 -10
arch/powerpc/kernel/udbg_16550.c
··· 43 43 #define LSR_TEMT 0x40 /* Xmitter empty */ 44 44 #define LSR_ERR 0x80 /* Error */ 45 45 46 + #define LCR_DLAB 0x80 47 + 46 48 static volatile struct NS16550 __iomem *udbg_comport; 47 49 48 50 static void udbg_550_putc(unsigned char c) ··· 79 77 return 0; 80 78 } 81 79 82 - void udbg_init_uart(void __iomem *comport, unsigned int speed) 80 + void udbg_init_uart(void __iomem *comport, unsigned int speed, 81 + unsigned int clock) 83 82 { 84 - u16 dll = speed ? (115200 / speed) : 12; 83 + unsigned int dll, base_bauds = clock / 16; 84 + 85 + if (speed == 0) 86 + speed = 9600; 87 + dll = base_bauds / speed; 85 88 86 89 if (comport) { 87 90 udbg_comport = (struct NS16550 __iomem *)comport; 88 91 out_8(&udbg_comport->lcr, 0x00); 89 92 out_8(&udbg_comport->ier, 0xff); 90 93 out_8(&udbg_comport->ier, 0x00); 91 - out_8(&udbg_comport->lcr, 0x80); /* Access baud rate */ 92 - out_8(&udbg_comport->dll, dll & 0xff); /* 1 = 115200, 2 = 57600, 93 - 3 = 38400, 12 = 9600 baud */ 94 - out_8(&udbg_comport->dlm, dll >> 8); /* dll >> 8 which should be zero 95 - for fast rates; */ 96 - out_8(&udbg_comport->lcr, 0x03); /* 8 data, 1 stop, no parity */ 97 - out_8(&udbg_comport->mcr, 0x03); /* RTS/DTR */ 98 - out_8(&udbg_comport->fcr ,0x07); /* Clear & enable FIFOs */ 94 + out_8(&udbg_comport->lcr, LCR_DLAB); 95 + out_8(&udbg_comport->dll, dll & 0xff); 96 + out_8(&udbg_comport->dlm, dll >> 8); 97 + /* 8 data, 1 stop, no parity */ 98 + out_8(&udbg_comport->lcr, 0x03); 99 + /* RTS/DTR */ 100 + out_8(&udbg_comport->mcr, 0x03); 101 + /* Clear & enable FIFOs */ 102 + out_8(&udbg_comport->fcr ,0x07); 99 103 udbg_putc = udbg_550_putc; 100 104 udbg_getc = udbg_550_getc; 101 105 udbg_getc_poll = udbg_550_getc_poll; 102 106 } 107 + } 108 + 109 + unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock) 110 + { 111 + unsigned int dll, dlm, divisor, prescaler, speed; 112 + u8 old_lcr; 113 + volatile struct NS16550 __iomem *port = comport; 114 + 115 + old_lcr = in_8(&port->lcr); 116 + 117 + /* select divisor latch registers. */ 118 + out_8(&port->lcr, LCR_DLAB); 119 + 120 + /* now, read the divisor */ 121 + dll = in_8(&port->dll); 122 + dlm = in_8(&port->dlm); 123 + divisor = dlm << 8 | dll; 124 + 125 + /* check prescaling */ 126 + if (in_8(&port->mcr) & 0x80) 127 + prescaler = 4; 128 + else 129 + prescaler = 1; 130 + 131 + /* restore the LCR */ 132 + out_8(&port->lcr, old_lcr); 133 + 134 + /* calculate speed */ 135 + speed = (clock / prescaler) / (divisor * 16); 136 + 137 + /* sanity check */ 138 + if (speed < 9600 || speed > 115200) 139 + speed = 9600; 140 + 141 + return speed; 103 142 } 104 143 105 144 #ifdef CONFIG_PPC_MAPLE
-14
arch/powerpc/platforms/maple/setup.c
··· 192 192 */ 193 193 hpte_init_native(); 194 194 195 - /* Find the serial port */ 196 - generic_find_legacy_serial_ports(&physport, &default_speed); 197 - 198 - DBG("phys port addr: %lx\n", (long)physport); 199 - 200 - if (physport) { 201 - void *comport; 202 - /* Map the uart for udbg. */ 203 - comport = (void *)ioremap(physport, 16); 204 - udbg_init_uart(comport, default_speed); 205 - 206 - DBG("Hello World !\n"); 207 - } 208 - 209 195 /* Setup interrupt mapping options */ 210 196 ppc64_interrupt_controller = IC_OPEN_PIC; 211 197
+30 -38
arch/powerpc/platforms/pseries/lpar.c
··· 24 24 #include <linux/config.h> 25 25 #include <linux/kernel.h> 26 26 #include <linux/dma-mapping.h> 27 + #include <linux/console.h> 27 28 #include <asm/processor.h> 28 29 #include <asm/mmu.h> 29 30 #include <asm/page.h> ··· 192 191 /* call this from early_init() for a working debug console on 193 192 * vterm capable LPAR machines 194 193 */ 195 - void udbg_init_debug_lpar(void) 194 + void __init udbg_init_debug_lpar(void) 196 195 { 197 196 vtermno = 0; 198 197 udbg_putc = udbg_putcLP; ··· 201 200 } 202 201 203 202 /* returns 0 if couldn't find or use /chosen/stdout as console */ 204 - int find_udbg_vterm(void) 203 + void __init find_udbg_vterm(void) 205 204 { 206 205 struct device_node *stdout_node; 207 206 u32 *termno; 208 207 char *name; 209 - int found = 0; 208 + int add_console; 210 209 211 210 /* find the boot console from /chosen/stdout */ 212 211 if (!of_chosen) 213 - return 0; 212 + return; 214 213 name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); 215 214 if (name == NULL) 216 - return 0; 215 + return; 217 216 stdout_node = of_find_node_by_path(name); 218 217 if (!stdout_node) 219 - return 0; 220 - 221 - /* now we have the stdout node; figure out what type of device it is. */ 218 + return; 222 219 name = (char *)get_property(stdout_node, "name", NULL); 223 220 if (!name) { 224 221 printk(KERN_WARNING "stdout node missing 'name' property!\n"); 225 222 goto out; 226 223 } 224 + /* The user has requested a console so this is already set up. */ 225 + add_console = !strstr(cmd_line, "console="); 227 226 228 - if (strncmp(name, "vty", 3) == 0) { 229 - if (device_is_compatible(stdout_node, "hvterm1")) { 230 - termno = (u32 *)get_property(stdout_node, "reg", NULL); 231 - if (termno) { 232 - vtermno = termno[0]; 233 - udbg_putc = udbg_putcLP; 234 - udbg_getc = udbg_getcLP; 235 - udbg_getc_poll = udbg_getc_pollLP; 236 - found = 1; 237 - } 238 - } else if (device_is_compatible(stdout_node, "hvterm-protocol")) { 239 - termno = (u32 *)get_property(stdout_node, "reg", NULL); 240 - if (termno) { 241 - vtermno = termno[0]; 242 - udbg_putc = udbg_hvsi_putc; 243 - udbg_getc = udbg_hvsi_getc; 244 - udbg_getc_poll = udbg_hvsi_getc_poll; 245 - found = 1; 246 - } 247 - } 248 - } else if (strncmp(name, "serial", 6)) { 249 - /* XXX fix ISA serial console */ 250 - printk(KERN_WARNING "serial stdout on LPAR ('%s')! " 251 - "can't print udbg messages\n", 252 - stdout_node->full_name); 253 - } else { 254 - printk(KERN_WARNING "don't know how to print to stdout '%s'\n", 255 - stdout_node->full_name); 227 + /* Check if it's a virtual terminal */ 228 + if (strncmp(name, "vty", 3) != 0) 229 + goto out; 230 + termno = (u32 *)get_property(stdout_node, "reg", NULL); 231 + if (termno == NULL) 232 + goto out; 233 + vtermno = termno[0]; 234 + 235 + if (device_is_compatible(stdout_node, "hvterm1")) { 236 + udbg_putc = udbg_putcLP; 237 + udbg_getc = udbg_getcLP; 238 + udbg_getc_poll = udbg_getc_pollLP; 239 + if (add_console) 240 + add_preferred_console("hvc", termno[0] & 0xff, NULL); 241 + } else if (device_is_compatible(stdout_node, "hvterm-protocol")) { 242 + vtermno = termno[0]; 243 + udbg_putc = udbg_hvsi_putc; 244 + udbg_getc = udbg_hvsi_getc; 245 + udbg_getc_poll = udbg_hvsi_getc_poll; 246 + if (add_console) 247 + add_preferred_console("hvsi", termno[0] & 0xff, NULL); 256 248 } 257 - 258 249 out: 259 250 of_node_put(stdout_node); 260 - return found; 261 251 } 262 252 263 253 void vpa_init(int cpu)
-14
arch/powerpc/platforms/pseries/setup.c
··· 79 79 extern void find_udbg_vterm(void); 80 80 extern void system_reset_fwnmi(void); /* from head.S */ 81 81 extern void machine_check_fwnmi(void); /* from head.S */ 82 - extern void generic_find_legacy_serial_ports(u64 *physport, 83 - unsigned int *default_speed); 84 82 85 83 int fwnmi_active; /* TRUE if an FWNMI handler is present */ 86 84 ··· 364 366 */ 365 367 static void __init pSeries_init_early(void) 366 368 { 367 - void *comport; 368 369 int iommu_off = 0; 369 - unsigned int default_speed; 370 - u64 physport; 371 370 372 371 DBG(" -> pSeries_init_early()\n"); 373 372 ··· 378 383 get_property(of_chosen, "linux,iommu-off", NULL)); 379 384 } 380 385 381 - generic_find_legacy_serial_ports(&physport, &default_speed); 382 - 383 386 if (platform_is_lpar()) 384 387 find_udbg_vterm(); 385 - else if (physport) { 386 - /* Map the uart for udbg. */ 387 - comport = (void *)ioremap(physport, 16); 388 - udbg_init_uart(comport, default_speed); 389 - 390 - DBG("Hello World !\n"); 391 - } 392 388 393 389 if (firmware_has_feature(FW_FEATURE_DABR)) 394 390 ppc_md.set_dabr = pseries_set_dabr;
+1 -2
arch/ppc/kernel/pci.c
··· 815 815 * to set pci_assign_all_buses to 1 and still use RTAS for PCI 816 816 * config cycles. 817 817 */ 818 - struct pci_controller* 819 - pci_find_hose_for_OF_device(struct device_node* node) 818 + struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) 820 819 { 821 820 if (!have_of) 822 821 return NULL;
+3
include/asm-powerpc/pci-bridge.h
··· 140 140 return PCI_DN(busdn)->phb; 141 141 } 142 142 143 + extern struct pci_controller* 144 + pci_find_hose_for_OF_device(struct device_node* node); 145 + 143 146 extern struct pci_controller * 144 147 pcibios_alloc_controller(struct device_node *dev); 145 148 extern void pcibios_free_controller(struct pci_controller *phb);
+2
include/asm-powerpc/serial.h
··· 15 15 /* Default baud base if not found in device-tree */ 16 16 #define BASE_BAUD ( 1843200 / 16 ) 17 17 18 + extern void find_legacy_serial_ports(void); 19 + 18 20 #endif /* _PPC64_SERIAL_H */
+4 -1
include/asm-powerpc/udbg.h
··· 24 24 extern void register_early_udbg_console(void); 25 25 extern void udbg_printf(const char *fmt, ...); 26 26 27 - extern void udbg_init_uart(void __iomem *comport, unsigned int speed); 27 + extern void udbg_init_uart(void __iomem *comport, unsigned int speed, 28 + unsigned int clock); 29 + extern unsigned int udbg_probe_uart_speed(void __iomem *comport, 30 + unsigned int clock); 28 31 29 32 struct device_node; 30 33 extern void udbg_init_scc(struct device_node *np);