diff options
Diffstat (limited to 'drivers/char/amiserial.c')
-rw-r--r-- | drivers/char/amiserial.c | 61 |
1 files changed, 35 insertions, 26 deletions
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 56b27671adc4..4f8d60c25a98 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -84,6 +84,7 @@ static char *serial_version = "4.30"; | |||
84 | #include <linux/smp_lock.h> | 84 | #include <linux/smp_lock.h> |
85 | #include <linux/init.h> | 85 | #include <linux/init.h> |
86 | #include <linux/bitops.h> | 86 | #include <linux/bitops.h> |
87 | #include <linux/platform_device.h> | ||
87 | 88 | ||
88 | #include <asm/setup.h> | 89 | #include <asm/setup.h> |
89 | 90 | ||
@@ -1954,29 +1955,16 @@ static const struct tty_operations serial_ops = { | |||
1954 | /* | 1955 | /* |
1955 | * The serial driver boot-time initialization code! | 1956 | * The serial driver boot-time initialization code! |
1956 | */ | 1957 | */ |
1957 | static int __init rs_init(void) | 1958 | static int __init amiga_serial_probe(struct platform_device *pdev) |
1958 | { | 1959 | { |
1959 | unsigned long flags; | 1960 | unsigned long flags; |
1960 | struct serial_state * state; | 1961 | struct serial_state * state; |
1961 | int error; | 1962 | int error; |
1962 | 1963 | ||
1963 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_SERIAL)) | ||
1964 | return -ENODEV; | ||
1965 | |||
1966 | serial_driver = alloc_tty_driver(1); | 1964 | serial_driver = alloc_tty_driver(1); |
1967 | if (!serial_driver) | 1965 | if (!serial_driver) |
1968 | return -ENOMEM; | 1966 | return -ENOMEM; |
1969 | 1967 | ||
1970 | /* | ||
1971 | * We request SERDAT and SERPER only, because the serial registers are | ||
1972 | * too spreaded over the custom register space | ||
1973 | */ | ||
1974 | if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4, | ||
1975 | "amiserial [Paula]")) { | ||
1976 | error = -EBUSY; | ||
1977 | goto fail_put_tty_driver; | ||
1978 | } | ||
1979 | |||
1980 | IRQ_ports = NULL; | 1968 | IRQ_ports = NULL; |
1981 | 1969 | ||
1982 | show_serial_version(); | 1970 | show_serial_version(); |
@@ -1998,7 +1986,7 @@ static int __init rs_init(void) | |||
1998 | 1986 | ||
1999 | error = tty_register_driver(serial_driver); | 1987 | error = tty_register_driver(serial_driver); |
2000 | if (error) | 1988 | if (error) |
2001 | goto fail_release_mem_region; | 1989 | goto fail_put_tty_driver; |
2002 | 1990 | ||
2003 | state = rs_table; | 1991 | state = rs_table; |
2004 | state->magic = SSTATE_MAGIC; | 1992 | state->magic = SSTATE_MAGIC; |
@@ -2050,23 +2038,24 @@ static int __init rs_init(void) | |||
2050 | ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ | 2038 | ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ |
2051 | ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */ | 2039 | ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */ |
2052 | 2040 | ||
2041 | platform_set_drvdata(pdev, state); | ||
2042 | |||
2053 | return 0; | 2043 | return 0; |
2054 | 2044 | ||
2055 | fail_free_irq: | 2045 | fail_free_irq: |
2056 | free_irq(IRQ_AMIGA_TBE, state); | 2046 | free_irq(IRQ_AMIGA_TBE, state); |
2057 | fail_unregister: | 2047 | fail_unregister: |
2058 | tty_unregister_driver(serial_driver); | 2048 | tty_unregister_driver(serial_driver); |
2059 | fail_release_mem_region: | ||
2060 | release_mem_region(CUSTOM_PHYSADDR+0x30, 4); | ||
2061 | fail_put_tty_driver: | 2049 | fail_put_tty_driver: |
2062 | put_tty_driver(serial_driver); | 2050 | put_tty_driver(serial_driver); |
2063 | return error; | 2051 | return error; |
2064 | } | 2052 | } |
2065 | 2053 | ||
2066 | static __exit void rs_exit(void) | 2054 | static int __exit amiga_serial_remove(struct platform_device *pdev) |
2067 | { | 2055 | { |
2068 | int error; | 2056 | int error; |
2069 | struct async_struct *info = rs_table[0].info; | 2057 | struct serial_state *state = platform_get_drvdata(pdev); |
2058 | struct async_struct *info = state->info; | ||
2070 | 2059 | ||
2071 | /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ | 2060 | /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ |
2072 | tasklet_kill(&info->tlet); | 2061 | tasklet_kill(&info->tlet); |
@@ -2075,19 +2064,38 @@ static __exit void rs_exit(void) | |||
2075 | error); | 2064 | error); |
2076 | put_tty_driver(serial_driver); | 2065 | put_tty_driver(serial_driver); |
2077 | 2066 | ||
2078 | if (info) { | 2067 | rs_table[0].info = NULL; |
2079 | rs_table[0].info = NULL; | 2068 | kfree(info); |
2080 | kfree(info); | ||
2081 | } | ||
2082 | 2069 | ||
2083 | free_irq(IRQ_AMIGA_TBE, rs_table); | 2070 | free_irq(IRQ_AMIGA_TBE, rs_table); |
2084 | free_irq(IRQ_AMIGA_RBF, rs_table); | 2071 | free_irq(IRQ_AMIGA_RBF, rs_table); |
2085 | 2072 | ||
2086 | release_mem_region(CUSTOM_PHYSADDR+0x30, 4); | 2073 | platform_set_drvdata(pdev, NULL); |
2074 | |||
2075 | return error; | ||
2076 | } | ||
2077 | |||
2078 | static struct platform_driver amiga_serial_driver = { | ||
2079 | .remove = __exit_p(amiga_serial_remove), | ||
2080 | .driver = { | ||
2081 | .name = "amiga-serial", | ||
2082 | .owner = THIS_MODULE, | ||
2083 | }, | ||
2084 | }; | ||
2085 | |||
2086 | static int __init amiga_serial_init(void) | ||
2087 | { | ||
2088 | return platform_driver_probe(&amiga_serial_driver, amiga_serial_probe); | ||
2089 | } | ||
2090 | |||
2091 | module_init(amiga_serial_init); | ||
2092 | |||
2093 | static void __exit amiga_serial_exit(void) | ||
2094 | { | ||
2095 | platform_driver_unregister(&amiga_serial_driver); | ||
2087 | } | 2096 | } |
2088 | 2097 | ||
2089 | module_init(rs_init) | 2098 | module_exit(amiga_serial_exit); |
2090 | module_exit(rs_exit) | ||
2091 | 2099 | ||
2092 | 2100 | ||
2093 | #if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE) | 2101 | #if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE) |
@@ -2154,3 +2162,4 @@ console_initcall(amiserial_console_init); | |||
2154 | #endif /* CONFIG_SERIAL_CONSOLE && !MODULE */ | 2162 | #endif /* CONFIG_SERIAL_CONSOLE && !MODULE */ |
2155 | 2163 | ||
2156 | MODULE_LICENSE("GPL"); | 2164 | MODULE_LICENSE("GPL"); |
2165 | MODULE_ALIAS("platform:amiga-serial"); | ||