serial1.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * serial.h - common serial defines for early debug and serial driver.
  3. * any functions defined here must be always_inline since
  4. * initcode cannot have function calls.
  5. *
  6. * Copyright (c) 2004-2011 Analog Devices Inc.
  7. *
  8. * Licensed under the GPL-2 or later.
  9. */
  10. #ifndef __BFIN_CPU_SERIAL1_H__
  11. #define __BFIN_CPU_SERIAL1_H__
  12. #include <asm/mach-common/bits/uart.h>
  13. #ifndef __ASSEMBLY__
  14. #include <asm/clock.h>
  15. #define MMR_UART(n) _PASTE_UART(n, UART, DLL)
  16. #ifdef UART_DLL
  17. # define UART0_DLL UART_DLL
  18. # if CONFIG_UART_CONSOLE != 0
  19. # error CONFIG_UART_CONSOLE must be 0 on parts with only one UART
  20. # endif
  21. #endif
  22. #define UART_BASE MMR_UART(CONFIG_UART_CONSOLE)
  23. #define LOB(x) ((x) & 0xFF)
  24. #define HIB(x) (((x) >> 8) & 0xFF)
  25. /*
  26. * All Blackfin system MMRs are padded to 32bits even if the register
  27. * itself is only 16bits. So use a helper macro to streamline this.
  28. */
  29. struct bfin_mmr_serial {
  30. #if BFIN_UART_HW_VER == 2
  31. u16 dll;
  32. u16 __pad_0;
  33. u16 dlh;
  34. u16 __pad_1;
  35. u16 gctl;
  36. u16 __pad_2;
  37. u16 lcr;
  38. u16 __pad_3;
  39. u16 mcr;
  40. u16 __pad_4;
  41. u16 lsr;
  42. u16 __pad_5;
  43. u16 msr;
  44. u16 __pad_6;
  45. u16 scr;
  46. u16 __pad_7;
  47. u16 ier_set;
  48. u16 __pad_8;
  49. u16 ier_clear;
  50. u16 __pad_9;
  51. u16 thr;
  52. u16 __pad_10;
  53. u16 rbr;
  54. u16 __pad_11;
  55. #else
  56. union {
  57. u16 dll;
  58. u16 thr;
  59. const u16 rbr;
  60. };
  61. const u16 __spad0;
  62. union {
  63. u16 dlh;
  64. u16 ier;
  65. };
  66. const u16 __spad1;
  67. const u16 iir;
  68. u16 __pad_0;
  69. u16 lcr;
  70. u16 __pad_1;
  71. u16 mcr;
  72. u16 __pad_2;
  73. u16 lsr;
  74. u16 __pad_3;
  75. u16 msr;
  76. u16 __pad_4;
  77. u16 scr;
  78. u16 __pad_5;
  79. const u32 __spad2;
  80. u16 gctl;
  81. u16 __pad_6;
  82. #endif
  83. };
  84. #define uart_lsr_t uint32_t
  85. #define _lsr_read(p) bfin_read(&p->lsr)
  86. #define _lsr_write(p, v) bfin_write(&p->lsr, v)
  87. #if BFIN_UART_HW_VER == 2
  88. # define ACCESS_LATCH()
  89. # define ACCESS_PORT_IER()
  90. #else
  91. # define ACCESS_LATCH() bfin_write_or(&pUART->lcr, DLAB)
  92. # define ACCESS_PORT_IER() bfin_write_and(&pUART->lcr, ~DLAB)
  93. #endif
  94. __attribute__((always_inline))
  95. static inline void serial_early_do_mach_portmux(char port, int mux_mask,
  96. int mux_func, int port_pin)
  97. {
  98. switch (port) {
  99. #if defined(__ADSPBF54x__)
  100. case 'B':
  101. bfin_write_PORTB_MUX((bfin_read_PORTB_MUX() &
  102. ~mux_mask) | mux_func);
  103. bfin_write_PORTB_FER(bfin_read_PORTB_FER() | port_pin);
  104. break;
  105. case 'E':
  106. bfin_write_PORTE_MUX((bfin_read_PORTE_MUX() &
  107. ~mux_mask) | mux_func);
  108. bfin_write_PORTE_FER(bfin_read_PORTE_FER() | port_pin);
  109. break;
  110. #endif
  111. #if defined(__ADSPBF50x__) || defined(__ADSPBF51x__) || defined(__ADSPBF52x__)
  112. case 'F':
  113. bfin_write_PORTF_MUX((bfin_read_PORTF_MUX() &
  114. ~mux_mask) | mux_func);
  115. bfin_write_PORTF_FER(bfin_read_PORTF_FER() | port_pin);
  116. break;
  117. case 'G':
  118. bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() &
  119. ~mux_mask) | mux_func);
  120. bfin_write_PORTG_FER(bfin_read_PORTG_FER() | port_pin);
  121. break;
  122. case 'H':
  123. bfin_write_PORTH_MUX((bfin_read_PORTH_MUX() &
  124. ~mux_mask) | mux_func);
  125. bfin_write_PORTH_FER(bfin_read_PORTH_FER() | port_pin);
  126. break;
  127. #endif
  128. default:
  129. break;
  130. }
  131. }
  132. __attribute__((always_inline))
  133. static inline void serial_early_do_portmux(void)
  134. {
  135. #if defined(__ADSPBF50x__)
  136. switch (CONFIG_UART_CONSOLE) {
  137. case 0:
  138. serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK,
  139. PORT_x_MUX_7_FUNC_1, PG12); /* TX: G; mux 7; func 1; PG12 */
  140. serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK,
  141. PORT_x_MUX_7_FUNC_1, PG13); /* RX: G; mux 7; func 1; PG13 */
  142. break;
  143. case 1:
  144. serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK,
  145. PORT_x_MUX_3_FUNC_1, PF7); /* TX: F; mux 3; func 1; PF6 */
  146. serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK,
  147. PORT_x_MUX_3_FUNC_1, PF6); /* RX: F; mux 3; func 1; PF7 */
  148. break;
  149. }
  150. #elif defined(__ADSPBF51x__)
  151. switch (CONFIG_UART_CONSOLE) {
  152. case 0:
  153. serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK,
  154. PORT_x_MUX_5_FUNC_2, PG9); /* TX: G; mux 5; func 2; PG9 */
  155. serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK,
  156. PORT_x_MUX_5_FUNC_2, PG10); /* RX: G; mux 5; func 2; PG10 */
  157. break;
  158. case 1:
  159. serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK,
  160. PORT_x_MUX_3_FUNC_2, PH7); /* TX: H; mux 3; func 2; PH6 */
  161. serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK,
  162. PORT_x_MUX_3_FUNC_2, PH6); /* RX: H; mux 3; func 2; PH7 */
  163. break;
  164. }
  165. #elif defined(__ADSPBF52x__)
  166. switch (CONFIG_UART_CONSOLE) {
  167. case 0:
  168. serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK,
  169. PORT_x_MUX_2_FUNC_3, PG7); /* TX: G; mux 2; func 3; PG7 */
  170. serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK,
  171. PORT_x_MUX_2_FUNC_3, PG8); /* RX: G; mux 2; func 3; PG8 */
  172. break;
  173. case 1:
  174. serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK,
  175. PORT_x_MUX_5_FUNC_3, PF14); /* TX: F; mux 5; func 3; PF14 */
  176. serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK,
  177. PORT_x_MUX_5_FUNC_3, PF15); /* RX: F; mux 5; func 3; PF15 */
  178. break;
  179. }
  180. #elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__)
  181. const uint16_t func[] = { PFDE, PFTE, };
  182. bfin_write_PORT_MUX(bfin_read_PORT_MUX() & ~func[CONFIG_UART_CONSOLE]);
  183. bfin_write_PORTF_FER(bfin_read_PORTF_FER() |
  184. (1 << P_IDENT(P_UART(RX))) |
  185. (1 << P_IDENT(P_UART(TX))));
  186. #elif defined(__ADSPBF54x__)
  187. switch (CONFIG_UART_CONSOLE) {
  188. case 0:
  189. serial_early_do_mach_portmux('E', PORT_x_MUX_7_MASK,
  190. PORT_x_MUX_7_FUNC_1, PE7); /* TX: E; mux 7; func 1; PE7 */
  191. serial_early_do_mach_portmux('E', PORT_x_MUX_8_MASK,
  192. PORT_x_MUX_8_FUNC_1, PE8); /* RX: E; mux 8; func 1; PE8 */
  193. break;
  194. case 1:
  195. serial_early_do_mach_portmux('H', PORT_x_MUX_0_MASK,
  196. PORT_x_MUX_0_FUNC_1, PH0); /* TX: H; mux 0; func 1; PH0 */
  197. serial_early_do_mach_portmux('H', PORT_x_MUX_1_MASK,
  198. PORT_x_MUX_1_FUNC_1, PH1); /* RX: H; mux 1; func 1; PH1 */
  199. break;
  200. case 2:
  201. serial_early_do_mach_portmux('B', PORT_x_MUX_4_MASK,
  202. PORT_x_MUX_4_FUNC_1, PB4); /* TX: B; mux 4; func 1; PB4 */
  203. serial_early_do_mach_portmux('B', PORT_x_MUX_5_MASK,
  204. PORT_x_MUX_5_FUNC_1, PB5); /* RX: B; mux 5; func 1; PB5 */
  205. break;
  206. case 3:
  207. serial_early_do_mach_portmux('B', PORT_x_MUX_6_MASK,
  208. PORT_x_MUX_6_FUNC_1, PB6); /* TX: B; mux 6; func 1; PB6 */
  209. serial_early_do_mach_portmux('B', PORT_x_MUX_7_MASK,
  210. PORT_x_MUX_7_FUNC_1, PB7); /* RX: B; mux 7; func 1; PB7 */
  211. break;
  212. }
  213. #elif defined(__ADSPBF561__)
  214. /* UART pins could be GPIO, but they aren't pin muxed. */
  215. #else
  216. # if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED)
  217. # error "missing portmux logic for UART"
  218. # endif
  219. #endif
  220. SSYNC();
  221. }
  222. __attribute__((always_inline))
  223. static inline int uart_init(uint32_t uart_base)
  224. {
  225. /* always enable UART -- avoids anomalies 05000309 and 05000350 */
  226. bfin_write(&pUART->gctl, UCEN);
  227. /* Set LCR to Word Lengh 8-bit word select */
  228. bfin_write(&pUART->lcr, WLS_8);
  229. SSYNC();
  230. return 0;
  231. }
  232. __attribute__((always_inline))
  233. static inline int serial_early_init(uint32_t uart_base)
  234. {
  235. /* handle portmux crap on different Blackfins */
  236. serial_do_portmux();
  237. return uart_init(uart_base);
  238. }
  239. __attribute__((always_inline))
  240. static inline int serial_early_uninit(uint32_t uart_base)
  241. {
  242. /* disable the UART by clearing UCEN */
  243. bfin_write(&pUART->gctl, 0);
  244. return 0;
  245. }
  246. __attribute__((always_inline))
  247. static inline void serial_set_divisor(uint32_t uart_base, uint16_t divisor)
  248. {
  249. /* Set DLAB in LCR to Access DLL and DLH */
  250. ACCESS_LATCH();
  251. SSYNC();
  252. /* Program the divisor to get the baud rate we want */
  253. bfin_write(&pUART->dll, LOB(divisor));
  254. bfin_write(&pUART->dlh, HIB(divisor));
  255. SSYNC();
  256. /* Clear DLAB in LCR to Access THR RBR IER */
  257. ACCESS_PORT_IER();
  258. SSYNC();
  259. }
  260. __attribute__((always_inline))
  261. static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud)
  262. {
  263. /* Translate from baud into divisor in terms of SCLK. The
  264. * weird multiplication is to make sure we over sample just
  265. * a little rather than under sample the incoming signals.
  266. */
  267. #if CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS
  268. uint16_t divisor = (early_get_uart_clk() + baud * 8) / (baud * 16)
  269. - ANOMALY_05000230;
  270. #else
  271. uint16_t divisor = early_division(early_get_uart_clk() + (baud * 8),
  272. baud * 16) - ANOMALY_05000230;
  273. #endif
  274. serial_set_divisor(uart_base, divisor);
  275. }
  276. __attribute__((always_inline))
  277. static inline void serial_early_put_div(uint16_t divisor)
  278. {
  279. uint32_t uart_base = UART_BASE;
  280. /* Set DLAB in LCR to Access DLL and DLH */
  281. ACCESS_LATCH();
  282. SSYNC();
  283. /* Program the divisor to get the baud rate we want */
  284. bfin_write(&pUART->dll, LOB(divisor));
  285. bfin_write(&pUART->dlh, HIB(divisor));
  286. SSYNC();
  287. /* Clear DLAB in LCR to Access THR RBR IER */
  288. ACCESS_PORT_IER();
  289. SSYNC();
  290. }
  291. __attribute__((always_inline))
  292. static inline uint16_t serial_early_get_div(void)
  293. {
  294. uint32_t uart_base = UART_BASE;
  295. /* Set DLAB in LCR to Access DLL and DLH */
  296. ACCESS_LATCH();
  297. SSYNC();
  298. uint8_t dll = bfin_read(&pUART->dll);
  299. uint8_t dlh = bfin_read(&pUART->dlh);
  300. uint16_t divisor = (dlh << 8) | dll;
  301. /* Clear DLAB in LCR to Access THR RBR IER */
  302. ACCESS_PORT_IER();
  303. SSYNC();
  304. return divisor;
  305. }
  306. #endif
  307. #endif