amazon_asc.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. /*
  2. * Driver for AMAZONASC serial ports
  3. *
  4. * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  5. * Based on drivers/serial/serial_s3c2400.c
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. * Copyright (C) 2004 Infineon IFAP DC COM CPE
  22. * Copyright (C) 2007 Felix Fietkau <[email protected]>
  23. * Copyright (C) 2007 John Crispin <[email protected]>
  24. */
  25. #include <linux/module.h>
  26. #include <linux/errno.h>
  27. #include <linux/signal.h>
  28. #include <linux/sched.h>
  29. #include <linux/interrupt.h>
  30. #include <linux/tty.h>
  31. #include <linux/tty_flip.h>
  32. #include <linux/major.h>
  33. #include <linux/string.h>
  34. #include <linux/fcntl.h>
  35. #include <linux/ptrace.h>
  36. #include <linux/ioport.h>
  37. #include <linux/mm.h>
  38. #include <linux/slab.h>
  39. #include <linux/init.h>
  40. #include <linux/circ_buf.h>
  41. #include <linux/serial.h>
  42. #include <linux/serial_core.h>
  43. #include <linux/console.h>
  44. #include <linux/sysrq.h>
  45. #include <linux/irq.h>
  46. #include <asm/system.h>
  47. #include <asm/io.h>
  48. #include <asm/uaccess.h>
  49. #include <asm/bitops.h>
  50. #include <asm/amazon/amazon.h>
  51. #include <asm/amazon/irq.h>
  52. #include <asm/amazon/serial.h>
  53. #define PORT_AMAZONASC 111
  54. #include <linux/serial_core.h>
  55. #define UART_NR 1
  56. #define UART_DUMMY_UER_RX 1
  57. #define SERIAL_AMAZONASC_MAJOR TTY_MAJOR
  58. #define CALLOUT_AMAZONASC_MAJOR TTYAUX_MAJOR
  59. #define SERIAL_AMAZONASC_MINOR 64
  60. #define SERIAL_AMAZONASC_NR UART_NR
  61. static void amazonasc_tx_chars(struct uart_port *port);
  62. extern void prom_printf(const char * fmt, ...);
  63. static struct uart_port amazonasc_ports[UART_NR];
  64. static struct uart_driver amazonasc_reg;
  65. static unsigned int uartclk = 0;
  66. extern unsigned int amazon_get_fpi_hz(void);
  67. static void amazonasc_stop_tx(struct uart_port *port)
  68. {
  69. /* fifo underrun shuts up after firing once */
  70. return;
  71. }
  72. static void amazonasc_start_tx(struct uart_port *port)
  73. {
  74. unsigned long flags;
  75. local_irq_save(flags);
  76. amazonasc_tx_chars(port);
  77. local_irq_restore(flags);
  78. return;
  79. }
  80. static void amazonasc_stop_rx(struct uart_port *port)
  81. {
  82. /* clear the RX enable bit */
  83. amazon_writel(ASCWHBCON_CLRREN, AMAZON_ASC_WHBCON);
  84. }
  85. static void amazonasc_enable_ms(struct uart_port *port)
  86. {
  87. /* no modem signals */
  88. return;
  89. }
  90. #include <linux/version.h>
  91. static void
  92. amazonasc_rx_chars(struct uart_port *port)
  93. {
  94. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26))
  95. struct tty_struct *tty = port->info->port.tty;
  96. #else
  97. struct tty_struct *tty = port->info->tty;
  98. #endif
  99. unsigned int ch = 0, rsr = 0, fifocnt;
  100. fifocnt = amazon_readl(AMAZON_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
  101. while (fifocnt--)
  102. {
  103. u8 flag = TTY_NORMAL;
  104. ch = amazon_readl(AMAZON_ASC_RBUF);
  105. rsr = (amazon_readl(AMAZON_ASC_CON) & ASCCON_ANY) | UART_DUMMY_UER_RX;
  106. tty_flip_buffer_push(tty);
  107. port->icount.rx++;
  108. /*
  109. * Note that the error handling code is
  110. * out of the main execution path
  111. */
  112. if (rsr & ASCCON_ANY) {
  113. if (rsr & ASCCON_PE) {
  114. port->icount.parity++;
  115. amazon_writel_masked(AMAZON_ASC_WHBCON, ASCWHBCON_CLRPE, ASCWHBCON_CLRPE);
  116. } else if (rsr & ASCCON_FE) {
  117. port->icount.frame++;
  118. amazon_writel_masked(AMAZON_ASC_WHBCON, ASCWHBCON_CLRFE, ASCWHBCON_CLRFE);
  119. }
  120. if (rsr & ASCCON_OE) {
  121. port->icount.overrun++;
  122. amazon_writel_masked(AMAZON_ASC_WHBCON, ASCWHBCON_CLROE, ASCWHBCON_CLROE);
  123. }
  124. rsr &= port->read_status_mask;
  125. if (rsr & ASCCON_PE)
  126. flag = TTY_PARITY;
  127. else if (rsr & ASCCON_FE)
  128. flag = TTY_FRAME;
  129. }
  130. if ((rsr & port->ignore_status_mask) == 0)
  131. tty_insert_flip_char(tty, ch, flag);
  132. if (rsr & ASCCON_OE)
  133. /*
  134. * Overrun is special, since it's reported
  135. * immediately, and doesn't affect the current
  136. * character
  137. */
  138. tty_insert_flip_char(tty, 0, TTY_OVERRUN);
  139. }
  140. if (ch != 0)
  141. tty_flip_buffer_push(tty);
  142. return;
  143. }
  144. static void amazonasc_tx_chars(struct uart_port *port)
  145. {
  146. struct circ_buf *xmit = &port->info->xmit;
  147. if (uart_tx_stopped(port)) {
  148. amazonasc_stop_tx(port);
  149. return;
  150. }
  151. while (((amazon_readl(AMAZON_ASC_FSTAT) & ASCFSTAT_TXFFLMASK)
  152. >> ASCFSTAT_TXFFLOFF) != AMAZONASC_TXFIFO_FULL)
  153. {
  154. if (port->x_char) {
  155. amazon_writel(port->x_char, AMAZON_ASC_TBUF);
  156. port->icount.tx++;
  157. port->x_char = 0;
  158. continue;
  159. }
  160. if (uart_circ_empty(xmit))
  161. break;
  162. amazon_writel(xmit->buf[xmit->tail], AMAZON_ASC_TBUF);
  163. xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  164. port->icount.tx++;
  165. }
  166. if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  167. uart_write_wakeup(port);
  168. }
  169. static irqreturn_t amazonasc_tx_int(int irq, void *port)
  170. {
  171. amazon_writel(ASC_IRNCR_TIR, AMAZON_ASC_IRNCR1);
  172. amazonasc_start_tx(port);
  173. /* clear any pending interrupts */
  174. amazon_writel_masked(AMAZON_ASC_WHBCON,
  175. (ASCWHBCON_CLRPE | ASCWHBCON_CLRFE | ASCWHBCON_CLROE),
  176. (ASCWHBCON_CLRPE | ASCWHBCON_CLRFE | ASCWHBCON_CLROE));
  177. return IRQ_HANDLED;
  178. }
  179. static irqreturn_t amazonasc_er_int(int irq, void *port)
  180. {
  181. /* clear any pending interrupts */
  182. amazon_writel_masked(AMAZON_ASC_WHBCON,
  183. (ASCWHBCON_CLRPE | ASCWHBCON_CLRFE | ASCWHBCON_CLROE),
  184. (ASCWHBCON_CLRPE | ASCWHBCON_CLRFE | ASCWHBCON_CLROE));
  185. return IRQ_HANDLED;
  186. }
  187. static irqreturn_t amazonasc_rx_int(int irq, void *port)
  188. {
  189. amazon_writel(ASC_IRNCR_RIR, AMAZON_ASC_IRNCR1);
  190. amazonasc_rx_chars((struct uart_port *) port);
  191. return IRQ_HANDLED;
  192. }
  193. static u_int amazonasc_tx_empty(struct uart_port *port)
  194. {
  195. int status;
  196. /*
  197. * FSTAT tells exactly how many bytes are in the FIFO.
  198. * The question is whether we really need to wait for all
  199. * 16 bytes to be transmitted before reporting that the
  200. * transmitter is empty.
  201. */
  202. status = amazon_readl(AMAZON_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
  203. return status ? 0 : TIOCSER_TEMT;
  204. }
  205. static u_int amazonasc_get_mctrl(struct uart_port *port)
  206. {
  207. /* no modem control signals - the readme says to pretend all are set */
  208. return TIOCM_CTS|TIOCM_CAR|TIOCM_DSR;
  209. }
  210. static void amazonasc_set_mctrl(struct uart_port *port, u_int mctrl)
  211. {
  212. /* no modem control - just return */
  213. return;
  214. }
  215. static void amazonasc_break_ctl(struct uart_port *port, int break_state)
  216. {
  217. /* no way to send a break */
  218. return;
  219. }
  220. static int amazonasc_startup(struct uart_port *port)
  221. {
  222. unsigned int con = 0;
  223. unsigned long flags;
  224. int retval;
  225. /* this assumes: CON.BRS = CON.FDE = 0 */
  226. if (uartclk == 0)
  227. uartclk = amazon_get_fpi_hz();
  228. amazonasc_ports[0].uartclk = uartclk;
  229. local_irq_save(flags);
  230. /* this setup was probably already done in u-boot */
  231. /* ASC and GPIO Port 1 bits 3 and 4 share the same pins
  232. * P1.3 (RX) in, Alternate 10
  233. * P1.4 (TX) in, Alternate 10
  234. */
  235. amazon_writel_masked(AMAZON_GPIO_P1_DIR, 0x18, 0x10); //P1.4 output, P1.3 input
  236. amazon_writel_masked(AMAZON_GPIO_P1_ALTSEL0, 0x18, 0x18); //ALTSETL0 11
  237. amazon_writel_masked(AMAZON_GPIO_P1_ALTSEL1, 0x18, 0); //ALTSETL1 00
  238. amazon_writel_masked(AMAZON_GPIO_P1_OD, 0x18, 0x10);
  239. /* set up the CLC */
  240. amazon_writel_masked(AMAZON_ASC_CLC, AMAZON_ASC_CLC_DISS, 0);
  241. amazon_writel_masked(AMAZON_ASC_CLC, ASCCLC_RMCMASK, 1 << ASCCLC_RMCOFFSET);
  242. /* asynchronous mode */
  243. con = ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_OEN | ASCCON_PEN;
  244. /* choose the line - there's only one */
  245. amazon_writel(0, AMAZON_ASC_PISEL);
  246. amazon_writel(((AMAZONASC_TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) | ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
  247. AMAZON_ASC_TXFCON);
  248. amazon_writel(((AMAZONASC_RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
  249. AMAZON_ASC_RXFCON);
  250. wmb();
  251. amazon_writel_masked(AMAZON_ASC_CON, con, con);
  252. retval = request_irq(AMAZONASC_RIR, amazonasc_rx_int, 0, "asc_rx", port);
  253. if (retval){
  254. printk("failed to request amazonasc_rx_int\n");
  255. return retval;
  256. }
  257. retval = request_irq(AMAZONASC_TIR, amazonasc_tx_int, 0, "asc_tx", port);
  258. if (retval){
  259. printk("failed to request amazonasc_tx_int\n");
  260. goto err1;
  261. }
  262. retval = request_irq(AMAZONASC_EIR, amazonasc_er_int, 0, "asc_er", port);
  263. if (retval){
  264. printk("failed to request amazonasc_er_int\n");
  265. goto err2;
  266. }
  267. local_irq_restore(flags);
  268. return 0;
  269. err2:
  270. free_irq(AMAZONASC_TIR, port);
  271. err1:
  272. free_irq(AMAZONASC_RIR, port);
  273. local_irq_restore(flags);
  274. return retval;
  275. }
  276. static void amazonasc_shutdown(struct uart_port *port)
  277. {
  278. free_irq(AMAZONASC_RIR, port);
  279. free_irq(AMAZONASC_TIR, port);
  280. free_irq(AMAZONASC_EIR, port);
  281. /*
  282. * disable the baudrate generator to disable the ASC
  283. */
  284. amazon_writel(0, AMAZON_ASC_CON);
  285. /* flush and then disable the fifos */
  286. amazon_writel_masked(AMAZON_ASC_RXFCON, ASCRXFCON_RXFFLU, ASCRXFCON_RXFFLU);
  287. amazon_writel_masked(AMAZON_ASC_RXFCON, ASCRXFCON_RXFEN, 0);
  288. amazon_writel_masked(AMAZON_ASC_TXFCON, ASCTXFCON_TXFFLU, ASCTXFCON_TXFFLU);
  289. amazon_writel_masked(AMAZON_ASC_TXFCON, ASCTXFCON_TXFEN, 0);
  290. }
  291. static void amazonasc_set_termios(struct uart_port *port, struct ktermios *new, struct ktermios *old)
  292. {
  293. unsigned int cflag;
  294. unsigned int iflag;
  295. unsigned int baud, quot;
  296. unsigned int con = 0;
  297. unsigned long flags;
  298. cflag = new->c_cflag;
  299. iflag = new->c_iflag;
  300. /* byte size and parity */
  301. switch (cflag & CSIZE) {
  302. /* 7 bits are always with parity */
  303. case CS7: con = ASCCON_M_7ASYNCPAR; break;
  304. /* the ASC only suports 7 and 8 bits */
  305. case CS5:
  306. case CS6:
  307. default:
  308. if (cflag & PARENB)
  309. con = ASCCON_M_8ASYNCPAR;
  310. else
  311. con = ASCCON_M_8ASYNC;
  312. break;
  313. }
  314. if (cflag & CSTOPB)
  315. con |= ASCCON_STP;
  316. if (cflag & PARENB) {
  317. if (!(cflag & PARODD))
  318. con &= ~ASCCON_ODD;
  319. else
  320. con |= ASCCON_ODD;
  321. }
  322. port->read_status_mask = ASCCON_OE;
  323. if (iflag & INPCK)
  324. port->read_status_mask |= ASCCON_FE | ASCCON_PE;
  325. port->ignore_status_mask = 0;
  326. if (iflag & IGNPAR)
  327. port->ignore_status_mask |= ASCCON_FE | ASCCON_PE;
  328. if (iflag & IGNBRK) {
  329. /*
  330. * If we're ignoring parity and break indicators,
  331. * ignore overruns too (for real raw support).
  332. */
  333. if (iflag & IGNPAR)
  334. port->ignore_status_mask |= ASCCON_OE;
  335. }
  336. /*
  337. * Ignore all characters if CREAD is not set.
  338. */
  339. if ((cflag & CREAD) == 0)
  340. port->ignore_status_mask |= UART_DUMMY_UER_RX;
  341. /* set error signals - framing, parity and overrun */
  342. con |= ASCCON_FEN;
  343. con |= ASCCON_OEN;
  344. con |= ASCCON_PEN;
  345. /* enable the receiver */
  346. con |= ASCCON_REN;
  347. /* block the IRQs */
  348. local_irq_save(flags);
  349. /* set up CON */
  350. amazon_writel(con, AMAZON_ASC_CON);
  351. /* Set baud rate - take a divider of 2 into account */
  352. baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
  353. quot = uart_get_divisor(port, baud);
  354. quot = quot/2 - 1;
  355. /* the next 3 probably already happened when we set CON above */
  356. /* disable the baudrate generator */
  357. amazon_writel_masked(AMAZON_ASC_CON, ASCCON_R, 0);
  358. /* make sure the fractional divider is off */
  359. amazon_writel_masked(AMAZON_ASC_CON, ASCCON_FDE, 0);
  360. /* set up to use divisor of 2 */
  361. amazon_writel_masked(AMAZON_ASC_CON, ASCCON_BRS, 0);
  362. /* now we can write the new baudrate into the register */
  363. amazon_writel(quot, AMAZON_ASC_BTR);
  364. /* turn the baudrate generator back on */
  365. amazon_writel_masked(AMAZON_ASC_CON, ASCCON_R, ASCCON_R);
  366. local_irq_restore(flags);
  367. }
  368. static const char *amazonasc_type(struct uart_port *port)
  369. {
  370. return port->type == PORT_AMAZONASC ? "AMAZONASC" : NULL;
  371. }
  372. /*
  373. * Release the memory region(s) being used by 'port'
  374. */
  375. static void amazonasc_release_port(struct uart_port *port)
  376. {
  377. return;
  378. }
  379. /*
  380. * Request the memory region(s) being used by 'port'
  381. */
  382. static int amazonasc_request_port(struct uart_port *port)
  383. {
  384. return 0;
  385. }
  386. /*
  387. * Configure/autoconfigure the port.
  388. */
  389. static void amazonasc_config_port(struct uart_port *port, int flags)
  390. {
  391. if (flags & UART_CONFIG_TYPE) {
  392. port->type = PORT_AMAZONASC;
  393. amazonasc_request_port(port);
  394. }
  395. }
  396. /*
  397. * verify the new serial_struct (for TIOCSSERIAL).
  398. */
  399. static int amazonasc_verify_port(struct uart_port *port, struct serial_struct *ser)
  400. {
  401. int ret = 0;
  402. if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMAZONASC)
  403. ret = -EINVAL;
  404. if (ser->irq < 0 || ser->irq >= NR_IRQS)
  405. ret = -EINVAL;
  406. if (ser->baud_base < 9600)
  407. ret = -EINVAL;
  408. return ret;
  409. }
  410. static struct uart_ops amazonasc_pops = {
  411. .tx_empty = amazonasc_tx_empty,
  412. .set_mctrl = amazonasc_set_mctrl,
  413. .get_mctrl = amazonasc_get_mctrl,
  414. .stop_tx = amazonasc_stop_tx,
  415. .start_tx = amazonasc_start_tx,
  416. .stop_rx = amazonasc_stop_rx,
  417. .enable_ms = amazonasc_enable_ms,
  418. .break_ctl = amazonasc_break_ctl,
  419. .startup = amazonasc_startup,
  420. .shutdown = amazonasc_shutdown,
  421. .set_termios = amazonasc_set_termios,
  422. .type = amazonasc_type,
  423. .release_port = amazonasc_release_port,
  424. .request_port = amazonasc_request_port,
  425. .config_port = amazonasc_config_port,
  426. .verify_port = amazonasc_verify_port,
  427. };
  428. static struct uart_port amazonasc_ports[UART_NR] = {
  429. {
  430. membase: (void *)AMAZON_ASC,
  431. mapbase: AMAZON_ASC,
  432. iotype: SERIAL_IO_MEM,
  433. irq: AMAZONASC_RIR, /* RIR */
  434. uartclk: 0, /* filled in dynamically */
  435. fifosize: 16,
  436. unused: { AMAZONASC_TIR, AMAZONASC_EIR}, /* xmit/error/xmit-buffer-empty IRQ */
  437. type: PORT_AMAZONASC,
  438. ops: &amazonasc_pops,
  439. flags: ASYNC_BOOT_AUTOCONF,
  440. },
  441. };
  442. static void amazonasc_console_write(struct console *co, const char *s, u_int count)
  443. {
  444. int i, fifocnt;
  445. unsigned long flags;
  446. local_irq_save(flags);
  447. for (i = 0; i < count;)
  448. {
  449. /* wait until the FIFO is not full */
  450. do
  451. {
  452. fifocnt = (amazon_readl(AMAZON_ASC_FSTAT) & ASCFSTAT_TXFFLMASK)
  453. >> ASCFSTAT_TXFFLOFF;
  454. } while (fifocnt == AMAZONASC_TXFIFO_FULL);
  455. if (s[i] == '\0')
  456. {
  457. break;
  458. }
  459. if (s[i] == '\n')
  460. {
  461. amazon_writel('\r', AMAZON_ASC_TBUF);
  462. do
  463. {
  464. fifocnt = (amazon_readl(AMAZON_ASC_FSTAT) &
  465. ASCFSTAT_TXFFLMASK) >> ASCFSTAT_TXFFLOFF;
  466. } while (fifocnt == AMAZONASC_TXFIFO_FULL);
  467. }
  468. amazon_writel(s[i], AMAZON_ASC_TBUF);
  469. i++;
  470. }
  471. local_irq_restore(flags);
  472. }
  473. static void __init
  474. amazonasc_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
  475. {
  476. u_int lcr_h;
  477. lcr_h = amazon_readl(AMAZON_ASC_CON);
  478. /* do this only if the ASC is turned on */
  479. if (lcr_h & ASCCON_R) {
  480. u_int quot, div, fdiv, frac;
  481. *parity = 'n';
  482. if ((lcr_h & ASCCON_MODEMASK) == ASCCON_M_7ASYNCPAR ||
  483. (lcr_h & ASCCON_MODEMASK) == ASCCON_M_8ASYNCPAR) {
  484. if (lcr_h & ASCCON_ODD)
  485. *parity = 'o';
  486. else
  487. *parity = 'e';
  488. }
  489. if ((lcr_h & ASCCON_MODEMASK) == ASCCON_M_7ASYNCPAR)
  490. *bits = 7;
  491. else
  492. *bits = 8;
  493. quot = amazon_readl(AMAZON_ASC_BTR) + 1;
  494. /* this gets hairy if the fractional divider is used */
  495. if (lcr_h & ASCCON_FDE)
  496. {
  497. div = 1;
  498. fdiv = amazon_readl(AMAZON_ASC_FDV);
  499. if (fdiv == 0)
  500. fdiv = 512;
  501. frac = 512;
  502. }
  503. else
  504. {
  505. div = lcr_h & ASCCON_BRS ? 3 : 2;
  506. fdiv = frac = 1;
  507. }
  508. /*
  509. * This doesn't work exactly because we use integer
  510. * math to calculate baud which results in rounding
  511. * errors when we try to go from quot -> baud !!
  512. * Try to make this work for both the fractional divider
  513. * and the simple divider. Also try to avoid rounding
  514. * errors using integer math.
  515. */
  516. *baud = frac * (port->uartclk / (div * 512 * 16 * quot));
  517. if (*baud > 1100 && *baud < 2400)
  518. *baud = 1200;
  519. if (*baud > 2300 && *baud < 4800)
  520. *baud = 2400;
  521. if (*baud > 4700 && *baud < 9600)
  522. *baud = 4800;
  523. if (*baud > 9500 && *baud < 19200)
  524. *baud = 9600;
  525. if (*baud > 19000 && *baud < 38400)
  526. *baud = 19200;
  527. if (*baud > 38400 && *baud < 57600)
  528. *baud = 38400;
  529. if (*baud > 57600 && *baud < 115200)
  530. *baud = 57600;
  531. if (*baud > 115200 && *baud < 230400)
  532. *baud = 115200;
  533. }
  534. }
  535. static int __init amazonasc_console_setup(struct console *co, char *options)
  536. {
  537. struct uart_port *port;
  538. int baud = 115200;
  539. int bits = 8;
  540. int parity = 'n';
  541. int flow = 'n';
  542. /* this assumes: CON.BRS = CON.FDE = 0 */
  543. if (uartclk == 0)
  544. uartclk = amazon_get_fpi_hz();
  545. co->index = 0;
  546. port = &amazonasc_ports[0];
  547. amazonasc_ports[0].uartclk = uartclk;
  548. amazonasc_ports[0].type = PORT_AMAZONASC;
  549. if (options){
  550. uart_parse_options(options, &baud, &parity, &bits, &flow);
  551. }
  552. return uart_set_options(port, co, baud, parity, bits, flow);
  553. }
  554. static struct uart_driver amazonasc_reg;
  555. static struct console amazonasc_console = {
  556. name: "ttyS",
  557. write: amazonasc_console_write,
  558. device: uart_console_device,
  559. setup: amazonasc_console_setup,
  560. flags: CON_PRINTBUFFER,
  561. index: -1,
  562. data: &amazonasc_reg,
  563. };
  564. static int __init amazonasc_console_init(void)
  565. {
  566. register_console(&amazonasc_console);
  567. return 0;
  568. }
  569. console_initcall(amazonasc_console_init);
  570. static struct uart_driver amazonasc_reg = {
  571. .owner = THIS_MODULE,
  572. .driver_name = "serial",
  573. .dev_name = "ttyS",
  574. .major = TTY_MAJOR,
  575. .minor = 64,
  576. .nr = UART_NR,
  577. .cons = &amazonasc_console,
  578. };
  579. static int __init amazonasc_init(void)
  580. {
  581. unsigned char res;
  582. uart_register_driver(&amazonasc_reg);
  583. res = uart_add_one_port(&amazonasc_reg, &amazonasc_ports[0]);
  584. return res;
  585. }
  586. static void __exit amazonasc_exit(void)
  587. {
  588. uart_unregister_driver(&amazonasc_reg);
  589. }
  590. module_init(amazonasc_init);
  591. module_exit(amazonasc_exit);
  592. MODULE_AUTHOR("Gary Jennejohn, Felix Fietkau, John Crispin");
  593. MODULE_DESCRIPTION("MIPS AMAZONASC serial port driver");
  594. MODULE_LICENSE("GPL");