1 | // SPDX-License-Identifier: GPL-2.0 |
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 <linux/of.h> |
9 | #include <linux/of_address.h> |
10 | #include <linux/of_irq.h> |
11 | #include <linux/serial_reg.h> |
12 | #include <asm/io.h> |
13 | #include <asm/mmu.h> |
14 | #include <asm/serial.h> |
15 | #include <asm/udbg.h> |
16 | #include <asm/pci-bridge.h> |
17 | #include <asm/ppc-pci.h> |
18 | #include <asm/early_ioremap.h> |
19 | |
20 | #undef DEBUG |
21 | |
22 | #ifdef DEBUG |
23 | #define DBG(fmt...) do { printk(fmt); } while(0) |
24 | #else |
25 | #define DBG(fmt...) do { } while(0) |
26 | #endif |
27 | |
28 | #define MAX_LEGACY_SERIAL_PORTS 8 |
29 | |
30 | static struct plat_serial8250_port |
31 | legacy_serial_ports[MAX_LEGACY_SERIAL_PORTS+1]; |
32 | static struct legacy_serial_info { |
33 | struct device_node *np; |
34 | unsigned int speed; |
35 | unsigned int clock; |
36 | int irq_check_parent; |
37 | phys_addr_t taddr; |
38 | void __iomem *early_addr; |
39 | } legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS]; |
40 | |
41 | static const struct of_device_id legacy_serial_parents[] __initconst = { |
42 | {.type = "soc" ,}, |
43 | {.type = "tsi-bridge" ,}, |
44 | {.type = "opb" , }, |
45 | {.compatible = "ibm,opb" ,}, |
46 | {.compatible = "simple-bus" ,}, |
47 | {.compatible = "wrs,epld-localbus" ,}, |
48 | {}, |
49 | }; |
50 | |
51 | static unsigned int legacy_serial_count; |
52 | static int legacy_serial_console = -1; |
53 | |
54 | static const upf_t legacy_port_flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | |
55 | UPF_SHARE_IRQ | UPF_FIXED_PORT; |
56 | |
57 | static unsigned int tsi_serial_in(struct uart_port *p, int offset) |
58 | { |
59 | unsigned int tmp; |
60 | offset = offset << p->regshift; |
61 | if (offset == UART_IIR) { |
62 | tmp = readl(addr: p->membase + (UART_IIR & ~3)); |
63 | return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */ |
64 | } else |
65 | return readb(addr: p->membase + offset); |
66 | } |
67 | |
68 | static void tsi_serial_out(struct uart_port *p, int offset, int value) |
69 | { |
70 | offset = offset << p->regshift; |
71 | if (!((offset == UART_IER) && (value & UART_IER_UUE))) |
72 | writeb(val: value, addr: p->membase + offset); |
73 | } |
74 | |
75 | static int __init add_legacy_port(struct device_node *np, int want_index, |
76 | int iotype, phys_addr_t base, |
77 | phys_addr_t taddr, unsigned long irq, |
78 | upf_t flags, int irq_check_parent) |
79 | { |
80 | const __be32 *clk, *spd, *rs; |
81 | u32 clock = BASE_BAUD * 16; |
82 | u32 shift = 0; |
83 | int index; |
84 | |
85 | /* get clock freq. if present */ |
86 | clk = of_get_property(node: np, name: "clock-frequency" , NULL); |
87 | if (clk && *clk) |
88 | clock = be32_to_cpup(p: clk); |
89 | |
90 | /* get default speed if present */ |
91 | spd = of_get_property(node: np, name: "current-speed" , NULL); |
92 | |
93 | /* get register shift if present */ |
94 | rs = of_get_property(node: np, name: "reg-shift" , NULL); |
95 | if (rs && *rs) |
96 | shift = be32_to_cpup(p: rs); |
97 | |
98 | /* If we have a location index, then try to use it */ |
99 | if (want_index >= 0 && want_index < MAX_LEGACY_SERIAL_PORTS) |
100 | index = want_index; |
101 | else |
102 | index = legacy_serial_count; |
103 | |
104 | /* if our index is still out of range, that mean that |
105 | * array is full, we could scan for a free slot but that |
106 | * make little sense to bother, just skip the port |
107 | */ |
108 | if (index >= MAX_LEGACY_SERIAL_PORTS) |
109 | return -1; |
110 | if (index >= legacy_serial_count) |
111 | legacy_serial_count = index + 1; |
112 | |
113 | /* Check if there is a port who already claimed our slot */ |
114 | if (legacy_serial_infos[index].np != NULL) { |
115 | /* if we still have some room, move it, else override */ |
116 | if (legacy_serial_count < MAX_LEGACY_SERIAL_PORTS) { |
117 | printk(KERN_DEBUG "Moved legacy port %d -> %d\n" , |
118 | index, legacy_serial_count); |
119 | legacy_serial_ports[legacy_serial_count] = |
120 | legacy_serial_ports[index]; |
121 | legacy_serial_infos[legacy_serial_count] = |
122 | legacy_serial_infos[index]; |
123 | legacy_serial_count++; |
124 | } else { |
125 | printk(KERN_DEBUG "Replacing legacy port %d\n" , index); |
126 | } |
127 | } |
128 | |
129 | /* Now fill the entry */ |
130 | memset(&legacy_serial_ports[index], 0, |
131 | sizeof(struct plat_serial8250_port)); |
132 | if (iotype == UPIO_PORT) |
133 | legacy_serial_ports[index].iobase = base; |
134 | else |
135 | legacy_serial_ports[index].mapbase = base; |
136 | |
137 | legacy_serial_ports[index].iotype = iotype; |
138 | legacy_serial_ports[index].uartclk = clock; |
139 | legacy_serial_ports[index].irq = irq; |
140 | legacy_serial_ports[index].flags = flags; |
141 | legacy_serial_ports[index].regshift = shift; |
142 | legacy_serial_infos[index].taddr = taddr; |
143 | legacy_serial_infos[index].np = of_node_get(node: np); |
144 | legacy_serial_infos[index].clock = clock; |
145 | legacy_serial_infos[index].speed = spd ? be32_to_cpup(p: spd) : 0; |
146 | legacy_serial_infos[index].irq_check_parent = irq_check_parent; |
147 | |
148 | if (iotype == UPIO_TSI) { |
149 | legacy_serial_ports[index].serial_in = tsi_serial_in; |
150 | legacy_serial_ports[index].serial_out = tsi_serial_out; |
151 | } |
152 | |
153 | printk(KERN_DEBUG "Found legacy serial port %d for %pOF\n" , |
154 | index, np); |
155 | printk(KERN_DEBUG " %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n" , |
156 | (iotype == UPIO_PORT) ? "port" : "mem" , |
157 | (unsigned long long)base, (unsigned long long)taddr, irq, |
158 | legacy_serial_ports[index].uartclk, |
159 | legacy_serial_infos[index].speed); |
160 | |
161 | return index; |
162 | } |
163 | |
164 | static int __init add_legacy_soc_port(struct device_node *np, |
165 | struct device_node *soc_dev) |
166 | { |
167 | u64 addr; |
168 | const __be32 *addrp; |
169 | struct device_node *tsi = of_get_parent(node: np); |
170 | |
171 | /* We only support ports that have a clock frequency properly |
172 | * encoded in the device-tree. |
173 | */ |
174 | if (!of_property_present(np, propname: "clock-frequency" )) |
175 | return -1; |
176 | |
177 | /* if reg-offset don't try to use it */ |
178 | if (of_property_present(np, propname: "reg-offset" )) |
179 | return -1; |
180 | |
181 | /* if rtas uses this device, don't try to use it as well */ |
182 | if (of_property_read_bool(np, propname: "used-by-rtas" )) |
183 | return -1; |
184 | |
185 | /* Get the address */ |
186 | addrp = of_get_address(dev: soc_dev, index: 0, NULL, NULL); |
187 | if (addrp == NULL) |
188 | return -1; |
189 | |
190 | addr = of_translate_address(np: soc_dev, addr: addrp); |
191 | if (addr == OF_BAD_ADDR) |
192 | return -1; |
193 | |
194 | /* Add port, irq will be dealt with later. We passed a translated |
195 | * IO port value. It will be fixed up later along with the irq |
196 | */ |
197 | if (of_node_is_type(np: tsi, type: "tsi-bridge" )) |
198 | return add_legacy_port(np, want_index: -1, UPIO_TSI, base: addr, taddr: addr, |
199 | irq: 0, flags: legacy_port_flags, irq_check_parent: 0); |
200 | else |
201 | return add_legacy_port(np, want_index: -1, UPIO_MEM, base: addr, taddr: addr, |
202 | irq: 0, flags: legacy_port_flags, irq_check_parent: 0); |
203 | } |
204 | |
205 | static int __init add_legacy_isa_port(struct device_node *np, |
206 | struct device_node *isa_brg) |
207 | { |
208 | const __be32 *reg; |
209 | const char *typep; |
210 | int index = -1; |
211 | u64 taddr; |
212 | |
213 | DBG(" -> add_legacy_isa_port(%pOF)\n" , np); |
214 | |
215 | /* Get the ISA port number */ |
216 | reg = of_get_property(node: np, name: "reg" , NULL); |
217 | if (reg == NULL) |
218 | return -1; |
219 | |
220 | /* Verify it's an IO port, we don't support anything else */ |
221 | if (!(be32_to_cpu(reg[0]) & 0x00000001)) |
222 | return -1; |
223 | |
224 | /* Now look for an "ibm,aix-loc" property that gives us ordering |
225 | * if any... |
226 | */ |
227 | typep = of_get_property(node: np, name: "ibm,aix-loc" , NULL); |
228 | |
229 | /* If we have a location index, then use it */ |
230 | if (typep && *typep == 'S') |
231 | index = simple_strtol(typep+1, NULL, 0) - 1; |
232 | |
233 | /* Translate ISA address. If it fails, we still register the port |
234 | * with no translated address so that it can be picked up as an IO |
235 | * port later by the serial driver |
236 | * |
237 | * Note: Don't even try on P8 lpc, we know it's not directly mapped |
238 | */ |
239 | if (!of_device_is_compatible(device: isa_brg, "ibm,power8-lpc" ) || |
240 | of_property_present(np: isa_brg, propname: "ranges" )) { |
241 | taddr = of_translate_address(np, addr: reg); |
242 | if (taddr == OF_BAD_ADDR) |
243 | taddr = 0; |
244 | } else |
245 | taddr = 0; |
246 | |
247 | /* Add port, irq will be dealt with later */ |
248 | return add_legacy_port(np, want_index: index, UPIO_PORT, be32_to_cpu(reg[1]), |
249 | taddr, irq: 0, flags: legacy_port_flags, irq_check_parent: 0); |
250 | |
251 | } |
252 | |
253 | #ifdef CONFIG_PCI |
254 | static int __init add_legacy_pci_port(struct device_node *np, |
255 | struct device_node *pci_dev) |
256 | { |
257 | u64 addr, base; |
258 | const __be32 *addrp; |
259 | unsigned int flags; |
260 | int iotype, index = -1, lindex = 0; |
261 | |
262 | DBG(" -> add_legacy_pci_port(%pOF)\n" , np); |
263 | |
264 | /* We only support ports that have a clock frequency properly |
265 | * encoded in the device-tree (that is have an fcode). Anything |
266 | * else can't be used that early and will be normally probed by |
267 | * the generic 8250_pci driver later on. The reason is that 8250 |
268 | * compatible UARTs on PCI need all sort of quirks (port offsets |
269 | * etc...) that this code doesn't know about |
270 | */ |
271 | if (!of_property_present(np, propname: "clock-frequency" )) |
272 | return -1; |
273 | |
274 | /* Get the PCI address. Assume BAR 0 */ |
275 | addrp = of_get_pci_address(dev: pci_dev, bar_no: 0, NULL, flags: &flags); |
276 | if (addrp == NULL) |
277 | return -1; |
278 | |
279 | /* We only support BAR 0 for now */ |
280 | iotype = (flags & IORESOURCE_MEM) ? UPIO_MEM : UPIO_PORT; |
281 | addr = of_translate_address(np: pci_dev, addr: addrp); |
282 | if (addr == OF_BAD_ADDR) |
283 | return -1; |
284 | |
285 | /* Set the IO base to the same as the translated address for MMIO, |
286 | * or to the domain local IO base for PIO (it will be fixed up later) |
287 | */ |
288 | if (iotype == UPIO_MEM) |
289 | base = addr; |
290 | else |
291 | base = of_read_number(cell: &addrp[2], size: 1); |
292 | |
293 | /* Try to guess an index... If we have subdevices of the pci dev, |
294 | * we get to their "reg" property |
295 | */ |
296 | if (np != pci_dev) { |
297 | const __be32 *reg = of_get_property(node: np, name: "reg" , NULL); |
298 | if (reg && (be32_to_cpup(p: reg) < 4)) |
299 | index = lindex = be32_to_cpup(p: reg); |
300 | } |
301 | |
302 | /* Local index means it's the Nth port in the PCI chip. Unfortunately |
303 | * the offset to add here is device specific. We know about those |
304 | * EXAR ports and we default to the most common case. If your UART |
305 | * doesn't work for these settings, you'll have to add your own special |
306 | * cases here |
307 | */ |
308 | if (of_device_is_compatible(device: pci_dev, "pci13a8,152" ) || |
309 | of_device_is_compatible(device: pci_dev, "pci13a8,154" ) || |
310 | of_device_is_compatible(device: pci_dev, "pci13a8,158" )) { |
311 | addr += 0x200 * lindex; |
312 | base += 0x200 * lindex; |
313 | } else { |
314 | addr += 8 * lindex; |
315 | base += 8 * lindex; |
316 | } |
317 | |
318 | /* Add port, irq will be dealt with later. We passed a translated |
319 | * IO port value. It will be fixed up later along with the irq |
320 | */ |
321 | return add_legacy_port(np, want_index: index, iotype, base, taddr: addr, irq: 0, |
322 | flags: legacy_port_flags, irq_check_parent: np != pci_dev); |
323 | } |
324 | #endif |
325 | |
326 | static void __init setup_legacy_serial_console(int console) |
327 | { |
328 | struct legacy_serial_info *info = &legacy_serial_infos[console]; |
329 | struct plat_serial8250_port *port = &legacy_serial_ports[console]; |
330 | unsigned int stride; |
331 | |
332 | stride = 1 << port->regshift; |
333 | |
334 | /* Check if a translated MMIO address has been found */ |
335 | if (info->taddr) { |
336 | info->early_addr = early_ioremap(phys_addr: info->taddr, size: 0x1000); |
337 | if (info->early_addr == NULL) |
338 | return; |
339 | udbg_uart_init_mmio(info->early_addr, stride); |
340 | } else { |
341 | /* Check if it's PIO and we support untranslated PIO */ |
342 | if (port->iotype == UPIO_PORT && isa_io_special) |
343 | udbg_uart_init_pio(port->iobase, stride); |
344 | else |
345 | return; |
346 | } |
347 | |
348 | /* Try to query the current speed */ |
349 | if (info->speed == 0) |
350 | info->speed = udbg_probe_uart_speed(info->clock); |
351 | |
352 | /* Set it up */ |
353 | DBG("default console speed = %d\n" , info->speed); |
354 | udbg_uart_setup(info->speed, info->clock); |
355 | } |
356 | |
357 | static int __init ioremap_legacy_serial_console(void) |
358 | { |
359 | struct plat_serial8250_port *port; |
360 | struct legacy_serial_info *info; |
361 | void __iomem *vaddr; |
362 | |
363 | if (legacy_serial_console < 0) |
364 | return 0; |
365 | |
366 | info = &legacy_serial_infos[legacy_serial_console]; |
367 | port = &legacy_serial_ports[legacy_serial_console]; |
368 | |
369 | if (!info->early_addr) |
370 | return 0; |
371 | |
372 | vaddr = ioremap(offset: info->taddr, size: 0x1000); |
373 | if (WARN_ON(!vaddr)) |
374 | return -ENOMEM; |
375 | |
376 | udbg_uart_init_mmio(vaddr, 1 << port->regshift); |
377 | early_iounmap(addr: info->early_addr, size: 0x1000); |
378 | info->early_addr = NULL; |
379 | |
380 | return 0; |
381 | } |
382 | early_initcall(ioremap_legacy_serial_console); |
383 | |
384 | /* |
385 | * This is called very early, as part of setup_system() or eventually |
386 | * setup_arch(), basically before anything else in this file. This function |
387 | * will try to build a list of all the available 8250-compatible serial ports |
388 | * in the machine using the Open Firmware device-tree. It currently only deals |
389 | * with ISA and PCI busses but could be extended. It allows a very early boot |
390 | * console to be initialized, that list is also used later to provide 8250 with |
391 | * the machine non-PCI ports and to properly pick the default console port |
392 | */ |
393 | void __init find_legacy_serial_ports(void) |
394 | { |
395 | struct device_node *np, *stdout = NULL; |
396 | const char *path; |
397 | int index; |
398 | |
399 | DBG(" -> find_legacy_serial_port()\n" ); |
400 | |
401 | /* Now find out if one of these is out firmware console */ |
402 | path = of_get_property(node: of_chosen, name: "linux,stdout-path" , NULL); |
403 | if (path == NULL) |
404 | path = of_get_property(node: of_chosen, name: "stdout-path" , NULL); |
405 | if (path != NULL) { |
406 | stdout = of_find_node_by_path(path); |
407 | if (stdout) |
408 | DBG("stdout is %pOF\n" , stdout); |
409 | } else { |
410 | DBG(" no linux,stdout-path !\n" ); |
411 | } |
412 | |
413 | /* Iterate over all the 16550 ports, looking for known parents */ |
414 | for_each_compatible_node(np, "serial" , "ns16550" ) { |
415 | struct device_node *parent = of_get_parent(node: np); |
416 | if (!parent) |
417 | continue; |
418 | if (of_match_node(matches: legacy_serial_parents, node: parent) != NULL) { |
419 | if (of_device_is_available(device: np)) { |
420 | index = add_legacy_soc_port(np, soc_dev: np); |
421 | if (index >= 0 && np == stdout) |
422 | legacy_serial_console = index; |
423 | } |
424 | } |
425 | of_node_put(node: parent); |
426 | } |
427 | |
428 | /* Next, fill our array with ISA ports */ |
429 | for_each_node_by_type(np, "serial" ) { |
430 | struct device_node *isa = of_get_parent(node: np); |
431 | if (of_node_name_eq(np: isa, name: "isa" ) || of_node_name_eq(np: isa, name: "lpc" )) { |
432 | if (of_device_is_available(device: np)) { |
433 | index = add_legacy_isa_port(np, isa_brg: isa); |
434 | if (index >= 0 && np == stdout) |
435 | legacy_serial_console = index; |
436 | } |
437 | } |
438 | of_node_put(node: isa); |
439 | } |
440 | |
441 | #ifdef CONFIG_PCI |
442 | /* Next, try to locate PCI ports */ |
443 | for (np = NULL; (np = of_find_all_nodes(prev: np));) { |
444 | struct device_node *pci, *parent = of_get_parent(node: np); |
445 | if (of_node_name_eq(np: parent, name: "isa" )) { |
446 | of_node_put(node: parent); |
447 | continue; |
448 | } |
449 | if (!of_node_name_eq(np, name: "serial" ) && |
450 | !of_node_is_type(np, type: "serial" )) { |
451 | of_node_put(node: parent); |
452 | continue; |
453 | } |
454 | /* Check for known pciclass, and also check whether we have |
455 | * a device with child nodes for ports or not |
456 | */ |
457 | if (of_device_is_compatible(device: np, "pciclass,0700" ) || |
458 | of_device_is_compatible(device: np, "pciclass,070002" )) |
459 | pci = np; |
460 | else if (of_device_is_compatible(device: parent, "pciclass,0700" ) || |
461 | of_device_is_compatible(device: parent, "pciclass,070002" )) |
462 | pci = parent; |
463 | else { |
464 | of_node_put(node: parent); |
465 | continue; |
466 | } |
467 | index = add_legacy_pci_port(np, pci_dev: pci); |
468 | if (index >= 0 && np == stdout) |
469 | legacy_serial_console = index; |
470 | of_node_put(node: parent); |
471 | } |
472 | #endif |
473 | |
474 | of_node_put(node: stdout); |
475 | |
476 | DBG("legacy_serial_console = %d\n" , legacy_serial_console); |
477 | if (legacy_serial_console >= 0) |
478 | setup_legacy_serial_console(legacy_serial_console); |
479 | DBG(" <- find_legacy_serial_port()\n" ); |
480 | } |
481 | |
482 | static struct platform_device serial_device = { |
483 | .name = "serial8250" , |
484 | .id = PLAT8250_DEV_PLATFORM, |
485 | .dev = { |
486 | .platform_data = legacy_serial_ports, |
487 | }, |
488 | }; |
489 | |
490 | static void __init fixup_port_irq(int index, |
491 | struct device_node *np, |
492 | struct plat_serial8250_port *port) |
493 | { |
494 | unsigned int virq; |
495 | |
496 | DBG("fixup_port_irq(%d)\n" , index); |
497 | |
498 | virq = irq_of_parse_and_map(node: np, index: 0); |
499 | if (!virq && legacy_serial_infos[index].irq_check_parent) { |
500 | np = of_get_parent(node: np); |
501 | if (np == NULL) |
502 | return; |
503 | virq = irq_of_parse_and_map(node: np, index: 0); |
504 | of_node_put(node: np); |
505 | } |
506 | if (!virq) |
507 | return; |
508 | |
509 | port->irq = virq; |
510 | |
511 | if (IS_ENABLED(CONFIG_SERIAL_8250) && |
512 | of_device_is_compatible(device: np, "fsl,ns16550" )) { |
513 | if (IS_REACHABLE(CONFIG_SERIAL_8250_FSL)) { |
514 | port->handle_irq = fsl8250_handle_irq; |
515 | port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); |
516 | } else { |
517 | pr_warn_once("Not activating Freescale specific workaround for device %pOFP\n" , |
518 | np); |
519 | } |
520 | } |
521 | } |
522 | |
523 | static void __init fixup_port_pio(int index, |
524 | struct device_node *np, |
525 | struct plat_serial8250_port *port) |
526 | { |
527 | #ifdef CONFIG_PCI |
528 | struct pci_controller *hose; |
529 | |
530 | DBG("fixup_port_pio(%d)\n" , index); |
531 | |
532 | hose = pci_find_hose_for_OF_device(np); |
533 | if (hose) { |
534 | unsigned long offset = (unsigned long)hose->io_base_virt - |
535 | #ifdef CONFIG_PPC64 |
536 | pci_io_base; |
537 | #else |
538 | isa_io_base; |
539 | #endif |
540 | DBG("port %d, IO %lx -> %lx\n" , |
541 | index, port->iobase, port->iobase + offset); |
542 | port->iobase += offset; |
543 | } |
544 | #endif |
545 | } |
546 | |
547 | static void __init fixup_port_mmio(int index, |
548 | struct device_node *np, |
549 | struct plat_serial8250_port *port) |
550 | { |
551 | DBG("fixup_port_mmio(%d)\n" , index); |
552 | |
553 | port->membase = ioremap(offset: port->mapbase, size: 0x100); |
554 | } |
555 | |
556 | /* |
557 | * This is called as an arch initcall, hopefully before the PCI bus is |
558 | * probed and/or the 8250 driver loaded since we need to register our |
559 | * platform devices before 8250 PCI ones are detected as some of them |
560 | * must properly "override" the platform ones. |
561 | * |
562 | * This function fixes up the interrupt value for platform ports as it |
563 | * couldn't be done earlier before interrupt maps have been parsed. It |
564 | * also "corrects" the IO address for PIO ports for the same reason, |
565 | * since earlier, the PHBs virtual IO space wasn't assigned yet. It then |
566 | * registers all those platform ports for use by the 8250 driver when it |
567 | * finally loads. |
568 | */ |
569 | static int __init serial_dev_init(void) |
570 | { |
571 | int i; |
572 | |
573 | if (legacy_serial_count == 0) |
574 | return -ENODEV; |
575 | |
576 | /* |
577 | * Before we register the platform serial devices, we need |
578 | * to fixup their interrupts and their IO ports. |
579 | */ |
580 | DBG("Fixing serial ports interrupts and IO ports ...\n" ); |
581 | |
582 | for (i = 0; i < legacy_serial_count; i++) { |
583 | struct plat_serial8250_port *port = &legacy_serial_ports[i]; |
584 | struct device_node *np = legacy_serial_infos[i].np; |
585 | |
586 | if (!port->irq) |
587 | fixup_port_irq(index: i, np, port); |
588 | if (port->iotype == UPIO_PORT) |
589 | fixup_port_pio(index: i, np, port); |
590 | if ((port->iotype == UPIO_MEM) || (port->iotype == UPIO_TSI)) |
591 | fixup_port_mmio(index: i, np, port); |
592 | } |
593 | |
594 | DBG("Registering platform serial ports\n" ); |
595 | |
596 | return platform_device_register(&serial_device); |
597 | } |
598 | device_initcall(serial_dev_init); |
599 | |
600 | |
601 | #ifdef CONFIG_SERIAL_8250_CONSOLE |
602 | /* |
603 | * This is called very early, as part of console_init() (typically just after |
604 | * time_init()). This function is respondible for trying to find a good |
605 | * default console on serial ports. It tries to match the open firmware |
606 | * default output with one of the available serial console drivers that have |
607 | * been probed earlier by find_legacy_serial_ports() |
608 | */ |
609 | static int __init check_legacy_serial_console(void) |
610 | { |
611 | struct device_node *prom_stdout = NULL; |
612 | int i, speed = 0, offset = 0; |
613 | const char *name; |
614 | const __be32 *spd; |
615 | |
616 | DBG(" -> check_legacy_serial_console()\n" ); |
617 | |
618 | /* The user has requested a console so this is already set up. */ |
619 | if (strstr(boot_command_line, "console=" )) { |
620 | DBG(" console was specified !\n" ); |
621 | return -EBUSY; |
622 | } |
623 | |
624 | if (!of_chosen) { |
625 | DBG(" of_chosen is NULL !\n" ); |
626 | return -ENODEV; |
627 | } |
628 | |
629 | if (legacy_serial_console < 0) { |
630 | DBG(" legacy_serial_console not found !\n" ); |
631 | return -ENODEV; |
632 | } |
633 | /* We are getting a weird phandle from OF ... */ |
634 | /* ... So use the full path instead */ |
635 | name = of_get_property(node: of_chosen, name: "linux,stdout-path" , NULL); |
636 | if (name == NULL) |
637 | name = of_get_property(node: of_chosen, name: "stdout-path" , NULL); |
638 | if (name == NULL) { |
639 | DBG(" no stdout-path !\n" ); |
640 | return -ENODEV; |
641 | } |
642 | prom_stdout = of_find_node_by_path(path: name); |
643 | if (!prom_stdout) { |
644 | DBG(" can't find stdout package %s !\n" , name); |
645 | return -ENODEV; |
646 | } |
647 | DBG("stdout is %pOF\n" , prom_stdout); |
648 | |
649 | name = of_get_property(node: prom_stdout, name: "name" , NULL); |
650 | if (!name) { |
651 | DBG(" stdout package has no name !\n" ); |
652 | goto not_found; |
653 | } |
654 | spd = of_get_property(node: prom_stdout, name: "current-speed" , NULL); |
655 | if (spd) |
656 | speed = be32_to_cpup(p: spd); |
657 | |
658 | if (strcmp(name, "serial" ) != 0) |
659 | goto not_found; |
660 | |
661 | /* Look for it in probed array */ |
662 | for (i = 0; i < legacy_serial_count; i++) { |
663 | if (prom_stdout != legacy_serial_infos[i].np) |
664 | continue; |
665 | offset = i; |
666 | speed = legacy_serial_infos[i].speed; |
667 | break; |
668 | } |
669 | if (i >= legacy_serial_count) |
670 | goto not_found; |
671 | |
672 | of_node_put(node: prom_stdout); |
673 | |
674 | DBG("Found serial console at ttyS%d\n" , offset); |
675 | |
676 | if (speed) { |
677 | static char __initdata opt[16]; |
678 | sprintf(buf: opt, fmt: "%d" , speed); |
679 | return add_preferred_console(name: "ttyS" , idx: offset, options: opt); |
680 | } else |
681 | return add_preferred_console(name: "ttyS" , idx: offset, NULL); |
682 | |
683 | not_found: |
684 | DBG("No preferred console found !\n" ); |
685 | of_node_put(node: prom_stdout); |
686 | return -ENODEV; |
687 | } |
688 | console_initcall(check_legacy_serial_console); |
689 | |
690 | #endif /* CONFIG_SERIAL_8250_CONSOLE */ |
691 | |