amazon_asc.c 18 KB

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