uart_16550.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365
  1. /****************************************************************************
  2. * drivers/serial/uart_16550.c
  3. * Serial driver for 16550 UART
  4. *
  5. * Copyright (C) 2011, 2013, 2017-2018 Gregory Nutt. All rights reserved.
  6. * Author: Gregory Nutt <gnutt@nuttx.org>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. * 3. Neither the name NuttX nor the names of its contributors may be
  19. * used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  29. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  30. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. ****************************************************************************/
  36. /****************************************************************************
  37. * Included Files
  38. ****************************************************************************/
  39. #include <nuttx/config.h>
  40. #include <sys/types.h>
  41. #include <stdint.h>
  42. #include <stdbool.h>
  43. #include <unistd.h>
  44. #include <semaphore.h>
  45. #include <string.h>
  46. #include <errno.h>
  47. #include <debug.h>
  48. #include <nuttx/irq.h>
  49. #include <nuttx/arch.h>
  50. #include <nuttx/serial/serial.h>
  51. #include <nuttx/fs/ioctl.h>
  52. #include <nuttx/serial/uart_16550.h>
  53. #include <arch/board/board.h>
  54. #ifdef CONFIG_16550_UART
  55. /****************************************************************************
  56. * Pre-processor definitions
  57. ****************************************************************************/
  58. /****************************************************************************
  59. * Private Types
  60. ****************************************************************************/
  61. struct u16550_s
  62. {
  63. uart_addrwidth_t uartbase; /* Base address of UART registers */
  64. #ifndef CONFIG_16550_SUPRESS_CONFIG
  65. uint32_t baud; /* Configured baud */
  66. uint32_t uartclk; /* UART clock frequency */
  67. #endif
  68. uart_datawidth_t ier; /* Saved IER value */
  69. uint8_t irq; /* IRQ associated with this UART */
  70. #ifndef CONFIG_16550_SUPRESS_CONFIG
  71. uint8_t parity; /* 0=none, 1=odd, 2=even */
  72. uint8_t bits; /* Number of bits (7 or 8) */
  73. bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */
  74. #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
  75. bool flow; /* flow control (RTS/CTS) enabled */
  76. #endif
  77. #endif
  78. };
  79. /****************************************************************************
  80. * Private Function Prototypes
  81. ****************************************************************************/
  82. static int u16550_setup(FAR struct uart_dev_s *dev);
  83. static void u16550_shutdown(FAR struct uart_dev_s *dev);
  84. static int u16550_attach(FAR struct uart_dev_s *dev);
  85. static void u16550_detach(FAR struct uart_dev_s *dev);
  86. static int u16550_interrupt(int irq, FAR void *context, FAR void *arg);
  87. static int u16550_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
  88. static int u16550_receive(FAR struct uart_dev_s *dev, uint32_t *status);
  89. static void u16550_rxint(FAR struct uart_dev_s *dev, bool enable);
  90. static bool u16550_rxavailable(FAR struct uart_dev_s *dev);
  91. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  92. static bool u16550_rxflowcontrol(struct uart_dev_s *dev, unsigned int nbuffered,
  93. bool upper);
  94. #endif
  95. #ifdef CONFIG_SERIAL_DMA
  96. static void u16550_dmasend(FAR struct uart_dev_s *dev);
  97. static void u16550_dmareceive(FAR struct uart_dev_s *dev);
  98. static void u16550_dmarxfree(FAR struct uart_dev_s *dev);
  99. static void u16550_dmatxavail(FAR struct uart_dev_s *dev);
  100. #endif
  101. static void u16550_send(FAR struct uart_dev_s *dev, int ch);
  102. static void u16550_txint(FAR struct uart_dev_s *dev, bool enable);
  103. static bool u16550_txready(FAR struct uart_dev_s *dev);
  104. static bool u16550_txempty(FAR struct uart_dev_s *dev);
  105. /****************************************************************************
  106. * Private Data
  107. ****************************************************************************/
  108. static const struct uart_ops_s g_uart_ops =
  109. {
  110. .setup = u16550_setup,
  111. .shutdown = u16550_shutdown,
  112. .attach = u16550_attach,
  113. .detach = u16550_detach,
  114. .ioctl = u16550_ioctl,
  115. .receive = u16550_receive,
  116. .rxint = u16550_rxint,
  117. .rxavailable = u16550_rxavailable,
  118. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  119. .rxflowcontrol = u16550_rxflowcontrol,
  120. #endif
  121. #ifdef CONFIG_SERIAL_DMA
  122. .dmasend = u16550_dmasend,
  123. .dmareceive = u16550_dmareceive,
  124. .dmarxfree = u16550_dmarxfree,
  125. .dmatxavail = u16550_dmatxavail,
  126. #endif
  127. .send = u16550_send,
  128. .txint = u16550_txint,
  129. .txready = u16550_txready,
  130. .txempty = u16550_txempty,
  131. };
  132. /* I/O buffers */
  133. #ifdef CONFIG_16550_UART0
  134. static char g_uart0rxbuffer[CONFIG_16550_UART0_RXBUFSIZE];
  135. static char g_uart0txbuffer[CONFIG_16550_UART0_TXBUFSIZE];
  136. #endif
  137. #ifdef CONFIG_16550_UART1
  138. static char g_uart1rxbuffer[CONFIG_16550_UART1_RXBUFSIZE];
  139. static char g_uart1txbuffer[CONFIG_16550_UART1_TXBUFSIZE];
  140. #endif
  141. #ifdef CONFIG_16550_UART2
  142. static char g_uart2rxbuffer[CONFIG_16550_UART2_RXBUFSIZE];
  143. static char g_uart2txbuffer[CONFIG_16550_UART2_TXBUFSIZE];
  144. #endif
  145. #ifdef CONFIG_16550_UART3
  146. static char g_uart3rxbuffer[CONFIG_16550_UART3_RXBUFSIZE];
  147. static char g_uart3txbuffer[CONFIG_16550_UART3_TXBUFSIZE];
  148. #endif
  149. /* This describes the state of the 16550 uart0 port. */
  150. #ifdef CONFIG_16550_UART0
  151. static struct u16550_s g_uart0priv =
  152. {
  153. .uartbase = CONFIG_16550_UART0_BASE,
  154. #ifndef CONFIG_16550_SUPRESS_CONFIG
  155. .baud = CONFIG_16550_UART0_BAUD,
  156. .uartclk = CONFIG_16550_UART0_CLOCK,
  157. #endif
  158. .irq = CONFIG_16550_UART0_IRQ,
  159. #ifndef CONFIG_16550_SUPRESS_CONFIG
  160. .parity = CONFIG_16550_UART0_PARITY,
  161. .bits = CONFIG_16550_UART0_BITS,
  162. .stopbits2 = CONFIG_16550_UART0_2STOP,
  163. #if defined(CONFIG_16550_UART0_IFLOWCONTROL) || defined(CONFIG_16550_UART0_OFLOWCONTROL)
  164. .flow = true,
  165. #endif
  166. #endif
  167. };
  168. static uart_dev_t g_uart0port =
  169. {
  170. .recv =
  171. {
  172. .size = CONFIG_16550_UART0_RXBUFSIZE,
  173. .buffer = g_uart0rxbuffer,
  174. },
  175. .xmit =
  176. {
  177. .size = CONFIG_16550_UART0_TXBUFSIZE,
  178. .buffer = g_uart0txbuffer,
  179. },
  180. .ops = &g_uart_ops,
  181. .priv = &g_uart0priv,
  182. };
  183. #endif
  184. /* This describes the state of the 16550 uart1 port. */
  185. #ifdef CONFIG_16550_UART1
  186. static struct u16550_s g_uart1priv =
  187. {
  188. .uartbase = CONFIG_16550_UART1_BASE,
  189. #ifndef CONFIG_16550_SUPRESS_CONFIG
  190. .baud = CONFIG_16550_UART1_BAUD,
  191. .uartclk = CONFIG_16550_UART1_CLOCK,
  192. #endif
  193. .irq = CONFIG_16550_UART1_IRQ,
  194. #ifndef CONFIG_16550_SUPRESS_CONFIG
  195. .parity = CONFIG_16550_UART1_PARITY,
  196. .bits = CONFIG_16550_UART1_BITS,
  197. .stopbits2 = CONFIG_16550_UART1_2STOP,
  198. #if defined(CONFIG_16550_UART1_IFLOWCONTROL) || defined(CONFIG_16551_UART1_OFLOWCONTROL)
  199. .flow = true,
  200. #endif
  201. #endif
  202. };
  203. static uart_dev_t g_uart1port =
  204. {
  205. .recv =
  206. {
  207. .size = CONFIG_16550_UART1_RXBUFSIZE,
  208. .buffer = g_uart1rxbuffer,
  209. },
  210. .xmit =
  211. {
  212. .size = CONFIG_16550_UART1_TXBUFSIZE,
  213. .buffer = g_uart1txbuffer,
  214. },
  215. .ops = &g_uart_ops,
  216. .priv = &g_uart1priv,
  217. };
  218. #endif
  219. /* This describes the state of the 16550 uart1 port. */
  220. #ifdef CONFIG_16550_UART2
  221. static struct u16550_s g_uart2priv =
  222. {
  223. .uartbase = CONFIG_16550_UART2_BASE,
  224. #ifndef CONFIG_16550_SUPRESS_CONFIG
  225. .baud = CONFIG_16550_UART2_BAUD,
  226. .uartclk = CONFIG_16550_UART2_CLOCK,
  227. #endif
  228. .irq = CONFIG_16550_UART2_IRQ,
  229. #ifndef CONFIG_16550_SUPRESS_CONFIG
  230. .parity = CONFIG_16550_UART2_PARITY,
  231. .bits = CONFIG_16550_UART2_BITS,
  232. .stopbits2 = CONFIG_16550_UART2_2STOP,
  233. #if defined(CONFIG_16550_UART2_IFLOWCONTROL) || defined(CONFIG_16550_UART2_OFLOWCONTROL)
  234. .flow = true,
  235. #endif
  236. #endif
  237. };
  238. static uart_dev_t g_uart2port =
  239. {
  240. .recv =
  241. {
  242. .size = CONFIG_16550_UART2_RXBUFSIZE,
  243. .buffer = g_uart2rxbuffer,
  244. },
  245. .xmit =
  246. {
  247. .size = CONFIG_16550_UART2_TXBUFSIZE,
  248. .buffer = g_uart2txbuffer,
  249. },
  250. .ops = &g_uart_ops,
  251. .priv = &g_uart2priv,
  252. };
  253. #endif
  254. /* This describes the state of the 16550 uart1 port. */
  255. #ifdef CONFIG_16550_UART3
  256. static struct u16550_s g_uart3priv =
  257. {
  258. .uartbase = CONFIG_16550_UART3_BASE,
  259. #ifndef CONFIG_16550_SUPRESS_CONFIG
  260. .baud = CONFIG_16550_UART3_BAUD,
  261. .uartclk = CONFIG_16550_UART3_CLOCK,
  262. #endif
  263. .irq = CONFIG_16550_UART3_IRQ,
  264. #ifndef CONFIG_16550_SUPRESS_CONFIG
  265. .parity = CONFIG_16550_UART3_PARITY,
  266. .bits = CONFIG_16550_UART3_BITS,
  267. .stopbits2 = CONFIG_16550_UART3_2STOP,
  268. #if defined(CONFIG_16550_UART3_IFLOWCONTROL) || defined(CONFIG_16550_UART3_OFLOWCONTROL)
  269. .flow = true,
  270. #endif
  271. #endif
  272. };
  273. static uart_dev_t g_uart3port =
  274. {
  275. .recv =
  276. {
  277. .size = CONFIG_16550_UART3_RXBUFSIZE,
  278. .buffer = g_uart3rxbuffer,
  279. },
  280. .xmit =
  281. {
  282. .size = CONFIG_16550_UART3_TXBUFSIZE,
  283. .buffer = g_uart3txbuffer,
  284. },
  285. .ops = &g_uart_ops,
  286. .priv = &g_uart3priv,
  287. };
  288. #endif
  289. /* Which UART with be tty0/console and which tty1? tty2? tty3? */
  290. #ifdef CONFIG_16550_SERIAL_DISABLE_REORDERING
  291. # if defined(CONFIG_16550_UART0_SERIAL_CONSOLE)
  292. # define CONSOLE_DEV g_uart0port /* UART0=console */
  293. # elif defined(CONFIG_16550_UART1_SERIAL_CONSOLE)
  294. # define CONSOLE_DEV g_uart1port /* UART1=console */
  295. # elif defined(CONFIG_16550_UART2_SERIAL_CONSOLE)
  296. # define CONSOLE_DEV g_uart2port /* UART2=console */
  297. # elif defined(CONFIG_16550_UART3_SERIAL_CONSOLE)
  298. # define CONSOLE_DEV g_uart3port /* UART3=console */
  299. # endif
  300. # ifdef CONFIG_16550_UART0
  301. # define TTYS0_DEV g_uart0port
  302. # endif
  303. # ifdef CONFIG_16550_UART1
  304. # define TTYS1_DEV g_uart1port
  305. # endif
  306. # ifdef CONFIG_16550_UART2
  307. # define TTYS2_DEV g_uart2port
  308. # endif
  309. # ifdef CONFIG_16550_UART3
  310. # define TTYS3_DEV g_uart3port
  311. # endif
  312. #else /* CONFIG_16550_SERIAL_DISABLE_REORDERING */
  313. /* Which UART with be tty0/console and which tty1? tty2? tty3? */
  314. # if defined(CONFIG_16550_UART0_SERIAL_CONSOLE)
  315. # define CONSOLE_DEV g_uart0port /* UART0=console */
  316. # define TTYS0_DEV g_uart0port /* UART0=ttyS0 */
  317. # ifdef CONFIG_16550_UART1
  318. # define TTYS1_DEV g_uart1port /* UART0=ttyS0;UART1=ttyS1 */
  319. # ifdef CONFIG_16550_UART2
  320. # define TTYS2_DEV g_uart2port /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS2 */
  321. # ifdef CONFIG_16550_UART3
  322. # define TTYS3_DEV g_uart3port /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS2;UART3=ttyS3 */
  323. # else
  324. # undef TTYS3_DEV /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS;No ttyS3 */
  325. # endif
  326. # else
  327. # ifdef CONFIG_16550_UART3
  328. # define TTYS2_DEV g_uart3port /* UART0=ttyS0;UART1=ttyS1;UART3=ttys2;No ttyS3 */
  329. # else
  330. # undef TTYS2_DEV /* UART0=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */
  331. # endif
  332. # undef TTYS3_DEV /* No ttyS3 */
  333. # endif
  334. # else
  335. # ifdef CONFIG_16550_UART2
  336. # define TTYS1_DEV g_uart2port /* UART0=ttyS0;UART2=ttyS1;No ttyS3 */
  337. # ifdef CONFIG_16550_UART3
  338. # define TTYS2_DEV g_uart3port /* UART0=ttyS0;UART2=ttyS1;UART3=ttyS2;No ttyS3 */
  339. # else
  340. # undef TTYS2_DEV /* UART0=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */
  341. # endif
  342. # undef TTYS3_DEV /* No ttyS3 */
  343. # else
  344. # ifdef CONFIG_16550_UART3
  345. # define TTYS1_DEV g_uart3port /* UART0=ttyS0;UART3=ttyS1;No ttyS2;No ttyS3 */
  346. # else
  347. # undef TTYS1_DEV /* UART0=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
  348. # endif
  349. # undef TTYS2_DEV /* No ttyS2 */
  350. # undef TTYS3_DEV /* No ttyS3 */
  351. # endif
  352. # endif
  353. # elif defined(CONFIG_16550_UART1_SERIAL_CONSOLE)
  354. # define CONSOLE_DEV g_uart1port /* UART1=console */
  355. # define TTYS0_DEV g_uart1port /* UART1=ttyS0 */
  356. # ifdef CONFIG_16550_UART
  357. # define TTYS1_DEV g_uart0port /* UART1=ttyS0;UART0=ttyS1 */
  358. # ifdef CONFIG_16550_UART2
  359. # define TTYS2_DEV g_uart2port /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS2 */
  360. # ifdef CONFIG_16550_UART3
  361. # define TTYS3_DEV g_uart3port /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS2;UART3=ttyS3 */
  362. # else
  363. # undef TTYS3_DEV /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS;No ttyS3 */
  364. # endif
  365. # else
  366. # ifdef CONFIG_16550_UART3
  367. # define TTYS2_DEV g_uart3port /* UART1=ttyS0;UART0=ttyS1;UART3=ttys2;No ttyS3 */
  368. # else
  369. # undef TTYS2_DEV /* UART1=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */
  370. # endif
  371. # undef TTYS3_DEV /* No ttyS3 */
  372. # endif
  373. # else
  374. # ifdef CONFIG_16550_UART2
  375. # define TTYS1_DEV g_uart2port /* UART1=ttyS0;UART2=ttyS1 */
  376. # ifdef CONFIG_16550_UART3
  377. # define TTYS2_DEV g_uart3port /* UART1=ttyS0;UART2=ttyS1;UART3=ttyS2;No ttyS3 */
  378. # else
  379. # undef TTYS2_DEV /* UART1=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */
  380. # endif
  381. # undef TTYS3_DEV /* No ttyS3 */
  382. # else
  383. # ifdef CONFIG_16550_UART3
  384. # define TTYS1_DEV g_uart3port /* UART1=ttyS0;UART3=ttyS1;No ttyS2;No ttyS3 */
  385. # else
  386. # undef TTYS1_DEV /* UART1=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
  387. # endif
  388. # undef TTYS2_DEV /* No ttyS2 */
  389. # undef TTYS3_DEV /* No ttyS3 */
  390. # endif
  391. # endif
  392. # elif defined(CONFIG_16550_UART2_SERIAL_CONSOLE)
  393. # define CONSOLE_DEV g_uart2port /* UART2=console */
  394. # define TTYS0_DEV g_uart2port /* UART2=ttyS0 */
  395. # ifdef CONFIG_16550_UART
  396. # define TTYS1_DEV g_uart0port /* UART2=ttyS0;UART0=ttyS1 */
  397. # ifdef CONFIG_16550_UART1
  398. # define TTYS2_DEV g_uart1port /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS2 */
  399. # ifdef CONFIG_16550_UART3
  400. # define TTYS3_DEV g_uart3port /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS2;UART3=ttyS3 */
  401. # else
  402. # undef TTYS3_DEV /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS;No ttyS3 */
  403. # endif
  404. # else
  405. # ifdef CONFIG_16550_UART3
  406. # define TTYS2_DEV g_uart3port /* UART2=ttyS0;UART0=ttyS1;UART3=ttys2;No ttyS3 */
  407. # else
  408. # undef TTYS2_DEV /* UART2=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */
  409. # endif
  410. # undef TTYS3_DEV /* No ttyS3 */
  411. # endif
  412. # else
  413. # ifdef CONFIG_16550_UART1
  414. # define TTYS1_DEV g_uart1port /* UART2=ttyS0;UART1=ttyS1 */
  415. # ifdef CONFIG_16550_UART3
  416. # define TTYS2_DEV g_uart3port /* UART2=ttyS0;UART1=ttyS1;UART3=ttyS2 */
  417. # else
  418. # undef TTYS2_DEV /* UART2=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */
  419. # endif
  420. # undef TTYS3_DEV /* No ttyS3 */
  421. # else
  422. # ifdef CONFIG_16550_UART3
  423. # define TTYS1_DEV g_uart3port /* UART2=ttyS0;UART3=ttyS1;No ttyS3 */
  424. # else
  425. # undef TTYS1_DEV /* UART2=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
  426. # endif
  427. # undef TTYS2_DEV /* No ttyS2 */
  428. # undef TTYS3_DEV /* No ttyS3 */
  429. # endif
  430. # endif
  431. # elif defined(CONFIG_16550_UART3_SERIAL_CONSOLE)
  432. # define CONSOLE_DEV g_uart3port /* UART3=console */
  433. # define TTYS0_DEV g_uart3port /* UART3=ttyS0 */
  434. # ifdef CONFIG_16550_UART
  435. # define TTYS1_DEV g_uart0port /* UART3=ttyS0;UART0=ttyS1 */
  436. # ifdef CONFIG_16550_UART1
  437. # define TTYS2_DEV g_uart1port /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS2 */
  438. # ifdef CONFIG_16550_UART2
  439. # define TTYS3_DEV g_uart2port /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS2;UART2=ttyS3 */
  440. # else
  441. # undef TTYS3_DEV /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS;No ttyS3 */
  442. # endif
  443. # else
  444. # ifdef CONFIG_16550_UART2
  445. # define TTYS2_DEV g_uart2port /* UART3=ttyS0;UART0=ttyS1;UART2=ttys2;No ttyS3 */
  446. # else
  447. # undef TTYS2_DEV /* UART3=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */
  448. # endif
  449. # undef TTYS3_DEV /* No ttyS3 */
  450. # endif
  451. # else
  452. # ifdef CONFIG_16550_UART1
  453. # define TTYS1_DEV g_uart1port /* UART3=ttyS0;UART1=ttyS1 */
  454. # ifdef CONFIG_16550_UART2
  455. # define TTYS2_DEV g_uart2port /* UART3=ttyS0;UART1=ttyS1;UART2=ttyS2;No ttyS3 */
  456. # else
  457. # undef TTYS2_DEV /* UART3=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */
  458. # endif
  459. # undef TTYS3_DEV /* No ttyS3 */
  460. # else
  461. # ifdef CONFIG_16550_UART2
  462. # define TTYS1_DEV g_uart2port /* UART3=ttyS0;UART2=ttyS1;No ttyS3;No ttyS3 */
  463. # undef TTYS3_DEV /* UART3=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */
  464. # else
  465. # undef TTYS1_DEV /* UART3=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
  466. # endif
  467. # undef TTYS2_DEV /* No ttyS2 */
  468. # undef TTYS3_DEV /* No ttyS3 */
  469. # endif
  470. # endif
  471. # endif
  472. #endif /* CONFIG_16550_SERIAL_DISABLE_REORDERING */
  473. /****************************************************************************
  474. * Private Functions
  475. ****************************************************************************/
  476. /****************************************************************************
  477. * Name: u16550_serialin
  478. ****************************************************************************/
  479. static inline uart_datawidth_t u16550_serialin(FAR struct u16550_s *priv, int offset)
  480. {
  481. #ifdef CONFIG_SERIAL_UART_ARCH_MMIO
  482. return *((FAR volatile uart_addrwidth_t *)priv->uartbase + offset);
  483. #else
  484. return uart_getreg(priv->uartbase, offset);
  485. #endif
  486. }
  487. /****************************************************************************
  488. * Name: u16550_serialout
  489. ****************************************************************************/
  490. static inline void u16550_serialout(FAR struct u16550_s *priv, int offset,
  491. uart_datawidth_t value)
  492. {
  493. #ifdef CONFIG_SERIAL_UART_ARCH_MMIO
  494. *((FAR volatile uart_addrwidth_t *)priv->uartbase + offset) = value;
  495. #else
  496. uart_putreg(priv->uartbase, offset, value);
  497. #endif
  498. }
  499. /****************************************************************************
  500. * Name: u16550_disableuartint
  501. ****************************************************************************/
  502. static inline void u16550_disableuartint(FAR struct u16550_s *priv,
  503. FAR uart_datawidth_t *ier)
  504. {
  505. if (ier)
  506. {
  507. *ier = priv->ier & UART_IER_ALLIE;
  508. }
  509. priv->ier &= ~UART_IER_ALLIE;
  510. u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
  511. }
  512. /****************************************************************************
  513. * Name: u16550_restoreuartint
  514. ****************************************************************************/
  515. static inline void u16550_restoreuartint(FAR struct u16550_s *priv,
  516. uint32_t ier)
  517. {
  518. priv->ier |= ier & UART_IER_ALLIE;
  519. u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
  520. }
  521. /****************************************************************************
  522. * Name: u16550_enablebreaks
  523. ****************************************************************************/
  524. static inline void u16550_enablebreaks(FAR struct u16550_s *priv,
  525. bool enable)
  526. {
  527. uint32_t lcr = u16550_serialin(priv, UART_LCR_OFFSET);
  528. if (enable)
  529. {
  530. lcr |= UART_LCR_BRK;
  531. }
  532. else
  533. {
  534. lcr &= ~UART_LCR_BRK;
  535. }
  536. u16550_serialout(priv, UART_LCR_OFFSET, lcr);
  537. }
  538. /****************************************************************************
  539. * Name: u16550_divisor
  540. *
  541. * Description:
  542. * Select a divider to produce the BAUD from the UART_CLK.
  543. *
  544. * BAUD = UART_CLK / (16 * DL), or
  545. * DIV = UART_CLK / BAUD / 16
  546. *
  547. * Ignoring the fractional divider for now.
  548. *
  549. ****************************************************************************/
  550. #ifndef CONFIG_16550_SUPRESS_CONFIG
  551. static inline uint32_t u16550_divisor(FAR struct u16550_s *priv)
  552. {
  553. return (priv->uartclk + (priv->baud << 3)) / (priv->baud << 4);
  554. }
  555. #endif
  556. /****************************************************************************
  557. * Name: u16550_setup
  558. *
  559. * Description:
  560. * Configure the UART baud, bits, parity, fifos, etc. This
  561. * method is called the first time that the serial port is
  562. * opened.
  563. *
  564. ****************************************************************************/
  565. static int u16550_setup(FAR struct uart_dev_s *dev)
  566. {
  567. #ifndef CONFIG_16550_SUPRESS_CONFIG
  568. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  569. uint16_t div;
  570. uint32_t lcr;
  571. #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
  572. uint32_t mcr;
  573. #endif
  574. /* Clear fifos */
  575. u16550_serialout(priv, UART_FCR_OFFSET,
  576. (UART_FCR_RXRST | UART_FCR_TXRST));
  577. /* Set trigger */
  578. u16550_serialout(priv, UART_FCR_OFFSET,
  579. (UART_FCR_FIFOEN | UART_FCR_RXTRIGGER_8));
  580. /* Set up the IER */
  581. priv->ier = u16550_serialin(priv, UART_IER_OFFSET);
  582. /* Set up the LCR */
  583. lcr = 0;
  584. switch (priv->bits)
  585. {
  586. case 5 :
  587. lcr |= UART_LCR_WLS_5BIT;
  588. break;
  589. case 6 :
  590. lcr |= UART_LCR_WLS_6BIT;
  591. break;
  592. case 7 :
  593. lcr |= UART_LCR_WLS_7BIT;
  594. break;
  595. default:
  596. case 8 :
  597. lcr |= UART_LCR_WLS_8BIT;
  598. break;
  599. }
  600. if (priv->stopbits2)
  601. {
  602. lcr |= UART_LCR_STB;
  603. }
  604. if (priv->parity == 1)
  605. {
  606. lcr |= UART_LCR_PEN;
  607. }
  608. else if (priv->parity == 2)
  609. {
  610. lcr |= (UART_LCR_PEN | UART_LCR_EPS);
  611. }
  612. /* Enter DLAB=1 */
  613. u16550_serialout(priv, UART_LCR_OFFSET, (lcr | UART_LCR_DLAB));
  614. /* Set the BAUD divisor */
  615. div = u16550_divisor(priv);
  616. u16550_serialout(priv, UART_DLM_OFFSET, div >> 8);
  617. u16550_serialout(priv, UART_DLL_OFFSET, div & 0xff);
  618. /* Clear DLAB */
  619. u16550_serialout(priv, UART_LCR_OFFSET, lcr);
  620. /* Configure the FIFOs */
  621. u16550_serialout(priv, UART_FCR_OFFSET,
  622. (UART_FCR_RXTRIGGER_8 | UART_FCR_TXRST | UART_FCR_RXRST |
  623. UART_FCR_FIFOEN));
  624. /* Set up the auto flow control */
  625. #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
  626. mcr = u16550_serialin(priv, UART_MCR_OFFSET);
  627. if (priv->flow)
  628. {
  629. mcr |= UART_MCR_AFCE;
  630. }
  631. else
  632. {
  633. mcr &= ~UART_MCR_AFCE;
  634. }
  635. mcr |= UART_MCR_RTS;
  636. u16550_serialout(priv, UART_MCR_OFFSET, mcr);
  637. #endif /* defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL) */
  638. #endif
  639. return OK;
  640. }
  641. /****************************************************************************
  642. * Name: u16550_shutdown
  643. *
  644. * Description:
  645. * Disable the UART. This method is called when the serial
  646. * port is closed
  647. *
  648. ****************************************************************************/
  649. static void u16550_shutdown(struct uart_dev_s *dev)
  650. {
  651. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  652. u16550_disableuartint(priv, NULL);
  653. }
  654. /****************************************************************************
  655. * Name: u16550_attach
  656. *
  657. * Description:
  658. * Configure the UART to operation in interrupt driven mode. This method is
  659. * called when the serial port is opened. Normally, this is just after the
  660. * the setup() method is called, however, the serial console may operate in
  661. * a non-interrupt driven mode during the boot phase.
  662. *
  663. * RX and TX interrupts are not enabled when by the attach method (unless the
  664. * hardware supports multiple levels of interrupt enabling). The RX and TX
  665. * interrupts are not enabled until the txint() and rxint() methods are called.
  666. *
  667. ****************************************************************************/
  668. static int u16550_attach(struct uart_dev_s *dev)
  669. {
  670. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  671. int ret;
  672. /* Attach and enable the IRQ */
  673. ret = irq_attach(priv->irq, u16550_interrupt, dev);
  674. #ifndef CONFIG_ARCH_NOINTC
  675. if (ret == OK)
  676. {
  677. /* Enable the interrupt (RX and TX interrupts are still disabled
  678. * in the UART
  679. */
  680. up_enable_irq(priv->irq);
  681. }
  682. #endif
  683. return ret;
  684. }
  685. /****************************************************************************
  686. * Name: u16550_detach
  687. *
  688. * Description:
  689. * Detach UART interrupts. This method is called when the serial port is
  690. * closed normally just before the shutdown method is called. The exception is
  691. * the serial console which is never shutdown.
  692. *
  693. ****************************************************************************/
  694. static void u16550_detach(FAR struct uart_dev_s *dev)
  695. {
  696. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  697. up_disable_irq(priv->irq);
  698. irq_detach(priv->irq);
  699. }
  700. /****************************************************************************
  701. * Name: u16550_interrupt
  702. *
  703. * Description:
  704. * This is the UART interrupt handler. It will be invoked when an
  705. * interrupt received on the 'irq' It should call uart_transmitchars or
  706. * uart_receivechar to perform the appropriate data transfers. The
  707. * interrupt handling logic must be able to map the 'irq' number into the
  708. * appropriate u16550_s structure in order to call these functions.
  709. *
  710. ****************************************************************************/
  711. static int u16550_interrupt(int irq, FAR void *context, FAR void *arg)
  712. {
  713. FAR struct uart_dev_s *dev = (struct uart_dev_s *)arg;
  714. FAR struct u16550_s *priv;
  715. uint32_t status;
  716. int passes;
  717. DEBUGASSERT(dev != NULL && dev->priv != NULL);
  718. priv = (FAR struct u16550_s *)dev->priv;
  719. /* Loop until there are no characters to be transferred or,
  720. * until we have been looping for a long time.
  721. */
  722. for (passes = 0; passes < 256; passes++)
  723. {
  724. /* Get the current UART status and check for loop
  725. * termination conditions
  726. */
  727. status = u16550_serialin(priv, UART_IIR_OFFSET);
  728. /* The UART_IIR_INTSTATUS bit should be zero if there are pending
  729. * interrupts
  730. */
  731. if ((status & UART_IIR_INTSTATUS) != 0)
  732. {
  733. /* Break out of the loop when there is no longer a
  734. * pending interrupt
  735. */
  736. break;
  737. }
  738. /* Handle the interrupt by its interrupt ID field */
  739. switch (status & UART_IIR_INTID_MASK)
  740. {
  741. /* Handle incoming, receive bytes (with or without timeout) */
  742. case UART_IIR_INTID_RDA:
  743. case UART_IIR_INTID_CTI:
  744. {
  745. uart_recvchars(dev);
  746. break;
  747. }
  748. /* Handle outgoing, transmit bytes */
  749. case UART_IIR_INTID_THRE:
  750. {
  751. uart_xmitchars(dev);
  752. break;
  753. }
  754. /* Just clear modem status interrupts (UART1 only) */
  755. case UART_IIR_INTID_MSI:
  756. {
  757. /* Read the modem status register (MSR) to clear */
  758. status = u16550_serialin(priv, UART_MSR_OFFSET);
  759. sinfo("MSR: %02x\n", status);
  760. break;
  761. }
  762. /* Just clear any line status interrupts */
  763. case UART_IIR_INTID_RLS:
  764. {
  765. /* Read the line status register (LSR) to clear */
  766. status = u16550_serialin(priv, UART_LSR_OFFSET);
  767. sinfo("LSR: %02x\n", status);
  768. break;
  769. }
  770. /* There should be no other values */
  771. default:
  772. {
  773. serr("ERROR: Unexpected IIR: %02x\n", status);
  774. break;
  775. }
  776. }
  777. }
  778. return OK;
  779. }
  780. /****************************************************************************
  781. * Name: u16550_ioctl
  782. *
  783. * Description:
  784. * All ioctl calls will be routed through this method
  785. *
  786. ****************************************************************************/
  787. static int u16550_ioctl(struct file *filep, int cmd, unsigned long arg)
  788. {
  789. FAR struct inode *inode = filep->f_inode;
  790. FAR struct uart_dev_s *dev = inode->i_private;
  791. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  792. int ret;
  793. #ifdef CONFIG_SERIAL_UART_ARCH_IOCTL
  794. ret = uart_ioctl(filep, cmd, arg);
  795. if (ret != -ENOTTY)
  796. {
  797. return ret;
  798. }
  799. #else
  800. ret = OK;
  801. #endif
  802. switch (cmd)
  803. {
  804. #ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
  805. case TIOCSERGSTRUCT:
  806. {
  807. FAR struct u16550_s *user = (FAR struct u16550_s *)arg;
  808. if (!user)
  809. {
  810. ret = -EINVAL;
  811. }
  812. else
  813. {
  814. memcpy(user, dev, sizeof(struct u16550_s));
  815. }
  816. }
  817. break;
  818. #endif
  819. case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
  820. {
  821. irqstate_t flags = enter_critical_section();
  822. u16550_enablebreaks(priv, true);
  823. leave_critical_section(flags);
  824. }
  825. break;
  826. case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */
  827. {
  828. irqstate_t flags;
  829. flags = enter_critical_section();
  830. u16550_enablebreaks(priv, false);
  831. leave_critical_section(flags);
  832. }
  833. break;
  834. #if defined(CONFIG_SERIAL_TERMIOS) && !defined(CONFIG_16550_SUPRESS_CONFIG)
  835. case TCGETS:
  836. {
  837. FAR struct termios *termiosp = (FAR struct termios *)arg;
  838. irqstate_t flags;
  839. if (!termiosp)
  840. {
  841. ret = -EINVAL;
  842. break;
  843. }
  844. flags = enter_critical_section();
  845. cfsetispeed(termiosp, priv->baud);
  846. termiosp->c_cflag = ((priv->parity != 0) ? PARENB : 0) |
  847. ((priv->parity == 1) ? PARODD : 0);
  848. termiosp->c_cflag |= (priv->stopbits2) ? CSTOPB : 0;
  849. #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
  850. termiosp->c_cflag |= priv->flow ? CRTSCTS : 0;
  851. #endif
  852. switch (priv->bits)
  853. {
  854. case 5:
  855. termiosp->c_cflag |= CS5;
  856. break;
  857. case 6:
  858. termiosp->c_cflag |= CS6;
  859. break;
  860. case 7:
  861. termiosp->c_cflag |= CS7;
  862. break;
  863. case 8:
  864. default:
  865. termiosp->c_cflag |= CS8;
  866. break;
  867. }
  868. leave_critical_section(flags);
  869. }
  870. break;
  871. case TCSETS:
  872. {
  873. FAR struct termios *termiosp = (FAR struct termios *)arg;
  874. irqstate_t flags;
  875. if (!termiosp)
  876. {
  877. ret = -EINVAL;
  878. break;
  879. }
  880. flags = enter_critical_section();
  881. switch (termiosp->c_cflag & CSIZE)
  882. {
  883. case CS5:
  884. priv->bits = 5;
  885. break;
  886. case CS6:
  887. priv->bits = 6;
  888. break;
  889. case CS7:
  890. priv->bits = 7;
  891. break;
  892. case CS8:
  893. default:
  894. priv->bits = 8;
  895. break;
  896. }
  897. if ((termiosp->c_cflag & PARENB) != 0)
  898. {
  899. priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2;
  900. }
  901. else
  902. {
  903. priv->parity = 0;
  904. }
  905. priv->baud = cfgetispeed(termiosp);
  906. priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0;
  907. #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
  908. priv->flow = (termiosp->c_cflag & CRTSCTS) != 0;
  909. #endif
  910. u16550_setup(dev);
  911. leave_critical_section(flags);
  912. }
  913. break;
  914. #endif
  915. default:
  916. ret = -ENOTTY;
  917. break;
  918. }
  919. return ret;
  920. }
  921. /****************************************************************************
  922. * Name: u16550_receive
  923. *
  924. * Description:
  925. * Called (usually) from the interrupt level to receive one
  926. * character from the UART. Error bits associated with the
  927. * receipt are provided in the return 'status'.
  928. *
  929. ****************************************************************************/
  930. static int u16550_receive(struct uart_dev_s *dev, uint32_t *status)
  931. {
  932. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  933. uint32_t rbr;
  934. *status = u16550_serialin(priv, UART_LSR_OFFSET);
  935. rbr = u16550_serialin(priv, UART_RBR_OFFSET);
  936. return rbr;
  937. }
  938. /****************************************************************************
  939. * Name: u16550_rxint
  940. *
  941. * Description:
  942. * Call to enable or disable RX interrupts
  943. *
  944. ****************************************************************************/
  945. static void u16550_rxint(struct uart_dev_s *dev, bool enable)
  946. {
  947. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  948. if (enable)
  949. {
  950. priv->ier |= UART_IER_ERBFI;
  951. }
  952. else
  953. {
  954. priv->ier &= ~UART_IER_ERBFI;
  955. }
  956. u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
  957. }
  958. /****************************************************************************
  959. * Name: u16550_rxavailable
  960. *
  961. * Description:
  962. * Return true if the receive fifo is not empty
  963. *
  964. ****************************************************************************/
  965. static bool u16550_rxavailable(struct uart_dev_s *dev)
  966. {
  967. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  968. return ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_DR) != 0);
  969. }
  970. /****************************************************************************
  971. * Name: u16550_dma*
  972. *
  973. * Description:
  974. * Stubbed out DMA-related methods
  975. *
  976. ****************************************************************************/
  977. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  978. static bool u16550_rxflowcontrol(struct uart_dev_s *dev, unsigned int nbuffered,
  979. bool upper)
  980. {
  981. #ifndef CONFIG_16550_SUPRESS_CONFIG
  982. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  983. if (priv->flow)
  984. {
  985. /* Disable Rx interrupt to prevent more data being from
  986. * peripheral if the RX buffer is near full. When hardware
  987. * RTS is enabled, this will prevent more data from coming
  988. * in. Otherwise, enable Rx interrupt to make sure that more
  989. * input is received.
  990. */
  991. u16550_rxint(dev, !upper);
  992. return true;
  993. }
  994. #endif
  995. return false;
  996. }
  997. #endif
  998. /****************************************************************************
  999. * Name: u16550_dma*
  1000. *
  1001. * Description:
  1002. * Stub functions used when serial DMA is enabled.
  1003. *
  1004. ****************************************************************************/
  1005. #ifdef CONFIG_SERIAL_DMA
  1006. static void u16550_dmasend(FAR struct uart_dev_s *dev)
  1007. {
  1008. }
  1009. static void u16550_dmareceive(FAR struct uart_dev_s *dev)
  1010. {
  1011. }
  1012. static void u16550_dmarxfree(FAR struct uart_dev_s *dev)
  1013. {
  1014. }
  1015. static void u16550_dmatxavail(FAR struct uart_dev_s *dev)
  1016. {
  1017. }
  1018. #endif
  1019. /****************************************************************************
  1020. * Name: u16550_send
  1021. *
  1022. * Description:
  1023. * This method will send one byte on the UART
  1024. *
  1025. ****************************************************************************/
  1026. static void u16550_send(struct uart_dev_s *dev, int ch)
  1027. {
  1028. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  1029. u16550_serialout(priv, UART_THR_OFFSET, (uart_datawidth_t)ch);
  1030. }
  1031. /****************************************************************************
  1032. * Name: u16550_txint
  1033. *
  1034. * Description:
  1035. * Call to enable or disable TX interrupts
  1036. *
  1037. ****************************************************************************/
  1038. static void u16550_txint(struct uart_dev_s *dev, bool enable)
  1039. {
  1040. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  1041. irqstate_t flags;
  1042. flags = enter_critical_section();
  1043. if (enable)
  1044. {
  1045. priv->ier |= UART_IER_ETBEI;
  1046. u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
  1047. /* Fake a TX interrupt here by just calling uart_xmitchars() with
  1048. * interrupts disabled (note this may recurse).
  1049. */
  1050. uart_xmitchars(dev);
  1051. }
  1052. else
  1053. {
  1054. priv->ier &= ~UART_IER_ETBEI;
  1055. u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
  1056. }
  1057. leave_critical_section(flags);
  1058. }
  1059. /****************************************************************************
  1060. * Name: u16550_txready
  1061. *
  1062. * Description:
  1063. * Return true if the tranmsit fifo is not full
  1064. *
  1065. ****************************************************************************/
  1066. static bool u16550_txready(struct uart_dev_s *dev)
  1067. {
  1068. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  1069. return ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_THRE) != 0);
  1070. }
  1071. /****************************************************************************
  1072. * Name: u16550_txempty
  1073. *
  1074. * Description:
  1075. * Return true if the transmit fifo is empty
  1076. *
  1077. ****************************************************************************/
  1078. static bool u16550_txempty(struct uart_dev_s *dev)
  1079. {
  1080. FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
  1081. return ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_TEMT) != 0);
  1082. }
  1083. /****************************************************************************
  1084. * Name: u16550_putc
  1085. *
  1086. * Description:
  1087. * Write one character to the UART (polled)
  1088. *
  1089. ****************************************************************************/
  1090. #ifdef HAVE_16550_CONSOLE
  1091. static void u16550_putc(FAR struct u16550_s *priv, int ch)
  1092. {
  1093. while ((u16550_serialin(priv, UART_LSR_OFFSET) & UART_LSR_THRE) == 0);
  1094. u16550_serialout(priv, UART_THR_OFFSET, (uart_datawidth_t)ch);
  1095. }
  1096. #endif
  1097. /****************************************************************************
  1098. * Public Functions
  1099. ****************************************************************************/
  1100. /****************************************************************************
  1101. * Name: up_earlyserialinit
  1102. *
  1103. * Description:
  1104. * Performs the low level UART initialization early in debug so that the
  1105. * serial console will be available during bootup. This must be called
  1106. * before uart_serialinit.
  1107. *
  1108. * NOTE: Configuration of the CONSOLE UART was performed by uart_lowsetup()
  1109. * very early in the boot sequence.
  1110. *
  1111. ****************************************************************************/
  1112. void up_earlyserialinit(void)
  1113. {
  1114. /* Configuration whichever one is the console */
  1115. #ifdef CONSOLE_DEV
  1116. CONSOLE_DEV.isconsole = true;
  1117. #ifndef CONFIG_16550_SUPRESS_INITIAL_CONFIG
  1118. u16550_setup(&CONSOLE_DEV);
  1119. #endif
  1120. #endif
  1121. }
  1122. /****************************************************************************
  1123. * Name: up_serialinit
  1124. *
  1125. * Description:
  1126. * Register serial console and serial ports. This assumes that
  1127. * up_earlyserialinit was called previously.
  1128. *
  1129. ****************************************************************************/
  1130. void up_serialinit(void)
  1131. {
  1132. #ifdef CONSOLE_DEV
  1133. (void)uart_register("/dev/console", &CONSOLE_DEV);
  1134. #endif
  1135. #ifdef TTYS0_DEV
  1136. (void)uart_register("/dev/ttyS0", &TTYS0_DEV);
  1137. #endif
  1138. #ifdef TTYS1_DEV
  1139. (void)uart_register("/dev/ttyS1", &TTYS1_DEV);
  1140. #endif
  1141. #ifdef TTYS2_DEV
  1142. (void)uart_register("/dev/ttyS2", &TTYS2_DEV);
  1143. #endif
  1144. #ifdef TTYS3_DEV
  1145. (void)uart_register("/dev/ttyS3", &TTYS3_DEV);
  1146. #endif
  1147. }
  1148. /****************************************************************************
  1149. * Name: up_putc
  1150. *
  1151. * Description:
  1152. * Provide priority, low-level access to support OS debug writes
  1153. *
  1154. ****************************************************************************/
  1155. #ifdef HAVE_16550_CONSOLE
  1156. int up_putc(int ch)
  1157. {
  1158. FAR struct u16550_s *priv = (FAR struct u16550_s *)CONSOLE_DEV.priv;
  1159. uart_datawidth_t ier;
  1160. u16550_disableuartint(priv, &ier);
  1161. /* Check for LF */
  1162. if (ch == '\n')
  1163. {
  1164. /* Add CR */
  1165. u16550_putc(priv, '\r');
  1166. }
  1167. u16550_putc(priv, ch);
  1168. u16550_restoreuartint(priv, ier);
  1169. return ch;
  1170. }
  1171. #endif
  1172. #endif /* CONFIG_16550_UART */