mcu_serial.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. #include <common.h>
  2. #include <errno.h>
  3. #include <watchdog.h>
  4. #include <asm/io.h>
  5. struct pl01x_regs {
  6. u32 dr; /* 0x00 Data register */
  7. u32 ecr; /* 0x04 Error clear register (Write) */
  8. u32 pl010_lcrh; /* 0x08 Line control register, high byte */
  9. u32 pl010_lcrm; /* 0x0C Line control register, middle byte */
  10. u32 pl010_lcrl; /* 0x10 Line control register, low byte */
  11. u32 pl010_cr; /* 0x14 Control register */
  12. u32 fr; /* 0x18 Flag register (Read only) */
  13. #ifdef CONFIG_PL011_SERIAL_RLCR
  14. u32 pl011_rlcr; /* 0x1c Receive line control register */
  15. #else
  16. u32 reserved;
  17. #endif
  18. u32 ilpr; /* 0x20 IrDA low-power counter register */
  19. u32 pl011_ibrd; /* 0x24 Integer baud rate register */
  20. u32 pl011_fbrd; /* 0x28 Fractional baud rate register */
  21. u32 pl011_lcrh; /* 0x2C Line control register */
  22. u32 pl011_cr; /* 0x30 Control register */
  23. };
  24. #define UART_PL01x_RSR_OE 0x08
  25. #define UART_PL01x_RSR_BE 0x04
  26. #define UART_PL01x_RSR_PE 0x02
  27. #define UART_PL01x_RSR_FE 0x01
  28. #define UART_PL01x_FR_TXFE 0x80
  29. #define UART_PL01x_FR_RXFF 0x40
  30. #define UART_PL01x_FR_TXFF 0x20
  31. #define UART_PL01x_FR_RXFE 0x10
  32. #define UART_PL01x_FR_BUSY 0x08
  33. #define UART_PL01x_FR_TMSK (UART_PL01x_FR_TXFF + UART_PL01x_FR_BUSY)
  34. /*
  35. * PL011 definitions
  36. *
  37. */
  38. #define UART_PL011_LCRH_SPS (1 << 7)
  39. #define UART_PL011_LCRH_WLEN_8 (3 << 5)
  40. #define UART_PL011_LCRH_WLEN_7 (2 << 5)
  41. #define UART_PL011_LCRH_WLEN_6 (1 << 5)
  42. #define UART_PL011_LCRH_WLEN_5 (0 << 5)
  43. #define UART_PL011_LCRH_FEN (1 << 4)
  44. #define UART_PL011_LCRH_STP2 (1 << 3)
  45. #define UART_PL011_LCRH_EPS (1 << 2)
  46. #define UART_PL011_LCRH_PEN (1 << 1)
  47. #define UART_PL011_LCRH_BRK (1 << 0)
  48. #define UART_PL011_CR_CTSEN (1 << 15)
  49. #define UART_PL011_CR_RTSEN (1 << 14)
  50. #define UART_PL011_CR_OUT2 (1 << 13)
  51. #define UART_PL011_CR_OUT1 (1 << 12)
  52. #define UART_PL011_CR_RTS (1 << 11)
  53. #define UART_PL011_CR_DTR (1 << 10)
  54. #define UART_PL011_CR_RXE (1 << 9)
  55. #define UART_PL011_CR_TXE (1 << 8)
  56. #define UART_PL011_CR_LPE (1 << 7)
  57. #define UART_PL011_CR_IIRLP (1 << 2)
  58. #define UART_PL011_CR_SIREN (1 << 1)
  59. #define UART_PL011_CR_UARTEN (1 << 0)
  60. #define UART_PL011_IMSC_OEIM (1 << 10)
  61. #define UART_PL011_IMSC_BEIM (1 << 9)
  62. #define UART_PL011_IMSC_PEIM (1 << 8)
  63. #define UART_PL011_IMSC_FEIM (1 << 7)
  64. #define UART_PL011_IMSC_RTIM (1 << 6)
  65. #define UART_PL011_IMSC_TXIM (1 << 5)
  66. #define UART_PL011_IMSC_RXIM (1 << 4)
  67. #define UART_PL011_IMSC_DSRMIM (1 << 3)
  68. #define UART_PL011_IMSC_DCDMIM (1 << 2)
  69. #define UART_PL011_IMSC_CTSMIM (1 << 1)
  70. #define UART_PL011_IMSC_RIMIM (1 << 0)
  71. #if defined(CONFIG_ARK1668FAMILY)
  72. #define rSYS_PAD_CTRL08 *((volatile unsigned int *)(0xe49001e0))
  73. #elif defined(CONFIG_ARKN141FAMILY)
  74. #define rSYS_PAD_CTRL09 *((volatile unsigned int *)(0x404081e4))
  75. #define rSYS_APB_CLK_EN *((volatile unsigned int *)(0x40408048))
  76. #define rSYS_PER_CLK_EN *((volatile unsigned int *)(0x40408050))
  77. #endif
  78. static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS;
  79. static struct pl01x_regs *base_regs;
  80. static int pl01x_putc(struct pl01x_regs *regs, unsigned char c)
  81. {
  82. /* Wait until there is space in the FIFO */
  83. if (readl(&regs->fr) & UART_PL01x_FR_TXFF)
  84. return -EAGAIN;
  85. /* Send the character */
  86. writel(c, &regs->dr);
  87. return 0;
  88. }
  89. static int pl01x_getc(struct pl01x_regs *regs)
  90. {
  91. unsigned int data;
  92. /* Wait until there is data in the FIFO */
  93. if (readl(&regs->fr) & UART_PL01x_FR_RXFE)
  94. return -EAGAIN;
  95. data = readl(&regs->dr);
  96. /* Check for an error flag */
  97. if (data & 0xFFFFFF00) {
  98. /* Clear the error */
  99. writel(0xFFFFFFFF, &regs->ecr);
  100. return -1;
  101. }
  102. return (int) data;
  103. }
  104. static int pl01x_generic_serial_init(struct pl01x_regs *regs)
  105. {
  106. /* disable everything */
  107. writel(0, &regs->pl011_cr);
  108. return 0;
  109. }
  110. static int pl011_set_line_control(struct pl01x_regs *regs)
  111. {
  112. unsigned int lcr;
  113. /*
  114. * Internal update of baud rate register require line
  115. * control register write
  116. */
  117. lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN;
  118. writel(lcr, &regs->pl011_lcrh);
  119. return 0;
  120. }
  121. static int pl01x_generic_setbrg(struct pl01x_regs *regs, int clock, int baudrate)
  122. {
  123. unsigned int temp;
  124. unsigned int divider;
  125. unsigned int remainder;
  126. unsigned int fraction;
  127. /*
  128. * Set baud rate
  129. *
  130. * IBRD = UART_CLK / (16 * BAUD_RATE)
  131. * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
  132. * / (16 * BAUD_RATE))
  133. */
  134. temp = 16 * baudrate;
  135. divider = clock / temp;
  136. remainder = clock % temp;
  137. temp = (8 * remainder) / baudrate;
  138. fraction = (temp >> 1) + (temp & 1);
  139. writel(divider, &regs->pl011_ibrd);
  140. writel(fraction, &regs->pl011_fbrd);
  141. pl011_set_line_control(regs);
  142. /* Finally, enable the UART */
  143. writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE |
  144. UART_PL011_CR_RXE | UART_PL011_CR_RTS, &regs->pl011_cr);
  145. return 0;
  146. }
  147. static void pl01x_serial_init_baud(int baudrate)
  148. {
  149. int clock = 0;
  150. clock = CONFIG_PL011_CLOCK;
  151. base_regs = (struct pl01x_regs *)port[CONFIG_MCU_SERIAL_PORT];
  152. pl01x_generic_serial_init(base_regs);
  153. pl01x_generic_setbrg(base_regs, clock, baudrate);
  154. }
  155. int mcu_serial_init(void)
  156. {
  157. #if defined(CONFIG_ARK1668FAMILY)
  158. //uartx pad select
  159. int offset = CONFIG_MCU_SERIAL_PORT * 4;
  160. unsigned int val = rSYS_PAD_CTRL08;
  161. val &= ~(0xf << offset);
  162. val |= (1 << (offset + 2)) | (1 << offset);
  163. rSYS_PAD_CTRL08 = val;
  164. #elif defined(CONFIG_ARKN141FAMILY)
  165. //uartx pad select
  166. int offset = CONFIG_MCU_SERIAL_PORT * 4 + 16;
  167. unsigned int val = rSYS_PAD_CTRL09;
  168. val &= ~(0xf << offset);
  169. val |= (1 << (offset + 2)) | (1 << offset);
  170. rSYS_PAD_CTRL09 = val;
  171. //uartx APB CLK enable
  172. offset = CONFIG_MCU_SERIAL_PORT + 7;
  173. val = rSYS_APB_CLK_EN;
  174. val |= (1 << offset);
  175. rSYS_APB_CLK_EN = val;
  176. //uartx UART CLK enable
  177. offset = CONFIG_MCU_SERIAL_PORT + 19;
  178. val = rSYS_PER_CLK_EN;
  179. val |= (1 << offset);
  180. rSYS_PER_CLK_EN = val;
  181. #endif
  182. pl01x_serial_init_baud(CONFIG_MCU_SERIAL_BAUDRATE);
  183. return 0;
  184. }
  185. void mcu_serial_putc(const unsigned char c)
  186. {
  187. while (pl01x_putc(base_regs, c) == -EAGAIN);
  188. }
  189. void mcu_serial_puts(const unsigned char *s)
  190. {
  191. while (*s)
  192. mcu_serial_putc(*s++);
  193. }
  194. int mcu_serial_getc(void)
  195. {
  196. while (1) {
  197. int ch = pl01x_getc(base_regs);
  198. if (ch == -EAGAIN) {
  199. WATCHDOG_RESET();
  200. continue;
  201. }
  202. return ch;
  203. }
  204. }
  205. void mcu_serial_send(const unsigned char *buf, int len)
  206. {
  207. int i;
  208. for (i = 0; i < len; i++)
  209. mcu_serial_putc(buf[i]);
  210. }
  211. int mcu_serial_receive(unsigned char *buf, int len)
  212. {
  213. int length = 0;
  214. int i;
  215. for (i = 0; i < len; i++) {
  216. int ch = pl01x_getc(base_regs);
  217. if (ch == -EAGAIN) {
  218. break;
  219. }
  220. buf[length++] = ch;
  221. }
  222. return length;
  223. }
  224. int mcu_serial_read(unsigned char *buf)
  225. {
  226. int len = 0;
  227. while (1) {
  228. int ch = pl01x_getc(base_regs);
  229. if (ch == -EAGAIN) {
  230. break;
  231. }
  232. buf[len++] = ch;
  233. }
  234. return len;
  235. }