2009-04-18 18:52:53

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 0/16] m68k: Device model patches

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 -- [email protected]

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


2009-04-18 18:53:19

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 02/16] m68k: amiga - Zorro bus modalias support

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
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

2009-04-18 18:53:35

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 06/16] m68k: amiga - Floppy platform device conversion

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
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

2009-04-18 18:53:48

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 04/16] m68k: amiga - Frame buffer platform device conversion

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: [email protected]
---
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 = &currentpar;
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

2009-04-18 18:54:48

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 03/16] m68k: amiga - Zorro host bridge platform device conversion

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
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

2009-04-18 18:54:07

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 11/16] m68k: amiga - Mouse platform device conversion

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: [email protected]
---
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

2009-04-18 18:54:31

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 08/16] m68k: amiga - A4000T SCSI platform device conversion

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: [email protected]
---
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 <[email protected]> / Kars de Jong <[email protected]>");
-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 <[email protected]> / "
+ "Kars de Jong <[email protected]>");
+MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:amiga-a4000t-scsi");
--
1.6.2.3

2009-04-18 18:55:07

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 07/16] m68k: amiga - A3000 SCSI platform device conversion

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: [email protected]
---
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 = &regs->SASR;
+ wdregs.SCMD = &regs->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

2009-04-18 18:55:35

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 12/16] m68k: amiga - Serial port platform device conversion

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
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

2009-04-18 18:55:51

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 10/16] m68k: amiga - Keyboard platform device conversion

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: [email protected]
---
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

2009-04-18 18:56:16

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 13/16] m68k: amiga - Parallel port platform device conversion

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
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 <[email protected]>");
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

2009-04-18 18:56:49

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 01/16] platform: Make platform resources input parameters const

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 <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
---
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

2009-04-18 18:56:34

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: [email protected]
---
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

2009-04-18 18:57:16

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 14/16] rtc: Add an RTC driver for the Oki MSM6242

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: [email protected]
---
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

2009-04-18 18:57:39

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 16/16] m68k: amiga - RTC platform device conversion

The A2000 TOD is an Oki MSM6242B, while the A3000 TOD is a Ricoh RP5C01.

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: [email protected]
---
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

2009-04-18 18:57:56

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 09/16] m68k: amiga - Amiga Gayle IDE platform device conversion

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: [email protected]
---
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

2009-04-18 18:58:22

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 05/16] m68k: amiga - Sound platform device conversion

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
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

2009-04-18 21:55:45

by Alessandro Zummo

[permalink] [raw]
Subject: Re: [rtc-linux] [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01

On Sat, 18 Apr 2009 20:52:23 +0200
Geert Uytterhoeven <[email protected]> wrote:

Hi Geert, thanks for your contributions. Comments below.

Missing patch description.

>
> Signed-off-by: Geert Uytterhoeven <[email protected]>
> Cc: [email protected]
> ---
> 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

2009-04-18 21:57:19

by Alessandro Zummo

[permalink] [raw]
Subject: Re: [rtc-linux] [PATCH/RFC 14/16] rtc: Add an RTC driver for the Oki MSM6242

On Sat, 18 Apr 2009 20:52:22 +0200
Geert Uytterhoeven <[email protected]> wrote:


Hi, my comments to the other patch of yours
are applicable to this one too.

>
> Signed-off-by: Geert Uytterhoeven <[email protected]>
> Cc: [email protected]
> ---
> 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

2009-04-18 23:28:50

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH/RFC 01/16] platform: Make platform resources input parameters const

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 <[email protected]>
> Cc: Greg Kroah-Hartman <[email protected]>

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 <[email protected]>

to it.

thanks,

greg k-h

2009-04-19 18:23:42

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH/RFC 01/16] platform: Make platform resources input parameters const

On Sun, Apr 19, 2009 at 01:25, Greg KH <[email protected]> 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 <[email protected]>
>> Cc: Greg Kroah-Hartman <[email protected]>
>
> 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 <[email protected]>
>
> to it.

Acked-by, I assume...

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

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

2009-04-19 18:41:36

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [rtc-linux] [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01

Hi Alessandro,

On Sat, Apr 18, 2009 at 23:55, Alessandro Zummo
<[email protected]> wrote:
> On Sat, 18 Apr 2009 20:52:23 +0200 Geert Uytterhoeven <[email protected]> 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 <[email protected]>
>> Cc: [email protected]
>> ---
>>  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 -- [email protected]

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

2009-04-19 18:57:14

by Alessandro Zummo

[permalink] [raw]
Subject: Re: [rtc-linux] Re: [PATCH/RFC 15/16] rtc: Add an RTC driver for the Ricoh RP5C01

On Sun, 19 Apr 2009 20:41:21 +0200
Geert Uytterhoeven <[email protected]> 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