diff options
Diffstat (limited to 'drivers/serial/pmac_zilog.c')
-rw-r--r-- | drivers/serial/pmac_zilog.c | 262 |
1 files changed, 194 insertions, 68 deletions
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 0700cd10b97c..700e10833bf9 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c | |||
@@ -54,7 +54,6 @@ | |||
54 | #include <linux/delay.h> | 54 | #include <linux/delay.h> |
55 | #include <linux/init.h> | 55 | #include <linux/init.h> |
56 | #include <linux/console.h> | 56 | #include <linux/console.h> |
57 | #include <linux/slab.h> | ||
58 | #include <linux/adb.h> | 57 | #include <linux/adb.h> |
59 | #include <linux/pmu.h> | 58 | #include <linux/pmu.h> |
60 | #include <linux/bitops.h> | 59 | #include <linux/bitops.h> |
@@ -63,11 +62,17 @@ | |||
63 | #include <asm/sections.h> | 62 | #include <asm/sections.h> |
64 | #include <asm/io.h> | 63 | #include <asm/io.h> |
65 | #include <asm/irq.h> | 64 | #include <asm/irq.h> |
65 | |||
66 | #ifdef CONFIG_PPC_PMAC | ||
66 | #include <asm/prom.h> | 67 | #include <asm/prom.h> |
67 | #include <asm/machdep.h> | 68 | #include <asm/machdep.h> |
68 | #include <asm/pmac_feature.h> | 69 | #include <asm/pmac_feature.h> |
69 | #include <asm/dbdma.h> | 70 | #include <asm/dbdma.h> |
70 | #include <asm/macio.h> | 71 | #include <asm/macio.h> |
72 | #else | ||
73 | #include <linux/platform_device.h> | ||
74 | #define of_machine_is_compatible(x) (0) | ||
75 | #endif | ||
71 | 76 | ||
72 | #if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 77 | #if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
73 | #define SUPPORT_SYSRQ | 78 | #define SUPPORT_SYSRQ |
@@ -83,11 +88,9 @@ | |||
83 | 88 | ||
84 | static char version[] __initdata = "pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)"; | 89 | static char version[] __initdata = "pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)"; |
85 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | 90 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); |
86 | MODULE_DESCRIPTION("Driver for the PowerMac serial ports."); | 91 | MODULE_DESCRIPTION("Driver for the Mac and PowerMac serial ports."); |
87 | MODULE_LICENSE("GPL"); | 92 | MODULE_LICENSE("GPL"); |
88 | 93 | ||
89 | #define PWRDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg) | ||
90 | |||
91 | #ifdef CONFIG_SERIAL_PMACZILOG_TTYS | 94 | #ifdef CONFIG_SERIAL_PMACZILOG_TTYS |
92 | #define PMACZILOG_MAJOR TTY_MAJOR | 95 | #define PMACZILOG_MAJOR TTY_MAJOR |
93 | #define PMACZILOG_MINOR 64 | 96 | #define PMACZILOG_MINOR 64 |
@@ -153,8 +156,8 @@ static void pmz_load_zsregs(struct uart_pmac_port *uap, u8 *regs) | |||
153 | write_zsreg(uap, R10, regs[R10]); | 156 | write_zsreg(uap, R10, regs[R10]); |
154 | 157 | ||
155 | /* Set TX/RX controls sans the enable bits. */ | 158 | /* Set TX/RX controls sans the enable bits. */ |
156 | write_zsreg(uap, R3, regs[R3] & ~RxENABLE); | 159 | write_zsreg(uap, R3, regs[R3] & ~RxENABLE); |
157 | write_zsreg(uap, R5, regs[R5] & ~TxENABLE); | 160 | write_zsreg(uap, R5, regs[R5] & ~TxENABLE); |
158 | 161 | ||
159 | /* now set R7 "prime" on ESCC */ | 162 | /* now set R7 "prime" on ESCC */ |
160 | write_zsreg(uap, R15, regs[R15] | EN85C30); | 163 | write_zsreg(uap, R15, regs[R15] | EN85C30); |
@@ -205,7 +208,7 @@ static void pmz_load_zsregs(struct uart_pmac_port *uap, u8 *regs) | |||
205 | */ | 208 | */ |
206 | static void pmz_maybe_update_regs(struct uart_pmac_port *uap) | 209 | static void pmz_maybe_update_regs(struct uart_pmac_port *uap) |
207 | { | 210 | { |
208 | if (!ZS_REGS_HELD(uap)) { | 211 | if (!ZS_REGS_HELD(uap)) { |
209 | if (ZS_TX_ACTIVE(uap)) { | 212 | if (ZS_TX_ACTIVE(uap)) { |
210 | uap->flags |= PMACZILOG_FLAG_REGS_HELD; | 213 | uap->flags |= PMACZILOG_FLAG_REGS_HELD; |
211 | } else { | 214 | } else { |
@@ -281,7 +284,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) | |||
281 | spin_lock(&uap->port.lock); | 284 | spin_lock(&uap->port.lock); |
282 | if (swallow) | 285 | if (swallow) |
283 | goto next_char; | 286 | goto next_char; |
284 | } | 287 | } |
285 | #endif /* CONFIG_MAGIC_SYSRQ && CONFIG_SERIAL_CORE_CONSOLE */ | 288 | #endif /* CONFIG_MAGIC_SYSRQ && CONFIG_SERIAL_CORE_CONSOLE */ |
286 | 289 | ||
287 | /* A real serial line, record the character and status. */ | 290 | /* A real serial line, record the character and status. */ |
@@ -317,7 +320,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) | |||
317 | 320 | ||
318 | if (uap->port.ignore_status_mask == 0xff || | 321 | if (uap->port.ignore_status_mask == 0xff || |
319 | (r1 & uap->port.ignore_status_mask) == 0) { | 322 | (r1 & uap->port.ignore_status_mask) == 0) { |
320 | tty_insert_flip_char(tty, ch, flag); | 323 | tty_insert_flip_char(tty, ch, flag); |
321 | } | 324 | } |
322 | if (r1 & Rx_OVR) | 325 | if (r1 & Rx_OVR) |
323 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 326 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
@@ -341,7 +344,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) | |||
341 | uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); | 344 | uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); |
342 | write_zsreg(uap, R1, uap->curregs[R1]); | 345 | write_zsreg(uap, R1, uap->curregs[R1]); |
343 | zssync(uap); | 346 | zssync(uap); |
344 | dev_err(&uap->dev->ofdev.dev, "pmz: rx irq flood !\n"); | 347 | pmz_error("pmz: rx irq flood !\n"); |
345 | return tty; | 348 | return tty; |
346 | } | 349 | } |
347 | 350 | ||
@@ -411,6 +414,17 @@ static void pmz_transmit_chars(struct uart_pmac_port *uap) | |||
411 | goto ack_tx_int; | 414 | goto ack_tx_int; |
412 | } | 415 | } |
413 | 416 | ||
417 | /* Under some circumstances, we see interrupts reported for | ||
418 | * a closed channel. The interrupt mask in R1 is clear, but | ||
419 | * R3 still signals the interrupts and we see them when taking | ||
420 | * an interrupt for the other channel (this could be a qemu | ||
421 | * bug but since the ESCC doc doesn't specify precsiely whether | ||
422 | * R3 interrup status bits are masked by R1 interrupt enable | ||
423 | * bits, better safe than sorry). --BenH. | ||
424 | */ | ||
425 | if (!ZS_IS_OPEN(uap)) | ||
426 | goto ack_tx_int; | ||
427 | |||
414 | if (uap->port.x_char) { | 428 | if (uap->port.x_char) { |
415 | uap->flags |= PMACZILOG_FLAG_TX_ACTIVE; | 429 | uap->flags |= PMACZILOG_FLAG_TX_ACTIVE; |
416 | write_zsdata(uap, uap->port.x_char); | 430 | write_zsdata(uap, uap->port.x_char); |
@@ -459,47 +473,47 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id) | |||
459 | 473 | ||
460 | uap_a = pmz_get_port_A(uap); | 474 | uap_a = pmz_get_port_A(uap); |
461 | uap_b = uap_a->mate; | 475 | uap_b = uap_a->mate; |
462 | 476 | ||
463 | spin_lock(&uap_a->port.lock); | 477 | spin_lock(&uap_a->port.lock); |
464 | r3 = read_zsreg(uap_a, R3); | 478 | r3 = read_zsreg(uap_a, R3); |
465 | 479 | ||
466 | #ifdef DEBUG_HARD | 480 | #ifdef DEBUG_HARD |
467 | pmz_debug("irq, r3: %x\n", r3); | 481 | pmz_debug("irq, r3: %x\n", r3); |
468 | #endif | 482 | #endif |
469 | /* Channel A */ | 483 | /* Channel A */ |
470 | tty = NULL; | 484 | tty = NULL; |
471 | if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { | 485 | if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { |
472 | write_zsreg(uap_a, R0, RES_H_IUS); | 486 | write_zsreg(uap_a, R0, RES_H_IUS); |
473 | zssync(uap_a); | 487 | zssync(uap_a); |
474 | if (r3 & CHAEXT) | 488 | if (r3 & CHAEXT) |
475 | pmz_status_handle(uap_a); | 489 | pmz_status_handle(uap_a); |
476 | if (r3 & CHARxIP) | 490 | if (r3 & CHARxIP) |
477 | tty = pmz_receive_chars(uap_a); | 491 | tty = pmz_receive_chars(uap_a); |
478 | if (r3 & CHATxIP) | 492 | if (r3 & CHATxIP) |
479 | pmz_transmit_chars(uap_a); | 493 | pmz_transmit_chars(uap_a); |
480 | rc = IRQ_HANDLED; | 494 | rc = IRQ_HANDLED; |
481 | } | 495 | } |
482 | spin_unlock(&uap_a->port.lock); | 496 | spin_unlock(&uap_a->port.lock); |
483 | if (tty != NULL) | 497 | if (tty != NULL) |
484 | tty_flip_buffer_push(tty); | 498 | tty_flip_buffer_push(tty); |
485 | 499 | ||
486 | if (uap_b->node == NULL) | 500 | if (uap_b->node == NULL) |
487 | goto out; | 501 | goto out; |
488 | 502 | ||
489 | spin_lock(&uap_b->port.lock); | 503 | spin_lock(&uap_b->port.lock); |
490 | tty = NULL; | 504 | tty = NULL; |
491 | if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { | 505 | if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { |
492 | write_zsreg(uap_b, R0, RES_H_IUS); | 506 | write_zsreg(uap_b, R0, RES_H_IUS); |
493 | zssync(uap_b); | 507 | zssync(uap_b); |
494 | if (r3 & CHBEXT) | 508 | if (r3 & CHBEXT) |
495 | pmz_status_handle(uap_b); | 509 | pmz_status_handle(uap_b); |
496 | if (r3 & CHBRxIP) | 510 | if (r3 & CHBRxIP) |
497 | tty = pmz_receive_chars(uap_b); | 511 | tty = pmz_receive_chars(uap_b); |
498 | if (r3 & CHBTxIP) | 512 | if (r3 & CHBTxIP) |
499 | pmz_transmit_chars(uap_b); | 513 | pmz_transmit_chars(uap_b); |
500 | rc = IRQ_HANDLED; | 514 | rc = IRQ_HANDLED; |
501 | } | 515 | } |
502 | spin_unlock(&uap_b->port.lock); | 516 | spin_unlock(&uap_b->port.lock); |
503 | if (tty != NULL) | 517 | if (tty != NULL) |
504 | tty_flip_buffer_push(tty); | 518 | tty_flip_buffer_push(tty); |
505 | 519 | ||
@@ -707,7 +721,7 @@ static void pmz_enable_ms(struct uart_port *port) | |||
707 | 721 | ||
708 | if (ZS_IS_ASLEEP(uap)) | 722 | if (ZS_IS_ASLEEP(uap)) |
709 | return; | 723 | return; |
710 | /* NOTE: Not subject to 'transmitter active' rule. */ | 724 | /* NOTE: Not subject to 'transmitter active' rule. */ |
711 | write_zsreg(uap, R15, uap->curregs[R15]); | 725 | write_zsreg(uap, R15, uap->curregs[R15]); |
712 | } | 726 | } |
713 | } | 727 | } |
@@ -737,15 +751,19 @@ static void pmz_break_ctl(struct uart_port *port, int break_state) | |||
737 | if (new_reg != uap->curregs[R5]) { | 751 | if (new_reg != uap->curregs[R5]) { |
738 | uap->curregs[R5] = new_reg; | 752 | uap->curregs[R5] = new_reg; |
739 | 753 | ||
740 | /* NOTE: Not subject to 'transmitter active' rule. */ | 754 | /* NOTE: Not subject to 'transmitter active' rule. */ |
741 | if (ZS_IS_ASLEEP(uap)) | 755 | if (ZS_IS_ASLEEP(uap)) { |
756 | spin_unlock_irqrestore(&port->lock, flags); | ||
742 | return; | 757 | return; |
758 | } | ||
743 | write_zsreg(uap, R5, uap->curregs[R5]); | 759 | write_zsreg(uap, R5, uap->curregs[R5]); |
744 | } | 760 | } |
745 | 761 | ||
746 | spin_unlock_irqrestore(&port->lock, flags); | 762 | spin_unlock_irqrestore(&port->lock, flags); |
747 | } | 763 | } |
748 | 764 | ||
765 | #ifdef CONFIG_PPC_PMAC | ||
766 | |||
749 | /* | 767 | /* |
750 | * Turn power on or off to the SCC and associated stuff | 768 | * Turn power on or off to the SCC and associated stuff |
751 | * (port drivers, modem, IR port, etc.) | 769 | * (port drivers, modem, IR port, etc.) |
@@ -781,6 +799,15 @@ static int pmz_set_scc_power(struct uart_pmac_port *uap, int state) | |||
781 | return delay; | 799 | return delay; |
782 | } | 800 | } |
783 | 801 | ||
802 | #else | ||
803 | |||
804 | static int pmz_set_scc_power(struct uart_pmac_port *uap, int state) | ||
805 | { | ||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | #endif /* !CONFIG_PPC_PMAC */ | ||
810 | |||
784 | /* | 811 | /* |
785 | * FixZeroBug....Works around a bug in the SCC receving channel. | 812 | * FixZeroBug....Works around a bug in the SCC receving channel. |
786 | * Inspired from Darwin code, 15 Sept. 2000 -DanM | 813 | * Inspired from Darwin code, 15 Sept. 2000 -DanM |
@@ -897,7 +924,6 @@ static int __pmz_startup(struct uart_pmac_port *uap) | |||
897 | /* Remember status for DCD/CTS changes */ | 924 | /* Remember status for DCD/CTS changes */ |
898 | uap->prev_status = read_zsreg(uap, R0); | 925 | uap->prev_status = read_zsreg(uap, R0); |
899 | 926 | ||
900 | |||
901 | return pwr_delay; | 927 | return pwr_delay; |
902 | } | 928 | } |
903 | 929 | ||
@@ -944,9 +970,9 @@ static int pmz_startup(struct uart_port *port) | |||
944 | } | 970 | } |
945 | 971 | ||
946 | pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON; | 972 | pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON; |
947 | if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED, "PowerMac Zilog", uap)) { | 973 | if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED, |
948 | dev_err(&uap->dev->ofdev.dev, | 974 | "SCC", uap)) { |
949 | "Unable to register zs interrupt handler.\n"); | 975 | pmz_error("Unable to register zs interrupt handler.\n"); |
950 | pmz_set_scc_power(uap, 0); | 976 | pmz_set_scc_power(uap, 0); |
951 | mutex_unlock(&pmz_irq_mutex); | 977 | mutex_unlock(&pmz_irq_mutex); |
952 | return -ENXIO; | 978 | return -ENXIO; |
@@ -972,7 +998,7 @@ static int pmz_startup(struct uart_port *port) | |||
972 | if (!ZS_IS_EXTCLK(uap)) | 998 | if (!ZS_IS_EXTCLK(uap)) |
973 | uap->curregs[R1] |= EXT_INT_ENAB; | 999 | uap->curregs[R1] |= EXT_INT_ENAB; |
974 | write_zsreg(uap, R1, uap->curregs[R1]); | 1000 | write_zsreg(uap, R1, uap->curregs[R1]); |
975 | spin_unlock_irqrestore(&port->lock, flags); | 1001 | spin_unlock_irqrestore(&port->lock, flags); |
976 | 1002 | ||
977 | pmz_debug("pmz: startup() done.\n"); | 1003 | pmz_debug("pmz: startup() done.\n"); |
978 | 1004 | ||
@@ -992,7 +1018,7 @@ static void pmz_shutdown(struct uart_port *port) | |||
992 | mutex_lock(&pmz_irq_mutex); | 1018 | mutex_lock(&pmz_irq_mutex); |
993 | 1019 | ||
994 | /* Release interrupt handler */ | 1020 | /* Release interrupt handler */ |
995 | free_irq(uap->port.irq, uap); | 1021 | free_irq(uap->port.irq, uap); |
996 | 1022 | ||
997 | spin_lock_irqsave(&port->lock, flags); | 1023 | spin_lock_irqsave(&port->lock, flags); |
998 | 1024 | ||
@@ -1040,7 +1066,6 @@ static void pmz_convert_to_zs(struct uart_pmac_port *uap, unsigned int cflag, | |||
1040 | { | 1066 | { |
1041 | int brg; | 1067 | int brg; |
1042 | 1068 | ||
1043 | |||
1044 | /* Switch to external clocking for IrDA high clock rates. That | 1069 | /* Switch to external clocking for IrDA high clock rates. That |
1045 | * code could be re-used for Midi interfaces with different | 1070 | * code could be re-used for Midi interfaces with different |
1046 | * multipliers | 1071 | * multipliers |
@@ -1187,7 +1212,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1187 | while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0 | 1212 | while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0 |
1188 | || (read_zsreg(uap, R1) & ALL_SNT) == 0) { | 1213 | || (read_zsreg(uap, R1) & ALL_SNT) == 0) { |
1189 | if (--t <= 0) { | 1214 | if (--t <= 0) { |
1190 | dev_err(&uap->dev->ofdev.dev, "transmitter didn't drain\n"); | 1215 | pmz_error("transmitter didn't drain\n"); |
1191 | return; | 1216 | return; |
1192 | } | 1217 | } |
1193 | udelay(10); | 1218 | udelay(10); |
@@ -1203,7 +1228,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1203 | read_zsdata(uap); | 1228 | read_zsdata(uap); |
1204 | mdelay(10); | 1229 | mdelay(10); |
1205 | if (--t <= 0) { | 1230 | if (--t <= 0) { |
1206 | dev_err(&uap->dev->ofdev.dev, "receiver didn't drain\n"); | 1231 | pmz_error("receiver didn't drain\n"); |
1207 | return; | 1232 | return; |
1208 | } | 1233 | } |
1209 | } | 1234 | } |
@@ -1212,20 +1237,19 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1212 | uap->curregs[R5] |= DTR; | 1237 | uap->curregs[R5] |= DTR; |
1213 | write_zsreg(uap, R5, uap->curregs[R5]); | 1238 | write_zsreg(uap, R5, uap->curregs[R5]); |
1214 | zssync(uap); | 1239 | zssync(uap); |
1215 | mdelay(1); | 1240 | mdelay(1); |
1216 | 1241 | ||
1217 | /* Switch SCC to 19200 */ | 1242 | /* Switch SCC to 19200 */ |
1218 | pmz_convert_to_zs(uap, CS8, 0, 19200); | 1243 | pmz_convert_to_zs(uap, CS8, 0, 19200); |
1219 | pmz_load_zsregs(uap, uap->curregs); | 1244 | pmz_load_zsregs(uap, uap->curregs); |
1220 | mdelay(1); | 1245 | mdelay(1); |
1221 | 1246 | ||
1222 | /* Write get_version command byte */ | 1247 | /* Write get_version command byte */ |
1223 | write_zsdata(uap, 1); | 1248 | write_zsdata(uap, 1); |
1224 | t = 5000; | 1249 | t = 5000; |
1225 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { | 1250 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { |
1226 | if (--t <= 0) { | 1251 | if (--t <= 0) { |
1227 | dev_err(&uap->dev->ofdev.dev, | 1252 | pmz_error("irda_setup timed out on get_version byte\n"); |
1228 | "irda_setup timed out on get_version byte\n"); | ||
1229 | goto out; | 1253 | goto out; |
1230 | } | 1254 | } |
1231 | udelay(10); | 1255 | udelay(10); |
@@ -1233,8 +1257,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1233 | version = read_zsdata(uap); | 1257 | version = read_zsdata(uap); |
1234 | 1258 | ||
1235 | if (version < 4) { | 1259 | if (version < 4) { |
1236 | dev_info(&uap->dev->ofdev.dev, "IrDA: dongle version %d not supported\n", | 1260 | pmz_info("IrDA: dongle version %d not supported\n", version); |
1237 | version); | ||
1238 | goto out; | 1261 | goto out; |
1239 | } | 1262 | } |
1240 | 1263 | ||
@@ -1243,18 +1266,16 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1243 | t = 5000; | 1266 | t = 5000; |
1244 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { | 1267 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { |
1245 | if (--t <= 0) { | 1268 | if (--t <= 0) { |
1246 | dev_err(&uap->dev->ofdev.dev, | 1269 | pmz_error("irda_setup timed out on speed mode byte\n"); |
1247 | "irda_setup timed out on speed mode byte\n"); | ||
1248 | goto out; | 1270 | goto out; |
1249 | } | 1271 | } |
1250 | udelay(10); | 1272 | udelay(10); |
1251 | } | 1273 | } |
1252 | t = read_zsdata(uap); | 1274 | t = read_zsdata(uap); |
1253 | if (t != cmdbyte) | 1275 | if (t != cmdbyte) |
1254 | dev_err(&uap->dev->ofdev.dev, | 1276 | pmz_error("irda_setup speed mode byte = %x (%x)\n", t, cmdbyte); |
1255 | "irda_setup speed mode byte = %x (%x)\n", t, cmdbyte); | ||
1256 | 1277 | ||
1257 | dev_info(&uap->dev->ofdev.dev, "IrDA setup for %ld bps, dongle version: %d\n", | 1278 | pmz_info("IrDA setup for %ld bps, dongle version: %d\n", |
1258 | *baud, version); | 1279 | *baud, version); |
1259 | 1280 | ||
1260 | (void)read_zsdata(uap); | 1281 | (void)read_zsdata(uap); |
@@ -1404,7 +1425,7 @@ static void pmz_poll_put_char(struct uart_port *port, unsigned char c) | |||
1404 | write_zsdata(uap, c); | 1425 | write_zsdata(uap, c); |
1405 | } | 1426 | } |
1406 | 1427 | ||
1407 | #endif | 1428 | #endif /* CONFIG_CONSOLE_POLL */ |
1408 | 1429 | ||
1409 | static struct uart_ops pmz_pops = { | 1430 | static struct uart_ops pmz_pops = { |
1410 | .tx_empty = pmz_tx_empty, | 1431 | .tx_empty = pmz_tx_empty, |
@@ -1429,6 +1450,8 @@ static struct uart_ops pmz_pops = { | |||
1429 | #endif | 1450 | #endif |
1430 | }; | 1451 | }; |
1431 | 1452 | ||
1453 | #ifdef CONFIG_PPC_PMAC | ||
1454 | |||
1432 | /* | 1455 | /* |
1433 | * Setup one port structure after probing, HW is down at this point, | 1456 | * Setup one port structure after probing, HW is down at this point, |
1434 | * Unlike sunzilog, we don't need to pre-init the spinlock as we don't | 1457 | * Unlike sunzilog, we don't need to pre-init the spinlock as we don't |
@@ -1452,7 +1475,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap) | |||
1452 | return -ENODEV; | 1475 | return -ENODEV; |
1453 | uap->port.mapbase = r_ports.start; | 1476 | uap->port.mapbase = r_ports.start; |
1454 | uap->port.membase = ioremap(uap->port.mapbase, 0x1000); | 1477 | uap->port.membase = ioremap(uap->port.mapbase, 0x1000); |
1455 | 1478 | ||
1456 | uap->control_reg = uap->port.membase; | 1479 | uap->control_reg = uap->port.membase; |
1457 | uap->data_reg = uap->control_reg + 0x10; | 1480 | uap->data_reg = uap->control_reg + 0x10; |
1458 | 1481 | ||
@@ -1579,7 +1602,7 @@ static void pmz_dispose_port(struct uart_pmac_port *uap) | |||
1579 | } | 1602 | } |
1580 | 1603 | ||
1581 | /* | 1604 | /* |
1582 | * Called upon match with an escc node in the devive-tree. | 1605 | * Called upon match with an escc node in the device-tree. |
1583 | */ | 1606 | */ |
1584 | static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match) | 1607 | static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match) |
1585 | { | 1608 | { |
@@ -1801,7 +1824,7 @@ static int __init pmz_probe(void) | |||
1801 | pmz_ports[count].node = node_a; | 1824 | pmz_ports[count].node = node_a; |
1802 | pmz_ports[count+1].node = node_b; | 1825 | pmz_ports[count+1].node = node_b; |
1803 | pmz_ports[count].port.line = count; | 1826 | pmz_ports[count].port.line = count; |
1804 | pmz_ports[count+1].port.line = count+1; | 1827 | pmz_ports[count+1].port.line = count+1; |
1805 | 1828 | ||
1806 | /* | 1829 | /* |
1807 | * Setup the ports for real | 1830 | * Setup the ports for real |
@@ -1825,6 +1848,88 @@ next: | |||
1825 | return 0; | 1848 | return 0; |
1826 | } | 1849 | } |
1827 | 1850 | ||
1851 | #else | ||
1852 | |||
1853 | extern struct platform_device scc_a_pdev, scc_b_pdev; | ||
1854 | |||
1855 | static int __init pmz_init_port(struct uart_pmac_port *uap) | ||
1856 | { | ||
1857 | struct resource *r_ports; | ||
1858 | int irq; | ||
1859 | |||
1860 | r_ports = platform_get_resource(uap->node, IORESOURCE_MEM, 0); | ||
1861 | irq = platform_get_irq(uap->node, 0); | ||
1862 | if (!r_ports || !irq) | ||
1863 | return -ENODEV; | ||
1864 | |||
1865 | uap->port.mapbase = r_ports->start; | ||
1866 | uap->port.membase = (unsigned char __iomem *) r_ports->start; | ||
1867 | uap->port.iotype = UPIO_MEM; | ||
1868 | uap->port.irq = irq; | ||
1869 | uap->port.uartclk = ZS_CLOCK; | ||
1870 | uap->port.fifosize = 1; | ||
1871 | uap->port.ops = &pmz_pops; | ||
1872 | uap->port.type = PORT_PMAC_ZILOG; | ||
1873 | uap->port.flags = 0; | ||
1874 | |||
1875 | uap->control_reg = uap->port.membase; | ||
1876 | uap->data_reg = uap->control_reg + 4; | ||
1877 | uap->port_type = 0; | ||
1878 | |||
1879 | pmz_convert_to_zs(uap, CS8, 0, 9600); | ||
1880 | |||
1881 | return 0; | ||
1882 | } | ||
1883 | |||
1884 | static int __init pmz_probe(void) | ||
1885 | { | ||
1886 | int err; | ||
1887 | |||
1888 | pmz_ports_count = 0; | ||
1889 | |||
1890 | pmz_ports[0].mate = &pmz_ports[1]; | ||
1891 | pmz_ports[0].port.line = 0; | ||
1892 | pmz_ports[0].flags = PMACZILOG_FLAG_IS_CHANNEL_A; | ||
1893 | pmz_ports[0].node = &scc_a_pdev; | ||
1894 | err = pmz_init_port(&pmz_ports[0]); | ||
1895 | if (err) | ||
1896 | return err; | ||
1897 | pmz_ports_count++; | ||
1898 | |||
1899 | pmz_ports[1].mate = &pmz_ports[0]; | ||
1900 | pmz_ports[1].port.line = 1; | ||
1901 | pmz_ports[1].flags = 0; | ||
1902 | pmz_ports[1].node = &scc_b_pdev; | ||
1903 | err = pmz_init_port(&pmz_ports[1]); | ||
1904 | if (err) | ||
1905 | return err; | ||
1906 | pmz_ports_count++; | ||
1907 | |||
1908 | return 0; | ||
1909 | } | ||
1910 | |||
1911 | static void pmz_dispose_port(struct uart_pmac_port *uap) | ||
1912 | { | ||
1913 | memset(uap, 0, sizeof(struct uart_pmac_port)); | ||
1914 | } | ||
1915 | |||
1916 | static int __init pmz_attach(struct platform_device *pdev) | ||
1917 | { | ||
1918 | int i; | ||
1919 | |||
1920 | for (i = 0; i < pmz_ports_count; i++) | ||
1921 | if (pmz_ports[i].node == pdev) | ||
1922 | return 0; | ||
1923 | return -ENODEV; | ||
1924 | } | ||
1925 | |||
1926 | static int __exit pmz_detach(struct platform_device *pdev) | ||
1927 | { | ||
1928 | return 0; | ||
1929 | } | ||
1930 | |||
1931 | #endif /* !CONFIG_PPC_PMAC */ | ||
1932 | |||
1828 | #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE | 1933 | #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE |
1829 | 1934 | ||
1830 | static void pmz_console_write(struct console *con, const char *s, unsigned int count); | 1935 | static void pmz_console_write(struct console *con, const char *s, unsigned int count); |
@@ -1885,28 +1990,41 @@ err_out: | |||
1885 | return rc; | 1990 | return rc; |
1886 | } | 1991 | } |
1887 | 1992 | ||
1993 | #ifdef CONFIG_PPC_PMAC | ||
1994 | |||
1888 | static struct of_device_id pmz_match[] = | 1995 | static struct of_device_id pmz_match[] = |
1889 | { | 1996 | { |
1890 | { | 1997 | { |
1891 | .name = "ch-a", | 1998 | .name = "ch-a", |
1892 | }, | 1999 | }, |
1893 | { | 2000 | { |
1894 | .name = "ch-b", | 2001 | .name = "ch-b", |
1895 | }, | 2002 | }, |
1896 | {}, | 2003 | {}, |
1897 | }; | 2004 | }; |
1898 | MODULE_DEVICE_TABLE (of, pmz_match); | 2005 | MODULE_DEVICE_TABLE (of, pmz_match); |
1899 | 2006 | ||
1900 | static struct macio_driver pmz_driver = | 2007 | static struct macio_driver pmz_driver = { |
1901 | { | ||
1902 | .name = "pmac_zilog", | 2008 | .name = "pmac_zilog", |
1903 | .match_table = pmz_match, | 2009 | .match_table = pmz_match, |
1904 | .probe = pmz_attach, | 2010 | .probe = pmz_attach, |
1905 | .remove = pmz_detach, | 2011 | .remove = pmz_detach, |
1906 | .suspend = pmz_suspend, | 2012 | .suspend = pmz_suspend, |
1907 | .resume = pmz_resume, | 2013 | .resume = pmz_resume, |
2014 | }; | ||
2015 | |||
2016 | #else | ||
2017 | |||
2018 | static struct platform_driver pmz_driver = { | ||
2019 | .remove = __exit_p(pmz_detach), | ||
2020 | .driver = { | ||
2021 | .name = "scc", | ||
2022 | .owner = THIS_MODULE, | ||
2023 | }, | ||
1908 | }; | 2024 | }; |
1909 | 2025 | ||
2026 | #endif /* !CONFIG_PPC_PMAC */ | ||
2027 | |||
1910 | static int __init init_pmz(void) | 2028 | static int __init init_pmz(void) |
1911 | { | 2029 | { |
1912 | int rc, i; | 2030 | int rc, i; |
@@ -1941,19 +2059,27 @@ static int __init init_pmz(void) | |||
1941 | pmz_dispose_port(&pmz_ports[i]); | 2059 | pmz_dispose_port(&pmz_ports[i]); |
1942 | return rc; | 2060 | return rc; |
1943 | } | 2061 | } |
1944 | 2062 | ||
1945 | /* | 2063 | /* |
1946 | * Then we register the macio driver itself | 2064 | * Then we register the macio driver itself |
1947 | */ | 2065 | */ |
2066 | #ifdef CONFIG_PPC_PMAC | ||
1948 | return macio_register_driver(&pmz_driver); | 2067 | return macio_register_driver(&pmz_driver); |
2068 | #else | ||
2069 | return platform_driver_probe(&pmz_driver, pmz_attach); | ||
2070 | #endif | ||
1949 | } | 2071 | } |
1950 | 2072 | ||
1951 | static void __exit exit_pmz(void) | 2073 | static void __exit exit_pmz(void) |
1952 | { | 2074 | { |
1953 | int i; | 2075 | int i; |
1954 | 2076 | ||
2077 | #ifdef CONFIG_PPC_PMAC | ||
1955 | /* Get rid of macio-driver (detach from macio) */ | 2078 | /* Get rid of macio-driver (detach from macio) */ |
1956 | macio_unregister_driver(&pmz_driver); | 2079 | macio_unregister_driver(&pmz_driver); |
2080 | #else | ||
2081 | platform_driver_unregister(&pmz_driver); | ||
2082 | #endif | ||
1957 | 2083 | ||
1958 | for (i = 0; i < pmz_ports_count; i++) { | 2084 | for (i = 0; i < pmz_ports_count; i++) { |
1959 | struct uart_pmac_port *uport = &pmz_ports[i]; | 2085 | struct uart_pmac_port *uport = &pmz_ports[i]; |
@@ -2020,10 +2146,10 @@ static int __init pmz_console_setup(struct console *co, char *options) | |||
2020 | /* | 2146 | /* |
2021 | * XServe's default to 57600 bps | 2147 | * XServe's default to 57600 bps |
2022 | */ | 2148 | */ |
2023 | if (machine_is_compatible("RackMac1,1") | 2149 | if (of_machine_is_compatible("RackMac1,1") |
2024 | || machine_is_compatible("RackMac1,2") | 2150 | || of_machine_is_compatible("RackMac1,2") |
2025 | || machine_is_compatible("MacRISC4")) | 2151 | || of_machine_is_compatible("MacRISC4")) |
2026 | baud = 57600; | 2152 | baud = 57600; |
2027 | 2153 | ||
2028 | /* | 2154 | /* |
2029 | * Check whether an invalid uart number has been specified, and | 2155 | * Check whether an invalid uart number has been specified, and |