serial_max3100.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * (C) Copyright 2003
  3. *
  4. * Pantelis Antoniou <panto@intracom.gr>
  5. * Intracom S.A.
  6. *
  7. * SPDX-License-Identifier: GPL-2.0+
  8. */
  9. #include <common.h>
  10. #include <watchdog.h>
  11. #include <serial.h>
  12. #include <linux/compiler.h>
  13. DECLARE_GLOBAL_DATA_PTR;
  14. /**************************************************************/
  15. /* convienient macros */
  16. #define MAX3100_SPI_RXD() (MAX3100_SPI_RXD_PORT & MAX3100_SPI_RXD_BIT)
  17. #define MAX3100_SPI_TXD(x) \
  18. do { \
  19. if (x) \
  20. MAX3100_SPI_TXD_PORT |= MAX3100_SPI_TXD_BIT; \
  21. else \
  22. MAX3100_SPI_TXD_PORT &= ~MAX3100_SPI_TXD_BIT; \
  23. } while(0)
  24. #define MAX3100_SPI_CLK(x) \
  25. do { \
  26. if (x) \
  27. MAX3100_SPI_CLK_PORT |= MAX3100_SPI_CLK_BIT; \
  28. else \
  29. MAX3100_SPI_CLK_PORT &= ~MAX3100_SPI_CLK_BIT; \
  30. } while(0)
  31. #define MAX3100_SPI_CLK_TOGGLE() (MAX3100_SPI_CLK_PORT ^= MAX3100_SPI_CLK_BIT)
  32. #define MAX3100_CS(x) \
  33. do { \
  34. if (x) \
  35. MAX3100_CS_PORT |= MAX3100_CS_BIT; \
  36. else \
  37. MAX3100_CS_PORT &= ~MAX3100_CS_BIT; \
  38. } while(0)
  39. /**************************************************************/
  40. /* MAX3100 definitions */
  41. #define MAX3100_WC (3 << 14) /* write configuration */
  42. #define MAX3100_RC (1 << 14) /* read configuration */
  43. #define MAX3100_WD (2 << 14) /* write data */
  44. #define MAX3100_RD (0 << 14) /* read data */
  45. /* configuration register bits */
  46. #define MAX3100_FEN (1 << 13) /* FIFO enable */
  47. #define MAX3100_SHDN (1 << 12) /* shutdown bit */
  48. #define MAX3100_TM (1 << 11) /* T bit irq mask */
  49. #define MAX3100_RM (1 << 10) /* R bit irq mask */
  50. #define MAX3100_PM (1 << 9) /* P bit irq mask */
  51. #define MAX3100_RAM (1 << 8) /* mask for RA/FE bit */
  52. #define MAX3100_IR (1 << 7) /* IRDA timing mode */
  53. #define MAX3100_ST (1 << 6) /* transmit stop bit */
  54. #define MAX3100_PE (1 << 5) /* parity enable bit */
  55. #define MAX3100_L (1 << 4) /* Length bit */
  56. #define MAX3100_B_MASK (0x000F) /* baud rate bits mask */
  57. #define MAX3100_B(x) ((x) & 0x000F) /* baud rate select bits */
  58. /* data register bits (write) */
  59. #define MAX3100_TE (1 << 10) /* transmit enable bit (active low) */
  60. #define MAX3100_RTS (1 << 9) /* request-to-send bit (inverted ~RTS pin) */
  61. /* data register bits (read) */
  62. #define MAX3100_RA (1 << 10) /* receiver activity when in shutdown mode */
  63. #define MAX3100_FE (1 << 10) /* framing error when in normal mode */
  64. #define MAX3100_CTS (1 << 9) /* clear-to-send bit (inverted ~CTS pin) */
  65. /* data register bits (both directions) */
  66. #define MAX3100_R (1 << 15) /* receive bit */
  67. #define MAX3100_T (1 << 14) /* transmit bit */
  68. #define MAX3100_P (1 << 8) /* parity bit */
  69. #define MAX3100_D_MASK 0x00FF /* data bits mask */
  70. #define MAX3100_D(x) ((x) & 0x00FF) /* data bits */
  71. /* these definitions are valid only for fOSC = 3.6864MHz */
  72. #define MAX3100_B_230400 MAX3100_B(0)
  73. #define MAX3100_B_115200 MAX3100_B(1)
  74. #define MAX3100_B_57600 MAX3100_B(2)
  75. #define MAX3100_B_38400 MAX3100_B(9)
  76. #define MAX3100_B_19200 MAX3100_B(10)
  77. #define MAX3100_B_9600 MAX3100_B(11)
  78. #define MAX3100_B_4800 MAX3100_B(12)
  79. #define MAX3100_B_2400 MAX3100_B(13)
  80. #define MAX3100_B_1200 MAX3100_B(14)
  81. #define MAX3100_B_600 MAX3100_B(15)
  82. /**************************************************************/
  83. static inline unsigned int max3100_transfer(unsigned int val)
  84. {
  85. unsigned int rx;
  86. int b;
  87. MAX3100_SPI_CLK(0);
  88. MAX3100_CS(0);
  89. rx = 0; b = 16;
  90. while (--b >= 0) {
  91. MAX3100_SPI_TXD(val & 0x8000);
  92. val <<= 1;
  93. MAX3100_SPI_CLK_TOGGLE();
  94. udelay(1);
  95. rx <<= 1;
  96. if (MAX3100_SPI_RXD())
  97. rx |= 1;
  98. MAX3100_SPI_CLK_TOGGLE();
  99. udelay(1);
  100. }
  101. MAX3100_SPI_CLK(1);
  102. MAX3100_CS(1);
  103. return rx;
  104. }
  105. /**************************************************************/
  106. /* must be power of 2 */
  107. #define RXFIFO_SZ 16
  108. static int rxfifo_cnt;
  109. static int rxfifo_in;
  110. static int rxfifo_out;
  111. static unsigned char rxfifo_buf[16];
  112. static void max3100_serial_putc_raw(int c)
  113. {
  114. unsigned int rx;
  115. while (((rx = max3100_transfer(MAX3100_RC)) & MAX3100_T) == 0)
  116. WATCHDOG_RESET();
  117. rx = max3100_transfer(MAX3100_WD | (c & 0xff));
  118. if ((rx & MAX3100_RD) != 0 && rxfifo_cnt < RXFIFO_SZ) {
  119. rxfifo_cnt++;
  120. rxfifo_buf[rxfifo_in++] = rx & 0xff;
  121. rxfifo_in &= RXFIFO_SZ - 1;
  122. }
  123. }
  124. static int max3100_serial_getc(void)
  125. {
  126. int c;
  127. unsigned int rx;
  128. while (rxfifo_cnt == 0) {
  129. rx = max3100_transfer(MAX3100_RD);
  130. if ((rx & MAX3100_R) != 0) {
  131. do {
  132. rxfifo_cnt++;
  133. rxfifo_buf[rxfifo_in++] = rx & 0xff;
  134. rxfifo_in &= RXFIFO_SZ - 1;
  135. if (rxfifo_cnt >= RXFIFO_SZ)
  136. break;
  137. } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
  138. }
  139. WATCHDOG_RESET();
  140. }
  141. rxfifo_cnt--;
  142. c = rxfifo_buf[rxfifo_out++];
  143. rxfifo_out &= RXFIFO_SZ - 1;
  144. return c;
  145. }
  146. static int max3100_serial_tstc(void)
  147. {
  148. unsigned int rx;
  149. if (rxfifo_cnt > 0)
  150. return 1;
  151. rx = max3100_transfer(MAX3100_RD);
  152. if ((rx & MAX3100_R) == 0)
  153. return 0;
  154. do {
  155. rxfifo_cnt++;
  156. rxfifo_buf[rxfifo_in++] = rx & 0xff;
  157. rxfifo_in &= RXFIFO_SZ - 1;
  158. if (rxfifo_cnt >= RXFIFO_SZ)
  159. break;
  160. } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
  161. return 1;
  162. }
  163. static int max3100_serial_init(void)
  164. {
  165. unsigned int wconf, rconf;
  166. int i;
  167. wconf = 0;
  168. /* Set baud rate */
  169. switch (gd->baudrate) {
  170. case 1200:
  171. wconf = MAX3100_B_1200;
  172. break;
  173. case 2400:
  174. wconf = MAX3100_B_2400;
  175. break;
  176. case 4800:
  177. wconf = MAX3100_B_4800;
  178. break;
  179. case 9600:
  180. wconf = MAX3100_B_9600;
  181. break;
  182. case 19200:
  183. wconf = MAX3100_B_19200;
  184. break;
  185. case 38400:
  186. wconf = MAX3100_B_38400;
  187. break;
  188. case 57600:
  189. wconf = MAX3100_B_57600;
  190. break;
  191. default:
  192. case 115200:
  193. wconf = MAX3100_B_115200;
  194. break;
  195. case 230400:
  196. wconf = MAX3100_B_230400;
  197. break;
  198. }
  199. /* try for 10ms, with a 100us gap */
  200. for (i = 0; i < 10000; i += 100) {
  201. max3100_transfer(MAX3100_WC | wconf);
  202. rconf = max3100_transfer(MAX3100_RC) & 0x3fff;
  203. if (rconf == wconf)
  204. break;
  205. udelay(100);
  206. }
  207. rxfifo_in = rxfifo_out = rxfifo_cnt = 0;
  208. return (0);
  209. }
  210. static void max3100_serial_putc(const char c)
  211. {
  212. if (c == '\n')
  213. max3100_serial_putc_raw('\r');
  214. max3100_serial_putc_raw(c);
  215. }
  216. static void max3100_serial_puts(const char *s)
  217. {
  218. while (*s)
  219. max3100_serial_putc_raw(*s++);
  220. }
  221. static void max3100_serial_setbrg(void)
  222. {
  223. }
  224. static struct serial_device max3100_serial_drv = {
  225. .name = "max3100_serial",
  226. .start = max3100_serial_init,
  227. .stop = NULL,
  228. .setbrg = max3100_serial_setbrg,
  229. .putc = max3100_serial_putc,
  230. .puts = max3100_serial_puts,
  231. .getc = max3100_serial_getc,
  232. .tstc = max3100_serial_tstc,
  233. };
  234. void max3100_serial_initialize(void)
  235. {
  236. serial_register(&max3100_serial_drv);
  237. }
  238. __weak struct serial_device *default_serial_console(void)
  239. {
  240. return &max3100_serial_drv;
  241. }