aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/imx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-09 15:09:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-09 15:09:24 -0500
commit5983faf942f260023e547f3c5f38c1033c35cc9b (patch)
treef54ce89de5d9f7a05e99948937ac5456df09df30 /drivers/tty/serial/imx.c
parent21a2cb565a74bf794d343ce22300c5f6c1568ae1 (diff)
parent995234da19b927f42722d796e8270384f33be11c (diff)
Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (65 commits) tty: serial: imx: move del_timer_sync() to avoid potential deadlock imx: add polled io uart methods imx: Add save/restore functions for UART control regs serial/imx: let probing fail for the dt case without a valid alias serial/imx: propagate error from of_alias_get_id instead of using -ENODEV tty: serial: imx: Allow UART to be a source for wakeup serial: driver for m32 arch should not have DEC alpha errata serial/documentation: fix documented name of DCD cpp symbol atmel_serial: fix spinlock lockup in RS485 code tty: Fix memory leak in virtual console when enable unicode translation serial: use DIV_ROUND_CLOSEST instead of open coding it serial: add support for 400 and 800 v3 series Titan cards serial: bfin-uart: Remove ASYNC_CTS_FLOW flag for hardware automatic CTS. serial: bfin-uart: Enable hardware automatic CTS only when CTS pin is available. serial: make FSL errata depend on 8250_CONSOLE, not just 8250 serial: add irq handler for Freescale 16550 errata. serial: manually inline serial8250_handle_port serial: make 8250 timeout use the specified IRQ handler serial: export the key functions for an 8250 IRQ handler serial: clean up parameter passing for 8250 Rx IRQ handling ...
Diffstat (limited to 'drivers/tty/serial/imx.c')
-rw-r--r--drivers/tty/serial/imx.c148
1 files changed, 133 insertions, 15 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 163fc9021f5a..0b7fed746b27 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -102,6 +102,7 @@
102#define UCR2_STPB (1<<6) /* Stop */ 102#define UCR2_STPB (1<<6) /* Stop */
103#define UCR2_WS (1<<5) /* Word size */ 103#define UCR2_WS (1<<5) /* Word size */
104#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ 104#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */
105#define UCR2_ATEN (1<<3) /* Aging Timer Enable */
105#define UCR2_TXEN (1<<2) /* Transmitter enabled */ 106#define UCR2_TXEN (1<<2) /* Transmitter enabled */
106#define UCR2_RXEN (1<<1) /* Receiver enabled */ 107#define UCR2_RXEN (1<<1) /* Receiver enabled */
107#define UCR2_SRST (1<<0) /* SW reset */ 108#define UCR2_SRST (1<<0) /* SW reset */
@@ -207,6 +208,12 @@ struct imx_port {
207 struct imx_uart_data *devdata; 208 struct imx_uart_data *devdata;
208}; 209};
209 210
211struct imx_port_ucrs {
212 unsigned int ucr1;
213 unsigned int ucr2;
214 unsigned int ucr3;
215};
216
210#ifdef CONFIG_IRDA 217#ifdef CONFIG_IRDA
211#define USE_IRDA(sport) ((sport)->use_irda) 218#define USE_IRDA(sport) ((sport)->use_irda)
212#else 219#else
@@ -260,6 +267,27 @@ static inline int is_imx21_uart(struct imx_port *sport)
260} 267}
261 268
262/* 269/*
270 * Save and restore functions for UCR1, UCR2 and UCR3 registers
271 */
272static void imx_port_ucrs_save(struct uart_port *port,
273 struct imx_port_ucrs *ucr)
274{
275 /* save control registers */
276 ucr->ucr1 = readl(port->membase + UCR1);
277 ucr->ucr2 = readl(port->membase + UCR2);
278 ucr->ucr3 = readl(port->membase + UCR3);
279}
280
281static void imx_port_ucrs_restore(struct uart_port *port,
282 struct imx_port_ucrs *ucr)
283{
284 /* restore control registers */
285 writel(ucr->ucr1, port->membase + UCR1);
286 writel(ucr->ucr2, port->membase + UCR2);
287 writel(ucr->ucr3, port->membase + UCR3);
288}
289
290/*
263 * Handle any change of modem status signal since we were last called. 291 * Handle any change of modem status signal since we were last called.
264 */ 292 */
265static void imx_mctrl_check(struct imx_port *sport) 293static void imx_mctrl_check(struct imx_port *sport)
@@ -566,6 +594,9 @@ static irqreturn_t imx_int(int irq, void *dev_id)
566 if (sts & USR1_RTSD) 594 if (sts & USR1_RTSD)
567 imx_rtsint(irq, dev_id); 595 imx_rtsint(irq, dev_id);
568 596
597 if (sts & USR1_AWAKE)
598 writel(USR1_AWAKE, sport->port.membase + USR1);
599
569 return IRQ_HANDLED; 600 return IRQ_HANDLED;
570} 601}
571 602
@@ -901,6 +932,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
901 ucr2 |= UCR2_PROE; 932 ucr2 |= UCR2_PROE;
902 } 933 }
903 934
935 del_timer_sync(&sport->timer);
936
904 /* 937 /*
905 * Ask the core to calculate the divisor for us. 938 * Ask the core to calculate the divisor for us.
906 */ 939 */
@@ -931,8 +964,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
931 sport->port.ignore_status_mask |= URXD_OVRRUN; 964 sport->port.ignore_status_mask |= URXD_OVRRUN;
932 } 965 }
933 966
934 del_timer_sync(&sport->timer);
935
936 /* 967 /*
937 * Update the per-port timeout. 968 * Update the per-port timeout.
938 */ 969 */
@@ -1079,6 +1110,70 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser)
1079 return ret; 1110 return ret;
1080} 1111}
1081 1112
1113#if defined(CONFIG_CONSOLE_POLL)
1114static int imx_poll_get_char(struct uart_port *port)
1115{
1116 struct imx_port_ucrs old_ucr;
1117 unsigned int status;
1118 unsigned char c;
1119
1120 /* save control registers */
1121 imx_port_ucrs_save(port, &old_ucr);
1122
1123 /* disable interrupts */
1124 writel(UCR1_UARTEN, port->membase + UCR1);
1125 writel(old_ucr.ucr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI),
1126 port->membase + UCR2);
1127 writel(old_ucr.ucr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN),
1128 port->membase + UCR3);
1129
1130 /* poll */
1131 do {
1132 status = readl(port->membase + USR2);
1133 } while (~status & USR2_RDR);
1134
1135 /* read */
1136 c = readl(port->membase + URXD0);
1137
1138 /* restore control registers */
1139 imx_port_ucrs_restore(port, &old_ucr);
1140
1141 return c;
1142}
1143
1144static void imx_poll_put_char(struct uart_port *port, unsigned char c)
1145{
1146 struct imx_port_ucrs old_ucr;
1147 unsigned int status;
1148
1149 /* save control registers */
1150 imx_port_ucrs_save(port, &old_ucr);
1151
1152 /* disable interrupts */
1153 writel(UCR1_UARTEN, port->membase + UCR1);
1154 writel(old_ucr.ucr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI),
1155 port->membase + UCR2);
1156 writel(old_ucr.ucr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN),
1157 port->membase + UCR3);
1158
1159 /* drain */
1160 do {
1161 status = readl(port->membase + USR1);
1162 } while (~status & USR1_TRDY);
1163
1164 /* write */
1165 writel(c, port->membase + URTX0);
1166
1167 /* flush */
1168 do {
1169 status = readl(port->membase + USR2);
1170 } while (~status & USR2_TXDC);
1171
1172 /* restore control registers */
1173 imx_port_ucrs_restore(port, &old_ucr);
1174}
1175#endif
1176
1082static struct uart_ops imx_pops = { 1177static struct uart_ops imx_pops = {
1083 .tx_empty = imx_tx_empty, 1178 .tx_empty = imx_tx_empty,
1084 .set_mctrl = imx_set_mctrl, 1179 .set_mctrl = imx_set_mctrl,
@@ -1096,6 +1191,10 @@ static struct uart_ops imx_pops = {
1096 .request_port = imx_request_port, 1191 .request_port = imx_request_port,
1097 .config_port = imx_config_port, 1192 .config_port = imx_config_port,
1098 .verify_port = imx_verify_port, 1193 .verify_port = imx_verify_port,
1194#if defined(CONFIG_CONSOLE_POLL)
1195 .poll_get_char = imx_poll_get_char,
1196 .poll_put_char = imx_poll_put_char,
1197#endif
1099}; 1198};
1100 1199
1101static struct imx_port *imx_ports[UART_NR]; 1200static struct imx_port *imx_ports[UART_NR];
@@ -1118,13 +1217,14 @@ static void
1118imx_console_write(struct console *co, const char *s, unsigned int count) 1217imx_console_write(struct console *co, const char *s, unsigned int count)
1119{ 1218{
1120 struct imx_port *sport = imx_ports[co->index]; 1219 struct imx_port *sport = imx_ports[co->index];
1121 unsigned int old_ucr1, old_ucr2, ucr1; 1220 struct imx_port_ucrs old_ucr;
1221 unsigned int ucr1;
1122 1222
1123 /* 1223 /*
1124 * First, save UCR1/2 and then disable interrupts 1224 * First, save UCR1/2/3 and then disable interrupts
1125 */ 1225 */
1126 ucr1 = old_ucr1 = readl(sport->port.membase + UCR1); 1226 imx_port_ucrs_save(&sport->port, &old_ucr);
1127 old_ucr2 = readl(sport->port.membase + UCR2); 1227 ucr1 = old_ucr.ucr1;
1128 1228
1129 if (is_imx1_uart(sport)) 1229 if (is_imx1_uart(sport))
1130 ucr1 |= IMX1_UCR1_UARTCLKEN; 1230 ucr1 |= IMX1_UCR1_UARTCLKEN;
@@ -1133,18 +1233,17 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
1133 1233
1134 writel(ucr1, sport->port.membase + UCR1); 1234 writel(ucr1, sport->port.membase + UCR1);
1135 1235
1136 writel(old_ucr2 | UCR2_TXEN, sport->port.membase + UCR2); 1236 writel(old_ucr.ucr2 | UCR2_TXEN, sport->port.membase + UCR2);
1137 1237
1138 uart_console_write(&sport->port, s, count, imx_console_putchar); 1238 uart_console_write(&sport->port, s, count, imx_console_putchar);
1139 1239
1140 /* 1240 /*
1141 * Finally, wait for transmitter to become empty 1241 * Finally, wait for transmitter to become empty
1142 * and restore UCR1/2 1242 * and restore UCR1/2/3
1143 */ 1243 */
1144 while (!(readl(sport->port.membase + USR2) & USR2_TXDC)); 1244 while (!(readl(sport->port.membase + USR2) & USR2_TXDC));
1145 1245
1146 writel(old_ucr1, sport->port.membase + UCR1); 1246 imx_port_ucrs_restore(&sport->port, &old_ucr);
1147 writel(old_ucr2, sport->port.membase + UCR2);
1148} 1247}
1149 1248
1150/* 1249/*
@@ -1269,6 +1368,12 @@ static struct uart_driver imx_reg = {
1269static int serial_imx_suspend(struct platform_device *dev, pm_message_t state) 1368static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
1270{ 1369{
1271 struct imx_port *sport = platform_get_drvdata(dev); 1370 struct imx_port *sport = platform_get_drvdata(dev);
1371 unsigned int val;
1372
1373 /* enable wakeup from i.MX UART */
1374 val = readl(sport->port.membase + UCR3);
1375 val |= UCR3_AWAKEN;
1376 writel(val, sport->port.membase + UCR3);
1272 1377
1273 if (sport) 1378 if (sport)
1274 uart_suspend_port(&imx_reg, &sport->port); 1379 uart_suspend_port(&imx_reg, &sport->port);
@@ -1279,6 +1384,12 @@ static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
1279static int serial_imx_resume(struct platform_device *dev) 1384static int serial_imx_resume(struct platform_device *dev)
1280{ 1385{
1281 struct imx_port *sport = platform_get_drvdata(dev); 1386 struct imx_port *sport = platform_get_drvdata(dev);
1387 unsigned int val;
1388
1389 /* disable wakeup from i.MX UART */
1390 val = readl(sport->port.membase + UCR3);
1391 val &= ~UCR3_AWAKEN;
1392 writel(val, sport->port.membase + UCR3);
1282 1393
1283 if (sport) 1394 if (sport)
1284 uart_resume_port(&imx_reg, &sport->port); 1395 uart_resume_port(&imx_reg, &sport->port);
@@ -1287,6 +1398,10 @@ static int serial_imx_resume(struct platform_device *dev)
1287} 1398}
1288 1399
1289#ifdef CONFIG_OF 1400#ifdef CONFIG_OF
1401/*
1402 * This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it
1403 * could successfully get all information from dt or a negative errno.
1404 */
1290static int serial_imx_probe_dt(struct imx_port *sport, 1405static int serial_imx_probe_dt(struct imx_port *sport,
1291 struct platform_device *pdev) 1406 struct platform_device *pdev)
1292{ 1407{
@@ -1296,12 +1411,13 @@ static int serial_imx_probe_dt(struct imx_port *sport,
1296 int ret; 1411 int ret;
1297 1412
1298 if (!np) 1413 if (!np)
1299 return -ENODEV; 1414 /* no device tree device */
1415 return 1;
1300 1416
1301 ret = of_alias_get_id(np, "serial"); 1417 ret = of_alias_get_id(np, "serial");
1302 if (ret < 0) { 1418 if (ret < 0) {
1303 dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret); 1419 dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
1304 return -ENODEV; 1420 return ret;
1305 } 1421 }
1306 sport->port.line = ret; 1422 sport->port.line = ret;
1307 1423
@@ -1319,7 +1435,7 @@ static int serial_imx_probe_dt(struct imx_port *sport,
1319static inline int serial_imx_probe_dt(struct imx_port *sport, 1435static inline int serial_imx_probe_dt(struct imx_port *sport,
1320 struct platform_device *pdev) 1436 struct platform_device *pdev)
1321{ 1437{
1322 return -ENODEV; 1438 return 1;
1323} 1439}
1324#endif 1440#endif
1325 1441
@@ -1354,8 +1470,10 @@ static int serial_imx_probe(struct platform_device *pdev)
1354 return -ENOMEM; 1470 return -ENOMEM;
1355 1471
1356 ret = serial_imx_probe_dt(sport, pdev); 1472 ret = serial_imx_probe_dt(sport, pdev);
1357 if (ret == -ENODEV) 1473 if (ret > 0)
1358 serial_imx_probe_pdata(sport, pdev); 1474 serial_imx_probe_pdata(sport, pdev);
1475 else if (ret < 0)
1476 goto free;
1359 1477
1360 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1478 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1361 if (!res) { 1479 if (!res) {
@@ -1476,7 +1594,7 @@ static int __init imx_serial_init(void)
1476 if (ret != 0) 1594 if (ret != 0)
1477 uart_unregister_driver(&imx_reg); 1595 uart_unregister_driver(&imx_reg);
1478 1596
1479 return 0; 1597 return ret;
1480} 1598}
1481 1599
1482static void __exit imx_serial_exit(void) 1600static void __exit imx_serial_exit(void)