Revert "Merge commit 'main-jb-2012.08.03-B4' into t114-0806"
[linux-2.6.git] / drivers / rtc / rtc-mrst.c
index 28e02e7..f51719b 100644 (file)
@@ -76,12 +76,15 @@ static inline unsigned char vrtc_is_updating(void)
 /*
  * rtc_time's year contains the increment over 1900, but vRTC's YEAR
  * register can't be programmed to value larger than 0x64, so vRTC
- * driver chose to use 1960 (1970 is UNIX time start point) as the base,
+ * driver chose to use 1972 (1970 is UNIX time start point) as the base,
  * and does the translation at read/write time.
  *
- * Why not just use 1970 as the offset? it's because using 1960 will
+ * Why not just use 1970 as the offset? it's because using 1972 will
  * make it consistent in leap year setting for both vrtc and low-level
- * physical rtc devices.
+ * physical rtc devices. Then why not use 1960 as the offset? If we use
+ * 1960, for a device's first use, its YEAR register is 0 and the system
+ * year will be parsed as 1960 which is not a valid UNIX time and will
+ * cause many applications to fail mysteriously.
  */
 static int mrst_read_time(struct device *dev, struct rtc_time *time)
 {
@@ -99,10 +102,10 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
        time->tm_year = vrtc_cmos_read(RTC_YEAR);
        spin_unlock_irqrestore(&rtc_lock, flags);
 
-       /* Adjust for the 1960/1900 */
-       time->tm_year += 60;
+       /* Adjust for the 1972/1900 */
+       time->tm_year += 72;
        time->tm_mon--;
-       return RTC_24H;
+       return rtc_valid_tm(time);
 }
 
 static int mrst_set_time(struct device *dev, struct rtc_time *time)
@@ -119,9 +122,9 @@ static int mrst_set_time(struct device *dev, struct rtc_time *time)
        min = time->tm_min;
        sec = time->tm_sec;
 
-       if (yrs < 70 || yrs > 138)
+       if (yrs < 72 || yrs > 138)
                return -EINVAL;
-       yrs -= 60;
+       yrs -= 72;
 
        spin_lock_irqsave(&rtc_lock, flags);
 
@@ -247,61 +250,21 @@ static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        return 0;
 }
 
-static int mrst_irq_set_state(struct device *dev, int enabled)
+/* Currently, the vRTC doesn't support UIE ON/OFF */
+static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
        struct mrst_rtc *mrst = dev_get_drvdata(dev);
        unsigned long   flags;
 
-       if (!mrst->irq)
-               return -ENXIO;
-
        spin_lock_irqsave(&rtc_lock, flags);
-
        if (enabled)
-               mrst_irq_enable(mrst, RTC_PIE);
+               mrst_irq_enable(mrst, RTC_AIE);
        else
-               mrst_irq_disable(mrst, RTC_PIE);
-
-       spin_unlock_irqrestore(&rtc_lock, flags);
-       return 0;
-}
-
-#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
-
-/* Currently, the vRTC doesn't support UIE ON/OFF */
-static int
-mrst_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-       struct mrst_rtc *mrst = dev_get_drvdata(dev);
-       unsigned long   flags;
-
-       switch (cmd) {
-       case RTC_AIE_OFF:
-       case RTC_AIE_ON:
-               if (!mrst->irq)
-                       return -EINVAL;
-               break;
-       default:
-               /* PIE ON/OFF is handled by mrst_irq_set_state() */
-               return -ENOIOCTLCMD;
-       }
-
-       spin_lock_irqsave(&rtc_lock, flags);
-       switch (cmd) {
-       case RTC_AIE_OFF:       /* alarm off */
                mrst_irq_disable(mrst, RTC_AIE);
-               break;
-       case RTC_AIE_ON:        /* alarm on */
-               mrst_irq_enable(mrst, RTC_AIE);
-               break;
-       }
        spin_unlock_irqrestore(&rtc_lock, flags);
        return 0;
 }
 
-#else
-#define        mrst_rtc_ioctl  NULL
-#endif
 
 #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
 
@@ -328,13 +291,12 @@ static int mrst_procfs(struct device *dev, struct seq_file *seq)
 #endif
 
 static const struct rtc_class_ops mrst_rtc_ops = {
-       .ioctl          = mrst_rtc_ioctl,
        .read_time      = mrst_read_time,
        .set_time       = mrst_set_time,
        .read_alarm     = mrst_read_alarm,
        .set_alarm      = mrst_set_alarm,
        .proc           = mrst_procfs,
-       .irq_set_state  = mrst_irq_set_state,
+       .alarm_irq_enable = mrst_rtc_alarm_irq_enable,
 };
 
 static struct mrst_rtc mrst_rtc;
@@ -360,7 +322,7 @@ static irqreturn_t mrst_rtc_irq(int irq, void *p)
        return IRQ_NONE;
 }
 
-static int __init
+static int __devinit
 vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
 {
        int retval = 0;
@@ -373,9 +335,8 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
        if (!iomem)
                return -ENODEV;
 
-       iomem = request_mem_region(iomem->start,
-                       iomem->end + 1 - iomem->start,
-                       driver_name);
+       iomem = request_mem_region(iomem->start, resource_size(iomem),
+                                  driver_name);
        if (!iomem) {
                dev_dbg(dev, "i/o mem already in use.\n");
                return -EBUSY;
@@ -383,6 +344,8 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
 
        mrst_rtc.irq = rtc_irq;
        mrst_rtc.iomem = iomem;
+       mrst_rtc.dev = dev;
+       dev_set_drvdata(dev, &mrst_rtc);
 
        mrst_rtc.rtc = rtc_device_register(driver_name, dev,
                                &mrst_rtc_ops, THIS_MODULE);
@@ -391,8 +354,6 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
                goto cleanup0;
        }
 
-       mrst_rtc.dev = dev;
-       dev_set_drvdata(dev, &mrst_rtc);
        rename_region(iomem, dev_name(&mrst_rtc.rtc->dev));
 
        spin_lock_irq(&rtc_lock);
@@ -405,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",
@@ -417,10 +378,11 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
        return 0;
 
 cleanup1:
-       mrst_rtc.dev = NULL;
        rtc_device_unregister(mrst_rtc.rtc);
 cleanup0:
-       release_region(iomem->start, iomem->end + 1 - iomem->start);
+       dev_set_drvdata(dev, NULL);
+       mrst_rtc.dev = NULL;
+       release_mem_region(iomem->start, resource_size(iomem));
        dev_err(dev, "rtc-mrst: unable to initialise\n");
        return retval;
 }
@@ -432,7 +394,7 @@ static void rtc_mrst_do_shutdown(void)
        spin_unlock_irq(&rtc_lock);
 }
 
-static void __exit rtc_mrst_do_remove(struct device *dev)
+static void __devexit rtc_mrst_do_remove(struct device *dev)
 {
        struct mrst_rtc *mrst = dev_get_drvdata(dev);
        struct resource *iomem;
@@ -446,7 +408,7 @@ static void __exit rtc_mrst_do_remove(struct device *dev)
        mrst->rtc = NULL;
 
        iomem = mrst->iomem;
-       release_region(iomem->start, iomem->end + 1 - iomem->start);
+       release_mem_region(iomem->start, resource_size(iomem));
        mrst->iomem = NULL;
 
        mrst->dev = NULL;
@@ -541,14 +503,14 @@ static inline int mrst_poweroff(struct device *dev)
 
 #endif
 
-static int __init vrtc_mrst_platform_probe(struct platform_device *pdev)
+static int __devinit vrtc_mrst_platform_probe(struct platform_device *pdev)
 {
        return vrtc_mrst_do_probe(&pdev->dev,
                        platform_get_resource(pdev, IORESOURCE_MEM, 0),
                        platform_get_irq(pdev, 0));
 }
 
-static int __exit vrtc_mrst_platform_remove(struct platform_device *pdev)
+static int __devexit vrtc_mrst_platform_remove(struct platform_device *pdev)
 {
        rtc_mrst_do_remove(&pdev->dev);
        return 0;
@@ -566,7 +528,7 @@ MODULE_ALIAS("platform:vrtc_mrst");
 
 static struct platform_driver vrtc_mrst_platform_driver = {
        .probe          = vrtc_mrst_platform_probe,
-       .remove         = __exit_p(vrtc_mrst_platform_remove),
+       .remove         = __devexit_p(vrtc_mrst_platform_remove),
        .shutdown       = vrtc_mrst_platform_shutdown,
        .driver = {
                .name           = (char *) driver_name,
@@ -575,18 +537,7 @@ static struct platform_driver vrtc_mrst_platform_driver = {
        }
 };
 
-static int __init vrtc_mrst_init(void)
-{
-       return platform_driver_register(&vrtc_mrst_platform_driver);
-}
-
-static void __exit vrtc_mrst_exit(void)
-{
-       platform_driver_unregister(&vrtc_mrst_platform_driver);
-}
-
-module_init(vrtc_mrst_init);
-module_exit(vrtc_mrst_exit);
+module_platform_driver(vrtc_mrst_platform_driver);
 
 MODULE_AUTHOR("Jacob Pan; Feng Tang");
 MODULE_DESCRIPTION("Driver for Moorestown virtual RTC");