aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-10 16:32:05 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-10 16:32:05 -0400
commit0ab598099c18affd73a21482274c00e8119236be (patch)
tree599ddc4ffb8bfa4bb6364eb4f4a3e91bfd9cb6c9 /drivers/serial
parentb526ca438b95a6d71210e0ffc79aabac8aba2b1e (diff)
parent26e6385f14b991e30450daee4348cbbc4bc4bb09 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: [SPARC64]: Use alloc_pci_dev() in PCI bus probes. [SPARC64]: Bump PROMINTR_MAX to 32. [SPARC64]: Fix recursion in PROM tree building. [SERIAL] sunzilog: Interrupt enable before ISR handler installed [SPARC64] PCI: Consolidate PCI access code into pci_common.c
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/sunzilog.c138
-rw-r--r--drivers/serial/sunzilog.h19
2 files changed, 122 insertions, 35 deletions
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index da73205e54cd..0985193dc57d 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -92,6 +92,8 @@ struct uart_sunzilog_port {
92#define SUNZILOG_FLAG_REGS_HELD 0x00000040 92#define SUNZILOG_FLAG_REGS_HELD 0x00000040
93#define SUNZILOG_FLAG_TX_STOPPED 0x00000080 93#define SUNZILOG_FLAG_TX_STOPPED 0x00000080
94#define SUNZILOG_FLAG_TX_ACTIVE 0x00000100 94#define SUNZILOG_FLAG_TX_ACTIVE 0x00000100
95#define SUNZILOG_FLAG_ESCC 0x00000200
96#define SUNZILOG_FLAG_ISR_HANDLER 0x00000400
95 97
96 unsigned int cflag; 98 unsigned int cflag;
97 99
@@ -174,9 +176,11 @@ static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel)
174/* This function must only be called when the TX is not busy. The UART 176/* This function must only be called when the TX is not busy. The UART
175 * port lock must be held and local interrupts disabled. 177 * port lock must be held and local interrupts disabled.
176 */ 178 */
177static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs) 179static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs)
178{ 180{
179 int i; 181 int i;
182 int escc;
183 unsigned char r15;
180 184
181 /* Let pending transmits finish. */ 185 /* Let pending transmits finish. */
182 for (i = 0; i < 1000; i++) { 186 for (i = 0; i < 1000; i++) {
@@ -229,11 +233,25 @@ static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *
229 write_zsreg(channel, R14, regs[R14]); 233 write_zsreg(channel, R14, regs[R14]);
230 234
231 /* External status interrupt control. */ 235 /* External status interrupt control. */
232 write_zsreg(channel, R15, regs[R15]); 236 write_zsreg(channel, R15, (regs[R15] | WR7pEN) & ~FIFOEN);
237
238 /* ESCC Extension Register */
239 r15 = read_zsreg(channel, R15);
240 if (r15 & 0x01) {
241 write_zsreg(channel, R7, regs[R7p]);
242
243 /* External status interrupt and FIFO control. */
244 write_zsreg(channel, R15, regs[R15] & ~WR7pEN);
245 escc = 1;
246 } else {
247 /* Clear FIFO bit case it is an issue */
248 regs[R15] &= ~FIFOEN;
249 escc = 0;
250 }
233 251
234 /* Reset external status interrupts. */ 252 /* Reset external status interrupts. */
235 write_zsreg(channel, R0, RES_EXT_INT); 253 write_zsreg(channel, R0, RES_EXT_INT); /* First Latch */
236 write_zsreg(channel, R0, RES_EXT_INT); 254 write_zsreg(channel, R0, RES_EXT_INT); /* Second Latch */
237 255
238 /* Rewrite R3/R5, this time without enables masked. */ 256 /* Rewrite R3/R5, this time without enables masked. */
239 write_zsreg(channel, R3, regs[R3]); 257 write_zsreg(channel, R3, regs[R3]);
@@ -241,6 +259,8 @@ static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *
241 259
242 /* Rewrite R1, this time without IRQ enabled masked. */ 260 /* Rewrite R1, this time without IRQ enabled masked. */
243 write_zsreg(channel, R1, regs[R1]); 261 write_zsreg(channel, R1, regs[R1]);
262
263 return escc;
244} 264}
245 265
246/* Reprogram the Zilog channel HW registers with the copies found in the 266/* Reprogram the Zilog channel HW registers with the copies found in the
@@ -731,7 +751,7 @@ static void sunzilog_enable_ms(struct uart_port *port)
731 up->curregs[R15] = new_reg; 751 up->curregs[R15] = new_reg;
732 752
733 /* NOTE: Not subject to 'transmitter active' rule. */ 753 /* NOTE: Not subject to 'transmitter active' rule. */
734 write_zsreg(channel, R15, up->curregs[R15]); 754 write_zsreg(channel, R15, up->curregs[R15] & ~WR7pEN);
735 } 755 }
736} 756}
737 757
@@ -861,44 +881,44 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag,
861 up->curregs[R14] = BRSRC | BRENAB; 881 up->curregs[R14] = BRSRC | BRENAB;
862 882
863 /* Character size, stop bits, and parity. */ 883 /* Character size, stop bits, and parity. */
864 up->curregs[3] &= ~RxN_MASK; 884 up->curregs[R3] &= ~RxN_MASK;
865 up->curregs[5] &= ~TxN_MASK; 885 up->curregs[R5] &= ~TxN_MASK;
866 switch (cflag & CSIZE) { 886 switch (cflag & CSIZE) {
867 case CS5: 887 case CS5:
868 up->curregs[3] |= Rx5; 888 up->curregs[R3] |= Rx5;
869 up->curregs[5] |= Tx5; 889 up->curregs[R5] |= Tx5;
870 up->parity_mask = 0x1f; 890 up->parity_mask = 0x1f;
871 break; 891 break;
872 case CS6: 892 case CS6:
873 up->curregs[3] |= Rx6; 893 up->curregs[R3] |= Rx6;
874 up->curregs[5] |= Tx6; 894 up->curregs[R5] |= Tx6;
875 up->parity_mask = 0x3f; 895 up->parity_mask = 0x3f;
876 break; 896 break;
877 case CS7: 897 case CS7:
878 up->curregs[3] |= Rx7; 898 up->curregs[R3] |= Rx7;
879 up->curregs[5] |= Tx7; 899 up->curregs[R5] |= Tx7;
880 up->parity_mask = 0x7f; 900 up->parity_mask = 0x7f;
881 break; 901 break;
882 case CS8: 902 case CS8:
883 default: 903 default:
884 up->curregs[3] |= Rx8; 904 up->curregs[R3] |= Rx8;
885 up->curregs[5] |= Tx8; 905 up->curregs[R5] |= Tx8;
886 up->parity_mask = 0xff; 906 up->parity_mask = 0xff;
887 break; 907 break;
888 }; 908 };
889 up->curregs[4] &= ~0x0c; 909 up->curregs[R4] &= ~0x0c;
890 if (cflag & CSTOPB) 910 if (cflag & CSTOPB)
891 up->curregs[4] |= SB2; 911 up->curregs[R4] |= SB2;
892 else 912 else
893 up->curregs[4] |= SB1; 913 up->curregs[R4] |= SB1;
894 if (cflag & PARENB) 914 if (cflag & PARENB)
895 up->curregs[4] |= PAR_ENAB; 915 up->curregs[R4] |= PAR_ENAB;
896 else 916 else
897 up->curregs[4] &= ~PAR_ENAB; 917 up->curregs[R4] &= ~PAR_ENAB;
898 if (!(cflag & PARODD)) 918 if (!(cflag & PARODD))
899 up->curregs[4] |= PAR_EVEN; 919 up->curregs[R4] |= PAR_EVEN;
900 else 920 else
901 up->curregs[4] &= ~PAR_EVEN; 921 up->curregs[R4] &= ~PAR_EVEN;
902 922
903 up->port.read_status_mask = Rx_OVR; 923 up->port.read_status_mask = Rx_OVR;
904 if (iflag & INPCK) 924 if (iflag & INPCK)
@@ -952,7 +972,9 @@ sunzilog_set_termios(struct uart_port *port, struct ktermios *termios,
952 972
953static const char *sunzilog_type(struct uart_port *port) 973static const char *sunzilog_type(struct uart_port *port)
954{ 974{
955 return "zs"; 975 struct uart_sunzilog_port *up = UART_ZILOG(port);
976
977 return (up->flags & SUNZILOG_FLAG_ESCC) ? "zs (ESCC)" : "zs";
956} 978}
957 979
958/* We do not request/release mappings of the registers here, this 980/* We do not request/release mappings of the registers here, this
@@ -1170,7 +1192,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options)
1170 1192
1171 spin_lock_irqsave(&up->port.lock, flags); 1193 spin_lock_irqsave(&up->port.lock, flags);
1172 1194
1173 up->curregs[R15] = BRKIE; 1195 up->curregs[R15] |= BRKIE;
1174 sunzilog_convert_to_zs(up, con->cflag, 0, brg); 1196 sunzilog_convert_to_zs(up, con->cflag, 0, brg);
1175 1197
1176 sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); 1198 sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
@@ -1229,7 +1251,7 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
1229 baud = 4800; 1251 baud = 4800;
1230 } 1252 }
1231 1253
1232 up->curregs[R15] = BRKIE; 1254 up->curregs[R15] |= BRKIE;
1233 brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); 1255 brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
1234 sunzilog_convert_to_zs(up, up->cflag, 0, brg); 1256 sunzilog_convert_to_zs(up, up->cflag, 0, brg);
1235 sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); 1257 sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
@@ -1283,8 +1305,18 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
1283 1305
1284 if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | 1306 if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
1285 SUNZILOG_FLAG_CONS_MOUSE)) { 1307 SUNZILOG_FLAG_CONS_MOUSE)) {
1308 up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
1309 up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
1310 up->curregs[R3] = RxENAB | Rx8;
1311 up->curregs[R5] = TxENAB | Tx8;
1312 up->curregs[R6] = 0x00; /* SDLC Address */
1313 up->curregs[R7] = 0x7E; /* SDLC Flag */
1314 up->curregs[R9] = NV;
1315 up->curregs[R7p] = 0x00;
1286 sunzilog_init_kbdms(up, up->port.line); 1316 sunzilog_init_kbdms(up, up->port.line);
1287 up->curregs[R9] |= (NV | MIE); 1317 /* Only enable interrupts if an ISR handler available */
1318 if (up->flags & SUNZILOG_FLAG_ISR_HANDLER)
1319 up->curregs[R9] |= MIE;
1288 write_zsreg(channel, R9, up->curregs[R9]); 1320 write_zsreg(channel, R9, up->curregs[R9]);
1289 } else { 1321 } else {
1290 /* Normal serial TTY. */ 1322 /* Normal serial TTY. */
@@ -1293,7 +1325,9 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
1293 up->curregs[R4] = PAR_EVEN | X16CLK | SB1; 1325 up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
1294 up->curregs[R3] = RxENAB | Rx8; 1326 up->curregs[R3] = RxENAB | Rx8;
1295 up->curregs[R5] = TxENAB | Tx8; 1327 up->curregs[R5] = TxENAB | Tx8;
1296 up->curregs[R9] = NV | MIE; 1328 up->curregs[R6] = 0x00; /* SDLC Address */
1329 up->curregs[R7] = 0x7E; /* SDLC Flag */
1330 up->curregs[R9] = NV;
1297 up->curregs[R10] = NRZ; 1331 up->curregs[R10] = NRZ;
1298 up->curregs[R11] = TCBR | RCBR; 1332 up->curregs[R11] = TCBR | RCBR;
1299 baud = 9600; 1333 baud = 9600;
@@ -1301,7 +1335,14 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
1301 up->curregs[R12] = (brg & 0xff); 1335 up->curregs[R12] = (brg & 0xff);
1302 up->curregs[R13] = (brg >> 8) & 0xff; 1336 up->curregs[R13] = (brg >> 8) & 0xff;
1303 up->curregs[R14] = BRSRC | BRENAB; 1337 up->curregs[R14] = BRSRC | BRENAB;
1304 __load_zsregs(channel, up->curregs); 1338 up->curregs[R15] = FIFOEN; /* Use FIFO if on ESCC */
1339 up->curregs[R7p] = TxFIFO_LVL | RxFIFO_LVL;
1340 if (__load_zsregs(channel, up->curregs)) {
1341 up->flags |= SUNZILOG_FLAG_ESCC;
1342 }
1343 /* Only enable interrupts if an ISR handler available */
1344 if (up->flags & SUNZILOG_FLAG_ISR_HANDLER)
1345 up->curregs[R9] |= MIE;
1305 write_zsreg(channel, R9, up->curregs[R9]); 1346 write_zsreg(channel, R9, up->curregs[R9]);
1306 } 1347 }
1307 1348
@@ -1390,12 +1431,14 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
1390 return err; 1431 return err;
1391 } 1432 }
1392 } else { 1433 } else {
1393 printk(KERN_INFO "%s: Keyboard at MMIO %lx (irq = %d) " 1434 printk(KERN_INFO "%s: Keyboard at MMIO 0x%lx (irq = %d) "
1394 "is a zs\n", 1435 "is a %s\n",
1395 op->dev.bus_id, up[0].port.mapbase, op->irqs[0]); 1436 op->dev.bus_id, up[0].port.mapbase, op->irqs[0],
1396 printk(KERN_INFO "%s: Mouse at MMIO %lx (irq = %d) " 1437 sunzilog_type (&up[0].port));
1397 "is a zs\n", 1438 printk(KERN_INFO "%s: Mouse at MMIO 0x%lx (irq = %d) "
1398 op->dev.bus_id, up[1].port.mapbase, op->irqs[0]); 1439 "is a %s\n",
1440 op->dev.bus_id, up[1].port.mapbase, op->irqs[0],
1441 sunzilog_type (&up[1].port));
1399 } 1442 }
1400 1443
1401 dev_set_drvdata(&op->dev, &up[0]); 1444 dev_set_drvdata(&op->dev, &up[0]);
@@ -1487,10 +1530,23 @@ static int __init sunzilog_init(void)
1487 goto out_unregister_uart; 1530 goto out_unregister_uart;
1488 1531
1489 if (zilog_irq != -1) { 1532 if (zilog_irq != -1) {
1533 struct uart_sunzilog_port *up = sunzilog_irq_chain;
1490 err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, 1534 err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
1491 "zs", sunzilog_irq_chain); 1535 "zs", sunzilog_irq_chain);
1492 if (err) 1536 if (err)
1493 goto out_unregister_driver; 1537 goto out_unregister_driver;
1538
1539 /* Enable Interrupts */
1540 while (up) {
1541 struct zilog_channel __iomem *channel;
1542
1543 /* printk (KERN_INFO "Enable IRQ for ZILOG Hardware %p\n", up); */
1544 channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
1545 up->flags |= SUNZILOG_FLAG_ISR_HANDLER;
1546 up->curregs[R9] |= MIE;
1547 write_zsreg(channel, R9, up->curregs[R9]);
1548 up = up->next;
1549 }
1494 } 1550 }
1495 1551
1496out: 1552out:
@@ -1515,6 +1571,20 @@ static void __exit sunzilog_exit(void)
1515 of_unregister_driver(&zs_driver); 1571 of_unregister_driver(&zs_driver);
1516 1572
1517 if (zilog_irq != -1) { 1573 if (zilog_irq != -1) {
1574 struct uart_sunzilog_port *up = sunzilog_irq_chain;
1575
1576 /* Disable Interrupts */
1577 while (up) {
1578 struct zilog_channel __iomem *channel;
1579
1580 /* printk (KERN_INFO "Disable IRQ for ZILOG Hardware %p\n", up); */
1581 channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
1582 up->flags &= ~SUNZILOG_FLAG_ISR_HANDLER;
1583 up->curregs[R9] &= ~MIE;
1584 write_zsreg(channel, R9, up->curregs[R9]);
1585 up = up->next;
1586 }
1587
1518 free_irq(zilog_irq, sunzilog_irq_chain); 1588 free_irq(zilog_irq, sunzilog_irq_chain);
1519 zilog_irq = -1; 1589 zilog_irq = -1;
1520 } 1590 }
diff --git a/drivers/serial/sunzilog.h b/drivers/serial/sunzilog.h
index 7939b6d71270..5dec7b47cc38 100644
--- a/drivers/serial/sunzilog.h
+++ b/drivers/serial/sunzilog.h
@@ -13,7 +13,8 @@ struct zilog_layout {
13 struct zilog_channel channelA; 13 struct zilog_channel channelA;
14}; 14};
15 15
16#define NUM_ZSREGS 16 16#define NUM_ZSREGS 17
17#define R7p 16 /* Written as R7 with P15 bit 0 set */
17 18
18/* Conversion routines to/from brg time constants from/to bits 19/* Conversion routines to/from brg time constants from/to bits
19 * per second. 20 * per second.
@@ -127,6 +128,15 @@ struct zilog_layout {
127 128
128/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ 129/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
129 130
131/* Write Register 7' (ESCC Only) */
132#define AUTO_TxFLAG 1 /* Automatic Tx SDLC Flag */
133#define AUTO_EOM_RST 2 /* Automatic EOM Reset */
134#define AUTOnRTS 4 /* Automatic /RTS pin deactivation */
135#define RxFIFO_LVL 8 /* Receive FIFO interrupt level */
136#define nDTRnREQ 0x10 /* /DTR/REQ timing */
137#define TxFIFO_LVL 0x20 /* Transmit FIFO interrupt level */
138#define EXT_RD_EN 0x40 /* Extended read register enable */
139
130/* Write Register 8 (transmit buffer) */ 140/* Write Register 8 (transmit buffer) */
131 141
132/* Write Register 9 (Master interrupt control) */ 142/* Write Register 9 (Master interrupt control) */
@@ -135,6 +145,7 @@ struct zilog_layout {
135#define DLC 4 /* Disable Lower Chain */ 145#define DLC 4 /* Disable Lower Chain */
136#define MIE 8 /* Master Interrupt Enable */ 146#define MIE 8 /* Master Interrupt Enable */
137#define STATHI 0x10 /* Status high */ 147#define STATHI 0x10 /* Status high */
148#define SWIACK 0x20 /* Software Interrupt Ack (not on NMOS) */
138#define NORESET 0 /* No reset on write to R9 */ 149#define NORESET 0 /* No reset on write to R9 */
139#define CHRB 0x40 /* Reset channel B */ 150#define CHRB 0x40 /* Reset channel B */
140#define CHRA 0x80 /* Reset channel A */ 151#define CHRA 0x80 /* Reset channel A */
@@ -187,7 +198,9 @@ struct zilog_layout {
187#define SNRZI 0xe0 /* Set NRZI mode */ 198#define SNRZI 0xe0 /* Set NRZI mode */
188 199
189/* Write Register 15 (external/status interrupt control) */ 200/* Write Register 15 (external/status interrupt control) */
201#define WR7pEN 1 /* WR7' Enable (ESCC only) */
190#define ZCIE 2 /* Zero count IE */ 202#define ZCIE 2 /* Zero count IE */
203#define FIFOEN 4 /* FIFO Enable (ESCC only) */
191#define DCDIE 8 /* DCD IE */ 204#define DCDIE 8 /* DCD IE */
192#define SYNCIE 0x10 /* Sync/hunt IE */ 205#define SYNCIE 0x10 /* Sync/hunt IE */
193#define CTSIE 0x20 /* CTS IE */ 206#define CTSIE 0x20 /* CTS IE */
@@ -241,6 +254,10 @@ struct zilog_layout {
241#define CHATxIP 0x10 /* Channel A Tx IP */ 254#define CHATxIP 0x10 /* Channel A Tx IP */
242#define CHARxIP 0x20 /* Channel A Rx IP */ 255#define CHARxIP 0x20 /* Channel A Rx IP */
243 256
257/* Read Register 6 (LSB frame byte count [Not on NMOS]) */
258
259/* Read Register 7 (MSB frame byte count and FIFO status [Not on NMOS]) */
260
244/* Read Register 8 (receive data register) */ 261/* Read Register 8 (receive data register) */
245 262
246/* Read Register 10 (misc status bits) */ 263/* Read Register 10 (misc status bits) */