|
@@ -27,7 +27,8 @@
|
|
|
#include <linux/pm_runtime.h>
|
|
|
#include <linux/power/smartreflex.h>
|
|
|
|
|
|
-#define SMARTREFLEX_NAME_LEN 16
|
|
|
+#define DRIVER_NAME "smartreflex"
|
|
|
+#define SMARTREFLEX_NAME_LEN 32
|
|
|
#define NVALUE_NAME_LEN 40
|
|
|
#define SR_DISABLE_TIMEOUT 200
|
|
|
|
|
@@ -207,12 +208,11 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)
|
|
|
static int sr_late_init(struct omap_sr *sr_info)
|
|
|
{
|
|
|
struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;
|
|
|
- struct resource *mem;
|
|
|
int ret = 0;
|
|
|
|
|
|
if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
|
|
|
- ret = request_irq(sr_info->irq, sr_interrupt,
|
|
|
- 0, sr_info->name, sr_info);
|
|
|
+ ret = devm_request_irq(&sr_info->pdev->dev, sr_info->irq,
|
|
|
+ sr_interrupt, 0, sr_info->name, sr_info);
|
|
|
if (ret)
|
|
|
goto error;
|
|
|
disable_irq(sr_info->irq);
|
|
@@ -224,14 +224,10 @@ static int sr_late_init(struct omap_sr *sr_info)
|
|
|
return ret;
|
|
|
|
|
|
error:
|
|
|
- iounmap(sr_info->base);
|
|
|
- mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
|
|
|
- release_mem_region(mem->start, resource_size(mem));
|
|
|
list_del(&sr_info->node);
|
|
|
dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
|
|
|
"interrupt handler. Smartreflex will"
|
|
|
"not function as desired\n", __func__);
|
|
|
- kfree(sr_info);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -341,9 +337,9 @@ static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
|
|
|
/* Public Functions */
|
|
|
|
|
|
/**
|
|
|
- * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the
|
|
|
+ * sr_configure_errgen() - Configures the SmartReflex to perform AVS using the
|
|
|
* error generator module.
|
|
|
- * @voltdm: VDD pointer to which the SR module to be configured belongs to.
|
|
|
+ * @sr: SR module to be configured.
|
|
|
*
|
|
|
* This API is to be called from the smartreflex class driver to
|
|
|
* configure the error generator module inside the smartreflex module.
|
|
@@ -352,17 +348,17 @@ static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
|
|
|
* SR CLASS 2 can choose between ERROR module and MINMAXAVG
|
|
|
* module. Returns 0 on success and error value in case of failure.
|
|
|
*/
|
|
|
-int sr_configure_errgen(struct voltagedomain *voltdm)
|
|
|
+int sr_configure_errgen(struct omap_sr *sr)
|
|
|
{
|
|
|
u32 sr_config, sr_errconfig, errconfig_offs;
|
|
|
u32 vpboundint_en, vpboundint_st;
|
|
|
u32 senp_en = 0, senn_en = 0;
|
|
|
u8 senp_shift, senn_shift;
|
|
|
- struct omap_sr *sr = _sr_lookup(voltdm);
|
|
|
|
|
|
- if (IS_ERR(sr)) {
|
|
|
- pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
|
|
- return PTR_ERR(sr);
|
|
|
+ if (!sr) {
|
|
|
+ pr_warn("%s: NULL omap_sr from %pF\n", __func__,
|
|
|
+ (void *)_RET_IP_);
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
if (!sr->clk_length)
|
|
@@ -414,22 +410,22 @@ int sr_configure_errgen(struct voltagedomain *voltdm)
|
|
|
|
|
|
/**
|
|
|
* sr_disable_errgen() - Disables SmartReflex AVS module's errgen component
|
|
|
- * @voltdm: VDD pointer to which the SR module to be configured belongs to.
|
|
|
+ * @sr: SR module to be configured.
|
|
|
*
|
|
|
* 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)
|
|
|
+int sr_disable_errgen(struct omap_sr *sr)
|
|
|
{
|
|
|
u32 errconfig_offs;
|
|
|
u32 vpboundint_en, vpboundint_st;
|
|
|
- struct omap_sr *sr = _sr_lookup(voltdm);
|
|
|
|
|
|
- if (IS_ERR(sr)) {
|
|
|
- pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
|
|
- return PTR_ERR(sr);
|
|
|
+ if (!sr) {
|
|
|
+ pr_warn("%s: NULL omap_sr from %pF\n", __func__,
|
|
|
+ (void *)_RET_IP_);
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
switch (sr->ip_type) {
|
|
@@ -449,19 +445,24 @@ int sr_disable_errgen(struct voltagedomain *voltdm)
|
|
|
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);
|
|
|
|
|
|
+ /*
|
|
|
+ * Disable the interrupts of ERROR module
|
|
|
+ * NOTE: modify is a read, modify,write - an implicit OCP barrier
|
|
|
+ * which is required is present here - sequencing is critical
|
|
|
+ * at this point (after errgen is disabled, vpboundint disable)
|
|
|
+ */
|
|
|
+ sr_modify_reg(sr, errconfig_offs, vpboundint_en | vpboundint_st, 0);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * sr_configure_minmax() - Configures the smrtreflex to perform AVS using the
|
|
|
+ * sr_configure_minmax() - Configures the SmartReflex to perform AVS using the
|
|
|
* minmaxavg module.
|
|
|
- * @voltdm: VDD pointer to which the SR module to be configured belongs to.
|
|
|
+ * @sr: SR module to be configured.
|
|
|
*
|
|
|
* This API is to be called from the smartreflex class driver to
|
|
|
* configure the minmaxavg module inside the smartreflex module.
|
|
@@ -470,16 +471,16 @@ int sr_disable_errgen(struct voltagedomain *voltdm)
|
|
|
* SR CLASS 2 can choose between ERROR module and MINMAXAVG
|
|
|
* module. Returns 0 on success and error value in case of failure.
|
|
|
*/
|
|
|
-int sr_configure_minmax(struct voltagedomain *voltdm)
|
|
|
+int sr_configure_minmax(struct omap_sr *sr)
|
|
|
{
|
|
|
u32 sr_config, sr_avgwt;
|
|
|
u32 senp_en = 0, senn_en = 0;
|
|
|
u8 senp_shift, senn_shift;
|
|
|
- struct omap_sr *sr = _sr_lookup(voltdm);
|
|
|
|
|
|
- if (IS_ERR(sr)) {
|
|
|
- pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
|
|
- return PTR_ERR(sr);
|
|
|
+ if (!sr) {
|
|
|
+ pr_warn("%s: NULL omap_sr from %pF\n", __func__,
|
|
|
+ (void *)_RET_IP_);
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
if (!sr->clk_length)
|
|
@@ -546,7 +547,7 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
|
|
|
|
|
|
/**
|
|
|
* sr_enable() - Enables the smartreflex module.
|
|
|
- * @voltdm: VDD pointer to which the SR module to be configured belongs to.
|
|
|
+ * @sr: pointer to which the SR module to be configured belongs to.
|
|
|
* @volt: The voltage at which the Voltage domain associated with
|
|
|
* the smartreflex module is operating at.
|
|
|
* This is required only to program the correct Ntarget value.
|
|
@@ -555,16 +556,16 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
|
|
|
* enable a smartreflex module. Returns 0 on success. Returns error
|
|
|
* value if the voltage passed is wrong or if ntarget value is wrong.
|
|
|
*/
|
|
|
-int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
|
|
|
+int sr_enable(struct omap_sr *sr, unsigned long volt)
|
|
|
{
|
|
|
struct omap_volt_data *volt_data;
|
|
|
- struct omap_sr *sr = _sr_lookup(voltdm);
|
|
|
struct omap_sr_nvalue_table *nvalue_row;
|
|
|
int ret;
|
|
|
|
|
|
- if (IS_ERR(sr)) {
|
|
|
- pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
|
|
- return PTR_ERR(sr);
|
|
|
+ if (!sr) {
|
|
|
+ pr_warn("%s: NULL omap_sr from %pF\n", __func__,
|
|
|
+ (void *)_RET_IP_);
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
volt_data = omap_voltage_get_voltdata(sr->voltdm, volt);
|
|
@@ -606,17 +607,16 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
|
|
|
|
|
|
/**
|
|
|
* sr_disable() - Disables the smartreflex module.
|
|
|
- * @voltdm: VDD pointer to which the SR module to be configured belongs to.
|
|
|
+ * @sr: pointer to which the SR module to be configured belongs to.
|
|
|
*
|
|
|
* This API is to be called from the smartreflex class driver to
|
|
|
* disable a smartreflex module.
|
|
|
*/
|
|
|
-void sr_disable(struct voltagedomain *voltdm)
|
|
|
+void sr_disable(struct omap_sr *sr)
|
|
|
{
|
|
|
- struct omap_sr *sr = _sr_lookup(voltdm);
|
|
|
-
|
|
|
- if (IS_ERR(sr)) {
|
|
|
- pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
|
|
+ if (!sr) {
|
|
|
+ pr_warn("%s: NULL omap_sr from %pF\n", __func__,
|
|
|
+ (void *)_RET_IP_);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -847,34 +847,33 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
|
|
struct dentry *nvalue_dir;
|
|
|
int i, ret = 0;
|
|
|
|
|
|
- sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
|
|
|
+ sr_info = devm_kzalloc(&pdev->dev, sizeof(struct omap_sr), GFP_KERNEL);
|
|
|
if (!sr_info) {
|
|
|
dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
|
|
|
__func__);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
+ sr_info->name = devm_kzalloc(&pdev->dev,
|
|
|
+ SMARTREFLEX_NAME_LEN, GFP_KERNEL);
|
|
|
+ if (!sr_info->name) {
|
|
|
+ dev_err(&pdev->dev, "%s: unable to allocate SR instance name\n",
|
|
|
+ __func__);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
platform_set_drvdata(pdev, sr_info);
|
|
|
|
|
|
if (!pdata) {
|
|
|
dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
|
|
|
- ret = -EINVAL;
|
|
|
- goto err_free_devinfo;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
- if (!mem) {
|
|
|
- dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
|
|
|
- ret = -ENODEV;
|
|
|
- goto err_free_devinfo;
|
|
|
- }
|
|
|
-
|
|
|
- mem = request_mem_region(mem->start, resource_size(mem),
|
|
|
- dev_name(&pdev->dev));
|
|
|
- if (!mem) {
|
|
|
- dev_err(&pdev->dev, "%s: no mem region\n", __func__);
|
|
|
- ret = -EBUSY;
|
|
|
- goto err_free_devinfo;
|
|
|
+ sr_info->base = devm_ioremap_resource(&pdev->dev, mem);
|
|
|
+ if (IS_ERR(sr_info->base)) {
|
|
|
+ dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
|
|
|
+ return PTR_ERR(sr_info->base);
|
|
|
}
|
|
|
|
|
|
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
|
@@ -882,13 +881,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
|
|
pm_runtime_enable(&pdev->dev);
|
|
|
pm_runtime_irq_safe(&pdev->dev);
|
|
|
|
|
|
- sr_info->name = kasprintf(GFP_KERNEL, "%s", pdata->name);
|
|
|
- if (!sr_info->name) {
|
|
|
- dev_err(&pdev->dev, "%s: Unable to alloc SR instance name\n",
|
|
|
- __func__);
|
|
|
- ret = -ENOMEM;
|
|
|
- goto err_release_region;
|
|
|
- }
|
|
|
+ snprintf(sr_info->name, SMARTREFLEX_NAME_LEN, "%s", pdata->name);
|
|
|
|
|
|
sr_info->pdev = pdev;
|
|
|
sr_info->srid = pdev->id;
|
|
@@ -905,13 +898,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
|
|
sr_info->autocomp_active = false;
|
|
|
sr_info->ip_type = pdata->ip_type;
|
|
|
|
|
|
- sr_info->base = ioremap(mem->start, resource_size(mem));
|
|
|
- if (!sr_info->base) {
|
|
|
- dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
|
|
|
- ret = -ENOMEM;
|
|
|
- goto err_free_name;
|
|
|
- }
|
|
|
-
|
|
|
if (irq)
|
|
|
sr_info->irq = irq->start;
|
|
|
|
|
@@ -927,7 +913,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__);
|
|
|
- goto err_iounmap;
|
|
|
+ goto err_list_del;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -938,7 +924,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
|
|
ret = PTR_ERR(sr_dbg_dir);
|
|
|
pr_err("%s:sr debugfs dir creation failed(%d)\n",
|
|
|
__func__, ret);
|
|
|
- goto err_iounmap;
|
|
|
+ goto err_list_del;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -991,16 +977,8 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
|
|
|
|
|
err_debugfs:
|
|
|
debugfs_remove_recursive(sr_info->dbg_dir);
|
|
|
-err_iounmap:
|
|
|
+err_list_del:
|
|
|
list_del(&sr_info->node);
|
|
|
- iounmap(sr_info->base);
|
|
|
-err_free_name:
|
|
|
- kfree(sr_info->name);
|
|
|
-err_release_region:
|
|
|
- release_mem_region(mem->start, resource_size(mem));
|
|
|
-err_free_devinfo:
|
|
|
- kfree(sr_info);
|
|
|
-
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -1008,7 +986,6 @@ static int omap_sr_remove(struct platform_device *pdev)
|
|
|
{
|
|
|
struct omap_sr_data *pdata = pdev->dev.platform_data;
|
|
|
struct omap_sr *sr_info;
|
|
|
- struct resource *mem;
|
|
|
|
|
|
if (!pdata) {
|
|
|
dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
|
|
@@ -1027,13 +1004,8 @@ static int omap_sr_remove(struct platform_device *pdev)
|
|
|
if (sr_info->dbg_dir)
|
|
|
debugfs_remove_recursive(sr_info->dbg_dir);
|
|
|
|
|
|
+ pm_runtime_disable(&pdev->dev);
|
|
|
list_del(&sr_info->node);
|
|
|
- iounmap(sr_info->base);
|
|
|
- kfree(sr_info->name);
|
|
|
- kfree(sr_info);
|
|
|
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
- release_mem_region(mem->start, resource_size(mem));
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1064,7 +1036,7 @@ static struct platform_driver smartreflex_driver = {
|
|
|
.remove = omap_sr_remove,
|
|
|
.shutdown = omap_sr_shutdown,
|
|
|
.driver = {
|
|
|
- .name = "smartreflex",
|
|
|
+ .name = DRIVER_NAME,
|
|
|
},
|
|
|
};
|
|
|
|