1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * PDC early console support - use PDC firmware to dump text via boot console |
4 | * |
5 | * Copyright (C) 2001-2022 Helge Deller <deller@gmx.de> |
6 | */ |
7 | |
8 | #include <linux/console.h> |
9 | #include <linux/init.h> |
10 | #include <linux/serial_core.h> |
11 | #include <linux/kgdb.h> |
12 | #include <asm/page.h> /* for PAGE0 */ |
13 | #include <asm/pdc.h> /* for iodc_call() proto and friends */ |
14 | |
15 | static void pdc_console_write(struct console *co, const char *s, unsigned count) |
16 | { |
17 | int i = 0; |
18 | |
19 | do { |
20 | i += pdc_iodc_print(s + i, count - i); |
21 | } while (i < count); |
22 | } |
23 | |
24 | #ifdef CONFIG_KGDB |
25 | static int kgdb_pdc_read_char(void) |
26 | { |
27 | int c = pdc_iodc_getc(); |
28 | |
29 | return (c <= 0) ? NO_POLL_CHAR : c; |
30 | } |
31 | |
32 | static void kgdb_pdc_write_char(u8 chr) |
33 | { |
34 | /* no need to print char as it's shown on standard console */ |
35 | /* pdc_iodc_print(&chr, 1); */ |
36 | } |
37 | |
38 | static struct kgdb_io kgdb_pdc_io_ops = { |
39 | .name = "kgdb_pdc" , |
40 | .read_char = kgdb_pdc_read_char, |
41 | .write_char = kgdb_pdc_write_char, |
42 | }; |
43 | #endif |
44 | |
45 | static int __init pdc_earlycon_setup(struct earlycon_device *device, |
46 | const char *opt) |
47 | { |
48 | struct console *earlycon_console; |
49 | |
50 | /* If the console is duplex then copy the COUT parameters to CIN. */ |
51 | if (PAGE0->mem_cons.cl_class == CL_DUPLEX) |
52 | memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons)); |
53 | |
54 | earlycon_console = device->con; |
55 | earlycon_console->write = pdc_console_write; |
56 | device->port.iotype = UPIO_MEM32BE; |
57 | |
58 | #ifdef CONFIG_KGDB |
59 | kgdb_register_io_module(local_kgdb_io_ops: &kgdb_pdc_io_ops); |
60 | #endif |
61 | |
62 | return 0; |
63 | } |
64 | |
65 | EARLYCON_DECLARE(pdc, pdc_earlycon_setup); |
66 | |