1 | /* |
2 | * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
5 | * |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License |
8 | * Version 2.0 (the 'License'). You may not use this file except in |
9 | * compliance with the License. The rights granted to you under the License |
10 | * may not be used to create, or enable the creation or redistribution of, |
11 | * unlawful or unlicensed copies of an Apple operating system, or to |
12 | * circumvent, violate, or enable the circumvention or violation of, any |
13 | * terms of an Apple operating system software license agreement. |
14 | * |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
17 | * |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and |
24 | * limitations under the License. |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ |
28 | |
29 | /* |
30 | * file: pe_serial.c |
31 | * Polled-mode 16x50 UART driver. |
32 | */ |
33 | |
34 | #include <machine/machine_routines.h> |
35 | #include <pexpert/protos.h> |
36 | #include <pexpert/pexpert.h> |
37 | |
38 | struct pe_serial_functions { |
39 | void (*uart_init) (void); |
40 | void (*uart_set_baud_rate) (int unit, uint32_t baud_rate); |
41 | int (*tr0) (void); |
42 | void (*td0) (int c); |
43 | int (*rr0) (void); |
44 | int (*rd0) (void); |
45 | }; |
46 | |
47 | static struct pe_serial_functions *gPESF; |
48 | |
49 | static int uart_initted = 0; /* 1 if init'ed */ |
50 | |
51 | static unsigned int legacy_uart_enabled = 0; /* 1 Legacy IO based UART is supported on platform */ |
52 | |
53 | static boolean_t lpss_uart_supported = 0; /* 1 if LPSS UART is supported on platform */ |
54 | static unsigned int lpss_uart_enabled = 0; /* 1 if it is LPSS UART is in D0 state */ |
55 | static void lpss_uart_re_init (void); |
56 | |
57 | static boolean_t pcie_uart_enabled = 0; /* 1 if PCIe UART is supported on platform */ |
58 | |
59 | #define DEFAULT_UART_BAUD_RATE 115200 |
60 | |
61 | static unsigned uart_baud_rate = DEFAULT_UART_BAUD_RATE; |
62 | |
63 | // ============================================================================= |
64 | // Legacy UART support using IO transactions to COM1 or COM2 |
65 | // ============================================================================= |
66 | |
67 | #define LEGACY_UART_PORT_ADDR COM1_PORT_ADDR |
68 | #define LEGACY_UART_CLOCK 1843200 /* 1.8432 MHz clock */ |
69 | |
70 | #define IO_WRITE(r, v) outb(LEGACY_UART_PORT_ADDR + UART_##r, v) |
71 | #define IO_READ(r) inb(LEGACY_UART_PORT_ADDR + UART_##r) |
72 | |
73 | enum { |
74 | COM1_PORT_ADDR = 0x3f8, |
75 | COM2_PORT_ADDR = 0x2f8 |
76 | }; |
77 | |
78 | enum { |
79 | UART_RBR = 0, /* receive buffer Register (R) */ |
80 | UART_THR = 0, /* transmit holding register (W) */ |
81 | UART_DLL = 0, /* DLAB = 1, divisor latch (LSB) */ |
82 | UART_IER = 1, /* interrupt enable register */ |
83 | UART_DLM = 1, /* DLAB = 1, divisor latch (MSB) */ |
84 | UART_IIR = 2, /* interrupt ident register (R) */ |
85 | UART_FCR = 2, /* fifo control register (W) */ |
86 | UART_LCR = 3, /* line control register */ |
87 | UART_MCR = 4, /* modem control register */ |
88 | UART_LSR = 5, /* line status register */ |
89 | UART_MSR = 6, /* modem status register */ |
90 | UART_SCR = 7 /* scratch register */ |
91 | }; |
92 | |
93 | enum { |
94 | UART_LCR_8BITS = 0x03, |
95 | UART_LCR_DLAB = 0x80 |
96 | }; |
97 | |
98 | enum { |
99 | UART_MCR_DTR = 0x01, |
100 | UART_MCR_RTS = 0x02, |
101 | UART_MCR_OUT1 = 0x04, |
102 | UART_MCR_OUT2 = 0x08, |
103 | UART_MCR_LOOP = 0x10 |
104 | }; |
105 | |
106 | enum { |
107 | UART_LSR_DR = 0x01, |
108 | UART_LSR_OE = 0x02, |
109 | UART_LSR_PE = 0x04, |
110 | UART_LSR_FE = 0x08, |
111 | UART_LSR_THRE = 0x20 |
112 | }; |
113 | |
114 | enum { |
115 | UART_CLK_125M_1 = 0x60002, |
116 | UART_CLK_125M_2 = 0x80060003, |
117 | }; |
118 | |
119 | static int |
120 | legacy_uart_probe( void ) |
121 | { |
122 | /* Verify that the Scratch Register is accessible */ |
123 | |
124 | IO_WRITE( SCR, 0x5a ); |
125 | if (IO_READ(SCR) != 0x5a) return 0; |
126 | IO_WRITE( SCR, 0xa5 ); |
127 | if (IO_READ(SCR) != 0xa5) return 0; |
128 | return 1; |
129 | } |
130 | |
131 | static void |
132 | legacy_uart_set_baud_rate( __unused int unit, uint32_t baud_rate ) |
133 | { |
134 | const unsigned char lcr = IO_READ( LCR ); |
135 | unsigned long div; |
136 | |
137 | if (baud_rate == 0) baud_rate = 9600; |
138 | div = LEGACY_UART_CLOCK / 16 / baud_rate; |
139 | IO_WRITE( LCR, lcr | UART_LCR_DLAB ); |
140 | IO_WRITE( DLM, (unsigned char)(div >> 8) ); |
141 | IO_WRITE( DLL, (unsigned char) div ); |
142 | IO_WRITE( LCR, lcr & ~UART_LCR_DLAB); |
143 | } |
144 | |
145 | static int |
146 | legacy_uart_tr0( void ) |
147 | { |
148 | return (IO_READ(LSR) & UART_LSR_THRE); |
149 | } |
150 | |
151 | static void |
152 | legacy_uart_td0( int c ) |
153 | { |
154 | IO_WRITE( THR, c ); |
155 | } |
156 | |
157 | static void |
158 | legacy_uart_init( void ) |
159 | { |
160 | /* Disable hardware interrupts */ |
161 | |
162 | IO_WRITE( MCR, 0 ); |
163 | IO_WRITE( IER, 0 ); |
164 | |
165 | /* Disable FIFO's for 16550 devices */ |
166 | |
167 | IO_WRITE( FCR, 0 ); |
168 | |
169 | /* Set for 8-bit, no parity, DLAB bit cleared */ |
170 | |
171 | IO_WRITE( LCR, UART_LCR_8BITS ); |
172 | |
173 | /* Set baud rate */ |
174 | |
175 | gPESF->uart_set_baud_rate ( 0, uart_baud_rate ); |
176 | |
177 | /* Assert DTR# and RTS# lines (OUT2?) */ |
178 | |
179 | IO_WRITE( MCR, UART_MCR_DTR | UART_MCR_RTS ); |
180 | |
181 | /* Clear any garbage in the input buffer */ |
182 | |
183 | IO_READ( RBR ); |
184 | |
185 | uart_initted = 1; |
186 | } |
187 | |
188 | static int |
189 | legacy_uart_rr0( void ) |
190 | { |
191 | unsigned char lsr; |
192 | |
193 | lsr = IO_READ( LSR ); |
194 | |
195 | if ( lsr & (UART_LSR_FE | UART_LSR_PE | UART_LSR_OE) ) |
196 | { |
197 | IO_READ( RBR ); /* discard */ |
198 | return 0; |
199 | } |
200 | |
201 | return (lsr & UART_LSR_DR); |
202 | } |
203 | |
204 | static int |
205 | legacy_uart_rd0( void ) |
206 | { |
207 | return IO_READ( RBR ); |
208 | } |
209 | |
210 | static struct pe_serial_functions legacy_uart_serial_functions = { |
211 | .uart_init = legacy_uart_init, |
212 | .uart_set_baud_rate = legacy_uart_set_baud_rate, |
213 | .tr0 = legacy_uart_tr0, |
214 | .td0 = legacy_uart_td0, |
215 | .rr0 = legacy_uart_rr0, |
216 | .rd0 = legacy_uart_rd0 |
217 | }; |
218 | |
219 | // ============================================================================= |
220 | // MMIO UART (using PCH LPSS UART2) |
221 | // ============================================================================= |
222 | |
223 | #define MMIO_UART2_BASE_LEGACY 0xFE034000 /* Legacy MMIO Config space */ |
224 | #define MMIO_UART2_BASE 0xFE036000 /* MMIO Config space */ |
225 | #define PCI_UART2 0xFE037000 /* PCI Config Space */ |
226 | |
227 | #define MMIO_WRITE(r, v) ml_phys_write_word(mmio_uart_base + MMIO_UART_##r, v) |
228 | #define MMIO_READ(r) ml_phys_read_word(mmio_uart_base + MMIO_UART_##r) |
229 | |
230 | enum { |
231 | MMIO_UART_RBR = 0x0, /* receive buffer Register (R) */ |
232 | MMIO_UART_THR = 0x0, /* transmit holding register (W) */ |
233 | MMIO_UART_DLL = 0x0, /* DLAB = 1, divisor latch (LSB) */ |
234 | MMIO_UART_IER = 0x4, /* interrupt enable register */ |
235 | MMIO_UART_DLM = 0x4, /* DLAB = 1, divisor latch (MSB) */ |
236 | MMIO_UART_FCR = 0x8, /* fifo control register (W) */ |
237 | MMIO_UART_LCR = 0xc, /* line control register */ |
238 | MMIO_UART_MCR = 0x10, /* modem control register */ |
239 | MMIO_UART_LSR = 0x14, /* line status register */ |
240 | MMIO_UART_SCR = 0x1c, /* scratch register */ |
241 | MMIO_UART_CLK = 0x200, /* clocks register */ |
242 | MMIO_UART_RST = 0x204 /* Reset register */ |
243 | }; |
244 | |
245 | static vm_offset_t mmio_uart_base = 0; |
246 | |
247 | static int |
248 | mmio_uart_present( void ) |
249 | { |
250 | MMIO_WRITE( SCR, 0x5a ); |
251 | if (MMIO_READ(SCR) != 0x5a) return 0; |
252 | MMIO_WRITE( SCR, 0xa5 ); |
253 | if (MMIO_READ(SCR) != 0xa5) return 0; |
254 | return 1; |
255 | } |
256 | |
257 | static int |
258 | mmio_uart_probe( void ) |
259 | { |
260 | unsigned new_mmio_uart_base = 0; |
261 | |
262 | // if specified, mmio_uart overrides all probing |
263 | if (PE_parse_boot_argn("mmio_uart" , &new_mmio_uart_base, sizeof (new_mmio_uart_base))) |
264 | { |
265 | // mmio_uart=0 will disable mmio_uart support |
266 | if (new_mmio_uart_base == 0) { |
267 | return 0; |
268 | } |
269 | |
270 | mmio_uart_base = new_mmio_uart_base; |
271 | return 1; |
272 | } |
273 | |
274 | // probe the two possible MMIO_UART2 addresses |
275 | mmio_uart_base = MMIO_UART2_BASE; |
276 | if (mmio_uart_present()) { |
277 | return 1; |
278 | } |
279 | |
280 | mmio_uart_base = MMIO_UART2_BASE_LEGACY; |
281 | if (mmio_uart_present()) { |
282 | return 1; |
283 | } |
284 | |
285 | // no mmio uart found |
286 | return 0; |
287 | } |
288 | |
289 | static void |
290 | mmio_uart_set_baud_rate( __unused int unit, __unused uint32_t baud_rate ) |
291 | { |
292 | const unsigned char lcr = MMIO_READ( LCR ); |
293 | unsigned long div; |
294 | |
295 | if (baud_rate == 0) baud_rate = 9600; |
296 | div = LEGACY_UART_CLOCK / 16 / baud_rate; |
297 | |
298 | MMIO_WRITE( LCR, lcr | UART_LCR_DLAB ); |
299 | MMIO_WRITE( DLM, (unsigned char)(div >> 8) ); |
300 | MMIO_WRITE( DLL, (unsigned char) div ); |
301 | MMIO_WRITE( LCR, lcr & ~UART_LCR_DLAB); |
302 | } |
303 | |
304 | static int |
305 | mmio_uart_tr0( void ) |
306 | { |
307 | return (MMIO_READ(LSR) & UART_LSR_THRE); |
308 | } |
309 | |
310 | static void |
311 | mmio_uart_td0( int c ) |
312 | { |
313 | MMIO_WRITE( THR, c ); |
314 | } |
315 | |
316 | static void |
317 | mmio_uart_init( void ) |
318 | { |
319 | /* Disable hardware interrupts */ |
320 | |
321 | MMIO_WRITE( MCR, 0 ); |
322 | MMIO_WRITE( IER, 0 ); |
323 | |
324 | /* Disable FIFO's for 16550 devices */ |
325 | |
326 | MMIO_WRITE( FCR, 0 ); |
327 | |
328 | /* Set for 8-bit, no parity, DLAB bit cleared */ |
329 | |
330 | MMIO_WRITE( LCR, UART_LCR_8BITS ); |
331 | |
332 | /* Leave baud rate as set by firmware unless serialbaud boot-arg overrides */ |
333 | |
334 | if (uart_baud_rate != DEFAULT_UART_BAUD_RATE) |
335 | { |
336 | gPESF->uart_set_baud_rate ( 0, uart_baud_rate ); |
337 | } |
338 | |
339 | /* Assert DTR# and RTS# lines (OUT2?) */ |
340 | |
341 | MMIO_WRITE( MCR, UART_MCR_DTR | UART_MCR_RTS ); |
342 | |
343 | /* Clear any garbage in the input buffer */ |
344 | |
345 | MMIO_READ( RBR ); |
346 | |
347 | uart_initted = 1; |
348 | } |
349 | |
350 | static int |
351 | mmio_uart_rr0( void ) |
352 | { |
353 | unsigned char lsr; |
354 | |
355 | lsr = MMIO_READ( LSR ); |
356 | |
357 | if ( lsr & (UART_LSR_FE | UART_LSR_PE | UART_LSR_OE) ) |
358 | { |
359 | MMIO_READ( RBR ); /* discard */ |
360 | return 0; |
361 | } |
362 | |
363 | return (lsr & UART_LSR_DR); |
364 | } |
365 | |
366 | void lpss_uart_enable( boolean_t on_off ) |
367 | { |
368 | unsigned int pmcs_reg; |
369 | |
370 | if (!lpss_uart_supported) { |
371 | return; |
372 | } |
373 | |
374 | pmcs_reg = ml_phys_read_byte (PCI_UART2 + 0x84); |
375 | if (on_off == FALSE) { |
376 | pmcs_reg |= 0x03; |
377 | lpss_uart_enabled = 0; |
378 | } else { |
379 | pmcs_reg &= ~(0x03); |
380 | } |
381 | |
382 | ml_phys_write_byte (PCI_UART2 + 0x84, pmcs_reg); |
383 | pmcs_reg = ml_phys_read_byte (PCI_UART2 + 0x84); |
384 | |
385 | if (on_off == TRUE) { |
386 | lpss_uart_re_init(); |
387 | lpss_uart_enabled = 1; |
388 | } |
389 | } |
390 | |
391 | static void lpss_uart_re_init( void ) |
392 | { |
393 | uint32_t register_read; |
394 | |
395 | MMIO_WRITE (RST, 0x7); /* LPSS UART2 controller out ot reset */ |
396 | register_read = MMIO_READ (RST); |
397 | |
398 | MMIO_WRITE (LCR, UART_LCR_DLAB); /* Set DLAB bit to enable reading/writing of DLL, DLH */ |
399 | register_read = MMIO_READ (LCR); |
400 | |
401 | MMIO_WRITE (DLL, 1); /* Divisor Latch Low Register */ |
402 | register_read = MMIO_READ (DLL); |
403 | |
404 | MMIO_WRITE (DLM, 0); /* Divisor Latch High Register */ |
405 | register_read = MMIO_READ (DLM); |
406 | |
407 | MMIO_WRITE (FCR, 1); /* Enable FIFO */ |
408 | register_read = MMIO_READ (FCR); |
409 | |
410 | MMIO_WRITE (LCR, UART_LCR_8BITS); /* Set 8 bits, clear DLAB */ |
411 | register_read = MMIO_READ (LCR); |
412 | |
413 | MMIO_WRITE (MCR, UART_MCR_RTS); /* Request to send */ |
414 | register_read = MMIO_READ (MCR); |
415 | |
416 | MMIO_WRITE (CLK, UART_CLK_125M_1); /* 1.25M Clock speed */ |
417 | register_read = MMIO_READ (CLK); |
418 | |
419 | MMIO_WRITE (CLK, UART_CLK_125M_2); /* 1.25M Clock speed */ |
420 | register_read = MMIO_READ (CLK); |
421 | } |
422 | |
423 | static int |
424 | mmio_uart_rd0( void ) |
425 | { |
426 | return MMIO_READ( RBR ); |
427 | } |
428 | |
429 | static struct pe_serial_functions mmio_uart_serial_functions = { |
430 | .uart_init = mmio_uart_init, |
431 | .uart_set_baud_rate = mmio_uart_set_baud_rate, |
432 | .tr0 = mmio_uart_tr0, |
433 | .td0 = mmio_uart_td0, |
434 | .rr0 = mmio_uart_rr0, |
435 | .rd0 = mmio_uart_rd0 |
436 | }; |
437 | |
438 | // ============================================================================= |
439 | // PCIE_MMIO UART |
440 | // ============================================================================= |
441 | |
442 | #define PCIE_MMIO_UART_BASE 0xFE410000 |
443 | |
444 | #define PCIE_MMIO_WRITE(r, v) ml_phys_write_byte(pcie_mmio_uart_base + PCIE_MMIO_UART_##r, v) |
445 | #define PCIE_MMIO_READ(r) ml_phys_read_byte(pcie_mmio_uart_base + PCIE_MMIO_UART_##r) |
446 | |
447 | enum { |
448 | PCIE_MMIO_UART_RBR = 0x0, /* receive buffer Register (R) */ |
449 | PCIE_MMIO_UART_THR = 0x0, /* transmit holding register (W) */ |
450 | PCIE_MMIO_UART_IER = 0x1, /* interrupt enable register */ |
451 | PCIE_MMIO_UART_FCR = 0x2, /* fifo control register (W) */ |
452 | PCIE_MMIO_UART_LCR = 0x4, /* line control register */ |
453 | PCIE_MMIO_UART_MCR = 0x4, /* modem control register */ |
454 | PCIE_MMIO_UART_LSR = 0x5, /* line status register */ |
455 | PCIE_MMIO_UART_DLL = 0x8, /* DLAB = 1, divisor latch (LSB) */ |
456 | PCIE_MMIO_UART_DLM = 0x9, /* DLAB = 1, divisor latch (MSB) */ |
457 | PCIE_MMIO_UART_SCR = 0x30, /* scratch register */ |
458 | }; |
459 | |
460 | static vm_offset_t pcie_mmio_uart_base = 0; |
461 | |
462 | static int |
463 | pcie_mmio_uart_present( void ) |
464 | { |
465 | |
466 | PCIE_MMIO_WRITE( SCR, 0x5a ); |
467 | if (PCIE_MMIO_READ(SCR) != 0x5a) return 0; |
468 | PCIE_MMIO_WRITE( SCR, 0xa5 ); |
469 | if (PCIE_MMIO_READ(SCR) != 0xa5) return 0; |
470 | |
471 | return 1; |
472 | } |
473 | |
474 | static int |
475 | pcie_mmio_uart_probe( void ) |
476 | { |
477 | unsigned new_pcie_mmio_uart_base = 0; |
478 | |
479 | // if specified, pcie_mmio_uart overrides all probing |
480 | if (PE_parse_boot_argn("pcie_mmio_uart" , &new_pcie_mmio_uart_base, sizeof (new_pcie_mmio_uart_base))) |
481 | { |
482 | // pcie_mmio_uart=0 will disable pcie_mmio_uart support |
483 | if (new_pcie_mmio_uart_base == 0) { |
484 | return 0; |
485 | } |
486 | pcie_mmio_uart_base = new_pcie_mmio_uart_base; |
487 | return 1; |
488 | } |
489 | |
490 | pcie_mmio_uart_base = PCIE_MMIO_UART_BASE; |
491 | if (pcie_mmio_uart_present()) { |
492 | return 1; |
493 | } |
494 | |
495 | // no pcie_mmio uart found |
496 | return 0; |
497 | } |
498 | |
499 | static void |
500 | pcie_mmio_uart_set_baud_rate( __unused int unit, __unused uint32_t baud_rate ) |
501 | { |
502 | const unsigned char lcr = PCIE_MMIO_READ( LCR ); |
503 | unsigned long div; |
504 | |
505 | if (baud_rate == 0) baud_rate = 9600; |
506 | div = LEGACY_UART_CLOCK / 16 / baud_rate; |
507 | |
508 | PCIE_MMIO_WRITE( LCR, lcr | UART_LCR_DLAB ); |
509 | PCIE_MMIO_WRITE( DLM, (unsigned char)(div >> 8) ); |
510 | PCIE_MMIO_WRITE( DLL, (unsigned char) div ); |
511 | PCIE_MMIO_WRITE( LCR, lcr & ~UART_LCR_DLAB); |
512 | } |
513 | |
514 | static int |
515 | pcie_mmio_uart_tr0( void ) |
516 | { |
517 | return (PCIE_MMIO_READ(LSR) & UART_LSR_THRE); |
518 | } |
519 | |
520 | static void |
521 | pcie_mmio_uart_td0( int c ) |
522 | { |
523 | PCIE_MMIO_WRITE( THR, c ); |
524 | } |
525 | |
526 | static void |
527 | pcie_mmio_uart_init( void ) |
528 | { |
529 | uart_initted = 1; |
530 | } |
531 | |
532 | static int |
533 | pcie_mmio_uart_rr0( void ) |
534 | { |
535 | unsigned char lsr; |
536 | |
537 | lsr = PCIE_MMIO_READ( LSR ); |
538 | |
539 | if ( lsr & (UART_LSR_FE | UART_LSR_PE | UART_LSR_OE) ) |
540 | { |
541 | PCIE_MMIO_READ( RBR ); /* discard */ |
542 | return 0; |
543 | } |
544 | |
545 | return (lsr & UART_LSR_DR); |
546 | } |
547 | |
548 | static int |
549 | pcie_mmio_uart_rd0( void ) |
550 | { |
551 | return PCIE_MMIO_READ( RBR ); |
552 | } |
553 | |
554 | static struct pe_serial_functions pcie_mmio_uart_serial_functions = { |
555 | .uart_init = pcie_mmio_uart_init, |
556 | .uart_set_baud_rate = pcie_mmio_uart_set_baud_rate, |
557 | .tr0 = pcie_mmio_uart_tr0, |
558 | .td0 = pcie_mmio_uart_td0, |
559 | .rr0 = pcie_mmio_uart_rr0, |
560 | .rd0 = pcie_mmio_uart_rd0 |
561 | }; |
562 | |
563 | // ============================================================================= |
564 | // Generic serial support below |
565 | // ============================================================================= |
566 | |
567 | int |
568 | serial_init( void ) |
569 | { |
570 | unsigned new_uart_baud_rate = 0; |
571 | |
572 | if (PE_parse_boot_argn("serialbaud" , &new_uart_baud_rate, sizeof (new_uart_baud_rate))) |
573 | { |
574 | /* Valid divisor? */ |
575 | if (!((LEGACY_UART_CLOCK / 16) % new_uart_baud_rate)) { |
576 | uart_baud_rate = new_uart_baud_rate; |
577 | } |
578 | } |
579 | |
580 | if ( mmio_uart_probe() ) |
581 | { |
582 | gPESF = &mmio_uart_serial_functions; |
583 | gPESF->uart_init(); |
584 | lpss_uart_supported = 1; |
585 | lpss_uart_enabled = 1; |
586 | return 1; |
587 | } |
588 | else if ( legacy_uart_probe() ) |
589 | { |
590 | gPESF = &legacy_uart_serial_functions; |
591 | gPESF->uart_init(); |
592 | legacy_uart_enabled = 1; |
593 | return 1; |
594 | } |
595 | else if ( pcie_mmio_uart_probe() ) |
596 | { |
597 | gPESF = &pcie_mmio_uart_serial_functions; |
598 | gPESF->uart_init(); |
599 | pcie_uart_enabled = 1; |
600 | return 1; |
601 | } |
602 | else |
603 | { |
604 | return 0; |
605 | } |
606 | |
607 | } |
608 | |
609 | static void |
610 | uart_putc(char c) |
611 | { |
612 | if (uart_initted && (legacy_uart_enabled || lpss_uart_enabled || pcie_uart_enabled)) { |
613 | while (!gPESF->tr0()); /* Wait until THR is empty. */ |
614 | gPESF->td0(c); |
615 | } |
616 | } |
617 | |
618 | static int |
619 | uart_getc(void) |
620 | { |
621 | if (uart_initted && (legacy_uart_enabled || lpss_uart_enabled || pcie_uart_enabled)) { |
622 | if (!gPESF->rr0()) |
623 | return -1; |
624 | return gPESF->rd0(); |
625 | } |
626 | return -1; |
627 | } |
628 | |
629 | void |
630 | serial_putc( char c ) |
631 | { |
632 | uart_putc(c); |
633 | } |
634 | |
635 | int |
636 | serial_getc( void ) |
637 | { |
638 | return uart_getc(); |
639 | } |
640 | |