omapuart.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /*++
  2. Copyright (c) 2012 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. omapuart.c
  9. Abstract:
  10. This module implements the firmware serial port interface for the UART
  11. in the Texas Instruments OMAP3 and OMAP4.
  12. Author:
  13. Evan Green 16-Aug-2012
  14. Environment:
  15. Firmware
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include "uefifw.h"
  21. #include "dev/omapuart.h"
  22. //
  23. // --------------------------------------------------------------------- Macros
  24. //
  25. //
  26. // This macro performs a 32-bit read from the serial port.
  27. //
  28. #define READ_SERIAL_REGISTER(_Context, _Register) \
  29. EfiReadRegister32((_Context)->UartBase + _Register)
  30. //
  31. // This macro performs a 32-bit write to the serial port.
  32. //
  33. #define WRITE_SERIAL_REGISTER(_Context, _Register, _Value) \
  34. EfiWriteRegister32((_Context)->UartBase + _Register, _Value)
  35. //
  36. // ---------------------------------------------------------------- Definitions
  37. //
  38. #define OMAP_UART_SLEEP_MODE_BIT 0x00000010
  39. #define OMAP_UART_WRITE_CONFIGURATION_BIT 0x00000010
  40. //
  41. // Line Status Register bits.
  42. //
  43. #define OMAP_UART_LINE_ERRORS 0x0000009E
  44. #define OMAP_UART_TRANSMIT_DONE 0x00000020
  45. #define OMAP_UART_RECEIVE_READY 0x00000001
  46. //
  47. // Operational mode sets the UART to run with a character length of 8 bits
  48. // (bits 1:0 = 11), 1 stop bit (bit 2 = 0), and no parity (bit 3 = 0)
  49. //
  50. #define OMAP_UART_OPERATIONAL_MODE 0x00000003
  51. #define OMAP_UART_CONFIGURATION_A 0x00000080
  52. #define OMAP_UART_CONFIGURATION_B 0x000000BF
  53. #define OMAP_UART_MODE1_DISABLED 0x00000007
  54. #define OMAP_UART_MODE1_OPERATIONAL 0x00000000
  55. #define OMAP_UART_MODE2_OPERATIONAL 0x00000000
  56. //
  57. // ----------------------------------------------- Internal Function Prototypes
  58. //
  59. //
  60. // ------------------------------------------------------ Data Type Definitions
  61. //
  62. typedef enum _UART_REGISTERS {
  63. UartDivisorLow = 0x0,
  64. UartReceiveData = 0x0,
  65. UartTransmitData = 0x0,
  66. UartDivisorHigh = 0x4,
  67. UartInterruptEnable = 0x4,
  68. UartFifoControl = 0x8,
  69. UartEnhancedFeatures = 0x8,
  70. UartInterruptIdentification = 0x8,
  71. UartLineControl = 0xC,
  72. UartModemControl = 0x10,
  73. UartXOn1Character = 0x10,
  74. UartLineStatus = 0x14,
  75. UartXOn2Character = 0x14,
  76. UartTransmissionControl = 0x18,
  77. UartModemStatus = 0x18,
  78. UartXOff1Character = 0x18,
  79. UartXOff2Character = 0x1C,
  80. UartScratchpad = 0x1C,
  81. UartTriggerLevel = 0x1C,
  82. UartMode1 = 0x20,
  83. UartMode2 = 0x24,
  84. UartTransmitFrameLengthLow = 0x28,
  85. UartFifoLineStatus = 0x28,
  86. UartResume = 0x2C,
  87. UartTrasmitFrameLengthHigh = 0x2C,
  88. UartReceiveFrameLengthLow = 0x30,
  89. UartFifoStatusLow = 0x30,
  90. UartFifoStatusHigh = 0x34,
  91. UartReceiveFrameLengthHigh = 0x34,
  92. UartAutobaudStatus = 0x38,
  93. UartBofControl = 0x38,
  94. UartAuxiliaryControl = 0x3C,
  95. UartSupplementaryControl = 0x40,
  96. UartSupplementaryStatus = 0x44,
  97. UartBofLength = 0x48,
  98. UartSystemConfiguration = 0x54,
  99. UartSystemStatus = 0x58,
  100. UartWakeEnable = 0x5C,
  101. UartCarrierFrequencyPrescaler = 0x60
  102. } UART_REGISTERS, *PUART_REGISTERS;
  103. /*++
  104. Structure Description:
  105. This structure defines a baud rate for the UEFI platforms.
  106. Members:
  107. BaudRate - Stores the baud rate.
  108. BaudRateRegister - Stores the divisors for the baud rate.
  109. --*/
  110. typedef struct _BAUD_RATE {
  111. UINT32 BaudRate;
  112. UINT16 BaudRateRegister;
  113. } BAUD_RATE, *PBAUD_RATE;
  114. //
  115. // -------------------------------------------------------------------- Globals
  116. //
  117. //
  118. // Integer and fractional baud rates for the UART.
  119. //
  120. BAUD_RATE EfiOmapUartBaudRates[] = {
  121. {9600, 0x138},
  122. {19200, 0x9C},
  123. {38400, 0x4E},
  124. {57600, 0x34},
  125. {115200, 0x1A}
  126. };
  127. //
  128. // ------------------------------------------------------------------ Functions
  129. //
  130. //
  131. // --------------------------------------------------------- Internal Functions
  132. //
  133. EFI_STATUS
  134. EfipUartOmapComputeDivisor (
  135. UINTN BaudRate,
  136. UINT16 *Divisor
  137. )
  138. /*++
  139. Routine Description:
  140. This routine computes the divisor for the given baud rate.
  141. Arguments:
  142. BaudRate - Supplies the desired baud rate.
  143. Divisor - Supplies a pointer where the divisor will be returned on success.
  144. Return Value:
  145. EFI_SUCCESS on success.
  146. EFI_UNSUPPORTED if the baud rate cannot be achieved.
  147. --*/
  148. {
  149. UINTN RateCount;
  150. UINTN RateIndex;
  151. RateCount = sizeof(EfiOmapUartBaudRates) / sizeof(EfiOmapUartBaudRates[0]);
  152. for (RateIndex = 0; RateIndex < RateCount; RateIndex += 1) {
  153. if (EfiOmapUartBaudRates[RateIndex].BaudRate == BaudRate) {
  154. *Divisor = EfiOmapUartBaudRates[RateIndex].BaudRateRegister;
  155. return EFI_SUCCESS;
  156. }
  157. }
  158. return EFI_UNSUPPORTED;
  159. }
  160. EFI_STATUS
  161. EfipUartOmapInitialize (
  162. POMAP_UART_CONTEXT Context
  163. )
  164. /*++
  165. Routine Description:
  166. This routine initializes the OMAP UART controller.
  167. Arguments:
  168. Context - Supplies the pointer to the port's context. The caller should
  169. have initialized some of these members.
  170. Return Value:
  171. EFI status code.
  172. --*/
  173. {
  174. INT8 EnhancedRegister;
  175. EnhancedRegister = 0;
  176. if ((Context->UartBase == NULL) || (Context->BaudRateRegister == 0)) {
  177. return EFI_INVALID_PARAMETER;
  178. }
  179. //
  180. // Set mode to disable UART.
  181. //
  182. WRITE_SERIAL_REGISTER(Context, UartMode1, OMAP_UART_MODE1_DISABLED);
  183. //
  184. // Switch to configuration mode B, and set the Enhanced Mode bit to allow
  185. // writes to the Interrupt Enable and FIFO Control registers. Setting the
  186. // Enhanced Features register also disables auto RTC/CTS, disables
  187. // special character detection, and disables software flow control.
  188. //
  189. WRITE_SERIAL_REGISTER(Context, UartLineControl, OMAP_UART_CONFIGURATION_B);
  190. EnhancedRegister = READ_SERIAL_REGISTER(Context, UartEnhancedFeatures);
  191. WRITE_SERIAL_REGISTER(Context,
  192. UartEnhancedFeatures,
  193. EnhancedRegister | OMAP_UART_WRITE_CONFIGURATION_BIT);
  194. //
  195. // Switch to configuration mode A and set the Modem Control Register to
  196. // basically disable all modem functionality.
  197. //
  198. WRITE_SERIAL_REGISTER(Context, UartLineControl, OMAP_UART_CONFIGURATION_A);
  199. WRITE_SERIAL_REGISTER(Context, UartModemControl, 0);
  200. //
  201. // Switch back to operational mode to get to the Interrupt Enable Register.
  202. // Program the interrupt enable to 0, which masks all interrupts and
  203. // disables sleep mode. The baud rate divisors cannot be programmed unless
  204. // sleep mode is disabled.
  205. //
  206. WRITE_SERIAL_REGISTER(Context, UartLineControl, OMAP_UART_OPERATIONAL_MODE);
  207. WRITE_SERIAL_REGISTER(Context, UartInterruptEnable, 0);
  208. //
  209. // Switch to Configuration Mode B again to set the divisors. Set them to 0
  210. // for now to disable clocking, so that the FIFO control register can be
  211. // programmed.
  212. //
  213. WRITE_SERIAL_REGISTER(Context, UartLineControl, OMAP_UART_CONFIGURATION_B);
  214. WRITE_SERIAL_REGISTER(Context, UartDivisorHigh, 0);
  215. WRITE_SERIAL_REGISTER(Context, UartDivisorLow, 0);
  216. WRITE_SERIAL_REGISTER(Context, UartEnhancedFeatures, EnhancedRegister);
  217. //
  218. // Switch to Configuration Mode A and program the FIFO control register to
  219. // enable and clear the FIFOs.
  220. //
  221. WRITE_SERIAL_REGISTER(Context, UartLineControl, OMAP_UART_CONFIGURATION_A);
  222. WRITE_SERIAL_REGISTER(Context, UartFifoControl, 0x7);
  223. //
  224. // Set Supplementary Control to 0 to disable DMA. Set System Configuration
  225. // to 0 to turn off all power saving features, and set Wake Enable to 0
  226. // to disable wake on interrupt capabilities.
  227. //
  228. WRITE_SERIAL_REGISTER(Context, UartSupplementaryControl, 0);
  229. WRITE_SERIAL_REGISTER(Context, UartSystemConfiguration, 0);
  230. WRITE_SERIAL_REGISTER(Context, UartWakeEnable, 0);
  231. //
  232. // Program the real divisor values to restart the baud rate clock.
  233. //
  234. WRITE_SERIAL_REGISTER(Context,
  235. UartDivisorHigh,
  236. (UINT8)(Context->BaudRateRegister >> 8));
  237. WRITE_SERIAL_REGISTER(Context,
  238. UartDivisorLow,
  239. (UINT8)(Context->BaudRateRegister));
  240. //
  241. // Set Mode2 to 0 for normal UART operation (without pulse shaping), and
  242. // set Mode1 to 0 to enable the UART in normal UART mode (no IrDA or other
  243. // crazy modes).
  244. //
  245. WRITE_SERIAL_REGISTER(Context, UartMode2, OMAP_UART_MODE2_OPERATIONAL);
  246. WRITE_SERIAL_REGISTER(Context, UartMode1, OMAP_UART_MODE1_OPERATIONAL);
  247. //
  248. // Switch back to operational mode, which also configures the UART for the
  249. // 8-N-1 configuration, and return success.
  250. //
  251. WRITE_SERIAL_REGISTER(Context, UartLineControl, OMAP_UART_OPERATIONAL_MODE);
  252. return EFI_SUCCESS;
  253. }
  254. EFI_STATUS
  255. EfipUartOmapTransmit (
  256. POMAP_UART_CONTEXT Context,
  257. VOID *Data,
  258. UINTN Size
  259. )
  260. /*++
  261. Routine Description:
  262. This routine writes data out the serial port. This routine should busily
  263. spin if the previously sent byte has not finished transmitting.
  264. Arguments:
  265. Context - Supplies the pointer to the port context.
  266. Data - Supplies a pointer to the data to write.
  267. Size - Supplies the size to write, in bytes.
  268. Return Value:
  269. EFI_SUCCESS on success.
  270. EFI_DEVICE_ERROR if a device error occurred.
  271. --*/
  272. {
  273. UINT32 ByteIndex;
  274. UINT8 *Bytes;
  275. UINT32 StatusRegister;
  276. Bytes = Data;
  277. for (ByteIndex = 0; ByteIndex < Size; ByteIndex += 1) {
  278. //
  279. // Spin waiting for the buffer to become ready to send. If an error is
  280. // detected, bail out and report to the caller.
  281. //
  282. do {
  283. StatusRegister = READ_SERIAL_REGISTER(Context, UartLineStatus);
  284. if ((StatusRegister & OMAP_UART_LINE_ERRORS) != 0) {
  285. return EFI_DEVICE_ERROR;
  286. }
  287. } while ((StatusRegister & OMAP_UART_TRANSMIT_DONE) == 0);
  288. //
  289. // Send the byte and return.
  290. //
  291. WRITE_SERIAL_REGISTER(Context, UartTransmitData, Bytes[ByteIndex]);
  292. }
  293. return EFI_SUCCESS;
  294. }
  295. EFI_STATUS
  296. EfipUartOmapReceive (
  297. POMAP_UART_CONTEXT Context,
  298. VOID *Data,
  299. UINTN *Size
  300. )
  301. /*++
  302. Routine Description:
  303. This routine reads bytes from the serial port.
  304. Arguments:
  305. Context - Supplies the pointer to the port context.
  306. Data - Supplies a pointer where the read data will be returned on success.
  307. Size - Supplies a pointer that on input contains the size of the receive
  308. buffer. On output, returns the number of bytes read.
  309. Return Value:
  310. EFI_SUCCESS on success.
  311. EFI_NOT_READY if there was no data to be read at the current time.
  312. EFI_DEVICE_ERROR if a device error occurred.
  313. --*/
  314. {
  315. UINT32 ByteCount;
  316. UINT32 ByteIndex;
  317. UINT8 *Bytes;
  318. EFI_STATUS Status;
  319. UINT32 StatusRegister;
  320. ByteCount = *Size;
  321. Bytes = Data;
  322. Status = EFI_NOT_READY;
  323. for (ByteIndex = 0; ByteIndex < ByteCount; ByteIndex += 1) {
  324. StatusRegister = READ_SERIAL_REGISTER(Context, UartLineStatus);
  325. if ((StatusRegister & OMAP_UART_LINE_ERRORS) != 0) {
  326. Status = EFI_DEVICE_ERROR;
  327. break;
  328. }
  329. if ((StatusRegister & OMAP_UART_RECEIVE_READY) == 0) {
  330. break;
  331. }
  332. Bytes[ByteIndex] = READ_SERIAL_REGISTER(Context, UartReceiveData);
  333. Status = EFI_SUCCESS;
  334. }
  335. *Size = ByteIndex;
  336. return Status;
  337. }
  338. EFI_STATUS
  339. EfipUartOmapGetStatus (
  340. POMAP_UART_CONTEXT Context,
  341. BOOLEAN *ReceiveDataAvailable
  342. )
  343. /*++
  344. Routine Description:
  345. This routine returns the current device status.
  346. Arguments:
  347. Context - Supplies a pointer to the serial port context.
  348. ReceiveDataAvailable - Supplies a pointer where a boolean will be returned
  349. indicating whether or not receive data is available.
  350. Return Value:
  351. EFI_SUCCESS on success.
  352. EFI_DEVICE_ERROR if a device error occurred.
  353. --*/
  354. {
  355. UINT32 StatusRegister;
  356. *ReceiveDataAvailable = FALSE;
  357. StatusRegister = READ_SERIAL_REGISTER(Context, UartLineStatus);
  358. if ((StatusRegister & OMAP_UART_RECEIVE_READY) != 0) {
  359. *ReceiveDataAvailable = TRUE;
  360. }
  361. return EFI_SUCCESS;
  362. }
  363. //
  364. // --------------------------------------------------------- Internal Functions
  365. //