• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Serial I/O Port library functions with base address discovered from FDT
3 
4   Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
5   Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>
6   Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
7   Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
8 
9   This program and the accompanying materials
10   are licensed and made available under the terms and conditions of the BSD License
11   which accompanies this distribution.  The full text of the license may be found at
12   http://opensource.org/licenses/bsd-license.php
13 
14   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 
17 **/
18 
19 #include <Base.h>
20 
21 #include <Library/PcdLib.h>
22 #include <Library/SerialPortLib.h>
23 #include <libfdt.h>
24 
25 #include <Drivers/PL011Uart.h>
26 
27 RETURN_STATUS
28 EFIAPI
SerialPortInitialize(VOID)29 SerialPortInitialize (
30   VOID
31   )
32 {
33   //
34   // This SerialPortInitialize() function is completely empty, for a number of
35   // reasons:
36   // - if we are executing from flash, it is hard to keep state (i.e., store the
37   //   discovered base address in a global), and the most robust way to deal
38   //   with this is to discover the base address at every Write ();
39   // - calls to the Write() function in this module may be issued before this
40   //   initialization function is called: this is not a problem when the base
41   //   address of the UART is hardcoded, and only the baud rate may be wrong,
42   //   but if we don't know the base address yet, we may be poking into memory
43   //   that does not tolerate being poked into;
44   // - SEC and PEI phases produce debug output only, so with debug disabled, no
45   //   initialization (or device tree parsing) is performed at all.
46   //
47   // Note that this means that on *every* Write () call, the device tree will be
48   // parsed and the UART re-initialized. However, this is a small price to pay
49   // for having serial debug output on a UART with no fixed base address.
50   //
51   return RETURN_SUCCESS;
52 }
53 
54 STATIC
55 UINT64
SerialPortGetBaseAddress(VOID)56 SerialPortGetBaseAddress (
57   VOID
58   )
59 {
60   UINT64              BaudRate;
61   UINT32              ReceiveFifoDepth;
62   EFI_PARITY_TYPE     Parity;
63   UINT8               DataBits;
64   EFI_STOP_BITS_TYPE  StopBits;
65   VOID                *DeviceTreeBase;
66   INT32               Node, Prev;
67   INT32               Len;
68   CONST CHAR8         *Compatible;
69   CONST CHAR8         *CompatibleItem;
70   CONST UINT64        *RegProperty;
71   UINTN               UartBase;
72   RETURN_STATUS       Status;
73 
74   DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
75 
76   if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) {
77     return 0;
78   }
79 
80   //
81   // Enumerate all FDT nodes looking for a PL011 and capture its base address
82   //
83   for (Prev = 0;; Prev = Node) {
84     Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
85     if (Node < 0) {
86       break;
87     }
88 
89     Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
90     if (Compatible == NULL) {
91       continue;
92     }
93 
94     //
95     // Iterate over the NULL-separated items in the compatible string
96     //
97     for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len;
98       CompatibleItem += 1 + AsciiStrLen (CompatibleItem)) {
99 
100       if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) {
101         RegProperty = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
102         if (Len != 16) {
103           return 0;
104         }
105         UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty));
106 
107         BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate);
108         ReceiveFifoDepth = 0; // Use the default value for Fifo depth
109         Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
110         DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
111         StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits);
112 
113         Status = PL011UartInitializePort (
114                    UartBase,
115                    FixedPcdGet32 (PL011UartClkInHz),
116                    &BaudRate,
117                    &ReceiveFifoDepth,
118                    &Parity,
119                    &DataBits,
120                    &StopBits
121                    );
122         if (!EFI_ERROR (Status)) {
123           return UartBase;
124         }
125       }
126     }
127   }
128   return 0;
129 }
130 
131 /**
132   Write data to serial device.
133 
134   @param  Buffer           Point of data buffer which need to be written.
135   @param  NumberOfBytes    Number of output bytes which are cached in Buffer.
136 
137   @retval 0                Write data failed.
138   @retval !0               Actual number of bytes written to serial device.
139 
140 **/
141 UINTN
142 EFIAPI
SerialPortWrite(IN UINT8 * Buffer,IN UINTN NumberOfBytes)143 SerialPortWrite (
144   IN UINT8     *Buffer,
145   IN UINTN     NumberOfBytes
146   )
147 {
148   UINT64 SerialRegisterBase;
149 
150   SerialRegisterBase = SerialPortGetBaseAddress ();
151   if (SerialRegisterBase != 0) {
152     return PL011UartWrite ((UINTN)SerialRegisterBase, Buffer, NumberOfBytes);
153   }
154   return 0;
155 }
156 
157 /**
158   Read data from serial device and save the data in buffer.
159 
160   @param  Buffer           Point of data buffer which need to be written.
161   @param  NumberOfBytes    Size of Buffer[].
162 
163   @retval 0                Read data failed.
164   @retval !0               Actual number of bytes read from serial device.
165 
166 **/
167 UINTN
168 EFIAPI
SerialPortRead(OUT UINT8 * Buffer,IN UINTN NumberOfBytes)169 SerialPortRead (
170   OUT UINT8     *Buffer,
171   IN  UINTN     NumberOfBytes
172 )
173 {
174   return 0;
175 }
176 
177 /**
178   Check to see if any data is available to be read from the debug device.
179 
180   @retval TRUE       At least one byte of data is available to be read
181   @retval FALSE      No data is available to be read
182 
183 **/
184 BOOLEAN
185 EFIAPI
SerialPortPoll(VOID)186 SerialPortPoll (
187   VOID
188   )
189 {
190   return FALSE;
191 }
192 
193 /**
194   Sets the control bits on a serial device.
195 
196   @param[in] Control            Sets the bits of Control that are settable.
197 
198   @retval RETURN_SUCCESS        The new control bits were set on the serial device.
199   @retval RETURN_UNSUPPORTED    The serial device does not support this operation.
200   @retval RETURN_DEVICE_ERROR   The serial device is not functioning correctly.
201 
202 **/
203 RETURN_STATUS
204 EFIAPI
SerialPortSetControl(IN UINT32 Control)205 SerialPortSetControl (
206   IN UINT32 Control
207   )
208 {
209   return RETURN_UNSUPPORTED;
210 }
211 
212 /**
213   Retrieve the status of the control bits on a serial device.
214 
215   @param[out] Control           A pointer to return the current control signals from the serial device.
216 
217   @retval RETURN_SUCCESS        The control bits were read from the serial device.
218   @retval RETURN_UNSUPPORTED    The serial device does not support this operation.
219   @retval RETURN_DEVICE_ERROR   The serial device is not functioning correctly.
220 
221 **/
222 RETURN_STATUS
223 EFIAPI
SerialPortGetControl(OUT UINT32 * Control)224 SerialPortGetControl (
225   OUT UINT32 *Control
226   )
227 {
228   return RETURN_UNSUPPORTED;
229 }
230 
231 /**
232   Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
233   data bits, and stop bits on a serial device.
234 
235   @param BaudRate           The requested baud rate. A BaudRate value of 0 will use the
236                             device's default interface speed.
237                             On output, the value actually set.
238   @param ReveiveFifoDepth   The requested depth of the FIFO on the receive side of the
239                             serial interface. A ReceiveFifoDepth value of 0 will use
240                             the device's default FIFO depth.
241                             On output, the value actually set.
242   @param Timeout            The requested time out for a single character in microseconds.
243                             This timeout applies to both the transmit and receive side of the
244                             interface. A Timeout value of 0 will use the device's default time
245                             out value.
246                             On output, the value actually set.
247   @param Parity             The type of parity to use on this serial device. A Parity value of
248                             DefaultParity will use the device's default parity value.
249                             On output, the value actually set.
250   @param DataBits           The number of data bits to use on the serial device. A DataBits
251                             vaule of 0 will use the device's default data bit setting.
252                             On output, the value actually set.
253   @param StopBits           The number of stop bits to use on this serial device. A StopBits
254                             value of DefaultStopBits will use the device's default number of
255                             stop bits.
256                             On output, the value actually set.
257 
258   @retval RETURN_SUCCESS            The new attributes were set on the serial device.
259   @retval RETURN_UNSUPPORTED        The serial device does not support this operation.
260   @retval RETURN_INVALID_PARAMETER  One or more of the attributes has an unsupported value.
261   @retval RETURN_DEVICE_ERROR       The serial device is not functioning correctly.
262 
263 **/
264 RETURN_STATUS
265 EFIAPI
SerialPortSetAttributes(IN OUT UINT64 * BaudRate,IN OUT UINT32 * ReceiveFifoDepth,IN OUT UINT32 * Timeout,IN OUT EFI_PARITY_TYPE * Parity,IN OUT UINT8 * DataBits,IN OUT EFI_STOP_BITS_TYPE * StopBits)266 SerialPortSetAttributes (
267   IN OUT UINT64             *BaudRate,
268   IN OUT UINT32             *ReceiveFifoDepth,
269   IN OUT UINT32             *Timeout,
270   IN OUT EFI_PARITY_TYPE    *Parity,
271   IN OUT UINT8              *DataBits,
272   IN OUT EFI_STOP_BITS_TYPE *StopBits
273   )
274 {
275   return RETURN_UNSUPPORTED;
276 }
277 
278