diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-04-14 13:18:27 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-04-14 13:19:04 +0200 |
commit | 6ac1ef482d7ae0c690f1640bf6eb818ff9a2d91e (patch) | |
tree | 021cc9f6b477146fcebe6f3be4752abfa2ba18a9 /drivers/rtc | |
parent | 682968e0c425c60f0dde37977e5beb2b12ddc4cc (diff) | |
parent | a385ec4f11bdcf81af094c03e2444ee9b7fad2e5 (diff) |
Merge branch 'perf/core' into perf/uprobes
Merge in latest upstream (and the latest perf development tree),
to prepare for tooling changes, and also to pick up v3.4 MM
changes that the uprobes code needs to take care of.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/rtc')
59 files changed, 1036 insertions, 712 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 3a125b83554..8c8377d50c4 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -554,6 +554,13 @@ config RTC_DRV_DS1742 This driver can also be built as a module. If so, the module will be called rtc-ds1742. +config RTC_DRV_DA9052 + tristate "Dialog DA9052/DA9053 RTC" + depends on PMIC_DA9052 + help + Say y here to support the RTC driver for Dialog Semiconductor + DA9052-BC and DA9053-AA/Bx PMICs. + config RTC_DRV_EFI tristate "EFI RTC" depends on IA64 @@ -748,7 +755,7 @@ config HAVE_S3C_RTC config RTC_DRV_S3C tristate "Samsung S3C series SoC RTC" - depends on ARCH_S3C2410 || ARCH_S3C64XX || HAVE_S3C_RTC + depends on ARCH_S3C64XX || HAVE_S3C_RTC help RTC (Realtime Clock) driver for the clock inbuilt into the Samsung S3C24XX series of SoCs. This can provide periodic @@ -773,8 +780,8 @@ config RTC_DRV_EP93XX will be called rtc-ep93xx. config RTC_DRV_SA1100 - tristate "SA11x0/PXA2xx" - depends on ARCH_SA1100 || ARCH_PXA + tristate "SA11x0/PXA2xx/PXA910" + depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP help If you say Y here you will get access to the real time clock built into your SA11x0 or PXA2xx CPU. @@ -1070,4 +1077,14 @@ config RTC_DRV_PUV3 This drive can also be built as a module. If so, the module will be called rtc-puv3. +config RTC_DRV_LOONGSON1 + tristate "loongson1 RTC support" + depends on MACH_LOONGSON1 + help + This is a driver for the loongson1 on-chip Counter0 (Time-Of-Year + counter) to be used as a RTC. + + This driver can also be built as a module. If so, the module + will be called rtc-ls1x. + endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 6e6982335c1..727ae7786e6 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o +obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o @@ -53,6 +54,7 @@ obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o +obj-$(CONFIG_RTC_DRV_LOONGSON1) += rtc-ls1x.o obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o obj-$(CONFIG_RTC_DRV_M41T93) += rtc-m41t93.o obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 8a1c031391d..eb415bd7649 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -73,6 +73,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) err = -EINVAL; mutex_unlock(&rtc->ops_lock); + /* A timer might have just expired */ + schedule_work(&rtc->irqwork); return err; } EXPORT_SYMBOL_GPL(rtc_set_time); @@ -112,6 +114,8 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) err = -EINVAL; mutex_unlock(&rtc->ops_lock); + /* A timer might have just expired */ + schedule_work(&rtc->irqwork); return err; } @@ -380,18 +384,27 @@ EXPORT_SYMBOL_GPL(rtc_set_alarm); int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { int err; + struct rtc_time now; err = rtc_valid_tm(&alarm->time); if (err != 0) return err; + err = rtc_read_time(rtc, &now); + if (err) + return err; + err = mutex_lock_interruptible(&rtc->ops_lock); if (err) return err; rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); rtc->aie_timer.period = ktime_set(0, 0); - if (alarm->enabled) { + + /* Alarm has to be enabled & in the futrure for us to enqueue it */ + if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 < + rtc->aie_timer.node.expires.tv64)) { + rtc->aie_timer.enabled = 1; timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); } @@ -445,6 +458,11 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) if (rtc->uie_rtctimer.enabled == enabled) goto out; + if (rtc->uie_unsupported) { + err = -EINVAL; + goto out; + } + if (enabled) { struct rtc_time tm; ktime_t now, onesec; @@ -763,6 +781,14 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) return 0; } +static void rtc_alarm_disable(struct rtc_device *rtc) +{ + if (!rtc->ops || !rtc->ops->alarm_irq_enable) + return; + + rtc->ops->alarm_irq_enable(rtc->dev.parent, false); +} + /** * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue * @rtc rtc device @@ -784,8 +810,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) struct rtc_wkalrm alarm; int err; next = timerqueue_getnext(&rtc->timerqueue); - if (!next) + if (!next) { + rtc_alarm_disable(rtc); return; + } alarm.time = rtc_ktime_to_tm(next->expires); alarm.enabled = 1; err = __rtc_set_alarm(rtc, &alarm); @@ -847,7 +875,8 @@ again: err = __rtc_set_alarm(rtc, &alarm); if (err == -ETIME) goto again; - } + } else + rtc_alarm_disable(rtc); mutex_unlock(&rtc->ops_lock); } diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index f04761e6622..feddefc4210 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -72,9 +72,9 @@ static int pm860x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) struct pm860x_rtc_info *info = dev_get_drvdata(dev); if (enabled) - pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, ALARM); + pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, ALARM_EN); else - pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, 0); + pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, 0); return 0; } @@ -376,6 +376,9 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&info->calib_work, calibrate_vrtc_work); schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL); #endif /* VRTC_CALIBRATION */ + + device_init_wakeup(&pdev->dev, 1); + return 0; out_rtc: free_irq(info->irq, info); @@ -401,10 +404,34 @@ static int __devexit pm860x_rtc_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int pm860x_rtc_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); + + if (device_may_wakeup(dev)) + chip->wakeup_flag |= 1 << PM8607_IRQ_RTC; + return 0; +} +static int pm860x_rtc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); + + if (device_may_wakeup(dev)) + chip->wakeup_flag &= ~(1 << PM8607_IRQ_RTC); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(pm860x_rtc_pm_ops, pm860x_rtc_suspend, pm860x_rtc_resume); + static struct platform_driver pm860x_rtc_driver = { .driver = { .name = "88pm860x-rtc", .owner = THIS_MODULE, + .pm = &pm860x_rtc_pm_ops, }, .probe = pm860x_rtc_probe, .remove = __devexit_p(pm860x_rtc_remove), diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index ee3c122c059..831868904e0 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -57,6 +57,7 @@ struct sam9_rtc { void __iomem *rtt; struct rtc_device *rtcdev; u32 imr; + void __iomem *gpbr; }; #define rtt_readl(rtc, field) \ @@ -65,9 +66,9 @@ struct sam9_rtc { __raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field) #define gpbr_readl(rtc) \ - at91_sys_read(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR) + __raw_readl((rtc)->gpbr) #define gpbr_writel(rtc, val) \ - at91_sys_write(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR, (val)) + __raw_writel((val), (rtc)->gpbr) /* * Read current time and date in RTC @@ -287,16 +288,19 @@ static const struct rtc_class_ops at91_rtc_ops = { /* * Initialize and install RTC driver */ -static int __init at91_rtc_probe(struct platform_device *pdev) +static int __devinit at91_rtc_probe(struct platform_device *pdev) { - struct resource *r; + struct resource *r, *r_gpbr; struct sam9_rtc *rtc; int ret; u32 mr; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) + r_gpbr = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!r || !r_gpbr) { + dev_err(&pdev->dev, "need 2 ressources\n"); return -ENODEV; + } rtc = kzalloc(sizeof *rtc, GFP_KERNEL); if (!rtc) @@ -314,6 +318,13 @@ static int __init at91_rtc_probe(struct platform_device *pdev) goto fail; } + rtc->gpbr = ioremap(r_gpbr->start, resource_size(r_gpbr)); + if (!rtc->gpbr) { + dev_err(&pdev->dev, "failed to map gpbr registers, aborting.\n"); + ret = -ENOMEM; + goto fail_gpbr; + } + mr = rtt_readl(rtc, MR); /* unless RTT is counting at 1 Hz, re-initialize it */ @@ -335,12 +346,12 @@ static int __init at91_rtc_probe(struct platform_device *pdev) /* register irq handler after we know what name we'll use */ ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, - IRQF_DISABLED | IRQF_SHARED, + IRQF_SHARED, dev_name(&rtc->rtcdev->dev), rtc); if (ret) { dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS); rtc_device_unregister(rtc->rtcdev); - goto fail; + goto fail_register; } /* NOTE: sam9260 rev A silicon has a ROM bug which resets the @@ -356,6 +367,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev) return 0; fail_register: + iounmap(rtc->gpbr); +fail_gpbr: iounmap(rtc->rtt); fail: platform_set_drvdata(pdev, NULL); @@ -366,7 +379,7 @@ fail: /* * Disable and remove the RTC driver */ -static int __exit at91_rtc_remove(struct platform_device *pdev) +static int __devexit at91_rtc_remove(struct platform_device *pdev) { struct sam9_rtc *rtc = platform_get_drvdata(pdev); u32 mr = rtt_readl(rtc, MR); @@ -377,6 +390,7 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) rtc_device_unregister(rtc->rtcdev); + iounmap(rtc->gpbr); iounmap(rtc->rtt); platform_set_drvdata(pdev, NULL); kfree(rtc); @@ -440,63 +454,20 @@ static int at91_rtc_resume(struct platform_device *pdev) #endif static struct platform_driver at91_rtc_driver = { - .driver.name = "rtc-at91sam9", - .driver.owner = THIS_MODULE, - .remove = __exit_p(at91_rtc_remove), + .probe = at91_rtc_probe, + .remove = __devexit_p(at91_rtc_remove), .shutdown = at91_rtc_shutdown, .suspend = at91_rtc_suspend, .resume = at91_rtc_resume, + .driver = { + .name = "rtc-at91sam9", + .owner = THIS_MODULE, + }, }; -/* Chips can have more than one RTT module, and they can be used for more - * than just RTCs. So we can't just register as "the" RTT driver. - * - * A normal approach in such cases is to create a library to allocate and - * free the modules. Here we just use bus_find_device() as like such a - * library, binding directly ... no runtime "library" footprint is needed. - */ -static int __init at91_rtc_match(struct device *dev, void *v) -{ - struct platform_device *pdev = to_platform_device(dev); - int ret; - - /* continue searching if this isn't the RTT we need */ - if (strcmp("at91_rtt", pdev->name) != 0 - || pdev->id != CONFIG_RTC_DRV_AT91SAM9_RTT) - goto fail; - - /* else we found it ... but fail unless we can bind to the RTC driver */ - if (dev->driver) { - dev_dbg(dev, "busy, can't use as RTC!\n"); - goto fail; - } - dev->driver = &at91_rtc_driver.driver; - if (device_attach(dev) == 0) { - dev_dbg(dev, "can't attach RTC!\n"); - goto fail; - } - ret = at91_rtc_probe(pdev); - if (ret == 0) - return true; - - dev_dbg(dev, "RTC probe err %d!\n", ret); -fail: - return false; -} - static int __init at91_rtc_init(void) { - int status; - struct device *rtc; - - status = platform_driver_register(&at91_rtc_driver); - if (status) - return status; - rtc = bus_find_device(&platform_bus_type, NULL, - NULL, at91_rtc_match); - if (!rtc) - platform_driver_unregister(&at91_rtc_driver); - return rtc ? 0 : -ENODEV; + return platform_driver_register(&at91_rtc_driver); } module_init(at91_rtc_init); diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index 408cc8f735b..f090159dce4 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -187,17 +187,7 @@ static struct i2c_driver bq32k_driver = { .id_table = bq32k_id, }; -static __init int bq32k_init(void) -{ - return i2c_add_driver(&bq32k_driver); -} -module_init(bq32k_init); - -static __exit void bq32k_exit(void) -{ - i2c_del_driver(&bq32k_driver); -} -module_exit(bq32k_exit); +module_i2c_driver(bq32k_driver); MODULE_AUTHOR("Semihalf, Piotr Ziecik <kosmo@semihalf.com>"); MODULE_DESCRIPTION("TI BQ32000 I2C RTC driver"); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index d7782aa0994..7d5f56edb8e 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -714,7 +714,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) rtc_cmos_int_handler = cmos_interrupt; retval = request_irq(rtc_irq, rtc_cmos_int_handler, - IRQF_DISABLED, dev_name(&cmos_rtc.rtc->dev), + 0, dev_name(&cmos_rtc.rtc->dev), cmos_rtc.rtc); if (retval < 0) { dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index 80f9c88214c..a5b8a0c4ea8 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c @@ -199,7 +199,7 @@ static int __init coh901331_probe(struct platform_device *pdev) } rtap->irq = platform_get_irq(pdev, 0); - if (request_irq(rtap->irq, coh901331_interrupt, IRQF_DISABLED, + if (request_irq(rtap->irq, coh901331_interrupt, 0, "RTC COH 901 331 Alarm", rtap)) { ret = -EIO; goto out_no_irq; diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c new file mode 100644 index 00000000000..da6ab5291a4 --- /dev/null +++ b/drivers/rtc/rtc-da9052.c @@ -0,0 +1,293 @@ +/* + * Real time clock driver for DA9052 + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. + * + * Author: Dajun Dajun Chen <dajun.chen@diasemi.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> + +#include <linux/mfd/da9052/da9052.h> +#include <linux/mfd/da9052/reg.h> + +#define rtc_err(da9052, fmt, ...) \ + dev_err(da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__) + +struct da9052_rtc { + struct rtc_device *rtc; + struct da9052 *da9052; + int irq; +}; + +static int da9052_rtc_enable_alarm(struct da9052 *da9052, bool enable) +{ + int ret; + if (enable) { + ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG, + DA9052_ALARM_Y_ALARM_ON, + DA9052_ALARM_Y_ALARM_ON); + if (ret != 0) + rtc_err(da9052, "Failed to enable ALM: %d\n", ret); + } else { + ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG, + DA9052_ALARM_Y_ALARM_ON, 0); + if (ret != 0) + rtc_err(da9052, "Write error: %d\n", ret); + } + return ret; +} + +static irqreturn_t da9052_rtc_irq(int irq, void *data) +{ + struct da9052_rtc *rtc = data; + int ret; + + ret = da9052_reg_read(rtc->da9052, DA9052_ALARM_MI_REG); + if (ret < 0) { + rtc_err(rtc->da9052, "Read error: %d\n", ret); + return IRQ_NONE; + } + + if (ret & DA9052_ALARMMI_ALARMTYPE) { + da9052_rtc_enable_alarm(rtc->da9052, 0); + rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); + } else + rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_PF); + + return IRQ_HANDLED; +} + +static int da9052_read_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm) +{ + int ret; + uint8_t v[5]; + + ret = da9052_group_read(da9052, DA9052_ALARM_MI_REG, 5, v); + if (ret != 0) { + rtc_err(da9052, "Failed to group read ALM: %d\n", ret); + return ret; + } + + rtc_tm->tm_year = (v[4] & DA9052_RTC_YEAR) + 100; + rtc_tm->tm_mon = (v[3] & DA9052_RTC_MONTH) - 1; + rtc_tm->tm_mday = v[2] & DA9052_RTC_DAY; + rtc_tm->tm_hour = v[1] & DA9052_RTC_HOUR; + rtc_tm->tm_min = v[0] & DA9052_RTC_MIN; + + ret = rtc_valid_tm(rtc_tm); + if (ret != 0) + return ret; + return ret; +} + +static int da9052_set_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm) +{ + int ret; + uint8_t v[3]; + + rtc_tm->tm_year -= 100; + rtc_tm->tm_mon += 1; + + ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG, + DA9052_RTC_MIN, rtc_tm->tm_min); + if (ret != 0) { + rtc_err(da9052, "Failed to write ALRM MIN: %d\n", ret); + return ret; + } + + v[0] = rtc_tm->tm_hour; + v[1] = rtc_tm->tm_mday; + v[2] = rtc_tm->tm_mon; + + ret = da9052_group_write(da9052, DA9052_ALARM_H_REG, 3, v); + if (ret < 0) + return ret; + + ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG, + DA9052_RTC_YEAR, rtc_tm->tm_year); + if (ret != 0) + rtc_err(da9052, "Failed to write ALRM YEAR: %d\n", ret); + + return ret; +} + +static int da9052_rtc_get_alarm_status(struct da9052 *da9052) +{ + int ret; + + ret = da9052_reg_read(da9052, DA9052_ALARM_Y_REG); + if (ret < 0) { + rtc_err(da9052, "Failed to read ALM: %d\n", ret); + return ret; + } + ret &= DA9052_ALARM_Y_ALARM_ON; + return (ret > 0) ? 1 : 0; +} + +static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) +{ + struct da9052_rtc *rtc = dev_get_drvdata(dev); + uint8_t v[6]; + int ret; + + ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v); + if (ret < 0) { + rtc_err(rtc->da9052, "Failed to read RTC time : %d\n", ret); + return ret; + } + + rtc_tm->tm_year = (v[5] & DA9052_RTC_YEAR) + 100; + rtc_tm->tm_mon = (v[4] & DA9052_RTC_MONTH) - 1; + rtc_tm->tm_mday = v[3] & DA9052_RTC_DAY; + rtc_tm->tm_hour = v[2] & DA9052_RTC_HOUR; + rtc_tm->tm_min = v[1] & DA9052_RTC_MIN; + rtc_tm->tm_sec = v[0] & DA9052_RTC_SEC; + + ret = rtc_valid_tm(rtc_tm); + if (ret != 0) { + rtc_err(rtc->da9052, "rtc_valid_tm failed: %d\n", ret); + return ret; + } + + return 0; +} + +static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct da9052_rtc *rtc; + uint8_t v[6]; + + rtc = dev_get_drvdata(dev); + + v[0] = tm->tm_sec; + v[1] = tm->tm_min; + v[2] = tm->tm_hour; + v[3] = tm->tm_mday; + v[4] = tm->tm_mon + 1; + v[5] = tm->tm_year - 100; + + return da9052_group_write(rtc->da9052, DA9052_COUNT_S_REG, 6, v); +} + +static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + int ret; + struct rtc_time *tm = &alrm->time; + struct da9052_rtc *rtc = dev_get_drvdata(dev); + + ret = da9052_read_alarm(rtc->da9052, tm); + + if (ret) + return ret; + + alrm->enabled = da9052_rtc_get_alarm_status(rtc->da9052); + + return 0; +} + +static int da9052_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + int ret; + struct rtc_time *tm = &alrm->time; + struct da9052_rtc *rtc = dev_get_drvdata(dev); + + ret = da9052_rtc_enable_alarm(rtc->da9052, 0); + if (ret < 0) + return ret; + + ret = da9052_set_alarm(rtc->da9052, tm); + if (ret) + return ret; + + ret = da9052_rtc_enable_alarm(rtc->da9052, 1); + + return ret; +} + +static int da9052_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct da9052_rtc *rtc = dev_get_drvdata(dev); + + return da9052_rtc_enable_alarm(rtc->da9052, enabled); +} + +static const struct rtc_class_ops da9052_rtc_ops = { + .read_time = da9052_rtc_read_time, + .set_time = da9052_rtc_set_time, + .read_alarm = da9052_rtc_read_alarm, + .set_alarm = da9052_rtc_set_alarm, + .alarm_irq_enable = da9052_rtc_alarm_irq_enable, +}; + +static int __devinit da9052_rtc_probe(struct platform_device *pdev) +{ + struct da9052_rtc *rtc; + int ret; + + rtc = devm_kzalloc(&pdev->dev, sizeof(struct da9052_rtc), GFP_KERNEL); + if (!rtc) + return -ENOMEM; + + rtc->da9052 = dev_get_drvdata(pdev->dev.parent); + platform_set_drvdata(pdev, rtc); + rtc->irq = platform_get_irq_byname(pdev, "ALM"); + ret = request_threaded_irq(rtc->irq, NULL, da9052_rtc_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "ALM", rtc); + if (ret != 0) { + rtc_err(rtc->da9052, "irq registration failed: %d\n", ret); + goto err_mem; + } + + rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + &da9052_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc->rtc)) { + ret = PTR_ERR(rtc->rtc); + goto err_free_irq; + } + + return 0; + +err_free_irq: + free_irq(rtc->irq, rtc); +err_mem: + devm_kfree(&pdev->dev, rtc); + return ret; +} + +static int __devexit da9052_rtc_remove(struct platform_device *pdev) +{ + struct da9052_rtc *rtc = pdev->dev.platform_data; + + rtc_device_unregister(rtc->rtc); + free_irq(rtc->irq, rtc); + platform_set_drvdata(pdev, NULL); + devm_kfree(&pdev->dev, rtc); + + return 0; +} + +static struct platform_driver da9052_rtc_driver = { + .probe = da9052_rtc_probe, + .remove = __devexit_p(da9052_rtc_remove), + .driver = { + .name = "da9052-rtc", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(da9052_rtc_driver); + +MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); +MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da9052-rtc"); diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index 755e1fe914a..14c2109dbaa 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -542,7 +542,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CCTRL); ret = request_irq(davinci_rtc->irq, davinci_rtc_interrupt, - IRQF_DISABLED, "davinci_rtc", davinci_rtc); + 0, "davinci_rtc", davinci_rtc); if (ret < 0) { dev_err(dev, "unable to register davinci RTC interrupt\n"); goto fail4; diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 3a33b1fdbe0..686a865913e 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -814,17 +814,7 @@ static struct spi_driver ds1305_driver = { /* REVISIT add suspend/resume */ }; -static int __init ds1305_init(void) -{ - return spi_register_driver(&ds1305_driver); -} -module_init(ds1305_init); - -static void __exit ds1305_exit(void) -{ - spi_unregister_driver(&ds1305_driver); -} -module_exit(ds1305_exit); +module_spi_driver(ds1305_driver); MODULE_DESCRIPTION("RTC driver for DS1305 and DS1306 chips"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 62b0763b7b9..cd188ab72f7 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -20,7 +20,8 @@ -/* We can't determine type by probing, but if we expect pre-Linux code +/* + * We can't determine type by probing, but if we expect pre-Linux code * to have set the chip up as a clock (turning on the oscillator and * setting the date and time), Linux can ignore the non-clock features. * That's a natural job for a factory or repair bench. @@ -36,7 +37,8 @@ enum ds_type { m41t00, mcp7941x, rx_8025, - // rs5c372 too? different address... + last_ds_type /* always last */ + /* rs5c372 too? different address... */ }; @@ -58,7 +60,8 @@ enum ds_type { # define DS1337_BIT_CENTURY 0x80 /* in REG_MONTH */ #define DS1307_REG_YEAR 0x06 /* 00-99 */ -/* Other registers (control, status, alarms, trickle charge, NVRAM, etc) +/* + * Other registers (control, status, alarms, trickle charge, NVRAM, etc) * start at 7, and they differ a LOT. Only control and status matter for * basic RTC date and time functionality; be careful using them. */ @@ -102,6 +105,8 @@ enum ds_type { struct ds1307 { u8 offset; /* register's offset */ u8 regs[11]; + u16 nvram_offset; + struct bin_attribute *nvram; enum ds_type type; unsigned long flags; #define HAS_NVRAM 0 /* bit 0 == sysfs file active */ @@ -116,34 +121,35 @@ struct ds1307 { }; struct chip_desc { - unsigned nvram56:1; unsigned alarm:1; + u16 nvram_offset; + u16 nvram_size; }; -static const struct chip_desc chips[] = { -[ds_1307] = { - .nvram56 = 1, -}, -[ds_1337] = { - .alarm = 1, -}, -[ds_1338] = { - .nvram56 = 1, -}, -[ds_1339] = { - .alarm = 1, -}, -[ds_1340] = { -}, -[ds_3231] = { - .alarm = 1, -}, -[m41t00] = { -}, -[mcp7941x] = { -}, -[rx_8025] = { -}, }; +static const struct chip_desc chips[last_ds_type] = { + [ds_1307] = { + .nvram_offset = 8, + .nvram_size = 56, + }, + [ds_1337] = { + .alarm = 1, + }, + [ds_1338] = { + .nvram_offset = 8, + .nvram_size = 56, + }, + [ds_1339] = { + .alarm = 1, + }, + [ds_3231] = { + .alarm = 1, + }, + [mcp7941x] = { + /* this is battery backed SRAM */ + .nvram_offset = 0x20, + .nvram_size = 0x40, + }, +}; static const struct i2c_device_id ds1307_id[] = { { "ds1307", ds_1307 }, @@ -372,6 +378,11 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | DS1340_BIT_CENTURY; break; case mcp7941x: + /* + * these bits were cleared when preparing the date/time + * values and need to be set again before writing the + * buffer out to the device. + */ buf[DS1307_REG_SECS] |= MCP7941X_BIT_ST; buf[DS1307_REG_WDAY] |= MCP7941X_BIT_VBATEN; break; @@ -417,7 +428,8 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t) ds1307->regs[6], ds1307->regs[7], ds1307->regs[8]); - /* report alarm time (ALARM1); assume 24 hour and day-of-month modes, + /* + * report alarm time (ALARM1); assume 24 hour and day-of-month modes, * and that all four fields are checked matches */ t->time.tm_sec = bcd2bin(ds1307->regs[0] & 0x7f); @@ -445,7 +457,7 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t) static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) { - struct i2c_client *client = to_i2c_client(dev); + struct i2c_client *client = to_i2c_client(dev); struct ds1307 *ds1307 = i2c_get_clientdata(client); unsigned char *buf = ds1307->regs; u8 control, status; @@ -541,8 +553,6 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { /*----------------------------------------------------------------------*/ -#define NVRAM_SIZE 56 - static ssize_t ds1307_nvram_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, @@ -555,14 +565,15 @@ ds1307_nvram_read(struct file *filp, struct kobject *kobj, client = kobj_to_i2c_client(kobj); ds1307 = i2c_get_clientdata(client); - if (unlikely(off >= NVRAM_SIZE)) + if (unlikely(off >= ds1307->nvram->size)) return 0; - if ((off + count) > NVRAM_SIZE) - count = NVRAM_SIZE - off; + if ((off + count) > ds1307->nvram->size) + count = ds1307->nvram->size - off; if (unlikely(!count)) return count; - result = ds1307->read_block_data(client, 8 + off, count, buf); + result = ds1307->read_block_data(client, ds1307->nvram_offset + off, + count, buf); if (result < 0) dev_err(&client->dev, "%s error %d\n", "nvram read", result); return result; @@ -580,14 +591,15 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj, client = kobj_to_i2c_client(kobj); ds1307 = i2c_get_clientdata(client); - if (unlikely(off >= NVRAM_SIZE)) + if (unlikely(off >= ds1307->nvram->size)) return -EFBIG; - if ((off + count) > NVRAM_SIZE) - count = NVRAM_SIZE - off; + if ((off + count) > ds1307->nvram->size) + count = ds1307->nvram->size - off; if (unlikely(!count)) return count; - result = ds1307->write_block_data(client, 8 + off, count, buf); + result = ds1307->write_block_data(client, ds1307->nvram_offset + off, + count, buf); if (result < 0) { dev_err(&client->dev, "%s error %d\n", "nvram write", result); return result; @@ -595,21 +607,8 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj, return count; } -static struct bin_attribute nvram = { - .attr = { - .name = "nvram", - .mode = S_IRUGO | S_IWUSR, - }, - - .read = ds1307_nvram_read, - .write = ds1307_nvram_write, - .size = NVRAM_SIZE, -}; - /*----------------------------------------------------------------------*/ -static struct i2c_driver ds1307_driver; - static int __devinit ds1307_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -630,7 +629,8 @@ static int __devinit ds1307_probe(struct i2c_client *client, && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) return -EIO; - if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) + ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL); + if (!ds1307) return -ENOMEM; i2c_set_clientdata(client, ds1307); @@ -652,11 +652,6 @@ static int __devinit ds1307_probe(struct i2c_client *client, case ds_1337: case ds_1339: case ds_3231: - /* has IRQ? */ - if (ds1307->client->irq > 0 && chip->alarm) { - INIT_WORK(&ds1307->work, ds1307_work); - want_irq = true; - } /* get registers that the "rtc" read below won't read... */ tmp = ds1307->read_block_data(ds1307->client, DS1337_REG_CONTROL, 2, buf); @@ -670,14 +665,19 @@ static int __devinit ds1307_probe(struct i2c_client *client, if (ds1307->regs[0] & DS1337_BIT_nEOSC) ds1307->regs[0] &= ~DS1337_BIT_nEOSC; - /* Using IRQ? Disable the square wave and both alarms. + /* + * Using IRQ? Disable the square wave and both alarms. * For some variants, be sure alarms can trigger when we're * running on Vbackup (BBSQI/BBSQW) */ - if (want_irq) { + if (ds1307->client->irq > 0 && chip->alarm) { + INIT_WORK(&ds1307->work, ds1307_work); + ds1307->regs[0] |= DS1337_BIT_INTCN | bbsqi_bitpos[ds1307->type]; ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); + + want_irq = true; } i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, @@ -772,7 +772,8 @@ read_rtc: goto exit_free; } - /* minimal sanity checking; some chips (like DS1340) don't + /* + * minimal sanity checking; some chips (like DS1340) don't * specify the extra bits as must-be-zero, but there are * still a few values that are clearly out-of-range. */ @@ -836,11 +837,7 @@ read_rtc: } break; - case rx_8025: - case ds_1337: - case ds_1339: - case ds_1388: - case ds_3231: + default: break; } @@ -848,7 +845,8 @@ read_rtc: switch (ds1307->type) { case ds_1340: case m41t00: - /* NOTE: ignores century bits; fix before deploying + /* + * NOTE: ignores century bits; fix before deploying * systems that will run through year 2100. */ break; @@ -858,7 +856,8 @@ read_rtc: if (!(tmp & DS1307_BIT_12HR)) break; - /* Be sure we're in 24 hour mode. Multi-master systems + /* + * Be sure we're in 24 hour mode. Multi-master systems * take note... */ tmp = bcd2bin(tmp & 0x1f); @@ -894,16 +893,31 @@ read_rtc: dev_dbg(&client->dev, "got IRQ %d\n", client->irq); } - if (chip->nvram56) { - err = sysfs_create_bin_file(&client->dev.kobj, &nvram); - if (err == 0) { - set_bit(HAS_NVRAM, &ds1307->flags); - dev_info(&client->dev, "56 bytes nvram\n"); + if (chip->nvram_size) { + ds1307->nvram = kzalloc(sizeof(struct bin_attribute), + GFP_KERNEL); + if (!ds1307->nvram) { + err = -ENOMEM; + goto exit_nvram; + } + ds1307->nvram->attr.name = "nvram"; + ds1307->nvram->attr.mode = S_IRUGO | S_IWUSR; + ds1307->nvram->read = ds1307_nvram_read, + ds1307->nvram->write = ds1307_nvram_write, + ds1307->nvram->size = chip->nvram_size; + ds1307->nvram_offset = chip->nvram_offset; + err = sysfs_create_bin_file(&client->dev.kobj, ds1307->nvram); + if (err) { + kfree(ds1307->nvram); + goto exit_nvram; } + set_bit(HAS_NVRAM, &ds1307->flags); + dev_info(&client->dev, "%zu bytes nvram\n", ds1307->nvram->size); } return 0; +exit_nvram: exit_irq: rtc_device_unregister(ds1307->rtc); exit_free: @@ -913,15 +927,17 @@ exit_free: static int __devexit ds1307_remove(struct i2c_client *client) { - struct ds1307 *ds1307 = i2c_get_clientdata(client); + struct ds1307 *ds1307 = i2c_get_clientdata(client); if (test_and_clear_bit(HAS_ALARM, &ds1307->flags)) { free_irq(client->irq, client); cancel_work_sync(&ds1307->work); } - if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) - sysfs_remove_bin_file(&client->dev.kobj, &nvram); + if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) { + sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram); + kfree(ds1307->nvram); + } rtc_device_unregister(ds1307->rtc); kfree(ds1307); @@ -938,17 +954,7 @@ static struct i2c_driver ds1307_driver = { .id_table = ds1307_id, }; -static int __init ds1307_init(void) -{ - return i2c_add_driver(&ds1307_driver); -} -module_init(ds1307_init); - -static void __exit ds1307_exit(void) -{ - i2c_del_driver(&ds1307_driver); -} -module_exit(ds1307_exit); +module_i2c_driver(ds1307_driver); MODULE_DESCRIPTION("RTC driver for DS1307 and similar chips"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index e6e71deb188..966316088b7 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -446,18 +446,7 @@ static struct i2c_driver ds1374_driver = { .id_table = ds1374_id, }; -static int __init ds1374_init(void) -{ - return i2c_add_driver(&ds1374_driver); -} - -static void __exit ds1374_exit(void) -{ - i2c_del_driver(&ds1374_driver); -} - -module_init(ds1374_init); -module_exit(ds1374_exit); +module_i2c_driver(ds1374_driver); MODULE_AUTHOR("Scott Wood <scottwood@freescale.com>"); MODULE_DESCRIPTION("Maxim/Dallas DS1374 RTC Driver"); diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c index b038d2cfef2..b0a99e1b25b 100644 --- a/drivers/rtc/rtc-ds1390.c +++ b/drivers/rtc/rtc-ds1390.c @@ -175,17 +175,7 @@ static struct spi_driver ds1390_driver = { .remove = __devexit_p(ds1390_remove), }; -static __init int ds1390_init(void) -{ - return spi_register_driver(&ds1390_driver); -} -module_init(ds1390_init); - -static __exit void ds1390_exit(void) -{ - spi_unregister_driver(&ds1390_driver); -} -module_exit(ds1390_exit); +module_spi_driver(ds1390_driver); MODULE_DESCRIPTION("Dallas/Maxim DS1390/93/94 SPI RTC driver"); MODULE_AUTHOR("Mark Jackson <mpfj@mimc.co.uk>"); diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 761f36bc83a..1f675f5294f 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -532,7 +532,7 @@ ds1511_rtc_probe(struct platform_device *pdev) if (pdata->irq > 0) { rtc_read(RTC_CMD1); if (devm_request_irq(&pdev->dev, pdata->irq, ds1511_interrupt, - IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { + IRQF_SHARED, pdev->name, pdev) < 0) { dev_warn(&pdev->dev, "interrupt not available.\n"); pdata->irq = 0; diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 6f0a1b530f2..6ccedbbf923 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -320,7 +320,7 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev) writeb(0, ioaddr + RTC_INTERRUPTS); if (devm_request_irq(&pdev->dev, pdata->irq, ds1553_rtc_interrupt, - IRQF_DISABLED, pdev->name, pdev) < 0) { + 0, pdev->name, pdev) < 0) { dev_warn(&pdev->dev, "interrupt not available.\n"); pdata->irq = 0; } diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index a319402a544..7fa67d0df17 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c @@ -202,20 +202,9 @@ static struct i2c_driver ds1672_driver = { .id_table = ds1672_id, }; -static int __init ds1672_init(void) -{ - return i2c_add_driver(&ds1672_driver); -} - -static void __exit ds1672_exit(void) -{ - i2c_del_driver(&ds1672_driver); -} +module_i2c_driver(ds1672_driver); MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); - -module_init(ds1672_init); -module_exit(ds1672_exit); diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 27b7bf672ac..e1945095814 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -473,18 +473,7 @@ static struct i2c_driver ds3232_driver = { .id_table = ds3232_id, }; -static int __init ds3232_init(void) -{ - return i2c_add_driver(&ds3232_driver); -} - -static void __exit ds3232_exit(void) -{ - i2c_del_driver(&ds3232_driver); -} - -module_init(ds3232_init); -module_exit(ds3232_exit); +module_i2c_driver(ds3232_driver); MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>"); MODULE_DESCRIPTION("Maxim/Dallas DS3232 RTC Driver"); diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c index bbd26228f53..fda707926f0 100644 --- a/drivers/rtc/rtc-ds3234.c +++ b/drivers/rtc/rtc-ds3234.c @@ -173,17 +173,7 @@ static struct spi_driver ds3234_driver = { .remove = __devexit_p(ds3234_remove), }; -static __init int ds3234_init(void) -{ - return spi_register_driver(&ds3234_driver); -} -module_init(ds3234_init); - -static __exit void ds3234_exit(void) -{ - spi_unregister_driver(&ds3234_driver); -} -module_exit(ds3234_exit); +module_spi_driver(ds3234_driver); MODULE_DESCRIPTION("DS3234 SPI RTC driver"); MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>"); diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c index 8414dea5fb1..0104ea7ebe5 100644 --- a/drivers/rtc/rtc-em3027.c +++ b/drivers/rtc/rtc-em3027.c @@ -144,19 +144,8 @@ static struct i2c_driver em3027_driver = { .id_table = em3027_id, }; -static int __init em3027_init(void) -{ - return i2c_add_driver(&em3027_driver); -} - -static void __exit em3027_exit(void) -{ - i2c_del_driver(&em3027_driver); -} +module_i2c_driver(em3027_driver); MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); MODULE_DESCRIPTION("EM Microelectronic EM3027 RTC driver"); MODULE_LICENSE("GPL"); - -module_init(em3027_init); -module_exit(em3027_exit); diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 4cf2e70c507..86b6ecce99f 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c @@ -565,17 +565,7 @@ static struct i2c_driver fm3130_driver = { .id_table = fm3130_id, }; -static int __init fm3130_init(void) -{ - return i2c_add_driver(&fm3130_driver); -} -module_init(fm3130_init); - -static void __exit fm3130_exit(void) -{ - i2c_del_driver(&fm3130_driver); -} -module_exit(fm3130_exit); +module_i2c_driver(fm3130_driver); MODULE_DESCRIPTION("RTC driver for FM3130"); MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>"); diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 6186833973e..1850104705c 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -309,18 +309,7 @@ static struct i2c_driver isl12022_driver = { .id_table = isl12022_id, }; -static int __init isl12022_init(void) -{ - return i2c_add_driver(&isl12022_driver); -} - -static void __exit isl12022_exit(void) -{ - i2c_del_driver(&isl12022_driver); -} - -module_init(isl12022_init); -module_exit(isl12022_exit); +module_i2c_driver(isl12022_driver); MODULE_AUTHOR("roman.fietze@telemotive.de"); MODULE_DESCRIPTION("ISL 12022 RTC driver"); diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index da8beb8cae5..dd2aeee6c66 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -710,22 +710,9 @@ static struct i2c_driver isl1208_driver = { .id_table = isl1208_id, }; -static int __init -isl1208_init(void) -{ - return i2c_add_driver(&isl1208_driver); -} - -static void __exit -isl1208_exit(void) -{ - i2c_del_driver(&isl1208_driver); -} +module_i2c_driver(isl1208_driver); MODULE_AUTHOR("Herbert Valerio Riedel <hvr@gnu.org>"); MODULE_DESCRIPTION("Intersil ISL1208 RTC driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); - -module_init(isl1208_init); -module_exit(isl1208_exit); diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c index ecc1713b2b4..63c72189c64 100644 --- a/drivers/rtc/rtc-lpc32xx.c +++ b/drivers/rtc/rtc-lpc32xx.c @@ -287,7 +287,7 @@ static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev) if (rtc->irq >= 0) { if (devm_request_irq(&pdev->dev, rtc->irq, lpc32xx_rtc_alarm_interrupt, - IRQF_DISABLED, pdev->name, rtc) < 0) { + 0, pdev->name, rtc) < 0) { dev_warn(&pdev->dev, "Can't request interrupt.\n"); rtc->irq = -1; } else { diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c new file mode 100644 index 00000000000..07e81c5f824 --- /dev/null +++ b/drivers/rtc/rtc-ls1x.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2011 Zhao Zhang <zhzhl555@gmail.com> + * + * Derived from driver/rtc/rtc-au1xxx.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/rtc.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/types.h> +#include <linux/io.h> +#include <asm/mach-loongson1/loongson1.h> + +#define LS1X_RTC_REG_OFFSET (LS1X_RTC_BASE + 0x20) +#define LS1X_RTC_REGS(x) \ + ((void __iomem *)KSEG1ADDR(LS1X_RTC_REG_OFFSET + (x))) + +/*RTC programmable counters 0 and 1*/ +#define SYS_COUNTER_CNTRL (LS1X_RTC_REGS(0x20)) +#define SYS_CNTRL_ERS (1 << 23) +#define SYS_CNTRL_RTS (1 << 20) +#define SYS_CNTRL_RM2 (1 << 19) +#define SYS_CNTRL_RM1 (1 << 18) +#define SYS_CNTRL_RM0 (1 << 17) +#define SYS_CNTRL_RS (1 << 16) +#define SYS_CNTRL_BP (1 << 14) +#define SYS_CNTRL_REN (1 << 13) +#define SYS_CNTRL_BRT (1 << 12) +#define SYS_CNTRL_TEN (1 << 11) +#define SYS_CNTRL_BTT (1 << 10) +#define SYS_CNTRL_E0 (1 << 8) +#define SYS_CNTRL_ETS (1 << 7) +#define SYS_CNTRL_32S (1 << 5) +#define SYS_CNTRL_TTS (1 << 4) +#define SYS_CNTRL_TM2 (1 << 3) +#define SYS_CNTRL_TM1 (1 << 2) +#define SYS_CNTRL_TM0 (1 << 1) +#define SYS_CNTRL_TS (1 << 0) + +/* Programmable Counter 0 Registers */ +#define SYS_TOYTRIM (LS1X_RTC_REGS(0)) +#define SYS_TOYWRITE0 (LS1X_RTC_REGS(4)) +#define SYS_TOYWRITE1 (LS1X_RTC_REGS(8)) +#define SYS_TOYREAD0 (LS1X_RTC_REGS(0xC)) +#define SYS_TOYREAD1 (LS1X_RTC_REGS(0x10)) +#define SYS_TOYMATCH0 (LS1X_RTC_REGS(0x14)) +#define SYS_TOYMATCH1 (LS1X_RTC_REGS(0x18)) +#define SYS_TOYMATCH2 (LS1X_RTC_REGS(0x1C)) + +/* Programmable Counter 1 Registers */ +#define SYS_RTCTRIM (LS1X_RTC_REGS(0x40)) +#define SYS_RTCWRITE0 (LS1X_RTC_REGS(0x44)) +#define SYS_RTCREAD0 (LS1X_RTC_REGS(0x48)) +#define SYS_RTCMATCH0 (LS1X_RTC_REGS(0x4C)) +#define SYS_RTCMATCH1 (LS1X_RTC_REGS(0x50)) +#define SYS_RTCMATCH2 (LS1X_RTC_REGS(0x54)) + +#define LS1X_SEC_OFFSET (4) +#define LS1X_MIN_OFFSET (10) +#define LS1X_HOUR_OFFSET (16) +#define LS1X_DAY_OFFSET (21) +#define LS1X_MONTH_OFFSET (26) + + +#define LS1X_SEC_MASK (0x3f) +#define LS1X_MIN_MASK (0x3f) +#define LS1X_HOUR_MASK (0x1f) +#define LS1X_DAY_MASK (0x1f) +#define LS1X_MONTH_MASK (0x3f) +#define LS1X_YEAR_MASK (0xffffffff) + +#define ls1x_get_sec(t) (((t) >> LS1X_SEC_OFFSET) & LS1X_SEC_MASK) +#define ls1x_get_min(t) (((t) >> LS1X_MIN_OFFSET) & LS1X_MIN_MASK) +#define ls1x_get_hour(t) (((t) >> LS1X_HOUR_OFFSET) & LS1X_HOUR_MASK) +#define ls1x_get_day(t) (((t) >> LS1X_DAY_OFFSET) & LS1X_DAY_MASK) +#define ls1x_get_month(t) (((t) >> LS1X_MONTH_OFFSET) & LS1X_MONTH_MASK) + +#define RTC_CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S) + +static int ls1x_rtc_read_time(struct device *dev, struct rtc_time *rtm) +{ + unsigned long v, t; + + v = readl(SYS_TOYREAD0); + t = readl(SYS_TOYREAD1); + + memset(rtm, 0, sizeof(struct rtc_time)); + t = mktime((t & LS1X_YEAR_MASK), ls1x_get_month(v), + ls1x_get_day(v), ls1x_get_hour(v), + ls1x_get_min(v), ls1x_get_sec(v)); + rtc_time_to_tm(t, rtm); + + return rtc_valid_tm(rtm); +} + +static int ls1x_rtc_set_time(struct device *dev, struct rtc_time *rtm) +{ + unsigned long v, t, c; + int ret = -ETIMEDOUT; + + v = ((rtm->tm_mon + 1) << LS1X_MONTH_OFFSET) + | (rtm->tm_mday << LS1X_DAY_OFFSET) + | (rtm->tm_hour << LS1X_HOUR_OFFSET) + | (rtm->tm_min << LS1X_MIN_OFFSET) + | (rtm->tm_sec << LS1X_SEC_OFFSET); + + writel(v, SYS_TOYWRITE0); + c = 0x10000; + /* add timeout check counter, for more safe */ + while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TS) && --c) + usleep_range(1000, 3000); + + if (!c) { + dev_err(dev, "set time timeout!\n"); + goto err; + } + + t = rtm->tm_year + 1900; + writel(t, SYS_TOYWRITE1); + c = 0x10000; + while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TS) && --c) + usleep_range(1000, 3000); + + if (!c) { + dev_err(dev, "set time timeout!\n"); + goto err; + } + return 0; +err: + return ret; +} + +static struct rtc_class_ops ls1x_rtc_ops = { + .read_time = ls1x_rtc_read_time, + .set_time = ls1x_rtc_set_time, +}; + +static int __devinit ls1x_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtcdev; + unsigned long v; + int ret; + + v = readl(SYS_COUNTER_CNTRL); + if (!(v & RTC_CNTR_OK)) { + dev_err(&pdev->dev, "rtc counters not working\n"); + ret = -ENODEV; + goto err; + } + ret = -ETIMEDOUT; + /* set to 1 HZ if needed */ + if (readl(SYS_TOYTRIM) != 32767) { + v = 0x100000; + while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS) && --v) + usleep_range(1000, 3000); + + if (!v) { + dev_err(&pdev->dev, "time out\n"); + goto err; + } + writel(32767, SYS_TOYTRIM); + } + /* this loop coundn't be endless */ + while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS) + usleep_range(1000, 3000); + + rtcdev = rtc_device_register("ls1x-rtc", &pdev->dev, + &ls1x_rtc_ops , THIS_MODULE); + if (IS_ERR(rtcdev)) { + ret = PTR_ERR(rtcdev); + goto err; + } + + platform_set_drvdata(pdev, rtcdev); + return 0; +err: + return ret; +} + +static int __devexit ls1x_rtc_remove(struct platform_device *pdev) +{ + struct rtc_device *rtcdev = platform_get_drvdata(pdev); + + rtc_device_unregister(rtcdev); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver ls1x_rtc_driver = { + .driver = { + .name = "ls1x-rtc", + .owner = THIS_MODULE, + }, + .remove = __devexit_p(ls1x_rtc_remove), + .probe = ls1x_rtc_probe, +}; + +module_platform_driver(ls1x_rtc_driver); + +MODULE_AUTHOR("zhao zhang <zhzhl555@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 64aedd8cc09..4e0f84af99a 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -900,20 +900,9 @@ static struct i2c_driver m41t80_driver = { .id_table = m41t80_id, }; -static int __init m41t80_rtc_init(void) -{ - return i2c_add_driver(&m41t80_driver); -} - -static void __exit m41t80_rtc_exit(void) -{ - i2c_del_driver(&m41t80_driver); -} +module_i2c_driver(m41t80_driver); MODULE_AUTHOR("Alexander Bigga <ab@mycable.de>"); MODULE_DESCRIPTION("ST Microelectronics M41T80 series RTC I2C Client Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); - -module_init(m41t80_rtc_init); -module_exit(m41t80_rtc_exit); diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c index ef71132ff20..10f1c29436e 100644 --- a/drivers/rtc/rtc-m41t93.c +++ b/drivers/rtc/rtc-m41t93.c @@ -206,17 +206,7 @@ static struct spi_driver m41t93_driver = { .remove = __devexit_p(m41t93_remove), }; -static __init int m41t93_init(void) -{ - return spi_register_driver(&m41t93_driver); -} -module_init(m41t93_init); - -static __exit void m41t93_exit(void) -{ - spi_unregister_driver(&m41t93_driver); -} -module_exit(m41t93_exit); +module_spi_driver(m41t93_driver); MODULE_AUTHOR("Nikolaus Voss <n.voss@weinmann.de>"); MODULE_DESCRIPTION("Driver for ST M41T93 SPI RTC"); diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c index 2a4721f6179..6e78193e026 100644 --- a/drivers/rtc/rtc-m41t94.c +++ b/drivers/rtc/rtc-m41t94.c @@ -153,19 +153,7 @@ static struct spi_driver m41t94_driver = { .remove = __devexit_p(m41t94_remove), }; -static __init int m41t94_init(void) -{ - return spi_register_driver(&m41t94_driver); -} - -module_init(m41t94_init); - -static __exit void m41t94_exit(void) -{ - spi_unregister_driver(&m41t94_driver); -} - -module_exit(m41t94_exit); +module_spi_driver(m41t94_driver); MODULE_AUTHOR("Kim B. Heino <Kim.Heino@bluegiga.com>"); MODULE_DESCRIPTION("Driver for ST M41T94 SPI RTC"); diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index 486142c2637..a00e33204b9 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c @@ -261,20 +261,9 @@ static struct i2c_driver max6900_driver = { .id_table = max6900_id, }; -static int __init max6900_init(void) -{ - return i2c_add_driver(&max6900_driver); -} - -static void __exit max6900_exit(void) -{ - i2c_del_driver(&max6900_driver); -} +module_i2c_driver(max6900_driver); MODULE_DESCRIPTION("Maxim MAX6900 RTC driver"); MODULE_AUTHOR("Dale Farnsworth <dale@farnsworth.org>"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); - -module_init(max6900_init); -module_exit(max6900_exit); diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 1f6b3cc58e8..36c74d22e8b 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c @@ -160,17 +160,7 @@ static struct spi_driver max6902_driver = { .remove = __devexit_p(max6902_remove), }; -static __init int max6902_init(void) -{ - return spi_register_driver(&max6902_driver); -} -module_init(max6902_init); - -static __exit void max6902_exit(void) -{ - spi_unregister_driver(&max6902_driver); -} -module_exit(max6902_exit); +module_spi_driver(max6902_driver); MODULE_DESCRIPTION ("max6902 spi RTC driver"); MODULE_AUTHOR ("Raphael Assenat"); diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c index 2d71943bc43..1459055a83a 100644 --- a/drivers/rtc/rtc-max8925.c +++ b/drivers/rtc/rtc-max8925.c @@ -193,10 +193,17 @@ static int max8925_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ret = max8925_reg_read(info->rtc, MAX8925_RTC_IRQ_MASK); if (ret < 0) goto out; - if ((ret & ALARM0_IRQ) == 0) - alrm->enabled = 1; - else + if (ret & ALARM0_IRQ) { alrm->enabled = 0; + } else { + ret = max8925_reg_read(info->rtc, MAX8925_ALARM0_CNTL); + if (ret < 0) + goto out; + if (!ret) + alrm->enabled = 0; + else + alrm->enabled = 1; + } ret = max8925_reg_read(info->rtc, MAX8925_RTC_STATUS); if (ret < 0) goto out; @@ -204,6 +211,7 @@ static int max8925_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) alrm->pending = 1; else alrm->pending = 0; + return 0; out: return ret; } @@ -220,8 +228,11 @@ static int max8925_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ret = max8925_bulk_write(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf); if (ret < 0) goto out; - /* only enable alarm on year/month/day/hour/min/sec */ - ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x77); + if (alrm->enabled) + /* only enable alarm on year/month/day/hour/min/sec */ + ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x77); + else + ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x0); if (ret < 0) goto out; out: diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 9d3caccfc25..42f5f829b3e 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -327,7 +327,7 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op) dev_set_drvdata(&op->dev, rtc); rtc->irq = irq_of_parse_and_map(op->dev.of_node, 1); - err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED, + err = request_irq(rtc->irq, mpc5121_rtc_handler, 0, "mpc5121-rtc", &op->dev); if (err) { dev_err(&op->dev, "%s: could not request irq: %i\n", @@ -337,7 +337,7 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op) rtc->irq_periodic = irq_of_parse_and_map(op->dev.of_node, 0); err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd, - IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev); + 0, "mpc5121-rtc_upd", &op->dev); if (err) { dev_err(&op->dev, "%s: could not request irq: %i\n", __func__, rtc->irq_periodic); @@ -360,6 +360,8 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op) &mpc5200_rtc_ops, THIS_MODULE); } + rtc->rtc->uie_unsupported = 1; + if (IS_ERR(rtc->rtc)) { err = PTR_ERR(rtc->rtc); goto out_free_irq; diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index 6cd6c723534..f51719bf4a7 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -366,7 +366,7 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) if (rtc_irq) { retval = request_irq(rtc_irq, mrst_rtc_irq, - IRQF_DISABLED, dev_name(&mrst_rtc.rtc->dev), + 0, dev_name(&mrst_rtc.rtc->dev), mrst_rtc.rtc); if (retval < 0) { dev_dbg(dev, "IRQ %d is already in use, err %d\n", diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index 768e2edb967..b2185f4255a 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c @@ -12,6 +12,7 @@ #include <linux/bcd.h> #include <linux/io.h> #include <linux/platform_device.h> +#include <linux/of.h> #include <linux/delay.h> #include <linux/gfp.h> #include <linux/module.h> @@ -273,7 +274,7 @@ static int __devinit mv_rtc_probe(struct platform_device *pdev) if (pdata->irq >= 0) { writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); if (devm_request_irq(&pdev->dev, pdata->irq, mv_rtc_interrupt, - IRQF_DISABLED | IRQF_SHARED, + IRQF_SHARED, pdev->name, pdata) < 0) { dev_warn(&pdev->dev, "interrupt not available.\n"); pdata->irq = -1; @@ -294,11 +295,19 @@ static int __exit mv_rtc_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static struct of_device_id rtc_mv_of_match_table[] = { + { .compatible = "mrvl,orion-rtc", }, + {} +}; +#endif + static struct platform_driver mv_rtc_driver = { .remove = __exit_p(mv_rtc_remove), .driver = { .name = "rtc-mv", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rtc_mv_of_match_table), }, }; diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index 781068d62f2..b79010987d1 100644 --- a/drivers/rtc/rtc-nuc900.c +++ b/drivers/rtc/rtc-nuc900.c @@ -269,7 +269,7 @@ static int __devinit nuc900_rtc_probe(struct platform_device *pdev) nuc900_rtc->irq_num = platform_get_irq(pdev, 0); if (request_irq(nuc900_rtc->irq_num, nuc900_rtc_interrupt, - IRQF_DISABLED, "nuc900rtc", nuc900_rtc)) { + 0, "nuc900rtc", nuc900_rtc)) { dev_err(&pdev->dev, "NUC900 RTC request irq failed\n"); err = -EBUSY; goto fail4; diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 7789002bdd5..0b614e32653 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -348,14 +348,14 @@ static int __init omap_rtc_probe(struct platform_device *pdev) rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG); /* handle periodic and alarm irqs */ - if (request_irq(omap_rtc_timer, rtc_irq, IRQF_DISABLED, + if (request_irq(omap_rtc_timer, rtc_irq, 0, dev_name(&rtc->dev), rtc)) { pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", pdev->name, omap_rtc_timer); goto fail1; } if ((omap_rtc_timer != omap_rtc_alarm) && - (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED, + (request_irq(omap_rtc_alarm, rtc_irq, 0, dev_name(&rtc->dev), rtc))) { pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", pdev->name, omap_rtc_alarm); diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index b46c4004d8f..836118795c0 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -346,20 +346,9 @@ static struct spi_driver pcf2123_driver = { .remove = __devexit_p(pcf2123_remove), }; -static int __init pcf2123_init(void) -{ - return spi_register_driver(&pcf2123_driver); -} - -static void __exit pcf2123_exit(void) -{ - spi_unregister_driver(&pcf2123_driver); -} +module_spi_driver(pcf2123_driver); MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>"); MODULE_DESCRIPTION("NXP PCF2123 RTC driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); - -module_init(pcf2123_init); -module_exit(pcf2123_exit); diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 606fdfab34e..bc0677de199 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -252,20 +252,9 @@ static struct i2c_driver pcf8563_driver = { .id_table = pcf8563_id, }; -static int __init pcf8563_init(void) -{ - return i2c_add_driver(&pcf8563_driver); -} - -static void __exit pcf8563_exit(void) -{ - i2c_del_driver(&pcf8563_driver); -} +module_i2c_driver(pcf8563_driver); MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); - -module_init(pcf8563_init); -module_exit(pcf8563_exit); diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 2d201afead3..019ff357116 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c @@ -320,18 +320,7 @@ static struct i2c_driver pcf8583_driver = { .id_table = pcf8583_id, }; -static __init int pcf8583_init(void) -{ - return i2c_add_driver(&pcf8583_driver); -} - -static __exit void pcf8583_exit(void) -{ - i2c_del_driver(&pcf8583_driver); -} - -module_init(pcf8583_init); -module_exit(pcf8583_exit); +module_i2c_driver(pcf8583_driver); MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("PCF8583 I2C RTC driver"); diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index 02111fee077..22bacdbf913 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c @@ -123,7 +123,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) amba_set_drvdata(dev, rtc); - ret = request_irq(dev->irq[0], pl030_interrupt, IRQF_DISABLED, + ret = request_irq(dev->irq[0], pl030_interrupt, 0, "rtc-pl030", rtc); if (ret) goto err_irq; @@ -185,18 +185,7 @@ static struct amba_driver pl030_driver = { .id_table = pl030_ids, }; -static int __init pl030_init(void) -{ - return amba_driver_register(&pl030_driver); -} - -static void __exit pl030_exit(void) -{ - amba_driver_unregister(&pl030_driver); -} - -module_init(pl030_init); -module_exit(pl030_exit); +module_amba_driver(pl030_driver); MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); MODULE_DESCRIPTION("ARM AMBA PL030 RTC Driver"); diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index a952c8de1dd..692de7360e9 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -352,7 +352,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) } if (request_irq(adev->irq[0], pl031_interrupt, - IRQF_DISABLED, "rtc-pl031", ldata)) { + 0, "rtc-pl031", ldata)) { ret = -EIO; goto out_no_irq; } @@ -431,18 +431,7 @@ static struct amba_driver pl031_driver = { .remove = pl031_remove, }; -static int __init pl031_init(void) -{ - return amba_driver_register(&pl031_driver); -} - -static void __exit pl031_exit(void) -{ - amba_driver_unregister(&pl031_driver); -} - -module_init(pl031_init); -module_exit(pl031_exit); +module_amba_driver(pl031_driver); MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net"); MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver"); diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index 9f1d6bcbdf6..d00bd24342a 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -520,7 +520,7 @@ static int pm8xxx_rtc_suspend(struct device *dev) } #endif -SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resume); +static SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resume); static struct platform_driver pm8xxx_rtc_driver = { .probe = pm8xxx_rtc_probe, diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index fc9f4991574..0075c8fd93d 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c @@ -174,14 +174,14 @@ static int pxa_rtc_open(struct device *dev) struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); int ret; - ret = request_irq(pxa_rtc->irq_1Hz, pxa_rtc_irq, IRQF_DISABLED, + ret = request_irq(pxa_rtc->irq_1Hz, pxa_rtc_irq, 0, "rtc 1Hz", dev); if (ret < 0) { dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_1Hz, ret); goto err_irq_1Hz; } - ret = request_irq(pxa_rtc->irq_Alrm, pxa_rtc_irq, IRQF_DISABLED, + ret = request_irq(pxa_rtc->irq_Alrm, pxa_rtc_irq, 0, "rtc Alrm", dev); if (ret < 0) { dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_Alrm, diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index 9beba49c3c5..7f8e6c24793 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c @@ -125,6 +125,13 @@ static int __devinit r9701_probe(struct spi_device *spi) unsigned char tmp; int res; + tmp = R100CNT; + res = read_regs(&spi->dev, &tmp, 1); + if (res || tmp != 0x20) { + dev_err(&spi->dev, "cannot read RTC register\n"); + return -ENODEV; + } + rtc = rtc_device_register("r9701", &spi->dev, &r9701_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) @@ -132,13 +139,6 @@ static int __devinit r9701_probe(struct spi_device *spi) dev_set_drvdata(&spi->dev, rtc); - tmp = R100CNT; - res = read_regs(&spi->dev, &tmp, 1); - if (res || tmp != 0x20) { - rtc_device_unregister(rtc); - return res; - } - return 0; } @@ -159,17 +159,7 @@ static struct spi_driver r9701_driver = { .remove = __devexit_p(r9701_remove), }; -static __init int r9701_init(void) -{ - return spi_register_driver(&r9701_driver); -} -module_init(r9701_init); - -static __exit void r9701_exit(void) -{ - spi_unregister_driver(&r9701_driver); -} -module_exit(r9701_exit); +module_spi_driver(r9701_driver); MODULE_DESCRIPTION("r9701 spi RTC driver"); MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index ce2ca8523dd..77074ccd285 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -235,18 +235,7 @@ static struct spi_driver rs5c348_driver = { .remove = __devexit_p(rs5c348_remove), }; -static __init int rs5c348_init(void) -{ - return spi_register_driver(&rs5c348_driver); -} - -static __exit void rs5c348_exit(void) -{ - spi_unregister_driver(&rs5c348_driver); -} - -module_init(rs5c348_init); -module_exit(rs5c348_exit); +module_spi_driver(rs5c348_driver); MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); MODULE_DESCRIPTION("Ricoh RS5C348 RTC driver"); diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index d29f5432c6e..fb4842c3544 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -689,18 +689,7 @@ static struct i2c_driver rs5c372_driver = { .id_table = rs5c372_id, }; -static __init int rs5c372_init(void) -{ - return i2c_add_driver(&rs5c372_driver); -} - -static __exit void rs5c372_exit(void) -{ - i2c_del_driver(&rs5c372_driver); -} - -module_init(rs5c372_init); -module_exit(rs5c372_exit); +module_i2c_driver(rs5c372_driver); MODULE_AUTHOR( "Pavel Mironchik <pmironchik@optifacio.net>, " diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index ea09ff211dc..0fbe57b2f6d 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -436,18 +436,7 @@ static struct i2c_driver rv3029c2_driver = { .id_table = rv3029c2_id, }; -static int __init rv3029c2_init(void) -{ - return i2c_add_driver(&rv3029c2_driver); -} - -static void __exit rv3029c2_exit(void) -{ - i2c_del_driver(&rv3029c2_driver); -} - -module_init(rv3029c2_init); -module_exit(rv3029c2_exit); +module_i2c_driver(rv3029c2_driver); MODULE_AUTHOR("Gregory Hermant <gregory.hermant@calao-systems.com>"); MODULE_DESCRIPTION("Micro Crystal RV3029C2 RTC driver"); diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index fde172fb2ab..0de902dc1cd 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -644,19 +644,8 @@ static struct i2c_driver rx8025_driver = { .id_table = rx8025_id, }; -static int __init rx8025_init(void) -{ - return i2c_add_driver(&rx8025_driver); -} - -static void __exit rx8025_exit(void) -{ - i2c_del_driver(&rx8025_driver); -} +module_i2c_driver(rx8025_driver); MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>"); MODULE_DESCRIPTION("RX-8025 SA/NB RTC driver"); MODULE_LICENSE("GPL"); - -module_init(rx8025_init); -module_exit(rx8025_exit); diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 600b890a3c1..d84825124a7 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -276,20 +276,9 @@ static struct i2c_driver rx8581_driver = { .id_table = rx8581_id, }; -static int __init rx8581_init(void) -{ - return i2c_add_driver(&rx8581_driver); -} - -static void __exit rx8581_exit(void) -{ - i2c_del_driver(&rx8581_driver); -} +module_i2c_driver(rx8581_driver); MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com>"); MODULE_DESCRIPTION("Epson RX-8581 RTC driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); - -module_init(rx8581_init); -module_exit(rx8581_exit); diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index f789e002c9b..c9562ceedef 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -304,19 +304,8 @@ static struct i2c_driver s35390a_driver = { .id_table = s35390a_id, }; -static int __init s35390a_rtc_init(void) -{ - return i2c_add_driver(&s35390a_driver); -} - -static void __exit s35390a_rtc_exit(void) -{ - i2c_del_driver(&s35390a_driver); -} +module_i2c_driver(s35390a_driver); MODULE_AUTHOR("Byron Bradley <byron.bbradley@gmail.com>"); MODULE_DESCRIPTION("S35390A RTC driver"); MODULE_LICENSE("GPL"); - -module_init(s35390a_rtc_init); -module_exit(s35390a_rtc_exit); diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index aef40bd2957..9ccea134a99 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -35,6 +35,8 @@ enum s3c_cpu_type { TYPE_S3C2410, + TYPE_S3C2416, + TYPE_S3C2443, TYPE_S3C64XX, }; @@ -132,6 +134,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) struct platform_device *pdev = to_platform_device(dev); struct rtc_device *rtc_dev = platform_get_drvdata(pdev); unsigned int tmp = 0; + int val; if (!is_power_of_2(freq)) return -EINVAL; @@ -139,12 +142,22 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) clk_enable(rtc_clk); spin_lock_irq(&s3c_rtc_pie_lock); - if (s3c_rtc_cpu_type == TYPE_S3C2410) { + if (s3c_rtc_cpu_type != TYPE_S3C64XX) { tmp = readb(s3c_rtc_base + S3C2410_TICNT); tmp &= S3C2410_TICNT_ENABLE; } - tmp |= (rtc_dev->max_user_freq / freq)-1; + val = (rtc_dev->max_user_freq / freq) - 1; + + if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) { + tmp |= S3C2443_TICNT_PART(val); + writel(S3C2443_TICNT1_PART(val), s3c_rtc_base + S3C2443_TICNT1); + + if (s3c_rtc_cpu_type == TYPE_S3C2416) + writel(S3C2416_TICNT2_PART(val), s3c_rtc_base + S3C2416_TICNT2); + } else { + tmp |= val; + } writel(tmp, s3c_rtc_base + S3C2410_TICNT); spin_unlock_irq(&s3c_rtc_pie_lock); @@ -371,7 +384,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) tmp &= ~S3C2410_RTCCON_RTCEN; writew(tmp, base + S3C2410_RTCCON); - if (s3c_rtc_cpu_type == TYPE_S3C2410) { + if (s3c_rtc_cpu_type != TYPE_S3C64XX) { tmp = readb(base + S3C2410_TICNT); tmp &= ~S3C2410_TICNT_ENABLE; writeb(tmp, base + S3C2410_TICNT); @@ -428,12 +441,27 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) return 0; } +static const struct of_device_id s3c_rtc_dt_match[]; + +static inline int s3c_rtc_get_driver_data(struct platform_device *pdev) +{ +#ifdef CONFIG_OF + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node); + return match->data; + } +#endif + return platform_get_device_id(pdev)->driver_data; +} + static int __devinit s3c_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; struct rtc_time rtc_tm; struct resource *res; int ret; + int tmp; pr_debug("%s: probe=%p\n", __func__, pdev); @@ -508,13 +536,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) goto err_nortc; } -#ifdef CONFIG_OF - if (pdev->dev.of_node) - s3c_rtc_cpu_type = of_device_is_compatible(pdev->dev.of_node, - "samsung,s3c6410-rtc") ? TYPE_S3C64XX : TYPE_S3C2410; - else -#endif - s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; + s3c_rtc_cpu_type = s3c_rtc_get_driver_data(pdev); /* Check RTC Time */ @@ -533,24 +555,30 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); } - if (s3c_rtc_cpu_type == TYPE_S3C64XX) + if (s3c_rtc_cpu_type != TYPE_S3C2410) rtc->max_user_freq = 32768; else rtc->max_user_freq = 128; + if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) { + tmp = readw(s3c_rtc_base + S3C2410_RTCCON); + tmp |= S3C2443_RTCCON_TICSEL; + writew(tmp, s3c_rtc_base + S3C2410_RTCCON); + } + platform_set_drvdata(pdev, rtc); s3c_rtc_setfreq(&pdev->dev, 1); ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, - IRQF_DISABLED, "s3c2410-rtc alarm", rtc); + 0, "s3c2410-rtc alarm", rtc); if (ret) { dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); goto err_alarm_irq; } ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, - IRQF_DISABLED, "s3c2410-rtc tick", rtc); + 0, "s3c2410-rtc tick", rtc); if (ret) { dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); free_irq(s3c_rtc_alarmno, rtc); @@ -638,8 +666,19 @@ static int s3c_rtc_resume(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id s3c_rtc_dt_match[] = { - { .compatible = "samsung,s3c2410-rtc" }, - { .compatible = "samsung,s3c6410-rtc" }, + { + .compatible = "samsung,s3c2410-rtc" + .data = TYPE_S3C2410, + }, { + .compatible = "samsung,s3c2416-rtc" + .data = TYPE_S3C2416, + }, { + .compatible = "samsung,s3c2443-rtc" + .data = TYPE_S3C2443, + }, { + .compatible = "samsung,s3c6410-rtc" + .data = TYPE_S3C64XX, + }, {}, }; MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match); @@ -652,6 +691,12 @@ static struct platform_device_id s3c_rtc_driver_ids[] = { .name = "s3c2410-rtc", .driver_data = TYPE_S3C2410, }, { + .name = "s3c2416-rtc", + .driver_data = TYPE_S3C2416, + }, { + .name = "s3c2443-rtc", + .driver_data = TYPE_S3C2443, + }, { .name = "s3c64xx-rtc", .driver_data = TYPE_S3C64XX, }, diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index cb9a585312c..50a5c4adee4 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -23,94 +23,45 @@ #include <linux/platform_device.h> #include <linux/module.h> +#include <linux/clk.h> #include <linux/rtc.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/interrupt.h> +#include <linux/slab.h> #include <linux/string.h> +#include <linux/of.h> #include <linux/pm.h> #include <linux/bitops.h> +#include <linux/io.h> #include <mach/hardware.h> -#include <asm/irq.h> +#include <mach/irqs.h> -#ifdef CONFIG_ARCH_PXA +#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP) #include <mach/regs-rtc.h> #endif #define RTC_DEF_DIVIDER (32768 - 1) #define RTC_DEF_TRIM 0 - -static const unsigned long RTC_FREQ = 1024; -static struct rtc_time rtc_alarm; -static DEFINE_SPINLOCK(sa1100_rtc_lock); - -static inline int rtc_periodic_alarm(struct rtc_time *tm) -{ - return (tm->tm_year == -1) || - ((unsigned)tm->tm_mon >= 12) || - ((unsigned)(tm->tm_mday - 1) >= 31) || - ((unsigned)tm->tm_hour > 23) || - ((unsigned)tm->tm_min > 59) || - ((unsigned)tm->tm_sec > 59); -} - -/* - * Calculate the next alarm time given the requested alarm time mask - * and the current time. - */ -static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, - struct rtc_time *alrm) -{ - unsigned long next_time; - unsigned long now_time; - - next->tm_year = now->tm_year; - next->tm_mon = now->tm_mon; - next->tm_mday = now->tm_mday; - next->tm_hour = alrm->tm_hour; - next->tm_min = alrm->tm_min; - next->tm_sec = alrm->tm_sec; - - rtc_tm_to_time(now, &now_time); - rtc_tm_to_time(next, &next_time); - - if (next_time < now_time) { - /* Advance one day */ - next_time += 60 * 60 * 24; - rtc_time_to_tm(next_time, next); - } -} - -static int rtc_update_alarm(struct rtc_time *alrm) -{ - struct rtc_time alarm_tm, now_tm; - unsigned long now, time; - int ret; - - do { - now = RCNR; - rtc_time_to_tm(now, &now_tm); - rtc_next_alarm_time(&alarm_tm, &now_tm, alrm); - ret = rtc_tm_to_time(&alarm_tm, &time); - if (ret != 0) - break; - - RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); - RTAR = time; - } while (now != RCNR); - - return ret; -} +#define RTC_FREQ 1024 + +struct sa1100_rtc { + spinlock_t lock; + int irq_1hz; + int irq_alarm; + struct rtc_device *rtc; + struct clk *clk; +}; static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) { - struct platform_device *pdev = to_platform_device(dev_id); - struct rtc_device *rtc = platform_get_drvdata(pdev); + struct sa1100_rtc *info = dev_get_drvdata(dev_id); + struct rtc_device *rtc = info->rtc; unsigned int rtsr; unsigned long events = 0; - spin_lock(&sa1100_rtc_lock); + spin_lock(&info->lock); rtsr = RTSR; /* clear interrupt sources */ @@ -146,30 +97,28 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) rtc_update_irq(rtc, 1, events); - if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) - rtc_update_alarm(&rtc_alarm); - - spin_unlock(&sa1100_rtc_lock); + spin_unlock(&info->lock); return IRQ_HANDLED; } static int sa1100_rtc_open(struct device *dev) { + struct sa1100_rtc *info = dev_get_drvdata(dev); + struct rtc_device *rtc = info->rtc; int ret; - struct platform_device *plat_dev = to_platform_device(dev); - struct rtc_device *rtc = platform_get_drvdata(plat_dev); - ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, - "rtc 1Hz", dev); + ret = clk_prepare_enable(info->clk); + if (ret) + goto fail_clk; + ret = request_irq(info->irq_1hz, sa1100_rtc_interrupt, 0, "rtc 1Hz", dev); if (ret) { - dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); + dev_err(dev, "IRQ %d already in use.\n", info->irq_1hz); goto fail_ui; } - ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED, - "rtc Alrm", dev); + ret = request_irq(info->irq_alarm, sa1100_rtc_interrupt, 0, "rtc Alrm", dev); if (ret) { - dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); + dev_err(dev, "IRQ %d already in use.\n", info->irq_alarm); goto fail_ai; } rtc->max_user_freq = RTC_FREQ; @@ -178,29 +127,36 @@ static int sa1100_rtc_open(struct device *dev) return 0; fail_ai: - free_irq(IRQ_RTC1Hz, dev); + free_irq(info->irq_1hz, dev); fail_ui: + clk_disable_unprepare(info->clk); + fail_clk: return ret; } static void sa1100_rtc_release(struct device *dev) { - spin_lock_irq(&sa1100_rtc_lock); + struct sa1100_rtc *info = dev_get_drvdata(dev); + + spin_lock_irq(&info->lock); RTSR = 0; - spin_unlock_irq(&sa1100_rtc_lock); + spin_unlock_irq(&info->lock); - free_irq(IRQ_RTCAlrm, dev); - free_irq(IRQ_RTC1Hz, dev); + free_irq(info->irq_alarm, dev); + free_irq(info->irq_1hz, dev); + clk_disable_unprepare(info->clk); } static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { - spin_lock_irq(&sa1100_rtc_lock); + struct sa1100_rtc *info = dev_get_drvdata(dev); + + spin_lock_irq(&info->lock); if (enabled) RTSR |= RTSR_ALE; else RTSR &= ~RTSR_ALE; - spin_unlock_irq(&sa1100_rtc_lock); + spin_unlock_irq(&info->lock); return 0; } @@ -225,7 +181,6 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { u32 rtsr; - memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); rtsr = RTSR; alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; @@ -234,17 +189,22 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { + struct sa1100_rtc *info = dev_get_drvdata(dev); + unsigned long time; int ret; - spin_lock_irq(&sa1100_rtc_lock); - ret = rtc_update_alarm(&alrm->time); - if (ret == 0) { - if (alrm->enabled) - RTSR |= RTSR_ALE; - else - RTSR &= ~RTSR_ALE; - } - spin_unlock_irq(&sa1100_rtc_lock); + spin_lock_irq(&info->lock); + ret = rtc_tm_to_time(&alrm->time, &time); + if (ret != 0) + goto out; + RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); + RTAR = time; + if (alrm->enabled) + RTSR |= RTSR_ALE; + else + RTSR &= ~RTSR_ALE; +out: + spin_unlock_irq(&info->lock); return ret; } @@ -271,6 +231,27 @@ static const struct rtc_class_ops sa1100_rtc_ops = { static int sa1100_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; + struct sa1100_rtc *info; + int irq_1hz, irq_alarm, ret = 0; + + irq_1hz = platform_get_irq_byname(pdev, "rtc 1Hz"); + irq_alarm = platform_get_irq_byname(pdev, "rtc alarm"); + if (irq_1hz < 0 || irq_alarm < 0) + return -ENODEV; + + info = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL); + if (!info) + return -ENOMEM; + info->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(info->clk)) { + dev_err(&pdev->dev, "failed to find rtc clock source\n"); + ret = PTR_ERR(info->clk); + goto err_clk; + } + info->irq_1hz = irq_1hz; + info->irq_alarm = irq_alarm; + spin_lock_init(&info->lock); + platform_set_drvdata(pdev, info); /* * According to the manual we should be able to let RTTR be zero @@ -292,10 +273,11 @@ static int sa1100_rtc_probe(struct platform_device *pdev) rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) - return PTR_ERR(rtc); - - platform_set_drvdata(pdev, rtc); + if (IS_ERR(rtc)) { + ret = PTR_ERR(rtc); + goto err_dev; + } + info->rtc = rtc; /* Fix for a nasty initialization problem the in SA11xx RTSR register. * See also the comments in sa1100_rtc_interrupt(). @@ -322,14 +304,24 @@ static int sa1100_rtc_probe(struct platform_device *pdev) RTSR = RTSR_AL | RTSR_HZ; return 0; +err_dev: + platform_set_drvdata(pdev, NULL); + clk_put(info->clk); +err_clk: + kfree(info); + return ret; } static int sa1100_rtc_remove(struct platform_device *pdev) { - struct rtc_device *rtc = platform_get_drvdata(pdev); + struct sa1100_rtc *info = platform_get_drvdata(pdev); - if (rtc) - rtc_device_unregister(rtc); + if (info) { + rtc_device_unregister(info->rtc); + clk_put(info->clk); + platform_set_drvdata(pdev, NULL); + kfree(info); + } return 0; } @@ -337,15 +329,17 @@ static int sa1100_rtc_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int sa1100_rtc_suspend(struct device *dev) { + struct sa1100_rtc *info = dev_get_drvdata(dev); if (device_may_wakeup(dev)) - enable_irq_wake(IRQ_RTCAlrm); + enable_irq_wake(info->irq_alarm); return 0; } static int sa1100_rtc_resume(struct device *dev) { + struct sa1100_rtc *info = dev_get_drvdata(dev); if (device_may_wakeup(dev)) - disable_irq_wake(IRQ_RTCAlrm); + disable_irq_wake(info->irq_alarm); return 0; } @@ -355,6 +349,13 @@ static const struct dev_pm_ops sa1100_rtc_pm_ops = { }; #endif +static struct of_device_id sa1100_rtc_dt_ids[] = { + { .compatible = "mrvl,sa1100-rtc", }, + { .compatible = "mrvl,mmp-rtc", }, + {} +}; +MODULE_DEVICE_TABLE(of, sa1100_rtc_dt_ids); + static struct platform_driver sa1100_rtc_driver = { .probe = sa1100_rtc_probe, .remove = sa1100_rtc_remove, @@ -363,6 +364,7 @@ static struct platform_driver sa1100_rtc_driver = { #ifdef CONFIG_PM .pm = &sa1100_rtc_pm_ops, #endif + .of_match_table = sa1100_rtc_dt_ids, }, }; diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 6ac55fd4841..e55a7635ae5 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -666,7 +666,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev) if (rtc->carry_irq <= 0) { /* register shared periodic/carry/alarm irq */ ret = request_irq(rtc->periodic_irq, sh_rtc_shared, - IRQF_DISABLED, "sh-rtc", rtc); + 0, "sh-rtc", rtc); if (unlikely(ret)) { dev_err(&pdev->dev, "request IRQ failed with %d, IRQ %d\n", ret, @@ -676,7 +676,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev) } else { /* register periodic/carry/alarm irqs */ ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, - IRQF_DISABLED, "sh-rtc period", rtc); + 0, "sh-rtc period", rtc); if (unlikely(ret)) { dev_err(&pdev->dev, "request period IRQ failed with %d, IRQ %d\n", @@ -685,7 +685,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev) } ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, - IRQF_DISABLED, "sh-rtc carry", rtc); + 0, "sh-rtc carry", rtc); if (unlikely(ret)) { dev_err(&pdev->dev, "request carry IRQ failed with %d, IRQ %d\n", @@ -695,7 +695,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev) } ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, - IRQF_DISABLED, "sh-rtc alarm", rtc); + 0, "sh-rtc alarm", rtc); if (unlikely(ret)) { dev_err(&pdev->dev, "request alarm IRQ failed with %d, IRQ %d\n", diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index 19a28a671a8..e38da0dc418 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -77,9 +77,11 @@ #define STATUS_FAIL (LOST_WR_TIME | LOST_WR_DATE) struct spear_rtc_config { + struct rtc_device *rtc; struct clk *clk; spinlock_t lock; void __iomem *ioaddr; + unsigned int irq_wake; }; static inline void spear_rtc_clear_interrupt(struct spear_rtc_config *config) @@ -149,8 +151,7 @@ static void rtc_wait_not_busy(struct spear_rtc_config *config) static irqreturn_t spear_rtc_irq(int irq, void *dev_id) { - struct rtc_device *rtc = (struct rtc_device *)dev_id; - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); + struct spear_rtc_config *config = dev_id; unsigned long flags, events = 0; unsigned int irq_data; @@ -161,7 +162,7 @@ static irqreturn_t spear_rtc_irq(int irq, void *dev_id) if ((irq_data & RTC_INT_MASK)) { spear_rtc_clear_interrupt(config); events = RTC_IRQF | RTC_AF; - rtc_update_irq(rtc, 1, events); + rtc_update_irq(config->rtc, 1, events); return IRQ_HANDLED; } else return IRQ_NONE; @@ -203,9 +204,7 @@ static void bcd2tm(struct rtc_time *tm) */ static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); + struct spear_rtc_config *config = dev_get_drvdata(dev); unsigned int time, date; /* we don't report wday/yday/isdst ... */ @@ -234,9 +233,7 @@ static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm) */ static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); + struct spear_rtc_config *config = dev_get_drvdata(dev); unsigned int time, date, err = 0; if (tm2bcd(tm) < 0) @@ -266,9 +263,7 @@ static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm) */ static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); + struct spear_rtc_config *config = dev_get_drvdata(dev); unsigned int time, date; rtc_wait_not_busy(config); @@ -298,9 +293,7 @@ static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) */ static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) { - struct platform_device *pdev = to_platform_device(dev); - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); + struct spear_rtc_config *config = dev_get_drvdata(dev); unsigned int time, date, err = 0; if (tm2bcd(&alm->time) < 0) @@ -326,17 +319,42 @@ static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) return 0; } + +static int spear_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct spear_rtc_config *config = dev_get_drvdata(dev); + int ret = 0; + + spear_rtc_clear_interrupt(config); + + switch (enabled) { + case 0: + /* alarm off */ + spear_rtc_disable_interrupt(config); + break; + case 1: + /* alarm on */ + spear_rtc_enable_interrupt(config); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + static struct rtc_class_ops spear_rtc_ops = { .read_time = spear_rtc_read_time, .set_time = spear_rtc_set_time, .read_alarm = spear_rtc_read_alarm, .set_alarm = spear_rtc_set_alarm, + .alarm_irq_enable = spear_alarm_irq_enable, }; static int __devinit spear_rtc_probe(struct platform_device *pdev) { struct resource *res; - struct rtc_device *rtc; struct spear_rtc_config *config; unsigned int status = 0; int irq; @@ -376,19 +394,17 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) } spin_lock_init(&config->lock); + platform_set_drvdata(pdev, config); - rtc = rtc_device_register(pdev->name, &pdev->dev, &spear_rtc_ops, - THIS_MODULE); - if (IS_ERR(rtc)) { + config->rtc = rtc_device_register(pdev->name, &pdev->dev, + &spear_rtc_ops, THIS_MODULE); + if (IS_ERR(config->rtc)) { dev_err(&pdev->dev, "can't register RTC device, err %ld\n", - PTR_ERR(rtc)); - status = PTR_ERR(rtc); + PTR_ERR(config->rtc)); + status = PTR_ERR(config->rtc); goto err_iounmap; } - platform_set_drvdata(pdev, rtc); - dev_set_drvdata(&rtc->dev, config); - /* alarm irqs */ irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -397,7 +413,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) goto err_clear_platdata; } - status = request_irq(irq, spear_rtc_irq, 0, pdev->name, rtc); + status = request_irq(irq, spear_rtc_irq, 0, pdev->name, config); if (status) { dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \ claimed\n", irq); @@ -411,8 +427,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) err_clear_platdata: platform_set_drvdata(pdev, NULL); - dev_set_drvdata(&rtc->dev, NULL); - rtc_device_unregister(rtc); + rtc_device_unregister(config->rtc); err_iounmap: iounmap(config->ioaddr); err_disable_clock: @@ -429,8 +444,7 @@ err_release_region: static int __devexit spear_rtc_remove(struct platform_device *pdev) { - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); + struct spear_rtc_config *config = platform_get_drvdata(pdev); int irq; struct resource *res; @@ -448,8 +462,7 @@ static int __devexit spear_rtc_remove(struct platform_device *pdev) if (res) release_mem_region(res->start, resource_size(res)); platform_set_drvdata(pdev, NULL); - dev_set_drvdata(&rtc->dev, NULL); - rtc_device_unregister(rtc); + rtc_device_unregister(config->rtc); return 0; } @@ -458,14 +471,14 @@ static int __devexit spear_rtc_remove(struct platform_device *pdev) static int spear_rtc_suspend(struct platform_device *pdev, pm_message_t state) { - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); + struct spear_rtc_config *config = platform_get_drvdata(pdev); int irq; irq = platform_get_irq(pdev, 0); - if (device_may_wakeup(&pdev->dev)) - enable_irq_wake(irq); - else { + if (device_may_wakeup(&pdev->dev)) { + if (!enable_irq_wake(irq)) + config->irq_wake = 1; + } else { spear_rtc_disable_interrupt(config); clk_disable(config->clk); } @@ -475,15 +488,17 @@ static int spear_rtc_suspend(struct platform_device *pdev, pm_message_t state) static int spear_rtc_resume(struct platform_device *pdev) { - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); + struct spear_rtc_config *config = platform_get_drvdata(pdev); int irq; irq = platform_get_irq(pdev, 0); - if (device_may_wakeup(&pdev->dev)) - disable_irq_wake(irq); - else { + if (device_may_wakeup(&pdev->dev)) { + if (config->irq_wake) { + disable_irq_wake(irq); + config->irq_wake = 0; + } + } else { clk_enable(config->clk); spear_rtc_enable_interrupt(config); } @@ -498,8 +513,7 @@ static int spear_rtc_resume(struct platform_device *pdev) static void spear_rtc_shutdown(struct platform_device *pdev) { - struct rtc_device *rtc = platform_get_drvdata(pdev); - struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); + struct spear_rtc_config *config = platform_get_drvdata(pdev); spear_rtc_disable_interrupt(config); clk_disable(config->clk); diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 7621116bd20..279f5cfa691 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -329,7 +329,7 @@ static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev) writeb(0, ioaddr + RTC_INTERRUPTS); if (devm_request_irq(&pdev->dev, pdata->irq, stk17ta8_rtc_interrupt, - IRQF_DISABLED | IRQF_SHARED, + IRQF_SHARED, pdev->name, pdev) < 0) { dev_warn(&pdev->dev, "interrupt not available.\n"); pdata->irq = 0; diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index d43b4f6eb4e..4c2c6df2a9e 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -176,6 +176,10 @@ static int set_rtc_irq_bit(unsigned char bit) unsigned char val; int ret; + /* if the bit is set, return from here */ + if (rtc_irq_bits & bit) + return 0; + val = rtc_irq_bits | bit; val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); @@ -193,6 +197,10 @@ static int mask_rtc_irq_bit(unsigned char bit) unsigned char val; int ret; + /* if the bit is clear, return from here */ + if (!(rtc_irq_bits & bit)) + return 0; + val = rtc_irq_bits & ~bit; ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); if (ret == 0) @@ -357,7 +365,7 @@ out: static irqreturn_t twl_rtc_interrupt(int irq, void *rtc) { - unsigned long events = 0; + unsigned long events; int ret = IRQ_NONE; int res; u8 rd_reg; @@ -372,11 +380,11 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc) * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM] */ if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) - events |= RTC_IRQF | RTC_AF; + events = RTC_IRQF | RTC_AF; else - events |= RTC_IRQF | RTC_UF; + events = RTC_IRQF | RTC_PF; - res = twl_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, + res = twl_rtc_write_u8(BIT_RTC_STATUS_REG_ALARM_M, REG_RTC_STATUS_REG); if (res) goto out; @@ -449,19 +457,11 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) REG_INT_MSK_STS_A); } - /* Check RTC module status, Enable if it is off */ - ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); + dev_info(&pdev->dev, "Enabling TWL-RTC\n"); + ret = twl_rtc_write_u8(BIT_RTC_CTRL_REG_STOP_RTC_M, REG_RTC_CTRL_REG); if (ret < 0) goto out1; - if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { - dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); - rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; - ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); - if (ret < 0) - goto out1; - } - /* init cached IRQ enable bits */ ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index aac0ffed434..a12bfac49d3 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c @@ -266,7 +266,7 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) spin_lock_init(&pdata->lock); tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, - IRQF_DISABLED, pdev->name, &pdev->dev) < 0) + 0, pdev->name, &pdev->dev) < 0) return -EBUSY; rtc = rtc_device_register(pdev->name, &pdev->dev, &tx4939_rtc_ops, THIS_MODULE); diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index fcbfdda2993..5f60a7c6a15 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -333,7 +333,7 @@ static int __devinit rtc_probe(struct platform_device *pdev) goto err_device_unregister; } - retval = request_irq(aie_irq, elapsedtime_interrupt, IRQF_DISABLED, + retval = request_irq(aie_irq, elapsedtime_interrupt, 0, "elapsed_time", pdev); if (retval < 0) goto err_device_unregister; @@ -342,7 +342,7 @@ static int __devinit rtc_probe(struct platform_device *pdev) if (pie_irq <= 0) goto err_free_irq; - retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED, + retval = request_irq(pie_irq, rtclong1_interrupt, 0, "rtclong1", pdev); if (retval < 0) goto err_free_irq; diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 8c051d3179d..403b3d41d10 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -623,15 +623,7 @@ static struct i2c_driver x1205_driver = { .id_table = x1205_id, }; -static int __init x1205_init(void) -{ - return i2c_add_driver(&x1205_driver); -} - -static void __exit x1205_exit(void) -{ - i2c_del_driver(&x1205_driver); -} +module_i2c_driver(x1205_driver); MODULE_AUTHOR( "Karen Spearel <kas111 at gmail dot com>, " @@ -639,6 +631,3 @@ MODULE_AUTHOR( MODULE_DESCRIPTION("Xicor/Intersil X1205 RTC driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); - -module_init(x1205_init); -module_exit(x1205_exit); |