* [PATCH/RFC 0/16] m68k: Device model patches
@ 2009-04-18 18:52 Geert Uytterhoeven
2009-04-18 18:52 ` [PATCH/RFC 01/16] platform: Make platform resources input parameters const Geert Uytterhoeven
2009-05-05 7:36 ` [PATCH/RFC 0/16] m68k: Device model patches Geert Uytterhoeven
0 siblings, 2 replies; 24+ messages in thread
From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw)
To: linux-m68k, linux-kernel
This set of patches brings Amiga hardware support better in line with to the
Linux device model:
- Add module alias support for Zorro drivers (not all drivers can
benefit from this yet though, as some still use zorro_find_device()
instead of struct zorro_driver),
- Convert the various builtin Amiga hardware to the platform driver
framework.
[01] platform: Make platform resources input parameters const
[02] m68k: amiga - Zorro bus modalias support
[03] m68k: amiga - Zorro host bridge platform device conversion
[04] m68k: amiga - Frame buffer platform device conversion
[05] m68k: amiga - Sound platform device conversion
[06] m68k: amiga - Floppy platform device conversion
[07] m68k: amiga - A3000 SCSI platform device conversion
[08] m68k: amiga - A4000T SCSI platform device conversion
[09] m68k: amiga - Amiga Gayle IDE platform device conversion
[10] m68k: amiga - Keyboard platform device conversion
[11] m68k: amiga - Mouse platform device conversion
[12] m68k: amiga - Serial port platform device conversion
[13] m68k: amiga - Parallel port platform device conversion
[14] rtc: Add an RTC driver for the Oki MSM6242
[15] rtc: Add an RTC driver for the Ricoh RP5C01
[16] m68k: amiga - RTC platform device conversion
Due to lack of hardware (only Amiga 4000 here), I couldn't test all drivers.
Especially the SCSI drivers could use some testing feedback.
The changes to most other drivers are fairly trivial.
Note that I removed all request_mem_region() calls for subregions of the Amiga
custom chips, as the drivers now bind to the platform device.
Thanks for your review comments (and other feedback, of course)!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH/RFC 01/16] platform: Make platform resources input parameters const 2009-04-18 18:52 [PATCH/RFC 0/16] m68k: Device model patches Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 02/16] m68k: amiga - Zorro bus modalias support Geert Uytterhoeven 2009-04-18 23:25 ` [PATCH/RFC 01/16] platform: Make platform resources input parameters const Greg KH 2009-05-05 7:36 ` [PATCH/RFC 0/16] m68k: Device model patches Geert Uytterhoeven 1 sibling, 2 replies; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, Greg Kroah-Hartman Make the platform resources input parameters of platform_device_add_resources() and platform_device_register_simple() const, as the resources are copied and never modified. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/base/platform.c | 4 ++-- include/linux/platform_device.h | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index b5b6c97..2c83e21 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -184,7 +184,7 @@ EXPORT_SYMBOL_GPL(platform_device_alloc); * released. */ int platform_device_add_resources(struct platform_device *pdev, - struct resource *res, unsigned int num) + const struct resource *res, unsigned int num) { struct resource *r; @@ -379,7 +379,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); */ struct platform_device *platform_device_register_simple(const char *name, int id, - struct resource *res, + const struct resource *res, unsigned int num) { struct platform_device *pdev; diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 72736fd..1391a5d 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -42,12 +42,14 @@ extern int platform_get_irq_byname(struct platform_device *, char *); extern int platform_add_devices(struct platform_device **, int); extern struct platform_device *platform_device_register_simple(const char *, int id, - struct resource *, unsigned int); + const struct resource *, unsigned int); extern struct platform_device *platform_device_register_data(struct device *, const char *, int, const void *, size_t); extern struct platform_device *platform_device_alloc(const char *name, int id); -extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num); +extern int platform_device_add_resources(struct platform_device *pdev, + const struct resource *res, + unsigned int num); extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size); extern int platform_device_add(struct platform_device *pdev); extern void platform_device_del(struct platform_device *pdev); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 02/16] m68k: amiga - Zorro bus modalias support 2009-04-18 18:52 ` [PATCH/RFC 01/16] platform: Make platform resources input parameters const Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 03/16] m68k: amiga - Zorro host bridge platform device conversion Geert Uytterhoeven 2009-04-18 23:25 ` [PATCH/RFC 01/16] platform: Make platform resources input parameters const Greg KH 1 sibling, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> --- drivers/net/a2065.c | 1 + drivers/net/ariadne.c | 1 + drivers/net/hydra.c | 1 + drivers/net/zorro8390.c | 1 + drivers/scsi/zorro7xx.c | 1 + drivers/video/cirrusfb.c | 1 + drivers/video/fm2fb.c | 1 + drivers/zorro/zorro-driver.c | 24 ++++++++++++++++++++++++ drivers/zorro/zorro-sysfs.c | 11 +++++++++++ include/linux/mod_devicetable.h | 9 +++++++++ include/linux/zorro.h | 13 +------------ scripts/mod/file2alias.c | 14 ++++++++++++++ 12 files changed, 66 insertions(+), 12 deletions(-) diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 02f64d5..6619069 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -684,6 +684,7 @@ static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = { { ZORRO_PROD_AMERISTAR_A2065 }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, a2065_zorro_tbl); static struct zorro_driver a2065_driver = { .name = "a2065", diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index 58e8d52..74ad89d 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -147,6 +147,7 @@ static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = { { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl); static struct zorro_driver ariadne_driver = { .name = "ariadne", diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 8ac0930..358d8ce 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -72,6 +72,7 @@ static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = { { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl); static struct zorro_driver hydra_driver = { .name = "hydra", diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index 37c84e3..d7755a9 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -102,6 +102,7 @@ static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = { { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl); static struct zorro_driver zorro8390_driver = { .name = "zorro8390", diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index 64d40a2..b416fa4 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c @@ -68,6 +68,7 @@ static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = { }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl); static int __devinit zorro7xx_init_one(struct zorro_dev *z, const struct zorro_device_id *ent) diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 4c2bf92..dc5d201 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -300,6 +300,7 @@ static const struct zorro_device_id cirrusfb_zorro_table[] = { }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); static const struct { zorro_id id2; diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index 6c91c61..1b0feb8 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -219,6 +219,7 @@ static struct zorro_device_id fm2fb_devices[] __devinitdata = { { ZORRO_PROD_HELFRICH_RAINBOW_II }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, fm2fb_devices); static struct zorro_driver fm2fb_driver = { .name = "fm2fb", diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index e6c4390..409244b 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c @@ -137,10 +137,34 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv) return 0; } +static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env) +{ +#ifdef CONFIG_HOTPLUG + struct zorro_dev *z; + + if (!dev) + return -ENODEV; + + z = to_zorro_dev(dev); + if (!z) + return -ENODEV; + + if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) || + add_uevent_var(env, "ZORRO_SLOT_NAME=%s", dev_name(dev)) || + add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) || + add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id)) + return -ENOMEM; + + return 0; +#else /* !CONFIG_HOTPLUG */ + return -ENODEV; +#endif /* !CONFIG_HOTPLUG */ +} struct bus_type zorro_bus_type = { .name = "zorro", .match = zorro_bus_match, + .uevent = zorro_uevent, .probe = zorro_device_probe, .remove = zorro_device_remove, }; diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 1d2a772..26dff20 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c @@ -49,6 +49,16 @@ static ssize_t zorro_show_resource(struct device *dev, struct device_attribute * static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL); +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct zorro_dev *z = to_zorro_dev(dev); + + return sprintf(buf, ZORRO_DEVICE_MODALIAS_FMT "\n", z->id); +} + +static DEVICE_ATTR(modalias, S_IRUGO, modalias_show, NULL); + static ssize_t zorro_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) @@ -89,6 +99,7 @@ int zorro_create_sysfs_dev_files(struct zorro_dev *z) (error = device_create_file(dev, &dev_attr_slotaddr)) || (error = device_create_file(dev, &dev_attr_slotsize)) || (error = device_create_file(dev, &dev_attr_resource)) || + (error = device_create_file(dev, &dev_attr_modalias)) || (error = sysfs_create_bin_file(&dev->kobj, &zorro_config_attr))) return error; diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 1bf5900..a31cf4f 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -463,4 +463,13 @@ struct platform_device_id { __attribute__((aligned(sizeof(kernel_ulong_t)))); }; +struct zorro_device_id { + __u32 id; /* Device ID or ZORRO_WILDCARD */ + kernel_ulong_t driver_data; /* Data private to the driver */ +}; + +#define ZORRO_WILDCARD (0xffffffff) /* not official */ + +#define ZORRO_DEVICE_MODALIAS_FMT "zorro:i%08X" + #endif /* LINUX_MOD_DEVICETABLE_H */ diff --git a/include/linux/zorro.h b/include/linux/zorro.h index 913bfc2..908db1b 100644 --- a/include/linux/zorro.h +++ b/include/linux/zorro.h @@ -38,8 +38,6 @@ typedef __u32 zorro_id; -#define ZORRO_WILDCARD (0xffffffff) /* not official */ - /* Include the ID list */ #include <linux/zorro_ids.h> @@ -116,6 +114,7 @@ struct ConfigDev { #include <linux/init.h> #include <linux/ioport.h> +#include <linux/mod_devicetable.h> #include <asm/zorro.h> @@ -155,16 +154,6 @@ extern struct bus_type zorro_bus_type; /* - * Zorro device IDs - */ - -struct zorro_device_id { - zorro_id id; /* Device ID or ZORRO_WILDCARD */ - unsigned long driver_data; /* Data private to the driver */ -}; - - - /* * Zorro device drivers */ diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index a334428..633af66 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -718,6 +718,16 @@ static int do_platform_entry(const char *filename, return 1; } +/* Looks like: zorro:iN. */ +static int do_zorro_entry(const char *filename, struct zorro_device_id *id, + char *alias) +{ + id->id = TO_NATIVE(id->id); + strcpy(alias, "zorro:"); + ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id); + return 1; +} + /* Ignore any prefix, eg. some architectures prepend _ */ static inline int sym_is(const char *symbol, const char *name) { @@ -861,6 +871,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, do_table(symval, sym->st_size, sizeof(struct platform_device_id), "platform", do_platform_entry, mod); + else if (sym_is(symname, "__mod_zorro_device_table")) + do_table(symval, sym->st_size, + sizeof(struct zorro_device_id), "zorro", + do_zorro_entry, mod); free(zeros); } -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 03/16] m68k: amiga - Zorro host bridge platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 02/16] m68k: amiga - Zorro bus modalias support Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 04/16] m68k: amiga - Frame buffer " Geert Uytterhoeven 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> --- arch/m68k/amiga/Makefile | 2 +- arch/m68k/amiga/platform.c | 58 +++++++++++ drivers/zorro/proc.c | 6 +- drivers/zorro/zorro.c | 242 +++++++++++++++++++++++--------------------- include/linux/zorro.h | 9 -- 5 files changed, 189 insertions(+), 128 deletions(-) create mode 100644 arch/m68k/amiga/platform.c diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile index 6a0d765..11dd30b 100644 --- a/arch/m68k/amiga/Makefile +++ b/arch/m68k/amiga/Makefile @@ -2,6 +2,6 @@ # Makefile for Linux arch/m68k/amiga source directory # -obj-y := config.o amiints.o cia.o chipram.o amisound.o +obj-y := config.o amiints.o cia.o chipram.o amisound.o platform.o obj-$(CONFIG_AMIGA_PCMCIA) += pcmcia.o diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c new file mode 100644 index 0000000..33a7669 --- /dev/null +++ b/arch/m68k/amiga/platform.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007-2009 Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/zorro.h> + +#include <asm/amigahw.h> + + +#ifdef CONFIG_ZORRO + +static const struct resource zorro_resources[] __initconst = { + /* Zorro II regions (on Zorro II/III) */ + { + .name = "Zorro II exp", + .start = 0x00e80000, + .end = 0x00efffff, + .flags = IORESOURCE_MEM, + }, { + .name = "Zorro II mem", + .start = 0x00200000, + .end = 0x009fffff, + .flags = IORESOURCE_MEM, + }, + /* Zorro III regions (on Zorro III only) */ + { + .name = "Zorro III exp", + .start = 0xff000000, + .end = 0xffffffff, + .flags = IORESOURCE_MEM, + }, { + .name = "Zorro III cfg", + .start = 0x40000000, + .end = 0x7fffffff, + .flags = IORESOURCE_MEM, + } +}; + + +static int __init amiga_init_bus(void) +{ + if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) + return -ENODEV; + + platform_device_register_simple("amiga-zorro", -1, zorro_resources, + AMIGAHW_PRESENT(ZORRO3) ? 4 : 2); + return 0; +} + +subsys_initcall(amiga_init_bus); + +#endif /* CONFIG_ZORRO */ diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index d47c47f..3c7046d 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c @@ -97,7 +97,7 @@ static void zorro_seq_stop(struct seq_file *m, void *v) static int zorro_seq_show(struct seq_file *m, void *v) { - u_int slot = *(loff_t *)v; + unsigned int slot = *(loff_t *)v; struct zorro_dev *z = &zorro_autocon[slot]; seq_printf(m, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, z->id, @@ -129,7 +129,7 @@ static const struct file_operations zorro_devices_proc_fops = { static struct proc_dir_entry *proc_bus_zorro_dir; -static int __init zorro_proc_attach_device(u_int slot) +static int __init zorro_proc_attach_device(unsigned int slot) { struct proc_dir_entry *entry; char name[4]; @@ -146,7 +146,7 @@ static int __init zorro_proc_attach_device(u_int slot) static int __init zorro_proc_init(void) { - u_int slot; + unsigned int slot; if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) { proc_bus_zorro_dir = proc_mkdir("bus/zorro", NULL); diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index d45fb34..3a3cad9 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -15,6 +15,7 @@ #include <linux/zorro.h> #include <linux/bitops.h> #include <linux/string.h> +#include <linux/platform_device.h> #include <asm/setup.h> #include <asm/amigahw.h> @@ -26,24 +27,17 @@ * Zorro Expansion Devices */ -u_int zorro_num_autocon = 0; +unsigned int zorro_num_autocon; struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; /* - * Single Zorro bus + * Zorro bus */ -struct zorro_bus zorro_bus = {\ - .resources = { - /* Zorro II regions (on Zorro II/III) */ - { .name = "Zorro II exp", .start = 0x00e80000, .end = 0x00efffff }, - { .name = "Zorro II mem", .start = 0x00200000, .end = 0x009fffff }, - /* Zorro III regions (on Zorro III only) */ - { .name = "Zorro III exp", .start = 0xff000000, .end = 0xffffffff }, - { .name = "Zorro III cfg", .start = 0x40000000, .end = 0x7fffffff } - }, - .name = "Zorro bus" +struct zorro_bus { + struct list_head devices; /* list of devices on this bus */ + struct device dev; }; @@ -53,18 +47,19 @@ struct zorro_bus zorro_bus = {\ struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) { - struct zorro_dev *z; + struct zorro_dev *z; - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) - return NULL; + if (!zorro_num_autocon) + return NULL; - for (z = from ? from+1 : &zorro_autocon[0]; - z < zorro_autocon+zorro_num_autocon; - z++) - if (id == ZORRO_WILDCARD || id == z->id) - return z; - return NULL; + for (z = from ? from+1 : &zorro_autocon[0]; + z < zorro_autocon+zorro_num_autocon; + z++) + if (id == ZORRO_WILDCARD || id == z->id) + return z; + return NULL; } +EXPORT_SYMBOL(zorro_find_device); /* @@ -83,121 +78,138 @@ struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) */ DECLARE_BITMAP(zorro_unused_z2ram, 128); +EXPORT_SYMBOL(zorro_unused_z2ram); static void __init mark_region(unsigned long start, unsigned long end, int flag) { - if (flag) - start += Z2RAM_CHUNKMASK; - else - end += Z2RAM_CHUNKMASK; - start &= ~Z2RAM_CHUNKMASK; - end &= ~Z2RAM_CHUNKMASK; - - if (end <= Z2RAM_START || start >= Z2RAM_END) - return; - start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; - end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; - while (start < end) { - u32 chunk = start>>Z2RAM_CHUNKSHIFT; if (flag) - set_bit(chunk, zorro_unused_z2ram); + start += Z2RAM_CHUNKMASK; else - clear_bit(chunk, zorro_unused_z2ram); - start += Z2RAM_CHUNKSIZE; - } + end += Z2RAM_CHUNKMASK; + start &= ~Z2RAM_CHUNKMASK; + end &= ~Z2RAM_CHUNKMASK; + + if (end <= Z2RAM_START || start >= Z2RAM_END) + return; + start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; + end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; + while (start < end) { + u32 chunk = start>>Z2RAM_CHUNKSHIFT; + if (flag) + set_bit(chunk, zorro_unused_z2ram); + else + clear_bit(chunk, zorro_unused_z2ram); + start += Z2RAM_CHUNKSIZE; + } } -static struct resource __init *zorro_find_parent_resource(struct zorro_dev *z) +static struct resource __init *zorro_find_parent_resource( + struct platform_device *bridge, struct zorro_dev *z) { - int i; + int i; - for (i = 0; i < zorro_bus.num_resources; i++) - if (zorro_resource_start(z) >= zorro_bus.resources[i].start && - zorro_resource_end(z) <= zorro_bus.resources[i].end) - return &zorro_bus.resources[i]; - return &iomem_resource; + for (i = 0; i < bridge->num_resources; i++) { + struct resource *r = &bridge->resource[i]; + if (zorro_resource_start(z) >= r->start && + zorro_resource_end(z) <= r->end) + return r; + } + return &iomem_resource; } - /* - * Initialization - */ -static int __init zorro_init(void) +static int __init amiga_zorro_probe(struct platform_device *pdev) { - struct zorro_dev *z; - unsigned int i; - int error; - - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) - return 0; - - pr_info("Zorro: Probing AutoConfig expansion devices: %d device%s\n", - zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); - - /* Initialize the Zorro bus */ - INIT_LIST_HEAD(&zorro_bus.devices); - dev_set_name(&zorro_bus.dev, "zorro"); - error = device_register(&zorro_bus.dev); - if (error) { - pr_err("Zorro: Error registering zorro_bus\n"); - return error; - } - - /* Request the resources */ - zorro_bus.num_resources = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2; - for (i = 0; i < zorro_bus.num_resources; i++) - request_resource(&iomem_resource, &zorro_bus.resources[i]); - - /* Register all devices */ - for (i = 0; i < zorro_num_autocon; i++) { - z = &zorro_autocon[i]; - z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); - if (z->id == ZORRO_PROD_GVP_EPC_BASE) { - /* GVP quirk */ - unsigned long magic = zorro_resource_start(z)+0x8000; - z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; - } - sprintf(z->name, "Zorro device %08x", z->id); - zorro_name_device(z); - z->resource.name = z->name; - if (request_resource(zorro_find_parent_resource(z), &z->resource)) - pr_err("Zorro: Address space collision on device %s %pR\n", - z->name, &z->resource); - dev_set_name(&z->dev, "%02x", i); - z->dev.parent = &zorro_bus.dev; - z->dev.bus = &zorro_bus_type; - error = device_register(&z->dev); + struct zorro_bus *bus; + struct zorro_dev *z; + struct resource *r; + unsigned int i; + int error; + + /* Initialize the Zorro bus */ + bus = kzalloc(sizeof(*bus), GFP_KERNEL); + if (!bus) + return -ENOMEM; + + INIT_LIST_HEAD(&bus->devices); + bus->dev.parent = &pdev->dev; + dev_set_name(&bus->dev, "zorro"); + error = device_register(&bus->dev); if (error) { - pr_err("Zorro: Error registering device %s\n", z->name); - continue; + pr_err("Zorro: Error registering zorro_bus\n"); + kfree(bus); + return error; } - error = zorro_create_sysfs_dev_files(z); - if (error) - dev_err(&z->dev, "Error creating sysfs files\n"); - } - - /* Mark all available Zorro II memory */ - zorro_for_each_dev(z) { - if (z->rom.er_Type & ERTF_MEMLIST) - mark_region(zorro_resource_start(z), zorro_resource_end(z)+1, 1); - } - - /* Unmark all used Zorro II memory */ - for (i = 0; i < m68k_num_memory; i++) - if (m68k_memory[i].addr < 16*1024*1024) - mark_region(m68k_memory[i].addr, - m68k_memory[i].addr+m68k_memory[i].size, 0); - - return 0; + platform_set_drvdata(pdev, bus); + + /* Register all devices */ + pr_info("Zorro: Probing AutoConfig expansion devices: %u device%s\n", + zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); + + for (i = 0; i < zorro_num_autocon; i++) { + z = &zorro_autocon[i]; + z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); + if (z->id == ZORRO_PROD_GVP_EPC_BASE) { + /* GVP quirk */ + unsigned long magic = zorro_resource_start(z)+0x8000; + z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; + } + sprintf(z->name, "Zorro device %08x", z->id); + zorro_name_device(z); + z->resource.name = z->name; + r = zorro_find_parent_resource(pdev, z); + error = request_resource(r, &z->resource); + if (error) + dev_err(&bus->dev, + "Address space collision on device %s %pR\n", + z->name, &z->resource); + dev_set_name(&z->dev, "%02x", i); + z->dev.parent = &bus->dev; + z->dev.bus = &zorro_bus_type; + error = device_register(&z->dev); + if (error) { + dev_err(&bus->dev, "Error registering device %s\n", + z->name); + continue; + } + error = zorro_create_sysfs_dev_files(z); + if (error) + dev_err(&z->dev, "Error creating sysfs files\n"); + } + + /* Mark all available Zorro II memory */ + zorro_for_each_dev(z) { + if (z->rom.er_Type & ERTF_MEMLIST) + mark_region(zorro_resource_start(z), + zorro_resource_end(z)+1, 1); + } + + /* Unmark all used Zorro II memory */ + for (i = 0; i < m68k_num_memory; i++) + if (m68k_memory[i].addr < 16*1024*1024) + mark_region(m68k_memory[i].addr, + m68k_memory[i].addr+m68k_memory[i].size, + 0); + + return 0; } -subsys_initcall(zorro_init); +static struct platform_driver amiga_zorro_driver = { + .driver = { + .name = "amiga-zorro", + .owner = THIS_MODULE, + }, +}; -EXPORT_SYMBOL(zorro_find_device); -EXPORT_SYMBOL(zorro_unused_z2ram); +static int __init amiga_zorro_init(void) +{ + return platform_driver_probe(&amiga_zorro_driver, amiga_zorro_probe); +} + +module_init(amiga_zorro_init); MODULE_LICENSE("GPL"); diff --git a/include/linux/zorro.h b/include/linux/zorro.h index 908db1b..7bf9db5 100644 --- a/include/linux/zorro.h +++ b/include/linux/zorro.h @@ -141,15 +141,6 @@ struct zorro_dev { * Zorro bus */ -struct zorro_bus { - struct list_head devices; /* list of devices on this bus */ - unsigned int num_resources; /* number of resources */ - struct resource resources[4]; /* address space routed to this bus */ - struct device dev; - char name[10]; -}; - -extern struct zorro_bus zorro_bus; /* single Zorro bus */ extern struct bus_type zorro_bus_type; -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 04/16] m68k: amiga - Frame buffer platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 03/16] m68k: amiga - Zorro host bridge platform device conversion Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 05/16] m68k: amiga - Sound " Geert Uytterhoeven 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, linux-fbdev-devel Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: linux-fbdev-devel@lists.sourceforge.net --- arch/m68k/amiga/platform.c | 15 +++++++++++++ drivers/video/amifb.c | 49 +++++++++++++++++++++++++++---------------- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 33a7669..7fa929c 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -56,3 +56,18 @@ static int __init amiga_init_bus(void) subsys_initcall(amiga_init_bus); #endif /* CONFIG_ZORRO */ + + +static int __init amiga_init_devices(void) +{ + if (!MACH_IS_AMIGA) + return -ENODEV; + + /* video hardware */ + if (AMIGAHW_PRESENT(AMI_VIDEO)) + platform_device_register_simple("amiga-video", -1, NULL, 0); + + return 0; +} + +device_initcall(amiga_init_devices); diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 82bedd7..36a4018 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -51,8 +51,9 @@ #include <linux/fb.h> #include <linux/init.h> #include <linux/ioport.h> - +#include <linux/platform_device.h> #include <linux/uaccess.h> + #include <asm/system.h> #include <asm/irq.h> #include <asm/amigahw.h> @@ -1136,7 +1137,7 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg * Interface to the low level console driver */ -static void amifb_deinit(void); +static void amifb_deinit(struct platform_device *pdev); /* * Internal routines @@ -2247,7 +2248,7 @@ static inline void chipfree(void) * Initialisation */ -static int __init amifb_init(void) +static int __init amifb_probe(struct platform_device *pdev) { int tag, i, err = 0; u_long chipptr; @@ -2262,16 +2263,6 @@ static int __init amifb_init(void) } amifb_setup(option); #endif - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) - return -ENODEV; - - /* - * We request all registers starting from bplpt[0] - */ - if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120, - "amifb [Denise/Lisa]")) - return -EBUSY; - custom.dmacon = DMAF_ALL | DMAF_MASTER; switch (amiga_chipset) { @@ -2378,6 +2369,7 @@ default_chipset: fb_info.fbops = &amifb_ops; fb_info.par = ¤tpar; fb_info.flags = FBINFO_DEFAULT; + fb_info.device = &pdev->dev; if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { @@ -2452,18 +2444,18 @@ default_chipset: return 0; amifb_error: - amifb_deinit(); + amifb_deinit(pdev); return err; } -static void amifb_deinit(void) +static void amifb_deinit(struct platform_device *pdev) { if (fb_info.cmap.len) fb_dealloc_cmap(&fb_info.cmap); + fb_dealloc_cmap(&fb_info.cmap); chipfree(); if (videomemory) iounmap((void*)videomemory); - release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120); custom.dmacon = DMAF_ALL | DMAF_MASTER; } @@ -3795,14 +3787,35 @@ static void ami_rebuild_copper(void) } } -static void __exit amifb_exit(void) +static int __exit amifb_remove(struct platform_device *pdev) { unregister_framebuffer(&fb_info); - amifb_deinit(); + amifb_deinit(pdev); amifb_video_off(); + return 0; +} + +static struct platform_driver amifb_driver = { + .remove = __exit_p(amifb_remove), + .driver = { + .name = "amiga-video", + .owner = THIS_MODULE, + }, +}; + +static int __init amifb_init(void) +{ + return platform_driver_probe(&amifb_driver, amifb_probe); } module_init(amifb_init); + +static void __exit amifb_exit(void) +{ + platform_driver_unregister(&amifb_driver); +} + module_exit(amifb_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-video"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 05/16] m68k: amiga - Sound platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 04/16] m68k: amiga - Frame buffer " Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 06/16] m68k: amiga - Floppy " Geert Uytterhoeven 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> --- arch/m68k/amiga/platform.c | 5 +++ sound/oss/dmasound/dmasound_paula.c | 51 +++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 7fa929c..2e308e7 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -67,6 +67,11 @@ static int __init amiga_init_devices(void) if (AMIGAHW_PRESENT(AMI_VIDEO)) platform_device_register_simple("amiga-video", -1, NULL, 0); + + /* sound hardware */ + if (AMIGAHW_PRESENT(AMI_AUDIO)) + platform_device_register_simple("amiga-audio", -1, NULL, 0); + return 0; } diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c index 06e9e88..98acde8 100644 --- a/sound/oss/dmasound/dmasound_paula.c +++ b/sound/oss/dmasound/dmasound_paula.c @@ -21,6 +21,7 @@ #include <linux/ioport.h> #include <linux/soundcard.h> #include <linux/interrupt.h> +#include <linux/platform_device.h> #include <asm/uaccess.h> #include <asm/setup.h> @@ -710,31 +711,41 @@ static MACHINE machAmiga = { /*** Config & Setup **********************************************************/ -static int __init dmasound_paula_init(void) +static int __init amiga_audio_probe(struct platform_device *pdev) { - int err; - - if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_AUDIO)) { - if (!request_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40, - "dmasound [Paula]")) - return -EBUSY; - dmasound.mach = machAmiga; - dmasound.mach.default_hard = def_hard ; - dmasound.mach.default_soft = def_soft ; - err = dmasound_init(); - if (err) - release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40); - return err; - } else - return -ENODEV; + dmasound.mach = machAmiga; + dmasound.mach.default_hard = def_hard ; + dmasound.mach.default_soft = def_soft ; + return dmasound_init(); } -static void __exit dmasound_paula_cleanup(void) +static int __exit amiga_audio_remove(struct platform_device *pdev) { dmasound_deinit(); - release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40); + return 0; +} + +static struct platform_driver amiga_audio_driver = { + .remove = __exit_p(amiga_audio_remove), + .driver = { + .name = "amiga-audio", + .owner = THIS_MODULE, + }, +}; + +static int __init amiga_audio_init(void) +{ + return platform_driver_probe(&amiga_audio_driver, amiga_audio_probe); } -module_init(dmasound_paula_init); -module_exit(dmasound_paula_cleanup); +module_init(amiga_audio_init); + +static void __exit amiga_audio_exit(void) +{ + platform_driver_unregister(&amiga_audio_driver); +} + +module_exit(amiga_audio_exit); + MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-audio"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 06/16] m68k: amiga - Floppy platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 05/16] m68k: amiga - Sound " Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 07/16] m68k: amiga - A3000 SCSI " Geert Uytterhoeven 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> --- arch/m68k/amiga/platform.c | 5 ++++ drivers/block/amiflop.c | 47 +++++++++++++++++++------------------------ 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 2e308e7..38f18bf 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -72,6 +72,11 @@ static int __init amiga_init_devices(void) if (AMIGAHW_PRESENT(AMI_AUDIO)) platform_device_register_simple("amiga-audio", -1, NULL, 0); + + /* storage interfaces */ + if (AMIGAHW_PRESENT(AMI_FLOPPY)) + platform_device_register_simple("amiga-floppy", -1, NULL, 0); + return 0; } diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 8df436f..76bf7e2 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -65,6 +65,7 @@ #include <linux/blkdev.h> #include <linux/elevator.h> #include <linux/interrupt.h> +#include <linux/platform_device.h> #include <asm/setup.h> #include <asm/uaccess.h> @@ -1703,34 +1704,18 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) return get_disk(unit[drive].gendisk); } -static int __init amiga_floppy_init(void) +static int __init amiga_floppy_probe(struct platform_device *pdev) { int i, ret; - if (!MACH_IS_AMIGA) - return -ENODEV; - - if (!AMIGAHW_PRESENT(AMI_FLOPPY)) - return -ENODEV; - if (register_blkdev(FLOPPY_MAJOR,"fd")) return -EBUSY; - /* - * We request DSKPTR, DSKLEN and DSKDATA only, because the other - * floppy registers are too spreaded over the custom register space - */ - ret = -EBUSY; - if (!request_mem_region(CUSTOM_PHYSADDR+0x20, 8, "amiflop [Paula]")) { - printk("fd: cannot get floppy registers\n"); - goto out_blkdev; - } - ret = -ENOMEM; if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) == NULL) { printk("fd: cannot get chip mem buffer\n"); - goto out_memregion; + goto out_blkdev; } ret = -EBUSY; @@ -1799,18 +1784,13 @@ out_irq2: free_irq(IRQ_AMIGA_DSKBLK, NULL); out_irq: amiga_chip_free(raw_buf); -out_memregion: - release_mem_region(CUSTOM_PHYSADDR+0x20, 8); out_blkdev: unregister_blkdev(FLOPPY_MAJOR,"fd"); return ret; } -module_init(amiga_floppy_init); -#ifdef MODULE - #if 0 /* not safe to unload */ -void cleanup_module(void) +static int __exit amiga_floppy_remove(struct platform_device *pdev) { int i; @@ -1827,12 +1807,25 @@ void cleanup_module(void) custom.dmacon = DMAF_DISK; /* disable DMA */ amiga_chip_free(raw_buf); blk_cleanup_queue(floppy_queue); - release_mem_region(CUSTOM_PHYSADDR+0x20, 8); unregister_blkdev(FLOPPY_MAJOR, "fd"); } #endif -#else +static struct platform_driver amiga_floppy_driver = { + .driver = { + .name = "amiga-floppy", + .owner = THIS_MODULE, + }, +}; + +static int __init amiga_floppy_init(void) +{ + return platform_driver_probe(&amiga_floppy_driver, amiga_floppy_probe); +} + +module_init(amiga_floppy_init); + +#ifndef MODULE static int __init amiga_floppy_setup (char *str) { int n; @@ -1847,3 +1840,5 @@ static int __init amiga_floppy_setup (char *str) __setup("floppy=", amiga_floppy_setup); #endif + +MODULE_ALIAS("platform:amiga-floppy"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 07/16] m68k: amiga - A3000 SCSI platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 06/16] m68k: amiga - Floppy " Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 08/16] m68k: amiga - A4000T " Geert Uytterhoeven 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, linux-scsi Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: linux-scsi@vger.kernel.org --- arch/m68k/amiga/platform.c | 11 ++ drivers/scsi/a3000.c | 373 ++++++++++++++++++++++++------------------- 2 files changed, 219 insertions(+), 165 deletions(-) diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 38f18bf..df1fae3 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -58,6 +58,13 @@ subsys_initcall(amiga_init_bus); #endif /* CONFIG_ZORRO */ +static const struct resource a3000_scsi_resource __initconst = { + .start = 0xdd0000, + .end = 0xdd00ff, + .flags = IORESOURCE_MEM, +}; + + static int __init amiga_init_devices(void) { if (!MACH_IS_AMIGA) @@ -77,6 +84,10 @@ static int __init amiga_init_devices(void) if (AMIGAHW_PRESENT(AMI_FLOPPY)) platform_device_register_simple("amiga-floppy", -1, NULL, 0); + if (AMIGAHW_PRESENT(A3000_SCSI)) + platform_device_register_simple("amiga-a3000-scsi", -1, + &a3000_scsi_resource, 1); + return 0; } diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index 6970ce8..73bf9ff 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c @@ -1,202 +1,157 @@ #include <linux/types.h> #include <linux/mm.h> -#include <linux/blkdev.h> #include <linux/ioport.h> #include <linux/init.h> #include <linux/spinlock.h> #include <linux/interrupt.h> +#include <linux/platform_device.h> #include <asm/setup.h> #include <asm/page.h> #include <asm/pgtable.h> #include <asm/amigaints.h> #include <asm/amigahw.h> -#include <asm/irq.h> #include "scsi.h" -#include <scsi/scsi_host.h> #include "wd33c93.h" #include "a3000.h" -#include<linux/stat.h> -#define DMA(ptr) ((a3000_scsiregs *)((ptr)->base)) -#define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata)) - -static struct Scsi_Host *a3000_host = NULL; - -static int a3000_release(struct Scsi_Host *instance); - -static irqreturn_t a3000_intr (int irq, void *dummy) +static irqreturn_t a3000_intr(int irq, void *data) { + struct Scsi_Host *host = data; unsigned long flags; - unsigned int status = DMA(a3000_host)->ISTR; + a3000_scsiregs *regs = (a3000_scsiregs *)(host->base); + unsigned int status = regs->ISTR; if (!(status & ISTR_INT_P)) return IRQ_NONE; - if (status & ISTR_INTS) - { - spin_lock_irqsave(a3000_host->host_lock, flags); - wd33c93_intr (a3000_host); - spin_unlock_irqrestore(a3000_host->host_lock, flags); + if (status & ISTR_INTS) { + spin_lock_irqsave(host->host_lock, flags); + wd33c93_intr(host); + spin_unlock_irqrestore(host->host_lock, flags); return IRQ_HANDLED; } - printk("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status); + pr_warning("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status); return IRQ_NONE; } static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { - unsigned short cntr = CNTR_PDMD | CNTR_INTEN; - unsigned long addr = virt_to_bus(cmd->SCp.ptr); - - /* - * if the physical address has the wrong alignment, or if - * physical address is bad, or if it is a write and at the - * end of a physical memory chunk, then allocate a bounce - * buffer - */ - if (addr & A3000_XFER_MASK) - { - HDATA(a3000_host)->dma_bounce_len = (cmd->SCp.this_residual + 511) - & ~0x1ff; - HDATA(a3000_host)->dma_bounce_buffer = - kmalloc (HDATA(a3000_host)->dma_bounce_len, GFP_KERNEL); - - /* can't allocate memory; use PIO */ - if (!HDATA(a3000_host)->dma_bounce_buffer) { - HDATA(a3000_host)->dma_bounce_len = 0; - return 1; - } - - if (!dir_in) { - /* copy to bounce buffer for a write */ - memcpy (HDATA(a3000_host)->dma_bounce_buffer, - cmd->SCp.ptr, cmd->SCp.this_residual); + struct Scsi_Host *host = cmd->device->host; + struct WD33C93_hostdata *hdata = shost_priv(host); + a3000_scsiregs *regs = (a3000_scsiregs *)(host->base); + unsigned short cntr = CNTR_PDMD | CNTR_INTEN; + unsigned long addr = virt_to_bus(cmd->SCp.ptr); + + /* + * if the physical address has the wrong alignment, or if + * physical address is bad, or if it is a write and at the + * end of a physical memory chunk, then allocate a bounce + * buffer + */ + if (addr & A3000_XFER_MASK) { + hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; + hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len, + GFP_KERNEL); + + /* can't allocate memory; use PIO */ + if (!hdata->dma_bounce_buffer) { + hdata->dma_bounce_len = 0; + return 1; + } + + if (!dir_in) { + /* copy to bounce buffer for a write */ + memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr, + cmd->SCp.this_residual); + } + + addr = virt_to_bus(hdata->dma_bounce_buffer); } - addr = virt_to_bus(HDATA(a3000_host)->dma_bounce_buffer); - } + /* setup dma direction */ + if (!dir_in) + cntr |= CNTR_DDIR; - /* setup dma direction */ - if (!dir_in) - cntr |= CNTR_DDIR; + /* remember direction */ + hdata->dma_dir = dir_in; - /* remember direction */ - HDATA(a3000_host)->dma_dir = dir_in; + regs->CNTR = cntr; - DMA(a3000_host)->CNTR = cntr; + /* setup DMA *physical* address */ + regs->ACR = addr; - /* setup DMA *physical* address */ - DMA(a3000_host)->ACR = addr; + if (dir_in) + /* invalidate any cache */ + cache_clear(addr, cmd->SCp.this_residual); + else + /* push any dirty cache */ + cache_push(addr, cmd->SCp.this_residual); - if (dir_in) - /* invalidate any cache */ - cache_clear (addr, cmd->SCp.this_residual); - else - /* push any dirty cache */ - cache_push (addr, cmd->SCp.this_residual); + /* start DMA */ + mb(); /* make sure setup is completed */ + regs->ST_DMA = 1; + mb(); /* make sure DMA has started before next IO */ - /* start DMA */ - mb(); /* make sure setup is completed */ - DMA(a3000_host)->ST_DMA = 1; - mb(); /* make sure DMA has started before next IO */ - - /* return success */ - return 0; + /* return success */ + return 0; } static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { - /* disable SCSI interrupts */ - unsigned short cntr = CNTR_PDMD; - - if (!HDATA(instance)->dma_dir) - cntr |= CNTR_DDIR; - - DMA(instance)->CNTR = cntr; - mb(); /* make sure CNTR is updated before next IO */ - - /* flush if we were reading */ - if (HDATA(instance)->dma_dir) { - DMA(instance)->FLUSH = 1; - mb(); /* don't allow prefetch */ - while (!(DMA(instance)->ISTR & ISTR_FE_FLG)) - barrier(); - mb(); /* no IO until FLUSH is done */ - } - - /* clear a possible interrupt */ - /* I think that this CINT is only necessary if you are - * using the terminal count features. HM 7 Mar 1994 - */ - DMA(instance)->CINT = 1; - - /* stop DMA */ - DMA(instance)->SP_DMA = 1; - mb(); /* make sure DMA is stopped before next IO */ - - /* restore the CONTROL bits (minus the direction flag) */ - DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN; - mb(); /* make sure CNTR is updated before next IO */ - - /* copy from a bounce buffer, if necessary */ - if (status && HDATA(instance)->dma_bounce_buffer) { - if (SCpnt) { - if (HDATA(instance)->dma_dir && SCpnt) - memcpy (SCpnt->SCp.ptr, - HDATA(instance)->dma_bounce_buffer, - SCpnt->SCp.this_residual); - kfree (HDATA(instance)->dma_bounce_buffer); - HDATA(instance)->dma_bounce_buffer = NULL; - HDATA(instance)->dma_bounce_len = 0; - } else { - kfree (HDATA(instance)->dma_bounce_buffer); - HDATA(instance)->dma_bounce_buffer = NULL; - HDATA(instance)->dma_bounce_len = 0; - } - } -} + struct WD33C93_hostdata *hdata = shost_priv(instance); + a3000_scsiregs *regs = (a3000_scsiregs *)(instance->base); -static int __init a3000_detect(struct scsi_host_template *tpnt) -{ - wd33c93_regs regs; + /* disable SCSI interrupts */ + unsigned short cntr = CNTR_PDMD; - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI)) - return 0; - if (!request_mem_region(0xDD0000, 256, "wd33c93")) - return 0; + if (!hdata->dma_dir) + cntr |= CNTR_DDIR; - tpnt->proc_name = "A3000"; - tpnt->proc_info = &wd33c93_proc_info; - - a3000_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata)); - if (a3000_host == NULL) - goto fail_register; - - a3000_host->base = ZTWO_VADDR(0xDD0000); - a3000_host->irq = IRQ_AMIGA_PORTS; - DMA(a3000_host)->DAWR = DAWR_A3000; - regs.SASR = &(DMA(a3000_host)->SASR); - regs.SCMD = &(DMA(a3000_host)->SCMD); - HDATA(a3000_host)->no_sync = 0xff; - HDATA(a3000_host)->fast = 0; - HDATA(a3000_host)->dma_mode = CTRL_DMA; - wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15); - if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI", - a3000_intr)) - goto fail_irq; - DMA(a3000_host)->CNTR = CNTR_PDMD | CNTR_INTEN; - - return 1; + regs->CNTR = cntr; + mb(); /* make sure CNTR is updated before next IO */ -fail_irq: - wd33c93_release(); - scsi_unregister(a3000_host); -fail_register: - release_mem_region(0xDD0000, 256); - return 0; + /* flush if we were reading */ + if (hdata->dma_dir) { + regs->FLUSH = 1; + mb(); /* don't allow prefetch */ + while (!(regs->ISTR & ISTR_FE_FLG)) + barrier(); + mb(); /* no IO until FLUSH is done */ + } + + /* clear a possible interrupt */ + /* I think that this CINT is only necessary if you are + * using the terminal count features. HM 7 Mar 1994 + */ + regs->CINT = 1; + + /* stop DMA */ + regs->SP_DMA = 1; + mb(); /* make sure DMA is stopped before next IO */ + + /* restore the CONTROL bits (minus the direction flag) */ + regs->CNTR = CNTR_PDMD | CNTR_INTEN; + mb(); /* make sure CNTR is updated before next IO */ + + /* copy from a bounce buffer, if necessary */ + if (status && hdata->dma_bounce_buffer) { + if (SCpnt) { + if (hdata->dma_dir && SCpnt) + memcpy(SCpnt->SCp.ptr, + hdata->dma_bounce_buffer, + SCpnt->SCp.this_residual); + kfree(hdata->dma_bounce_buffer); + hdata->dma_bounce_buffer = NULL; + hdata->dma_bounce_len = 0; + } else { + kfree(hdata->dma_bounce_buffer); + hdata->dma_bounce_buffer = NULL; + hdata->dma_bounce_len = 0; + } + } } static int a3000_bus_reset(struct scsi_cmnd *cmd) @@ -213,13 +168,11 @@ static int a3000_bus_reset(struct scsi_cmnd *cmd) return SUCCESS; } -#define HOSTS_C - -static struct scsi_host_template driver_template = { - .proc_name = "A3000", +static struct scsi_host_template amiga_a3000_scsi_template = { + .module = THIS_MODULE, .name = "Amiga 3000 built-in SCSI", - .detect = a3000_detect, - .release = a3000_release, + .proc_info = wd33c93_proc_info, + .proc_name = "A3000", .queuecommand = wd33c93_queuecommand, .eh_abort_handler = wd33c93_abort, .eh_bus_reset_handler = a3000_bus_reset, @@ -231,16 +184,106 @@ static struct scsi_host_template driver_template = { .use_clustering = ENABLE_CLUSTERING }; +static int __init amiga_a3000_scsi_probe(struct platform_device *pdev) +{ + struct resource *res; + struct Scsi_Host *host; + struct WD33C93_hostdata *hdata; + int error; + wd33c93_regs wdregs; + a3000_scsiregs *regs; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + if (!request_mem_region(res->start, resource_size(res), "wd33c93")) + return -EBUSY; + + host = scsi_host_alloc(&amiga_a3000_scsi_template, + sizeof(struct WD33C93_hostdata)); + if (!host) { + error = -ENOMEM; + goto fail_register; + } + + host->base = ZTWO_VADDR(res->start); + host->irq = IRQ_AMIGA_PORTS; -#include "scsi_module.c" + regs = (a3000_scsiregs *)(host->base); + regs->DAWR = DAWR_A3000; -static int a3000_release(struct Scsi_Host *instance) + wdregs.SASR = ®s->SASR; + wdregs.SCMD = ®s->SCMD; + + hdata = shost_priv(host); + hdata->no_sync = 0xff; + hdata->fast = 0; + hdata->dma_mode = CTRL_DMA; + + wd33c93_init(host, wdregs, dma_setup, dma_stop, WD33C93_FS_12_15); + error = request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, + "A3000 SCSI", host); + if (error) + goto fail_irq; + + regs->CNTR = CNTR_PDMD | CNTR_INTEN; + + error = scsi_add_host(host, NULL); + if (error) + goto fail_host; + + platform_set_drvdata(pdev, host); + + scsi_scan_host(host); + return 0; + +fail_host: + free_irq(IRQ_AMIGA_PORTS, host); +fail_irq: + scsi_host_put(host); +fail_register: + release_mem_region(res->start, resource_size(res)); + return error; +} + +static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev) { - wd33c93_release(); - DMA(instance)->CNTR = 0; - release_mem_region(0xDD0000, 256); - free_irq(IRQ_AMIGA_PORTS, a3000_intr); - return 1; + struct Scsi_Host *host = platform_get_drvdata(pdev); + a3000_scsiregs *regs = (a3000_scsiregs *)(host->base); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + regs->CNTR = 0; + scsi_remove_host(host); + free_irq(IRQ_AMIGA_PORTS, host); + scsi_host_put(host); + release_mem_region(res->start, resource_size(res)); + return 0; +} + +static struct platform_driver amiga_a3000_scsi_driver = { + .remove = __exit_p(amiga_a3000_scsi_remove), + .driver = { + .name = "amiga-a3000-scsi", + .owner = THIS_MODULE, + }, +}; + +static int __init amiga_a3000_scsi_init(void) +{ + return platform_driver_probe(&amiga_a3000_scsi_driver, + amiga_a3000_scsi_probe); } +module_init(amiga_a3000_scsi_init); + +static void __exit amiga_a3000_scsi_exit(void) +{ + platform_driver_unregister(&amiga_a3000_scsi_driver); +} + +module_exit(amiga_a3000_scsi_exit); + +MODULE_DESCRIPTION("Amiga 3000 built-in SCSI"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-a3000-scsi"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 08/16] m68k: amiga - A4000T SCSI platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 07/16] m68k: amiga - A3000 SCSI " Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 09/16] m68k: amiga - Amiga Gayle IDE " Geert Uytterhoeven 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, linux-scsi Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: linux-scsi@vger.kernel.org --- arch/m68k/amiga/platform.c | 11 +++++ drivers/scsi/a4000t.c | 101 ++++++++++++++++++++------------------------ 2 files changed, 57 insertions(+), 55 deletions(-) diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index df1fae3..027e4ca 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -65,6 +65,13 @@ static const struct resource a3000_scsi_resource __initconst = { }; +static const struct resource a4000t_scsi_resource __initconst = { + .start = 0xdd0000, + .end = 0xdd0fff, + .flags = IORESOURCE_MEM, +}; + + static int __init amiga_init_devices(void) { if (!MACH_IS_AMIGA) @@ -88,6 +95,10 @@ static int __init amiga_init_devices(void) platform_device_register_simple("amiga-a3000-scsi", -1, &a3000_scsi_resource, 1); + if (AMIGAHW_PRESENT(A4000_SCSI)) + platform_device_register_simple("amiga-a4000t-scsi", -1, + &a4000t_scsi_resource, 1); + return 0; } diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index 61af3d9..7f7a464 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c @@ -19,10 +19,6 @@ #include "53c700.h" -MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>"); -MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver"); -MODULE_LICENSE("GPL"); - static struct scsi_host_template a4000t_scsi_driver_template = { .name = "A4000T builtin SCSI", @@ -31,30 +27,35 @@ static struct scsi_host_template a4000t_scsi_driver_template = { .module = THIS_MODULE, }; -static struct platform_device *a4000t_scsi_device; -#define A4000T_SCSI_ADDR 0xdd0040 +#define A4000T_SCSI_OFFSET 0x40 -static int __devinit a4000t_probe(struct platform_device *dev) +static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev) { - struct Scsi_Host *host; + struct resource *res; + phys_addr_t scsi_addr; struct NCR_700_Host_Parameters *hostdata; + struct Scsi_Host *host; - if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI))) - goto out; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; - if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000, + if (!request_mem_region(res->start, resource_size(res), "A4000T builtin SCSI")) - goto out; + return -EBUSY; - hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); + hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), + GFP_KERNEL); if (!hostdata) { - printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n"); + dev_err(&pdev->dev, "Failed to allocate host data\n"); goto out_release; } + scsi_addr = res->start + A4000T_SCSI_OFFSET; + /* Fill in the required pieces of hostdata */ - hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR); + hostdata->base = (void __iomem *)ZTWO_VADDR(scsi_addr); hostdata->clock = 50; hostdata->chip710 = 1; hostdata->dmode_extra = DMODE_FC2; @@ -62,26 +63,25 @@ static int __devinit a4000t_probe(struct platform_device *dev) /* and register the chip */ host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, - &dev->dev); + &pdev->dev); if (!host) { - printk(KERN_ERR "a4000t-scsi: No host detected; " - "board configuration problem?\n"); + dev_err(&pdev->dev, + "No host detected; board configuration problem?\n"); goto out_free; } host->this_id = 7; - host->base = A4000T_SCSI_ADDR; + host->base = scsi_addr; host->irq = IRQ_AMIGA_PORTS; if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi", host)) { - printk(KERN_ERR "a4000t-scsi: request_irq failed\n"); + dev_err(&pdev->dev, "request_irq failed\n"); goto out_put_host; } - platform_set_drvdata(dev, host); + platform_set_drvdata(pdev, host); scsi_scan_host(host); - return 0; out_put_host: @@ -89,58 +89,49 @@ static int __devinit a4000t_probe(struct platform_device *dev) out_free: kfree(hostdata); out_release: - release_mem_region(A4000T_SCSI_ADDR, 0x1000); - out: + release_mem_region(res->start, resource_size(res)); return -ENODEV; } -static __devexit int a4000t_device_remove(struct platform_device *dev) +static int __exit amiga_a4000t_scsi_remove(struct platform_device *pdev) { - struct Scsi_Host *host = platform_get_drvdata(dev); + struct Scsi_Host *host = platform_get_drvdata(pdev); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); scsi_remove_host(host); - NCR_700_release(host); kfree(hostdata); free_irq(host->irq, host); - release_mem_region(A4000T_SCSI_ADDR, 0x1000); - + release_mem_region(res->start, resource_size(res)); return 0; } -static struct platform_driver a4000t_scsi_driver = { - .driver = { - .name = "a4000t-scsi", - .owner = THIS_MODULE, +static struct platform_driver amiga_a4000t_scsi_driver = { + .remove = __exit_p(amiga_a4000t_scsi_remove), + .driver = { + .name = "amiga-a4000t-scsi", + .owner = THIS_MODULE, }, - .probe = a4000t_probe, - .remove = __devexit_p(a4000t_device_remove), }; -static int __init a4000t_scsi_init(void) +static int __init amiga_a4000t_scsi_init(void) { - int err; - - err = platform_driver_register(&a4000t_scsi_driver); - if (err) - return err; - - a4000t_scsi_device = platform_device_register_simple("a4000t-scsi", - -1, NULL, 0); - if (IS_ERR(a4000t_scsi_device)) { - platform_driver_register(&a4000t_scsi_driver); - return PTR_ERR(a4000t_scsi_device); - } - - return err; + return platform_driver_probe(&amiga_a4000t_scsi_driver, + amiga_a4000t_scsi_probe); } -static void __exit a4000t_scsi_exit(void) +module_init(amiga_a4000t_scsi_init); + +static void __exit amiga_a4000t_scsi_exit(void) { - platform_device_unregister(a4000t_scsi_device); - platform_driver_unregister(&a4000t_scsi_driver); + platform_driver_unregister(&amiga_a4000t_scsi_driver); } -module_init(a4000t_scsi_init); -module_exit(a4000t_scsi_exit); +module_exit(amiga_a4000t_scsi_exit); + +MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / " + "Kars de Jong <jongk@linux-m68k.org>"); +MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-a4000t-scsi"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 09/16] m68k: amiga - Amiga Gayle IDE platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 08/16] m68k: amiga - A4000T " Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 10/16] m68k: amiga - Keyboard " Geert Uytterhoeven 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, linux-ide Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: linux-ide@vger.kernel.org --- arch/m68k/amiga/platform.c | 63 +++++++++++++++- arch/m68k/include/asm/amigayle.h | 6 ++ drivers/ide/gayle.c | 156 +++++++++++++++++++++----------------- 3 files changed, 153 insertions(+), 72 deletions(-) diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 027e4ca..907f6f5 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -11,6 +11,7 @@ #include <linux/zorro.h> #include <asm/amigahw.h> +#include <asm/amigayle.h> #ifdef CONFIG_ZORRO @@ -55,7 +56,24 @@ static int __init amiga_init_bus(void) subsys_initcall(amiga_init_bus); -#endif /* CONFIG_ZORRO */ + +static int z_dev_present(zorro_id id) +{ + unsigned int i; + + for (i = 0; i < zorro_num_autocon; i++) + if (zorro_autocon[i].rom.er_Manufacturer == ZORRO_MANUF(id) && + zorro_autocon[i].rom.er_Product == ZORRO_PROD(id)) + return 1; + + return 0; +} + +#else /* !CONFIG_ZORRO */ + +static inline int z_dev_present(zorro_id id) { return 0; } + +#endif /* !CONFIG_ZORRO */ static const struct resource a3000_scsi_resource __initconst = { @@ -72,8 +90,36 @@ static const struct resource a4000t_scsi_resource __initconst = { }; +static const struct resource a1200_ide_resource __initconst = { + .start = 0xda0000, + .end = 0xda1fff, + .flags = IORESOURCE_MEM, +}; + +static const struct gayle_ide_platform_data a1200_ide_pdata __initconst = { + .base = 0xda0000, + .irqport = 0xda9000, + .explicit_ack = 1, +}; + + +static const struct resource a4000_ide_resource __initconst = { + .start = 0xdd2000, + .end = 0xdd3fff, + .flags = IORESOURCE_MEM, +}; + +static const struct gayle_ide_platform_data a4000_ide_pdata __initconst = { + .base = 0xdd2020, + .irqport = 0xdd3020, + .explicit_ack = 0, +}; + + static int __init amiga_init_devices(void) { + struct platform_device *pdev; + if (!MACH_IS_AMIGA) return -ENODEV; @@ -99,6 +145,21 @@ static int __init amiga_init_devices(void) platform_device_register_simple("amiga-a4000t-scsi", -1, &a4000t_scsi_resource, 1); + if (AMIGAHW_PRESENT(A1200_IDE) || + z_dev_present(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE)) { + pdev = platform_device_register_simple("amiga-gayle-ide", -1, + &a1200_ide_resource, 1); + platform_device_add_data(pdev, &a1200_ide_pdata, + sizeof(a1200_ide_pdata)); + } + + if (AMIGAHW_PRESENT(A4000_IDE)) { + pdev = platform_device_register_simple("amiga-gayle-ide", -1, + &a4000_ide_resource, 1); + platform_device_add_data(pdev, &a4000_ide_pdata, + sizeof(a4000_ide_pdata)); + } + return 0; } diff --git a/arch/m68k/include/asm/amigayle.h b/arch/m68k/include/asm/amigayle.h index bb5a6aa..a01453d 100644 --- a/arch/m68k/include/asm/amigayle.h +++ b/arch/m68k/include/asm/amigayle.h @@ -104,4 +104,10 @@ struct GAYLE { #define GAYLE_CFG_250NS 0x00 #define GAYLE_CFG_720NS 0x0c +struct gayle_ide_platform_data { + unsigned long base; + unsigned long irqport; + int explicit_ack; /* A1200 IDE needs explicit ack */ +}; + #endif /* asm-m68k/amigayle.h */ diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c index c711951..093e976 100644 --- a/drivers/ide/gayle.c +++ b/drivers/ide/gayle.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/zorro.h> #include <linux/module.h> +#include <linux/platform_device.h> #include <asm/setup.h> #include <asm/amigahw.h> @@ -24,15 +25,6 @@ /* - * Bases of the IDE interfaces - */ - -#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */ -#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */ - -#define GAYLE_IDEREG_SIZE 0x2000 - - /* * Offsets from one of the above bases */ @@ -66,26 +58,25 @@ MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); * Check and acknowledge the interrupt status */ -static int gayle_ack_intr_a4000(ide_hwif_t *hwif) +static inline int gayle_ack_intr(ide_hwif_t *hwif) { - unsigned char ch; + unsigned char ch; - ch = z_readb(hwif->io_ports.irq_addr); - if (!(ch & GAYLE_IRQ_IDE)) - return 0; - return 1; + ch = z_readb(hwif->io_ports.irq_addr); + if (!(ch & GAYLE_IRQ_IDE)) + return 0; + return 1; } -static int gayle_ack_intr_a1200(ide_hwif_t *hwif) +static int gayle_ack_intr_explicit(ide_hwif_t *hwif) { - unsigned char ch; + int ret = gayle_ack_intr(hwif); + if (!ret) + return 0; - ch = z_readb(hwif->io_ports.irq_addr); - if (!(ch & GAYLE_IRQ_IDE)) - return 0; - (void)z_readb(hwif->io_ports.status_addr); - z_writeb(0x7c, hwif->io_ports.irq_addr); - return 1; + (void)z_readb(hwif->io_ports.status_addr); + z_writeb(0x7c, hwif->io_ports.irq_addr); + return 1; } static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, @@ -120,64 +111,87 @@ static const struct ide_port_info gayle_port_info = { * Probe for a Gayle IDE interface (and optionally for an IDE doubler) */ -static int __init gayle_init(void) +static int __init amiga_gayle_ide_probe(struct platform_device *pdev) { - unsigned long phys_base, res_start, res_n; - unsigned long base, ctrlport, irqport; - ide_ack_intr_t *ack_intr; - int a4000, i, rc; - hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; - - if (!MACH_IS_AMIGA) - return -ENODEV; - - if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE)) - goto found; - -#ifdef CONFIG_ZORRO - if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE, - NULL)) - goto found; -#endif - return -ENODEV; - -found: - printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n", - a4000 ? 4000 : 1200, - ide_doubler ? ", IDE doubler" : ""); - - if (a4000) { - phys_base = GAYLE_BASE_4000; - irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000); - ack_intr = gayle_ack_intr_a4000; - } else { - phys_base = GAYLE_BASE_1200; - irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200); - ack_intr = gayle_ack_intr_a1200; + struct resource *res; + struct gayle_ide_platform_data *pdata; + unsigned long base, ctrlport, irqport; + ide_ack_intr_t *ack_intr; + unsigned int i; + int error; + hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; + struct ide_host *host; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + if (!request_mem_region(res->start, resource_size(res), "IDE")) + return -EBUSY; + + pdata = pdev->dev.platform_data; + pr_info("ide: Gayle IDE controller (A%u style%s)\n", + pdata->explicit_ack ? 1200 : 4000, + ide_doubler ? ", IDE doubler" : ""); + + base = (unsigned long)ZTWO_VADDR(pdata->base); + ctrlport = 0; + irqport = (unsigned long)ZTWO_VADDR(pdata->irqport); + ack_intr = pdata->explicit_ack ? gayle_ack_intr_explicit + : gayle_ack_intr; + + for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++, base += GAYLE_NEXT_PORT) { + if (GAYLE_HAS_CONTROL_REG) + ctrlport = base + GAYLE_CONTROL; + + gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr); + hws[i] = &hw[i]; } - res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1); - res_n = GAYLE_IDEREG_SIZE; + error = ide_host_add(&gayle_port_info, hws, &host); + if (error) + goto out; - if (!request_mem_region(res_start, res_n, "IDE")) - return -EBUSY; + platform_set_drvdata(pdev, host); + return 0; + +out: + release_mem_region(res->start, resource_size(res)); + return error; +} + +static int __exit amiga_gayle_ide_remove(struct platform_device *pdev) +{ + struct ide_host *host = pdev->dev.driver_data; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { - base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT); - ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0; + ide_host_remove(host); + release_mem_region(res->start, resource_size(res)); + return 0; +} - gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr); +static struct platform_driver amiga_gayle_ide_driver = { + .remove = __exit_p(amiga_gayle_ide_remove), + .driver = { + .name = "amiga-gayle-ide", + .owner = THIS_MODULE, + }, +}; - hws[i] = &hw[i]; - } +static int __init amiga_gayle_ide_init(void) +{ + return platform_driver_probe(&amiga_gayle_ide_driver, + amiga_gayle_ide_probe); +} - rc = ide_host_add(&gayle_port_info, hws, NULL); - if (rc) - release_mem_region(res_start, res_n); +module_init(amiga_gayle_ide_init); - return rc; +static void __exit amiga_gayle_ide_exit(void) +{ + platform_driver_unregister(&amiga_gayle_ide_driver); } -module_init(gayle_init); +module_exit(amiga_gayle_ide_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-gayle-ide"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 10/16] m68k: amiga - Keyboard platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 09/16] m68k: amiga - Amiga Gayle IDE " Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 11/16] m68k: amiga - Mouse " Geert Uytterhoeven 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, linux-input Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: linux-input@vger.kernel.org --- arch/m68k/amiga/platform.c | 5 ++ drivers/input/keyboard/amikbd.c | 97 +++++++++++++++++++++++---------------- 2 files changed, 63 insertions(+), 39 deletions(-) diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 907f6f5..d427de2 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -160,6 +160,11 @@ static int __init amiga_init_devices(void) sizeof(a4000_ide_pdata)); } + + /* other I/O hardware */ + if (AMIGAHW_PRESENT(AMI_KEYBOARD)) + platform_device_register_simple("amiga-keyboard", -1, NULL, 0); + return 0; } diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c index 35149ec..79172af 100644 --- a/drivers/input/keyboard/amikbd.c +++ b/drivers/input/keyboard/amikbd.c @@ -35,6 +35,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/keyboard.h> +#include <linux/platform_device.h> #include <asm/amigaints.h> #include <asm/amigahw.h> @@ -154,10 +155,9 @@ static const char *amikbd_messages[8] = { [7] = KERN_WARNING "amikbd: keyboard interrupt\n" }; -static struct input_dev *amikbd_dev; - -static irqreturn_t amikbd_interrupt(int irq, void *dummy) +static irqreturn_t amikbd_interrupt(int irq, void *data) { + struct input_dev *dev = data; unsigned char scancode, down; scancode = ~ciaa.sdr; /* get and invert scancode (keyboard is active low) */ @@ -170,47 +170,42 @@ static irqreturn_t amikbd_interrupt(int irq, void *dummy) if (scancode < 0x78) { /* scancodes < 0x78 are keys */ if (scancode == 98) { /* CapsLock is a toggle switch key on Amiga */ - input_report_key(amikbd_dev, scancode, 1); - input_report_key(amikbd_dev, scancode, 0); + input_report_key(dev, scancode, 1); + input_report_key(dev, scancode, 0); } else { - input_report_key(amikbd_dev, scancode, down); + input_report_key(dev, scancode, down); } - input_sync(amikbd_dev); + input_sync(dev); } else /* scancodes >= 0x78 are error codes */ printk(amikbd_messages[scancode - 0x78]); return IRQ_HANDLED; } -static int __init amikbd_init(void) +static int __init amikbd_probe(struct platform_device *pdev) { + struct input_dev *dev; int i, j, err; - if (!AMIGAHW_PRESENT(AMI_KEYBOARD)) - return -ENODEV; - - if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb")) - return -EBUSY; - - amikbd_dev = input_allocate_device(); - if (!amikbd_dev) { - printk(KERN_ERR "amikbd: not enough memory for input device\n"); - err = -ENOMEM; - goto fail1; + dev = input_allocate_device(); + if (!dev) { + dev_err(&pdev->dev, "Not enough memory for input device\n"); + return -ENOMEM; } - amikbd_dev->name = "Amiga Keyboard"; - amikbd_dev->phys = "amikbd/input0"; - amikbd_dev->id.bustype = BUS_AMIGA; - amikbd_dev->id.vendor = 0x0001; - amikbd_dev->id.product = 0x0001; - amikbd_dev->id.version = 0x0100; + dev->name = pdev->name; + dev->phys = "amikbd/input0"; + dev->id.bustype = BUS_AMIGA; + dev->id.vendor = 0x0001; + dev->id.product = 0x0001; + dev->id.version = 0x0100; + dev->dev.parent = &pdev->dev; - amikbd_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); for (i = 0; i < 0x78; i++) - set_bit(i, amikbd_dev->keybit); + set_bit(i, dev->keybit); for (i = 0; i < MAX_NR_KEYMAPS; i++) { static u_short temp_map[NR_KEYS] __initdata; @@ -229,30 +224,54 @@ static int __init amikbd_init(void) memcpy(key_maps[i], temp_map, sizeof(temp_map)); } ciaa.cra &= ~0x41; /* serial data in, turn off TA */ - if (request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", - amikbd_interrupt)) { - err = -EBUSY; + err = request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", + dev); + if (err) goto fail2; - } - err = input_register_device(amikbd_dev); + err = input_register_device(dev); if (err) goto fail3; + platform_set_drvdata(pdev, dev); + return 0; - fail3: free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt); - fail2: input_free_device(amikbd_dev); - fail1: release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100); + fail3: free_irq(IRQ_AMIGA_CIAA_SP, dev); + fail2: input_free_device(dev); return err; } -static void __exit amikbd_exit(void) +static int __exit amikbd_remove(struct platform_device *pdev) +{ + struct input_dev *dev = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + free_irq(IRQ_AMIGA_CIAA_SP, dev); + input_unregister_device(dev); + return 0; +} + +static struct platform_driver amikbd_driver = { + .remove = __exit_p(amikbd_remove), + .driver = { + .name = "amiga-keyboard", + .owner = THIS_MODULE, + }, +}; + +static int __init amikbd_init(void) { - free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt); - input_unregister_device(amikbd_dev); - release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100); + return platform_driver_probe(&amikbd_driver, amikbd_probe); } module_init(amikbd_init); + +static void __exit amikbd_exit(void) +{ + platform_driver_unregister(&amikbd_driver); +} + module_exit(amikbd_exit); + +MODULE_ALIAS("platform:amiga-keyboard"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 11/16] m68k: amiga - Mouse platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 10/16] m68k: amiga - Keyboard " Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 12/16] m68k: amiga - Serial port " Geert Uytterhoeven 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, linux-input Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: linux-input@vger.kernel.org --- arch/m68k/amiga/platform.c | 3 + drivers/input/mouse/amimouse.c | 98 +++++++++++++++++++++++++-------------- 2 files changed, 66 insertions(+), 35 deletions(-) diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index d427de2..269bafc 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -165,6 +165,9 @@ static int __init amiga_init_devices(void) if (AMIGAHW_PRESENT(AMI_KEYBOARD)) platform_device_register_simple("amiga-keyboard", -1, NULL, 0); + if (AMIGAHW_PRESENT(AMI_MOUSE)) + platform_device_register_simple("amiga-mouse", -1, NULL, 0); + return 0; } diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c index a185ac7..ff5f61a 100644 --- a/drivers/input/mouse/amimouse.c +++ b/drivers/input/mouse/amimouse.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/input.h> #include <linux/interrupt.h> +#include <linux/platform_device.h> #include <asm/irq.h> #include <asm/setup.h> @@ -34,10 +35,10 @@ MODULE_DESCRIPTION("Amiga mouse driver"); MODULE_LICENSE("GPL"); static int amimouse_lastx, amimouse_lasty; -static struct input_dev *amimouse_dev; -static irqreturn_t amimouse_interrupt(int irq, void *dummy) +static irqreturn_t amimouse_interrupt(int irq, void *data) { + struct input_dev *dev = data; unsigned short joy0dat, potgor; int nx, ny, dx, dy; @@ -59,14 +60,14 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy) potgor = amiga_custom.potgor; - input_report_rel(amimouse_dev, REL_X, dx); - input_report_rel(amimouse_dev, REL_Y, dy); + input_report_rel(dev, REL_X, dx); + input_report_rel(dev, REL_Y, dy); - input_report_key(amimouse_dev, BTN_LEFT, ciaa.pra & 0x40); - input_report_key(amimouse_dev, BTN_MIDDLE, potgor & 0x0100); - input_report_key(amimouse_dev, BTN_RIGHT, potgor & 0x0400); + input_report_key(dev, BTN_LEFT, ciaa.pra & 0x40); + input_report_key(dev, BTN_MIDDLE, potgor & 0x0100); + input_report_key(dev, BTN_RIGHT, potgor & 0x0400); - input_sync(amimouse_dev); + input_sync(dev); return IRQ_HANDLED; } @@ -74,63 +75,90 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy) static int amimouse_open(struct input_dev *dev) { unsigned short joy0dat; + int error; joy0dat = amiga_custom.joy0dat; amimouse_lastx = joy0dat & 0xff; amimouse_lasty = joy0dat >> 8; - if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) { - printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); - return -EBUSY; - } + error = request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", + dev); + if (error) + dev_err(&dev->dev, "Can't allocate irq %d\n", IRQ_AMIGA_VERTB); - return 0; + return error; } static void amimouse_close(struct input_dev *dev) { - free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt); + free_irq(IRQ_AMIGA_VERTB, dev); } -static int __init amimouse_init(void) +static int __init amimouse_probe(struct platform_device *pdev) { int err; + struct input_dev *dev; - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE)) - return -ENODEV; - - amimouse_dev = input_allocate_device(); - if (!amimouse_dev) + dev = input_allocate_device(); + if (!dev) return -ENOMEM; - amimouse_dev->name = "Amiga mouse"; - amimouse_dev->phys = "amimouse/input0"; - amimouse_dev->id.bustype = BUS_AMIGA; - amimouse_dev->id.vendor = 0x0001; - amimouse_dev->id.product = 0x0002; - amimouse_dev->id.version = 0x0100; + dev->name = pdev->name; + dev->phys = "amimouse/input0"; + dev->id.bustype = BUS_AMIGA; + dev->id.vendor = 0x0001; + dev->id.product = 0x0002; + dev->id.version = 0x0100; - amimouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - amimouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - amimouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | + dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); + dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); + dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); - amimouse_dev->open = amimouse_open; - amimouse_dev->close = amimouse_close; + dev->open = amimouse_open; + dev->close = amimouse_close; + dev->dev.parent = &pdev->dev; - err = input_register_device(amimouse_dev); + err = input_register_device(dev); if (err) { - input_free_device(amimouse_dev); + input_free_device(dev); return err; } + platform_set_drvdata(pdev, dev); + return 0; } -static void __exit amimouse_exit(void) +static int __exit amimouse_remove(struct platform_device *pdev) { - input_unregister_device(amimouse_dev); + struct input_dev *dev = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + input_unregister_device(dev); + return 0; +} + +static struct platform_driver amimouse_driver = { + .remove = __exit_p(amimouse_remove), + .driver = { + .name = "amiga-mouse", + .owner = THIS_MODULE, + }, +}; + +static int __init amimouse_init(void) +{ + return platform_driver_probe(&amimouse_driver, amimouse_probe); } module_init(amimouse_init); + +static void __exit amimouse_exit(void) +{ + platform_driver_unregister(&amimouse_driver); +} + module_exit(amimouse_exit); + +MODULE_ALIAS("platform:amiga-mouse"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 12/16] m68k: amiga - Serial port platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 11/16] m68k: amiga - Mouse " Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 13/16] m68k: amiga - Parallel " Geert Uytterhoeven 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> --- arch/m68k/amiga/platform.c | 3 ++ drivers/char/amiserial.c | 61 +++++++++++++++++++++++++------------------ 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 269bafc..52aa62d 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -168,6 +168,9 @@ static int __init amiga_init_devices(void) if (AMIGAHW_PRESENT(AMI_MOUSE)) platform_device_register_simple("amiga-mouse", -1, NULL, 0); + if (AMIGAHW_PRESENT(AMI_SERIAL)) + platform_device_register_simple("amiga-serial", -1, NULL, 0); + return 0; } diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index fd3ebd1..6826dd1 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -83,6 +83,7 @@ static char *serial_version = "4.30"; #include <linux/slab.h> #include <linux/init.h> #include <linux/bitops.h> +#include <linux/platform_device.h> #include <asm/setup.h> @@ -1953,29 +1954,16 @@ static const struct tty_operations serial_ops = { /* * The serial driver boot-time initialization code! */ -static int __init rs_init(void) +static int __init amiga_serial_probe(struct platform_device *pdev) { unsigned long flags; struct serial_state * state; int error; - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_SERIAL)) - return -ENODEV; - serial_driver = alloc_tty_driver(1); if (!serial_driver) return -ENOMEM; - /* - * We request SERDAT and SERPER only, because the serial registers are - * too spreaded over the custom register space - */ - if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4, - "amiserial [Paula]")) { - error = -EBUSY; - goto fail_put_tty_driver; - } - IRQ_ports = NULL; show_serial_version(); @@ -1997,7 +1985,7 @@ static int __init rs_init(void) error = tty_register_driver(serial_driver); if (error) - goto fail_release_mem_region; + goto fail_put_tty_driver; state = rs_table; state->magic = SSTATE_MAGIC; @@ -2049,23 +2037,24 @@ static int __init rs_init(void) ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */ + platform_set_drvdata(pdev, state); + return 0; fail_free_irq: free_irq(IRQ_AMIGA_TBE, state); fail_unregister: tty_unregister_driver(serial_driver); -fail_release_mem_region: - release_mem_region(CUSTOM_PHYSADDR+0x30, 4); fail_put_tty_driver: put_tty_driver(serial_driver); return error; } -static __exit void rs_exit(void) +static int __exit amiga_serial_remove(struct platform_device *pdev) { int error; - struct async_struct *info = rs_table[0].info; + struct serial_state *state = platform_get_drvdata(pdev); + struct async_struct *info = state->info; /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ tasklet_kill(&info->tlet); @@ -2074,19 +2063,38 @@ static __exit void rs_exit(void) error); put_tty_driver(serial_driver); - if (info) { - rs_table[0].info = NULL; - kfree(info); - } + rs_table[0].info = NULL; + kfree(info); free_irq(IRQ_AMIGA_TBE, rs_table); free_irq(IRQ_AMIGA_RBF, rs_table); - release_mem_region(CUSTOM_PHYSADDR+0x30, 4); + platform_set_drvdata(pdev, NULL); + + return error; +} + +static struct platform_driver amiga_serial_driver = { + .remove = __exit_p(amiga_serial_remove), + .driver = { + .name = "amiga-serial", + .owner = THIS_MODULE, + }, +}; + +static int __init amiga_serial_init(void) +{ + return platform_driver_probe(&amiga_serial_driver, amiga_serial_probe); +} + +module_init(amiga_serial_init); + +static void __exit amiga_serial_exit(void) +{ + platform_driver_unregister(&amiga_serial_driver); } -module_init(rs_init) -module_exit(rs_exit) +module_exit(amiga_serial_exit); #if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE) @@ -2153,3 +2161,4 @@ console_initcall(amiserial_console_init); #endif /* CONFIG_SERIAL_CONSOLE && !MODULE */ MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-serial"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 13/16] m68k: amiga - Parallel port platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 12/16] m68k: amiga - Serial port " Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 14/16] rtc: Add an RTC driver for the Oki MSM6242 Geert Uytterhoeven 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> --- arch/m68k/amiga/platform.c | 3 ++ drivers/parport/parport_amiga.c | 64 ++++++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 52aa62d..c985db0 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -171,6 +171,9 @@ static int __init amiga_init_devices(void) if (AMIGAHW_PRESENT(AMI_SERIAL)) platform_device_register_simple("amiga-serial", -1, NULL, 0); + if (AMIGAHW_PRESENT(AMI_PARALLEL)) + platform_device_register_simple("amiga-parallel", -1, NULL, 0); + return 0; } diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c index 1586e1c..8bef6d6 100644 --- a/drivers/parport/parport_amiga.c +++ b/drivers/parport/parport_amiga.c @@ -18,6 +18,8 @@ #include <linux/parport.h> #include <linux/ioport.h> #include <linux/interrupt.h> +#include <linux/platform_device.h> + #include <asm/setup.h> #include <asm/amigahw.h> #include <asm/irq.h> @@ -31,7 +33,6 @@ #define DPRINTK(x...) do { } while (0) #endif -static struct parport *this_port = NULL; static void amiga_write_data(struct parport *p, unsigned char data) { @@ -227,18 +228,11 @@ static struct parport_operations pp_amiga_ops = { /* ----------- Initialisation code --------------------------------- */ -static int __init parport_amiga_init(void) +static int __init amiga_parallel_probe(struct platform_device *pdev) { struct parport *p; int err; - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_PARALLEL)) - return -ENODEV; - - err = -EBUSY; - if (!request_mem_region(CIAA_PHYSADDR-1+0x100, 0x100, "parallel")) - goto out_mem; - ciaa.ddrb = 0xff; ciab.ddra &= 0xf8; mb(); @@ -246,41 +240,63 @@ static int __init parport_amiga_init(void) p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG, PARPORT_DMA_NONE, &pp_amiga_ops); if (!p) - goto out_port; + return -EBUSY; - err = request_irq(IRQ_AMIGA_CIAA_FLG, parport_irq_handler, 0, p->name, p); + err = request_irq(IRQ_AMIGA_CIAA_FLG, parport_irq_handler, 0, p->name, + p); if (err) goto out_irq; - this_port = p; printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); /* XXX: set operating mode */ parport_announce_port(p); + platform_set_drvdata(pdev, p); + return 0; out_irq: parport_put_port(p); -out_port: - release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); -out_mem: return err; } -static void __exit parport_amiga_exit(void) +static int __exit amiga_parallel_remove(struct platform_device *pdev) +{ + struct parport *port = platform_get_drvdata(pdev); + + parport_remove_port(port); + if (port->irq != PARPORT_IRQ_NONE) + free_irq(IRQ_AMIGA_CIAA_FLG, port); + parport_put_port(port); + platform_set_drvdata(pdev, NULL); + return 0; +} + +static struct platform_driver amiga_parallel_driver = { + .remove = __exit_p(amiga_parallel_remove), + .driver = { + .name = "amiga-parallel", + .owner = THIS_MODULE, + }, +}; + +static int __init amiga_parallel_init(void) +{ + return platform_driver_probe(&amiga_parallel_driver, + amiga_parallel_probe); +} + +module_init(amiga_parallel_init); + +static void __exit amiga_parallel_exit(void) { - parport_remove_port(this_port); - if (this_port->irq != PARPORT_IRQ_NONE) - free_irq(IRQ_AMIGA_CIAA_FLG, this_port); - parport_put_port(this_port); - release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); + platform_driver_unregister(&amiga_parallel_driver); } +module_exit(amiga_parallel_exit); MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>"); MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port"); MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port"); MODULE_LICENSE("GPL"); - -module_init(parport_amiga_init) -module_exit(parport_amiga_exit) +MODULE_ALIAS("platform:amiga-parallel"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 14/16] rtc: Add an RTC driver for the Oki MSM6242 2009-04-18 18:52 ` [PATCH/RFC 13/16] m68k: amiga - Parallel " Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 Geert Uytterhoeven 2009-04-18 21:57 ` [rtc-linux] [PATCH/RFC 14/16] rtc: Add an RTC driver for the Oki MSM6242 Alessandro Zummo 0 siblings, 2 replies; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, rtc-linux Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: rtc-linux@googlegroups.com --- drivers/rtc/Kconfig | 9 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-msm6242.c | 285 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 295 insertions(+), 0 deletions(-) create mode 100644 drivers/rtc/rtc-msm6242.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ffe34a1..a0f6297 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -526,6 +526,15 @@ config RTC_DRV_PCF50633 If you say yes here you get support for the RTC subsystem of the NXP PCF50633 used in embedded systems. +config RTC_DRV_MSM6242 + tristate "Oki MSM6242" + help + If you say yes here you get support for the Oki MSM6242 + timekeeping chip. It is used in some Amiga models (e.g. A2000). + + This driver can also be built as a module. If so, the module + will be called rtc-msm6242. + comment "on-CPU RTC drivers" config RTC_DRV_OMAP diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 6c0639a..c70418b 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -76,4 +76,5 @@ obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o +obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c new file mode 100644 index 0000000..c3af4f8 --- /dev/null +++ b/drivers/rtc/rtc-msm6242.c @@ -0,0 +1,285 @@ +/* + * Oki MSM6242 RTC Driver + * + * Copyright 2009 Geert Uytterhoeven + * + * Based on the A2000 TOD code in arch/m68k/amiga/config.c + * Copyright (C) 1993 Hamish Macdonald + */ + +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> + + +enum { + MSM6242_SECOND1 = 0x0, /* 1-second digit register */ + MSM6242_SECOND10 = 0x1, /* 10-second digit register */ + MSM6242_MINUTE1 = 0x2, /* 1-minute digit register */ + MSM6242_MINUTE10 = 0x3, /* 10-minute digit register */ + MSM6242_HOUR1 = 0x4, /* 1-hour digit register */ + MSM6242_HOUR10 = 0x5, /* PM/AM, 10-hour digit register */ + MSM6242_DAY1 = 0x6, /* 1-day digit register */ + MSM6242_DAY10 = 0x7, /* 10-day digit register */ + MSM6242_MONTH1 = 0x8, /* 1-month digit register */ + MSM6242_MONTH10 = 0x9, /* 10-month digit register */ + MSM6242_YEAR1 = 0xa, /* 1-year digit register */ + MSM6242_YEAR10 = 0xb, /* 10-year digit register */ + MSM6242_WEEK = 0xc, /* Week register */ + MSM6242_CD = 0xd, /* Control Register D */ + MSM6242_CE = 0xe, /* Control Register E */ + MSM6242_CF = 0xf, /* Control Register F */ +}; + +#define MSM6242_HOUR10_AM (0 << 2) +#define MSM6242_HOUR10_PM (1 << 2) +#define MSM6242_HOUR10_HR_MASK (3 << 0) + +#define MSM6242_WEEK_SUNDAY 0 +#define MSM6242_WEEK_MONDAY 1 +#define MSM6242_WEEK_TUESDAY 2 +#define MSM6242_WEEK_WEDNESDAY 3 +#define MSM6242_WEEK_THURSDAY 4 +#define MSM6242_WEEK_FRIDAY 5 +#define MSM6242_WEEK_SATURDAY 6 + +#define MSM6242_CD_30_S_ADJ (1 << 3) /* 30-second adjustment */ +#define MSM6242_CD_IRQ_FLAG (1 << 2) +#define MSM6242_CD_BUSY (1 << 1) +#define MSM6242_CD_HOLD (1 << 0) + +#define MSM6242_CE_T_MASK (3 << 2) +#define MSM6242_CE_T_64HZ (0 << 2) /* period 1/64 second */ +#define MSM6242_CE_T_1HZ (1 << 2) /* period 1 second */ +#define MSM6242_CE_T_1MINUTE (2 << 2) /* period 1 minute */ +#define MSM6242_CE_T_1HOUR (3 << 2) /* period 1 hour */ + +#define MSM6242_CE_ITRPT_STND (1 << 1) +#define MSM6242_CE_MASK (1 << 0) /* STD.P output control */ + +#define MSM6242_CF_TEST (1 << 3) +#define MSM6242_CF_12H (0 << 2) +#define MSM6242_CF_24H (1 << 2) +#define MSM6242_CF_STOP (1 << 1) +#define MSM6242_CF_REST (1 << 0) /* reset */ + + +struct msm6242_priv { + u32 __iomem *regs; + struct rtc_device *rtc; +}; + +static inline unsigned int msm6242_read(struct msm6242_priv *priv, + unsigned int reg) +{ + return __raw_readl(&priv->regs[reg]) & 0xf; +} + +static inline void msm6242_write(struct msm6242_priv *priv, unsigned int val, + unsigned int reg) +{ + return __raw_writel(val, &priv->regs[reg]); +} + +static inline void msm6242_set(struct msm6242_priv *priv, unsigned int val, + unsigned int reg) +{ + msm6242_write(priv, msm6242_read(priv, reg) | val, reg); +} + +static inline void msm6242_clear(struct msm6242_priv *priv, unsigned int val, + unsigned int reg) +{ + msm6242_write(priv, msm6242_read(priv, reg) & ~val, reg); +} + +static void msm6242_lock(struct msm6242_priv *priv) +{ + int cnt = 5; + + msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD); + + while ((msm6242_read(priv, MSM6242_CD) & MSM6242_CD_BUSY) && cnt--) { + msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD); + udelay(70); + msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD); + } + + if (!cnt) + pr_warning("msm6242: timed out waiting for RTC (0x%x)\n", + msm6242_read(priv, MSM6242_CD)); +} + +static void msm6242_unlock(struct msm6242_priv *priv) +{ + msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD); +} + +static int msm6242_read_time(struct device *dev, struct rtc_time *tm) +{ + struct msm6242_priv *priv = dev_get_drvdata(dev); + + msm6242_lock(priv); + + tm->tm_sec = msm6242_read(priv, MSM6242_SECOND10) * 10 + + msm6242_read(priv, MSM6242_SECOND1); + tm->tm_min = msm6242_read(priv, MSM6242_MINUTE10) * 10 + + msm6242_read(priv, MSM6242_MINUTE1); + tm->tm_hour = (msm6242_read(priv, MSM6242_HOUR10 & 3)) * 10 + + msm6242_read(priv, MSM6242_HOUR1); + tm->tm_mday = msm6242_read(priv, MSM6242_DAY10) * 10 + + msm6242_read(priv, MSM6242_DAY1); + tm->tm_wday = msm6242_read(priv, MSM6242_WEEK); + tm->tm_mon = msm6242_read(priv, MSM6242_MONTH10) * 10 + + msm6242_read(priv, MSM6242_MONTH1) - 1; + tm->tm_year = msm6242_read(priv, MSM6242_YEAR10) * 10 + + msm6242_read(priv, MSM6242_YEAR1); + if (tm->tm_year <= 69) + tm->tm_year += 100; + + if (!(msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H)) { + unsigned int pm = msm6242_read(priv, MSM6242_HOUR10) & + MSM6242_HOUR10_PM; + if (!pm && tm->tm_hour == 12) + tm->tm_hour = 0; + else if (pm && tm->tm_hour != 12) + tm->tm_hour += 12; + } + + msm6242_unlock(priv); + + return rtc_valid_tm(tm); +} + +static int msm6242_set_time(struct device *dev, struct rtc_time *tm) +{ + struct msm6242_priv *priv = dev_get_drvdata(dev); + + msm6242_lock(priv); + + msm6242_write(priv, tm->tm_sec / 10, MSM6242_SECOND10); + msm6242_write(priv, tm->tm_sec % 10, MSM6242_SECOND1); + msm6242_write(priv, tm->tm_min / 10, MSM6242_MINUTE10); + msm6242_write(priv, tm->tm_min % 10, MSM6242_MINUTE1); + if (msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H) + msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10); + else if (tm->tm_hour >= 12) + msm6242_write(priv, MSM6242_HOUR10_PM + (tm->tm_hour - 12) / 10, + MSM6242_HOUR10); + else + msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10); + msm6242_write(priv, tm->tm_hour % 10, MSM6242_HOUR1); + msm6242_write(priv, tm->tm_mday / 10, MSM6242_DAY10); + msm6242_write(priv, tm->tm_mday % 10, MSM6242_DAY1); + if (tm->tm_wday != -1) + msm6242_write(priv, tm->tm_wday, MSM6242_WEEK); + msm6242_write(priv, (tm->tm_mon + 1) / 10, MSM6242_MONTH10); + msm6242_write(priv, (tm->tm_mon + 1) % 10, MSM6242_MONTH1); + if (tm->tm_year >= 100) + tm->tm_year -= 100; + msm6242_write(priv, tm->tm_year / 10, MSM6242_YEAR10); + msm6242_write(priv, tm->tm_year % 10, MSM6242_YEAR1); + + msm6242_unlock(priv); + return 0; +} + +static int msm6242_set_mmss(struct device *dev, unsigned long secs) +{ + struct msm6242_priv *priv = dev_get_drvdata(dev); + unsigned int real_seconds = secs % 60, real_minutes = (secs / 60) % 60; + + msm6242_lock(priv); + + msm6242_write(priv, real_seconds / 10, MSM6242_SECOND10); + msm6242_write(priv, real_seconds % 10, MSM6242_SECOND1); + msm6242_write(priv, real_minutes / 10, MSM6242_MINUTE10); + msm6242_write(priv, real_minutes % 10, MSM6242_MINUTE1); + + msm6242_unlock(priv); + return 0; +} + +static const struct rtc_class_ops msm6242_rtc_ops = { + .read_time = msm6242_read_time, + .set_time = msm6242_set_time, + .set_mmss = msm6242_set_mmss, +}; + +static int __init msm6242_rtc_probe(struct platform_device *dev) +{ + struct resource *res; + struct msm6242_priv *priv; + struct rtc_device *rtc; + int error; + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->regs = ioremap(res->start, resource_size(res)); + if (!priv->regs) { + error = -ENOMEM; + goto out_free_priv; + } + + rtc = rtc_device_register("rtc-msm6242", &dev->dev, &msm6242_rtc_ops, + THIS_MODULE); + if (IS_ERR(rtc)) { + error = PTR_ERR(rtc); + goto out_unmap; + } + + priv->rtc = rtc; + platform_set_drvdata(dev, priv); + return 0; + +out_unmap: + iounmap(priv->regs); +out_free_priv: + kfree(priv); + return error; +} + +static int __exit msm6242_rtc_remove(struct platform_device *dev) +{ + struct msm6242_priv *priv = platform_get_drvdata(dev); + + rtc_device_unregister(priv->rtc); + iounmap(priv->regs); + kfree(priv); + return 0; +} + +static struct platform_driver msm6242_rtc_driver = { + .driver = { + .name = "rtc-msm6242", + .owner = THIS_MODULE, + }, + .remove = __exit_p(msm6242_rtc_remove), +}; + +static int __init msm6242_rtc_init(void) +{ + return platform_driver_probe(&msm6242_rtc_driver, msm6242_rtc_probe); +} + +static void __exit msm6242_rtc_fini(void) +{ + platform_driver_unregister(&msm6242_rtc_driver); +} + +module_init(msm6242_rtc_init); +module_exit(msm6242_rtc_fini); + +MODULE_AUTHOR("Geert Uytterhoeven"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Oki MSM6242 RTC driver"); +MODULE_ALIAS("platform:rtc-msm6242"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 2009-04-18 18:52 ` [PATCH/RFC 14/16] rtc: Add an RTC driver for the Oki MSM6242 Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 16/16] m68k: amiga - RTC platform device conversion Geert Uytterhoeven 2009-04-18 21:55 ` [rtc-linux] [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 Alessandro Zummo 2009-04-18 21:57 ` [rtc-linux] [PATCH/RFC 14/16] rtc: Add an RTC driver for the Oki MSM6242 Alessandro Zummo 1 sibling, 2 replies; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, rtc-linux Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: rtc-linux@googlegroups.com --- drivers/rtc/Kconfig | 10 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-rp5c01.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 250 insertions(+), 0 deletions(-) create mode 100644 drivers/rtc/rtc-rp5c01.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index a0f6297..150fe43 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -535,6 +535,16 @@ config RTC_DRV_MSM6242 This driver can also be built as a module. If so, the module will be called rtc-msm6242. +config RTC_DRV_RP5C01 + tristate "Ricoh RP5C01" + help + If you say yes here you get support for the Ricoh RP5C01 + timekeeping chip. It is used in some Amiga models (e.g. A3000 + and A4000). + + This driver can also be built as a module. If so, the module + will be called rtc-rp5c01. + comment "on-CPU RTC drivers" config RTC_DRV_OMAP diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index c70418b..6176a8a 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -77,4 +77,5 @@ obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o +obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c new file mode 100644 index 0000000..d997f33 --- /dev/null +++ b/drivers/rtc/rtc-rp5c01.c @@ -0,0 +1,239 @@ +/* + * Ricoh RP5C01 RTC Driver + * + * Copyright 2009 Geert Uytterhoeven + * + * Based on the A3000 TOD code in arch/m68k/amiga/config.c + * Copyright (C) 1993 Hamish Macdonald + */ + +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> + + +enum { + RP5C01_1_SECOND = 0x0, /* MODE 00 */ + RP5C01_10_SECOND = 0x1, /* MODE 00 */ + RP5C01_1_MINUTE = 0x2, /* MODE 00 and MODE 01 */ + RP5C01_10_MINUTE = 0x3, /* MODE 00 and MODE 01 */ + RP5C01_1_HOUR = 0x4, /* MODE 00 and MODE 01 */ + RP5C01_10_HOUR = 0x5, /* MODE 00 and MODE 01 */ + RP5C01_DAY_OF_WEEK = 0x6, /* MODE 00 and MODE 01 */ + RP5C01_1_DAY = 0x7, /* MODE 00 and MODE 01 */ + RP5C01_10_DAY = 0x8, /* MODE 00 and MODE 01 */ + RP5C01_1_MONTH = 0x9, /* MODE 00 */ + RP5C01_10_MONTH = 0xa, /* MODE 00 */ + RP5C01_1_YEAR = 0xb, /* MODE 00 */ + RP5C01_10_YEAR = 0xc, /* MODE 00 */ + + RP5C01_12_24_SELECT = 0xa, /* MODE 01 */ + RP5C01_LEAP_YEAR = 0xb, /* MODE 01 */ + + RP5C01_MODE = 0xd, /* all modes */ + RP5C01_TEST = 0xe, /* all modes */ + RP5C01_RESET = 0xf, /* all modes */ +}; + +#define RP5C01_12_24_SELECT_12 (0 << 0) +#define RP5C01_12_24_SELECT_24 (1 << 0) + +#define RP5C01_10_HOUR_AM (0 << 1) +#define RP5C01_10_HOUR_PM (1 << 1) + +#define RP5C01_MODE_TIMER_EN (1 << 3) /* timer enable */ +#define RP5C01_MODE_ALARM_EN (1 << 2) /* alarm enable */ + +#define RP5C01_MODE_MODE_MASK (3 << 0) +#define RP5C01_MODE_MODE00 (0 << 0) /* time */ +#define RP5C01_MODE_MODE01 (1 << 0) /* alarm, 12h/24h, leap year */ +#define RP5C01_MODE_RAM_BLOCK10 (2 << 0) /* RAM 4 bits x 13 */ +#define RP5C01_MODE_RAM_BLOCK11 (3 << 0) /* RAM 4 bits x 13 */ + +#define RP5C01_RESET_1HZ_PULSE (1 << 3) +#define RP5C01_RESET_16HZ_PULSE (1 << 2) +#define RP5C01_RESET_SECOND (1 << 1) /* reset divider stages for */ + /* seconds or smaller units */ +#define RP5C01_RESET_ALARM (1 << 0) /* reset all alarm registers */ + + +struct rp5c01_priv { + u32 __iomem *regs; + struct rtc_device *rtc; +}; + +static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, + unsigned int reg) +{ + return __raw_readl(&priv->regs[reg]) & 0xf; +} + +static inline void rp5c01_write(struct rp5c01_priv *priv, unsigned int val, + unsigned int reg) +{ + return __raw_writel(val, &priv->regs[reg]); +} + +static void rp5c01_lock(struct rp5c01_priv *priv) +{ + rp5c01_write(priv, RP5C01_MODE_MODE00, RP5C01_MODE); +} + +static void rp5c01_unlock(struct rp5c01_priv *priv) +{ + rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01, + RP5C01_MODE); +} + +static int rp5c01_read_time(struct device *dev, struct rtc_time *tm) +{ + struct rp5c01_priv *priv = dev_get_drvdata(dev); + + rp5c01_lock(priv); + + tm->tm_sec = rp5c01_read(priv, RP5C01_10_SECOND) * 10 + + rp5c01_read(priv, RP5C01_1_SECOND); + tm->tm_min = rp5c01_read(priv, RP5C01_10_MINUTE) * 10 + + rp5c01_read(priv, RP5C01_1_MINUTE); + tm->tm_hour = rp5c01_read(priv, RP5C01_10_HOUR) * 10 + + rp5c01_read(priv, RP5C01_1_HOUR); + tm->tm_mday = rp5c01_read(priv, RP5C01_10_DAY) * 10 + + rp5c01_read(priv, RP5C01_1_DAY); + tm->tm_wday = rp5c01_read(priv, RP5C01_DAY_OF_WEEK); + tm->tm_mon = rp5c01_read(priv, RP5C01_10_MONTH) * 10 + + rp5c01_read(priv, RP5C01_1_MONTH) - 1; + tm->tm_year = rp5c01_read(priv, RP5C01_10_YEAR) * 10 + + rp5c01_read(priv, RP5C01_1_YEAR); + if (tm->tm_year <= 69) + tm->tm_year += 100; + + rp5c01_unlock(priv); + + return rtc_valid_tm(tm); +} + +static int rp5c01_set_time(struct device *dev, struct rtc_time *tm) +{ + struct rp5c01_priv *priv = dev_get_drvdata(dev); + + rp5c01_lock(priv); + + rp5c01_write(priv, tm->tm_sec / 10, RP5C01_10_SECOND); + rp5c01_write(priv, tm->tm_sec % 10, RP5C01_1_SECOND); + rp5c01_write(priv, tm->tm_min / 10, RP5C01_10_MINUTE); + rp5c01_write(priv, tm->tm_min % 10, RP5C01_1_MINUTE); + rp5c01_write(priv, tm->tm_hour / 10, RP5C01_10_HOUR); + rp5c01_write(priv, tm->tm_hour % 10, RP5C01_1_HOUR); + rp5c01_write(priv, tm->tm_mday / 10, RP5C01_10_DAY); + rp5c01_write(priv, tm->tm_mday % 10, RP5C01_1_DAY); + if (tm->tm_wday != -1) + rp5c01_write(priv, tm->tm_wday, RP5C01_DAY_OF_WEEK); + rp5c01_write(priv, (tm->tm_mon + 1) / 10, RP5C01_10_MONTH); + rp5c01_write(priv, (tm->tm_mon + 1) % 10, RP5C01_1_MONTH); + if (tm->tm_year >= 100) + tm->tm_year -= 100; + rp5c01_write(priv, tm->tm_year / 10, RP5C01_10_YEAR); + rp5c01_write(priv, tm->tm_year % 10, RP5C01_1_YEAR); + + rp5c01_unlock(priv); + return 0; +} + +static int rp5c01_set_mmss(struct device *dev, unsigned long secs) +{ + struct rp5c01_priv *priv = dev_get_drvdata(dev); + unsigned int real_seconds = secs % 60, real_minutes = (secs / 60) % 60; + + rp5c01_lock(priv); + + rp5c01_write(priv, real_seconds / 10, RP5C01_10_SECOND); + rp5c01_write(priv, real_seconds % 10, RP5C01_1_SECOND); + rp5c01_write(priv, real_minutes / 10, RP5C01_10_MINUTE); + rp5c01_write(priv, real_minutes % 10, RP5C01_1_MINUTE); + + rp5c01_unlock(priv); + return 0; +} + +static const struct rtc_class_ops rp5c01_rtc_ops = { + .read_time = rp5c01_read_time, + .set_time = rp5c01_set_time, + .set_mmss = rp5c01_set_mmss, +}; + +static int __init rp5c01_rtc_probe(struct platform_device *dev) +{ + struct resource *res; + struct rp5c01_priv *priv; + struct rtc_device *rtc; + int error; + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->regs = ioremap(res->start, resource_size(res)); + if (!priv->regs) { + error = -ENOMEM; + goto out_free_priv; + } + + rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops, + THIS_MODULE); + if (IS_ERR(rtc)) { + error = PTR_ERR(rtc); + goto out_unmap; + } + + priv->rtc = rtc; + platform_set_drvdata(dev, priv); + return 0; + +out_unmap: + iounmap(priv->regs); +out_free_priv: + kfree(priv); + return error; +} + +static int __exit rp5c01_rtc_remove(struct platform_device *dev) +{ + struct rp5c01_priv *priv = platform_get_drvdata(dev); + + rtc_device_unregister(priv->rtc); + iounmap(priv->regs); + kfree(priv); + return 0; +} + +static struct platform_driver rp5c01_rtc_driver = { + .driver = { + .name = "rtc-rp5c01", + .owner = THIS_MODULE, + }, + .remove = __exit_p(rp5c01_rtc_remove), +}; + +static int __init rp5c01_rtc_init(void) +{ + return platform_driver_probe(&rp5c01_rtc_driver, rp5c01_rtc_probe); +} + +static void __exit rp5c01_rtc_fini(void) +{ + platform_driver_unregister(&rp5c01_rtc_driver); +} + +module_init(rp5c01_rtc_init); +module_exit(rp5c01_rtc_fini); + +MODULE_AUTHOR("Geert Uytterhoeven"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Ricoh RP5C01 RTC driver"); +MODULE_ALIAS("platform:rtc-rp5c01"); -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH/RFC 16/16] m68k: amiga - RTC platform device conversion 2009-04-18 18:52 ` [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 Geert Uytterhoeven @ 2009-04-18 18:52 ` Geert Uytterhoeven 2009-04-18 21:55 ` [rtc-linux] [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 Alessandro Zummo 1 sibling, 0 replies; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-18 18:52 UTC (permalink / raw) To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, rtc-linux The A2000 TOD is an Oki MSM6242B, while the A3000 TOD is a Ricoh RP5C01. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: rtc-linux@googlegroups.com --- arch/m68k/amiga/config.c | 172 -------------------------------------------- arch/m68k/amiga/platform.c | 17 +++++ 2 files changed, 17 insertions(+), 172 deletions(-) diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index 6e56275..d060894 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -97,10 +97,6 @@ static void amiga_get_model(char *model); static void amiga_get_hardware_list(struct seq_file *m); /* amiga specific timer functions */ static unsigned long amiga_gettimeoffset(void); -static int a3000_hwclk(int, struct rtc_time *); -static int a2000_hwclk(int, struct rtc_time *); -static int amiga_set_clock_mmss(unsigned long); -static unsigned int amiga_get_ss(void); extern void amiga_mksound(unsigned int count, unsigned int ticks); static void amiga_reset(void); extern void amiga_init_sound(void); @@ -138,10 +134,6 @@ static struct { } }; -static struct resource rtc_resource = { - .start = 0x00dc0000, .end = 0x00dcffff -}; - static struct resource ram_resource[NUM_MEMINFO]; @@ -387,15 +379,6 @@ void __init config_amiga(void) mach_get_model = amiga_get_model; mach_get_hardware_list = amiga_get_hardware_list; mach_gettimeoffset = amiga_gettimeoffset; - if (AMIGAHW_PRESENT(A3000_CLK)) { - mach_hwclk = a3000_hwclk; - rtc_resource.name = "A3000 RTC"; - request_resource(&iomem_resource, &rtc_resource); - } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ { - mach_hwclk = a2000_hwclk; - rtc_resource.name = "A2000 RTC"; - request_resource(&iomem_resource, &rtc_resource); - } /* * default MAX_DMA=0xffffffff on all machines. If we don't do so, the SCSI @@ -404,8 +387,6 @@ void __init config_amiga(void) */ mach_max_dma_address = 0xffffffff; - mach_set_clock_mmss = amiga_set_clock_mmss; - mach_get_ss = amiga_get_ss; mach_reset = amiga_reset; #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) mach_beep = amiga_mksound; @@ -530,159 +511,6 @@ static unsigned long amiga_gettimeoffset(void) return ticks + offset; } -static int a3000_hwclk(int op, struct rtc_time *t) -{ - tod_3000.cntrl1 = TOD3000_CNTRL1_HOLD; - - if (!op) { /* read */ - t->tm_sec = tod_3000.second1 * 10 + tod_3000.second2; - t->tm_min = tod_3000.minute1 * 10 + tod_3000.minute2; - t->tm_hour = tod_3000.hour1 * 10 + tod_3000.hour2; - t->tm_mday = tod_3000.day1 * 10 + tod_3000.day2; - t->tm_wday = tod_3000.weekday; - t->tm_mon = tod_3000.month1 * 10 + tod_3000.month2 - 1; - t->tm_year = tod_3000.year1 * 10 + tod_3000.year2; - if (t->tm_year <= 69) - t->tm_year += 100; - } else { - tod_3000.second1 = t->tm_sec / 10; - tod_3000.second2 = t->tm_sec % 10; - tod_3000.minute1 = t->tm_min / 10; - tod_3000.minute2 = t->tm_min % 10; - tod_3000.hour1 = t->tm_hour / 10; - tod_3000.hour2 = t->tm_hour % 10; - tod_3000.day1 = t->tm_mday / 10; - tod_3000.day2 = t->tm_mday % 10; - if (t->tm_wday != -1) - tod_3000.weekday = t->tm_wday; - tod_3000.month1 = (t->tm_mon + 1) / 10; - tod_3000.month2 = (t->tm_mon + 1) % 10; - if (t->tm_year >= 100) - t->tm_year -= 100; - tod_3000.year1 = t->tm_year / 10; - tod_3000.year2 = t->tm_year % 10; - } - - tod_3000.cntrl1 = TOD3000_CNTRL1_FREE; - - return 0; -} - -static int a2000_hwclk(int op, struct rtc_time *t) -{ - int cnt = 5; - - tod_2000.cntrl1 = TOD2000_CNTRL1_HOLD; - - while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) { - tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD; - udelay(70); - tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD; - } - - if (!cnt) - printk(KERN_INFO "hwclk: timed out waiting for RTC (0x%x)\n", - tod_2000.cntrl1); - - if (!op) { /* read */ - t->tm_sec = tod_2000.second1 * 10 + tod_2000.second2; - t->tm_min = tod_2000.minute1 * 10 + tod_2000.minute2; - t->tm_hour = (tod_2000.hour1 & 3) * 10 + tod_2000.hour2; - t->tm_mday = tod_2000.day1 * 10 + tod_2000.day2; - t->tm_wday = tod_2000.weekday; - t->tm_mon = tod_2000.month1 * 10 + tod_2000.month2 - 1; - t->tm_year = tod_2000.year1 * 10 + tod_2000.year2; - if (t->tm_year <= 69) - t->tm_year += 100; - - if (!(tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)) { - if (!(tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour == 12) - t->tm_hour = 0; - else if ((tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour != 12) - t->tm_hour += 12; - } - } else { - tod_2000.second1 = t->tm_sec / 10; - tod_2000.second2 = t->tm_sec % 10; - tod_2000.minute1 = t->tm_min / 10; - tod_2000.minute2 = t->tm_min % 10; - if (tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE) - tod_2000.hour1 = t->tm_hour / 10; - else if (t->tm_hour >= 12) - tod_2000.hour1 = TOD2000_HOUR1_PM + - (t->tm_hour - 12) / 10; - else - tod_2000.hour1 = t->tm_hour / 10; - tod_2000.hour2 = t->tm_hour % 10; - tod_2000.day1 = t->tm_mday / 10; - tod_2000.day2 = t->tm_mday % 10; - if (t->tm_wday != -1) - tod_2000.weekday = t->tm_wday; - tod_2000.month1 = (t->tm_mon + 1) / 10; - tod_2000.month2 = (t->tm_mon + 1) % 10; - if (t->tm_year >= 100) - t->tm_year -= 100; - tod_2000.year1 = t->tm_year / 10; - tod_2000.year2 = t->tm_year % 10; - } - - tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD; - - return 0; -} - -static int amiga_set_clock_mmss(unsigned long nowtime) -{ - short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; - - if (AMIGAHW_PRESENT(A3000_CLK)) { - tod_3000.cntrl1 = TOD3000_CNTRL1_HOLD; - - tod_3000.second1 = real_seconds / 10; - tod_3000.second2 = real_seconds % 10; - tod_3000.minute1 = real_minutes / 10; - tod_3000.minute2 = real_minutes % 10; - - tod_3000.cntrl1 = TOD3000_CNTRL1_FREE; - } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ { - int cnt = 5; - - tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD; - - while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) { - tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD; - udelay(70); - tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD; - } - - if (!cnt) - printk(KERN_INFO "set_clock_mmss: timed out waiting for RTC (0x%x)\n", tod_2000.cntrl1); - - tod_2000.second1 = real_seconds / 10; - tod_2000.second2 = real_seconds % 10; - tod_2000.minute1 = real_minutes / 10; - tod_2000.minute2 = real_minutes % 10; - - tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD; - } - - return 0; -} - -static unsigned int amiga_get_ss(void) -{ - unsigned int s; - - if (AMIGAHW_PRESENT(A3000_CLK)) { - tod_3000.cntrl1 = TOD3000_CNTRL1_HOLD; - s = tod_3000.second1 * 10 + tod_3000.second2; - tod_3000.cntrl1 = TOD3000_CNTRL1_FREE; - } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ { - s = tod_2000.second1 * 10 + tod_2000.second2; - } - return s; -} - static NORET_TYPE void amiga_reset(void) ATTRIB_NORET; diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index c985db0..7fd8b41 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -116,6 +116,13 @@ static const struct gayle_ide_platform_data a4000_ide_pdata __initconst = { }; +static const struct resource amiga_rtc_resource __initconst = { + .start = 0x00dc0000, + .end = 0x00dcffff, + .flags = IORESOURCE_MEM, +}; + + static int __init amiga_init_devices(void) { struct platform_device *pdev; @@ -174,6 +181,16 @@ static int __init amiga_init_devices(void) if (AMIGAHW_PRESENT(AMI_PARALLEL)) platform_device_register_simple("amiga-parallel", -1, NULL, 0); + + /* real time clocks */ + if (AMIGAHW_PRESENT(A2000_CLK)) + platform_device_register_simple("rtc-msm6242", -1, + &amiga_rtc_resource, 1); + + if (AMIGAHW_PRESENT(A3000_CLK)) + platform_device_register_simple("rtc-rp5c01", -1, + &amiga_rtc_resource, 1); + return 0; } -- 1.6.2.3 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [rtc-linux] [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 2009-04-18 18:52 ` [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 16/16] m68k: amiga - RTC platform device conversion Geert Uytterhoeven @ 2009-04-18 21:55 ` Alessandro Zummo 2009-04-19 18:41 ` Geert Uytterhoeven 1 sibling, 1 reply; 24+ messages in thread From: Alessandro Zummo @ 2009-04-18 21:55 UTC (permalink / raw) To: rtc-linux; +Cc: geert, linux-m68k, linux-kernel On Sat, 18 Apr 2009 20:52:23 +0200 Geert Uytterhoeven <geert@linux-m68k.org> wrote: Hi Geert, thanks for your contributions. Comments below. Missing patch description. > > Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> > Cc: rtc-linux@googlegroups.com > --- > drivers/rtc/Kconfig | 10 ++ > drivers/rtc/Makefile | 1 + > drivers/rtc/rtc-rp5c01.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 250 insertions(+), 0 deletions(-) > create mode 100644 drivers/rtc/rtc-rp5c01.c > > diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig > index a0f6297..150fe43 100644 > --- a/drivers/rtc/Kconfig > +++ b/drivers/rtc/Kconfig > @@ -535,6 +535,16 @@ config RTC_DRV_MSM6242 > This driver can also be built as a module. If so, the module > will be called rtc-msm6242. > > +config RTC_DRV_RP5C01 > + tristate "Ricoh RP5C01" > + help > + If you say yes here you get support for the Ricoh RP5C01 > + timekeeping chip. It is used in some Amiga models (e.g. A3000 > + and A4000). > + > + This driver can also be built as a module. If so, the module > + will be called rtc-rp5c01. > + > comment "on-CPU RTC drivers" > > config RTC_DRV_OMAP > diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile > index c70418b..6176a8a 100644 > --- a/drivers/rtc/Makefile > +++ b/drivers/rtc/Makefile > @@ -77,4 +77,5 @@ obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o > obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o > obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o > obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o > +obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o > obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o alphabetic order please > diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c > new file mode 100644 > index 0000000..d997f33 > --- /dev/null > +++ b/drivers/rtc/rtc-rp5c01.c > @@ -0,0 +1,239 @@ > +/* > + * Ricoh RP5C01 RTC Driver > + * > + * Copyright 2009 Geert Uytterhoeven > + * > + * Based on the A3000 TOD code in arch/m68k/amiga/config.c > + * Copyright (C) 1993 Hamish Macdonald > + */ > + > +#include <linux/io.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/rtc.h> > + > + > +enum { > + RP5C01_1_SECOND = 0x0, /* MODE 00 */ > + RP5C01_10_SECOND = 0x1, /* MODE 00 */ > + RP5C01_1_MINUTE = 0x2, /* MODE 00 and MODE 01 */ > + RP5C01_10_MINUTE = 0x3, /* MODE 00 and MODE 01 */ > + RP5C01_1_HOUR = 0x4, /* MODE 00 and MODE 01 */ > + RP5C01_10_HOUR = 0x5, /* MODE 00 and MODE 01 */ > + RP5C01_DAY_OF_WEEK = 0x6, /* MODE 00 and MODE 01 */ > + RP5C01_1_DAY = 0x7, /* MODE 00 and MODE 01 */ > + RP5C01_10_DAY = 0x8, /* MODE 00 and MODE 01 */ > + RP5C01_1_MONTH = 0x9, /* MODE 00 */ > + RP5C01_10_MONTH = 0xa, /* MODE 00 */ > + RP5C01_1_YEAR = 0xb, /* MODE 00 */ > + RP5C01_10_YEAR = 0xc, /* MODE 00 */ > + > + RP5C01_12_24_SELECT = 0xa, /* MODE 01 */ > + RP5C01_LEAP_YEAR = 0xb, /* MODE 01 */ > + > + RP5C01_MODE = 0xd, /* all modes */ > + RP5C01_TEST = 0xe, /* all modes */ > + RP5C01_RESET = 0xf, /* all modes */ > +}; > + > +#define RP5C01_12_24_SELECT_12 (0 << 0) > +#define RP5C01_12_24_SELECT_24 (1 << 0) > + > +#define RP5C01_10_HOUR_AM (0 << 1) > +#define RP5C01_10_HOUR_PM (1 << 1) > + > +#define RP5C01_MODE_TIMER_EN (1 << 3) /* timer enable */ > +#define RP5C01_MODE_ALARM_EN (1 << 2) /* alarm enable */ > + > +#define RP5C01_MODE_MODE_MASK (3 << 0) > +#define RP5C01_MODE_MODE00 (0 << 0) /* time */ > +#define RP5C01_MODE_MODE01 (1 << 0) /* alarm, 12h/24h, leap year */ > +#define RP5C01_MODE_RAM_BLOCK10 (2 << 0) /* RAM 4 bits x 13 */ > +#define RP5C01_MODE_RAM_BLOCK11 (3 << 0) /* RAM 4 bits x 13 */ > + > +#define RP5C01_RESET_1HZ_PULSE (1 << 3) > +#define RP5C01_RESET_16HZ_PULSE (1 << 2) > +#define RP5C01_RESET_SECOND (1 << 1) /* reset divider stages for */ > + /* seconds or smaller units */ > +#define RP5C01_RESET_ALARM (1 << 0) /* reset all alarm registers */ > + > + > +struct rp5c01_priv { > + u32 __iomem *regs; > + struct rtc_device *rtc; > +}; > + > +static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, > + unsigned int reg) > +{ > + return __raw_readl(&priv->regs[reg]) & 0xf; > +} > + > +static inline void rp5c01_write(struct rp5c01_priv *priv, unsigned int val, > + unsigned int reg) > +{ > + return __raw_writel(val, &priv->regs[reg]); > +} > + > +static void rp5c01_lock(struct rp5c01_priv *priv) > +{ > + rp5c01_write(priv, RP5C01_MODE_MODE00, RP5C01_MODE); > +} > + > +static void rp5c01_unlock(struct rp5c01_priv *priv) > +{ > + rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01, > + RP5C01_MODE); > +} > + > +static int rp5c01_read_time(struct device *dev, struct rtc_time *tm) > +{ > + struct rp5c01_priv *priv = dev_get_drvdata(dev); > + > + rp5c01_lock(priv); > + > + tm->tm_sec = rp5c01_read(priv, RP5C01_10_SECOND) * 10 + > + rp5c01_read(priv, RP5C01_1_SECOND); > + tm->tm_min = rp5c01_read(priv, RP5C01_10_MINUTE) * 10 + > + rp5c01_read(priv, RP5C01_1_MINUTE); > + tm->tm_hour = rp5c01_read(priv, RP5C01_10_HOUR) * 10 + > + rp5c01_read(priv, RP5C01_1_HOUR); > + tm->tm_mday = rp5c01_read(priv, RP5C01_10_DAY) * 10 + > + rp5c01_read(priv, RP5C01_1_DAY); > + tm->tm_wday = rp5c01_read(priv, RP5C01_DAY_OF_WEEK); > + tm->tm_mon = rp5c01_read(priv, RP5C01_10_MONTH) * 10 + > + rp5c01_read(priv, RP5C01_1_MONTH) - 1; > + tm->tm_year = rp5c01_read(priv, RP5C01_10_YEAR) * 10 + > + rp5c01_read(priv, RP5C01_1_YEAR); > + if (tm->tm_year <= 69) > + tm->tm_year += 100; > + > + rp5c01_unlock(priv); > + > + return rtc_valid_tm(tm); > +} > + > +static int rp5c01_set_time(struct device *dev, struct rtc_time *tm) > +{ > + struct rp5c01_priv *priv = dev_get_drvdata(dev); > + > + rp5c01_lock(priv); > + > + rp5c01_write(priv, tm->tm_sec / 10, RP5C01_10_SECOND); > + rp5c01_write(priv, tm->tm_sec % 10, RP5C01_1_SECOND); > + rp5c01_write(priv, tm->tm_min / 10, RP5C01_10_MINUTE); > + rp5c01_write(priv, tm->tm_min % 10, RP5C01_1_MINUTE); > + rp5c01_write(priv, tm->tm_hour / 10, RP5C01_10_HOUR); > + rp5c01_write(priv, tm->tm_hour % 10, RP5C01_1_HOUR); > + rp5c01_write(priv, tm->tm_mday / 10, RP5C01_10_DAY); > + rp5c01_write(priv, tm->tm_mday % 10, RP5C01_1_DAY); > + if (tm->tm_wday != -1) > + rp5c01_write(priv, tm->tm_wday, RP5C01_DAY_OF_WEEK); > + rp5c01_write(priv, (tm->tm_mon + 1) / 10, RP5C01_10_MONTH); > + rp5c01_write(priv, (tm->tm_mon + 1) % 10, RP5C01_1_MONTH); > + if (tm->tm_year >= 100) > + tm->tm_year -= 100; > + rp5c01_write(priv, tm->tm_year / 10, RP5C01_10_YEAR); > + rp5c01_write(priv, tm->tm_year % 10, RP5C01_1_YEAR); > + > + rp5c01_unlock(priv); > + return 0; > +} > + > +static int rp5c01_set_mmss(struct device *dev, unsigned long secs) > +{ > + struct rp5c01_priv *priv = dev_get_drvdata(dev); > + unsigned int real_seconds = secs % 60, real_minutes = (secs / 60) % 60; > + > + rp5c01_lock(priv); > + > + rp5c01_write(priv, real_seconds / 10, RP5C01_10_SECOND); > + rp5c01_write(priv, real_seconds % 10, RP5C01_1_SECOND); > + rp5c01_write(priv, real_minutes / 10, RP5C01_10_MINUTE); > + rp5c01_write(priv, real_minutes % 10, RP5C01_1_MINUTE); > + > + rp5c01_unlock(priv); > + return 0; > +} > + > +static const struct rtc_class_ops rp5c01_rtc_ops = { > + .read_time = rp5c01_read_time, > + .set_time = rp5c01_set_time, > + .set_mmss = rp5c01_set_mmss, > +}; please implement either set_time or set_mmss, not both. I don't know the chip but I suspect set_time is the one you need. > +static int __init rp5c01_rtc_probe(struct platform_device *dev) > +{ > + struct resource *res; > + struct rp5c01_priv *priv; > + struct rtc_device *rtc; > + int error; > + > + res = platform_get_resource(dev, IORESOURCE_MEM, 0); > + if (!res) > + return -ENODEV; > + > + priv = kzalloc(sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + priv->regs = ioremap(res->start, resource_size(res)); > + if (!priv->regs) { > + error = -ENOMEM; > + goto out_free_priv; > + } > + > + rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops, > + THIS_MODULE); > + if (IS_ERR(rtc)) { > + error = PTR_ERR(rtc); > + goto out_unmap; > + } > + > + priv->rtc = rtc; > + platform_set_drvdata(dev, priv); > + return 0; > + > +out_unmap: > + iounmap(priv->regs); > +out_free_priv: > + kfree(priv); > + return error; > +} > + > +static int __exit rp5c01_rtc_remove(struct platform_device *dev) > +{ > + struct rp5c01_priv *priv = platform_get_drvdata(dev); > + > + rtc_device_unregister(priv->rtc); > + iounmap(priv->regs); > + kfree(priv); > + return 0; > +} > + > +static struct platform_driver rp5c01_rtc_driver = { > + .driver = { > + .name = "rtc-rp5c01", > + .owner = THIS_MODULE, > + }, > + .remove = __exit_p(rp5c01_rtc_remove), > +}; > + > +static int __init rp5c01_rtc_init(void) > +{ > + return platform_driver_probe(&rp5c01_rtc_driver, rp5c01_rtc_probe); > +} > + > +static void __exit rp5c01_rtc_fini(void) > +{ > + platform_driver_unregister(&rp5c01_rtc_driver); > +} > + > +module_init(rp5c01_rtc_init); > +module_exit(rp5c01_rtc_fini); > + > +MODULE_AUTHOR("Geert Uytterhoeven"); it would be fine to have your email here. > +MODULE_LICENSE("GPL"); > +MODULE_DESCRIPTION("Ricoh RP5C01 RTC driver"); > +MODULE_ALIAS("platform:rtc-rp5c01"); > -- > 1.6.2.3 > > > --~--~---------~--~----~------------~-------~--~----~ > You received this message because you are subscribed to "rtc-linux". > Membership options at http://groups.google.com/group/rtc-linux . > Please read http://groups.google.com/group/rtc-linux/web/checklist > before submitting a driver. > -~----------~----~----~----~------~----~------~--~--- > -- Best regards, Alessandro Zummo, Tower Technologies - Torino, Italy http://www.towertech.it ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [rtc-linux] [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 2009-04-18 21:55 ` [rtc-linux] [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 Alessandro Zummo @ 2009-04-19 18:41 ` Geert Uytterhoeven 2009-04-19 18:56 ` [rtc-linux] " Alessandro Zummo 0 siblings, 1 reply; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-19 18:41 UTC (permalink / raw) To: Alessandro Zummo; +Cc: rtc-linux, linux-m68k, linux-kernel Hi Alessandro, On Sat, Apr 18, 2009 at 23:55, Alessandro Zummo <alessandro.zummo@towertech.it> wrote: > On Sat, 18 Apr 2009 20:52:23 +0200 Geert Uytterhoeven <geert@linux-m68k.org> wrote: > > Hi Geert, thanks for your contributions. Comments below. > > Missing patch description. git-am is happy with the one-line summary in the subject:-line, and there's not much more to say. >> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> >> Cc: rtc-linux@googlegroups.com >> --- >> drivers/rtc/Kconfig | 10 ++ >> drivers/rtc/Makefile | 1 + >> drivers/rtc/rtc-rp5c01.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 250 insertions(+), 0 deletions(-) >> create mode 100644 drivers/rtc/rtc-rp5c01.c >> >> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig >> index a0f6297..150fe43 100644 >> --- a/drivers/rtc/Kconfig >> +++ b/drivers/rtc/Kconfig >> @@ -535,6 +535,16 @@ config RTC_DRV_MSM6242 >> This driver can also be built as a module. If so, the module >> will be called rtc-msm6242. >> >> +config RTC_DRV_RP5C01 >> + tristate "Ricoh RP5C01" >> + help >> + If you say yes here you get support for the Ricoh RP5C01 >> + timekeeping chip. It is used in some Amiga models (e.g. A3000 >> + and A4000). >> + >> + This driver can also be built as a module. If so, the module >> + will be called rtc-rp5c01. >> + >> comment "on-CPU RTC drivers" >> >> config RTC_DRV_OMAP >> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile >> index c70418b..6176a8a 100644 >> --- a/drivers/rtc/Makefile >> +++ b/drivers/rtc/Makefile >> @@ -77,4 +77,5 @@ obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o >> obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o >> obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o >> obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o >> +obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o >> obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o > > alphabetic order please Will do. >> +static const struct rtc_class_ops rp5c01_rtc_ops = { >> + .read_time = rp5c01_read_time, >> + .set_time = rp5c01_set_time, >> + .set_mmss = rp5c01_set_mmss, >> +}; > > please implement either set_time or set_mmss, not both. > I don't know the chip but I suspect set_time is the one you need. OK, I will remove .set_mmss. Got to confused by looking into how everything is used... BTW, the only remaining users of rtc_set_mmss() seem to be arch/sparc/kernel/time_{32,64}.c? >> +MODULE_AUTHOR("Geert Uytterhoeven"); > > it would be fine to have your email here. Will do. OK, if I take the result (for both rtc-rp5c01 and rtc-msm6242) through the m68k tree? Thanks! Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds -- To unsubscribe from this list: send the line "unsubscribe linux-m68k" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [rtc-linux] Re: [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 2009-04-19 18:41 ` Geert Uytterhoeven @ 2009-04-19 18:56 ` Alessandro Zummo 0 siblings, 0 replies; 24+ messages in thread From: Alessandro Zummo @ 2009-04-19 18:56 UTC (permalink / raw) To: rtc-linux; +Cc: geert, linux-m68k, linux-kernel On Sun, 19 Apr 2009 20:41:21 +0200 Geert Uytterhoeven <geert@linux-m68k.org> wrote: > > please implement either set_time or set_mmss, not both. > > I don't know the chip but I suspect set_time is the one you need. > > OK, I will remove .set_mmss. Got to confused by looking into how > everything is used... > BTW, the only remaining users of rtc_set_mmss() seem to be > arch/sparc/kernel/time_{32,64}.c? Yes. The facility is there for drives, not users. For some chips it's easier to implement a set_mmss like interface so it's better to have the rtc framewrk to convert between the twos than to have repeated code in drivers. > OK, if I take the result (for both rtc-rp5c01 and rtc-msm6242) through > the m68k tree? that's ok, you can add my acked by. -- Best regards, Alessandro Zummo, Tower Technologies - Torino, Italy http://www.towertech.it -- To unsubscribe from this list: send the line "unsubscribe linux-m68k" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [rtc-linux] [PATCH/RFC 14/16] rtc: Add an RTC driver for the Oki MSM6242 2009-04-18 18:52 ` [PATCH/RFC 14/16] rtc: Add an RTC driver for the Oki MSM6242 Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 Geert Uytterhoeven @ 2009-04-18 21:57 ` Alessandro Zummo 1 sibling, 0 replies; 24+ messages in thread From: Alessandro Zummo @ 2009-04-18 21:57 UTC (permalink / raw) To: rtc-linux; +Cc: geert, linux-m68k, linux-kernel On Sat, 18 Apr 2009 20:52:22 +0200 Geert Uytterhoeven <geert@linux-m68k.org> wrote: Hi, my comments to the other patch of yours are applicable to this one too. > > Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> > Cc: rtc-linux@googlegroups.com > --- > drivers/rtc/Kconfig | 9 ++ > drivers/rtc/Makefile | 1 + > drivers/rtc/rtc-msm6242.c | 285 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 295 insertions(+), 0 deletions(-) > create mode 100644 drivers/rtc/rtc-msm6242.c > > diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig > index ffe34a1..a0f6297 100644 > --- a/drivers/rtc/Kconfig > +++ b/drivers/rtc/Kconfig > @@ -526,6 +526,15 @@ config RTC_DRV_PCF50633 > If you say yes here you get support for the RTC subsystem of the > NXP PCF50633 used in embedded systems. > > +config RTC_DRV_MSM6242 > + tristate "Oki MSM6242" > + help > + If you say yes here you get support for the Oki MSM6242 > + timekeeping chip. It is used in some Amiga models (e.g. A2000). > + > + This driver can also be built as a module. If so, the module > + will be called rtc-msm6242. > + > comment "on-CPU RTC drivers" > > config RTC_DRV_OMAP > diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile > index 6c0639a..c70418b 100644 > --- a/drivers/rtc/Makefile > +++ b/drivers/rtc/Makefile > @@ -76,4 +76,5 @@ obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o > obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o > obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o > obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o > +obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o > obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o > diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c > new file mode 100644 > index 0000000..c3af4f8 > --- /dev/null > +++ b/drivers/rtc/rtc-msm6242.c > @@ -0,0 +1,285 @@ > +/* > + * Oki MSM6242 RTC Driver > + * > + * Copyright 2009 Geert Uytterhoeven > + * > + * Based on the A2000 TOD code in arch/m68k/amiga/config.c > + * Copyright (C) 1993 Hamish Macdonald > + */ > + > +#include <linux/delay.h> > +#include <linux/io.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/rtc.h> > + > + > +enum { > + MSM6242_SECOND1 = 0x0, /* 1-second digit register */ > + MSM6242_SECOND10 = 0x1, /* 10-second digit register */ > + MSM6242_MINUTE1 = 0x2, /* 1-minute digit register */ > + MSM6242_MINUTE10 = 0x3, /* 10-minute digit register */ > + MSM6242_HOUR1 = 0x4, /* 1-hour digit register */ > + MSM6242_HOUR10 = 0x5, /* PM/AM, 10-hour digit register */ > + MSM6242_DAY1 = 0x6, /* 1-day digit register */ > + MSM6242_DAY10 = 0x7, /* 10-day digit register */ > + MSM6242_MONTH1 = 0x8, /* 1-month digit register */ > + MSM6242_MONTH10 = 0x9, /* 10-month digit register */ > + MSM6242_YEAR1 = 0xa, /* 1-year digit register */ > + MSM6242_YEAR10 = 0xb, /* 10-year digit register */ > + MSM6242_WEEK = 0xc, /* Week register */ > + MSM6242_CD = 0xd, /* Control Register D */ > + MSM6242_CE = 0xe, /* Control Register E */ > + MSM6242_CF = 0xf, /* Control Register F */ > +}; > + > +#define MSM6242_HOUR10_AM (0 << 2) > +#define MSM6242_HOUR10_PM (1 << 2) > +#define MSM6242_HOUR10_HR_MASK (3 << 0) > + > +#define MSM6242_WEEK_SUNDAY 0 > +#define MSM6242_WEEK_MONDAY 1 > +#define MSM6242_WEEK_TUESDAY 2 > +#define MSM6242_WEEK_WEDNESDAY 3 > +#define MSM6242_WEEK_THURSDAY 4 > +#define MSM6242_WEEK_FRIDAY 5 > +#define MSM6242_WEEK_SATURDAY 6 > + > +#define MSM6242_CD_30_S_ADJ (1 << 3) /* 30-second adjustment */ > +#define MSM6242_CD_IRQ_FLAG (1 << 2) > +#define MSM6242_CD_BUSY (1 << 1) > +#define MSM6242_CD_HOLD (1 << 0) > + > +#define MSM6242_CE_T_MASK (3 << 2) > +#define MSM6242_CE_T_64HZ (0 << 2) /* period 1/64 second */ > +#define MSM6242_CE_T_1HZ (1 << 2) /* period 1 second */ > +#define MSM6242_CE_T_1MINUTE (2 << 2) /* period 1 minute */ > +#define MSM6242_CE_T_1HOUR (3 << 2) /* period 1 hour */ > + > +#define MSM6242_CE_ITRPT_STND (1 << 1) > +#define MSM6242_CE_MASK (1 << 0) /* STD.P output control */ > + > +#define MSM6242_CF_TEST (1 << 3) > +#define MSM6242_CF_12H (0 << 2) > +#define MSM6242_CF_24H (1 << 2) > +#define MSM6242_CF_STOP (1 << 1) > +#define MSM6242_CF_REST (1 << 0) /* reset */ > + > + > +struct msm6242_priv { > + u32 __iomem *regs; > + struct rtc_device *rtc; > +}; > + > +static inline unsigned int msm6242_read(struct msm6242_priv *priv, > + unsigned int reg) > +{ > + return __raw_readl(&priv->regs[reg]) & 0xf; > +} > + > +static inline void msm6242_write(struct msm6242_priv *priv, unsigned int val, > + unsigned int reg) > +{ > + return __raw_writel(val, &priv->regs[reg]); > +} > + > +static inline void msm6242_set(struct msm6242_priv *priv, unsigned int val, > + unsigned int reg) > +{ > + msm6242_write(priv, msm6242_read(priv, reg) | val, reg); > +} > + > +static inline void msm6242_clear(struct msm6242_priv *priv, unsigned int val, > + unsigned int reg) > +{ > + msm6242_write(priv, msm6242_read(priv, reg) & ~val, reg); > +} > + > +static void msm6242_lock(struct msm6242_priv *priv) > +{ > + int cnt = 5; > + > + msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD); > + > + while ((msm6242_read(priv, MSM6242_CD) & MSM6242_CD_BUSY) && cnt--) { > + msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD); > + udelay(70); > + msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD); > + } > + > + if (!cnt) > + pr_warning("msm6242: timed out waiting for RTC (0x%x)\n", > + msm6242_read(priv, MSM6242_CD)); > +} > + > +static void msm6242_unlock(struct msm6242_priv *priv) > +{ > + msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD); > +} > + > +static int msm6242_read_time(struct device *dev, struct rtc_time *tm) > +{ > + struct msm6242_priv *priv = dev_get_drvdata(dev); > + > + msm6242_lock(priv); > + > + tm->tm_sec = msm6242_read(priv, MSM6242_SECOND10) * 10 + > + msm6242_read(priv, MSM6242_SECOND1); > + tm->tm_min = msm6242_read(priv, MSM6242_MINUTE10) * 10 + > + msm6242_read(priv, MSM6242_MINUTE1); > + tm->tm_hour = (msm6242_read(priv, MSM6242_HOUR10 & 3)) * 10 + > + msm6242_read(priv, MSM6242_HOUR1); > + tm->tm_mday = msm6242_read(priv, MSM6242_DAY10) * 10 + > + msm6242_read(priv, MSM6242_DAY1); > + tm->tm_wday = msm6242_read(priv, MSM6242_WEEK); > + tm->tm_mon = msm6242_read(priv, MSM6242_MONTH10) * 10 + > + msm6242_read(priv, MSM6242_MONTH1) - 1; > + tm->tm_year = msm6242_read(priv, MSM6242_YEAR10) * 10 + > + msm6242_read(priv, MSM6242_YEAR1); > + if (tm->tm_year <= 69) > + tm->tm_year += 100; > + > + if (!(msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H)) { > + unsigned int pm = msm6242_read(priv, MSM6242_HOUR10) & > + MSM6242_HOUR10_PM; > + if (!pm && tm->tm_hour == 12) > + tm->tm_hour = 0; > + else if (pm && tm->tm_hour != 12) > + tm->tm_hour += 12; > + } > + > + msm6242_unlock(priv); > + > + return rtc_valid_tm(tm); > +} > + > +static int msm6242_set_time(struct device *dev, struct rtc_time *tm) > +{ > + struct msm6242_priv *priv = dev_get_drvdata(dev); > + > + msm6242_lock(priv); > + > + msm6242_write(priv, tm->tm_sec / 10, MSM6242_SECOND10); > + msm6242_write(priv, tm->tm_sec % 10, MSM6242_SECOND1); > + msm6242_write(priv, tm->tm_min / 10, MSM6242_MINUTE10); > + msm6242_write(priv, tm->tm_min % 10, MSM6242_MINUTE1); > + if (msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H) > + msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10); > + else if (tm->tm_hour >= 12) > + msm6242_write(priv, MSM6242_HOUR10_PM + (tm->tm_hour - 12) / 10, > + MSM6242_HOUR10); > + else > + msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10); > + msm6242_write(priv, tm->tm_hour % 10, MSM6242_HOUR1); > + msm6242_write(priv, tm->tm_mday / 10, MSM6242_DAY10); > + msm6242_write(priv, tm->tm_mday % 10, MSM6242_DAY1); > + if (tm->tm_wday != -1) > + msm6242_write(priv, tm->tm_wday, MSM6242_WEEK); > + msm6242_write(priv, (tm->tm_mon + 1) / 10, MSM6242_MONTH10); > + msm6242_write(priv, (tm->tm_mon + 1) % 10, MSM6242_MONTH1); > + if (tm->tm_year >= 100) > + tm->tm_year -= 100; > + msm6242_write(priv, tm->tm_year / 10, MSM6242_YEAR10); > + msm6242_write(priv, tm->tm_year % 10, MSM6242_YEAR1); > + > + msm6242_unlock(priv); > + return 0; > +} > + > +static int msm6242_set_mmss(struct device *dev, unsigned long secs) > +{ > + struct msm6242_priv *priv = dev_get_drvdata(dev); > + unsigned int real_seconds = secs % 60, real_minutes = (secs / 60) % 60; > + > + msm6242_lock(priv); > + > + msm6242_write(priv, real_seconds / 10, MSM6242_SECOND10); > + msm6242_write(priv, real_seconds % 10, MSM6242_SECOND1); > + msm6242_write(priv, real_minutes / 10, MSM6242_MINUTE10); > + msm6242_write(priv, real_minutes % 10, MSM6242_MINUTE1); > + > + msm6242_unlock(priv); > + return 0; > +} > + > +static const struct rtc_class_ops msm6242_rtc_ops = { > + .read_time = msm6242_read_time, > + .set_time = msm6242_set_time, > + .set_mmss = msm6242_set_mmss, > +}; > + > +static int __init msm6242_rtc_probe(struct platform_device *dev) > +{ > + struct resource *res; > + struct msm6242_priv *priv; > + struct rtc_device *rtc; > + int error; > + > + res = platform_get_resource(dev, IORESOURCE_MEM, 0); > + if (!res) > + return -ENODEV; > + > + priv = kzalloc(sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + priv->regs = ioremap(res->start, resource_size(res)); > + if (!priv->regs) { > + error = -ENOMEM; > + goto out_free_priv; > + } > + > + rtc = rtc_device_register("rtc-msm6242", &dev->dev, &msm6242_rtc_ops, > + THIS_MODULE); > + if (IS_ERR(rtc)) { > + error = PTR_ERR(rtc); > + goto out_unmap; > + } > + > + priv->rtc = rtc; > + platform_set_drvdata(dev, priv); > + return 0; > + > +out_unmap: > + iounmap(priv->regs); > +out_free_priv: > + kfree(priv); > + return error; > +} > + > +static int __exit msm6242_rtc_remove(struct platform_device *dev) > +{ > + struct msm6242_priv *priv = platform_get_drvdata(dev); > + > + rtc_device_unregister(priv->rtc); > + iounmap(priv->regs); > + kfree(priv); > + return 0; > +} > + > +static struct platform_driver msm6242_rtc_driver = { > + .driver = { > + .name = "rtc-msm6242", > + .owner = THIS_MODULE, > + }, > + .remove = __exit_p(msm6242_rtc_remove), > +}; > + > +static int __init msm6242_rtc_init(void) > +{ > + return platform_driver_probe(&msm6242_rtc_driver, msm6242_rtc_probe); > +} > + > +static void __exit msm6242_rtc_fini(void) > +{ > + platform_driver_unregister(&msm6242_rtc_driver); > +} > + > +module_init(msm6242_rtc_init); > +module_exit(msm6242_rtc_fini); > + > +MODULE_AUTHOR("Geert Uytterhoeven"); > +MODULE_LICENSE("GPL"); > +MODULE_DESCRIPTION("Oki MSM6242 RTC driver"); > +MODULE_ALIAS("platform:rtc-msm6242"); > -- > 1.6.2.3 > > > --~--~---------~--~----~------------~-------~--~----~ > You received this message because you are subscribed to "rtc-linux". > Membership options at http://groups.google.com/group/rtc-linux . > Please read http://groups.google.com/group/rtc-linux/web/checklist > before submitting a driver. > -~----------~----~----~----~------~----~------~--~--- > -- Best regards, Alessandro Zummo, Tower Technologies - Torino, Italy http://www.towertech.it ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH/RFC 01/16] platform: Make platform resources input parameters const 2009-04-18 18:52 ` [PATCH/RFC 01/16] platform: Make platform resources input parameters const Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 02/16] m68k: amiga - Zorro bus modalias support Geert Uytterhoeven @ 2009-04-18 23:25 ` Greg KH 2009-04-19 18:23 ` Geert Uytterhoeven 1 sibling, 1 reply; 24+ messages in thread From: Greg KH @ 2009-04-18 23:25 UTC (permalink / raw) To: Geert Uytterhoeven; +Cc: linux-m68k, linux-kernel, Greg Kroah-Hartman On Sat, Apr 18, 2009 at 08:52:09PM +0200, Geert Uytterhoeven wrote: > Make the platform resources input parameters of platform_device_add_resources() > and platform_device_register_simple() const, as the resources are copied and > never modified. > > Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> > Cc: Greg Kroah-Hartman <gregkh@suse.de> If you need this for your other patches, no objection from me, feel free to take it through your tree (or I can take it through mine if you want.) Either way, feel free to add: Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> to it. thanks, greg k-h ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH/RFC 01/16] platform: Make platform resources input parameters const 2009-04-18 23:25 ` [PATCH/RFC 01/16] platform: Make platform resources input parameters const Greg KH @ 2009-04-19 18:23 ` Geert Uytterhoeven 0 siblings, 0 replies; 24+ messages in thread From: Geert Uytterhoeven @ 2009-04-19 18:23 UTC (permalink / raw) To: Greg KH; +Cc: linux-m68k, linux-kernel, Greg Kroah-Hartman On Sun, Apr 19, 2009 at 01:25, Greg KH <greg@kroah.com> wrote: > On Sat, Apr 18, 2009 at 08:52:09PM +0200, Geert Uytterhoeven wrote: >> Make the platform resources input parameters of platform_device_add_resources() >> and platform_device_register_simple() const, as the resources are copied and >> never modified. >> >> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> >> Cc: Greg Kroah-Hartman <gregkh@suse.de> > > If you need this for your other patches, no objection from me, feel free Yes, my other patches depend on it. > to take it through your tree (or I can take it through mine if you > want.) OK, will take it. Thanks! > Either way, feel free to add: > Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> > > to it. Acked-by, I assume... Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds -- To unsubscribe from this list: send the line "unsubscribe linux-m68k" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH/RFC 0/16] m68k: Device model patches 2009-04-18 18:52 [PATCH/RFC 0/16] m68k: Device model patches Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 01/16] platform: Make platform resources input parameters const Geert Uytterhoeven @ 2009-05-05 7:36 ` Geert Uytterhoeven 1 sibling, 0 replies; 24+ messages in thread From: Geert Uytterhoeven @ 2009-05-05 7:36 UTC (permalink / raw) To: linux-m68k, linux-kernel On Sat, Apr 18, 2009 at 20:52, Geert Uytterhoeven <geert@linux-m68k.org> wrote: > This set of patches brings Amiga hardware support better in line with to the > Linux device model: > - Add module alias support for Zorro drivers (not all drivers can > benefit from this yet though, as some still use zorro_find_device() > instead of struct zorro_driver), > - Convert the various builtin Amiga hardware to the platform driver > framework. > > [01] platform: Make platform resources input parameters const > [02] m68k: amiga - Zorro bus modalias support > [03] m68k: amiga - Zorro host bridge platform device conversion > [04] m68k: amiga - Frame buffer platform device conversion > [05] m68k: amiga - Sound platform device conversion > [06] m68k: amiga - Floppy platform device conversion > [07] m68k: amiga - A3000 SCSI platform device conversion > [08] m68k: amiga - A4000T SCSI platform device conversion > [09] m68k: amiga - Amiga Gayle IDE platform device conversion > [10] m68k: amiga - Keyboard platform device conversion > [11] m68k: amiga - Mouse platform device conversion > [12] m68k: amiga - Serial port platform device conversion > [13] m68k: amiga - Parallel port platform device conversion > [14] rtc: Add an RTC driver for the Oki MSM6242 > [15] rtc: Add an RTC driver for the Ricoh RP5C01 > [16] m68k: amiga - RTC platform device conversion > > Due to lack of hardware (only Amiga 4000 here), I couldn't test all drivers. > Especially the SCSI drivers could use some testing feedback. > The changes to most other drivers are fairly trivial. I'm a bit reluctant to apply the A3000 SCSI platform device conversion without having received any feedback, and I would like to apply the whole series ASAP. Did anyone try on A3000/A3000T? Similar changes are needed to convert the A2091 and GVP II SCSI drivers to the zorro_driver model, so if we have more users of those, I can do that conversion first, so it can receive some testing. Thx! Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds -- To unsubscribe from this list: send the line "unsubscribe linux-m68k" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2009-05-05 7:36 UTC | newest] Thread overview: 24+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-04-18 18:52 [PATCH/RFC 0/16] m68k: Device model patches Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 01/16] platform: Make platform resources input parameters const Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 02/16] m68k: amiga - Zorro bus modalias support Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 03/16] m68k: amiga - Zorro host bridge platform device conversion Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 04/16] m68k: amiga - Frame buffer " Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 05/16] m68k: amiga - Sound " Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 06/16] m68k: amiga - Floppy " Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 07/16] m68k: amiga - A3000 SCSI " Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 08/16] m68k: amiga - A4000T " Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 09/16] m68k: amiga - Amiga Gayle IDE " Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 10/16] m68k: amiga - Keyboard " Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 11/16] m68k: amiga - Mouse " Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 12/16] m68k: amiga - Serial port " Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 13/16] m68k: amiga - Parallel " Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 14/16] rtc: Add an RTC driver for the Oki MSM6242 Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 Geert Uytterhoeven 2009-04-18 18:52 ` [PATCH/RFC 16/16] m68k: amiga - RTC platform device conversion Geert Uytterhoeven 2009-04-18 21:55 ` [rtc-linux] [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01 Alessandro Zummo 2009-04-19 18:41 ` Geert Uytterhoeven 2009-04-19 18:56 ` [rtc-linux] " Alessandro Zummo 2009-04-18 21:57 ` [rtc-linux] [PATCH/RFC 14/16] rtc: Add an RTC driver for the Oki MSM6242 Alessandro Zummo 2009-04-18 23:25 ` [PATCH/RFC 01/16] platform: Make platform resources input parameters const Greg KH 2009-04-19 18:23 ` Geert Uytterhoeven 2009-05-05 7:36 ` [PATCH/RFC 0/16] m68k: Device model patches Geert Uytterhoeven
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox