serial_max3100.c 6.9 KB

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