]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/rtc/rtc-cmos.c
rtc-cmos probe() cleanup
[karo-tx-linux.git] / drivers / rtc / rtc-cmos.c
index 6d0c35397b4932fc09d6b95b951858c9e555a8e4..e3fe83a23cf720049018dadb623de3c8b28d78d1 100644 (file)
@@ -433,6 +433,19 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
        if (!ports)
                return -ENODEV;
 
+       /* Claim I/O ports ASAP, minimizing conflict with legacy driver.
+        *
+        * REVISIT non-x86 systems may instead use memory space resources
+        * (needing ioremap etc), not i/o space resources like this ...
+        */
+       ports = request_region(ports->start,
+                       ports->end + 1 - ports->start,
+                       driver_name);
+       if (!ports) {
+               dev_dbg(dev, "i/o registers already in use\n");
+               return -EBUSY;
+       }
+
        cmos_rtc.irq = rtc_irq;
        cmos_rtc.iomem = ports;
 
@@ -454,24 +467,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
 
        cmos_rtc.rtc = rtc_device_register(driver_name, dev,
                                &cmos_rtc_ops, THIS_MODULE);
-       if (IS_ERR(cmos_rtc.rtc))
-               return PTR_ERR(cmos_rtc.rtc);
+       if (IS_ERR(cmos_rtc.rtc)) {
+               retval = PTR_ERR(cmos_rtc.rtc);
+               goto cleanup0;
+       }
 
        cmos_rtc.dev = dev;
        dev_set_drvdata(dev, &cmos_rtc);
-
-       /* platform and pnp busses handle resources incompatibly.
-        *
-        * REVISIT for non-x86 systems we may need to handle io memory
-        * resources: ioremap them, and request_mem_region().
-        */
-       if (is_pnp()) {
-               retval = request_resource(&ioport_resource, ports);
-               if (retval < 0) {
-                       dev_dbg(dev, "i/o registers already in use\n");
-                       goto cleanup0;
-               }
-       }
        rename_region(ports, cmos_rtc.rtc->dev.bus_id);
 
        spin_lock_irq(&rtc_lock);
@@ -534,9 +536,10 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
        return 0;
 
 cleanup1:
-       rename_region(ports, NULL);
-cleanup0:
+       cmos_rtc.dev = NULL;
        rtc_device_unregister(cmos_rtc.rtc);
+cleanup0:
+       release_region(ports->start, ports->end + 1 - ports->start);
        return retval;
 }
 
@@ -555,19 +558,21 @@ static void cmos_do_shutdown(void)
 static void __exit cmos_do_remove(struct device *dev)
 {
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
+       struct resource *ports;
 
        cmos_do_shutdown();
 
-       if (is_pnp())
-               release_resource(cmos->iomem);
-       rename_region(cmos->iomem, NULL);
-
        if (is_valid_irq(cmos->irq))
-               free_irq(cmos->irq, cmos_rtc.rtc);
+               free_irq(cmos->irq, cmos->rtc);
 
-       rtc_device_unregister(cmos_rtc.rtc);
+       rtc_device_unregister(cmos->rtc);
+       cmos->rtc = NULL;
 
-       cmos_rtc.dev = NULL;
+       ports = cmos->iomem;
+       release_region(ports->start, ports->end + 1 - ports->start);
+       cmos->iomem = NULL;
+
+       cmos->dev = NULL;
        dev_set_drvdata(dev, NULL);
 }
 
@@ -654,7 +659,8 @@ static int cmos_resume(struct device *dev)
 /*----------------------------------------------------------------*/
 
 /* The "CMOS" RTC normally lives on the platform_bus.  On ACPI systems,
- * the device node will always be created as a PNPACPI device.
+ * the device node will always be created as a PNPACPI device.  Plus
+ * pre-ACPI PCs probably list it in the PNPBIOS tables.
  */
 
 #ifdef CONFIG_PNP