serial_max3100.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * (C) Copyright 2003
  3. *
  4. * Pantelis Antoniou <panto@intracom.gr>
  5. * Intracom S.A.
  6. *
  7. * See file CREDITS for list of people who contributed to this
  8. * project.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation; either version 2 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23. * MA 02111-1307 USA
  24. */
  25. #include <common.h>
  26. #include <watchdog.h>
  27. #ifdef CONFIG_MAX3100_SERIAL
  28. DECLARE_GLOBAL_DATA_PTR;
  29. /**************************************************************/
  30. /* convienient macros */
  31. #define MAX3100_SPI_RXD() (MAX3100_SPI_RXD_PORT & MAX3100_SPI_RXD_BIT)
  32. #define MAX3100_SPI_TXD(x) \
  33. do { \
  34. if (x) \
  35. MAX3100_SPI_TXD_PORT |= MAX3100_SPI_TXD_BIT; \
  36. else \
  37. MAX3100_SPI_TXD_PORT &= ~MAX3100_SPI_TXD_BIT; \
  38. } while(0)
  39. #define MAX3100_SPI_CLK(x) \
  40. do { \
  41. if (x) \
  42. MAX3100_SPI_CLK_PORT |= MAX3100_SPI_CLK_BIT; \
  43. else \
  44. MAX3100_SPI_CLK_PORT &= ~MAX3100_SPI_CLK_BIT; \
  45. } while(0)
  46. #define MAX3100_SPI_CLK_TOGGLE() (MAX3100_SPI_CLK_PORT ^= MAX3100_SPI_CLK_BIT)
  47. #define MAX3100_CS(x) \
  48. do { \
  49. if (x) \
  50. MAX3100_CS_PORT |= MAX3100_CS_BIT; \
  51. else \
  52. MAX3100_CS_PORT &= ~MAX3100_CS_BIT; \
  53. } while(0)
  54. /**************************************************************/
  55. /* MAX3100 definitions */
  56. #define MAX3100_WC (3 << 14) /* write configuration */
  57. #define MAX3100_RC (1 << 14) /* read configuration */
  58. #define MAX3100_WD (2 << 14) /* write data */
  59. #define MAX3100_RD (0 << 14) /* read data */
  60. /* configuration register bits */
  61. #define MAX3100_FEN (1 << 13) /* FIFO enable */
  62. #define MAX3100_SHDN (1 << 12) /* shutdown bit */
  63. #define MAX3100_TM (1 << 11) /* T bit irq mask */
  64. #define MAX3100_RM (1 << 10) /* R bit irq mask */
  65. #define MAX3100_PM (1 << 9) /* P bit irq mask */
  66. #define MAX3100_RAM (1 << 8) /* mask for RA/FE bit */
  67. #define MAX3100_IR (1 << 7) /* IRDA timing mode */
  68. #define MAX3100_ST (1 << 6) /* transmit stop bit */
  69. #define MAX3100_PE (1 << 5) /* parity enable bit */
  70. #define MAX3100_L (1 << 4) /* Length bit */
  71. #define MAX3100_B_MASK (0x000F) /* baud rate bits mask */
  72. #define MAX3100_B(x) ((x) & 0x000F) /* baud rate select bits */
  73. /* data register bits (write) */
  74. #define MAX3100_TE (1 << 10) /* transmit enable bit (active low) */
  75. #define MAX3100_RTS (1 << 9) /* request-to-send bit (inverted ~RTS pin) */
  76. /* data register bits (read) */
  77. #define MAX3100_RA (1 << 10) /* receiver activity when in shutdown mode */
  78. #define MAX3100_FE (1 << 10) /* framing error when in normal mode */
  79. #define MAX3100_CTS (1 << 9) /* clear-to-send bit (inverted ~CTS pin) */
  80. /* data register bits (both directions) */
  81. #define MAX3100_R (1 << 15) /* receive bit */
  82. #define MAX3100_T (1 << 14) /* transmit bit */
  83. #define MAX3100_P (1 << 8) /* parity bit */
  84. #define MAX3100_D_MASK 0x00FF /* data bits mask */
  85. #define MAX3100_D(x) ((x) & 0x00FF) /* data bits */
  86. /* these definitions are valid only for fOSC = 3.6864MHz */
  87. #define MAX3100_B_230400 MAX3100_B(0)
  88. #define MAX3100_B_115200 MAX3100_B(1)
  89. #define MAX3100_B_57600 MAX3100_B(2)
  90. #define MAX3100_B_38400 MAX3100_B(9)
  91. #define MAX3100_B_19200 MAX3100_B(10)
  92. #define MAX3100_B_9600 MAX3100_B(11)
  93. #define MAX3100_B_4800 MAX3100_B(12)
  94. #define MAX3100_B_2400 MAX3100_B(13)
  95. #define MAX3100_B_1200 MAX3100_B(14)
  96. #define MAX3100_B_600 MAX3100_B(15)
  97. /**************************************************************/
  98. static inline unsigned int max3100_transfer(unsigned int val)
  99. {
  100. unsigned int rx;
  101. int b;
  102. MAX3100_SPI_CLK(0);
  103. MAX3100_CS(0);
  104. rx = 0; b = 16;
  105. while (--b >= 0) {
  106. MAX3100_SPI_TXD(val & 0x8000);
  107. val <<= 1;
  108. MAX3100_SPI_CLK_TOGGLE();
  109. udelay(1);
  110. rx <<= 1;
  111. if (MAX3100_SPI_RXD())
  112. rx |= 1;
  113. MAX3100_SPI_CLK_TOGGLE();
  114. udelay(1);
  115. }
  116. MAX3100_SPI_CLK(1);
  117. MAX3100_CS(1);
  118. return rx;
  119. }
  120. /**************************************************************/
  121. /* must be power of 2 */
  122. #define RXFIFO_SZ 16
  123. static int rxfifo_cnt;
  124. static int rxfifo_in;
  125. static int rxfifo_out;
  126. static unsigned char rxfifo_buf[16];
  127. static void max3100_putc(int c)
  128. {
  129. unsigned int rx;
  130. while (((rx = max3100_transfer(MAX3100_RC)) & MAX3100_T) == 0)
  131. WATCHDOG_RESET();
  132. rx = max3100_transfer(MAX3100_WD | (c & 0xff));
  133. if ((rx & MAX3100_RD) != 0 && rxfifo_cnt < RXFIFO_SZ) {
  134. rxfifo_cnt++;
  135. rxfifo_buf[rxfifo_in++] = rx & 0xff;
  136. rxfifo_in &= RXFIFO_SZ - 1;
  137. }
  138. }
  139. static int max3100_getc(void)
  140. {
  141. int c;
  142. unsigned int rx;
  143. while (rxfifo_cnt == 0) {
  144. rx = max3100_transfer(MAX3100_RD);
  145. if ((rx & MAX3100_R) != 0) {
  146. do {
  147. rxfifo_cnt++;
  148. rxfifo_buf[rxfifo_in++] = rx & 0xff;
  149. rxfifo_in &= RXFIFO_SZ - 1;
  150. if (rxfifo_cnt >= RXFIFO_SZ)
  151. break;
  152. } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
  153. }
  154. WATCHDOG_RESET();
  155. }
  156. rxfifo_cnt--;
  157. c = rxfifo_buf[rxfifo_out++];
  158. rxfifo_out &= RXFIFO_SZ - 1;
  159. return c;
  160. }
  161. static int max3100_tstc(void)
  162. {
  163. unsigned int rx;
  164. if (rxfifo_cnt > 0)
  165. return 1;
  166. rx = max3100_transfer(MAX3100_RD);
  167. if ((rx & MAX3100_R) == 0)
  168. return 0;
  169. do {
  170. rxfifo_cnt++;
  171. rxfifo_buf[rxfifo_in++] = rx & 0xff;
  172. rxfifo_in &= RXFIFO_SZ - 1;
  173. if (rxfifo_cnt >= RXFIFO_SZ)
  174. break;
  175. } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
  176. return 1;
  177. }
  178. int serial_init(void)
  179. {
  180. unsigned int wconf, rconf;
  181. int i;
  182. wconf = 0;
  183. /* Set baud rate */
  184. switch (gd->baudrate) {
  185. case 1200:
  186. wconf = MAX3100_B_1200;
  187. break;
  188. case 2400:
  189. wconf = MAX3100_B_2400;
  190. break;
  191. case 4800:
  192. wconf = MAX3100_B_4800;
  193. break;
  194. case 9600:
  195. wconf = MAX3100_B_9600;
  196. break;
  197. case 19200:
  198. wconf = MAX3100_B_19200;
  199. break;
  200. case 38400:
  201. wconf = MAX3100_B_38400;
  202. break;
  203. case 57600:
  204. wconf = MAX3100_B_57600;
  205. break;
  206. default:
  207. case 115200:
  208. wconf = MAX3100_B_115200;
  209. break;
  210. case 230400:
  211. wconf = MAX3100_B_230400;
  212. break;
  213. }
  214. /* try for 10ms, with a 100us gap */
  215. for (i = 0; i < 10000; i += 100) {
  216. max3100_transfer(MAX3100_WC | wconf);
  217. rconf = max3100_transfer(MAX3100_RC) & 0x3fff;
  218. if (rconf == wconf)
  219. break;
  220. udelay(100);
  221. }
  222. rxfifo_in = rxfifo_out = rxfifo_cnt = 0;
  223. return (0);
  224. }
  225. void serial_putc(const char c)
  226. {
  227. if (c == '\n')
  228. max3100_putc('\r');
  229. max3100_putc(c);
  230. }
  231. void serial_puts(const char *s)
  232. {
  233. while (*s)
  234. serial_putc (*s++);
  235. }
  236. int serial_getc(void)
  237. {
  238. return max3100_getc();
  239. }
  240. int serial_tstc(void)
  241. {
  242. return max3100_tstc();
  243. }
  244. /* XXX WTF? */
  245. void serial_setbrg(void)
  246. {
  247. }
  248. #endif