diff options
Diffstat (limited to 'drivers/serial/pmac_zilog.c')
-rw-r--r-- | drivers/serial/pmac_zilog.c | 246 |
1 files changed, 180 insertions, 66 deletions
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 683e66f18e8c..f020de1cdd50 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c | |||
@@ -63,11 +63,17 @@ | |||
63 | #include <asm/sections.h> | 63 | #include <asm/sections.h> |
64 | #include <asm/io.h> | 64 | #include <asm/io.h> |
65 | #include <asm/irq.h> | 65 | #include <asm/irq.h> |
66 | |||
67 | #ifdef CONFIG_PPC_PMAC | ||
66 | #include <asm/prom.h> | 68 | #include <asm/prom.h> |
67 | #include <asm/machdep.h> | 69 | #include <asm/machdep.h> |
68 | #include <asm/pmac_feature.h> | 70 | #include <asm/pmac_feature.h> |
69 | #include <asm/dbdma.h> | 71 | #include <asm/dbdma.h> |
70 | #include <asm/macio.h> | 72 | #include <asm/macio.h> |
73 | #else | ||
74 | #include <linux/platform_device.h> | ||
75 | #define of_machine_is_compatible(x) (0) | ||
76 | #endif | ||
71 | 77 | ||
72 | #if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 78 | #if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
73 | #define SUPPORT_SYSRQ | 79 | #define SUPPORT_SYSRQ |
@@ -83,11 +89,9 @@ | |||
83 | 89 | ||
84 | static char version[] __initdata = "pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)"; | 90 | static char version[] __initdata = "pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)"; |
85 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | 91 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); |
86 | MODULE_DESCRIPTION("Driver for the PowerMac serial ports."); | 92 | MODULE_DESCRIPTION("Driver for the Mac and PowerMac serial ports."); |
87 | MODULE_LICENSE("GPL"); | 93 | MODULE_LICENSE("GPL"); |
88 | 94 | ||
89 | #define PWRDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg) | ||
90 | |||
91 | #ifdef CONFIG_SERIAL_PMACZILOG_TTYS | 95 | #ifdef CONFIG_SERIAL_PMACZILOG_TTYS |
92 | #define PMACZILOG_MAJOR TTY_MAJOR | 96 | #define PMACZILOG_MAJOR TTY_MAJOR |
93 | #define PMACZILOG_MINOR 64 | 97 | #define PMACZILOG_MINOR 64 |
@@ -153,8 +157,8 @@ static void pmz_load_zsregs(struct uart_pmac_port *uap, u8 *regs) | |||
153 | write_zsreg(uap, R10, regs[R10]); | 157 | write_zsreg(uap, R10, regs[R10]); |
154 | 158 | ||
155 | /* Set TX/RX controls sans the enable bits. */ | 159 | /* Set TX/RX controls sans the enable bits. */ |
156 | write_zsreg(uap, R3, regs[R3] & ~RxENABLE); | 160 | write_zsreg(uap, R3, regs[R3] & ~RxENABLE); |
157 | write_zsreg(uap, R5, regs[R5] & ~TxENABLE); | 161 | write_zsreg(uap, R5, regs[R5] & ~TxENABLE); |
158 | 162 | ||
159 | /* now set R7 "prime" on ESCC */ | 163 | /* now set R7 "prime" on ESCC */ |
160 | write_zsreg(uap, R15, regs[R15] | EN85C30); | 164 | write_zsreg(uap, R15, regs[R15] | EN85C30); |
@@ -205,7 +209,7 @@ static void pmz_load_zsregs(struct uart_pmac_port *uap, u8 *regs) | |||
205 | */ | 209 | */ |
206 | static void pmz_maybe_update_regs(struct uart_pmac_port *uap) | 210 | static void pmz_maybe_update_regs(struct uart_pmac_port *uap) |
207 | { | 211 | { |
208 | if (!ZS_REGS_HELD(uap)) { | 212 | if (!ZS_REGS_HELD(uap)) { |
209 | if (ZS_TX_ACTIVE(uap)) { | 213 | if (ZS_TX_ACTIVE(uap)) { |
210 | uap->flags |= PMACZILOG_FLAG_REGS_HELD; | 214 | uap->flags |= PMACZILOG_FLAG_REGS_HELD; |
211 | } else { | 215 | } else { |
@@ -281,7 +285,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) | |||
281 | spin_lock(&uap->port.lock); | 285 | spin_lock(&uap->port.lock); |
282 | if (swallow) | 286 | if (swallow) |
283 | goto next_char; | 287 | goto next_char; |
284 | } | 288 | } |
285 | #endif /* CONFIG_MAGIC_SYSRQ && CONFIG_SERIAL_CORE_CONSOLE */ | 289 | #endif /* CONFIG_MAGIC_SYSRQ && CONFIG_SERIAL_CORE_CONSOLE */ |
286 | 290 | ||
287 | /* A real serial line, record the character and status. */ | 291 | /* A real serial line, record the character and status. */ |
@@ -317,7 +321,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) | |||
317 | 321 | ||
318 | if (uap->port.ignore_status_mask == 0xff || | 322 | if (uap->port.ignore_status_mask == 0xff || |
319 | (r1 & uap->port.ignore_status_mask) == 0) { | 323 | (r1 & uap->port.ignore_status_mask) == 0) { |
320 | tty_insert_flip_char(tty, ch, flag); | 324 | tty_insert_flip_char(tty, ch, flag); |
321 | } | 325 | } |
322 | if (r1 & Rx_OVR) | 326 | if (r1 & Rx_OVR) |
323 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 327 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
@@ -341,7 +345,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) | |||
341 | uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); | 345 | uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); |
342 | write_zsreg(uap, R1, uap->curregs[R1]); | 346 | write_zsreg(uap, R1, uap->curregs[R1]); |
343 | zssync(uap); | 347 | zssync(uap); |
344 | dev_err(&uap->dev->ofdev.dev, "pmz: rx irq flood !\n"); | 348 | pmz_error("pmz: rx irq flood !\n"); |
345 | return tty; | 349 | return tty; |
346 | } | 350 | } |
347 | 351 | ||
@@ -470,47 +474,47 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id) | |||
470 | 474 | ||
471 | uap_a = pmz_get_port_A(uap); | 475 | uap_a = pmz_get_port_A(uap); |
472 | uap_b = uap_a->mate; | 476 | uap_b = uap_a->mate; |
473 | 477 | ||
474 | spin_lock(&uap_a->port.lock); | 478 | spin_lock(&uap_a->port.lock); |
475 | r3 = read_zsreg(uap_a, R3); | 479 | r3 = read_zsreg(uap_a, R3); |
476 | 480 | ||
477 | #ifdef DEBUG_HARD | 481 | #ifdef DEBUG_HARD |
478 | pmz_debug("irq, r3: %x\n", r3); | 482 | pmz_debug("irq, r3: %x\n", r3); |
479 | #endif | 483 | #endif |
480 | /* Channel A */ | 484 | /* Channel A */ |
481 | tty = NULL; | 485 | tty = NULL; |
482 | if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { | 486 | if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { |
483 | write_zsreg(uap_a, R0, RES_H_IUS); | 487 | write_zsreg(uap_a, R0, RES_H_IUS); |
484 | zssync(uap_a); | 488 | zssync(uap_a); |
485 | if (r3 & CHAEXT) | 489 | if (r3 & CHAEXT) |
486 | pmz_status_handle(uap_a); | 490 | pmz_status_handle(uap_a); |
487 | if (r3 & CHARxIP) | 491 | if (r3 & CHARxIP) |
488 | tty = pmz_receive_chars(uap_a); | 492 | tty = pmz_receive_chars(uap_a); |
489 | if (r3 & CHATxIP) | 493 | if (r3 & CHATxIP) |
490 | pmz_transmit_chars(uap_a); | 494 | pmz_transmit_chars(uap_a); |
491 | rc = IRQ_HANDLED; | 495 | rc = IRQ_HANDLED; |
492 | } | 496 | } |
493 | spin_unlock(&uap_a->port.lock); | 497 | spin_unlock(&uap_a->port.lock); |
494 | if (tty != NULL) | 498 | if (tty != NULL) |
495 | tty_flip_buffer_push(tty); | 499 | tty_flip_buffer_push(tty); |
496 | 500 | ||
497 | if (uap_b->node == NULL) | 501 | if (uap_b->node == NULL) |
498 | goto out; | 502 | goto out; |
499 | 503 | ||
500 | spin_lock(&uap_b->port.lock); | 504 | spin_lock(&uap_b->port.lock); |
501 | tty = NULL; | 505 | tty = NULL; |
502 | if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { | 506 | if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { |
503 | write_zsreg(uap_b, R0, RES_H_IUS); | 507 | write_zsreg(uap_b, R0, RES_H_IUS); |
504 | zssync(uap_b); | 508 | zssync(uap_b); |
505 | if (r3 & CHBEXT) | 509 | if (r3 & CHBEXT) |
506 | pmz_status_handle(uap_b); | 510 | pmz_status_handle(uap_b); |
507 | if (r3 & CHBRxIP) | 511 | if (r3 & CHBRxIP) |
508 | tty = pmz_receive_chars(uap_b); | 512 | tty = pmz_receive_chars(uap_b); |
509 | if (r3 & CHBTxIP) | 513 | if (r3 & CHBTxIP) |
510 | pmz_transmit_chars(uap_b); | 514 | pmz_transmit_chars(uap_b); |
511 | rc = IRQ_HANDLED; | 515 | rc = IRQ_HANDLED; |
512 | } | 516 | } |
513 | spin_unlock(&uap_b->port.lock); | 517 | spin_unlock(&uap_b->port.lock); |
514 | if (tty != NULL) | 518 | if (tty != NULL) |
515 | tty_flip_buffer_push(tty); | 519 | tty_flip_buffer_push(tty); |
516 | 520 | ||
@@ -718,7 +722,7 @@ static void pmz_enable_ms(struct uart_port *port) | |||
718 | 722 | ||
719 | if (ZS_IS_ASLEEP(uap)) | 723 | if (ZS_IS_ASLEEP(uap)) |
720 | return; | 724 | return; |
721 | /* NOTE: Not subject to 'transmitter active' rule. */ | 725 | /* NOTE: Not subject to 'transmitter active' rule. */ |
722 | write_zsreg(uap, R15, uap->curregs[R15]); | 726 | write_zsreg(uap, R15, uap->curregs[R15]); |
723 | } | 727 | } |
724 | } | 728 | } |
@@ -748,7 +752,7 @@ static void pmz_break_ctl(struct uart_port *port, int break_state) | |||
748 | if (new_reg != uap->curregs[R5]) { | 752 | if (new_reg != uap->curregs[R5]) { |
749 | uap->curregs[R5] = new_reg; | 753 | uap->curregs[R5] = new_reg; |
750 | 754 | ||
751 | /* NOTE: Not subject to 'transmitter active' rule. */ | 755 | /* NOTE: Not subject to 'transmitter active' rule. */ |
752 | if (ZS_IS_ASLEEP(uap)) | 756 | if (ZS_IS_ASLEEP(uap)) |
753 | return; | 757 | return; |
754 | write_zsreg(uap, R5, uap->curregs[R5]); | 758 | write_zsreg(uap, R5, uap->curregs[R5]); |
@@ -757,6 +761,8 @@ static void pmz_break_ctl(struct uart_port *port, int break_state) | |||
757 | spin_unlock_irqrestore(&port->lock, flags); | 761 | spin_unlock_irqrestore(&port->lock, flags); |
758 | } | 762 | } |
759 | 763 | ||
764 | #ifdef CONFIG_PPC_PMAC | ||
765 | |||
760 | /* | 766 | /* |
761 | * Turn power on or off to the SCC and associated stuff | 767 | * Turn power on or off to the SCC and associated stuff |
762 | * (port drivers, modem, IR port, etc.) | 768 | * (port drivers, modem, IR port, etc.) |
@@ -792,6 +798,15 @@ static int pmz_set_scc_power(struct uart_pmac_port *uap, int state) | |||
792 | return delay; | 798 | return delay; |
793 | } | 799 | } |
794 | 800 | ||
801 | #else | ||
802 | |||
803 | static int pmz_set_scc_power(struct uart_pmac_port *uap, int state) | ||
804 | { | ||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | #endif /* !CONFIG_PPC_PMAC */ | ||
809 | |||
795 | /* | 810 | /* |
796 | * FixZeroBug....Works around a bug in the SCC receving channel. | 811 | * FixZeroBug....Works around a bug in the SCC receving channel. |
797 | * Inspired from Darwin code, 15 Sept. 2000 -DanM | 812 | * Inspired from Darwin code, 15 Sept. 2000 -DanM |
@@ -908,7 +923,6 @@ static int __pmz_startup(struct uart_pmac_port *uap) | |||
908 | /* Remember status for DCD/CTS changes */ | 923 | /* Remember status for DCD/CTS changes */ |
909 | uap->prev_status = read_zsreg(uap, R0); | 924 | uap->prev_status = read_zsreg(uap, R0); |
910 | 925 | ||
911 | |||
912 | return pwr_delay; | 926 | return pwr_delay; |
913 | } | 927 | } |
914 | 928 | ||
@@ -955,9 +969,9 @@ static int pmz_startup(struct uart_port *port) | |||
955 | } | 969 | } |
956 | 970 | ||
957 | pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON; | 971 | pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON; |
958 | if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED, "PowerMac Zilog", uap)) { | 972 | if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED, |
959 | dev_err(&uap->dev->ofdev.dev, | 973 | "SCC", uap)) { |
960 | "Unable to register zs interrupt handler.\n"); | 974 | pmz_error("Unable to register zs interrupt handler.\n"); |
961 | pmz_set_scc_power(uap, 0); | 975 | pmz_set_scc_power(uap, 0); |
962 | mutex_unlock(&pmz_irq_mutex); | 976 | mutex_unlock(&pmz_irq_mutex); |
963 | return -ENXIO; | 977 | return -ENXIO; |
@@ -983,7 +997,7 @@ static int pmz_startup(struct uart_port *port) | |||
983 | if (!ZS_IS_EXTCLK(uap)) | 997 | if (!ZS_IS_EXTCLK(uap)) |
984 | uap->curregs[R1] |= EXT_INT_ENAB; | 998 | uap->curregs[R1] |= EXT_INT_ENAB; |
985 | write_zsreg(uap, R1, uap->curregs[R1]); | 999 | write_zsreg(uap, R1, uap->curregs[R1]); |
986 | spin_unlock_irqrestore(&port->lock, flags); | 1000 | spin_unlock_irqrestore(&port->lock, flags); |
987 | 1001 | ||
988 | pmz_debug("pmz: startup() done.\n"); | 1002 | pmz_debug("pmz: startup() done.\n"); |
989 | 1003 | ||
@@ -1003,7 +1017,7 @@ static void pmz_shutdown(struct uart_port *port) | |||
1003 | mutex_lock(&pmz_irq_mutex); | 1017 | mutex_lock(&pmz_irq_mutex); |
1004 | 1018 | ||
1005 | /* Release interrupt handler */ | 1019 | /* Release interrupt handler */ |
1006 | free_irq(uap->port.irq, uap); | 1020 | free_irq(uap->port.irq, uap); |
1007 | 1021 | ||
1008 | spin_lock_irqsave(&port->lock, flags); | 1022 | spin_lock_irqsave(&port->lock, flags); |
1009 | 1023 | ||
@@ -1051,7 +1065,6 @@ static void pmz_convert_to_zs(struct uart_pmac_port *uap, unsigned int cflag, | |||
1051 | { | 1065 | { |
1052 | int brg; | 1066 | int brg; |
1053 | 1067 | ||
1054 | |||
1055 | /* Switch to external clocking for IrDA high clock rates. That | 1068 | /* Switch to external clocking for IrDA high clock rates. That |
1056 | * code could be re-used for Midi interfaces with different | 1069 | * code could be re-used for Midi interfaces with different |
1057 | * multipliers | 1070 | * multipliers |
@@ -1198,7 +1211,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1198 | while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0 | 1211 | while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0 |
1199 | || (read_zsreg(uap, R1) & ALL_SNT) == 0) { | 1212 | || (read_zsreg(uap, R1) & ALL_SNT) == 0) { |
1200 | if (--t <= 0) { | 1213 | if (--t <= 0) { |
1201 | dev_err(&uap->dev->ofdev.dev, "transmitter didn't drain\n"); | 1214 | pmz_error("transmitter didn't drain\n"); |
1202 | return; | 1215 | return; |
1203 | } | 1216 | } |
1204 | udelay(10); | 1217 | udelay(10); |
@@ -1214,7 +1227,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1214 | read_zsdata(uap); | 1227 | read_zsdata(uap); |
1215 | mdelay(10); | 1228 | mdelay(10); |
1216 | if (--t <= 0) { | 1229 | if (--t <= 0) { |
1217 | dev_err(&uap->dev->ofdev.dev, "receiver didn't drain\n"); | 1230 | pmz_error("receiver didn't drain\n"); |
1218 | return; | 1231 | return; |
1219 | } | 1232 | } |
1220 | } | 1233 | } |
@@ -1223,20 +1236,19 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1223 | uap->curregs[R5] |= DTR; | 1236 | uap->curregs[R5] |= DTR; |
1224 | write_zsreg(uap, R5, uap->curregs[R5]); | 1237 | write_zsreg(uap, R5, uap->curregs[R5]); |
1225 | zssync(uap); | 1238 | zssync(uap); |
1226 | mdelay(1); | 1239 | mdelay(1); |
1227 | 1240 | ||
1228 | /* Switch SCC to 19200 */ | 1241 | /* Switch SCC to 19200 */ |
1229 | pmz_convert_to_zs(uap, CS8, 0, 19200); | 1242 | pmz_convert_to_zs(uap, CS8, 0, 19200); |
1230 | pmz_load_zsregs(uap, uap->curregs); | 1243 | pmz_load_zsregs(uap, uap->curregs); |
1231 | mdelay(1); | 1244 | mdelay(1); |
1232 | 1245 | ||
1233 | /* Write get_version command byte */ | 1246 | /* Write get_version command byte */ |
1234 | write_zsdata(uap, 1); | 1247 | write_zsdata(uap, 1); |
1235 | t = 5000; | 1248 | t = 5000; |
1236 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { | 1249 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { |
1237 | if (--t <= 0) { | 1250 | if (--t <= 0) { |
1238 | dev_err(&uap->dev->ofdev.dev, | 1251 | pmz_error("irda_setup timed out on get_version byte\n"); |
1239 | "irda_setup timed out on get_version byte\n"); | ||
1240 | goto out; | 1252 | goto out; |
1241 | } | 1253 | } |
1242 | udelay(10); | 1254 | udelay(10); |
@@ -1244,8 +1256,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1244 | version = read_zsdata(uap); | 1256 | version = read_zsdata(uap); |
1245 | 1257 | ||
1246 | if (version < 4) { | 1258 | if (version < 4) { |
1247 | dev_info(&uap->dev->ofdev.dev, "IrDA: dongle version %d not supported\n", | 1259 | pmz_info("IrDA: dongle version %d not supported\n", version); |
1248 | version); | ||
1249 | goto out; | 1260 | goto out; |
1250 | } | 1261 | } |
1251 | 1262 | ||
@@ -1254,18 +1265,16 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1254 | t = 5000; | 1265 | t = 5000; |
1255 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { | 1266 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { |
1256 | if (--t <= 0) { | 1267 | if (--t <= 0) { |
1257 | dev_err(&uap->dev->ofdev.dev, | 1268 | pmz_error("irda_setup timed out on speed mode byte\n"); |
1258 | "irda_setup timed out on speed mode byte\n"); | ||
1259 | goto out; | 1269 | goto out; |
1260 | } | 1270 | } |
1261 | udelay(10); | 1271 | udelay(10); |
1262 | } | 1272 | } |
1263 | t = read_zsdata(uap); | 1273 | t = read_zsdata(uap); |
1264 | if (t != cmdbyte) | 1274 | if (t != cmdbyte) |
1265 | dev_err(&uap->dev->ofdev.dev, | 1275 | pmz_error("irda_setup speed mode byte = %x (%x)\n", t, cmdbyte); |
1266 | "irda_setup speed mode byte = %x (%x)\n", t, cmdbyte); | ||
1267 | 1276 | ||
1268 | dev_info(&uap->dev->ofdev.dev, "IrDA setup for %ld bps, dongle version: %d\n", | 1277 | pmz_info("IrDA setup for %ld bps, dongle version: %d\n", |
1269 | *baud, version); | 1278 | *baud, version); |
1270 | 1279 | ||
1271 | (void)read_zsdata(uap); | 1280 | (void)read_zsdata(uap); |
@@ -1415,7 +1424,7 @@ static void pmz_poll_put_char(struct uart_port *port, unsigned char c) | |||
1415 | write_zsdata(uap, c); | 1424 | write_zsdata(uap, c); |
1416 | } | 1425 | } |
1417 | 1426 | ||
1418 | #endif | 1427 | #endif /* CONFIG_CONSOLE_POLL */ |
1419 | 1428 | ||
1420 | static struct uart_ops pmz_pops = { | 1429 | static struct uart_ops pmz_pops = { |
1421 | .tx_empty = pmz_tx_empty, | 1430 | .tx_empty = pmz_tx_empty, |
@@ -1440,6 +1449,8 @@ static struct uart_ops pmz_pops = { | |||
1440 | #endif | 1449 | #endif |
1441 | }; | 1450 | }; |
1442 | 1451 | ||
1452 | #ifdef CONFIG_PPC_PMAC | ||
1453 | |||
1443 | /* | 1454 | /* |
1444 | * Setup one port structure after probing, HW is down at this point, | 1455 | * Setup one port structure after probing, HW is down at this point, |
1445 | * Unlike sunzilog, we don't need to pre-init the spinlock as we don't | 1456 | * Unlike sunzilog, we don't need to pre-init the spinlock as we don't |
@@ -1463,7 +1474,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap) | |||
1463 | return -ENODEV; | 1474 | return -ENODEV; |
1464 | uap->port.mapbase = r_ports.start; | 1475 | uap->port.mapbase = r_ports.start; |
1465 | uap->port.membase = ioremap(uap->port.mapbase, 0x1000); | 1476 | uap->port.membase = ioremap(uap->port.mapbase, 0x1000); |
1466 | 1477 | ||
1467 | uap->control_reg = uap->port.membase; | 1478 | uap->control_reg = uap->port.membase; |
1468 | uap->data_reg = uap->control_reg + 0x10; | 1479 | uap->data_reg = uap->control_reg + 0x10; |
1469 | 1480 | ||
@@ -1590,7 +1601,7 @@ static void pmz_dispose_port(struct uart_pmac_port *uap) | |||
1590 | } | 1601 | } |
1591 | 1602 | ||
1592 | /* | 1603 | /* |
1593 | * Called upon match with an escc node in the devive-tree. | 1604 | * Called upon match with an escc node in the device-tree. |
1594 | */ | 1605 | */ |
1595 | static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match) | 1606 | static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match) |
1596 | { | 1607 | { |
@@ -1812,7 +1823,7 @@ static int __init pmz_probe(void) | |||
1812 | pmz_ports[count].node = node_a; | 1823 | pmz_ports[count].node = node_a; |
1813 | pmz_ports[count+1].node = node_b; | 1824 | pmz_ports[count+1].node = node_b; |
1814 | pmz_ports[count].port.line = count; | 1825 | pmz_ports[count].port.line = count; |
1815 | pmz_ports[count+1].port.line = count+1; | 1826 | pmz_ports[count+1].port.line = count+1; |
1816 | 1827 | ||
1817 | /* | 1828 | /* |
1818 | * Setup the ports for real | 1829 | * Setup the ports for real |
@@ -1836,6 +1847,88 @@ next: | |||
1836 | return 0; | 1847 | return 0; |
1837 | } | 1848 | } |
1838 | 1849 | ||
1850 | #else | ||
1851 | |||
1852 | extern struct platform_device scc_a_pdev, scc_b_pdev; | ||
1853 | |||
1854 | static int __init pmz_init_port(struct uart_pmac_port *uap) | ||
1855 | { | ||
1856 | struct resource *r_ports; | ||
1857 | int irq; | ||
1858 | |||
1859 | r_ports = platform_get_resource(uap->node, IORESOURCE_MEM, 0); | ||
1860 | irq = platform_get_irq(uap->node, 0); | ||
1861 | if (!r_ports || !irq) | ||
1862 | return -ENODEV; | ||
1863 | |||
1864 | uap->port.mapbase = r_ports->start; | ||
1865 | uap->port.membase = (unsigned char __iomem *) r_ports->start; | ||
1866 | uap->port.iotype = UPIO_MEM; | ||
1867 | uap->port.irq = irq; | ||
1868 | uap->port.uartclk = ZS_CLOCK; | ||
1869 | uap->port.fifosize = 1; | ||
1870 | uap->port.ops = &pmz_pops; | ||
1871 | uap->port.type = PORT_PMAC_ZILOG; | ||
1872 | uap->port.flags = 0; | ||
1873 | |||
1874 | uap->control_reg = uap->port.membase; | ||
1875 | uap->data_reg = uap->control_reg + 4; | ||
1876 | uap->port_type = 0; | ||
1877 | |||
1878 | pmz_convert_to_zs(uap, CS8, 0, 9600); | ||
1879 | |||
1880 | return 0; | ||
1881 | } | ||
1882 | |||
1883 | static int __init pmz_probe(void) | ||
1884 | { | ||
1885 | int err; | ||
1886 | |||
1887 | pmz_ports_count = 0; | ||
1888 | |||
1889 | pmz_ports[0].mate = &pmz_ports[1]; | ||
1890 | pmz_ports[0].port.line = 0; | ||
1891 | pmz_ports[0].flags = PMACZILOG_FLAG_IS_CHANNEL_A; | ||
1892 | pmz_ports[0].node = &scc_a_pdev; | ||
1893 | err = pmz_init_port(&pmz_ports[0]); | ||
1894 | if (err) | ||
1895 | return err; | ||
1896 | pmz_ports_count++; | ||
1897 | |||
1898 | pmz_ports[1].mate = &pmz_ports[0]; | ||
1899 | pmz_ports[1].port.line = 1; | ||
1900 | pmz_ports[1].flags = 0; | ||
1901 | pmz_ports[1].node = &scc_b_pdev; | ||
1902 | err = pmz_init_port(&pmz_ports[1]); | ||
1903 | if (err) | ||
1904 | return err; | ||
1905 | pmz_ports_count++; | ||
1906 | |||
1907 | return 0; | ||
1908 | } | ||
1909 | |||
1910 | static void pmz_dispose_port(struct uart_pmac_port *uap) | ||
1911 | { | ||
1912 | memset(uap, 0, sizeof(struct uart_pmac_port)); | ||
1913 | } | ||
1914 | |||
1915 | static int __init pmz_attach(struct platform_device *pdev) | ||
1916 | { | ||
1917 | int i; | ||
1918 | |||
1919 | for (i = 0; i < pmz_ports_count; i++) | ||
1920 | if (pmz_ports[i].node == pdev) | ||
1921 | return 0; | ||
1922 | return -ENODEV; | ||
1923 | } | ||
1924 | |||
1925 | static int __exit pmz_detach(struct platform_device *pdev) | ||
1926 | { | ||
1927 | return 0; | ||
1928 | } | ||
1929 | |||
1930 | #endif /* !CONFIG_PPC_PMAC */ | ||
1931 | |||
1839 | #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE | 1932 | #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE |
1840 | 1933 | ||
1841 | static void pmz_console_write(struct console *con, const char *s, unsigned int count); | 1934 | static void pmz_console_write(struct console *con, const char *s, unsigned int count); |
@@ -1896,28 +1989,41 @@ err_out: | |||
1896 | return rc; | 1989 | return rc; |
1897 | } | 1990 | } |
1898 | 1991 | ||
1992 | #ifdef CONFIG_PPC_PMAC | ||
1993 | |||
1899 | static struct of_device_id pmz_match[] = | 1994 | static struct of_device_id pmz_match[] = |
1900 | { | 1995 | { |
1901 | { | 1996 | { |
1902 | .name = "ch-a", | 1997 | .name = "ch-a", |
1903 | }, | 1998 | }, |
1904 | { | 1999 | { |
1905 | .name = "ch-b", | 2000 | .name = "ch-b", |
1906 | }, | 2001 | }, |
1907 | {}, | 2002 | {}, |
1908 | }; | 2003 | }; |
1909 | MODULE_DEVICE_TABLE (of, pmz_match); | 2004 | MODULE_DEVICE_TABLE (of, pmz_match); |
1910 | 2005 | ||
1911 | static struct macio_driver pmz_driver = | 2006 | static struct macio_driver pmz_driver = { |
1912 | { | ||
1913 | .name = "pmac_zilog", | 2007 | .name = "pmac_zilog", |
1914 | .match_table = pmz_match, | 2008 | .match_table = pmz_match, |
1915 | .probe = pmz_attach, | 2009 | .probe = pmz_attach, |
1916 | .remove = pmz_detach, | 2010 | .remove = pmz_detach, |
1917 | .suspend = pmz_suspend, | 2011 | .suspend = pmz_suspend, |
1918 | .resume = pmz_resume, | 2012 | .resume = pmz_resume, |
1919 | }; | 2013 | }; |
1920 | 2014 | ||
2015 | #else | ||
2016 | |||
2017 | static struct platform_driver pmz_driver = { | ||
2018 | .remove = __exit_p(pmz_detach), | ||
2019 | .driver = { | ||
2020 | .name = "scc", | ||
2021 | .owner = THIS_MODULE, | ||
2022 | }, | ||
2023 | }; | ||
2024 | |||
2025 | #endif /* !CONFIG_PPC_PMAC */ | ||
2026 | |||
1921 | static int __init init_pmz(void) | 2027 | static int __init init_pmz(void) |
1922 | { | 2028 | { |
1923 | int rc, i; | 2029 | int rc, i; |
@@ -1952,19 +2058,27 @@ static int __init init_pmz(void) | |||
1952 | pmz_dispose_port(&pmz_ports[i]); | 2058 | pmz_dispose_port(&pmz_ports[i]); |
1953 | return rc; | 2059 | return rc; |
1954 | } | 2060 | } |
1955 | 2061 | ||
1956 | /* | 2062 | /* |
1957 | * Then we register the macio driver itself | 2063 | * Then we register the macio driver itself |
1958 | */ | 2064 | */ |
2065 | #ifdef CONFIG_PPC_PMAC | ||
1959 | return macio_register_driver(&pmz_driver); | 2066 | return macio_register_driver(&pmz_driver); |
2067 | #else | ||
2068 | return platform_driver_probe(&pmz_driver, pmz_attach); | ||
2069 | #endif | ||
1960 | } | 2070 | } |
1961 | 2071 | ||
1962 | static void __exit exit_pmz(void) | 2072 | static void __exit exit_pmz(void) |
1963 | { | 2073 | { |
1964 | int i; | 2074 | int i; |
1965 | 2075 | ||
2076 | #ifdef CONFIG_PPC_PMAC | ||
1966 | /* Get rid of macio-driver (detach from macio) */ | 2077 | /* Get rid of macio-driver (detach from macio) */ |
1967 | macio_unregister_driver(&pmz_driver); | 2078 | macio_unregister_driver(&pmz_driver); |
2079 | #else | ||
2080 | platform_driver_unregister(&pmz_driver); | ||
2081 | #endif | ||
1968 | 2082 | ||
1969 | for (i = 0; i < pmz_ports_count; i++) { | 2083 | for (i = 0; i < pmz_ports_count; i++) { |
1970 | struct uart_pmac_port *uport = &pmz_ports[i]; | 2084 | struct uart_pmac_port *uport = &pmz_ports[i]; |
@@ -2031,10 +2145,10 @@ static int __init pmz_console_setup(struct console *co, char *options) | |||
2031 | /* | 2145 | /* |
2032 | * XServe's default to 57600 bps | 2146 | * XServe's default to 57600 bps |
2033 | */ | 2147 | */ |
2034 | if (machine_is_compatible("RackMac1,1") | 2148 | if (of_machine_is_compatible("RackMac1,1") |
2035 | || machine_is_compatible("RackMac1,2") | 2149 | || of_machine_is_compatible("RackMac1,2") |
2036 | || machine_is_compatible("MacRISC4")) | 2150 | || of_machine_is_compatible("MacRISC4")) |
2037 | baud = 57600; | 2151 | baud = 57600; |
2038 | 2152 | ||
2039 | /* | 2153 | /* |
2040 | * Check whether an invalid uart number has been specified, and | 2154 | * Check whether an invalid uart number has been specified, and |