diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2009-11-17 04:04:44 -0500 |
---|---|---|
committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2010-02-27 12:31:02 -0500 |
commit | ec9cbe09899e36b5f216c3232215520dcf0320ab (patch) | |
tree | 7960e72bdad982d7dd18cab1e49ae3ca42d1a5a0 /drivers/serial/pmac_zilog.c | |
parent | 1f7b5fff505232521a7a770a639b63cd17636549 (diff) |
pmac-zilog: add platform driver
Add platform driver support to the pmac-zilog driver, for m68k macs.
Place the powermac-specific code inside #ifdef CONFIG_PPC_PMAC.
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'drivers/serial/pmac_zilog.c')
-rw-r--r-- | drivers/serial/pmac_zilog.c | 155 |
1 files changed, 136 insertions, 19 deletions
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 1c8afd98e14e..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 |
@@ -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 | ||
@@ -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 |
@@ -954,9 +969,9 @@ static int pmz_startup(struct uart_port *port) | |||
954 | } | 969 | } |
955 | 970 | ||
956 | pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON; | 971 | pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON; |
957 | if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED, "PowerMac Zilog", uap)) { | 972 | if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED, |
958 | dev_err(&uap->dev->ofdev.dev, | 973 | "SCC", uap)) { |
959 | "Unable to register zs interrupt handler.\n"); | 974 | pmz_error("Unable to register zs interrupt handler.\n"); |
960 | pmz_set_scc_power(uap, 0); | 975 | pmz_set_scc_power(uap, 0); |
961 | mutex_unlock(&pmz_irq_mutex); | 976 | mutex_unlock(&pmz_irq_mutex); |
962 | return -ENXIO; | 977 | return -ENXIO; |
@@ -1196,7 +1211,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1196 | while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0 | 1211 | while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0 |
1197 | || (read_zsreg(uap, R1) & ALL_SNT) == 0) { | 1212 | || (read_zsreg(uap, R1) & ALL_SNT) == 0) { |
1198 | if (--t <= 0) { | 1213 | if (--t <= 0) { |
1199 | dev_err(&uap->dev->ofdev.dev, "transmitter didn't drain\n"); | 1214 | pmz_error("transmitter didn't drain\n"); |
1200 | return; | 1215 | return; |
1201 | } | 1216 | } |
1202 | udelay(10); | 1217 | udelay(10); |
@@ -1212,7 +1227,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1212 | read_zsdata(uap); | 1227 | read_zsdata(uap); |
1213 | mdelay(10); | 1228 | mdelay(10); |
1214 | if (--t <= 0) { | 1229 | if (--t <= 0) { |
1215 | dev_err(&uap->dev->ofdev.dev, "receiver didn't drain\n"); | 1230 | pmz_error("receiver didn't drain\n"); |
1216 | return; | 1231 | return; |
1217 | } | 1232 | } |
1218 | } | 1233 | } |
@@ -1233,8 +1248,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1233 | t = 5000; | 1248 | t = 5000; |
1234 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { | 1249 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { |
1235 | if (--t <= 0) { | 1250 | if (--t <= 0) { |
1236 | dev_err(&uap->dev->ofdev.dev, | 1251 | pmz_error("irda_setup timed out on get_version byte\n"); |
1237 | "irda_setup timed out on get_version byte\n"); | ||
1238 | goto out; | 1252 | goto out; |
1239 | } | 1253 | } |
1240 | udelay(10); | 1254 | udelay(10); |
@@ -1242,8 +1256,7 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1242 | version = read_zsdata(uap); | 1256 | version = read_zsdata(uap); |
1243 | 1257 | ||
1244 | if (version < 4) { | 1258 | if (version < 4) { |
1245 | dev_info(&uap->dev->ofdev.dev, "IrDA: dongle version %d not supported\n", | 1259 | pmz_info("IrDA: dongle version %d not supported\n", version); |
1246 | version); | ||
1247 | goto out; | 1260 | goto out; |
1248 | } | 1261 | } |
1249 | 1262 | ||
@@ -1252,18 +1265,16 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) | |||
1252 | t = 5000; | 1265 | t = 5000; |
1253 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { | 1266 | while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { |
1254 | if (--t <= 0) { | 1267 | if (--t <= 0) { |
1255 | dev_err(&uap->dev->ofdev.dev, | 1268 | pmz_error("irda_setup timed out on speed mode byte\n"); |
1256 | "irda_setup timed out on speed mode byte\n"); | ||
1257 | goto out; | 1269 | goto out; |
1258 | } | 1270 | } |
1259 | udelay(10); | 1271 | udelay(10); |
1260 | } | 1272 | } |
1261 | t = read_zsdata(uap); | 1273 | t = read_zsdata(uap); |
1262 | if (t != cmdbyte) | 1274 | if (t != cmdbyte) |
1263 | dev_err(&uap->dev->ofdev.dev, | 1275 | pmz_error("irda_setup speed mode byte = %x (%x)\n", t, cmdbyte); |
1264 | "irda_setup speed mode byte = %x (%x)\n", t, cmdbyte); | ||
1265 | 1276 | ||
1266 | 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", |
1267 | *baud, version); | 1278 | *baud, version); |
1268 | 1279 | ||
1269 | (void)read_zsdata(uap); | 1280 | (void)read_zsdata(uap); |
@@ -1413,7 +1424,7 @@ static void pmz_poll_put_char(struct uart_port *port, unsigned char c) | |||
1413 | write_zsdata(uap, c); | 1424 | write_zsdata(uap, c); |
1414 | } | 1425 | } |
1415 | 1426 | ||
1416 | #endif | 1427 | #endif /* CONFIG_CONSOLE_POLL */ |
1417 | 1428 | ||
1418 | static struct uart_ops pmz_pops = { | 1429 | static struct uart_ops pmz_pops = { |
1419 | .tx_empty = pmz_tx_empty, | 1430 | .tx_empty = pmz_tx_empty, |
@@ -1438,6 +1449,8 @@ static struct uart_ops pmz_pops = { | |||
1438 | #endif | 1449 | #endif |
1439 | }; | 1450 | }; |
1440 | 1451 | ||
1452 | #ifdef CONFIG_PPC_PMAC | ||
1453 | |||
1441 | /* | 1454 | /* |
1442 | * 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, |
1443 | * 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 |
@@ -1834,6 +1847,88 @@ next: | |||
1834 | return 0; | 1847 | return 0; |
1835 | } | 1848 | } |
1836 | 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 | |||
1837 | #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE | 1932 | #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE |
1838 | 1933 | ||
1839 | 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); |
@@ -1894,6 +1989,8 @@ err_out: | |||
1894 | return rc; | 1989 | return rc; |
1895 | } | 1990 | } |
1896 | 1991 | ||
1992 | #ifdef CONFIG_PPC_PMAC | ||
1993 | |||
1897 | static struct of_device_id pmz_match[] = | 1994 | static struct of_device_id pmz_match[] = |
1898 | { | 1995 | { |
1899 | { | 1996 | { |
@@ -1915,6 +2012,18 @@ static struct macio_driver pmz_driver = { | |||
1915 | .resume = pmz_resume, | 2012 | .resume = pmz_resume, |
1916 | }; | 2013 | }; |
1917 | 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 | |||
1918 | static int __init init_pmz(void) | 2027 | static int __init init_pmz(void) |
1919 | { | 2028 | { |
1920 | int rc, i; | 2029 | int rc, i; |
@@ -1953,15 +2062,23 @@ static int __init init_pmz(void) | |||
1953 | /* | 2062 | /* |
1954 | * Then we register the macio driver itself | 2063 | * Then we register the macio driver itself |
1955 | */ | 2064 | */ |
2065 | #ifdef CONFIG_PPC_PMAC | ||
1956 | 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 | ||
1957 | } | 2070 | } |
1958 | 2071 | ||
1959 | static void __exit exit_pmz(void) | 2072 | static void __exit exit_pmz(void) |
1960 | { | 2073 | { |
1961 | int i; | 2074 | int i; |
1962 | 2075 | ||
2076 | #ifdef CONFIG_PPC_PMAC | ||
1963 | /* Get rid of macio-driver (detach from macio) */ | 2077 | /* Get rid of macio-driver (detach from macio) */ |
1964 | macio_unregister_driver(&pmz_driver); | 2078 | macio_unregister_driver(&pmz_driver); |
2079 | #else | ||
2080 | platform_driver_unregister(&pmz_driver); | ||
2081 | #endif | ||
1965 | 2082 | ||
1966 | for (i = 0; i < pmz_ports_count; i++) { | 2083 | for (i = 0; i < pmz_ports_count; i++) { |
1967 | struct uart_pmac_port *uport = &pmz_ports[i]; | 2084 | struct uart_pmac_port *uport = &pmz_ports[i]; |