]> Pileus Git - ~andy/linux/blobdiff - arch/arm/mach-omap2/smartreflex.c
ARM: OMAP3+: SmartReflex: Add a shutdown hook
[~andy/linux] / arch / arm / mach-omap2 / smartreflex.c
index 9dd93453e563eaa666b2640663d529dc9102c928..24ba80b70bd3dde1e101a292db75a098e495897b 100644 (file)
@@ -447,8 +447,52 @@ int sr_configure_errgen(struct voltagedomain *voltdm)
                sr_errconfig);
 
        /* Enabling the interrupts if the ERROR module is used */
-       sr_modify_reg(sr, errconfig_offs,
-               vpboundint_en, (vpboundint_en | vpboundint_st));
+       sr_modify_reg(sr, errconfig_offs, (vpboundint_en | vpboundint_st),
+                     vpboundint_en);
+
+       return 0;
+}
+
+/**
+ * sr_disable_errgen() - Disables SmartReflex AVS module's errgen component
+ * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * disable the error generator module inside the smartreflex module.
+ *
+ * Returns 0 on success and error value in case of failure.
+ */
+int sr_disable_errgen(struct voltagedomain *voltdm)
+{
+       u32 errconfig_offs, vpboundint_en;
+       u32 vpboundint_st;
+       struct omap_sr *sr = _sr_lookup(voltdm);
+
+       if (IS_ERR(sr)) {
+               pr_warning("%s: omap_sr struct for sr_%s not found\n",
+                       __func__, voltdm->name);
+               return -EINVAL;
+       }
+
+       if (sr->ip_type == SR_TYPE_V1) {
+               errconfig_offs = ERRCONFIG_V1;
+               vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
+               vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
+       } else if (sr->ip_type == SR_TYPE_V2) {
+               errconfig_offs = ERRCONFIG_V2;
+               vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
+               vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
+       } else {
+               dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+                       "module without specifying the ip\n", __func__);
+               return -EINVAL;
+       }
+
+       /* Disable the interrupts of ERROR module */
+       sr_modify_reg(sr, errconfig_offs, vpboundint_en | vpboundint_st, 0);
+
+       /* Disable the Sensor and errorgen */
+       sr_modify_reg(sr, SRCONFIG, SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN, 0);
 
        return 0;
 }
@@ -897,7 +941,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
                ret = sr_late_init(sr_info);
                if (ret) {
                        pr_warning("%s: Error in SR late init\n", __func__);
-                       return ret;
+                       goto err_iounmap;
                }
        }
 
@@ -1011,8 +1055,32 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
        return 0;
 }
 
+static void __devexit omap_sr_shutdown(struct platform_device *pdev)
+{
+       struct omap_sr_data *pdata = pdev->dev.platform_data;
+       struct omap_sr *sr_info;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+               return;
+       }
+
+       sr_info = _sr_lookup(pdata->voltdm);
+       if (IS_ERR(sr_info)) {
+               dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
+                       __func__);
+               return;
+       }
+
+       if (sr_info->autocomp_active)
+               sr_stop_vddautocomp(sr_info);
+
+       return;
+}
+
 static struct platform_driver smartreflex_driver = {
-       .remove         = omap_sr_remove,
+       .remove         = __devexit_p(omap_sr_remove),
+       .shutdown       = __devexit_p(omap_sr_shutdown),
        .driver         = {
                .name   = "smartreflex",
        },