1
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
2
/*
3
- * PDC Console support - ie use firmware to dump text via boot console
3
+ * PDC early console support - use PDC firmware to dump text via boot console
4
4
*
5
- * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
6
- * Copyright (C) 2000 Martin K Petersen <mkp at mkp.net>
7
- * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org>
8
- * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
9
- * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
10
- * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
11
- * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
12
- * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
13
- * Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
14
- * Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
15
- * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
16
- * Copyright (C) 2010 Guy Martin <gmsoft at tuxicoman.be>
5
+ * Copyright (C) 2001-2022 Helge Deller <[email protected] >
17
6
*/
18
7
19
- /*
20
- * The PDC console is a simple console, which can be used for debugging
21
- * boot related problems on HP PA-RISC machines. It is also useful when no
22
- * other console works.
23
- *
24
- * This code uses the ROM (=PDC) based functions to read and write characters
25
- * from and to PDC's boot path.
26
- */
27
-
28
- /* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems.
29
- * On production kernels EARLY_BOOTUP_DEBUG should be undefined. */
30
- #define EARLY_BOOTUP_DEBUG
31
-
32
-
33
- #include <linux/kernel.h>
34
8
#include <linux/console.h>
35
- #include <linux/string.h>
36
9
#include <linux/init.h>
37
- #include <linux/major .h>
38
- #include <linux/tty .h>
10
+ #include <linux/serial_core .h>
11
+ #include <linux/kgdb .h>
39
12
#include <asm/page.h> /* for PAGE0 */
40
13
#include <asm/pdc.h> /* for iodc_call() proto and friends */
41
14
42
15
static DEFINE_SPINLOCK (pdc_console_lock );
43
- static struct console pdc_cons ;
44
16
45
17
static void pdc_console_write (struct console * co , const char * s , unsigned count )
46
18
{
@@ -54,7 +26,8 @@ static void pdc_console_write(struct console *co, const char *s, unsigned count)
54
26
spin_unlock_irqrestore (& pdc_console_lock , flags );
55
27
}
56
28
57
- int pdc_console_poll_key (struct console * co )
29
+ #ifdef CONFIG_KGDB
30
+ static int kgdb_pdc_read_char (void )
58
31
{
59
32
int c ;
60
33
unsigned long flags ;
@@ -63,201 +36,40 @@ int pdc_console_poll_key(struct console *co)
63
36
c = pdc_iodc_getc ();
64
37
spin_unlock_irqrestore (& pdc_console_lock , flags );
65
38
66
- return c ;
67
- }
68
-
69
- static int pdc_console_setup (struct console * co , char * options )
70
- {
71
- return 0 ;
72
- }
73
-
74
- #if defined(CONFIG_PDC_CONSOLE )
75
- #include <linux/vt_kern.h>
76
- #include <linux/tty_flip.h>
77
-
78
- #define PDC_CONS_POLL_DELAY (30 * HZ / 1000)
79
-
80
- static void pdc_console_poll (struct timer_list * unused );
81
- static DEFINE_TIMER (pdc_console_timer , pdc_console_poll ) ;
82
- static struct tty_port tty_port ;
83
-
84
- static int pdc_console_tty_open (struct tty_struct * tty , struct file * filp )
85
- {
86
- tty_port_tty_set (& tty_port , tty );
87
- mod_timer (& pdc_console_timer , jiffies + PDC_CONS_POLL_DELAY );
88
-
89
- return 0 ;
39
+ return (c <= 0 ) ? NO_POLL_CHAR : c ;
90
40
}
91
41
92
- static void pdc_console_tty_close ( struct tty_struct * tty , struct file * filp )
42
+ static void kgdb_pdc_write_char ( u8 chr )
93
43
{
94
- if (tty -> count == 1 ) {
95
- del_timer_sync (& pdc_console_timer );
96
- tty_port_tty_set (& tty_port , NULL );
97
- }
44
+ if (PAGE0 -> mem_cons .cl_class != CL_DUPLEX )
45
+ pdc_console_write (NULL , & chr , 1 );
98
46
}
99
47
100
- static int pdc_console_tty_write (struct tty_struct * tty , const unsigned char * buf , int count )
101
- {
102
- pdc_console_write (NULL , buf , count );
103
- return count ;
104
- }
105
-
106
- static unsigned int pdc_console_tty_write_room (struct tty_struct * tty )
107
- {
108
- return 32768 ; /* no limit, no buffer used */
109
- }
110
-
111
- static const struct tty_operations pdc_console_tty_ops = {
112
- .open = pdc_console_tty_open ,
113
- .close = pdc_console_tty_close ,
114
- .write = pdc_console_tty_write ,
115
- .write_room = pdc_console_tty_write_room ,
48
+ static struct kgdb_io kgdb_pdc_io_ops = {
49
+ .name = "kgdb_pdc" ,
50
+ .read_char = kgdb_pdc_read_char ,
51
+ .write_char = kgdb_pdc_write_char ,
116
52
};
117
-
118
- static void pdc_console_poll (struct timer_list * unused )
119
- {
120
- int data , count = 0 ;
121
-
122
- while (1 ) {
123
- data = pdc_console_poll_key (NULL );
124
- if (data == -1 )
125
- break ;
126
- tty_insert_flip_char (& tty_port , data & 0xFF , TTY_NORMAL );
127
- count ++ ;
128
- }
129
-
130
- if (count )
131
- tty_flip_buffer_push (& tty_port );
132
-
133
- if (pdc_cons .flags & CON_ENABLED )
134
- mod_timer (& pdc_console_timer , jiffies + PDC_CONS_POLL_DELAY );
135
- }
136
-
137
- static struct tty_driver * pdc_console_tty_driver ;
138
-
139
- static int __init pdc_console_tty_driver_init (void )
140
- {
141
- struct tty_driver * driver ;
142
- int err ;
143
-
144
- /* Check if the console driver is still registered.
145
- * It is unregistered if the pdc console was not selected as the
146
- * primary console. */
147
-
148
- struct console * tmp ;
149
-
150
- console_lock ();
151
- for_each_console (tmp )
152
- if (tmp == & pdc_cons )
153
- break ;
154
- console_unlock ();
155
-
156
- if (!tmp ) {
157
- printk (KERN_INFO "PDC console driver not registered anymore, not creating %s\n" , pdc_cons .name );
158
- return - ENODEV ;
159
- }
160
-
161
- printk (KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n" );
162
- pdc_cons .flags &= ~CON_BOOT ;
163
-
164
- driver = tty_alloc_driver (1 , TTY_DRIVER_REAL_RAW |
165
- TTY_DRIVER_RESET_TERMIOS );
166
- if (IS_ERR (driver ))
167
- return PTR_ERR (driver );
168
-
169
- tty_port_init (& tty_port );
170
-
171
- driver -> driver_name = "pdc_cons" ;
172
- driver -> name = "ttyB" ;
173
- driver -> major = MUX_MAJOR ;
174
- driver -> minor_start = 0 ;
175
- driver -> type = TTY_DRIVER_TYPE_SYSTEM ;
176
- driver -> init_termios = tty_std_termios ;
177
- tty_set_operations (driver , & pdc_console_tty_ops );
178
- tty_port_link_device (& tty_port , driver , 0 );
179
-
180
- err = tty_register_driver (driver );
181
- if (err ) {
182
- printk (KERN_ERR "Unable to register the PDC console TTY driver\n" );
183
- tty_port_destroy (& tty_port );
184
- tty_driver_kref_put (driver );
185
- return err ;
186
- }
187
-
188
- pdc_console_tty_driver = driver ;
189
-
190
- return 0 ;
191
- }
192
- device_initcall (pdc_console_tty_driver_init );
193
-
194
- static struct tty_driver * pdc_console_device (struct console * c , int * index )
195
- {
196
- * index = c -> index ;
197
- return pdc_console_tty_driver ;
198
- }
199
- #else
200
- #define pdc_console_device NULL
201
53
#endif
202
54
203
- static struct console pdc_cons = {
204
- .name = "ttyB" ,
205
- .write = pdc_console_write ,
206
- .device = pdc_console_device ,
207
- .setup = pdc_console_setup ,
208
- .flags = CON_BOOT | CON_PRINTBUFFER ,
209
- .index = -1 ,
210
- };
211
-
212
- static int pdc_console_initialized ;
213
-
214
- static void pdc_console_init_force (void )
55
+ static int __init pdc_earlycon_setup (struct earlycon_device * device ,
56
+ const char * opt )
215
57
{
216
- if (pdc_console_initialized )
217
- return ;
218
- ++ pdc_console_initialized ;
219
-
58
+ struct console * earlycon_console ;
59
+
220
60
/* If the console is duplex then copy the COUT parameters to CIN. */
221
61
if (PAGE0 -> mem_cons .cl_class == CL_DUPLEX )
222
62
memcpy (& PAGE0 -> mem_kbd , & PAGE0 -> mem_cons , sizeof (PAGE0 -> mem_cons ));
223
63
224
- /* register the pdc console */
225
- register_console ( & pdc_cons ) ;
226
- }
64
+ earlycon_console = device -> con ;
65
+ earlycon_console -> write = pdc_console_write ;
66
+ device -> port . iotype = UPIO_MEM32BE ;
227
67
228
- void __init pdc_console_init (void )
229
- {
230
- #if defined(EARLY_BOOTUP_DEBUG ) || defined(CONFIG_PDC_CONSOLE )
231
- pdc_console_init_force ();
68
+ #ifdef CONFIG_KGDB
69
+ kgdb_register_io_module (& kgdb_pdc_io_ops );
232
70
#endif
233
- #ifdef EARLY_BOOTUP_DEBUG
234
- printk (KERN_INFO "Initialized PDC Console for debugging.\n" );
235
- #endif
236
- }
237
-
238
-
239
- /*
240
- * Used for emergencies. Currently only used if an HPMC occurs. If an
241
- * HPMC occurs, it is possible that the current console may not be
242
- * properly initialised after the PDC IO reset. This routine unregisters
243
- * all of the current consoles, reinitializes the pdc console and
244
- * registers it.
245
- */
246
-
247
- void pdc_console_restart (void )
248
- {
249
- struct console * console ;
250
-
251
- if (pdc_console_initialized )
252
- return ;
253
71
254
- /* If we've already seen the output, don't bother to print it again */
255
- if (console_drivers != NULL )
256
- pdc_cons .flags &= ~CON_PRINTBUFFER ;
257
-
258
- while ((console = console_drivers ) != NULL )
259
- unregister_console (console_drivers );
260
-
261
- /* force registering the pdc console */
262
- pdc_console_init_force ();
72
+ return 0 ;
263
73
}
74
+
75
+ EARLYCON_DECLARE (pdc , pdc_earlycon_setup );
0 commit comments