serial_s5p.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * (C) Copyright 2009 SAMSUNG Electronics
  3. * Minkyu Kang <mk7.kang@samsung.com>
  4. * Heungjun Kim <riverful.kim@samsung.com>
  5. *
  6. * based on drivers/serial/s3c64xx.c
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. *
  22. */
  23. #include <common.h>
  24. #include <fdtdec.h>
  25. #include <linux/compiler.h>
  26. #include <asm/io.h>
  27. #include <asm/arch/uart.h>
  28. #include <asm/arch/clk.h>
  29. #include <serial.h>
  30. DECLARE_GLOBAL_DATA_PTR;
  31. #define RX_FIFO_COUNT_MASK 0xff
  32. #define RX_FIFO_FULL_MASK (1 << 8)
  33. #define TX_FIFO_FULL_MASK (1 << 24)
  34. /* Information about a serial port */
  35. struct fdt_serial {
  36. u32 base_addr; /* address of registers in physical memory */
  37. u8 port_id; /* uart port number */
  38. u8 enabled; /* 1 if enabled, 0 if disabled */
  39. } config __attribute__ ((section(".data")));
  40. static inline struct s5p_uart *s5p_get_base_uart(int dev_index)
  41. {
  42. #ifdef CONFIG_OF_CONTROL
  43. return (struct s5p_uart *)(config.base_addr);
  44. #else
  45. u32 offset = dev_index * sizeof(struct s5p_uart);
  46. return (struct s5p_uart *)(samsung_get_base_uart() + offset);
  47. #endif
  48. }
  49. /*
  50. * The coefficient, used to calculate the baudrate on S5P UARTs is
  51. * calculated as
  52. * C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT
  53. * however, section 31.6.11 of the datasheet doesn't recomment using 1 for 1,
  54. * 3 for 2, ... (2^n - 1) for n, instead, they suggest using these constants:
  55. */
  56. static const int udivslot[] = {
  57. 0,
  58. 0x0080,
  59. 0x0808,
  60. 0x0888,
  61. 0x2222,
  62. 0x4924,
  63. 0x4a52,
  64. 0x54aa,
  65. 0x5555,
  66. 0xd555,
  67. 0xd5d5,
  68. 0xddd5,
  69. 0xdddd,
  70. 0xdfdd,
  71. 0xdfdf,
  72. 0xffdf,
  73. };
  74. void serial_setbrg_dev(const int dev_index)
  75. {
  76. struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
  77. u32 uclk = get_uart_clk(dev_index);
  78. u32 baudrate = gd->baudrate;
  79. u32 val;
  80. #if defined(CONFIG_SILENT_CONSOLE) && \
  81. defined(CONFIG_OF_CONTROL) && \
  82. !defined(CONFIG_SPL_BUILD)
  83. if (fdtdec_get_config_int(gd->fdt_blob, "silent_console", 0))
  84. gd->flags |= GD_FLG_SILENT;
  85. #endif
  86. if (!config.enabled)
  87. return;
  88. val = uclk / baudrate;
  89. writel(val / 16 - 1, &uart->ubrdiv);
  90. if (s5p_uart_divslot())
  91. writew(udivslot[val % 16], &uart->rest.slot);
  92. else
  93. writeb(val % 16, &uart->rest.value);
  94. }
  95. /*
  96. * Initialise the serial port with the given baudrate. The settings
  97. * are always 8 data bits, no parity, 1 stop bit, no start bits.
  98. */
  99. int serial_init_dev(const int dev_index)
  100. {
  101. struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
  102. /* enable FIFOs */
  103. writel(0x1, &uart->ufcon);
  104. writel(0, &uart->umcon);
  105. /* 8N1 */
  106. writel(0x3, &uart->ulcon);
  107. /* No interrupts, no DMA, pure polling */
  108. writel(0x245, &uart->ucon);
  109. serial_setbrg_dev(dev_index);
  110. return 0;
  111. }
  112. static int serial_err_check(const int dev_index, int op)
  113. {
  114. struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
  115. unsigned int mask;
  116. /*
  117. * UERSTAT
  118. * Break Detect [3]
  119. * Frame Err [2] : receive operation
  120. * Parity Err [1] : receive operation
  121. * Overrun Err [0] : receive operation
  122. */
  123. if (op)
  124. mask = 0x8;
  125. else
  126. mask = 0xf;
  127. return readl(&uart->uerstat) & mask;
  128. }
  129. /*
  130. * Read a single byte from the serial port. Returns 1 on success, 0
  131. * otherwise. When the function is succesfull, the character read is
  132. * written into its argument c.
  133. */
  134. int serial_getc_dev(const int dev_index)
  135. {
  136. struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
  137. if (!config.enabled)
  138. return 0;
  139. /* wait for character to arrive */
  140. while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
  141. RX_FIFO_FULL_MASK))) {
  142. if (serial_err_check(dev_index, 0))
  143. return 0;
  144. }
  145. return (int)(readb(&uart->urxh) & 0xff);
  146. }
  147. /*
  148. * Output a single byte to the serial port.
  149. */
  150. void serial_putc_dev(const char c, const int dev_index)
  151. {
  152. struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
  153. if (!config.enabled)
  154. return;
  155. /* wait for room in the tx FIFO */
  156. while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
  157. if (serial_err_check(dev_index, 1))
  158. return;
  159. }
  160. writeb(c, &uart->utxh);
  161. /* If \n, also do \r */
  162. if (c == '\n')
  163. serial_putc('\r');
  164. }
  165. /*
  166. * Test whether a character is in the RX buffer
  167. */
  168. int serial_tstc_dev(const int dev_index)
  169. {
  170. struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
  171. if (!config.enabled)
  172. return 0;
  173. return (int)(readl(&uart->utrstat) & 0x1);
  174. }
  175. void serial_puts_dev(const char *s, const int dev_index)
  176. {
  177. while (*s)
  178. serial_putc_dev(*s++, dev_index);
  179. }
  180. /* Multi serial device functions */
  181. #define DECLARE_S5P_SERIAL_FUNCTIONS(port) \
  182. int s5p_serial##port##_init(void) { return serial_init_dev(port); } \
  183. void s5p_serial##port##_setbrg(void) { serial_setbrg_dev(port); } \
  184. int s5p_serial##port##_getc(void) { return serial_getc_dev(port); } \
  185. int s5p_serial##port##_tstc(void) { return serial_tstc_dev(port); } \
  186. void s5p_serial##port##_putc(const char c) { serial_putc_dev(c, port); } \
  187. void s5p_serial##port##_puts(const char *s) { serial_puts_dev(s, port); }
  188. #define INIT_S5P_SERIAL_STRUCTURE(port, __name) { \
  189. .name = __name, \
  190. .start = s5p_serial##port##_init, \
  191. .stop = NULL, \
  192. .setbrg = s5p_serial##port##_setbrg, \
  193. .getc = s5p_serial##port##_getc, \
  194. .tstc = s5p_serial##port##_tstc, \
  195. .putc = s5p_serial##port##_putc, \
  196. .puts = s5p_serial##port##_puts, \
  197. }
  198. DECLARE_S5P_SERIAL_FUNCTIONS(0);
  199. struct serial_device s5p_serial0_device =
  200. INIT_S5P_SERIAL_STRUCTURE(0, "s5pser0");
  201. DECLARE_S5P_SERIAL_FUNCTIONS(1);
  202. struct serial_device s5p_serial1_device =
  203. INIT_S5P_SERIAL_STRUCTURE(1, "s5pser1");
  204. DECLARE_S5P_SERIAL_FUNCTIONS(2);
  205. struct serial_device s5p_serial2_device =
  206. INIT_S5P_SERIAL_STRUCTURE(2, "s5pser2");
  207. DECLARE_S5P_SERIAL_FUNCTIONS(3);
  208. struct serial_device s5p_serial3_device =
  209. INIT_S5P_SERIAL_STRUCTURE(3, "s5pser3");
  210. #ifdef CONFIG_OF_CONTROL
  211. int fdtdec_decode_console(int *index, struct fdt_serial *uart)
  212. {
  213. const void *blob = gd->fdt_blob;
  214. int node;
  215. node = fdt_path_offset(blob, "console");
  216. if (node < 0)
  217. return node;
  218. uart->base_addr = fdtdec_get_addr(blob, node, "reg");
  219. if (uart->base_addr == FDT_ADDR_T_NONE)
  220. return -FDT_ERR_NOTFOUND;
  221. uart->port_id = fdtdec_get_int(blob, node, "id", -1);
  222. uart->enabled = fdtdec_get_is_enabled(blob, node);
  223. return 0;
  224. }
  225. #endif
  226. __weak struct serial_device *default_serial_console(void)
  227. {
  228. #ifdef CONFIG_OF_CONTROL
  229. int index = 0;
  230. if ((!config.base_addr) && (fdtdec_decode_console(&index, &config))) {
  231. debug("Cannot decode default console node\n");
  232. return NULL;
  233. }
  234. switch (config.port_id) {
  235. case 0:
  236. return &s5p_serial0_device;
  237. case 1:
  238. return &s5p_serial1_device;
  239. case 2:
  240. return &s5p_serial2_device;
  241. case 3:
  242. return &s5p_serial3_device;
  243. default:
  244. debug("Unknown config.port_id: %d", config.port_id);
  245. break;
  246. }
  247. return NULL;
  248. #else
  249. config.enabled = 1;
  250. #if defined(CONFIG_SERIAL0)
  251. return &s5p_serial0_device;
  252. #elif defined(CONFIG_SERIAL1)
  253. return &s5p_serial1_device;
  254. #elif defined(CONFIG_SERIAL2)
  255. return &s5p_serial2_device;
  256. #elif defined(CONFIG_SERIAL3)
  257. return &s5p_serial3_device;
  258. #else
  259. #error "CONFIG_SERIAL? missing."
  260. #endif
  261. #endif
  262. }
  263. void s5p_serial_initialize(void)
  264. {
  265. serial_register(&s5p_serial0_device);
  266. serial_register(&s5p_serial1_device);
  267. serial_register(&s5p_serial2_device);
  268. serial_register(&s5p_serial3_device);
  269. }