pl11.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. pl11.c
  5. Abstract:
  6. This module implements the firmware serial port interface on a PrimeCell
  7. PL-011 UART.
  8. Author:
  9. Evan Green 27-Feb-2014
  10. Environment:
  11. Firmware
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include "uefifw.h"
  17. #include "dev/pl11.h"
  18. //
  19. // --------------------------------------------------------------------- Macros
  20. //
  21. //
  22. // This macro performs a 32-bit read from the serial port.
  23. //
  24. #define READ_SERIAL_REGISTER(_Context, _Register) \
  25. EfiReadRegister32((_Context)->UartBase + _Register)
  26. //
  27. // This macro performs a 32-bit write to the serial port.
  28. //
  29. #define WRITE_SERIAL_REGISTER(_Context, _Register, _Value) \
  30. EfiWriteRegister32((_Context)->UartBase + _Register, _Value)
  31. //
  32. // ---------------------------------------------------------------- Definitions
  33. //
  34. //
  35. // Define bits for the PL11 UART Line Control Register.
  36. //
  37. #define PL11_UART_LINE_CONTROL_FIFO_ENABLE 0x10
  38. #define PL11_UART_LINE_CONTROL_WORD_LENGTH_8BITS 0x60
  39. //
  40. // Define bits for the PL11 UART Control Register.
  41. //
  42. #define PL11_UART_CONTROL_UART_ENABLE 0x001
  43. #define PL11_UART_CONTROL_TRANSMITTER_ENABLE 0x100
  44. #define PL11_UART_CONTROL_RECEIVER_ENABLE 0x200
  45. //
  46. // Define the interrupt mask for the UART Interrupt Mask Register.
  47. //
  48. #define PL11_UART_INTERRUPT_MASK 0x7FF
  49. //
  50. // Define bits for the PL11 UART Flags Register.
  51. //
  52. #define PL11_UART_FLAG_CLEAR_TO_SEND 0x001
  53. #define PL11_UART_FLAG_DATA_SET_READY 0x002
  54. #define PL11_UART_FLAG_DATA_CARRIER_DETECT 0x004
  55. #define PL11_UART_FLAG_TRANSMIT_BUSY 0x008
  56. #define PL11_UART_FLAG_RECEIVE_EMPTY 0x010
  57. #define PL11_UART_FLAG_TRANSMIT_FULL 0x020
  58. #define PL11_UART_FLAG_RECEIVE_FULL 0x040
  59. #define PL11_UART_FLAG_TRANSMIT_EMPTY 0x080
  60. #define PL11_UART_FLAG_RING_INDICATOR 0x100
  61. //
  62. // Define bits for the PL11 UART Receive Status register.
  63. //
  64. #define PL11_UART_RECEIVE_STATUS_FRAMING_ERROR 0x0001
  65. #define PL11_UART_RECEIVE_STATUS_PARITY_ERROR 0x0002
  66. #define PL11_UART_RECEIVE_STATUS_BREAK_ERROR 0x0004
  67. #define PL11_UART_RECEIVE_STATUS_OVERRUN_ERROR 0x0008
  68. #define PL11_UART_RECEIVE_STATUS_ERROR_MASK 0x000F
  69. #define PL11_UART_RECEIVE_STATUS_ERROR_CLEAR 0xFF00
  70. //
  71. // Define the bits for the PL11 UART data register.
  72. //
  73. #define PL11_UART_DATA_BYTE_MASK 0x00FF
  74. #define PL11_UART_DATA_FRAMING_ERROR 0x0100
  75. #define PL11_UART_DATA_PARITY_ERROR 0x0200
  76. #define PL11_UART_DATA_BREAK_ERROR 0x0400
  77. #define PL11_UART_DATA_OVERRUN_ERROR 0x0800
  78. #define PL11_UART_DATA_ERROR_MASK 0x0F00
  79. //
  80. // ----------------------------------------------- Internal Function Prototypes
  81. //
  82. //
  83. // ------------------------------------------------------ Data Type Definitions
  84. //
  85. //
  86. // Register set definition for the PL-011. These are offsets in bytes, not
  87. // words.
  88. //
  89. typedef enum _PL011_REGISTER {
  90. UartDataBuffer = 0x0,
  91. UartReceiveStatus = 0x4,
  92. UartFlags = 0x18,
  93. UartIrDaLowPowerCounter = 0x20,
  94. UartIntegerBaudRate = 0x24,
  95. UartFractionalBaudRate = 0x28,
  96. UartLineControl = 0x2C,
  97. UartControl = 0x30,
  98. UartFifoInterruptLevel = 0x34,
  99. UartInterruptMask = 0x38,
  100. UartInterruptStatus = 0x3C,
  101. UartMaskedInterrupts = 0x40,
  102. UartInterruptClear = 0x44,
  103. UartDmaControl = 0x48,
  104. UartPeripheralId0 = 0xFE0,
  105. UartPeripheralId1 = 0xFE4,
  106. UartPeripheralId2 = 0xFE8,
  107. UartPeripheralId3 = 0xFEC,
  108. UartPcellId0 = 0xFF0,
  109. UartPcellId1 = 0xFF4,
  110. UartPcellId2 = 0xFF8,
  111. UartPcellId3 = 0xFFC
  112. } PL011_REGISTER, *PPL011_REGISTER;
  113. /*++
  114. Structure Description:
  115. This structures defines a baud rate for the PL011 UART.
  116. Members:
  117. BaudRate - Stores the baud rate value.
  118. IntegerDivisor - Stores the integer divisor to program into the PL011.
  119. FractionalDivisor - Stores the fractional divisor to program into the PL011.
  120. --*/
  121. typedef struct _BAUD_RATE {
  122. UINT32 BaudRate;
  123. UINT32 IntegerDivisor;
  124. UINT32 FractionalDivisor;
  125. } BAUD_RATE, *PBAUD_RATE;
  126. //
  127. // -------------------------------------------------------------------- Globals
  128. //
  129. //
  130. // Integer and fractional baud rates for an input clock of 14.7456 MHz.
  131. //
  132. BAUD_RATE EfiPl11Available14MhzRates[] = {
  133. {9600, 0x60, 0},
  134. {19200, 0x30, 0},
  135. {38400, 0x18, 0},
  136. {57600, 0x10, 0},
  137. {115200, 0x8, 0}
  138. };
  139. //
  140. // Integer and fractional baud rates for an input clock of 3 MHz.
  141. //
  142. BAUD_RATE EfiPl11Available3MhzRates[] = {
  143. {9600, 19, 34},
  144. {19200, 9, 49},
  145. {38400, 4, 57},
  146. {57600, 3, 16},
  147. {115200, 1, 40}
  148. };
  149. //
  150. // ------------------------------------------------------------------ Functions
  151. //
  152. EFI_STATUS
  153. EfipPl11ComputeDivisor (
  154. UINT32 InputClock,
  155. UINT32 BaudRate,
  156. UINT16 *IntegerDivisor,
  157. UINT16 *FractionalDivisor
  158. )
  159. /*++
  160. Routine Description:
  161. This routine computes the divisor rates for a PL-011 UART at a given baud
  162. rate.
  163. Arguments:
  164. InputClock - Supplies the input clock frequency in Hertz.
  165. BaudRate - Supplies the desired baud rate.
  166. IntegerDivisor - Supplies a pointer where the integer divisor will be
  167. returned on success.
  168. FractionalDivisor - Supplies a pointer where the fractional divisor will
  169. be returned on success.
  170. Return Value:
  171. EFI_SUCCESS on success.
  172. EFI_UNSUPPORTED if the given baud rate cannot be achieved.
  173. --*/
  174. {
  175. UINT32 BaudRateCount;
  176. PBAUD_RATE BaudRateData;
  177. PBAUD_RATE BaudRates;
  178. UINT32 RateIndex;
  179. BaudRateData = NULL;
  180. switch (InputClock) {
  181. case PL11_CLOCK_FREQUENCY_3MHZ:
  182. BaudRates = EfiPl11Available3MhzRates;
  183. BaudRateCount = sizeof(EfiPl11Available3MhzRates) /
  184. sizeof(EfiPl11Available3MhzRates[0]);
  185. break;
  186. case PL11_CLOCK_FREQUENCY_14MHZ:
  187. BaudRates = EfiPl11Available14MhzRates;
  188. BaudRateCount = sizeof(EfiPl11Available14MhzRates) /
  189. sizeof(EfiPl11Available14MhzRates[0]);
  190. break;
  191. default:
  192. return EFI_UNSUPPORTED;
  193. }
  194. for (RateIndex = 0; RateIndex < BaudRateCount; RateIndex += 1) {
  195. BaudRateData = &(BaudRates[RateIndex]);
  196. if (BaudRateData->BaudRate == BaudRate) {
  197. *IntegerDivisor = BaudRateData->IntegerDivisor;
  198. *FractionalDivisor = BaudRateData->FractionalDivisor;
  199. return EFI_SUCCESS;
  200. }
  201. }
  202. return EFI_UNSUPPORTED;
  203. }
  204. EFI_STATUS
  205. EfipPl11Initialize (
  206. PPL11_CONTEXT Context
  207. )
  208. /*++
  209. Routine Description:
  210. This routine initializes the PL-11 serial port hardware. The caller should
  211. have initialized at least some of the context structure.
  212. Arguments:
  213. Context - Supplies a pointer to the port's initialized context.
  214. Return Value:
  215. EFI Status code.
  216. --*/
  217. {
  218. UINT32 UartControlValue;
  219. UINT32 UartLineControlValue;
  220. if ((Context->UartBase == NULL) ||
  221. ((Context->BaudRateInteger == 0) && (Context->BaudRateFraction == 0))) {
  222. return EFI_INVALID_PARAMETER;
  223. }
  224. //
  225. // Program the Control Register. Enable the UART, transmitter, and receiver.
  226. // Clearing the other bits turns off hardware flow control, disables
  227. // loop-back mode, and disables IrDA features.
  228. //
  229. UartControlValue = PL11_UART_CONTROL_UART_ENABLE |
  230. PL11_UART_CONTROL_TRANSMITTER_ENABLE |
  231. PL11_UART_CONTROL_RECEIVER_ENABLE;
  232. WRITE_SERIAL_REGISTER(Context, UartControl, UartControlValue);
  233. //
  234. // Mask all interrupts.
  235. //
  236. WRITE_SERIAL_REGISTER(Context, UartInterruptMask, PL11_UART_INTERRUPT_MASK);
  237. //
  238. // Disable DMA.
  239. //
  240. WRITE_SERIAL_REGISTER(Context, UartDmaControl, 0);
  241. //
  242. // Set the correct divisor values for the chosen baud rate.
  243. //
  244. WRITE_SERIAL_REGISTER(Context,
  245. UartIntegerBaudRate,
  246. Context->BaudRateInteger);
  247. WRITE_SERIAL_REGISTER(Context,
  248. UartFractionalBaudRate,
  249. Context->BaudRateFraction);
  250. //
  251. // Program the Line Control Register. Clearing bit 4 turns off the FIFO.
  252. // Clearing bit 3 sets 1 stop bit. Clearing bit 1 sets no parity. Clearing
  253. // bit 0 means not sending a break. The TRM for the PL-011 implies that the
  254. // ordering of the Integer Baud Rate, Fractional Baud Rate, and Line Control
  255. // registers is somewhat fixed, so observe that order here.
  256. //
  257. UartLineControlValue = PL11_UART_LINE_CONTROL_FIFO_ENABLE |
  258. PL11_UART_LINE_CONTROL_WORD_LENGTH_8BITS;
  259. WRITE_SERIAL_REGISTER(Context, UartLineControl, UartLineControlValue);
  260. //
  261. // Write a 0 to the receive status register to clear all errors.
  262. //
  263. WRITE_SERIAL_REGISTER(Context, UartReceiveStatus, 0);
  264. return EFI_SUCCESS;
  265. }
  266. EFI_STATUS
  267. EfipPl11Transmit (
  268. PPL11_CONTEXT Context,
  269. VOID *Data,
  270. UINTN Size
  271. )
  272. /*++
  273. Routine Description:
  274. This routine writes data out the serial port. This routine should busily
  275. spin if the previously sent byte has not finished transmitting.
  276. Arguments:
  277. Context - Supplies the pointer to the port context.
  278. Data - Supplies a pointer to the data to write.
  279. Size - Supplies the size to write, in bytes.
  280. Return Value:
  281. EFI_SUCCESS on success.
  282. EFI_DEVICE_ERROR if a device error occurred.
  283. --*/
  284. {
  285. UINTN ByteIndex;
  286. UINT8 *Bytes;
  287. Bytes = Data;
  288. for (ByteIndex = 0; ByteIndex < Size; ByteIndex += 1) {
  289. //
  290. // Spin waiting for the buffer to become ready to send. If an error is
  291. // detected, bail out and report to the caller.
  292. //
  293. do {
  294. if ((READ_SERIAL_REGISTER(Context, UartReceiveStatus) &
  295. PL11_UART_RECEIVE_STATUS_ERROR_MASK) != 0) {
  296. return EFI_DEVICE_ERROR;
  297. }
  298. } while ((READ_SERIAL_REGISTER(Context, UartFlags) &
  299. PL11_UART_FLAG_TRANSMIT_BUSY) != 0);
  300. //
  301. // Send the byte and return.
  302. //
  303. WRITE_SERIAL_REGISTER(Context, UartDataBuffer, Bytes[ByteIndex]);
  304. }
  305. return EFI_SUCCESS;
  306. }
  307. EFI_STATUS
  308. EfipPl11Receive (
  309. PPL11_CONTEXT Context,
  310. VOID *Data,
  311. UINTN *Size
  312. )
  313. /*++
  314. Routine Description:
  315. This routine reads bytes from the serial port.
  316. Arguments:
  317. Context - Supplies the pointer to the port context.
  318. Data - Supplies a pointer where the read data will be returned on success.
  319. Size - Supplies a pointer that on input contains the size of the receive
  320. buffer. On output, returns the number of bytes read.
  321. Return Value:
  322. EFI_SUCCESS on success.
  323. EFI_NOT_READY if there was no data to be read at the current time.
  324. EFI_DEVICE_ERROR if a device error occurred.
  325. --*/
  326. {
  327. UINT32 ByteCount;
  328. UINT32 ByteIndex;
  329. UINT8 *Bytes;
  330. UINT32 DataRegister;
  331. EFI_STATUS Status;
  332. ByteCount = *Size;
  333. Bytes = Data;
  334. Status = EFI_NOT_READY;
  335. //
  336. // The receive status register contains the break, framing, and parity
  337. // error status for the character read prior to the read of the status. The
  338. // overrun error is set as soon as an overrun occurs. As a result, read the
  339. // data register rather than the status register; the data register also
  340. // returns the status bits.
  341. //
  342. for (ByteIndex = 0; ByteIndex < ByteCount; ByteIndex += 1) {
  343. if ((READ_SERIAL_REGISTER(Context, UartFlags) &
  344. PL11_UART_FLAG_RECEIVE_EMPTY) != 0) {
  345. break;
  346. }
  347. DataRegister = READ_SERIAL_REGISTER(Context, UartDataBuffer);
  348. if ((DataRegister & PL11_UART_DATA_ERROR_MASK) != 0) {
  349. //
  350. // Clear the errors and return.
  351. //
  352. WRITE_SERIAL_REGISTER(Context,
  353. UartReceiveStatus,
  354. PL11_UART_RECEIVE_STATUS_ERROR_CLEAR);
  355. Status = EFI_DEVICE_ERROR;
  356. break;
  357. }
  358. Bytes[ByteIndex] = DataRegister & PL11_UART_DATA_BYTE_MASK;
  359. Status = EFI_SUCCESS;
  360. }
  361. *Size = ByteIndex;
  362. return Status;
  363. }
  364. EFI_STATUS
  365. EfipPl11GetStatus (
  366. PPL11_CONTEXT Context,
  367. BOOLEAN *ReceiveDataAvailable
  368. )
  369. /*++
  370. Routine Description:
  371. This routine returns the current device status.
  372. Arguments:
  373. Context - Supplies a pointer to the serial port context.
  374. ReceiveDataAvailable - Supplies a pointer where a boolean will be returned
  375. indicating whether or not receive data is available.
  376. Return Value:
  377. EFI_SUCCESS on success.
  378. EFI_DEVICE_ERROR if a device error occurred.
  379. --*/
  380. {
  381. UINT32 Flags;
  382. *ReceiveDataAvailable = FALSE;
  383. Flags = READ_SERIAL_REGISTER(Context, UartFlags);
  384. if ((Flags & PL11_UART_FLAG_RECEIVE_EMPTY) == 0) {
  385. *ReceiveDataAvailable = TRUE;
  386. }
  387. return EFI_SUCCESS;
  388. }
  389. //
  390. // --------------------------------------------------------- Internal Functions
  391. //