[PATCH 31/31] PM / devfreq: convert to devm_pm_opp_register_notifier and remove unused API

2021-01-02 Thread Yangtao Li
 Use devm_pm_opp_* API to simplify code.

Signed-off-by: Yangtao Li 
---
 drivers/devfreq/devfreq.c | 66 +--
 include/linux/devfreq.h   | 23 --
 2 files changed, 1 insertion(+), 88 deletions(-)

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 6aa10de792b3..f593f30529ec 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -2004,40 +2004,6 @@ struct dev_pm_opp *devfreq_recommended_opp(struct device 
*dev,
 }
 EXPORT_SYMBOL(devfreq_recommended_opp);
 
-/**
- * devfreq_register_opp_notifier() - Helper function to get devfreq notified
- *  for any changes in the OPP availability
- *  changes
- * @dev:   The devfreq user device. (parent of devfreq)
- * @devfreq:   The devfreq object.
- */
-int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
-{
-   return dev_pm_opp_register_notifier(dev, >nb);
-}
-EXPORT_SYMBOL(devfreq_register_opp_notifier);
-
-/**
- * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq
- *notified for any changes in the OPP
- *availability changes anymore.
- * @dev:   The devfreq user device. (parent of devfreq)
- * @devfreq:   The devfreq object.
- *
- * At exit() callback of devfreq_dev_profile, this must be included if
- * devfreq_recommended_opp is used.
- */
-int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq 
*devfreq)
-{
-   return dev_pm_opp_unregister_notifier(dev, >nb);
-}
-EXPORT_SYMBOL(devfreq_unregister_opp_notifier);
-
-static void devm_devfreq_opp_release(struct device *dev, void *res)
-{
-   devfreq_unregister_opp_notifier(dev, *(struct devfreq **)res);
-}
-
 /**
  * devm_devfreq_register_opp_notifier() - Resource-managed
  *   devfreq_register_opp_notifier()
@@ -2047,40 +2013,10 @@ static void devm_devfreq_opp_release(struct device 
*dev, void *res)
 int devm_devfreq_register_opp_notifier(struct device *dev,
   struct devfreq *devfreq)
 {
-   struct devfreq **ptr;
-   int ret;
-
-   ptr = devres_alloc(devm_devfreq_opp_release, sizeof(*ptr), GFP_KERNEL);
-   if (!ptr)
-   return -ENOMEM;
-
-   ret = devfreq_register_opp_notifier(dev, devfreq);
-   if (ret) {
-   devres_free(ptr);
-   return ret;
-   }
-
-   *ptr = devfreq;
-   devres_add(dev, ptr);
-
-   return 0;
+   return devm_pm_opp_register_notifier(dev, >nb);
 }
 EXPORT_SYMBOL(devm_devfreq_register_opp_notifier);
 
-/**
- * devm_devfreq_unregister_opp_notifier() - Resource-managed
- * devfreq_unregister_opp_notifier()
- * @dev:   The devfreq user device. (parent of devfreq)
- * @devfreq:   The devfreq object.
- */
-void devm_devfreq_unregister_opp_notifier(struct device *dev,
-struct devfreq *devfreq)
-{
-   WARN_ON(devres_release(dev, devm_devfreq_opp_release,
-  devm_devfreq_dev_match, devfreq));
-}
-EXPORT_SYMBOL(devm_devfreq_unregister_opp_notifier);
-
 /**
  * devfreq_register_notifier() - Register a driver with devfreq
  * @devfreq:   The devfreq object.
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index b6d3bae1c74d..aca2cc4f4fa4 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -230,14 +230,8 @@ int update_devfreq(struct devfreq *devfreq);
 /* Helper functions for devfreq user device driver with OPP. */
 struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
unsigned long *freq, u32 flags);
-int devfreq_register_opp_notifier(struct device *dev,
-   struct devfreq *devfreq);
-int devfreq_unregister_opp_notifier(struct device *dev,
-   struct devfreq *devfreq);
 int devm_devfreq_register_opp_notifier(struct device *dev,
struct devfreq *devfreq);
-void devm_devfreq_unregister_opp_notifier(struct device *dev,
-   struct devfreq *devfreq);
 int devfreq_register_notifier(struct devfreq *devfreq,
struct notifier_block *nb,
unsigned int list);
@@ -355,29 +349,12 @@ static inline struct dev_pm_opp 
*devfreq_recommended_opp(struct device *dev,
return ERR_PTR(-EINVAL);
 }
 
-static inline int devfreq_register_opp_notifier(struct device *dev,
-   struct devfreq *devfreq)
-{
-   return -EINVAL;
-}
-
-static inline int devfreq_unregister_opp_notifier(struct device *dev,
-   struct devfreq *devfreq)
-{
-   return -EINVAL;
-}
-
 static inline int devm_devfreq_register_opp_notifier(struct de

[PATCH 29/31] PM / devfreq: imx-bus: convert to use devm_pm_opp_* API

2021-01-02 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code.

Signed-off-by: Yangtao Li 
---
 drivers/devfreq/imx-bus.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/devfreq/imx-bus.c b/drivers/devfreq/imx-bus.c
index 4f38455ad742..ff26ef049b1b 100644
--- a/drivers/devfreq/imx-bus.c
+++ b/drivers/devfreq/imx-bus.c
@@ -61,7 +61,6 @@ static void imx_bus_exit(struct device *dev)
 {
struct imx_bus *priv = dev_get_drvdata(dev);
 
-   dev_pm_opp_of_remove_table(dev);
platform_device_unregister(priv->icc_pdev);
 }
 
@@ -123,7 +122,7 @@ static int imx_bus_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, priv);
 
-   ret = dev_pm_opp_of_add_table(dev);
+   ret = devm_pm_opp_of_add_table(dev);
if (ret < 0) {
dev_err(dev, "failed to get OPP table\n");
return ret;
@@ -141,18 +140,11 @@ static int imx_bus_probe(struct platform_device *pdev)
if (IS_ERR(priv->devfreq)) {
ret = PTR_ERR(priv->devfreq);
dev_err(dev, "failed to add devfreq device: %d\n", ret);
-   goto err;
+   return ret;
}
 
-   ret = imx_bus_init_icc(dev);
-   if (ret)
-   goto err;
-
-   return 0;
+   return imx_bus_init_icc(dev);
 
-err:
-   dev_pm_opp_of_remove_table(dev);
-   return ret;
 }
 
 static const struct of_device_id imx_bus_of_match[] = {
-- 
2.25.1



[PATCH 30/31] PM / devfreq: exynos: convert to use devm_pm_opp_* API

2021-01-02 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code, and remove opp_table
from exynos_bus.

Signed-off-by: Yangtao Li 
---
 drivers/devfreq/exynos-bus.c | 42 
 1 file changed, 9 insertions(+), 33 deletions(-)

diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index e689101abc93..51752e5ce980 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -33,7 +33,6 @@ struct exynos_bus {
 
unsigned long curr_freq;
 
-   struct opp_table *opp_table;
struct clk *clk;
unsigned int ratio;
 };
@@ -159,10 +158,7 @@ static void exynos_bus_exit(struct device *dev)
 
platform_device_unregister(bus->icc_pdev);
 
-   dev_pm_opp_of_remove_table(dev);
clk_disable_unprepare(bus->clk);
-   dev_pm_opp_put_regulators(bus->opp_table);
-   bus->opp_table = NULL;
 }
 
 static void exynos_bus_passive_exit(struct device *dev)
@@ -171,7 +167,6 @@ static void exynos_bus_passive_exit(struct device *dev)
 
platform_device_unregister(bus->icc_pdev);
 
-   dev_pm_opp_of_remove_table(dev);
clk_disable_unprepare(bus->clk);
 }
 
@@ -183,15 +178,13 @@ static int exynos_bus_parent_parse_of(struct device_node 
*np,
const char *vdd = "vdd";
int i, ret, count, size;
 
-   opp_table = dev_pm_opp_set_regulators(dev, , 1);
+   opp_table = devm_pm_opp_set_regulators(dev, , 1);
if (IS_ERR(opp_table)) {
ret = PTR_ERR(opp_table);
dev_err(dev, "failed to set regulators %d\n", ret);
return ret;
}
 
-   bus->opp_table = opp_table;
-
/*
 * Get the devfreq-event devices to get the current utilization of
 * buses. This raw data will be used in devfreq ondemand governor.
@@ -199,25 +192,20 @@ static int exynos_bus_parent_parse_of(struct device_node 
*np,
count = devfreq_event_get_edev_count(dev, "devfreq-events");
if (count < 0) {
dev_err(dev, "failed to get the count of devfreq-event dev\n");
-   ret = count;
-   goto err_regulator;
+   return count;
}
bus->edev_count = count;
 
size = sizeof(*bus->edev) * count;
bus->edev = devm_kzalloc(dev, size, GFP_KERNEL);
-   if (!bus->edev) {
-   ret = -ENOMEM;
-   goto err_regulator;
-   }
+   if (!bus->edev)
+   return -ENOMEM;
 
for (i = 0; i < count; i++) {
bus->edev[i] = devfreq_event_get_edev_by_phandle(dev,
"devfreq-events", i);
-   if (IS_ERR(bus->edev[i])) {
-   ret = -EPROBE_DEFER;
-   goto err_regulator;
-   }
+   if (IS_ERR(bus->edev[i]))
+   return -EPROBE_DEFER;
}
 
/*
@@ -234,12 +222,6 @@ static int exynos_bus_parent_parse_of(struct device_node 
*np,
bus->ratio = DEFAULT_SATURATION_RATIO;
 
return 0;
-
-err_regulator:
-   dev_pm_opp_put_regulators(bus->opp_table);
-   bus->opp_table = NULL;
-
-   return ret;
 }
 
 static int exynos_bus_parse_of(struct device_node *np,
@@ -264,7 +246,7 @@ static int exynos_bus_parse_of(struct device_node *np,
}
 
/* Get the freq and voltage from OPP table to scale the bus freq */
-   ret = dev_pm_opp_of_add_table(dev);
+   ret = devm_pm_opp_of_add_table(dev);
if (ret < 0) {
dev_err(dev, "failed to get OPP table\n");
goto err_clk;
@@ -276,15 +258,13 @@ static int exynos_bus_parse_of(struct device_node *np,
if (IS_ERR(opp)) {
dev_err(dev, "failed to find dev_pm_opp\n");
ret = PTR_ERR(opp);
-   goto err_opp;
+   goto err_clk;
}
bus->curr_freq = dev_pm_opp_get_freq(opp);
dev_pm_opp_put(opp);
 
return 0;
 
-err_opp:
-   dev_pm_opp_of_remove_table(dev);
 err_clk:
clk_disable_unprepare(bus->clk);
 
@@ -425,7 +405,7 @@ static int exynos_bus_probe(struct platform_device *pdev)
/* Parse the device-tree to get the resource information */
ret = exynos_bus_parse_of(np, bus);
if (ret < 0)
-   goto err_reg;
+   return ret;
 
if (passive)
ret = exynos_bus_profile_init_passive(bus, profile);
@@ -456,11 +436,7 @@ static int exynos_bus_probe(struct platform_device *pdev)
return 0;
 
 err:
-   dev_pm_opp_of_remove_table(dev);
clk_disable_unprepare(bus->clk);
-err_reg:
-   dev_pm_opp_put_regulators(bus->opp_table);
-   bus->opp_table = NULL;
 
return ret;
 }
-- 
2.25.1



[PATCH 26/31] PM / devfreq: tegra30: convert to use devm_pm_opp_* API

2021-01-02 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code, and remove opp_table
from tegra_devfreq.

Signed-off-by: Yangtao Li 
---
 drivers/devfreq/tegra30-devfreq.c | 21 +++--
 1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/drivers/devfreq/tegra30-devfreq.c 
b/drivers/devfreq/tegra30-devfreq.c
index 117cad7968ab..4984cb91e9ea 100644
--- a/drivers/devfreq/tegra30-devfreq.c
+++ b/drivers/devfreq/tegra30-devfreq.c
@@ -178,7 +178,6 @@ struct tegra_devfreq_soc_data {
 
 struct tegra_devfreq {
struct devfreq  *devfreq;
-   struct opp_table*opp_table;
 
struct reset_control*reset;
struct clk  *clock;
@@ -794,6 +793,7 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
struct tegra_devfreq_device *dev;
struct tegra_devfreq *tegra;
struct devfreq *devfreq;
+   struct opp_tabl *opp_table;
unsigned int i;
long rate;
int err;
@@ -841,25 +841,25 @@ static int tegra_devfreq_probe(struct platform_device 
*pdev)
return err;
}
 
-   tegra->opp_table = dev_pm_opp_set_supported_hw(>dev,
-  _version, 1);
-   err = PTR_ERR_OR_ZERO(tegra->opp_table);
+   opp_table = devm_pm_opp_set_supported_hw(>dev,
+_version, 1);
+   err = PTR_ERR_OR_ZERO(opp_table);
if (err) {
dev_err(>dev, "Failed to set supported HW: %d\n", err);
return err;
}
 
-   err = dev_pm_opp_of_add_table(>dev);
+   err = devm_pm_opp_of_add_table(>dev);
if (err) {
dev_err(>dev, "Failed to add OPP table: %d\n", err);
-   goto put_hw;
+   return err;
}
 
err = clk_prepare_enable(tegra->clock);
if (err) {
dev_err(>dev,
"Failed to prepare and enable ACTMON clock\n");
-   goto remove_table;
+   return err;
}
 
err = reset_control_reset(tegra->reset);
@@ -917,10 +917,6 @@ static int tegra_devfreq_probe(struct platform_device 
*pdev)
reset_control_reset(tegra->reset);
 disable_clk:
clk_disable_unprepare(tegra->clock);
-remove_table:
-   dev_pm_opp_of_remove_table(>dev);
-put_hw:
-   dev_pm_opp_put_supported_hw(tegra->opp_table);
 
return err;
 }
@@ -935,9 +931,6 @@ static int tegra_devfreq_remove(struct platform_device 
*pdev)
reset_control_reset(tegra->reset);
clk_disable_unprepare(tegra->clock);
 
-   dev_pm_opp_of_remove_table(>dev);
-   dev_pm_opp_put_supported_hw(tegra->opp_table);
-
return 0;
 }
 
-- 
2.25.1



[PATCH 28/31] PM / devfreq: imx8m-ddrc: convert to use devm_pm_opp_* API

2021-01-02 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code.

Signed-off-by: Yangtao Li 
---
 drivers/devfreq/imx8m-ddrc.c | 15 ++-
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/drivers/devfreq/imx8m-ddrc.c b/drivers/devfreq/imx8m-ddrc.c
index bc82d3653bff..9383d6e5538b 100644
--- a/drivers/devfreq/imx8m-ddrc.c
+++ b/drivers/devfreq/imx8m-ddrc.c
@@ -370,11 +370,6 @@ static int imx8m_ddrc_check_opps(struct device *dev)
return 0;
 }
 
-static void imx8m_ddrc_exit(struct device *dev)
-{
-   dev_pm_opp_of_remove_table(dev);
-}
-
 static int imx8m_ddrc_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -419,7 +414,7 @@ static int imx8m_ddrc_probe(struct platform_device *pdev)
return ret;
}
 
-   ret = dev_pm_opp_of_add_table(dev);
+   ret = devm_pm_opp_of_add_table(dev);
if (ret < 0) {
dev_err(dev, "failed to get OPP table\n");
return ret;
@@ -427,12 +422,11 @@ static int imx8m_ddrc_probe(struct platform_device *pdev)
 
ret = imx8m_ddrc_check_opps(dev);
if (ret < 0)
-   goto err;
+   return ret;
 
priv->profile.polling_ms = 1000;
priv->profile.target = imx8m_ddrc_target;
priv->profile.get_dev_status = imx8m_ddrc_get_dev_status;
-   priv->profile.exit = imx8m_ddrc_exit;
priv->profile.get_cur_freq = imx8m_ddrc_get_cur_freq;
priv->profile.initial_freq = clk_get_rate(priv->dram_core);
 
@@ -441,13 +435,8 @@ static int imx8m_ddrc_probe(struct platform_device *pdev)
if (IS_ERR(priv->devfreq)) {
ret = PTR_ERR(priv->devfreq);
dev_err(dev, "failed to add devfreq device: %d\n", ret);
-   goto err;
}
 
-   return 0;
-
-err:
-   dev_pm_opp_of_remove_table(dev);
return ret;
 }
 
-- 
2.25.1



[PATCH 25/31] memory: tegra30: convert to use devm_pm_opp_* API

2021-01-02 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code.

Signed-off-by: Yangtao Li 
---
 drivers/memory/tegra/tegra30-emc.c | 29 +
 1 file changed, 9 insertions(+), 20 deletions(-)

diff --git a/drivers/memory/tegra/tegra30-emc.c 
b/drivers/memory/tegra/tegra30-emc.c
index 44ac155936aa..a93d8c3629fe 100644
--- a/drivers/memory/tegra/tegra30-emc.c
+++ b/drivers/memory/tegra/tegra30-emc.c
@@ -1483,31 +1483,31 @@ static int tegra_emc_interconnect_init(struct tegra_emc 
*emc)
 static int tegra_emc_opp_table_init(struct tegra_emc *emc)
 {
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
-   struct opp_table *clk_opp_table, *hw_opp_table;
+   struct opp_table *opp_table;
int err;
 
-   clk_opp_table = dev_pm_opp_set_clkname(emc->dev, NULL);
-   err = PTR_ERR_OR_ZERO(clk_opp_table);
+   opp_table = devm_pm_opp_set_clkname(emc->dev, NULL);
+   err = PTR_ERR_OR_ZERO(opp_table);
if (err) {
dev_err(emc->dev, "failed to set OPP clk: %d\n", err);
return err;
}
 
-   hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, _version, 1);
-   err = PTR_ERR_OR_ZERO(hw_opp_table);
+   opp_table = devm_pm_opp_set_supported_hw(emc->dev, _version, 1);
+   err = PTR_ERR_OR_ZERO(opp_table);
if (err) {
dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
-   goto put_clk_table;
+   return err;
}
 
-   err = dev_pm_opp_of_add_table(emc->dev);
+   err = devm_pm_opp_of_add_table(emc->dev);
if (err) {
if (err == -ENODEV)
dev_err(emc->dev, "OPP table not found, please update 
your device tree\n");
else
dev_err(emc->dev, "failed to add OPP table: %d\n", err);
 
-   goto put_hw_table;
+   return err;
}
 
dev_info(emc->dev, "OPP HW ver. 0x%x, current clock rate %lu MHz\n",
@@ -1515,19 +1515,8 @@ static int tegra_emc_opp_table_init(struct tegra_emc 
*emc)
 
/* first dummy rate-set initializes voltage state */
err = dev_pm_opp_set_rate(emc->dev, clk_get_rate(emc->clk));
-   if (err) {
+   if (err)
dev_err(emc->dev, "failed to initialize OPP clock: %d\n", err);
-   goto remove_table;
-   }
-
-   return 0;
-
-remove_table:
-   dev_pm_opp_of_remove_table(emc->dev);
-put_hw_table:
-   dev_pm_opp_put_supported_hw(hw_opp_table);
-put_clk_table:
-   dev_pm_opp_put_clkname(clk_opp_table);
 
return err;
 }
-- 
2.25.1



[PATCH 27/31] PM / devfreq: rk3399_dmc: convert to use devm_pm_opp_* API

2021-01-02 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code. Since devres release
can guarantee the order, let's remove
devm_devfreq_unregister_opp_notifier().

Signed-off-by: Yangtao Li 
---
 drivers/devfreq/rk3399_dmc.c | 22 +++---
 1 file changed, 3 insertions(+), 19 deletions(-)

diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
index 2e912166a993..9b8ab8be29d1 100644
--- a/drivers/devfreq/rk3399_dmc.c
+++ b/drivers/devfreq/rk3399_dmc.c
@@ -432,7 +432,7 @@ static int rk3399_dmcfreq_probe(struct platform_device 
*pdev)
 * We add a devfreq driver to our parent since it has a device tree node
 * with operating points.
 */
-   if (dev_pm_opp_of_add_table(dev)) {
+   if (devm_pm_opp_of_add_table(dev)) {
dev_err(dev, "Invalid operating-points in device tree.\n");
ret = -EINVAL;
goto err_edev;
@@ -448,7 +448,7 @@ static int rk3399_dmcfreq_probe(struct platform_device 
*pdev)
opp = devfreq_recommended_opp(dev, >rate, 0);
if (IS_ERR(opp)) {
ret = PTR_ERR(opp);
-   goto err_free_opp;
+   goto err_edev;
}
 
data->rate = dev_pm_opp_get_freq(opp);
@@ -463,7 +463,7 @@ static int rk3399_dmcfreq_probe(struct platform_device 
*pdev)
   >ondemand_data);
if (IS_ERR(data->devfreq)) {
ret = PTR_ERR(data->devfreq);
-   goto err_free_opp;
+   goto err_edev;
}
 
devm_devfreq_register_opp_notifier(dev, data->devfreq);
@@ -473,27 +473,12 @@ static int rk3399_dmcfreq_probe(struct platform_device 
*pdev)
 
return 0;
 
-err_free_opp:
-   dev_pm_opp_of_remove_table(>dev);
 err_edev:
devfreq_event_disable_edev(data->edev);
 
return ret;
 }
 
-static int rk3399_dmcfreq_remove(struct platform_device *pdev)
-{
-   struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(>dev);
-
-   /*
-* Before remove the opp table we need to unregister the opp notifier.
-*/
-   devm_devfreq_unregister_opp_notifier(dmcfreq->dev, dmcfreq->devfreq);
-   dev_pm_opp_of_remove_table(dmcfreq->dev);
-
-   return 0;
-}
-
 static const struct of_device_id rk3399dmc_devfreq_of_match[] = {
{ .compatible = "rockchip,rk3399-dmc" },
{ },
@@ -502,7 +487,6 @@ MODULE_DEVICE_TABLE(of, rk3399dmc_devfreq_of_match);
 
 static struct platform_driver rk3399_dmcfreq_driver = {
.probe  = rk3399_dmcfreq_probe,
-   .remove = rk3399_dmcfreq_remove,
.driver = {
.name   = "rk3399-dmc-freq",
.pm = _dmcfreq_pm,
-- 
2.25.1



[PATCH 19/31] drm/panfrost: convert to use devm_pm_opp_* API

2021-01-01 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code, and remove opp_table
from panfrost_devfreq.

Signed-off-by: Yangtao Li 
---
 drivers/gpu/drm/panfrost/panfrost_devfreq.c | 34 ++---
 drivers/gpu/drm/panfrost/panfrost_devfreq.h |  1 -
 2 files changed, 10 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c 
b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
index f44d28fad085..c42fa9eb43b1 100644
--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c
+++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
@@ -92,25 +92,26 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
struct thermal_cooling_device *cooling;
struct panfrost_devfreq *pfdevfreq = >pfdevfreq;
 
-   opp_table = dev_pm_opp_set_regulators(dev, pfdev->comp->supply_names,
+   opp_table = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names,
  pfdev->comp->num_supplies);
if (IS_ERR(opp_table)) {
ret = PTR_ERR(opp_table);
/* Continue if the optional regulator is missing */
if (ret != -ENODEV) {
DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n");
-   goto err_fini;
+   return ret;
}
-   } else {
-   pfdevfreq->regulators_opp_table = opp_table;
}
 
-   ret = dev_pm_opp_of_add_table(dev);
+   ret = devm_pm_opp_of_add_table(dev);
if (ret) {
+   if (!IS_ERR(opp_table))
+   devm_pm_opp_put_regulators(dev, opp_table);
+
/* Optional, continue without devfreq */
if (ret == -ENODEV)
ret = 0;
-   goto err_fini;
+   return ret;
}
pfdevfreq->opp_of_table_added = true;
 
@@ -121,10 +122,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
cur_freq = clk_get_rate(pfdev->clock);
 
opp = devfreq_recommended_opp(dev, _freq, 0);
-   if (IS_ERR(opp)) {
-   ret = PTR_ERR(opp);
-   goto err_fini;
-   }
+   if (IS_ERR(opp))
+   return PTR_ERR(opp);
 
panfrost_devfreq_profile.initial_freq = cur_freq;
dev_pm_opp_put(opp);
@@ -133,8 +132,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
  DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL);
if (IS_ERR(devfreq)) {
DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n");
-   ret = PTR_ERR(devfreq);
-   goto err_fini;
+   return PTR_ERR(devfreq);
}
pfdevfreq->devfreq = devfreq;
 
@@ -145,10 +143,6 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
pfdevfreq->cooling = cooling;
 
return 0;
-
-err_fini:
-   panfrost_devfreq_fini(pfdev);
-   return ret;
 }
 
 void panfrost_devfreq_fini(struct panfrost_device *pfdev)
@@ -159,14 +153,6 @@ void panfrost_devfreq_fini(struct panfrost_device *pfdev)
devfreq_cooling_unregister(pfdevfreq->cooling);
pfdevfreq->cooling = NULL;
}
-
-   if (pfdevfreq->opp_of_table_added) {
-   dev_pm_opp_of_remove_table(>pdev->dev);
-   pfdevfreq->opp_of_table_added = false;
-   }
-
-   dev_pm_opp_put_regulators(pfdevfreq->regulators_opp_table);
-   pfdevfreq->regulators_opp_table = NULL;
 }
 
 void panfrost_devfreq_resume(struct panfrost_device *pfdev)
diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h 
b/drivers/gpu/drm/panfrost/panfrost_devfreq.h
index db6ea48e21f9..a51854cc8c06 100644
--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h
+++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h
@@ -15,7 +15,6 @@ struct panfrost_device;
 
 struct panfrost_devfreq {
struct devfreq *devfreq;
-   struct opp_table *regulators_opp_table;
struct thermal_cooling_device *cooling;
bool opp_of_table_added;
 
-- 
2.25.1



[PATCH 24/31] memory: tegra20: convert to use devm_pm_opp_* API

2021-01-01 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code.

Signed-off-by: Yangtao Li 
---
 drivers/memory/tegra/tegra20-emc.c | 29 +
 1 file changed, 9 insertions(+), 20 deletions(-)

diff --git a/drivers/memory/tegra/tegra20-emc.c 
b/drivers/memory/tegra/tegra20-emc.c
index 686aaf477d8a..223d9d97eb8f 100644
--- a/drivers/memory/tegra/tegra20-emc.c
+++ b/drivers/memory/tegra/tegra20-emc.c
@@ -911,31 +911,31 @@ static int tegra_emc_interconnect_init(struct tegra_emc 
*emc)
 static int tegra_emc_opp_table_init(struct tegra_emc *emc)
 {
u32 hw_version = BIT(tegra_sku_info.soc_process_id);
-   struct opp_table *clk_opp_table, *hw_opp_table;
+   struct opp_table *opp_table;
int err;
 
-   clk_opp_table = dev_pm_opp_set_clkname(emc->dev, NULL);
-   err = PTR_ERR_OR_ZERO(clk_opp_table);
+   opp_table = devm_pm_opp_set_clkname(emc->dev, NULL);
+   err = PTR_ERR_OR_ZERO(opp_table);
if (err) {
dev_err(emc->dev, "failed to set OPP clk: %d\n", err);
return err;
}
 
-   hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, _version, 1);
-   err = PTR_ERR_OR_ZERO(hw_opp_table);
+   opp_table = devm_pm_opp_set_supported_hw(emc->dev, _version, 1);
+   err = PTR_ERR_OR_ZERO(opp_table);
if (err) {
dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
-   goto put_clk_table;
+   return err;
}
 
-   err = dev_pm_opp_of_add_table(emc->dev);
+   err = devm_pm_opp_of_add_table(emc->dev);
if (err) {
if (err == -ENODEV)
dev_err(emc->dev, "OPP table not found, please update 
your device tree\n");
else
dev_err(emc->dev, "failed to add OPP table: %d\n", err);
 
-   goto put_hw_table;
+   return err;
}
 
dev_info(emc->dev, "OPP HW ver. 0x%x, current clock rate %lu MHz\n",
@@ -943,19 +943,8 @@ static int tegra_emc_opp_table_init(struct tegra_emc *emc)
 
/* first dummy rate-set initializes voltage state */
err = dev_pm_opp_set_rate(emc->dev, clk_get_rate(emc->clk));
-   if (err) {
+   if (err)
dev_err(emc->dev, "failed to initialize OPP clock: %d\n", err);
-   goto remove_table;
-   }
-
-   return 0;
-
-remove_table:
-   dev_pm_opp_of_remove_table(emc->dev);
-put_hw_table:
-   dev_pm_opp_put_supported_hw(hw_opp_table);
-put_clk_table:
-   dev_pm_opp_put_clkname(clk_opp_table);
 
return err;
 }
-- 
2.25.1



[PATCH 23/31] memory: samsung: exynos5422-dmc: convert to use devm_pm_opp_* API

2021-01-01 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code.

Signed-off-by: Yangtao Li 
---
 drivers/memory/samsung/exynos5422-dmc.c | 21 +
 1 file changed, 5 insertions(+), 16 deletions(-)

diff --git a/drivers/memory/samsung/exynos5422-dmc.c 
b/drivers/memory/samsung/exynos5422-dmc.c
index 62a83633f837..cab9fd74322b 100644
--- a/drivers/memory/samsung/exynos5422-dmc.c
+++ b/drivers/memory/samsung/exynos5422-dmc.c
@@ -343,7 +343,7 @@ static int exynos5_init_freq_table(struct exynos5_dmc *dmc,
int idx;
unsigned long freq;
 
-   ret = dev_pm_opp_of_add_table(dmc->dev);
+   ret = devm_pm_opp_of_add_table(dmc->dev);
if (ret < 0) {
dev_err(dmc->dev, "Failed to get OPP table\n");
return ret;
@@ -353,20 +353,16 @@ static int exynos5_init_freq_table(struct exynos5_dmc 
*dmc,
 
dmc->opp = devm_kmalloc_array(dmc->dev, dmc->opp_count,
  sizeof(struct dmc_opp_table), GFP_KERNEL);
-   if (!dmc->opp) {
-   ret = -ENOMEM;
-   goto err_opp;
-   }
+   if (!dmc->opp)
+   return -ENOMEM;
 
idx = dmc->opp_count - 1;
for (i = 0, freq = ULONG_MAX; i < dmc->opp_count; i++, freq--) {
struct dev_pm_opp *opp;
 
opp = dev_pm_opp_find_freq_floor(dmc->dev, );
-   if (IS_ERR(opp)) {
-   ret = PTR_ERR(opp);
-   goto err_opp;
-   }
+   if (IS_ERR(opp))
+   return PTR_ERR(opp);
 
dmc->opp[idx - i].freq_hz = freq;
dmc->opp[idx - i].volt_uv = dev_pm_opp_get_voltage(opp);
@@ -375,11 +371,6 @@ static int exynos5_init_freq_table(struct exynos5_dmc *dmc,
}
 
return 0;
-
-err_opp:
-   dev_pm_opp_of_remove_table(dmc->dev);
-
-   return ret;
 }
 
 /**
@@ -1571,8 +1562,6 @@ static int exynos5_dmc_remove(struct platform_device 
*pdev)
clk_disable_unprepare(dmc->mout_bpll);
clk_disable_unprepare(dmc->fout_bpll);
 
-   dev_pm_opp_remove_table(dmc->dev);
-
return 0;
 }
 
-- 
2.25.1



[PATCH 21/31] media: venus: convert to use devm_pm_opp_* API

2021-01-01 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code.

Signed-off-by: Yangtao Li 
---
 .../media/platform/qcom/venus/pm_helpers.c| 21 ---
 1 file changed, 4 insertions(+), 17 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c 
b/drivers/media/platform/qcom/venus/pm_helpers.c
index 59cbd6c39450..9684c25558ef 100644
--- a/drivers/media/platform/qcom/venus/pm_helpers.c
+++ b/drivers/media/platform/qcom/venus/pm_helpers.c
@@ -871,31 +871,23 @@ static int core_get_v4(struct device *dev)
if (legacy_binding)
return 0;
 
-   core->opp_table = dev_pm_opp_set_clkname(dev, "core");
+   core->opp_table = devm_pm_opp_set_clkname(dev, "core");
if (IS_ERR(core->opp_table))
return PTR_ERR(core->opp_table);
 
if (core->res->opp_pmdomain) {
-   ret = dev_pm_opp_of_add_table(dev);
+   ret = devm_pm_opp_of_add_table(dev);
if (!ret) {
core->has_opp_table = true;
} else if (ret != -ENODEV) {
dev_err(dev, "invalid OPP table in device tree\n");
return ret;
} else {
-   dev_pm_opp_put_clkname(core->opp_table);
+   devm_pm_opp_put_clkname(dev, core->opp_table);
}
}
 
-   ret = vcodec_domains_get(dev);
-   if (ret) {
-   if (core->has_opp_table)
-   dev_pm_opp_of_remove_table(dev);
-   dev_pm_opp_put_clkname(core->opp_table);
-   return ret;
-   }
-
-   return 0;
+   return vcodec_domains_get(dev);
 }
 
 static void core_put_v4(struct device *dev)
@@ -906,11 +898,6 @@ static void core_put_v4(struct device *dev)
return;
 
vcodec_domains_put(dev);
-
-   if (core->has_opp_table)
-   dev_pm_opp_of_remove_table(dev);
-   dev_pm_opp_put_clkname(core->opp_table);
-
 }
 
 static int core_power_v4(struct device *dev, int on)
-- 
2.25.1



[PATCH 22/31] memory: samsung: exynos5422-dmc: fix return error in exynos5_init_freq_table

2021-01-01 Thread Yangtao Li
We can't always return -EINVAL, let's fix it.

Signed-off-by: Yangtao Li 
---
 drivers/memory/samsung/exynos5422-dmc.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/memory/samsung/exynos5422-dmc.c 
b/drivers/memory/samsung/exynos5422-dmc.c
index c5ee4121a4d2..62a83633f837 100644
--- a/drivers/memory/samsung/exynos5422-dmc.c
+++ b/drivers/memory/samsung/exynos5422-dmc.c
@@ -353,16 +353,20 @@ static int exynos5_init_freq_table(struct exynos5_dmc 
*dmc,
 
dmc->opp = devm_kmalloc_array(dmc->dev, dmc->opp_count,
  sizeof(struct dmc_opp_table), GFP_KERNEL);
-   if (!dmc->opp)
+   if (!dmc->opp) {
+   ret = -ENOMEM;
goto err_opp;
+   }
 
idx = dmc->opp_count - 1;
for (i = 0, freq = ULONG_MAX; i < dmc->opp_count; i++, freq--) {
struct dev_pm_opp *opp;
 
opp = dev_pm_opp_find_freq_floor(dmc->dev, );
-   if (IS_ERR(opp))
+   if (IS_ERR(opp)) {
+   ret = PTR_ERR(opp);
goto err_opp;
+   }
 
dmc->opp[idx - i].freq_hz = freq;
dmc->opp[idx - i].volt_uv = dev_pm_opp_get_voltage(opp);
@@ -375,7 +379,7 @@ static int exynos5_init_freq_table(struct exynos5_dmc *dmc,
 err_opp:
dev_pm_opp_of_remove_table(dmc->dev);
 
-   return -EINVAL;
+   return ret;
 }
 
 /**
-- 
2.25.1



[PATCH 20/31] media: venus: fix error check in core_get_v4()

2021-01-01 Thread Yangtao Li
Don't call dev_pm_opp_put_clkname() when got invalid OPP table
in device tree, since we do this in core_put_v4().

Signed-off-by: Yangtao Li 
---
 drivers/media/platform/qcom/venus/pm_helpers.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c 
b/drivers/media/platform/qcom/venus/pm_helpers.c
index a3850261d697..59cbd6c39450 100644
--- a/drivers/media/platform/qcom/venus/pm_helpers.c
+++ b/drivers/media/platform/qcom/venus/pm_helpers.c
@@ -881,8 +881,9 @@ static int core_get_v4(struct device *dev)
core->has_opp_table = true;
} else if (ret != -ENODEV) {
dev_err(dev, "invalid OPP table in device tree\n");
-   dev_pm_opp_put_clkname(core->opp_table);
return ret;
+   } else {
+   dev_pm_opp_put_clkname(core->opp_table);
}
}
 
-- 
2.25.1



[PATCH 18/31] drm/lima: remove unneeded devm_devfreq_remove_device()

2021-01-01 Thread Yangtao Li
There is no need to manually release devm related resources.

Signed-off-by: Yangtao Li 
---
 drivers/gpu/drm/lima/lima_devfreq.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/gpu/drm/lima/lima_devfreq.c 
b/drivers/gpu/drm/lima/lima_devfreq.c
index d5937cf86504..7690c5c69f9f 100644
--- a/drivers/gpu/drm/lima/lima_devfreq.c
+++ b/drivers/gpu/drm/lima/lima_devfreq.c
@@ -94,11 +94,6 @@ void lima_devfreq_fini(struct lima_device *ldev)
devfreq_cooling_unregister(devfreq->cooling);
devfreq->cooling = NULL;
}
-
-   if (devfreq->devfreq) {
-   devm_devfreq_remove_device(ldev->dev, devfreq->devfreq);
-   devfreq->devfreq = NULL;
-   }
 }
 
 int lima_devfreq_init(struct lima_device *ldev)
-- 
2.25.1



[PATCH 17/31] drm/lima: convert to use devm_pm_opp_* API

2021-01-01 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code, and remove opp_table
from lima_devfreq.

Signed-off-by: Yangtao Li 
---
 drivers/gpu/drm/lima/lima_devfreq.c | 40 -
 drivers/gpu/drm/lima/lima_devfreq.h |  2 --
 2 files changed, 10 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/lima/lima_devfreq.c 
b/drivers/gpu/drm/lima/lima_devfreq.c
index 5686ad4aaf7c..d5937cf86504 100644
--- a/drivers/gpu/drm/lima/lima_devfreq.c
+++ b/drivers/gpu/drm/lima/lima_devfreq.c
@@ -99,13 +99,6 @@ void lima_devfreq_fini(struct lima_device *ldev)
devm_devfreq_remove_device(ldev->dev, devfreq->devfreq);
devfreq->devfreq = NULL;
}
-
-   dev_pm_opp_of_remove_table(ldev->dev);
-
-   dev_pm_opp_put_regulators(devfreq->regulators_opp_table);
-   dev_pm_opp_put_clkname(devfreq->clkname_opp_table);
-   devfreq->regulators_opp_table = NULL;
-   devfreq->clkname_opp_table = NULL;
 }
 
 int lima_devfreq_init(struct lima_device *ldev)
@@ -125,15 +118,11 @@ int lima_devfreq_init(struct lima_device *ldev)
 
spin_lock_init(>lock);
 
-   opp_table = dev_pm_opp_set_clkname(dev, "core");
-   if (IS_ERR(opp_table)) {
-   ret = PTR_ERR(opp_table);
-   goto err_fini;
-   }
-
-   ldevfreq->clkname_opp_table = opp_table;
+   opp_table = devm_pm_opp_set_clkname(dev, "core");
+   if (IS_ERR(opp_table))
+   return PTR_ERR(opp_table);
 
-   opp_table = dev_pm_opp_set_regulators(dev,
+   opp_table = devm_pm_opp_set_regulators(dev,
  (const char *[]){ "mali" },
  1);
if (IS_ERR(opp_table)) {
@@ -141,24 +130,20 @@ int lima_devfreq_init(struct lima_device *ldev)
 
/* Continue if the optional regulator is missing */
if (ret != -ENODEV)
-   goto err_fini;
-   } else {
-   ldevfreq->regulators_opp_table = opp_table;
+   return ret;
}
 
-   ret = dev_pm_opp_of_add_table(dev);
+   ret = devm_pm_opp_of_add_table(dev);
if (ret)
-   goto err_fini;
+   return ret;
 
lima_devfreq_reset(ldevfreq);
 
cur_freq = clk_get_rate(ldev->clk_gpu);
 
opp = devfreq_recommended_opp(dev, _freq, 0);
-   if (IS_ERR(opp)) {
-   ret = PTR_ERR(opp);
-   goto err_fini;
-   }
+   if (IS_ERR(opp))
+   return PTR_ERR(opp);
 
lima_devfreq_profile.initial_freq = cur_freq;
dev_pm_opp_put(opp);
@@ -167,8 +152,7 @@ int lima_devfreq_init(struct lima_device *ldev)
  DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL);
if (IS_ERR(devfreq)) {
dev_err(dev, "Couldn't initialize GPU devfreq\n");
-   ret = PTR_ERR(devfreq);
-   goto err_fini;
+   return PTR_ERR(devfreq);
}
 
ldevfreq->devfreq = devfreq;
@@ -180,10 +164,6 @@ int lima_devfreq_init(struct lima_device *ldev)
ldevfreq->cooling = cooling;
 
return 0;
-
-err_fini:
-   lima_devfreq_fini(ldev);
-   return ret;
 }
 
 void lima_devfreq_record_busy(struct lima_devfreq *devfreq)
diff --git a/drivers/gpu/drm/lima/lima_devfreq.h 
b/drivers/gpu/drm/lima/lima_devfreq.h
index 2d9b3008ce77..c3bcae76ca07 100644
--- a/drivers/gpu/drm/lima/lima_devfreq.h
+++ b/drivers/gpu/drm/lima/lima_devfreq.h
@@ -15,8 +15,6 @@ struct lima_device;
 
 struct lima_devfreq {
struct devfreq *devfreq;
-   struct opp_table *clkname_opp_table;
-   struct opp_table *regulators_opp_table;
struct thermal_cooling_device *cooling;
 
ktime_t busy_time;
-- 
2.25.1



[PATCH 12/31] mmc: sdhci-msm: convert to use devm_pm_opp_* API

2021-01-01 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code, and remove opp_table
from sdhci_msm_host.

Signed-off-by: Yangtao Li 
---
 drivers/mmc/host/sdhci-msm.c | 19 +++
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 094ef95f5ecc..490ba5d68f72 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -261,7 +261,6 @@ struct sdhci_msm_host {
struct clk_bulk_data bulk_clks[4]; /* core, iface, cal, sleep clocks */
unsigned long clk_rate;
struct mmc_host *mmc;
-   struct opp_table *opp_table;
bool use_14lpp_dll_reset;
bool tuning_done;
bool calibration_done;
@@ -2215,6 +2214,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
const struct sdhci_msm_offset *msm_offset;
const struct sdhci_msm_variant_info *var_info;
struct device_node *node = pdev->dev.of_node;
+   struct opp_table *opp_table;
 
host = sdhci_pltfm_init(pdev, _msm_pdata, sizeof(*msm_host));
if (IS_ERR(host))
@@ -2283,16 +2283,16 @@ static int sdhci_msm_probe(struct platform_device *pdev)
if (ret)
goto bus_clk_disable;
 
-   msm_host->opp_table = dev_pm_opp_set_clkname(>dev, "core");
-   if (IS_ERR(msm_host->opp_table)) {
-   ret = PTR_ERR(msm_host->opp_table);
+   opp_table = devm_pm_opp_set_clkname(>dev, "core");
+   if (IS_ERR(opp_table)) {
+   ret = PTR_ERR(opp_table);
goto bus_clk_disable;
}
 
/* OPP table is optional */
-   ret = dev_pm_opp_of_add_table(>dev);
+   ret = devm_pm_opp_of_add_table(>dev);
if (ret) {
-   dev_pm_opp_put_clkname(msm_host->opp_table);
+   devm_pm_opp_put_clkname(>dev, opp_table);
if (ret != -ENODEV) {
dev_err(>dev, "Invalid OPP table in Device 
tree\n");
goto bus_clk_disable;
@@ -2317,7 +2317,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks),
  msm_host->bulk_clks);
if (ret)
-   goto opp_cleanup;
+   goto bus_clk_disable;
 
/*
 * xo clock is needed for FLL feature of cm_dll.
@@ -2462,9 +2462,6 @@ static int sdhci_msm_probe(struct platform_device *pdev)
 clk_disable:
clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks),
   msm_host->bulk_clks);
-opp_cleanup:
-   dev_pm_opp_of_remove_table(>dev);
-   dev_pm_opp_put_clkname(msm_host->opp_table);
 bus_clk_disable:
if (!IS_ERR(msm_host->bus_clk))
clk_disable_unprepare(msm_host->bus_clk);
@@ -2483,8 +2480,6 @@ static int sdhci_msm_remove(struct platform_device *pdev)
 
sdhci_remove_host(host, dead);
 
-   dev_pm_opp_of_remove_table(>dev);
-   dev_pm_opp_put_clkname(msm_host->opp_table);
pm_runtime_get_sync(>dev);
pm_runtime_disable(>dev);
pm_runtime_put_noidle(>dev);
-- 
2.25.1



[PATCH 14/31] spi: spi-qcom-qspi: convert to use devm_pm_opp_* API

2021-01-01 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code, and remove opp_table
from qcom_qspi.

Signed-off-by: Yangtao Li 
---
 drivers/spi/spi-qcom-qspi.c | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
index 915ae115d8c1..1a1ab153ff59 100644
--- a/drivers/spi/spi-qcom-qspi.c
+++ b/drivers/spi/spi-qcom-qspi.c
@@ -142,7 +142,6 @@ struct qcom_qspi {
struct clk_bulk_data *clks;
struct qspi_xfer xfer;
struct icc_path *icc_path_cpu_to_qspi;
-   struct opp_table *opp_table;
unsigned long last_speed;
/* Lock to protect data accessed by IRQs */
spinlock_t lock;
@@ -459,6 +458,7 @@ static int qcom_qspi_probe(struct platform_device *pdev)
struct device *dev;
struct spi_master *master;
struct qcom_qspi *ctrl;
+   struct opp_table *opp_table;
 
dev = >dev;
 
@@ -531,13 +531,13 @@ static int qcom_qspi_probe(struct platform_device *pdev)
master->handle_err = qcom_qspi_handle_err;
master->auto_runtime_pm = true;
 
-   ctrl->opp_table = dev_pm_opp_set_clkname(>dev, "core");
-   if (IS_ERR(ctrl->opp_table))
-   return PTR_ERR(ctrl->opp_table);
+   opp_table = devm_pm_opp_set_clkname(dev, "core");
+   if (IS_ERR(opp_table))
+   return PTR_ERR(opp_table);
/* OPP table is optional */
-   ret = dev_pm_opp_of_add_table(>dev);
+   ret = devm_pm_opp_of_add_table(dev);
if (ret) {
-   dev_pm_opp_put_clkname(ctrl->opp_table);
+   devm_pm_opp_put_clkname(dev, opp_table);
if (ret != -ENODEV) {
dev_err(>dev, "invalid OPP table in device 
tree\n");
return ret;
@@ -553,8 +553,6 @@ static int qcom_qspi_probe(struct platform_device *pdev)
return 0;
 
pm_runtime_disable(dev);
-   dev_pm_opp_of_remove_table(>dev);
-   dev_pm_opp_put_clkname(ctrl->opp_table);
 
return ret;
 }
@@ -568,8 +566,6 @@ static int qcom_qspi_remove(struct platform_device *pdev)
spi_unregister_master(master);
 
pm_runtime_disable(>dev);
-   dev_pm_opp_of_remove_table(>dev);
-   dev_pm_opp_put_clkname(ctrl->opp_table);
 
return 0;
 }
-- 
2.25.1



[PATCH 16/31] drm/msm: convert to use devm_pm_opp_* API and remove dp_ctrl_put

2021-01-01 Thread Yangtao Li
1. Use devm_pm_opp_* to simplif code and avoid mem leak.
2. Remove opp_table from dpu_kms, dp_ctrl_private and msm_dsi_host,
since it does not need a global scope.
3. Remove dp_ctrl_put.

Signed-off-by: Yangtao Li 
---
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c   |  2 +-
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c   |  2 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.c |  2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 23 
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  2 --
 drivers/gpu/drm/msm/dp/dp_ctrl.c| 29 ++---
 drivers/gpu/drm/msm/dp/dp_ctrl.h|  1 -
 drivers/gpu/drm/msm/dp/dp_display.c |  5 +
 drivers/gpu/drm/msm/dsi/dsi_host.c  | 15 +
 9 files changed, 26 insertions(+), 55 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index a5af223eaf50..47e51c632209 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -1560,7 +1560,7 @@ static void check_speed_bin(struct device *dev)
nvmem_cell_put(cell);
}
 
-   dev_pm_opp_set_supported_hw(dev, , 1);
+   devm_pm_opp_set_supported_hw(dev, , 1);
 }
 
 struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index e6703ae98760..bd159e6fac5a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -1321,7 +1321,7 @@ static int a6xx_gmu_pwrlevels_probe(struct a6xx_gmu *gmu)
 * The GMU handles its own frequency switching so build a list of
 * available frequencies to send during initialization
 */
-   ret = dev_pm_opp_of_add_table(gmu->dev);
+   ret = devm_pm_opp_of_add_table(gmu->dev);
if (ret) {
DRM_DEV_ERROR(gmu->dev, "Unable to set the OPP table for the 
GMU\n");
return ret;
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 6cf9975e951e..e6c446c436e3 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -845,7 +845,7 @@ static void adreno_get_pwrlevels(struct device *dev,
if (!of_find_property(dev->of_node, "operating-points-v2", NULL))
ret = adreno_get_legacy_pwrlevels(dev);
else {
-   ret = dev_pm_opp_of_add_table(dev);
+   ret = devm_pm_opp_of_add_table(dev);
if (ret)
DRM_DEV_ERROR(dev, "Unable to set the OPP table\n");
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 6f19dfcb4965..cb7e4fddf268 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1082,19 +1082,20 @@ static int dpu_bind(struct device *dev, struct device 
*master, void *data)
struct msm_drm_private *priv = ddev->dev_private;
struct dpu_kms *dpu_kms;
struct dss_module_power *mp;
+   struct opp_table *opp_table;
int ret = 0;
 
dpu_kms = devm_kzalloc(>dev, sizeof(*dpu_kms), GFP_KERNEL);
if (!dpu_kms)
return -ENOMEM;
 
-   dpu_kms->opp_table = dev_pm_opp_set_clkname(dev, "core");
-   if (IS_ERR(dpu_kms->opp_table))
-   return PTR_ERR(dpu_kms->opp_table);
+   opp_table = devm_pm_opp_set_clkname(dev, "core");
+   if (IS_ERR(opp_table))
+   return PTR_ERR(opp_table);
/* OPP table is optional */
-   ret = dev_pm_opp_of_add_table(dev);
+   ret = devm_pm_opp_of_add_table(dev);
if (ret) {
-   dev_pm_opp_put_clkname(dpu_kms->opp_table);
+   devm_pm_opp_put_clkname(dev, opp_table);
if (ret != -ENODEV) {
dev_err(dev, "invalid OPP table in device tree\n");
return ret;
@@ -1105,7 +1106,7 @@ static int dpu_bind(struct device *dev, struct device 
*master, void *data)
ret = msm_dss_parse_clock(pdev, mp);
if (ret) {
DPU_ERROR("failed to parse clocks, ret=%d\n", ret);
-   goto err;
+   return ret;
}
 
platform_set_drvdata(pdev, dpu_kms);
@@ -1113,7 +1114,7 @@ static int dpu_bind(struct device *dev, struct device 
*master, void *data)
ret = msm_kms_init(_kms->base, _funcs);
if (ret) {
DPU_ERROR("failed to init kms, ret=%d\n", ret);
-   goto err;
+   return ret;
}
dpu_kms->dev = ddev;
dpu_kms->pdev = pdev;
@@ -1122,10 +1123,7 @@ static int dpu_bind(struct device *dev, struct device 
*master, void *data)
dpu_kms->rpm_enabled = true;
 
priv->kms = _kms->base;
-   return ret;
-err:
-   dev_pm_opp_of_rem

[PATCH 15/31] drm/msm: fix potential mem leak

2021-01-01 Thread Yangtao Li
We should use dev_pm_opp_put_clkname() to free opp table each time
dev_pm_opp_of_add_table() got error.

Signed-off-by: Yangtao Li 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 10 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c  |  8 +---
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 374b0e8471e6..6f19dfcb4965 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1093,9 +1093,12 @@ static int dpu_bind(struct device *dev, struct device 
*master, void *data)
return PTR_ERR(dpu_kms->opp_table);
/* OPP table is optional */
ret = dev_pm_opp_of_add_table(dev);
-   if (ret && ret != -ENODEV) {
-   dev_err(dev, "invalid OPP table in device tree\n");
-   goto put_clkname;
+   if (ret) {
+   dev_pm_opp_put_clkname(dpu_kms->opp_table);
+   if (ret != -ENODEV) {
+   dev_err(dev, "invalid OPP table in device tree\n");
+   return ret;
+   }
}
 
mp = _kms->mp;
@@ -1122,7 +1125,6 @@ static int dpu_bind(struct device *dev, struct device 
*master, void *data)
return ret;
 err:
dev_pm_opp_of_remove_table(dev);
-put_clkname:
dev_pm_opp_put_clkname(dpu_kms->opp_table);
return ret;
 }
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index ab281cba0f08..a282307f2799 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1891,10 +1891,12 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
return PTR_ERR(msm_host->opp_table);
/* OPP table is optional */
ret = dev_pm_opp_of_add_table(>dev);
-   if (ret && ret != -ENODEV) {
-   dev_err(>dev, "invalid OPP table in device tree\n");
+   if (ret) {
dev_pm_opp_put_clkname(msm_host->opp_table);
-   return ret;
+   if (ret != -ENODEV) {
+   dev_err(>dev, "invalid OPP table in device 
tree\n");
+   return ret;
+   }
}
 
init_completion(_host->dma_comp);
-- 
2.25.1



[PATCH 13/31] spi: spi-qcom-qspi: fix potential mem leak in qcom_qspi_probe()

2021-01-01 Thread Yangtao Li
We should use dev_pm_opp_put_clkname() to free opp table each time
dev_pm_opp_of_add_table() got error.

Signed-off-by: Yangtao Li 
---
 drivers/spi/spi-qcom-qspi.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
index 8863be370884..915ae115d8c1 100644
--- a/drivers/spi/spi-qcom-qspi.c
+++ b/drivers/spi/spi-qcom-qspi.c
@@ -536,9 +536,12 @@ static int qcom_qspi_probe(struct platform_device *pdev)
return PTR_ERR(ctrl->opp_table);
/* OPP table is optional */
ret = dev_pm_opp_of_add_table(>dev);
-   if (ret && ret != -ENODEV) {
-   dev_err(>dev, "invalid OPP table in device tree\n");
-   goto exit_probe_put_clkname;
+   if (ret) {
+   dev_pm_opp_put_clkname(ctrl->opp_table);
+   if (ret != -ENODEV) {
+   dev_err(>dev, "invalid OPP table in device 
tree\n");
+   return ret;
+   }
}
 
pm_runtime_use_autosuspend(dev);
@@ -551,8 +554,6 @@ static int qcom_qspi_probe(struct platform_device *pdev)
 
pm_runtime_disable(dev);
dev_pm_opp_of_remove_table(>dev);
-
-exit_probe_put_clkname:
dev_pm_opp_put_clkname(ctrl->opp_table);
 
return ret;
-- 
2.25.1



[PATCH 10/31] qcom-geni-se: remove opp_table

2021-01-01 Thread Yangtao Li
opp_table isn't used anymore, remove it.

Signed-off-by: Yangtao Li 
---
 include/linux/qcom-geni-se.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index ec2ad4b0fe14..cddef864a760 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -47,7 +47,6 @@ struct geni_icc_path {
  * @num_clk_levels:Number of valid clock levels in clk_perf_tbl
  * @clk_perf_tbl:  Table of clock frequency input to serial engine clock
  * @icc_paths: Array of ICC paths for SE
- * @opp_table: Pointer to the OPP table
  */
 struct geni_se {
void __iomem *base;
@@ -57,7 +56,6 @@ struct geni_se {
unsigned int num_clk_levels;
unsigned long *clk_perf_tbl;
struct geni_icc_path icc_paths[3];
-   struct opp_table *opp_table;
 };
 
 /* Common SE registers */
-- 
2.25.1



[PATCH 11/31] mmc: sdhci-msm: fix potential mem leak in sdhci_msm_probe()

2021-01-01 Thread Yangtao Li
We should use dev_pm_opp_put_clkname() to free opp table each time
dev_pm_opp_of_add_table() got error.

Signed-off-by: Yangtao Li 
---
 drivers/mmc/host/sdhci-msm.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 9c7927b03253..094ef95f5ecc 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2291,9 +2291,12 @@ static int sdhci_msm_probe(struct platform_device *pdev)
 
/* OPP table is optional */
ret = dev_pm_opp_of_add_table(>dev);
-   if (ret && ret != -ENODEV) {
-   dev_err(>dev, "Invalid OPP table in Device tree\n");
-   goto opp_put_clkname;
+   if (ret) {
+   dev_pm_opp_put_clkname(msm_host->opp_table);
+   if (ret != -ENODEV) {
+   dev_err(>dev, "Invalid OPP table in Device 
tree\n");
+   goto bus_clk_disable;
+   }
}
 
/* Vote for maximum clock rate for maximum performance */
@@ -2461,7 +2464,6 @@ static int sdhci_msm_probe(struct platform_device *pdev)
   msm_host->bulk_clks);
 opp_cleanup:
dev_pm_opp_of_remove_table(>dev);
-opp_put_clkname:
dev_pm_opp_put_clkname(msm_host->opp_table);
 bus_clk_disable:
if (!IS_ERR(msm_host->bus_clk))
-- 
2.25.1



[PATCH 09/31] spi: spi-qcom-qspi: fix potential mem leak in spi_geni_probe()

2021-01-01 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code, and we don't need
to make opp_table glabal.

Let's remove opp_table from geni_se later.

Signed-off-by: Yangtao Li 
---
 drivers/spi/spi-geni-qcom.c | 15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 2b5a164fecb9..e330c46a9243 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -590,6 +590,7 @@ static int spi_geni_probe(struct platform_device *pdev)
void __iomem *base;
struct clk *clk;
struct device *dev = >dev;
+   struct opp_table *opp_table;
 
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -615,13 +616,13 @@ static int spi_geni_probe(struct platform_device *pdev)
mas->se.wrapper = dev_get_drvdata(dev->parent);
mas->se.base = base;
mas->se.clk = clk;
-   mas->se.opp_table = dev_pm_opp_set_clkname(>dev, "se");
-   if (IS_ERR(mas->se.opp_table))
-   return PTR_ERR(mas->se.opp_table);
+   opp_table = devm_pm_opp_set_clkname(dev, "se");
+   if (IS_ERR(opp_table))
+   return PTR_ERR(opp_table);
/* OPP table is optional */
-   ret = dev_pm_opp_of_add_table(>dev);
+   ret = devm_pm_opp_of_add_table(dev);
if (ret) {
-   dev_pm_opp_put_clkname(mas->se.opp_table);
+   devm_pm_opp_put_clkname(dev, opp_table);
if (ret != -ENODEV) {
dev_err(>dev, "invalid OPP table in device 
tree\n");
return ret;
@@ -677,8 +678,6 @@ static int spi_geni_probe(struct platform_device *pdev)
free_irq(mas->irq, spi);
 spi_geni_probe_runtime_disable:
pm_runtime_disable(dev);
-   dev_pm_opp_of_remove_table(>dev);
-   dev_pm_opp_put_clkname(mas->se.opp_table);
return ret;
 }
 
@@ -692,8 +691,6 @@ static int spi_geni_remove(struct platform_device *pdev)
 
free_irq(mas->irq, spi);
pm_runtime_disable(>dev);
-   dev_pm_opp_of_remove_table(>dev);
-   dev_pm_opp_put_clkname(mas->se.opp_table);
return 0;
 }
 
-- 
2.25.1



[PATCH 08/31] spi: spi-qcom-qspi: fix potential mem leak in spi_geni_probe()

2021-01-01 Thread Yangtao Li
We should use dev_pm_opp_put_clkname() to free opp table each time
dev_pm_opp_of_add_table() got error.

Signed-off-by: Yangtao Li 
---
 drivers/spi/spi-geni-qcom.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 512e925d5ea4..2b5a164fecb9 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -620,9 +620,12 @@ static int spi_geni_probe(struct platform_device *pdev)
return PTR_ERR(mas->se.opp_table);
/* OPP table is optional */
ret = dev_pm_opp_of_add_table(>dev);
-   if (ret && ret != -ENODEV) {
-   dev_err(>dev, "invalid OPP table in device tree\n");
-   goto put_clkname;
+   if (ret) {
+   dev_pm_opp_put_clkname(mas->se.opp_table);
+   if (ret != -ENODEV) {
+   dev_err(>dev, "invalid OPP table in device 
tree\n");
+   return ret;
+   }
}
 
spi->bus_num = -1;
@@ -675,7 +678,6 @@ static int spi_geni_probe(struct platform_device *pdev)
 spi_geni_probe_runtime_disable:
pm_runtime_disable(dev);
dev_pm_opp_of_remove_table(>dev);
-put_clkname:
dev_pm_opp_put_clkname(mas->se.opp_table);
return ret;
 }
-- 
2.25.1



[PATCH 07/31] serial: qcom_geni_serial: convert to use devm_pm_opp_* API

2021-01-01 Thread Yangtao Li
Use devm_pm_opp_* API to simplify code, and we don't need
to make opp_table glabal.

Let's remove opp_table from geni_se later.

Signed-off-by: Yangtao Li 
---
 drivers/tty/serial/qcom_geni_serial.c | 23 +--
 1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/drivers/tty/serial/qcom_geni_serial.c 
b/drivers/tty/serial/qcom_geni_serial.c
index 5aada7ebae35..36a92df8ec11 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -1352,6 +1352,7 @@ static int qcom_geni_serial_probe(struct platform_device 
*pdev)
int irq;
bool console = false;
struct uart_driver *drv;
+   struct opp_table *opp_table;
 
if (of_device_is_compatible(pdev->dev.of_node, "qcom,geni-debug-uart"))
console = true;
@@ -1433,13 +1434,13 @@ static int qcom_geni_serial_probe(struct 
platform_device *pdev)
if (of_property_read_bool(pdev->dev.of_node, "cts-rts-swap"))
port->cts_rts_swap = true;
 
-   port->se.opp_table = dev_pm_opp_set_clkname(>dev, "se");
-   if (IS_ERR(port->se.opp_table))
-   return PTR_ERR(port->se.opp_table);
+   opp_table = devm_pm_opp_set_clkname(>dev, "se");
+   if (IS_ERR(opp_table))
+   return PTR_ERR(opp_table);
/* OPP table is optional */
-   ret = dev_pm_opp_of_add_table(>dev);
+   ret = devm_pm_opp_of_add_table(>dev);
if (ret) {
-   dev_pm_opp_put_clkname(port->se.opp_table);
+   devm_pm_opp_put_clkname(>dev, opp_table);
if (ret != -ENODEV) {
dev_err(>dev, "invalid OPP table in device 
tree\n");
return ret;
@@ -1453,7 +1454,7 @@ static int qcom_geni_serial_probe(struct platform_device 
*pdev)
 
ret = uart_add_one_port(drv, uport);
if (ret)
-   goto err;
+   return ret;
 
irq_set_status_flags(uport->irq, IRQ_NOAUTOEN);
ret = devm_request_irq(uport->dev, uport->irq, qcom_geni_serial_isr,
@@ -1461,7 +1462,7 @@ static int qcom_geni_serial_probe(struct platform_device 
*pdev)
if (ret) {
dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret);
uart_remove_one_port(drv, uport);
-   goto err;
+   return ret;
}
 
/*
@@ -1478,15 +1479,11 @@ static int qcom_geni_serial_probe(struct 
platform_device *pdev)
if (ret) {
device_init_wakeup(>dev, false);
uart_remove_one_port(drv, uport);
-   goto err;
+   return ret;
}
}
 
return 0;
-err:
-   dev_pm_opp_of_remove_table(>dev);
-   dev_pm_opp_put_clkname(port->se.opp_table);
-   return ret;
 }
 
 static int qcom_geni_serial_remove(struct platform_device *pdev)
@@ -1494,8 +1491,6 @@ static int qcom_geni_serial_remove(struct platform_device 
*pdev)
struct qcom_geni_serial_port *port = platform_get_drvdata(pdev);
struct uart_driver *drv = port->private_data.drv;
 
-   dev_pm_opp_of_remove_table(>dev);
-   dev_pm_opp_put_clkname(port->se.opp_table);
dev_pm_clear_wake_irq(>dev);
device_init_wakeup(>dev, false);
uart_remove_one_port(drv, >uport);
-- 
2.25.1



[PATCH 06/31] serial: qcom_geni_serial: fix potential mem leak in qcom_geni_serial_probe()

2021-01-01 Thread Yangtao Li
We should use dev_pm_opp_put_clkname() to free opp table each time
dev_pm_opp_of_add_table() got error.

Signed-off-by: Yangtao Li 
---
 drivers/tty/serial/qcom_geni_serial.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/qcom_geni_serial.c 
b/drivers/tty/serial/qcom_geni_serial.c
index 291649f02821..5aada7ebae35 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -1438,9 +1438,12 @@ static int qcom_geni_serial_probe(struct platform_device 
*pdev)
return PTR_ERR(port->se.opp_table);
/* OPP table is optional */
ret = dev_pm_opp_of_add_table(>dev);
-   if (ret && ret != -ENODEV) {
-   dev_err(>dev, "invalid OPP table in device tree\n");
-   goto put_clkname;
+   if (ret) {
+   dev_pm_opp_put_clkname(port->se.opp_table);
+   if (ret != -ENODEV) {
+   dev_err(>dev, "invalid OPP table in device 
tree\n");
+   return ret;
+   }
}
 
port->private_data.drv = drv;
@@ -1482,7 +1485,6 @@ static int qcom_geni_serial_probe(struct platform_device 
*pdev)
return 0;
 err:
dev_pm_opp_of_remove_table(>dev);
-put_clkname:
dev_pm_opp_put_clkname(port->se.opp_table);
return ret;
 }
-- 
2.25.1



[PATCH 05/31] opp: Add devres wrapper for dev_pm_opp_register_notifier

2021-01-01 Thread Yangtao Li
Add devres wrapper for dev_pm_opp_register_notifier() to simplify driver
code.

Signed-off-by: Yangtao Li 
---
 drivers/opp/core.c | 38 ++
 include/linux/pm_opp.h |  6 ++
 2 files changed, 44 insertions(+)

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 6b83e373f0d8..ef3544f8cecd 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -2599,6 +2599,44 @@ int dev_pm_opp_unregister_notifier(struct device *dev,
 }
 EXPORT_SYMBOL(dev_pm_opp_unregister_notifier);
 
+static void devm_pm_opp_notifier_release(struct device *dev, void *res)
+{
+   struct notifier_block *nb = *(struct notifier_block **)res;
+
+   WARN_ON(dev_pm_opp_unregister_notifier(dev, nb));
+}
+
+/**
+ * devm_pm_opp_register_notifier() - Register OPP notifier for the device
+ * @dev:   Device for which notifier needs to be registered
+ * @nb:Notifier block to be registered
+ *
+ * Return: 0 on success or a negative error value.
+ *
+ * The notifier will be unregistered after the device is destroyed.
+ */
+int devm_pm_opp_register_notifier(struct device *dev, struct notifier_block 
*nb)
+{
+   struct notifier_block **ptr;
+   int ret;
+
+   ptr = devres_alloc(devm_pm_opp_notifier_release, sizeof(*ptr), 
GFP_KERNEL);
+   if (!ptr)
+   return -ENOMEM;
+
+   ret = dev_pm_opp_register_notifier(dev, nb);
+   if (ret) {
+   devres_free(ptr);
+   return ret;
+   }
+
+   *ptr = nb;
+   devres_add(dev, ptr);
+
+   return 0;
+}
+EXPORT_SYMBOL(devm_pm_opp_register_notifier);
+
 /**
  * dev_pm_opp_remove_table() - Free all OPPs associated with the device
  * @dev:   device pointer used to lookup OPP table.
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index e8bdac5f9555..c24bd34339d7 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -136,6 +136,7 @@ int dev_pm_opp_disable(struct device *dev, unsigned long 
freq);
 
 int dev_pm_opp_register_notifier(struct device *dev, struct notifier_block 
*nb);
 int dev_pm_opp_unregister_notifier(struct device *dev, struct notifier_block 
*nb);
+int devm_pm_opp_register_notifier(struct device *dev, struct notifier_block 
*nb);
 
 struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev, const u32 
*versions, unsigned int count);
 void dev_pm_opp_put_supported_hw(struct opp_table *opp_table);
@@ -288,6 +289,11 @@ static inline int dev_pm_opp_register_notifier(struct 
device *dev, struct notifi
return -ENOTSUPP;
 }
 
+static inline int devm_pm_opp_register_notifier(struct device *dev, struct 
notifier_block *nb)
+{
+   return -ENOTSUPP;
+}
+
 static inline int dev_pm_opp_unregister_notifier(struct device *dev, struct 
notifier_block *nb)
 {
return -ENOTSUPP;
-- 
2.25.1



[PATCH 04/31] opp: Add devres wrapper for dev_pm_opp_of_add_table

2021-01-01 Thread Yangtao Li
Add devres wrapper for dev_pm_opp_of_add_table() to simplify driver
code.

Signed-off-by: Yangtao Li 
---
 drivers/opp/of.c   | 36 
 include/linux/pm_opp.h |  6 ++
 2 files changed, 42 insertions(+)

diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 03cb387236c4..50df483c7dc3 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -998,6 +998,42 @@ int dev_pm_opp_of_add_table(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table);
 
+static void devm_pm_opp_of_table_release(void *data)
+{
+   dev_pm_opp_of_remove_table(data);
+}
+
+/**
+ * devm_pm_opp_of_add_table() - Initialize opp table from device tree
+ * @dev:   device pointer used to lookup OPP table.
+ *
+ * Register the initial OPP table with the OPP library for given device.
+ *
+ * The opp_table structure will be freed after the device is destroyed.
+ *
+ * Return:
+ * 0   On success OR
+ * Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST Freq are same and volt are different OR
+ * Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM Memory allocation failure
+ * -ENODEV when 'operating-points' property is not found or is invalid data
+ * in device node.
+ * -ENODATAwhen empty 'operating-points' property is found
+ * -EINVAL when invalid entries are found in opp-v2 table
+ */
+int devm_pm_opp_of_add_table(struct device *dev)
+{
+   int ret;
+
+   ret = dev_pm_opp_of_add_table(dev);
+   if (ret)
+   return ret;
+
+   return devm_add_action_or_reset(dev, devm_pm_opp_of_table_release, dev);
+}
+EXPORT_SYMBOL_GPL(devm_pm_opp_of_add_table);
+
 /**
  * dev_pm_opp_of_add_table_indexed() - Initialize indexed opp table from 
device tree
  * @dev:   device pointer used to lookup OPP table.
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index e5260fc82ba1..e8bdac5f9555 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -398,6 +398,7 @@ static inline void dev_pm_opp_cpumask_remove_table(const 
struct cpumask *cpumask
 int dev_pm_opp_of_add_table(struct device *dev);
 int dev_pm_opp_of_add_table_indexed(struct device *dev, int index);
 void dev_pm_opp_of_remove_table(struct device *dev);
+int devm_pm_opp_of_add_table(struct device *dev);
 int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask);
 void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask);
 int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, struct cpumask 
*cpumask);
@@ -425,6 +426,11 @@ static inline void dev_pm_opp_of_remove_table(struct 
device *dev)
 {
 }
 
+static inline int devm_pm_opp_of_add_table(struct device *dev)
+{
+   return -ENOTSUPP;
+}
+
 static inline int dev_pm_opp_of_cpumask_add_table(const struct cpumask 
*cpumask)
 {
return -ENOTSUPP;
-- 
2.25.1



[PATCH 03/31] opp: Add devres wrapper for dev_pm_opp_set_supported_hw

2021-01-01 Thread Yangtao Li
Add devres wrapper for dev_pm_opp_set_supported_hw() to simplify driver
code.

Signed-off-by: Yangtao Li 
---
 drivers/opp/core.c | 38 ++
 include/linux/pm_opp.h |  8 
 2 files changed, 46 insertions(+)

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 8709689a7152..6b83e373f0d8 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -1674,6 +1674,44 @@ void dev_pm_opp_put_supported_hw(struct opp_table 
*opp_table)
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_put_supported_hw);
 
+static void devm_pm_opp_supported_hw_release(void *data)
+{
+   dev_pm_opp_put_supported_hw(data);
+}
+
+/**
+ * devm_pm_opp_set_supported_hw() - Set supported platforms
+ * @dev: Device for which supported-hw has to be set.
+ * @versions: Array of hierarchy of versions to match.
+ * @count: Number of elements in the array.
+ *
+ * This is required only for the V2 bindings, and it enables a platform to
+ * specify the hierarchy of versions it supports. OPP layer will then enable
+ * OPPs, which are available for those versions, based on its 
'opp-supported-hw'
+ * property.
+ *
+ * The opp_table structure will be freed after the device is destroyed.
+ */
+struct opp_table *devm_pm_opp_set_supported_hw(struct device *dev,
+  const u32 *versions,
+  unsigned int count)
+{
+   struct opp_table *opp_table;
+   int err;
+
+   opp_table = dev_pm_opp_set_supported_hw(dev, versions, count);
+   if (IS_ERR(opp_table))
+   return opp_table;
+
+   err = devm_add_action_or_reset(dev, devm_pm_opp_supported_hw_release,
+  opp_table);
+   if (err)
+   opp_table = ERR_PTR(err);
+
+   return opp_table;
+}
+EXPORT_SYMBOL_GPL(devm_pm_opp_set_supported_hw);
+
 /**
  * dev_pm_opp_set_prop_name() - Set prop-extn name
  * @dev: Device for which the prop-name has to be set.
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 8a329247e08e..e5260fc82ba1 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -139,6 +139,7 @@ int dev_pm_opp_unregister_notifier(struct device *dev, 
struct notifier_block *nb
 
 struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev, const u32 
*versions, unsigned int count);
 void dev_pm_opp_put_supported_hw(struct opp_table *opp_table);
+struct opp_table *devm_pm_opp_set_supported_hw(struct device *dev, const u32 
*versions, unsigned int count);
 struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char 
*name);
 void dev_pm_opp_put_prop_name(struct opp_table *opp_table);
 struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * 
const names[], unsigned int count);
@@ -301,6 +302,13 @@ static inline struct opp_table 
*dev_pm_opp_set_supported_hw(struct device *dev,
 
 static inline void dev_pm_opp_put_supported_hw(struct opp_table *opp_table) {}
 
+static inline struct opp_table *devm_pm_opp_set_supported_hw(struct device 
*dev,
+   const u32 *versions,
+   unsigned int count)
+{
+   return ERR_PTR(-ENOTSUPP);
+}
+
 static inline struct opp_table *dev_pm_opp_register_set_opp_helper(struct 
device *dev,
int (*set_opp)(struct dev_pm_set_opp_data *data))
 {
-- 
2.25.1



[PATCH 02/31] opp: Add devres wrapper for dev_pm_opp_set_regulators and dev_pm_opp_put_regulators

2021-01-01 Thread Yangtao Li
Add devres wrapper for dev_pm_opp_set_regulators()
dev_pm_opp_put_regulators () to simplify driver code.

Signed-off-by: Yangtao Li 
---
 drivers/opp/core.c | 50 ++
 include/linux/pm_opp.h |  9 
 2 files changed, 59 insertions(+)

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 53fdf33732d5..8709689a7152 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -1878,6 +1878,56 @@ void dev_pm_opp_put_regulators(struct opp_table 
*opp_table)
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulators);
 
+static void devm_pm_opp_regulators_release(void *data)
+{
+   dev_pm_opp_put_regulators(data);
+}
+
+/**
+ * devm_pm_opp_set_regulators() - Set regulator names for the device
+ * @dev: Device for which regulator name is being set.
+ * @names: Array of pointers to the names of the regulator.
+ * @count: Number of regulators.
+ *
+ * In order to support OPP switching, OPP layer needs to know the name of the
+ * device's regulators, as the core would be required to switch voltages as
+ * well.
+ *
+ * This must be called before any OPPs are initialized for the device.
+ *
+ * The opp_table structure will be freed after the device is destroyed.
+ */
+struct opp_table *devm_pm_opp_set_regulators(struct device *dev,
+   const char * const names[],
+   unsigned int count)
+{
+   struct opp_table *opp_table;
+   int err;
+
+   opp_table = dev_pm_opp_set_regulators(dev, names, count);
+   if (IS_ERR(opp_table))
+   return opp_table;
+
+   err = devm_add_action_or_reset(dev, devm_pm_opp_regulators_release,
+  opp_table);
+   if (err)
+   opp_table = ERR_PTR(err);
+
+   return opp_table;
+}
+EXPORT_SYMBOL_GPL(devm_pm_opp_set_regulators);
+
+/**
+ * devm_pm_opp_put_regulators() - Releases resources blocked for regulator
+ * @dev: Device for which we do this operation.
+ * @opp_table: OPP table returned from dev_pm_opp_set_regulators().
+ */
+void devm_pm_opp_put_regulators(struct device *dev, struct opp_table 
*opp_table)
+{
+   devm_release_action(dev, devm_pm_opp_regulators_release, opp_table);
+}
+EXPORT_SYMBOL_GPL(devm_pm_opp_put_regulators);
+
 /**
  * dev_pm_opp_set_clkname() - Set clk name for the device
  * @dev: Device for which clk name is being set.
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 3418a2874f88..8a329247e08e 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -143,6 +143,8 @@ struct opp_table *dev_pm_opp_set_prop_name(struct device 
*dev, const char *name)
 void dev_pm_opp_put_prop_name(struct opp_table *opp_table);
 struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * 
const names[], unsigned int count);
 void dev_pm_opp_put_regulators(struct opp_table *opp_table);
+struct opp_table *devm_pm_opp_set_regulators(struct device *dev, const char * 
const names[], unsigned int count);
+void devm_pm_opp_put_regulators(struct device *dev, struct opp_table 
*opp_table);
 struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * 
name);
 void dev_pm_opp_put_clkname(struct opp_table *opp_table);
 struct opp_table *devm_pm_opp_set_clkname(struct device *dev, const char 
*name);
@@ -321,6 +323,13 @@ static inline struct opp_table 
*dev_pm_opp_set_regulators(struct device *dev, co
 
 static inline void dev_pm_opp_put_regulators(struct opp_table *opp_table) {}
 
+static inline struct opp_table *devm_pm_opp_set_regulators(struct device *dev, 
const char * const names[], unsigned int count)
+{
+   return ERR_PTR(-ENOTSUPP);
+}
+
+static inline void devm_pm_opp_put_regulators(struct device *dev, struct 
opp_table *opp_table) {}
+
 static inline struct opp_table *dev_pm_opp_set_clkname(struct device *dev, 
const char * name)
 {
return ERR_PTR(-ENOTSUPP);
-- 
2.25.1



[PATCH 01/31] opp: Add devres wrapper for dev_pm_opp_set_clkname and dev_pm_opp_put_clkname

2021-01-01 Thread Yangtao Li
Add devres wrapper for dev_pm_opp_set_clkname() and
dev_pm_opp_put_clkname() to simplify driver code.

Signed-off-by: Yangtao Li 
---
 drivers/opp/core.c | 47 ++
 include/linux/pm_opp.h |  9 
 2 files changed, 56 insertions(+)

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 4268eb359915..53fdf33732d5 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -1948,6 +1948,53 @@ void dev_pm_opp_put_clkname(struct opp_table *opp_table)
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_put_clkname);
 
+static void devm_pm_opp_clkname_release(void *data)
+{
+   dev_pm_opp_put_clkname(data);
+}
+
+/**
+ * devm_pm_opp_set_clkname() - Set clk name for the device
+ * @dev: Device for which clk name is being set.
+ * @name: Clk name.
+ *
+ * In order to support OPP switching, OPP layer needs to get pointer to the
+ * clock for the device. Simple cases work fine without using this routine 
(i.e.
+ * by passing connection-id as NULL), but for a device with multiple clocks
+ * available, the OPP core needs to know the exact name of the clk to use.
+ *
+ * This must be called before any OPPs are initialized for the device.
+ *
+ * The opp_table structure will be freed after the device is destroyed.
+ */
+struct opp_table *devm_pm_opp_set_clkname(struct device *dev, const char *name)
+{
+   struct opp_table *opp_table;
+   int err;
+
+   opp_table = dev_pm_opp_set_clkname(dev, name);
+   if (IS_ERR(opp_table))
+   return opp_table;
+
+   err = devm_add_action_or_reset(dev, devm_pm_opp_clkname_release, 
opp_table);
+   if (err)
+   opp_table = ERR_PTR(err);
+
+   return opp_table;
+}
+EXPORT_SYMBOL_GPL(devm_pm_opp_set_clkname);
+
+/**
+ * devm_pm_opp_put_clkname() - Releases resources blocked for clk.
+ * @dev: Device for which we do this operation.
+ * @opp_table: OPP table returned from devm_pm_opp_set_clkname().
+ */
+void devm_pm_opp_put_clkname(struct device *dev, struct opp_table *opp_table)
+{
+   devm_release_action(dev, devm_pm_opp_clkname_release, opp_table);
+}
+EXPORT_SYMBOL_GPL(devm_pm_opp_put_clkname);
+
 /**
  * dev_pm_opp_register_set_opp_helper() - Register custom set OPP helper
  * @dev: Device for which the helper is getting registered.
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 1435c054016a..3418a2874f88 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -145,6 +145,8 @@ struct opp_table *dev_pm_opp_set_regulators(struct device 
*dev, const char * con
 void dev_pm_opp_put_regulators(struct opp_table *opp_table);
 struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * 
name);
 void dev_pm_opp_put_clkname(struct opp_table *opp_table);
+struct opp_table *devm_pm_opp_set_clkname(struct device *dev, const char 
*name);
+void devm_pm_opp_put_clkname(struct device *dev, struct opp_table *opp_table);
 struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev, int 
(*set_opp)(struct dev_pm_set_opp_data *data));
 void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table);
 struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char 
**names, struct device ***virt_devs);
@@ -326,6 +328,13 @@ static inline struct opp_table 
*dev_pm_opp_set_clkname(struct device *dev, const
 
 static inline void dev_pm_opp_put_clkname(struct opp_table *opp_table) {}
 
+static inline struct opp_table *devm_pm_opp_set_clkname(struct device *dev, 
const char *name)
+{
+   return ERR_PTR(-ENOTSUPP);
+}
+
+static inline void devm_pm_opp_put_clkname(struct device *dev, struct 
opp_table *opp_table) {}
+
 static inline struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, 
const char **names, struct device ***virt_devs)
 {
return ERR_PTR(-ENOTSUPP);
-- 
2.25.1



[PATCH 00/31] Introduce devm_pm_opp_* API

2021-01-01 Thread Yangtao Li
Hi,

This patchset add devm_pm_opp_set_clkname, devm_pm_opp_put_clkname,
devm_pm_opp_set_regulators, devm_pm_opp_put_regulators,
devm_pm_opp_set_supported_hw, devm_pm_opp_of_add_table and
devm_pm_opp_register_notifier.

Yangtao Li (31):
  opp: Add devres wrapper for dev_pm_opp_set_clkname and
dev_pm_opp_put_clkname
  opp: Add devres wrapper for dev_pm_opp_set_regulators and
dev_pm_opp_put_regulators
  opp: Add devres wrapper for dev_pm_opp_set_supported_hw
  opp: Add devres wrapper for dev_pm_opp_of_add_table
  opp: Add devres wrapper for dev_pm_opp_register_notifier
  serial: qcom_geni_serial: fix potential mem leak in
qcom_geni_serial_probe()
  serial: qcom_geni_serial: convert to use devm_pm_opp_* API
  spi: spi-qcom-qspi: fix potential mem leak in spi_geni_probe()
  spi: spi-qcom-qspi: fix potential mem leak in spi_geni_probe()
  qcom-geni-se: remove opp_table
  mmc: sdhci-msm: fix potential mem leak in sdhci_msm_probe()
  mmc: sdhci-msm: convert to use devm_pm_opp_* API
  spi: spi-qcom-qspi: fix potential mem leak in qcom_qspi_probe()
  spi: spi-qcom-qspi: convert to use devm_pm_opp_* API
  drm/msm: fix potential mem leak
  drm/msm: convert to use devm_pm_opp_* API and remove dp_ctrl_put
  drm/lima: convert to use devm_pm_opp_* API
  drm/lima: remove unneeded devm_devfreq_remove_device()
  drm/panfrost: convert to use devm_pm_opp_* API
  media: venus: fix error check in core_get_v4()
  media: venus: convert to use devm_pm_opp_* API
  memory: samsung: exynos5422-dmc: fix return error in
exynos5_init_freq_table
  memory: samsung: exynos5422-dmc: convert to use devm_pm_opp_* API
  memory: tegra20: convert to use devm_pm_opp_* API
  memory: tegra30: convert to use devm_pm_opp_* API
  PM / devfreq: tegra30: convert to use devm_pm_opp_* API
  PM / devfreq: rk3399_dmc: convert to use devm_pm_opp_* API
  PM / devfreq: imx8m-ddrc: convert to use devm_pm_opp_* API
  PM / devfreq: imx-bus: convert to use devm_pm_opp_* API
  PM / devfreq: exynos: convert to use devm_pm_opp_* API
  PM / devfreq: convert to devm_pm_opp_register_notifier and remove
unused API

 drivers/devfreq/devfreq.c |  66 +--
 drivers/devfreq/exynos-bus.c  |  42 +
 drivers/devfreq/imx-bus.c |  14 +-
 drivers/devfreq/imx8m-ddrc.c  |  15 +-
 drivers/devfreq/rk3399_dmc.c  |  22 +--
 drivers/devfreq/tegra30-devfreq.c |  21 +--
 drivers/gpu/drm/lima/lima_devfreq.c   |  45 +
 drivers/gpu/drm/lima/lima_devfreq.h   |   2 -
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c |   2 +-
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c |   2 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.c   |   2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  31 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   2 -
 drivers/gpu/drm/msm/dp/dp_ctrl.c  |  29 +--
 drivers/gpu/drm/msm/dp/dp_ctrl.h  |   1 -
 drivers/gpu/drm/msm/dp/dp_display.c   |   5 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c|  23 ++-
 drivers/gpu/drm/panfrost/panfrost_devfreq.c   |  34 +---
 drivers/gpu/drm/panfrost/panfrost_devfreq.h   |   1 -
 .../media/platform/qcom/venus/pm_helpers.c|  22 +--
 drivers/memory/samsung/exynos5422-dmc.c   |  13 +-
 drivers/memory/tegra/tegra20-emc.c|  29 +--
 drivers/memory/tegra/tegra30-emc.c|  29 +--
 drivers/mmc/host/sdhci-msm.c  |  27 ++-
 drivers/opp/core.c| 173 ++
 drivers/opp/of.c  |  36 
 drivers/spi/spi-geni-qcom.c   |  23 ++-
 drivers/spi/spi-qcom-qspi.c   |  25 ++-
 drivers/tty/serial/qcom_geni_serial.c |  31 ++--
 include/linux/devfreq.h   |  23 ---
 include/linux/pm_opp.h|  38 
 include/linux/qcom-geni-se.h  |   2 -
 32 files changed, 402 insertions(+), 428 deletions(-)

-- 
2.25.1



[PATCH v5 13/18] thermal: sun8i: add thermal driver for A64

2019-08-09 Thread Yangtao Li
From: Vasily Khoruzhick 

Thermal sensor controller in A64 is similar to H3, but it has 3 sensors.
Extend H3 functions to add support for multiple sensors.

Signed-off-by: Vasily Khoruzhick 
---
 drivers/thermal/sun8i_thermal.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 41ce8cdc0546..3259081da841 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -515,6 +515,17 @@ static const struct ths_thermal_chip sun8i_h3_ths = {
.irq_ack = sun8i_h3_irq_ack,
 };
 
+static const struct ths_thermal_chip sun50i_a64_ths = {
+   .sensor_num = 3,
+   .offset = -2170,
+   .scale = -117,
+   .has_mod_clk = true,
+   .temp_data_base = SUN8I_THS_TEMP_DATA,
+   .calibrate = sun8i_h3_ths_calibrate,
+   .init = sun8i_h3_thermal_init,
+   .irq_ack = sun8i_h3_irq_ack,
+};
+
 static const struct ths_thermal_chip sun50i_h6_ths = {
.sensor_num = 2,
.offset = -2794,
@@ -528,6 +539,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 
 static const struct of_device_id of_ths_match[] = {
{ .compatible = "allwinner,sun8i-h3-ths", .data = _h3_ths },
+   { .compatible = "allwinner,sun50i-a64-ths", .data = _a64_ths },
{ .compatible = "allwinner,sun50i-h6-ths", .data = _h6_ths },
{ /* sentinel */ },
 };
-- 
2.17.1



[PATCH v5 18/18] thermal: sun8i: add support for Allwinner R40 thermal sensor

2019-08-09 Thread Yangtao Li
From: Icenowy Zheng 

The thermal sensor in Allwinner R40 SoC is quite similar to the one in
Allwinner A64 SoC, with only slightly different temperature calculation
formula.

Signed-off-by: Icenowy Zheng 
---
 drivers/thermal/sun8i_thermal.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 78a888d85cba..0de9a56c3775 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -529,6 +529,17 @@ static const struct ths_thermal_chip sun8i_h3_ths = {
.irq_ack = sun8i_h3_irq_ack,
 };
 
+static const struct ths_thermal_chip sun8i_r40_ths = {
+   .sensor_num = 3,
+   .offset = -,
+   .scale = -113,
+   .has_mod_clk = true,
+   .temp_data_base = SUN8I_THS_TEMP_DATA,
+   .calibrate = sun8i_h3_ths_calibrate,
+   .init = sun8i_h3_thermal_init,
+   .irq_ack = sun8i_h3_irq_ack,
+};
+
 static const struct ths_thermal_chip sun50i_a64_ths = {
.sensor_num = 3,
.offset = -2170,
@@ -563,6 +574,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 
 static const struct of_device_id of_ths_match[] = {
{ .compatible = "allwinner,sun8i-h3-ths", .data = _h3_ths },
+   { .compatible = "allwinner,sun8i-r40-ths", .data = _r40_ths },
{ .compatible = "allwinner,sun50i-a64-ths", .data = _a64_ths },
{ .compatible = "allwinner,sun50i-h5-ths", .data = _h5_ths },
{ .compatible = "allwinner,sun50i-h6-ths", .data = _h6_ths },
-- 
2.17.1



[PATCH v5 17/18] dt-bindings: thermal: add binding document for r40 thermal controller

2019-08-09 Thread Yangtao Li
This patch adds binding document for allwinner r40 thermal controller.

Signed-off-by: Yangtao Li 
---
 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml 
b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
index 2e28f5b33d33..28c438d3bfea 100644
--- a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -17,6 +17,7 @@ properties:
   compatible:
 enum:
   - allwinner,sun8i-h3-ths
+  - allwinner,sun8i-r40-ths
   - allwinner,sun50i-a64-ths
   - allwinner,sun50i-h5-ths
   - allwinner,sun50i-h6-ths
-- 
2.17.1



[PATCH v5 16/18] thermal: sun8i: add support for Allwinner H5 thermal sensor

2019-08-09 Thread Yangtao Li
From: Icenowy Zheng 

The thermal sensor in Allwinner H5 has 2 sensors, and they have a
special segmented temperature calculation formula.

Add support for this thermal sensor.

Signed-off-by: Icenowy Zheng 
---
 drivers/thermal/sun8i_thermal.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index a761e2afda08..78a888d85cba 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -99,6 +99,16 @@ static int sun8i_ths_reg2temp(struct ths_device *tmdev,
return (reg + tmdev->chip->offset) * tmdev->chip->scale;
 }
 
+static int sun50i_h5_calc_temp(int id, int reg)
+{
+   if (reg >= 0x500)
+   return -1191 * reg / 10 + 223000;
+   else if (!id)
+   return -1452 * reg / 10 + 259000;
+   else
+   return -1590 * reg / 10 + 276000;
+}
+
 static int sun8i_ths_get_temp(void *data, int *temp)
 {
struct tsensor *s = data;
@@ -530,6 +540,16 @@ static const struct ths_thermal_chip sun50i_a64_ths = {
.irq_ack = sun8i_h3_irq_ack,
 };
 
+static const struct ths_thermal_chip sun50i_h5_ths = {
+   .sensor_num = 2,
+   .has_mod_clk = true,
+   .temp_data_base = SUN8I_THS_TEMP_DATA,
+   .calibrate = sun8i_h3_ths_calibrate,
+   .init = sun8i_h3_thermal_init,
+   .irq_ack = sun8i_h3_irq_ack,
+   .calc_temp = sun50i_h5_calc_temp,
+};
+
 static const struct ths_thermal_chip sun50i_h6_ths = {
.sensor_num = 2,
.offset = -2794,
@@ -544,6 +564,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 static const struct of_device_id of_ths_match[] = {
{ .compatible = "allwinner,sun8i-h3-ths", .data = _h3_ths },
{ .compatible = "allwinner,sun50i-a64-ths", .data = _a64_ths },
+   { .compatible = "allwinner,sun50i-h5-ths", .data = _h5_ths },
{ .compatible = "allwinner,sun50i-h6-ths", .data = _h6_ths },
{ /* sentinel */ },
 };
-- 
2.17.1



[PATCH v5 03/18] thermal: fix indentation in makefile

2019-08-09 Thread Yangtao Li
To unify code style.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/Makefile | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index fa6f8b206281..d7eafb5ef8ef 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -5,7 +5,7 @@
 
 obj-$(CONFIG_THERMAL)  += thermal_sys.o
 thermal_sys-y  += thermal_core.o thermal_sysfs.o \
-   thermal_helpers.o
+  thermal_helpers.o
 
 # interface to/from other layers providing sensors
 thermal_sys-$(CONFIG_THERMAL_HWMON)+= thermal_hwmon.o
@@ -25,11 +25,11 @@ thermal_sys-$(CONFIG_CPU_THERMAL)   += cpu_cooling.o
 thermal_sys-$(CONFIG_CLOCK_THERMAL)+= clock_cooling.o
 
 # devfreq cooling
-thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
+thermal_sys-$(CONFIG_DEVFREQ_THERMAL)  += devfreq_cooling.o
 
 # platform thermal drivers
 obj-y  += broadcom/
-obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
+obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
 obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o
 obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
@@ -50,7 +50,7 @@ obj-$(CONFIG_TI_SOC_THERMAL)  += ti-soc-thermal/
 obj-y  += st/
 obj-$(CONFIG_QCOM_TSENS)   += qcom/
 obj-y  += tegra/
-obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
+obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)  += mtk_thermal.o
 obj-$(CONFIG_GENERIC_ADC_THERMAL)  += thermal-generic-adc.o
 obj-$(CONFIG_ZX2967_THERMAL)   += zx2967_thermal.o
-- 
2.17.1



[PATCH v5 12/18] dt-bindings: thermal: add binding document for a64 thermal controller

2019-08-09 Thread Yangtao Li
This patch adds binding document for allwinner a64 thermal controller.

Signed-off-by: Yangtao Li 
---
 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml 
b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
index 6624cf6b1ce8..f935b4fab8ec 100644
--- a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -17,6 +17,7 @@ properties:
   compatible:
 enum:
   - allwinner,sun8i-h3-ths
+  - allwinner,sun50i-a64-ths
   - allwinner,sun50i-h6-ths
 
   reg:
-- 
2.17.1



[PATCH v5 08/18] thermal: sun8i: support mod clocks

2019-08-09 Thread Yangtao Li
H3 has extra clock, so introduce something in ths_thermal_chip/ths_device
and adds the process of the clock.

This is pre-work for supprt it.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index b934bc81eba7..6f4294c2aba7 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -54,6 +54,7 @@ struct tsensor {
 };
 
 struct ths_thermal_chip {
+   boolhas_mod_clk;
int sensor_num;
int offset;
int scale;
@@ -69,6 +70,7 @@ struct ths_device {
struct regmap   *regmap;
struct reset_control*reset;
struct clk  *bus_clk;
+   struct clk  *mod_clk;
struct tsensor  sensor[MAX_SENSOR_NUM];
 };
 
@@ -274,6 +276,12 @@ static int sun8i_ths_resource_init(struct ths_device 
*tmdev)
if (IS_ERR(tmdev->bus_clk))
return PTR_ERR(tmdev->bus_clk);
 
+   if (tmdev->chip->has_mod_clk) {
+   tmdev->mod_clk = devm_clk_get(>dev, "mod");
+   if (IS_ERR(tmdev->mod_clk))
+   return PTR_ERR(tmdev->mod_clk);
+   }
+
ret = reset_control_deassert(tmdev->reset);
if (ret)
return ret;
@@ -282,12 +290,18 @@ static int sun8i_ths_resource_init(struct ths_device 
*tmdev)
if (ret)
goto assert_reset;
 
-   ret = sun50i_ths_calibrate(tmdev);
+   ret = clk_prepare_enable(tmdev->mod_clk);
if (ret)
goto bus_disable;
 
+   ret = sun50i_ths_calibrate(tmdev);
+   if (ret)
+   goto mod_disable;
+
return 0;
 
+mod_disable:
+   clk_disable_unprepare(tmdev->mod_clk);
 bus_disable:
clk_disable_unprepare(tmdev->bus_clk);
 assert_reset:
@@ -395,6 +409,7 @@ static int sun8i_ths_remove(struct platform_device *pdev)
 {
struct ths_device *tmdev = platform_get_drvdata(pdev);
 
+   clk_disable_unprepare(tmdev->mod_clk);
clk_disable_unprepare(tmdev->bus_clk);
reset_control_assert(tmdev->reset);
 
-- 
2.17.1



[PATCH v5 09/18] thermal: sun8i: rework for ths calibrate func

2019-08-09 Thread Yangtao Li
Here, we do something to prepare for the subsequent
support of multiple platforms.

1) rename sun50i_ths_calibrate to sun8i_ths_calibrate, because
   this function should be suitable for all platforms now.

2) introduce calibrate callback to mask calibration method
   differences.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 86 ++---
 1 file changed, 48 insertions(+), 38 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 6f4294c2aba7..47c20c4c69e7 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -60,6 +60,8 @@ struct ths_thermal_chip {
int scale;
int ft_deviation;
int temp_data_base;
+   int (*calibrate)(struct ths_device *tmdev,
+u16 *caldata, int callen);
int (*init)(struct ths_device *tmdev);
int (*irq_ack)(struct ths_device *tmdev);
 };
@@ -152,45 +154,14 @@ static irqreturn_t sun8i_irq_thread(int irq, void *data)
return IRQ_HANDLED;
 }
 
-static int sun50i_ths_calibrate(struct ths_device *tmdev)
+static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
+  u16 *caldata, int callen)
 {
-   struct nvmem_cell *calcell;
struct device *dev = tmdev->dev;
-   u16 *caldata;
-   size_t callen;
-   int ft_temp;
-   int i, ret = 0;
-
-   calcell = devm_nvmem_cell_get(dev, "calib");
-   if (IS_ERR(calcell)) {
-   if (PTR_ERR(calcell) == -EPROBE_DEFER)
-   return -EPROBE_DEFER;
-   /*
-* Even if the external calibration data stored in sid is
-* not accessible, the THS hardware can still work, although
-* the data won't be so accurate.
-*
-* The default value of calibration register is 0x800 for
-* every sensor, and the calibration value is usually 0x7xx
-* or 0x8xx, so they won't be away from the default value
-* for a lot.
-*
-* So here we do not return error if the calibartion data is
-* not available, except the probe needs deferring.
-*/
-   goto out;
-   }
+   int i, ft_temp;
 
-   caldata = nvmem_cell_read(calcell, );
-   if (IS_ERR(caldata)) {
-   ret = PTR_ERR(caldata);
-   goto out;
-   }
-
-   if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num) {
-   ret = -EINVAL;
-   goto out_free;
-   }
+   if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num)
+   return -EINVAL;
 
/*
 * efuse layout:
@@ -245,7 +216,45 @@ static int sun50i_ths_calibrate(struct ths_device *tmdev)
   cdata << offset);
}
 
-out_free:
+   return 0;
+}
+
+static int sun8i_ths_calibrate(struct ths_device *tmdev)
+{
+   struct nvmem_cell *calcell;
+   struct device *dev = tmdev->dev;
+   u16 *caldata;
+   size_t callen;
+   int ret = 0;
+
+   calcell = devm_nvmem_cell_get(dev, "calib");
+   if (IS_ERR(calcell)) {
+   if (PTR_ERR(calcell) == -EPROBE_DEFER)
+   return -EPROBE_DEFER;
+   /*
+* Even if the external calibration data stored in sid is
+* not accessible, the THS hardware can still work, although
+* the data won't be so accurate.
+*
+* The default value of calibration register is 0x800 for
+* every sensor, and the calibration value is usually 0x7xx
+* or 0x8xx, so they won't be away from the default value
+* for a lot.
+*
+* So here we do not return error if the calibartion data is
+* not available, except the probe needs deferring.
+*/
+   goto out;
+   }
+
+   caldata = nvmem_cell_read(calcell, );
+   if (IS_ERR(caldata)) {
+   ret = PTR_ERR(caldata);
+   goto out;
+   }
+
+   tmdev->chip->calibrate(tmdev, caldata, callen);
+
kfree(caldata);
 out:
return ret;
@@ -294,7 +303,7 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
if (ret)
goto bus_disable;
 
-   ret = sun50i_ths_calibrate(tmdev);
+   ret = sun8i_ths_calibrate(tmdev);
if (ret)
goto mod_disable;
 
@@ -422,6 +431,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
.scale = -67,
.ft_deviation = SUN50I_H6_FT_DEVIATION,
.temp_data_base = SUN50I_H6_THS_TEMP_DATA,
+   .calibrate = sun50i_h6_ths_calibrate,

[PATCH v5 10/18] dt-bindings: thermal: add binding document for h3 thermal controller

2019-08-09 Thread Yangtao Li
This patch adds binding document for allwinner h3 thermal controller.

Signed-off-by: Yangtao Li 
---
 .../bindings/thermal/sun8i-thermal.yaml   | 81 ++-
 1 file changed, 78 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml 
b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
index e0973199ba3c..6624cf6b1ce8 100644
--- a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -16,6 +16,7 @@ description: |-
 properties:
   compatible:
 enum:
+  - allwinner,sun8i-h3-ths
   - allwinner,sun50i-h6-ths
 
   reg:
@@ -28,13 +29,21 @@ properties:
 maxItems: 1
 
   clocks:
-maxItems: 1
+minItems: 1
+maxItems: 2
+items:
+  - description: ths bus clock
+  - description: ths mod clock
 
   clock-names:
-const: bus
+minItems: 1
+maxItems: 2
+items:
+  - const: bus
+  - const: mod
 
   "#thermal-sensor-cells":
-const: 1
+enum: [ 0, 1 ]
 
   nvmem-cells:
 description: ths calibrate data
@@ -51,9 +60,75 @@ required:
   - interrupts
   - "#thermal-sensor-cells"
 
+allOf:
+  - if:
+  properties:
+compatible:
+  contains:
+const: allwinner,sun50i-h6-ths
+
+then:
+  properties:
+clocks:
+  minItems: 1
+  maxItems: 1
+
+clock-names:
+  minItems: 1
+  maxItems: 1
+
+else:
+  properties:
+clocks:
+  minItems: 2
+  maxItems: 2
+
+clock-names:
+  minItems: 2
+  maxItems: 2
+
+  - if:
+  properties:
+compatible:
+  contains:
+const: allwinner,sun8i-h3-ths
+
+then:
+  properties:
+"#thermal-sensor-cells":
+  const: 0
+
+else:
+  properties:
+"#thermal-sensor-cells":
+  const: 1
+
 additionalProperties: false
 
 examples:
+  - |
+ths: ths@1c25000 {
+compatible = "allwinner,sun8i-h3-ths";
+reg = <0x01c25000 0x400>;
+clocks = < CLK_BUS_THS>, < CLK_THS>;
+clock-names = "bus", "mod";
+resets = < RST_BUS_THS>;
+interrupts = ;
+nvmem-cells = <_calib>;
+nvmem-cell-names = "calib";
+#thermal-sensor-cells = <0>;
+};
+
+sid: sid@1c14000 {
+compatible = "allwinner,sun8i-h3-sid";
+reg = <0x1c14000 0x400>;
+#address-cells = <1>;
+#size-cells = <1>;
+tsen_calib: calib@34 {
+reg = <0x34 2>;
+};
+};
+
   - |
 ths: ths@5070400 {
 compatible = "allwinner,sun50i-h6-ths";
-- 
2.17.1



[PATCH v5 06/18] thermal: sun8i: get ths init func from device compatible

2019-08-09 Thread Yangtao Li
There are some differences in register initialization for
different socs. So we get different initialization functions
from device compatible.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index f338fa25b98e..ad877b54f58e 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -59,6 +59,7 @@ struct ths_thermal_chip {
int scale;
int ft_deviation;
int temp_data_base;
+   int (*init)(struct ths_device *tmdev);
 };
 
 struct ths_device {
@@ -356,7 +357,7 @@ static int sun8i_ths_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
 
-   ret = sun50i_h6_thermal_init(tmdev);
+   ret = tmdev->chip->init(tmdev);
if (ret)
return ret;
 
@@ -394,6 +395,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
.scale = -67,
.ft_deviation = SUN50I_H6_FT_DEVIATION,
.temp_data_base = SUN50I_H6_THS_TEMP_DATA,
+   .init = sun50i_h6_thermal_init,
 };
 
 static const struct of_device_id of_ths_match[] = {
-- 
2.17.1



[PATCH v5 15/18] thermal: sun8i: allow to use custom temperature calculation function

2019-08-09 Thread Yangtao Li
From: Icenowy Zheng 

The H5 temperature calculation function is strange. Firstly, it's
segmented. Secondly, the formula of two sensors are different in the
second segment.

Allow to use a custom temperature calculation function, in case of
the function is complex.

Signed-off-by: Icenowy Zheng 
---
 drivers/thermal/sun8i_thermal.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 3259081da841..a761e2afda08 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -76,6 +76,7 @@ struct ths_thermal_chip {
 u16 *caldata, int callen);
int (*init)(struct ths_device *tmdev);
int (*irq_ack)(struct ths_device *tmdev);
+   int (*calc_temp)(int id, int reg);
 };
 
 struct ths_device {
@@ -90,9 +91,12 @@ struct ths_device {
 
 /* Temp Unit: millidegree Celsius */
 static int sun8i_ths_reg2temp(struct ths_device *tmdev,
- int reg)
+ int id, int reg)
 {
-   return (reg + tmdev->chip->offset) * tmdev->chip->scale;
+   if (tmdev->chip->calc_temp)
+   return tmdev->chip->calc_temp(id, reg);
+   else
+   return (reg + tmdev->chip->offset) * tmdev->chip->scale;
 }
 
 static int sun8i_ths_get_temp(void *data, int *temp)
@@ -108,7 +112,7 @@ static int sun8i_ths_get_temp(void *data, int *temp)
if (!val)
return -EAGAIN;
 
-   *temp = sun8i_ths_reg2temp(tmdev, val);
+   *temp = sun8i_ths_reg2temp(tmdev, s->id, val);
/*
 * XX - According to the original sdk, there are some platforms(rarely)
 * that add a fixed offset value after calculating the temperature
@@ -232,7 +236,7 @@ static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
 
for (i = 0; i < tmdev->chip->sensor_num; i++) {
int reg = (int)caldata[i + 1];
-   int sensor_temp = sun8i_ths_reg2temp(tmdev, reg);
+   int sensor_temp = sun8i_ths_reg2temp(tmdev, i, reg);
int delta, cdata, offset;
 
/*
-- 
2.17.1



[PATCH v5 04/18] thermal: sun8i: get ths sensor number from device compatible

2019-08-09 Thread Yangtao Li
For different socs, the number of ths sensors is different.
So we need to do some work in order to support more soc.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 28 
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 2ce36fa3fec3..e9c2acbaac74 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -22,7 +22,6 @@
 
 #define MAX_SENSOR_NUM 4
 
-#define SUN50I_H6_SENSOR_NUM   2
 #define SUN50I_H6_OFFSET   -2794
 #define SUN50I_H6_SCALE-67
 
@@ -57,7 +56,12 @@ struct tsensor {
int id;
 };
 
+struct ths_thermal_chip {
+   int sensor_num;
+};
+
 struct ths_device {
+   const struct ths_thermal_chip   *chip;
struct device   *dev;
struct regmap   *regmap;
struct reset_control*reset;
@@ -117,7 +121,7 @@ static irqreturn_t sun50i_h6_irq_thread(int irq, void *data)
 
regmap_read(tmdev->regmap, SUN50I_H6_THS_DIS, );
 
-   for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+   for (i = 0; i < tmdev->chip->sensor_num; i++) {
 
if (state & SUN50I_H6_THS_DATA_IRQ_STS(i)) {
/* clear data irq pending */
@@ -167,7 +171,7 @@ static int sun50i_ths_calibrate(struct ths_device *tmdev)
goto out;
}
 
-   if (!caldata[0] || callen < 2 + 2 * SUN50I_H6_SENSOR_NUM) {
+   if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num) {
ret = -EINVAL;
goto out_free;
}
@@ -190,7 +194,7 @@ static int sun50i_ths_calibrate(struct ths_device *tmdev)
 */
ft_temp = caldata[0] & FT_TEMP_MASK;
 
-   for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+   for (i = 0; i < tmdev->chip->sensor_num; i++) {
int reg = (int)caldata[i + 1];
int sensor_temp = sun8i_ths_reg2temp(tmdev, reg);
int delta, cdata, offset;
@@ -297,10 +301,10 @@ static int sun50i_h6_thermal_init(struct ths_device 
*tmdev)
regmap_write(tmdev->regmap, SUN50I_H6_THS_PC,
 SUN50I_H6_THS_PC_TEMP_PERIOD(58));
/* enable sensor */
-   val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
+   val = GENMASK(tmdev->chip->sensor_num - 1, 0);
regmap_write(tmdev->regmap, SUN50I_H6_THS_ENABLE, val);
/* thermal data interrupt enable */
-   val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
+   val = GENMASK(tmdev->chip->sensor_num - 1, 0);
regmap_write(tmdev->regmap, SUN50I_H6_THS_DIC, val);
 
return 0;
@@ -311,7 +315,7 @@ static int sun8i_ths_register(struct ths_device *tmdev)
struct thermal_zone_device *tzd;
int i;
 
-   for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+   for (i = 0; i < tmdev->chip->sensor_num; i++) {
tmdev->sensor[i].tmdev = tmdev;
tmdev->sensor[i].id = i;
tmdev->sensor[i].tzd =
@@ -337,6 +341,10 @@ static int sun8i_ths_probe(struct platform_device *pdev)
return -ENOMEM;
 
tmdev->dev = dev;
+   tmdev->chip = of_device_get_match_data(>dev);
+   if (!tmdev->chip)
+   return -EINVAL;
+
platform_set_drvdata(pdev, tmdev);
 
ret = sun8i_ths_resource_init(tmdev);
@@ -379,8 +387,12 @@ static int sun8i_ths_remove(struct platform_device *pdev)
return 0;
 }
 
+static const struct ths_thermal_chip sun50i_h6_ths = {
+   .sensor_num = 2,
+};
+
 static const struct of_device_id of_ths_match[] = {
-   { .compatible = "allwinner,sun50i-h6-ths"},
+   { .compatible = "allwinner,sun50i-h6-ths", .data = _h6_ths },
{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, of_ths_match);
-- 
2.17.1



[PATCH v5 14/18] dt-bindings: thermal: add binding document for h5 thermal controller

2019-08-09 Thread Yangtao Li
This patch adds binding document for allwinner h5 thermal controller.

Signed-off-by: Yangtao Li 
---
 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml 
b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
index f935b4fab8ec..2e28f5b33d33 100644
--- a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -18,6 +18,7 @@ properties:
 enum:
   - allwinner,sun8i-h3-ths
   - allwinner,sun50i-a64-ths
+  - allwinner,sun50i-h5-ths
   - allwinner,sun50i-h6-ths
 
   reg:
-- 
2.17.1



[PATCH v5 13/18] thermal: sun8i: add thermal driver for A64

2019-08-09 Thread Yangtao Li
From: Vasily Khoruzhick 

Thermal sensor controller in A64 is similar to H3, but it has 3 sensors.
Extend H3 functions to add support for multiple sensors.

Signed-off-by: Vasily Khoruzhick 
---
 drivers/thermal/sun8i_thermal.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 41ce8cdc0546..3259081da841 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -515,6 +515,17 @@ static const struct ths_thermal_chip sun8i_h3_ths = {
.irq_ack = sun8i_h3_irq_ack,
 };
 
+static const struct ths_thermal_chip sun50i_a64_ths = {
+   .sensor_num = 3,
+   .offset = -2170,
+   .scale = -117,
+   .has_mod_clk = true,
+   .temp_data_base = SUN8I_THS_TEMP_DATA,
+   .calibrate = sun8i_h3_ths_calibrate,
+   .init = sun8i_h3_thermal_init,
+   .irq_ack = sun8i_h3_irq_ack,
+};
+
 static const struct ths_thermal_chip sun50i_h6_ths = {
.sensor_num = 2,
.offset = -2794,
@@ -528,6 +539,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 
 static const struct of_device_id of_ths_match[] = {
{ .compatible = "allwinner,sun8i-h3-ths", .data = _h3_ths },
+   { .compatible = "allwinner,sun50i-a64-ths", .data = _a64_ths },
{ .compatible = "allwinner,sun50i-h6-ths", .data = _h6_ths },
{ /* sentinel */ },
 };
-- 
2.17.1



[PATCH v5 11/18] thermal: sun8i: add thermal driver for h3

2019-08-09 Thread Yangtao Li
This patch adds the support for allwinner h3 thermal sensor.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 91 +
 1 file changed, 91 insertions(+)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 47c20c4c69e7..41ce8cdc0546 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -27,6 +27,14 @@
 #define TEMP_TO_REG672
 #define CALIBRATE_DEFAULT  0x800
 
+#define SUN8I_THS_CTRL00x00
+#define SUN8I_THS_CTRL20x40
+#define SUN8I_THS_IC   0x44
+#define SUN8I_THS_IS   0x48
+#define SUN8I_THS_MFC  0x70
+#define SUN8I_THS_TEMP_CALIB   0x74
+#define SUN8I_THS_TEMP_DATA0x80
+
 #define SUN50I_THS_CTRL0   0x00
 #define SUN50I_H6_THS_ENABLE   0x04
 #define SUN50I_H6_THS_PC   0x08
@@ -36,6 +44,10 @@
 #define SUN50I_H6_THS_TEMP_CALIB   0xa0
 #define SUN50I_H6_THS_TEMP_DATA0xc0
 
+#define SUN8I_THS_CTRL0_T_ACQ0(x)  (GENMASK(15, 0) & (x))
+#define SUN8I_THS_CTRL2_T_ACQ1(x)  ((GENMASK(15, 0) & (x)) << 16)
+#define SUN8I_THS_DATA_IRQ_STS(x)  BIT(x + 8)
+
 #define SUN50I_THS_CTRL0_T_ACQ(x)  ((GENMASK(15, 0) & (x)) << 16)
 #define SUN50I_THS_FILTER_EN   BIT(2)
 #define SUN50I_THS_FILTER_TYPE(x)  (GENMASK(1, 0) & (x))
@@ -121,6 +133,23 @@ static const struct regmap_config config = {
.fast_io = true,
 };
 
+static int sun8i_h3_irq_ack(struct ths_device *tmdev)
+{
+   int i, state, ret = 0;
+
+   regmap_read(tmdev->regmap, SUN8I_THS_IS, );
+
+   for (i = 0; i < tmdev->chip->sensor_num; i++) {
+   if (state & SUN8I_THS_DATA_IRQ_STS(i)) {
+   regmap_write(tmdev->regmap, SUN8I_THS_IS,
+SUN8I_THS_DATA_IRQ_STS(i));
+   ret |= BIT(i);
+   }
+   }
+
+   return ret;
+}
+
 static int sun50i_h6_irq_ack(struct ths_device *tmdev)
 {
int i, state, ret = 0;
@@ -154,6 +183,26 @@ static irqreturn_t sun8i_irq_thread(int irq, void *data)
return IRQ_HANDLED;
 }
 
+static int sun8i_h3_ths_calibrate(struct ths_device *tmdev,
+ u16 *caldata, int callen)
+{
+   int i;
+
+   if (!caldata[0] || callen < 2 * tmdev->chip->sensor_num)
+   return -EINVAL;
+
+   for (i = 0; i < tmdev->chip->sensor_num; i++) {
+   int offset = (i % 2) << 4;
+
+   regmap_update_bits(tmdev->regmap,
+  SUN8I_THS_TEMP_CALIB + (4 * (i >> 1)),
+  0xfff << offset,
+  caldata[i] << offset);
+   }
+
+   return 0;
+}
+
 static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
   u16 *caldata, int callen)
 {
@@ -319,6 +368,36 @@ static int sun8i_ths_resource_init(struct ths_device 
*tmdev)
return ret;
 }
 
+static int sun8i_h3_thermal_init(struct ths_device *tmdev)
+{
+   int val;
+
+   /* average over 4 samples */
+   regmap_write(tmdev->regmap, SUN8I_THS_MFC,
+SUN50I_THS_FILTER_EN |
+SUN50I_THS_FILTER_TYPE(1));
+   /*
+* period = (x + 1) * 4096 / clkin; ~10ms
+* enable data interrupt
+*/
+   val = GENMASK(7 + tmdev->chip->sensor_num, 8);
+   regmap_write(tmdev->regmap, SUN8I_THS_IC,
+SUN50I_H6_THS_PC_TEMP_PERIOD(58) | val);
+   /*
+* clkin = 24MHz
+* T acquire = clkin / (x + 1)
+*   = 20us
+* enable sensor
+*/
+   regmap_write(tmdev->regmap, SUN8I_THS_CTRL0,
+SUN8I_THS_CTRL0_T_ACQ0(479));
+   val = GENMASK(tmdev->chip->sensor_num - 1, 0);
+   regmap_write(tmdev->regmap, SUN8I_THS_CTRL2,
+SUN8I_THS_CTRL2_T_ACQ1(479) | val);
+
+   return 0;
+}
+
 static int sun50i_h6_thermal_init(struct ths_device *tmdev)
 {
int val;
@@ -425,6 +504,17 @@ static int sun8i_ths_remove(struct platform_device *pdev)
return 0;
 }
 
+static const struct ths_thermal_chip sun8i_h3_ths = {
+   .sensor_num = 1,
+   .offset = -1794,
+   .scale = -121,
+   .has_mod_clk = true,
+   .temp_data_base = SUN8I_THS_TEMP_DATA,
+   .calibrate = sun8i_h3_ths_calibrate,
+   .init = sun8i_h3_thermal_init,
+   .irq_ack = sun8i_h3_irq_ack,
+};
+
 static const struct ths_thermal_chip sun50i_h6_ths = {
.sensor_num = 2,
.offset = -2794,
@@ -437,6 +527,7 @@ static const struct

[PATCH v5 07/18] thermal: sun8i: rework for ths irq handler func

2019-08-09 Thread Yangtao Li
Here, we do something to prepare for the subsequent
support of multiple platforms.

1) rename sun50i_h6_irq_thread to sun8i_irq_thread, because
   this function should be suitable for all platforms.

2) introduce irq_ack callback to mask interrupt register
   differences.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 27 ---
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index ad877b54f58e..b934bc81eba7 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -60,6 +60,7 @@ struct ths_thermal_chip {
int ft_deviation;
int temp_data_base;
int (*init)(struct ths_device *tmdev);
+   int (*irq_ack)(struct ths_device *tmdev);
 };
 
 struct ths_device {
@@ -116,23 +117,34 @@ static const struct regmap_config config = {
.fast_io = true,
 };
 
-static irqreturn_t sun50i_h6_irq_thread(int irq, void *data)
+static int sun50i_h6_irq_ack(struct ths_device *tmdev)
 {
-   struct ths_device *tmdev = data;
-   int i, state;
+   int i, state, ret = 0;
 
regmap_read(tmdev->regmap, SUN50I_H6_THS_DIS, );
 
for (i = 0; i < tmdev->chip->sensor_num; i++) {
-
if (state & SUN50I_H6_THS_DATA_IRQ_STS(i)) {
-   /* clear data irq pending */
regmap_write(tmdev->regmap, SUN50I_H6_THS_DIS,
 SUN50I_H6_THS_DATA_IRQ_STS(i));
+   ret |= BIT(i);
+   }
+   }
+
+   return ret;
+}
 
+static irqreturn_t sun8i_irq_thread(int irq, void *data)
+{
+   struct ths_device *tmdev = data;
+   int i, state;
+
+   state = tmdev->chip->irq_ack(tmdev);
+
+   for (i = 0; i < tmdev->chip->sensor_num; i++) {
+   if (state & BIT(i))
thermal_zone_device_update(tmdev->sensor[i].tzd,
   THERMAL_EVENT_UNSPECIFIED);
-   }
}
 
return IRQ_HANDLED;
@@ -371,7 +383,7 @@ static int sun8i_ths_probe(struct platform_device *pdev)
 * the end.
 */
ret = devm_request_threaded_irq(dev, irq, NULL,
-   sun50i_h6_irq_thread,
+   sun8i_irq_thread,
IRQF_ONESHOT, "ths", tmdev);
if (ret)
return ret;
@@ -396,6 +408,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
.ft_deviation = SUN50I_H6_FT_DEVIATION,
.temp_data_base = SUN50I_H6_THS_TEMP_DATA,
.init = sun50i_h6_thermal_init,
+   .irq_ack = sun50i_h6_irq_ack,
 };
 
 static const struct of_device_id of_ths_match[] = {
-- 
2.17.1



[PATCH v5 05/18] thermal: sun8i: rework for sun8i_ths_get_temp()

2019-08-09 Thread Yangtao Li
For different socs, the way they get and calculate the
temperature is roughly the same. So get the difference
from device compatible.

Difference point:
  1) temperature calculation formula parameters
  2) ths data register start address

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index e9c2acbaac74..f338fa25b98e 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -22,9 +22,6 @@
 
 #define MAX_SENSOR_NUM 4
 
-#define SUN50I_H6_OFFSET   -2794
-#define SUN50I_H6_SCALE-67
-
 #define FT_TEMP_MASK   GENMASK(11, 0)
 #define TEMP_CALIB_MASKGENMASK(11, 0)
 #define TEMP_TO_REG672
@@ -58,6 +55,10 @@ struct tsensor {
 
 struct ths_thermal_chip {
int sensor_num;
+   int offset;
+   int scale;
+   int ft_deviation;
+   int temp_data_base;
 };
 
 struct ths_device {
@@ -73,7 +74,7 @@ struct ths_device {
 static int sun8i_ths_reg2temp(struct ths_device *tmdev,
  int reg)
 {
-   return (reg + SUN50I_H6_OFFSET) * SUN50I_H6_SCALE;
+   return (reg + tmdev->chip->offset) * tmdev->chip->scale;
 }
 
 static int sun8i_ths_get_temp(void *data, int *temp)
@@ -82,7 +83,7 @@ static int sun8i_ths_get_temp(void *data, int *temp)
struct ths_device *tmdev = s->tmdev;
int val;
 
-   regmap_read(tmdev->regmap, SUN50I_H6_THS_TEMP_DATA +
+   regmap_read(tmdev->regmap, tmdev->chip->temp_data_base +
0x4 * s->id, );
 
/* ths have no data yet */
@@ -98,7 +99,7 @@ static int sun8i_ths_get_temp(void *data, int *temp)
 * temperature above is also used when the sensor is calibrated. If
 * do this, the correct calibration formula is hard to know.
 */
-   *temp += SUN50I_H6_FT_DEVIATION;
+   *temp += tmdev->chip->ft_deviation;
 
return 0;
 }
@@ -389,6 +390,10 @@ static int sun8i_ths_remove(struct platform_device *pdev)
 
 static const struct ths_thermal_chip sun50i_h6_ths = {
.sensor_num = 2,
+   .offset = -2794,
+   .scale = -67,
+   .ft_deviation = SUN50I_H6_FT_DEVIATION,
+   .temp_data_base = SUN50I_H6_THS_TEMP_DATA,
 };
 
 static const struct of_device_id of_ths_match[] = {
-- 
2.17.1



[PATCH v5 00/18] add thermal driver for h6

2019-08-09 Thread Yangtao Li
This patchset add support for A64, H3, H5, H6 and R40 thermal sensor.

Thx to Icenowy and Vasily.

BTY, do a cleanup in thermal makfile.

Icenowy Zheng (3):
  thermal: sun8i: allow to use custom temperature calculation function
  thermal: sun8i: add support for Allwinner H5 thermal sensor
  thermal: sun8i: add support for Allwinner R40 thermal sensor

Vasily Khoruzhick (1):
  thermal: sun8i: add thermal driver for A64

Yangtao Li (14):
  thermal: sun8i: add thermal driver for h6
  dt-bindings: thermal: add binding document for h6 thermal controller
  thermal: fix indentation in makefile
  thermal: sun8i: get ths sensor number from device compatible
  thermal: sun8i: rework for sun8i_ths_get_temp()
  thermal: sun8i: get ths init func from device compatible
  thermal: sun8i: rework for ths irq handler func
  thermal: sun8i: support mod clocks
  thermal: sun8i: rework for ths calibrate func
  dt-bindings: thermal: add binding document for h3 thermal controller
  thermal: sun8i: add thermal driver for h3
  dt-bindings: thermal: add binding document for a64 thermal controller
  dt-bindings: thermal: add binding document for h5 thermal controller
  dt-bindings: thermal: add binding document for r40 thermal controller

 .../bindings/thermal/sun8i-thermal.yaml   | 157 +
 MAINTAINERS   |   7 +
 drivers/thermal/Kconfig   |  14 +
 drivers/thermal/Makefile  |   9 +-
 drivers/thermal/sun8i_thermal.c   | 596 ++
 5 files changed, 779 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
 create mode 100644 drivers/thermal/sun8i_thermal.c

---
v5:
-add more support
-some trival fix
---
2.17.1



[PATCH v5 02/18] dt-bindings: thermal: add binding document for h6 thermal controller

2019-08-09 Thread Yangtao Li
This patch adds binding document for allwinner h6 thermal controller.

Signed-off-by: Yangtao Li 
---
 .../bindings/thermal/sun8i-thermal.yaml   | 79 +++
 1 file changed, 79 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml 
b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
new file mode 100644
index ..e0973199ba3c
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/sun8i-thermal.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner SUN8I Thermal Controller Device Tree Bindings
+
+maintainers:
+  - Yangtao Li 
+
+description: |-
+  This describes the device tree binding for the Allwinner thermal
+  controller which measures the on-SoC temperatures.
+
+properties:
+  compatible:
+enum:
+  - allwinner,sun50i-h6-ths
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  resets:
+maxItems: 1
+
+  clocks:
+maxItems: 1
+
+  clock-names:
+const: bus
+
+  "#thermal-sensor-cells":
+const: 1
+
+  nvmem-cells:
+description: ths calibrate data
+
+  nvmem-cell-names:
+const: calib
+
+required:
+  - compatible
+  - reg
+  - reset
+  - clocks
+  - clock-names
+  - interrupts
+  - "#thermal-sensor-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+ths: ths@5070400 {
+compatible = "allwinner,sun50i-h6-ths";
+reg = <0x05070400 0x100>;
+clocks = < CLK_BUS_THS>;
+clock-names = "bus";
+resets = < RST_BUS_THS>;
+interrupts = ;
+nvmem-cells = <_calib>;
+nvmem-cell-names = "calib";
+#thermal-sensor-cells = <1>;
+};
+
+sid: sid@3006000 {
+compatible = "allwinner,sun50i-h6-sid";
+reg = <0x03006000 0x400>;
+#address-cells = <1>;
+#size-cells = <1>;
+tsen_calib: calib@14 {
+reg = <0x14 6>;
+};
+};
+...
-- 
2.17.1



[PATCH v5 01/18] thermal: sun8i: add thermal driver for h6

2019-08-09 Thread Yangtao Li
This patch adds the support for allwinner thermal sensor, within
allwinner SoC. It will register sensors for thermal framework
and use device tree to bind cooling device.

Signed-off-by: Yangtao Li 
---
 MAINTAINERS |   7 +
 drivers/thermal/Kconfig |  14 ++
 drivers/thermal/Makefile|   1 +
 drivers/thermal/sun8i_thermal.c | 399 
 4 files changed, 421 insertions(+)
 create mode 100644 drivers/thermal/sun8i_thermal.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 47800d32cfbc..89dc43f4064d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -682,6 +682,13 @@ L: linux-cry...@vger.kernel.org
 S: Maintained
 F: drivers/crypto/sunxi-ss/
 
+ALLWINNER THERMAL DRIVER
+M: Yangtao Li 
+L: linux...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+F: drivers/thermal/sun8i_thermal.c
+
 ALLWINNER VPU DRIVER
 M: Maxime Ripard 
 M: Paul Kocialkowski 
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 9966364a6deb..f8b73b32b92d 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -262,6 +262,20 @@ config SPEAR_THERMAL
  Enable this to plug the SPEAr thermal sensor driver into the Linux
  thermal framework.
 
+config SUN8I_THERMAL
+   tristate "Allwinner sun8i thermal driver"
+   depends on ARCH_SUNXI || COMPILE_TEST
+   depends on HAS_IOMEM
+   depends on NVMEM
+   depends on OF
+   depends on RESET_CONTROLLER
+   help
+ Support for the sun8i thermal sensor driver into the Linux thermal
+ framework.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sun8i-thermal.
+
 config ROCKCHIP_THERMAL
tristate "Rockchip thermal driver"
depends on ARCH_ROCKCHIP || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 74a37c7f847a..fa6f8b206281 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -31,6 +31,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
 obj-y  += broadcom/
 obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
 obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o
+obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
 obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
 obj-$(CONFIG_RCAR_GEN3_THERMAL)+= rcar_gen3_thermal.o
diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
new file mode 100644
index ..2ce36fa3fec3
--- /dev/null
+++ b/drivers/thermal/sun8i_thermal.c
@@ -0,0 +1,399 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Thermal sensor driver for Allwinner SOC
+ * Copyright (C) 2019 Yangtao Li
+ *
+ * Based on the work of Icenowy Zheng 
+ * Based on the work of Ondrej Jirman 
+ * Based on the work of Josef Gajdusek 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_SENSOR_NUM 4
+
+#define SUN50I_H6_SENSOR_NUM   2
+#define SUN50I_H6_OFFSET   -2794
+#define SUN50I_H6_SCALE-67
+
+#define FT_TEMP_MASK   GENMASK(11, 0)
+#define TEMP_CALIB_MASKGENMASK(11, 0)
+#define TEMP_TO_REG672
+#define CALIBRATE_DEFAULT  0x800
+
+#define SUN50I_THS_CTRL0   0x00
+#define SUN50I_H6_THS_ENABLE   0x04
+#define SUN50I_H6_THS_PC   0x08
+#define SUN50I_H6_THS_DIC  0x10
+#define SUN50I_H6_THS_DIS  0x20
+#define SUN50I_H6_THS_MFC  0x30
+#define SUN50I_H6_THS_TEMP_CALIB   0xa0
+#define SUN50I_H6_THS_TEMP_DATA0xc0
+
+#define SUN50I_THS_CTRL0_T_ACQ(x)  ((GENMASK(15, 0) & (x)) << 16)
+#define SUN50I_THS_FILTER_EN   BIT(2)
+#define SUN50I_THS_FILTER_TYPE(x)  (GENMASK(1, 0) & (x))
+#define SUN50I_H6_THS_PC_TEMP_PERIOD(x)((GENMASK(19, 0) & (x)) 
<< 12)
+#define SUN50I_H6_THS_DATA_IRQ_STS(x)  BIT(x)
+
+/* millidegree celsius */
+#define SUN50I_H6_FT_DEVIATION 7000
+
+struct ths_device;
+
+struct tsensor {
+   struct ths_device   *tmdev;
+   struct thermal_zone_device  *tzd;
+   int id;
+};
+
+struct ths_device {
+   struct device   *dev;
+   struct regmap   *regmap;
+   struct reset_control*reset;
+   struct clk  *bus_clk;
+   struct tsensor  sensor[MAX_SENSOR_NUM];
+};
+
+/* Temp Unit: millidegree Celsius */
+static int sun8i_ths_reg2temp(struct ths_device *tmdev,
+

[PATCH v4 08/11] thermal: sun8i: support ahb clocks

2019-06-23 Thread Yangtao Li
H3 has extra clock, so introduce something in ths_thermal_chip/ths_device
and adds the process of the clock.

This is pre-work for supprt it.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index ed1c19bb27cf..04f53ffb6a14 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -54,6 +54,7 @@ struct tsensor {
 };
 
 struct ths_thermal_chip {
+   boolhas_ahb_clk;
int sensor_num;
int offset;
int scale;
@@ -69,6 +70,7 @@ struct ths_device {
struct regmap   *regmap;
struct reset_control*reset;
struct clk  *bus_clk;
+   struct clk  *ahb_clk;
struct tsensor  sensor[MAX_SENSOR_NUM];
 };
 
@@ -280,6 +282,12 @@ static int sun8i_ths_resource_init(struct ths_device 
*tmdev)
if (IS_ERR(tmdev->bus_clk))
return PTR_ERR(tmdev->bus_clk);
 
+   if (tmdev->chip->has_ahb_clk) {
+   tmdev->ahb_clk = devm_clk_get(>dev, "ahb");
+   if (IS_ERR(tmdev->ahb_clk))
+   return PTR_ERR(tmdev->ahb_clk);
+   }
+
ret = reset_control_deassert(tmdev->reset);
if (ret)
return ret;
@@ -288,12 +296,18 @@ static int sun8i_ths_resource_init(struct ths_device 
*tmdev)
if (ret)
goto assert_reset;
 
-   ret = sun50i_ths_calibrate(tmdev);
+   ret = clk_prepare_enable(tmdev->ahb_clk);
if (ret)
goto bus_disable;
 
+   ret = sun50i_ths_calibrate(tmdev);
+   if (ret)
+   goto ahb_disable;
+
return 0;
 
+ahb_disable:
+   clk_disable_unprepare(tmdev->ahb_clk);
 bus_disable:
clk_disable_unprepare(tmdev->bus_clk);
 assert_reset:
@@ -401,6 +415,7 @@ static int sun8i_ths_remove(struct platform_device *pdev)
 {
struct ths_device *tmdev = platform_get_drvdata(pdev);
 
+   clk_disable_unprepare(tmdev->ahb_clk);
clk_disable_unprepare(tmdev->bus_clk);
reset_control_assert(tmdev->reset);
 
-- 
2.17.1



[PATCH v4 05/11] thermal: sun8i: rework for sun8i_ths_get_temp()

2019-06-23 Thread Yangtao Li
For different socs, the way they get and calculate the
temperature is roughly the same. So get the difference
from device compatible.

Difference point:
  1) temperature calculation formula parameters
  2) ths data register start address

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index c37e1c51a543..e473a5651436 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -22,9 +22,6 @@
 
 #define MAX_SENSOR_NUM 4
 
-#define SUN50I_H6_OFFSET   -2794
-#define SUN50I_H6_SCALE-67
-
 #define FT_TEMP_MASK   GENMASK(11, 0)
 #define TEMP_CALIB_MASKGENMASK(11, 0)
 #define TEMP_TO_REG672
@@ -58,6 +55,10 @@ struct tsensor {
 
 struct ths_thermal_chip {
int sensor_num;
+   int offset;
+   int scale;
+   int ft_deviation;
+   int temp_data_base;
 };
 
 struct ths_device {
@@ -73,7 +74,7 @@ struct ths_device {
 static int sun8i_ths_reg2temp(struct ths_device *tmdev,
  int reg)
 {
-   return (reg + SUN50I_H6_OFFSET) * SUN50I_H6_SCALE;
+   return (reg + tmdev->chip->offset) * tmdev->chip->scale;
 }
 
 static int sun8i_ths_get_temp(void *data, int *temp)
@@ -82,7 +83,7 @@ static int sun8i_ths_get_temp(void *data, int *temp)
struct ths_device *tmdev = s->tmdev;
int val;
 
-   regmap_read(tmdev->regmap, SUN50I_H6_THS_TEMP_DATA +
+   regmap_read(tmdev->regmap, tmdev->chip->temp_data_base +
0x4 * s->id, );
 
/* ths have no data yet */
@@ -98,7 +99,7 @@ static int sun8i_ths_get_temp(void *data, int *temp)
 * temperature above is also used when the sensor is calibrated. If
 * do this, the correct calibration formula is hard to know.
 */
-   *temp += SUN50I_H6_FT_DEVIATION;
+   *temp += tmdev->chip->ft_deviation;
 
return 0;
 }
@@ -395,6 +396,10 @@ static int sun8i_ths_remove(struct platform_device *pdev)
 
 static const struct ths_thermal_chip sun50i_h6_ths = {
.sensor_num = 2,
+   .offset = -2794,
+   .scale = -67,
+   .ft_deviation = SUN50I_H6_FT_DEVIATION,
+   .temp_data_base = SUN50I_H6_THS_TEMP_DATA,
 };
 
 static const struct of_device_id of_ths_match[] = {
-- 
2.17.1



[PATCH v4 04/11] thermal: sun8i: get ths sensor number from device compatible

2019-06-23 Thread Yangtao Li
For different socs, the number of ths sensors is different.
So we need to do some work in order to support more soc.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 28 
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index d6918c62682b..c37e1c51a543 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -22,7 +22,6 @@
 
 #define MAX_SENSOR_NUM 4
 
-#define SUN50I_H6_SENSOR_NUM   2
 #define SUN50I_H6_OFFSET   -2794
 #define SUN50I_H6_SCALE-67
 
@@ -57,7 +56,12 @@ struct tsensor {
int id;
 };
 
+struct ths_thermal_chip {
+   int sensor_num;
+};
+
 struct ths_device {
+   const struct ths_thermal_chip   *chip;
struct device   *dev;
struct regmap   *regmap;
struct reset_control*reset;
@@ -117,7 +121,7 @@ static irqreturn_t sun50i_h6_irq_thread(int irq, void *data)
 
regmap_read(tmdev->regmap, SUN50I_H6_THS_DIS, );
 
-   for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+   for (i = 0; i < tmdev->chip->sensor_num; i++) {
 
if (state & SUN50I_H6_THS_DATA_IRQ_STS(i)) {
/* clear data irq pending */
@@ -167,7 +171,7 @@ static int sun50i_ths_calibrate(struct ths_device *tmdev)
goto out;
}
 
-   if (!caldata[0] || callen < 2 + 2 * SUN50I_H6_SENSOR_NUM) {
+   if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num) {
ret = -EINVAL;
goto out_free;
}
@@ -190,7 +194,7 @@ static int sun50i_ths_calibrate(struct ths_device *tmdev)
 */
ft_temp = caldata[0] & FT_TEMP_MASK;
 
-   for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+   for (i = 0; i < tmdev->chip->sensor_num; i++) {
int reg = (int)caldata[i + 1];
int sensor_temp = sun8i_ths_reg2temp(tmdev, reg);
int delta, cdata, calib_offest;
@@ -303,10 +307,10 @@ static int sun50i_thermal_init(struct ths_device *tmdev)
regmap_write(tmdev->regmap, SUN50I_H6_THS_PC,
 SUN50I_H6_THS_PC_TEMP_PERIOD(58));
/* enable sensor */
-   val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
+   val = GENMASK(tmdev->chip->sensor_num - 1, 0);
regmap_write(tmdev->regmap, SUN50I_H6_THS_ENABLE, val);
/* thermal data interrupt enable */
-   val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
+   val = GENMASK(tmdev->chip->sensor_num - 1, 0);
regmap_write(tmdev->regmap, SUN50I_H6_THS_DIC, val);
 
return 0;
@@ -317,7 +321,7 @@ static int sun8i_ths_register(struct ths_device *tmdev)
struct thermal_zone_device *tzd;
int i;
 
-   for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+   for (i = 0; i < tmdev->chip->sensor_num; i++) {
tmdev->sensor[i].tmdev = tmdev;
tmdev->sensor[i].id = i;
tmdev->sensor[i].tzd =
@@ -343,6 +347,10 @@ static int sun8i_ths_probe(struct platform_device *pdev)
return -ENOMEM;
 
tmdev->dev = dev;
+   tmdev->chip = of_device_get_match_data(>dev);
+   if (!tmdev->chip)
+   return -EINVAL;
+
platform_set_drvdata(pdev, tmdev);
 
ret = sun8i_ths_resource_init(tmdev);
@@ -385,8 +393,12 @@ static int sun8i_ths_remove(struct platform_device *pdev)
return 0;
 }
 
+static const struct ths_thermal_chip sun50i_h6_ths = {
+   .sensor_num = 2,
+};
+
 static const struct of_device_id of_ths_match[] = {
-   { .compatible = "allwinner,sun50i-h6-ths"},
+   { .compatible = "allwinner,sun50i-h6-ths", .data = _h6_ths },
{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, of_ths_match);
-- 
2.17.1



[PATCH v4 09/11] thermal: sun8i: rework for ths calibrate func

2019-06-23 Thread Yangtao Li
Here, we do something to prepare for the subsequent
support of multiple platforms.

1) rename sun50i_ths_calibrate to sun8i_ths_calibrate, because
   this function should be suitable for all platforms now.

2) introduce calibrate callback to mask calibration method
   differences.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 86 ++---
 1 file changed, 48 insertions(+), 38 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 04f53ffb6a14..260b24340f5b 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -60,6 +60,8 @@ struct ths_thermal_chip {
int scale;
int ft_deviation;
int temp_data_base;
+   int (*calibrate)(struct ths_device *tmdev,
+u16 *caldata, int callen);
int (*init)(struct ths_device *tmdev);
int (*irq_ack)(struct ths_device *tmdev);
 };
@@ -152,45 +154,14 @@ static irqreturn_t sun8i_irq_thread(int irq, void *data)
return IRQ_HANDLED;
 }
 
-static int sun50i_ths_calibrate(struct ths_device *tmdev)
+static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
+  u16 *caldata, int callen)
 {
-   struct nvmem_cell *calcell;
struct device *dev = tmdev->dev;
-   u16 *caldata;
-   size_t callen;
-   int ft_temp;
-   int i, ret = 0;
-
-   calcell = devm_nvmem_cell_get(dev, "calib");
-   if (IS_ERR(calcell)) {
-   if (PTR_ERR(calcell) == -EPROBE_DEFER)
-   return -EPROBE_DEFER;
-   /*
-* Even if the external calibration data stored in sid is
-* not accessible, the THS hardware can still work, although
-* the data won't be so accurate.
-*
-* The default value of calibration register is 0x800 for
-* every sensor, and the calibration value is usually 0x7xx
-* or 0x8xx, so they won't be away from the default value
-* for a lot.
-*
-* So here we do not return error if the calibartion data is
-* not available, except the probe needs deferring.
-*/
-   goto out;
-   }
+   int i, ft_temp;
 
-   caldata = nvmem_cell_read(calcell, );
-   if (IS_ERR(caldata)) {
-   ret = PTR_ERR(caldata);
-   goto out;
-   }
-
-   if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num) {
-   ret = -EINVAL;
-   goto out_free;
-   }
+   if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num)
+   return -EINVAL;
 
/*
 * efuse layout:
@@ -251,7 +222,45 @@ static int sun50i_ths_calibrate(struct ths_device *tmdev)
}
}
 
-out_free:
+   return 0;
+}
+
+static int sun8i_ths_calibrate(struct ths_device *tmdev)
+{
+   struct nvmem_cell *calcell;
+   struct device *dev = tmdev->dev;
+   u16 *caldata;
+   size_t callen;
+   int ret = 0;
+
+   calcell = devm_nvmem_cell_get(dev, "calib");
+   if (IS_ERR(calcell)) {
+   if (PTR_ERR(calcell) == -EPROBE_DEFER)
+   return -EPROBE_DEFER;
+   /*
+* Even if the external calibration data stored in sid is
+* not accessible, the THS hardware can still work, although
+* the data won't be so accurate.
+*
+* The default value of calibration register is 0x800 for
+* every sensor, and the calibration value is usually 0x7xx
+* or 0x8xx, so they won't be away from the default value
+* for a lot.
+*
+* So here we do not return error if the calibartion data is
+* not available, except the probe needs deferring.
+*/
+   goto out;
+   }
+
+   caldata = nvmem_cell_read(calcell, );
+   if (IS_ERR(caldata)) {
+   ret = PTR_ERR(caldata);
+   goto out;
+   }
+
+   tmdev->chip->calibrate(tmdev, caldata, callen);
+
kfree(caldata);
 out:
return ret;
@@ -300,7 +309,7 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
if (ret)
goto bus_disable;
 
-   ret = sun50i_ths_calibrate(tmdev);
+   ret = sun8i_ths_calibrate(tmdev);
if (ret)
goto ahb_disable;
 
@@ -428,6 +437,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
.scale = -67,
.ft_deviation = SUN50I_H6_FT_DEVIATION,
.temp_data_base = SUN50I_H6_THS_TEMP_DATA,
+   .calibrate = sun50i_h6_ths_calibrate,
.init = sun50i_thermal_init,
.irq_ack = sun50i_h6_irq_ack,
 };
-- 
2.17.1



[PATCH v4 00/11] add thermal driver for h6

2019-06-23 Thread Yangtao Li
This patchset add support for H3 and H6 thermal sensor.

BTY, do a cleanup in thermal makfile.

Yangtao Li (11):
  thermal: sun8i: add thermal driver for h6
  dt-bindings: thermal: add binding document for h6 thermal controller
  thermal: fix indentation in makefile
  thermal: sun8i: get ths sensor number from device compatible
  thermal: sun8i: rework for sun8i_ths_get_temp()
  thermal: sun8i: get ths init func from device compatible
  thermal: sun8i: rework for ths irq handler func
  thermal: sun8i: support ahb clocks
  thermal: sun8i: rework for ths calibrate func
  dt-bindings: thermal: add binding document for h3 thermal controller
  thermal: sun8i: add thermal driver for h3

 .../bindings/thermal/sun8i-thermal.yaml   |  94 +++
 MAINTAINERS   |   7 +
 drivers/thermal/Kconfig   |  14 +
 drivers/thermal/Makefile  |   9 +-
 drivers/thermal/sun8i_thermal.c   | 534 ++
 5 files changed, 654 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
 create mode 100644 drivers/thermal/sun8i_thermal.c

---
v4:
-add h3 support
-fix yaml file
---
2.17.1



[PATCH v4 01/11] thermal: sun8i: add thermal driver for h6

2019-06-23 Thread Yangtao Li
This patch adds the support for allwinner thermal sensor, within
allwinner SoC. It will register sensors for thermal framework
and use device tree to bind cooling device.

Signed-off-by: Yangtao Li 
---
 MAINTAINERS |   7 +
 drivers/thermal/Kconfig |  14 ++
 drivers/thermal/Makefile|   1 +
 drivers/thermal/sun8i_thermal.c | 405 
 4 files changed, 427 insertions(+)
 create mode 100644 drivers/thermal/sun8i_thermal.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 36a84614d6c3..67e7fcfaded2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -674,6 +674,13 @@ L: linux-cry...@vger.kernel.org
 S: Maintained
 F: drivers/crypto/sunxi-ss/
 
+ALLWINNER THERMAL DRIVER
+M: Yangtao Li 
+L: linux...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+F: drivers/thermal/sun8i_thermal.c
+
 ALLWINNER VPU DRIVER
 M: Maxime Ripard 
 M: Paul Kocialkowski 
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 9966364a6deb..f8b73b32b92d 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -262,6 +262,20 @@ config SPEAR_THERMAL
  Enable this to plug the SPEAr thermal sensor driver into the Linux
  thermal framework.
 
+config SUN8I_THERMAL
+   tristate "Allwinner sun8i thermal driver"
+   depends on ARCH_SUNXI || COMPILE_TEST
+   depends on HAS_IOMEM
+   depends on NVMEM
+   depends on OF
+   depends on RESET_CONTROLLER
+   help
+ Support for the sun8i thermal sensor driver into the Linux thermal
+ framework.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sun8i-thermal.
+
 config ROCKCHIP_THERMAL
tristate "Rockchip thermal driver"
depends on ARCH_ROCKCHIP || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 74a37c7f847a..fa6f8b206281 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -31,6 +31,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
 obj-y  += broadcom/
 obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
 obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o
+obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
 obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
 obj-$(CONFIG_RCAR_GEN3_THERMAL)+= rcar_gen3_thermal.o
diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
new file mode 100644
index ..d6918c62682b
--- /dev/null
+++ b/drivers/thermal/sun8i_thermal.c
@@ -0,0 +1,405 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Thermal sensor driver for Allwinner SOC
+ * Copyright (C) 2019 Yangtao Li
+ *
+ * Based on the work of Icenowy Zheng 
+ * Based on the work of Ondrej Jirman 
+ * Based on the work of Josef Gajdusek 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_SENSOR_NUM 4
+
+#define SUN50I_H6_SENSOR_NUM   2
+#define SUN50I_H6_OFFSET   -2794
+#define SUN50I_H6_SCALE-67
+
+#define FT_TEMP_MASK   GENMASK(11, 0)
+#define TEMP_CALIB_MASKGENMASK(11, 0)
+#define TEMP_TO_REG672
+#define CALIBRATE_DEFAULT  0x800
+
+#define SUN50I_THS_CTRL0   0x00
+#define SUN50I_H6_THS_ENABLE   0x04
+#define SUN50I_H6_THS_PC   0x08
+#define SUN50I_H6_THS_DIC  0x10
+#define SUN50I_H6_THS_DIS  0x20
+#define SUN50I_H6_THS_MFC  0x30
+#define SUN50I_H6_THS_TEMP_CALIB   0xa0
+#define SUN50I_H6_THS_TEMP_DATA0xc0
+
+#define SUN50I_THS_CTRL0_T_ACQ(x)  ((GENMASK(15, 0) & (x)) << 16)
+#define SUN50I_THS_FILTER_EN   BIT(2)
+#define SUN50I_THS_FILTER_TYPE(x)  (GENMASK(1, 0) & (x))
+#define SUN50I_H6_THS_PC_TEMP_PERIOD(x)((GENMASK(19, 0) & (x)) 
<< 12)
+#define SUN50I_H6_THS_DATA_IRQ_STS(x)  BIT(x)
+
+/* millidegree celsius */
+#define SUN50I_H6_FT_DEVIATION 7000
+
+struct ths_device;
+
+struct tsensor {
+   struct ths_device   *tmdev;
+   struct thermal_zone_device  *tzd;
+   int id;
+};
+
+struct ths_device {
+   struct device   *dev;
+   struct regmap   *regmap;
+   struct reset_control*reset;
+   struct clk  *bus_clk;
+   struct tsensor  sensor[MAX_SENSOR_NUM];
+};
+
+/* Temp Unit: millidegree Celsius */
+static int sun8i_ths_reg2temp(struct ths_device *tmdev,
+

[PATCH v4 03/11] thermal: fix indentation in makefile

2019-06-23 Thread Yangtao Li
To unify code style.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/Makefile | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index fa6f8b206281..d7eafb5ef8ef 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -5,7 +5,7 @@
 
 obj-$(CONFIG_THERMAL)  += thermal_sys.o
 thermal_sys-y  += thermal_core.o thermal_sysfs.o \
-   thermal_helpers.o
+  thermal_helpers.o
 
 # interface to/from other layers providing sensors
 thermal_sys-$(CONFIG_THERMAL_HWMON)+= thermal_hwmon.o
@@ -25,11 +25,11 @@ thermal_sys-$(CONFIG_CPU_THERMAL)   += cpu_cooling.o
 thermal_sys-$(CONFIG_CLOCK_THERMAL)+= clock_cooling.o
 
 # devfreq cooling
-thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
+thermal_sys-$(CONFIG_DEVFREQ_THERMAL)  += devfreq_cooling.o
 
 # platform thermal drivers
 obj-y  += broadcom/
-obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
+obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
 obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o
 obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
@@ -50,7 +50,7 @@ obj-$(CONFIG_TI_SOC_THERMAL)  += ti-soc-thermal/
 obj-y  += st/
 obj-$(CONFIG_QCOM_TSENS)   += qcom/
 obj-y  += tegra/
-obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
+obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)  += mtk_thermal.o
 obj-$(CONFIG_GENERIC_ADC_THERMAL)  += thermal-generic-adc.o
 obj-$(CONFIG_ZX2967_THERMAL)   += zx2967_thermal.o
-- 
2.17.1



[PATCH v4 10/11] dt-bindings: thermal: add binding document for h3 thermal controller

2019-06-23 Thread Yangtao Li
This patch adds binding document for allwinner h3 thermal controller.

Signed-off-by: Yangtao Li 
---
 .../bindings/thermal/sun8i-thermal.yaml   | 29 +--
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml 
b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
index 2c5acc61ed03..1eaf68b5dd5a 100644
--- a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -16,6 +16,7 @@ description: |-
 properties:
   compatible:
 enum:
+  - allwinner,sun8i-h3-ths
   - allwinner,sun50i-h6-ths
 
   reg:
@@ -29,13 +30,22 @@ properties:
 
   clocks:
 minItems: 1
-maxItems: 1
+maxItems: 2
 
   clock-names:
-const: bus
+items:
+  - const: bus
+  - const: ahb
 
   '#thermal-sensor-cells':
-const: 1
+enum: [ 0, 1 ]
+description: |
+  Definition depends on soc version:
+
+  For "allwinner,sun8i-h3-ths",
+  value must be 0.
+  For "allwinner,sun50i-h6-ths",
+  value must be 1.
 
   nvmem-cells:
 items:
@@ -55,6 +65,19 @@ required:
   - '#thermal-sensor-cells'
 
 examples:
+  - |
+ths: ths@1c25000 {
+ compatible = "allwinner,sun8i-h3-ths";
+ reg = <0x01c25000 0x400>;
+ clocks = < CLK_BUS_THS>, < CLK_THS>;
+ clock-names = "bus", "ahb";
+ resets = < RST_BUS_THS>;
+ interrupts = ;
+ nvmem-cells = <_calib>;
+ nvmem-cell-names = "calib";
+ #thermal-sensor-cells = <0>;
+};
+
   - |
 ths: ths@5070400 {
  compatible = "allwinner,sun50i-h6-ths";
-- 
2.17.1



[PATCH v4 11/11] thermal: sun8i: add thermal driver for h3

2019-06-23 Thread Yangtao Li
This patch adds the support for allwinner h3 thermal sensor.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 72 +
 1 file changed, 72 insertions(+)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 260b24340f5b..c8ee291f3b17 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -27,6 +27,14 @@
 #define TEMP_TO_REG672
 #define CALIBRATE_DEFAULT  0x800
 
+#define SUN8I_THS_CTRL00x00
+#define SUN8I_THS_CTRL20x40
+#define SUN8I_THS_IC   0x44
+#define SUN8I_THS_IS   0x48
+#define SUN8I_THS_MFC  0x70
+#define SUN8I_THS_TEMP_CALIB   0x74
+#define SUN8I_THS_TEMP_DATA0x80
+
 #define SUN50I_THS_CTRL0   0x00
 #define SUN50I_H6_THS_ENABLE   0x04
 #define SUN50I_H6_THS_PC   0x08
@@ -36,6 +44,9 @@
 #define SUN50I_H6_THS_TEMP_CALIB   0xa0
 #define SUN50I_H6_THS_TEMP_DATA0xc0
 
+#define SUN8I_THS_CTRL0_T_ACQ0(x)  (GENMASK(15, 0) & (x))
+#define SUN8I_THS_CTRL2_T_ACQ1(x)  ((GENMASK(15, 0) & (x)) << 16)
+
 #define SUN50I_THS_CTRL0_T_ACQ(x)  ((GENMASK(15, 0) & (x)) << 16)
 #define SUN50I_THS_FILTER_EN   BIT(2)
 #define SUN50I_THS_FILTER_TYPE(x)  (GENMASK(1, 0) & (x))
@@ -121,6 +132,21 @@ static const struct regmap_config config = {
.fast_io = true,
 };
 
+static int sun8i_h3_irq_ack(struct ths_device *tmdev)
+{
+   int state, ret = 0;
+
+   regmap_read(tmdev->regmap, SUN8I_THS_IS, );
+
+   if (state & BIT(8)) {
+   regmap_write(tmdev->regmap, SUN8I_THS_IS,
+BIT(8));
+   ret |= BIT(1);
+   }
+
+   return ret;
+}
+
 static int sun50i_h6_irq_ack(struct ths_device *tmdev)
 {
int i, state, ret = 0;
@@ -154,6 +180,14 @@ static irqreturn_t sun8i_irq_thread(int irq, void *data)
return IRQ_HANDLED;
 }
 
+static int sun8i_h3_ths_calibrate(struct ths_device *tmdev,
+  u16 *caldata, int callen)
+{
+   regmap_write(tmdev->regmap, SUN8I_THS_TEMP_CALIB, *caldata);
+
+   return 0;
+}
+
 static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
   u16 *caldata, int callen)
 {
@@ -325,6 +359,32 @@ static int sun8i_ths_resource_init(struct ths_device 
*tmdev)
return ret;
 }
 
+static int sun8i_h3_thermal_init(struct ths_device *tmdev)
+{
+   /* average over 4 samples */
+   regmap_write(tmdev->regmap, SUN8I_THS_MFC,
+SUN50I_THS_FILTER_EN |
+SUN50I_THS_FILTER_TYPE(1));
+   /*
+* period = (x + 1) * 4096 / clkin; ~10ms
+* enable data interrupt
+*/
+   regmap_write(tmdev->regmap, SUN8I_THS_IC,
+SUN50I_H6_THS_PC_TEMP_PERIOD(58) | BIT(8));
+   /*
+* clkin = 24MHz
+* T acquire = clkin / (x + 1)
+*   = 20us
+* enable sensor
+*/
+   regmap_write(tmdev->regmap, SUN8I_THS_CTRL0,
+SUN8I_THS_CTRL0_T_ACQ0(479));
+   regmap_write(tmdev->regmap, SUN8I_THS_CTRL2,
+SUN8I_THS_CTRL2_T_ACQ1(479) | BIT(0));
+
+   return 0;
+}
+
 static int sun50i_thermal_init(struct ths_device *tmdev)
 {
int val;
@@ -431,6 +491,17 @@ static int sun8i_ths_remove(struct platform_device *pdev)
return 0;
 }
 
+static const struct ths_thermal_chip sun8i_h3_ths = {
+   .sensor_num = 1,
+   .offset = -1794,
+   .scale = -121,
+   .has_ahb_clk = true,
+   .temp_data_base = SUN8I_THS_TEMP_DATA,
+   .calibrate = sun8i_h3_ths_calibrate,
+   .init = sun8i_h3_thermal_init,
+   .irq_ack = sun8i_h3_irq_ack,
+};
+
 static const struct ths_thermal_chip sun50i_h6_ths = {
.sensor_num = 2,
.offset = -2794,
@@ -443,6 +514,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 };
 
 static const struct of_device_id of_ths_match[] = {
+   { .compatible = "allwinner,sun8i-h3-ths", .data = _h3_ths },
{ .compatible = "allwinner,sun50i-h6-ths", .data = _h6_ths },
{ /* sentinel */ },
 };
-- 
2.17.1



[PATCH v4 02/11] dt-bindings: thermal: add binding document for h6 thermal controller

2019-06-23 Thread Yangtao Li
This patch adds binding document for allwinner h6 thermal controller.

Signed-off-by: Yangtao Li 
---
 .../bindings/thermal/sun8i-thermal.yaml   | 71 +++
 1 file changed, 71 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml 
b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
new file mode 100644
index ..2c5acc61ed03
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/sun8i-thermal.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner SUN8I Thermal Controller Device Tree Bindings
+
+maintainers:
+  - Yangtao Li 
+
+description: |-
+  This describes the device tree binding for the Allwinner thermal
+  controller which measures the on-SoC temperatures.
+
+properties:
+  compatible:
+enum:
+  - allwinner,sun50i-h6-ths
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  resets:
+maxItems: 1
+
+  clocks:
+minItems: 1
+maxItems: 1
+
+  clock-names:
+const: bus
+
+  '#thermal-sensor-cells':
+const: 1
+
+  nvmem-cells:
+items:
+  - description: ths calibrate data
+
+  nvmem-cell-names:
+items:
+  - const: calib
+
+required:
+  - compatible
+  - reg
+  - reset
+  - clocks
+  - clock-names
+  - interrupts
+  - '#thermal-sensor-cells'
+
+examples:
+  - |
+ths: ths@5070400 {
+ compatible = "allwinner,sun50i-h6-ths";
+ reg = <0x05070400 0x100>;
+ clocks = < CLK_BUS_THS>;
+ clock-names = "bus";
+ resets = < RST_BUS_THS>;
+ interrupts = ;
+ nvmem-cells = <_calib>;
+ nvmem-cell-names = "calib";
+ #thermal-sensor-cells = <1>;
+};
+
+...
-- 
2.17.1



[PATCH v4 06/11] thermal: sun8i: get ths init func from device compatible

2019-06-23 Thread Yangtao Li
There are some differences in register initialization for
different socs. So we get different initialization functions
from device compatible.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index e473a5651436..59acbbac76e4 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -59,6 +59,7 @@ struct ths_thermal_chip {
int scale;
int ft_deviation;
int temp_data_base;
+   int (*init)(struct ths_device *tmdev);
 };
 
 struct ths_device {
@@ -362,7 +363,7 @@ static int sun8i_ths_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
 
-   ret = sun50i_thermal_init(tmdev);
+   ret = tmdev->chip->init(tmdev);
if (ret)
return ret;
 
@@ -400,6 +401,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
.scale = -67,
.ft_deviation = SUN50I_H6_FT_DEVIATION,
.temp_data_base = SUN50I_H6_THS_TEMP_DATA,
+   .init = sun50i_thermal_init,
 };
 
 static const struct of_device_id of_ths_match[] = {
-- 
2.17.1



[PATCH v4 07/11] thermal: sun8i: rework for ths irq handler func

2019-06-23 Thread Yangtao Li
Here, we do something to prepare for the subsequent
support of multiple platforms.

1) rename sun50i_h6_irq_thread to sun8i_irq_thread, because
   this function should be suitable for all platforms.

2) introduce irq_ack callback to mask interrupt register
   differences.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/sun8i_thermal.c | 27 ---
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 59acbbac76e4..ed1c19bb27cf 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -60,6 +60,7 @@ struct ths_thermal_chip {
int ft_deviation;
int temp_data_base;
int (*init)(struct ths_device *tmdev);
+   int (*irq_ack)(struct ths_device *tmdev);
 };
 
 struct ths_device {
@@ -116,23 +117,34 @@ static const struct regmap_config config = {
.fast_io = true,
 };
 
-static irqreturn_t sun50i_h6_irq_thread(int irq, void *data)
+static int sun50i_h6_irq_ack(struct ths_device *tmdev)
 {
-   struct ths_device *tmdev = data;
-   int i, state;
+   int i, state, ret = 0;
 
regmap_read(tmdev->regmap, SUN50I_H6_THS_DIS, );
 
for (i = 0; i < tmdev->chip->sensor_num; i++) {
-
if (state & SUN50I_H6_THS_DATA_IRQ_STS(i)) {
-   /* clear data irq pending */
regmap_write(tmdev->regmap, SUN50I_H6_THS_DIS,
 SUN50I_H6_THS_DATA_IRQ_STS(i));
+   ret |= BIT(i);
+   }
+   }
+
+   return ret;
+}
 
+static irqreturn_t sun8i_irq_thread(int irq, void *data)
+{
+   struct ths_device *tmdev = data;
+   int i, state;
+
+   state = tmdev->chip->irq_ack(tmdev);
+
+   for (i = 0; i < tmdev->chip->sensor_num; i++) {
+   if (state & BIT(i))
thermal_zone_device_update(tmdev->sensor[i].tzd,
   THERMAL_EVENT_UNSPECIFIED);
-   }
}
 
return IRQ_HANDLED;
@@ -377,7 +389,7 @@ static int sun8i_ths_probe(struct platform_device *pdev)
 * the end.
 */
ret = devm_request_threaded_irq(dev, irq, NULL,
-   sun50i_h6_irq_thread,
+   sun8i_irq_thread,
IRQF_ONESHOT, "ths", tmdev);
if (ret)
return ret;
@@ -402,6 +414,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
.ft_deviation = SUN50I_H6_FT_DEVIATION,
.temp_data_base = SUN50I_H6_THS_TEMP_DATA,
.init = sun50i_thermal_init,
+   .irq_ack = sun50i_h6_irq_ack,
 };
 
 static const struct of_device_id of_ths_match[] = {
-- 
2.17.1



[tip:timers/core] alarmtimer: Fix kerneldoc comment for alarmtimer_suspend()

2019-06-14 Thread tip-bot for Yangtao Li
Commit-ID:  141e1ecda356bb0034027a9acb949e97a963ba16
Gitweb: https://git.kernel.org/tip/141e1ecda356bb0034027a9acb949e97a963ba16
Author: Yangtao Li 
AuthorDate: Sat, 25 May 2019 14:39:25 -0400
Committer:  Thomas Gleixner 
CommitDate: Fri, 14 Jun 2019 17:04:04 +0200

alarmtimer: Fix kerneldoc comment for alarmtimer_suspend()

This brings the kernel doc in line with the function signature.

Signed-off-by: Yangtao Li 
Signed-off-by: Thomas Gleixner 
Cc: john.stu...@linaro.org
Cc: sb...@kernel.org
Link: https://lkml.kernel.org/r/20190525183925.18963-1-tiny.win...@gmail.com

---
 kernel/time/alarmtimer.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 0519a8805aab..57518efc3810 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -233,7 +233,6 @@ EXPORT_SYMBOL_GPL(alarm_expires_remaining);
 /**
  * alarmtimer_suspend - Suspend time callback
  * @dev: unused
- * @state: unused
  *
  * When we are going into suspend, we look through the bases
  * to see which is the soonest timer to expire. We then


[PATCH v2] iommu/omap: convert to SPDX license tags

2019-06-13 Thread Yangtao Li
Updates license to use SPDX-License-Identifier.

Signed-off-by: Yangtao Li 
Acked-by: Suman Anna 
---
v2:
-add include/linux/platform_data/iommu-omap.h
---
 drivers/iommu/omap-iommu-debug.c | 5 +
 drivers/iommu/omap-iommu.c   | 5 +
 drivers/iommu/omap-iommu.h   | 5 +
 drivers/iommu/omap-iopgtable.h   | 5 +
 include/linux/platform_data/iommu-omap.h | 5 +
 5 files changed, 5 insertions(+), 20 deletions(-)

diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index 4abc0ef522a8..55ec67a45101 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * omap iommu: debugfs interface
  *
  * Copyright (C) 2008-2009 Nokia Corporation
  *
  * Written by Hiroshi DOYU 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #include 
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index d2fb347aa4ff..e6442876913f 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * omap iommu: tlb and pagetable primitives
  *
@@ -6,10 +7,6 @@
  *
  * Written by Hiroshi DOYU ,
  * Paul Mundt and Toshihiro Kobayashi
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #include 
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 1703159ef5af..5256e17d86a7 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -1,13 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * omap iommu: main structures
  *
  * Copyright (C) 2008-2009 Nokia Corporation
  *
  * Written by Hiroshi DOYU 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #ifndef _OMAP_IOMMU_H
diff --git a/drivers/iommu/omap-iopgtable.h b/drivers/iommu/omap-iopgtable.h
index 01a315227bf0..871c2a38f453 100644
--- a/drivers/iommu/omap-iopgtable.h
+++ b/drivers/iommu/omap-iopgtable.h
@@ -1,13 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * omap iommu: pagetable definitions
  *
  * Copyright (C) 2008-2010 Nokia Corporation
  *
  * Written by Hiroshi DOYU 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #ifndef _OMAP_IOPGTABLE_H
diff --git a/include/linux/platform_data/iommu-omap.h 
b/include/linux/platform_data/iommu-omap.h
index e8b12dbf6170..a6cbca5406e0 100644
--- a/include/linux/platform_data/iommu-omap.h
+++ b/include/linux/platform_data/iommu-omap.h
@@ -1,13 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * omap iommu: main structures
  *
  * Copyright (C) 2008-2009 Nokia Corporation
  *
  * Written by Hiroshi DOYU 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #include 
-- 
2.17.0



[PATCH 04/10] iommu/qcom: convert to SPDX license tags

2019-06-13 Thread Yangtao Li
Updates license to use SPDX-License-Identifier.

Signed-off-by: Yangtao Li 
---
 drivers/iommu/qcom_iommu.c | 13 +
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c
index 8cdd3f059513..ad913720d7dd 100644
--- a/drivers/iommu/qcom_iommu.c
+++ b/drivers/iommu/qcom_iommu.c
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * IOMMU API for QCOM secure IOMMUs.  Somewhat based on arm-smmu.c
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
  * Copyright (C) 2013 ARM Limited
  * Copyright (C) 2017 Red Hat
  */
-- 
2.17.0



[PATCH 08/10] iommu/sysfs: convert to SPDX license tags

2019-06-13 Thread Yangtao Li
Updates license to use SPDX-License-Identifier.

Signed-off-by: Yangtao Li 
---
 drivers/iommu/iommu-sysfs.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c
index 44127d54e943..a193758c8122 100644
--- a/drivers/iommu/iommu-sysfs.c
+++ b/drivers/iommu/iommu-sysfs.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * IOMMU sysfs class support
  *
  * Copyright (C) 2014 Red Hat, Inc.  All rights reserved.
  * Author: Alex Williamson 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #include 
-- 
2.17.0



[PATCH 01/10] iommu/exynos: convert to SPDX license tags

2019-06-13 Thread Yangtao Li
Updates license to use SPDX-License-Identifier.

Signed-off-by: Yangtao Li 
---
 drivers/iommu/exynos-iommu.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 05c6bc099d62..938a33d2f89d 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2011,2016 Samsung Electronics Co., Ltd.
  * http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #ifdef CONFIG_EXYNOS_IOMMU_DEBUG
-- 
2.17.0



[RESEND, PATCH v4 1/2] cpufreq: Add sun50i nvmem based CPU scaling driver

2019-06-12 Thread Yangtao Li
For some SoCs, the CPU frequency subset and voltage value of each OPP
varies based on the silicon variant in use. The sun50i-cpufreq-nvmem
driver reads the efuse value from the SoC to provide the OPP framework
with required information.

Signed-off-by: Yangtao Li 
Acked-by: Maxime Ripard 
---
 MAINTAINERS|   7 +
 drivers/cpufreq/Kconfig.arm|  12 ++
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c   |   2 +
 drivers/cpufreq/sun50i-cpufreq-nvmem.c | 226 +
 5 files changed, 248 insertions(+)
 create mode 100644 drivers/cpufreq/sun50i-cpufreq-nvmem.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 57f496cff999..c57f869af9d7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -668,6 +668,13 @@ S: Maintained
 F: Documentation/i2c/busses/i2c-ali1563
 F: drivers/i2c/busses/i2c-ali1563.c
 
+ALLWINNER CPUFREQ DRIVER
+M: Yangtao Li 
+L: linux...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt
+F: drivers/cpufreq/sun50i-cpufreq-nvmem.c
+
 ALLWINNER SECURITY SYSTEM
 M: Corentin Labbe 
 L: linux-cry...@vger.kernel.org
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index f8129edc145e..5796ecf13d7f 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -19,6 +19,18 @@ config ACPI_CPPC_CPUFREQ
 
  If in doubt, say N.
 
+config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM
+   tristate "Allwinner nvmem based SUN50I CPUFreq driver"
+   depends on ARCH_SUNXI
+   depends on NVMEM_SUNXI_SID
+   select PM_OPP
+   help
+ This adds the nvmem based CPUFreq driver for Allwinner
+ h6 SoC.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sun50i-cpufreq-nvmem.
+
 config ARM_ARMADA_37XX_CPUFREQ
tristate "Armada 37xx CPUFreq support"
depends on ARCH_MVEBU && CPUFREQ_DT
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 689b26c6f949..a78b8da80383 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -78,6 +78,7 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ)+= 
scmi-cpufreq.o
 obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o
 obj-$(CONFIG_ARM_SPEAR_CPUFREQ)+= spear-cpufreq.o
 obj-$(CONFIG_ARM_STI_CPUFREQ)  += sti-cpufreq.o
+obj-$(CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM) += sun50i-cpufreq-nvmem.o
 obj-$(CONFIG_ARM_TANGO_CPUFREQ)+= tango-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)  += tegra20-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 47729a22c159..50e7810f3a28 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -105,6 +105,8 @@ static const struct of_device_id whitelist[] __initconst = {
  * platforms using "operating-points-v2" property.
  */
 static const struct of_device_id blacklist[] __initconst = {
+   { .compatible = "allwinner,sun50i-h6", },
+
{ .compatible = "calxeda,highbank", },
{ .compatible = "calxeda,ecx-2000", },
 
diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c 
b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
new file mode 100644
index ..eca32e443716
--- /dev/null
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner CPUFreq nvmem based driver
+ *
+ * The sun50i-cpufreq-nvmem driver reads the efuse value from the SoC to
+ * provide the OPP framework with required information.
+ *
+ * Copyright (C) 2019 Yangtao Li 
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_NAME_LEN   7
+
+#define NVMEM_MASK 0x7
+#define NVMEM_SHIFT5
+
+static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev;
+
+/**
+ * sun50i_cpufreq_get_efuse() - Parse and return efuse value present on SoC
+ * @versions: Set to the value parsed from efuse
+ *
+ * Returns 0 if success.
+ */
+static int sun50i_cpufreq_get_efuse(u32 *versions)
+{
+   struct nvmem_cell *speedbin_nvmem;
+   struct device_node *np;
+   struct device *cpu_dev;
+   u32 *speedbin, efuse_value;
+   size_t len;
+   int ret;
+
+   cpu_dev = get_cpu_device(0);
+   if (!cpu_dev)
+   return -ENODEV;
+
+   np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
+   if (!np)
+   return -ENOENT;
+
+   ret = of_device_is_compatible(np,
+ "allwinner,sun50i-h6-operating-points");
+   if (!ret) {
+   of_node_put(np);
+   return -ENOENT;
+   }
+
+   speedbin_nvmem = of_nvmem_cell_get(np, NULL);
+   of_node_p

[RESEND, PATCH v4 0/2] cpufreq: Add sunxi nvmem based CPU scaling driver

2019-06-12 Thread Yangtao Li
Add sunxi nvmem based CPU scaling driver, refers to qcom-cpufreq-kryo.

Yangtao Li (2):
  cpufreq: Add sun50i nvmem based CPU scaling driver
  dt-bindings: cpufreq: Document allwinner,sun50i-h6-operating-points

 .../bindings/opp/sun50i-nvmem-cpufreq.txt | 167 +
 MAINTAINERS   |   7 +
 drivers/cpufreq/Kconfig.arm   |  12 +
 drivers/cpufreq/Makefile  |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c  |   2 +
 drivers/cpufreq/sun50i-cpufreq-nvmem.c| 226 ++
 6 files changed, 415 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt
 create mode 100644 drivers/cpufreq/sun50i-cpufreq-nvmem.c

---
v4:
-Remove sunxi_cpufreq_soc_data structure for now.
-Convert to less generic name.
-Update soc_bin xlate.
v3:
-update changelog and title
-convert compatibles to allwinner,cpu-operating-points-v2
-document the valid names for opp-microvolt-
v2:
-update changelog
-convert to dev_pm_opp_set_prop_name instead of
 dev_pm_opp_set_supported_hw
-some change in OPP Node  
--- 
2.17.0



[RESEND, PATCH v4 2/2] dt-bindings: cpufreq: Document allwinner,sun50i-h6-operating-points

2019-06-12 Thread Yangtao Li
Allwinner Process Voltage Scaling Tables defines the voltage and
frequency value based on the speedbin blown in the efuse combination.
The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to
provide the OPP framework with required information.
This is used to determine the voltage and frequency value for each
OPP of operating-points-v2 table when it is parsed by the OPP framework.

The "allwinner,sun50i-h6-operating-points" DT extends the
"operating-points-v2"
with following parameters:
- nvmem-cells (NVMEM area containig the speedbin information)
- opp-microvolt-: voltage in micro Volts.
  At runtime, the platform can pick a  and matching
  opp-microvolt- property.
HW: :
sun50i-h6  speed0 speed1 speed2

Signed-off-by: Yangtao Li 
Acked-by: Maxime Ripard 
---
 .../bindings/opp/sun50i-nvmem-cpufreq.txt | 167 ++
 1 file changed, 167 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt 
b/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt
new file mode 100644
index ..7deae57a587b
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt
@@ -0,0 +1,167 @@
+Allwinner Technologies, Inc. NVMEM CPUFreq and OPP bindings
+===
+
+For some SoCs, the CPU frequency subset and voltage value of each OPP
+varies based on the silicon variant in use. Allwinner Process Voltage
+Scaling Tables defines the voltage and frequency value based on the
+speedbin blown in the efuse combination. The sun50i-cpufreq-nvmem driver
+reads the efuse value from the SoC to provide the OPP framework with
+required information.
+
+Required properties:
+
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use.
+
+In 'operating-points-v2' table:
+- compatible: Should be
+   - 'allwinner,sun50i-h6-operating-points'.
+- nvmem-cells: A phandle pointing to a nvmem-cells node representing the
+   efuse registers that has information about the speedbin
+   that is used to select the right frequency/voltage value
+   pair. Please refer the for nvmem-cells bindings
+   Documentation/devicetree/bindings/nvmem/nvmem.txt and
+   also examples below.
+
+In every OPP node:
+- opp-microvolt-: Voltage in micro Volts.
+   At runtime, the platform can pick a  and
+   matching opp-microvolt- property.
+   [See: opp.txt]
+   HW: :
+   sun50i-h6   speed0 speed1 speed2
+
+Example 1:
+-
+
+   cpus {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   cpu0: cpu@0 {
+   compatible = "arm,cortex-a53";
+   device_type = "cpu";
+   reg = <0>;
+   enable-method = "psci";
+   clocks = < CLK_CPUX>;
+   clock-latency-ns = <244144>; /* 8 32k periods */
+   operating-points-v2 = <_opp_table>;
+   #cooling-cells = <2>;
+   };
+
+   cpu1: cpu@1 {
+   compatible = "arm,cortex-a53";
+   device_type = "cpu";
+   reg = <1>;
+   enable-method = "psci";
+   clocks = < CLK_CPUX>;
+   clock-latency-ns = <244144>; /* 8 32k periods */
+   operating-points-v2 = <_opp_table>;
+   #cooling-cells = <2>;
+   };
+
+   cpu2: cpu@2 {
+   compatible = "arm,cortex-a53";
+   device_type = "cpu";
+   reg = <2>;
+   enable-method = "psci";
+   clocks = < CLK_CPUX>;
+   clock-latency-ns = <244144>; /* 8 32k periods */
+   operating-points-v2 = <_opp_table>;
+   #cooling-cells = <2>;
+   };
+
+   cpu3: cpu@3 {
+   compatible = "arm,cortex-a53";
+   device_type = "cpu";
+   reg = <3>;
+   enable-method = "psci";
+   clocks = < CLK_CPUX>;
+   clock-latency-ns = <244144>; /* 8 32k periods */
+   operating-points-v2 = <_opp_table>;
+   #cooling-cells = <2>;
+

[tip:timers/core] hrtimer: Remove unused header include

2019-06-12 Thread tip-bot for Yangtao Li
Commit-ID:  0e5aa23282f8e6ee38c18f67ddfdaaa32d3df86b
Gitweb: https://git.kernel.org/tip/0e5aa23282f8e6ee38c18f67ddfdaaa32d3df86b
Author: Yangtao Li 
AuthorDate: Fri, 7 Jun 2019 13:42:53 -0400
Committer:  Thomas Gleixner 
CommitDate: Wed, 12 Jun 2019 10:21:17 +0200

hrtimer: Remove unused header include

seq_file.h does not need to be included, so remove it.

Signed-off-by: Yangtao Li 
Signed-off-by: Thomas Gleixner 
Link: https://lkml.kernel.org/r/20190607174253.27403-1-tiny.win...@gmail.com

---
 kernel/time/hrtimer.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 41dfff23c1f9..edb230aba3d1 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -30,7 +30,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 


[PATCH 4/5] random: fix typo in add_timer_randomness()

2019-06-07 Thread Yangtao Li
s/entimate/estimate

Signed-off-by: Yangtao Li 
---
 drivers/char/random.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index f0c834af14a8..885707ac8e3b 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1247,7 +1247,7 @@ static void add_timer_randomness(struct timer_rand_state 
*state, unsigned num)
/*
 * delta is now minimum absolute delta.
 * Round down by 1 bit on general principles,
-* and limit entropy entimate to 12 bits.
+* and limit entropy estimate to 12 bits.
 */
credit_entropy_bits(r, min_t(int, fls(delta>>1), 11));
 }
-- 
2.17.0



[PATCH 5/5] random: remove some dead code of poolinfo

2019-06-07 Thread Yangtao Li
Since it is not being used, so delete it.

Signed-off-by: Yangtao Li 
---
 drivers/char/random.c | 27 ---
 1 file changed, 27 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 885707ac8e3b..d83401e35f71 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -441,33 +441,6 @@ static const struct poolinfo {
/* was: x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 */
/* x^32 + x^26 + x^19 + x^14 + x^7 + x + 1 */
{ S(32),26, 19, 14, 7,  1 },
-#if 0
-   /* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1  -- 115 */
-   { S(2048),  1638,   1231,   819,411,1 },
-
-   /* x^1024 + x^817 + x^615 + x^412 + x^204 + x + 1 -- 290 */
-   { S(1024),  817,615,412,204,1 },
-
-   /* x^1024 + x^819 + x^616 + x^410 + x^207 + x^2 + 1 -- 115 */
-   { S(1024),  819,616,410,207,2 },
-
-   /* x^512 + x^411 + x^308 + x^208 + x^104 + x + 1 -- 225 */
-   { S(512),   411,308,208,104,1 },
-
-   /* x^512 + x^409 + x^307 + x^206 + x^102 + x^2 + 1 -- 95 */
-   { S(512),   409,307,206,102,2 },
-   /* x^512 + x^409 + x^309 + x^205 + x^103 + x^2 + 1 -- 95 */
-   { S(512),   409,309,205,103,2 },
-
-   /* x^256 + x^205 + x^155 + x^101 + x^52 + x + 1 -- 125 */
-   { S(256),   205,155,101,52, 1 },
-
-   /* x^128 + x^103 + x^78 + x^51 + x^27 + x^2 + 1 -- 70 */
-   { S(128),   103,78, 51, 27, 2 },
-
-   /* x^64 + x^52 + x^39 + x^26 + x^14 + x + 1 -- 15 */
-   { S(64),52, 39, 26, 14, 1 },
-#endif
 };
 
 /*
-- 
2.17.0



[PATCH 3/5] random: Add and use pr_fmt()

2019-06-07 Thread Yangtao Li
Prefix all printk/pr_ messages with "random: " to make the
logging a bit more consistent.

Miscellanea:

o Convert a printks to pr_notice
o Whitespace to align to open parentheses
o Remove embedded "random: " from pr_* as pr_fmt adds it

Signed-off-by: Yangtao Li 
---
 drivers/char/random.c | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index d714a458f088..f0c834af14a8 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -307,6 +307,8 @@
  * Eastlake, Steve Crocker, and Jeff Schiller.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include 
 #include 
 #include 
@@ -760,7 +762,7 @@ static void credit_entropy_bits(struct entropy_store *r, 
int nbits)
}
 
if (WARN_ON(entropy_count < 0)) {
-   pr_warn("random: negative entropy/overflow: pool %s count %d\n",
+   pr_warn("negative entropy/overflow: pool %s count %d\n",
r->name, entropy_count);
entropy_count = 0;
} else if (entropy_count > pool_size)
@@ -883,7 +885,7 @@ static void crng_initialize(struct crng_state *crng)
invalidate_batched_entropy();
numa_crng_init();
crng_init = 2;
-   pr_notice("random: crng done (trusting CPU's manufacturer)\n");
+   pr_notice("crng done (trusting CPU's manufacturer)\n");
}
crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
 }
@@ -946,7 +948,7 @@ static int crng_fast_load(const char *cp, size_t len)
invalidate_batched_entropy();
crng_init = 1;
wake_up_interruptible(_init_wait);
-   pr_notice("random: fast init done\n");
+   pr_notice("fast init done\n");
}
return 1;
 }
@@ -1031,15 +1033,15 @@ static void crng_reseed(struct crng_state *crng, struct 
entropy_store *r)
crng_init = 2;
process_random_ready_list();
wake_up_interruptible(_init_wait);
-   pr_notice("random: crng init done\n");
+   pr_notice("crng init done\n");
if (unseeded_warning.missed) {
-   pr_notice("random: %d get_random_xx warning(s) missed "
+   pr_notice("%d get_random_xx warning(s) missed "
  "due to ratelimiting\n",
  unseeded_warning.missed);
unseeded_warning.missed = 0;
}
if (urandom_warning.missed) {
-   pr_notice("random: %d urandom warning(s) missed "
+   pr_notice("%d urandom warning(s) missed "
  "due to ratelimiting\n",
  urandom_warning.missed);
urandom_warning.missed = 0;
@@ -1463,7 +1465,7 @@ static size_t account(struct entropy_store *r, size_t 
nbytes, int min,
ibytes = 0;
 
if (WARN_ON(entropy_count < 0)) {
-   pr_warn("random: negative entropy count: pool %s count %d\n",
+   pr_warn("negative entropy count: pool %s count %d\n",
r->name, entropy_count);
entropy_count = 0;
}
@@ -1682,7 +1684,7 @@ static void _warn_unseeded_randomness(const char 
*func_name, void *caller,
print_once = true;
 #endif
if (__ratelimit(_warning))
-   pr_notice("random: %s called from %pS with crng_init=%d\n",
+   pr_notice("%s called from %pS with crng_init=%d\n",
  func_name, caller, crng_init);
 }
 
@@ -1964,9 +1966,8 @@ urandom_read(struct file *file, char __user *buf, size_t 
nbytes, loff_t *ppos)
if (!crng_ready() && maxwarn > 0) {
maxwarn--;
if (__ratelimit(_warning))
-   printk(KERN_NOTICE "random: %s: uninitialized "
-  "urandom read (%zd bytes read)\n",
-  current->comm, nbytes);
+   pr_notice("%s: uninitialized urandom read (%zd bytes 
read)\n",
+ current->comm, nbytes);
spin_lock_irqsave(_crng.lock, flags);
crng_init_cnt = 0;
spin_unlock_irqrestore(_crng.lock, flags);
-- 
2.17.0



[PATCH 2/5] random: convert to ENTROPY_BITS

2019-06-07 Thread Yangtao Li
Use DEFINE_SHOW_ATTRIBUTE macro to enhance code readability.

Signed-off-by: Yangtao Li 
---
 drivers/char/random.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index bebf622c61c4..d714a458f088 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -788,7 +788,7 @@ static void credit_entropy_bits(struct entropy_store *r, 
int nbits)
if (entropy_bits < 128)
return;
crng_reseed(_crng, r);
-   entropy_bits = r->entropy_count >> ENTROPY_SHIFT;
+   entropy_bits = ENTROPY_BITS(r);
}
 
/* initialize the blocking pool if necessary */
@@ -1396,8 +1396,7 @@ EXPORT_SYMBOL_GPL(add_disk_randomness);
 static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes);
 static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 {
-   if (!r->pull ||
-   r->entropy_count >= (nbytes << (ENTROPY_SHIFT + 3)) ||
+   if (!r->pull || ENTROPY_BITS(r) >= (nbytes << 3) ||
r->entropy_count > r->poolinfo->poolfracbits)
return;
 
@@ -1435,8 +1434,7 @@ static void push_to_pool(struct work_struct *work)
  push_work);
BUG_ON(!r);
_xfer_secondary_pool(r, random_read_wakeup_bits/8);
-   trace_push_to_pool(r->name, r->entropy_count >> ENTROPY_SHIFT,
-  r->pull->entropy_count >> ENTROPY_SHIFT);
+   trace_push_to_pool(r->name, ENTROPY_BITS(r), ENTROPY_BITS(r->pull));
 }
 
 /*
@@ -1479,8 +1477,7 @@ static size_t account(struct entropy_store *r, size_t 
nbytes, int min,
goto retry;
 
trace_debit_entropy(r->name, 8 * ibytes);
-   if (ibytes &&
-   (r->entropy_count >> ENTROPY_SHIFT) < random_write_wakeup_bits) {
+   if (ibytes && ENTROPY_BITS(r) < random_write_wakeup_bits) {
wake_up_interruptible(_write_wait);
kill_fasync(, SIGIO, POLL_OUT);
}
-- 
2.17.0



[PATCH 1/5] random: remove unnecessary unlikely()

2019-06-07 Thread Yangtao Li
WARN_ON() already contains an unlikely(), so it's not necessary to use
unlikely.

Signed-off-by: Yangtao Li 
---
 drivers/char/random.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 5d5ea4ce1442..bebf622c61c4 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -759,10 +759,9 @@ static void credit_entropy_bits(struct entropy_store *r, 
int nbits)
} while (unlikely(entropy_count < pool_size-2 && pnfrac));
}
 
-   if (unlikely(entropy_count < 0)) {
+   if (WARN_ON(entropy_count < 0)) {
pr_warn("random: negative entropy/overflow: pool %s count %d\n",
r->name, entropy_count);
-   WARN_ON(1);
entropy_count = 0;
} else if (entropy_count > pool_size)
entropy_count = pool_size;
@@ -1465,10 +1464,9 @@ static size_t account(struct entropy_store *r, size_t 
nbytes, int min,
if (ibytes < min)
ibytes = 0;
 
-   if (unlikely(entropy_count < 0)) {
+   if (WARN_ON(entropy_count < 0)) {
pr_warn("random: negative entropy count: pool %s count %d\n",
r->name, entropy_count);
-   WARN_ON(1);
entropy_count = 0;
}
nfrac = ibytes << (ENTROPY_SHIFT + 3);
-- 
2.17.0



[PATCH] hrtimer: remove unused header files

2019-06-07 Thread Yangtao Li
seq_file.h does not need to be included, so remove it.

Signed-off-by: Yangtao Li 
---
 kernel/time/hrtimer.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 41dfff23c1f9..edb230aba3d1 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -30,7 +30,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
-- 
2.17.0



[PATCH] alarmtimer: fix kerneldoc comment for alarmtimer_suspend

2019-05-25 Thread Yangtao Li
This brings the kernel doc in line with the function signature.

Signed-off-by: Yangtao Li 
---
 kernel/time/alarmtimer.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 0519a8805aab..57518efc3810 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -233,7 +233,6 @@ EXPORT_SYMBOL_GPL(alarm_expires_remaining);
 /**
  * alarmtimer_suspend - Suspend time callback
  * @dev: unused
- * @state: unused
  *
  * When we are going into suspend, we look through the bases
  * to see which is the soonest timer to expire. We then
-- 
2.17.0



[PATCH v3 1/3] thermal: sun8i: add thermal driver for h6

2019-05-25 Thread Yangtao Li
This patch adds the support for allwinner thermal sensor, within
allwinner SoC. It will register sensors for thermal framework
and use device tree to bind cooling device.

Signed-off-by: Yangtao Li 
---
 MAINTAINERS |   7 +
 drivers/thermal/Kconfig |  14 +
 drivers/thermal/Makefile|   1 +
 drivers/thermal/sun8i_thermal.c | 437 
 4 files changed, 459 insertions(+)
 create mode 100644 drivers/thermal/sun8i_thermal.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 2336dd26ece4..d312f9eecf0d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -674,6 +674,13 @@ L: linux-cry...@vger.kernel.org
 S: Maintained
 F: drivers/crypto/sunxi-ss/
 
+ALLWINNER THERMAL DRIVER
+M: Yangtao Li 
+L: linux...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+F: drivers/thermal/sun8i_thermal.c
+
 ALLWINNER VPU DRIVER
 M: Maxime Ripard 
 M: Paul Kocialkowski 
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 9966364a6deb..e5465053d66f 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -262,6 +262,20 @@ config SPEAR_THERMAL
  Enable this to plug the SPEAr thermal sensor driver into the Linux
  thermal framework.
 
+config SUN8I_THERMAL
+   tristate "Allwinner sun8i thermal driver"
+   depends on ARCH_SUNXI || COMPILE_TEST
+   depends on HAS_IOMEM
+   depends on NVMEM_SUNXI_SID
+   depends on OF
+   depends on RESET_CONTROLLER
+   help
+ Support for the sun8i thermal sensor driver into the Linux thermal
+ framework.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sun8i-thermal.
+
 config ROCKCHIP_THERMAL
tristate "Rockchip thermal driver"
depends on ARCH_ROCKCHIP || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 74a37c7f847a..fa6f8b206281 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -31,6 +31,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
 obj-y  += broadcom/
 obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
 obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o
+obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
 obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
 obj-$(CONFIG_RCAR_GEN3_THERMAL)+= rcar_gen3_thermal.o
diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
new file mode 100644
index ..a9cc2197f4cb
--- /dev/null
+++ b/drivers/thermal/sun8i_thermal.c
@@ -0,0 +1,437 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Thermal sensor driver for Allwinner SOC
+ * Copyright (C) 2019 Yangtao Li
+ *
+ * Based on the work of Icenowy Zheng 
+ * Based on the work of Ondrej Jirman 
+ * Based on the work of Josef Gajdusek 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_SENSOR_NUM 4
+
+#define FT_TEMP_MASK   GENMASK(11, 0)
+#define TEMP_CALIB_MASKGENMASK(11, 0)
+#define TEMP_TO_REG672
+#define CALIBRATE_DEFAULT  0x800
+
+#define SUN50I_THS_CTRL0   0x00
+#define SUN50I_H6_THS_ENABLE   0x04
+#define SUN50I_H6_THS_PC   0x08
+#define SUN50I_H6_THS_DIC  0x10
+#define SUN50I_H6_THS_DIS  0x20
+#define SUN50I_H6_THS_MFC  0x30
+#define SUN50I_H6_THS_TEMP_CALIB   0xa0
+#define SUN50I_H6_THS_TEMP_DATA0xc0
+
+#define SUN50I_THS_CTRL0_T_ACQ(x)  ((GENMASK(15, 0) & (x)) << 16)
+#define SUN50I_THS_FILTER_EN   BIT(2)
+#define SUN50I_THS_FILTER_TYPE(x)  (GENMASK(1, 0) & (x))
+#define SUN50I_H6_THS_PC_TEMP_PERIOD(x)((GENMASK(19, 0) & (x)) 
<< 12)
+#define SUN50I_H6_THS_DATA_IRQ_STS(x)  BIT(x)
+
+/* millidegree celsius */
+#define SUN50I_H6_FT_DEVIATION 7000
+
+struct ths_device;
+
+struct tsensor {
+   struct ths_device   *tmdev;
+   struct thermal_zone_device  *tzd;
+   int id;
+   wait_queue_head_t   wait_queue;
+};
+
+struct ths_thermal_chip {
+   int sensor_num;
+   int offset;
+   int scale;
+   int ft_deviation;
+   int temp_calib_base;
+   int temp_data_base;
+   int (*calibrate)(struct ths_device *tmdev);
+   int (*init)(struct ths_device *tmdev);
+   irqreturn_t (*irq_thread)(int irq, void *data);
+};
+
+struct ths_device {
+   const struct ths_thermal

[PATCH v3 2/3] dt-bindings: thermal: add binding document for h6 thermal controller

2019-05-25 Thread Yangtao Li
This patch adds binding document for allwinner h6 thermal controller.

Signed-off-by: Yangtao Li 
---
 .../bindings/thermal/sun8i-thermal.yaml   | 71 +++
 1 file changed, 71 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml 
b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
new file mode 100644
index ..54cf1277870e
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/sun8i-thermal.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner SUN8I Thermal Controller Device Tree Bindings
+
+maintainers:
+  - Yangtao Li 
+
+description: |-
+  This describes the device tree binding for the Allwinner thermal
+  controller which measures the on-SoC temperatures.
+
+properties:
+  compatible:
+enum:
+  - allwinner,sun50i-h6-ths
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  resets:
+maxItems: 1
+
+  clocks:
+items:
+  - description: ths bus clock
+
+  clock-names:
+items:
+  - const: bus
+
+  "#thermal-sensor-cells":
+enum: [ 0, 1 ]
+
+  nvmem-cells:
+items:
+  - description: ths calibrate data
+
+  nvmem-cell-names:
+items:
+  - const: calib
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - reset
+  - clocks
+  - clock-names
+
+examples:
+  - |
+ths: ths@5070400 {
+ compatible = "allwinner,sun50i-h6-ths";
+ reg = <0x05070400 0x100>;
+ clocks = < CLK_BUS_THS>;
+ clock-names = "bus";
+ resets = < RST_BUS_THS>;
+ interrupts = ;
+ nvmem-cells = <_calib>;
+ nvmem-cell-names = "calib";
+ #thermal-sensor-cells = <1>;
+};
+
+...
-- 
2.17.0



[PATCH v3 3/3] thermal: fix indentation in makefile

2019-05-25 Thread Yangtao Li
To unify code style.

Signed-off-by: Yangtao Li 
---
 drivers/thermal/Makefile | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index fa6f8b206281..d7eafb5ef8ef 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -5,7 +5,7 @@
 
 obj-$(CONFIG_THERMAL)  += thermal_sys.o
 thermal_sys-y  += thermal_core.o thermal_sysfs.o \
-   thermal_helpers.o
+  thermal_helpers.o
 
 # interface to/from other layers providing sensors
 thermal_sys-$(CONFIG_THERMAL_HWMON)+= thermal_hwmon.o
@@ -25,11 +25,11 @@ thermal_sys-$(CONFIG_CPU_THERMAL)   += cpu_cooling.o
 thermal_sys-$(CONFIG_CLOCK_THERMAL)+= clock_cooling.o
 
 # devfreq cooling
-thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
+thermal_sys-$(CONFIG_DEVFREQ_THERMAL)  += devfreq_cooling.o
 
 # platform thermal drivers
 obj-y  += broadcom/
-obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
+obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
 obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o
 obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
@@ -50,7 +50,7 @@ obj-$(CONFIG_TI_SOC_THERMAL)  += ti-soc-thermal/
 obj-y  += st/
 obj-$(CONFIG_QCOM_TSENS)   += qcom/
 obj-y  += tegra/
-obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
+obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)  += mtk_thermal.o
 obj-$(CONFIG_GENERIC_ADC_THERMAL)  += thermal-generic-adc.o
 obj-$(CONFIG_ZX2967_THERMAL)   += zx2967_thermal.o
-- 
2.17.0



[PATCH v3 0/3] add thermal driver for h6

2019-05-25 Thread Yangtao Li
This patchset add support for H6 thermal sensor.

BWY, do a cleanup in thermal makfile.

Yangtao Li (3):
  thermal: sun8i: add thermal driver for h6
  dt-bindings: thermal: add binding document for h6 thermal controller
  thermal: fix indentation in makefile

 .../bindings/thermal/sun8i-thermal.yaml   |  71 +++
 MAINTAINERS   |   7 +
 drivers/thermal/Kconfig   |  14 +
 drivers/thermal/Makefile  |   9 +-
 drivers/thermal/sun8i_thermal.c   | 437 ++
 5 files changed, 534 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
 create mode 100644 drivers/thermal/sun8i_thermal.c

---
v3:
-Add a sun8i prefix to some function
-Remove disable callback and rename enable to init
-Remove clock enable, calibration from init callback
-Convert driver to interrupt based
-Convert doc to yaml file
---
2.17.0



[PATCH v2 1/2] thermal: sun8i: add thermal driver for h6

2019-05-16 Thread Yangtao Li
This patch adds the support for allwinner thermal sensor, within
allwinner SoC. It will register sensors for thermal framework
and use device tree to bind cooling device.

Signed-off-by: Yangtao Li 
---
 MAINTAINERS |   7 +
 drivers/thermal/Kconfig |  14 ++
 drivers/thermal/Makefile|   1 +
 drivers/thermal/sun8i_thermal.c | 422 
 4 files changed, 444 insertions(+)
 create mode 100644 drivers/thermal/sun8i_thermal.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 005902ea1450..4e753ed20cd0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -674,6 +674,13 @@ L: linux-cry...@vger.kernel.org
 S: Maintained
 F: drivers/crypto/sunxi-ss/
 
+ALLWINNER THERMAL DRIVER
+M: Yangtao Li 
+L: linux...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/thermal/sun8i-thermal.txt
+F: drivers/thermal/sun8i_thermal.c
+
 ALLWINNER VPU DRIVER
 M: Maxime Ripard 
 M: Paul Kocialkowski 
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 66a709d5d6b9..f03d941c5686 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -263,6 +263,20 @@ config SPEAR_THERMAL
  Enable this to plug the SPEAr thermal sensor driver into the Linux
  thermal framework.
 
+config SUN8I_THERMAL
+   tristate "Allwinner sun8i thermal driver"
+   depends on ARCH_SUNXI || COMPILE_TEST
+   depends on HAS_IOMEM
+   depends on NVMEM_SUNXI_SID
+   depends on OF
+   depends on RESET_CONTROLLER
+   help
+ Support for the sun8i thermal sensor driver into the Linux thermal
+ framework.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sun8i-thermal.
+
 config ROCKCHIP_THERMAL
tristate "Rockchip thermal driver"
depends on ARCH_ROCKCHIP || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 74a37c7f847a..fa6f8b206281 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -31,6 +31,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
 obj-y  += broadcom/
 obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
 obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o
+obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
 obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
 obj-$(CONFIG_RCAR_GEN3_THERMAL)+= rcar_gen3_thermal.o
diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
new file mode 100644
index ..c9920f58fc80
--- /dev/null
+++ b/drivers/thermal/sun8i_thermal.c
@@ -0,0 +1,422 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Thermal sensor driver for Allwinner SOC
+ * Copyright (C) 2019 Yangtao Li
+ *
+ * Based on the work of Icenowy Zheng 
+ * Based on the work of Ondrej Jirman 
+ * Based on the work of Josef Gajdusek 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_SENSOR_NUM 4
+
+#define FT_TEMP_MASK   GENMASK(11, 0)
+#define TEMP_CALIB_MASKGENMASK(11, 0)
+#define TEMP_TO_REG672
+#define CALIBRATE_DEFAULT  0x800
+
+#define SUN50I_THS_CTRL0   0x00
+#define SUN50I_H6_THS_ENABLE   0x04
+#define SUN50I_H6_THS_PC   0x08
+#define SUN50I_H6_THS_DIC  0x10
+#define SUN50I_H6_THS_DIS  0x20
+#define SUN50I_H6_THS_MFC  0x30
+#define SUN50I_H6_THS_TEMP_CALIB   0xa0
+#define SUN50I_H6_THS_TEMP_DATA0xc0
+
+#define SUN50I_THS_CTRL0_T_ACQ(x)  ((GENMASK(15, 0) & (x)) << 16)
+#define SUN50I_THS_FILTER_EN   BIT(2)
+#define SUN50I_THS_FILTER_TYPE(x)  (GENMASK(1, 0) & (x))
+#define SUN50I_H6_THS_PC_TEMP_PERIOD(x)((GENMASK(19, 0) & (x)) 
<< 12)
+#define SUN50I_H6_THS_DATA_IRQ_STS(x)  BIT(x)
+
+/* millidegree celsius */
+#define SUN50I_H6_FT_DEVIATION 7000
+
+struct ths_device;
+
+struct tsensor {
+   struct ths_device   *tmdev;
+   struct thermal_zone_device  *tzd;
+   int id;
+};
+
+struct ths_thermal_chip {
+   int sensor_num;
+   int offset;
+   int scale;
+   int ft_deviation;
+   int temp_calib_base;
+   int temp_data_base;
+   int (*enable)(struct ths_device *tmdev);
+   int (*disable)(struct ths_device *tmdev);
+   irqreturn_t (*irq_thread)(int irq, void *data);
+};
+
+struct ths_device {
+   const struct ths_thermal_chip   *chip;
+   struct device  

[PATCH v2 2/2] dt-bindings: thermal: add binding document for h6 thermal controller

2019-05-16 Thread Yangtao Li
This patch adds binding document for allwinner h6 thermal controller.

Signed-off-by: Yangtao Li 
---
 .../bindings/thermal/sun8i-thermal.txt| 34 +++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.txt

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.txt 
b/Documentation/devicetree/bindings/thermal/sun8i-thermal.txt
new file mode 100644
index ..bd417260501f
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.txt
@@ -0,0 +1,34 @@
+* Allwinner Thermal
+
+This describes the device tree binding for the Allwinner thermal controller
+which measures the on-SoC temperatures.
+
+Required properties:
+- compatible:
+  - "allwinner,sun50i-h6-ths" : For H6
+- reg: Address range of the thermal controller
+- clocks, clock-names: Clocks needed for the thermal controller.
+  The required clocks for h6 are: "bus".
+- resets: Reference to the reset controller controlling the thermal controller.
+- interrupts: IRQ for the thermal controller
+- #thermal-sensor-cells : For H6 Should be 1.
+ See ./thermal.txt for a description.
+
+Optional properties:
+- nvmem-cells: A phandle to the calibration data provided by a nvmem device. If
+  unspecified default values shall be used.
+- nvmem-cell-names: Should be "calib".
+
+Example:
+
+   ths: ths@1c25000 {
+   compatible = "allwinner,sun50i-h6-ths";
+   reg = <0x05070400 0x100>;
+   clocks = < CLK_BUS_THS>;
+   clock-names = "bus";
+   resets = < RST_BUS_THS>;
+   interrupts = ;
+   nvmem-cells = <_calib>;
+   nvmem-cell-names = "calib";
+   #thermal-sensor-cells = <1>;
+   };
-- 
2.17.0



[PATCH v2 0/2] add thermal driver for h6

2019-05-16 Thread Yangtao Li
This patchset supprt H6 thermal controller.

Yangtao Li (2):
  thermal: sun8i: add thermal driver for h6
  dt-bindings: thermal: add binding document for h6 thermal controller

 .../bindings/thermal/sun8i-thermal.txt|  34 ++
 MAINTAINERS   |   7 +
 drivers/thermal/Kconfig   |  14 +
 drivers/thermal/Makefile  |   1 +
 drivers/thermal/sun8i_thermal.c   | 422 ++
 5 files changed, 478 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.txt
 create mode 100644 drivers/thermal/sun8i_thermal.c

---
v2:
-Additions and deletions of some comments
-Change some function prefix to "ths_"
-Support interrupt
---
2.17.0



[PATCH] iio: adc: sun4i-gpadc-iio convert to SPDX license tags

2019-05-12 Thread Yangtao Li
Updates license to use SPDX-License-Identifier.

Signed-off-by: Yangtao Li 
---
 drivers/iio/adc/sun4i-gpadc-iio.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c 
b/drivers/iio/adc/sun4i-gpadc-iio.c
index 04d7147e0110..f13c6248a662 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /* ADC driver for sunxi platforms' (A10, A13 and A31) GPADC
  *
  * Copyright (c) 2016 Quentin Schulz 
  *
- * This program is free software; you can redistribute it and/or modify it 
under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- *
  * The Allwinner SoCs all have an ADC that can also act as a touchscreen
  * controller and a thermal sensor.
  * The thermal sensor works only when the ADC acts as a touchscreen controller
-- 
2.17.0



[PATCH 2/3] thermal: sun50i: add thermal driver for h6

2019-05-12 Thread Yangtao Li
This patch adds the support for allwinner thermal sensor, within
allwinner SoC. It will register sensors for thermal framework
and use device tree to bind cooling device.

Based on driver code found here:
https://megous.com/git/linux and 
https://github.com/Allwinner-Homlet/H6-BSP4.9-linux

Signed-off-by: Yangtao Li 
---
 MAINTAINERS  |   7 +
 drivers/thermal/Kconfig  |  14 ++
 drivers/thermal/Makefile |   1 +
 drivers/thermal/sun50i_thermal.c | 357 +++
 4 files changed, 379 insertions(+)
 create mode 100644 drivers/thermal/sun50i_thermal.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 3c65228e93c5..8da56582e72a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -674,6 +674,13 @@ L: linux-cry...@vger.kernel.org
 S: Maintained
 F: drivers/crypto/sunxi-ss/
 
+ALLWINNER THERMAL DRIVER
+M: Yangtao Li 
+L: linux...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/thermal/sun50i-thermal.txt
+F: drivers/thermal/sun50i_thermal.c
+
 ALLWINNER VPU DRIVER
 M: Maxime Ripard 
 M: Paul Kocialkowski 
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 653aa27a25a4..2a8d1c98c6ca 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -252,6 +252,20 @@ config SPEAR_THERMAL
  Enable this to plug the SPEAr thermal sensor driver into the Linux
  thermal framework.
 
+config SUN50I_THERMAL
+   tristate "Allwinner sun50i thermal driver"
+   depends on ARCH_SUNXI || COMPILE_TEST
+   depends on HAS_IOMEM
+   depends on NVMEM
+   depends on OF
+   depends on RESET_CONTROLLER
+   help
+ Support for the sun50i thermal sensor driver into the Linux thermal
+ framework.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sun50i-thermal.
+
 config ROCKCHIP_THERMAL
tristate "Rockchip thermal driver"
depends on ARCH_ROCKCHIP || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 486d682be047..a09b30b90003 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -30,6 +30,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
 # platform thermal drivers
 obj-y  += broadcom/
 obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o
+obj-$(CONFIG_SUN50I_THERMAL)   += sun50i_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
 obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
 obj-$(CONFIG_RCAR_GEN3_THERMAL)+= rcar_gen3_thermal.o
diff --git a/drivers/thermal/sun50i_thermal.c b/drivers/thermal/sun50i_thermal.c
new file mode 100644
index ..3bdb3677b3d4
--- /dev/null
+++ b/drivers/thermal/sun50i_thermal.c
@@ -0,0 +1,357 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Thermal sensor driver for Allwinner SOC
+ * Copyright (C) 2019 Yangtao Li
+ *
+ * Based on the work of Icenowy Zheng 
+ * Based on the work of Ondrej Jirman 
+ * Based on the work of Josef Gajdusek 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_SENSOR_NUM 4
+
+#define FT_TEMP_MASK   GENMASK(11, 0)
+#define TEMP_CALIB_MASKGENMASK(11, 0)
+#define TEMP_TO_REG672
+#define CALIBRATE_DEFAULT  0x800
+
+#define SUN50I_THS_CTRL0   0x00
+#define SUN50I_H6_THS_ENABLE   0x04
+#define SUN50I_H6_THS_PC   0x08
+#define SUN50I_H6_THS_MFC  0x30
+#define SUN50I_H6_TEMP_CALIB   0xa0
+#define SUN50I_H6_TEMP_DATA0xc0
+
+#define SUN50I_THS_CTRL0_T_ACQ(x)  ((GENMASK(15, 0) & (x)) << 16)
+#define SUN50I_THS_FILTER_EN   BIT(2)
+#define SUN50I_THS_FILTER_TYPE(x)  (GENMASK(1, 0) & (x))
+#define SUN50I_H6_THS_PC_TEMP_PERIOD(x)((GENMASK(19, 0) & (x)) 
<< 12)
+
+/* millidegree celsius */
+#define SUN50I_H6_FT_DEVIATION 7000
+
+struct tsens_device;
+
+struct tsensor {
+   struct tsens_device *tmdev;
+   struct thermal_zone_device  *tzd;
+   int id;
+};
+
+struct sun50i_thermal_chip {
+   int sensor_num;
+   int offset;
+   int scale;
+   int ft_deviation;
+   int temp_calib_base;
+   int temp_data_base;
+   int (*enable)(struct tsens_device *tmdev);
+   int (*disable)(struct tsens_device *tmdev);
+};
+
+
+struct tsens_device {
+   const struct sun50i_thermal_chip*chip;
+   struct device   *dev;
+   struct regmap   *regmap;
+   struct reset_control*reset;
+   struct clk  *bus_clk;
+   st

[PATCH 3/3] dt-bindings: thermal: add binding document for h6 thermal controller

2019-05-12 Thread Yangtao Li
This patch adds binding document for allwinner h6 thermal controller.

Signed-off-by: Yangtao Li 
---
 .../bindings/thermal/sun50i-thermal.txt   | 32 +++
 1 file changed, 32 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun50i-thermal.txt

diff --git a/Documentation/devicetree/bindings/thermal/sun50i-thermal.txt 
b/Documentation/devicetree/bindings/thermal/sun50i-thermal.txt
new file mode 100644
index ..67eda7794262
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/sun50i-thermal.txt
@@ -0,0 +1,32 @@
+Binding for Thermal Sensor of Allwinner SOC.
+
+This describes the device tree binding for the Allwinner thermal controller
+which measures the on-SoC temperatures.
+
+Required properties:
+- compatible:
+  - "allwinner,sun50i-h6-ths" : For H6
+- reg: Address range of the thermal controller
+- clocks, clock-names: Clocks needed for the thermal controller.
+  The required clocks for h6 are: "bus".
+- resets, reset-names: Reference to the reset controller controlling
+  the thermal controller.
+- nvmem-cells: A phandle to the calibration data provided by a nvmem device. If
+  unspecified default values shall be used.
+- nvmem-cell-names: Should be "calib"
+- #thermal-sensor-cells : For H6 Should be 1.
+ See ./thermal.txt for a description.
+
+Example:
+
+   ths: ths@1c25000 {
+   compatible = "allwinner,sun50i-h6-ths";
+   reg = <0x05070400 0x100>;
+   clocks = < CLK_BUS_THS>;
+   clock-names = "bus";
+   resets = < RST_BUS_THS>;
+   reset-names = "bus";
+   nvmem-cells = <_calib>;
+   nvmem-cell-names = "calib";
+   #thermal-sensor-cells = <1>;
+   };
-- 
2.17.0



[PATCH 1/3] arm64: defconfig: add allwinner sid support

2019-05-12 Thread Yangtao Li
Sid contains speedbin information and temperature sensor
calibration information and more, which are important for SOC.

This patch enables CONFIG_NVMEM_SUNXI_SID by default.

Signed-off-by: Yangtao Li 
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 2d9c39033c1a..8c23dd60f906 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -736,6 +736,7 @@ CONFIG_PHY_TEGRA_XUSB=y
 CONFIG_HISI_PMU=y
 CONFIG_QCOM_L2_PMU=y
 CONFIG_QCOM_L3_PMU=y
+CONFIG_NVMEM_SUNXI_SID=y
 CONFIG_QCOM_QFPROM=y
 CONFIG_ROCKCHIP_EFUSE=y
 CONFIG_UNIPHIER_EFUSE=y
-- 
2.17.0



[PATCH 0/3] add thermal driver for h6

2019-05-12 Thread Yangtao Li
This patchset support thermal driver of allwinner H6.

Yangtao Li (3):
  arm64: defconfig: add allwinner sid support
  thermal: sun50i: add thermal driver for h6
  dt-bindings: thermal: add binding document for h6 thermal controller

 .../bindings/thermal/sun50i-thermal.txt   |  32 ++
 MAINTAINERS   |   7 +
 arch/arm64/configs/defconfig  |   1 +
 drivers/thermal/Kconfig   |  14 +
 drivers/thermal/Makefile  |   1 +
 drivers/thermal/sun50i_thermal.c  | 357 ++
 6 files changed, 412 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun50i-thermal.txt
 create mode 100644 drivers/thermal/sun50i_thermal.c

-- 
2.17.0



[PATCH 4/7] iio: adc: sun4i-gpadc-iio: support clocks and reset

2019-05-03 Thread Yangtao Li
H6 has bus clock and a reset, so introduce something in
gpadc_data/sun4i_gpadc_iio and adds the process of the
clocks and resets.

This is pre-work for supprt it.

Signed-off-by: Yangtao Li 
---
 drivers/iio/adc/sun4i-gpadc-iio.c | 32 +--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c 
b/drivers/iio/adc/sun4i-gpadc-iio.c
index de6b8556a549..f24eb76d65c0 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -22,6 +22,7 @@
  * shutdown for not being used.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -31,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -52,6 +54,8 @@ static unsigned int sun6i_gpadc_chan_select(unsigned int chan)
 struct sun4i_gpadc_iio;
 
 struct gpadc_data {
+   boolhas_bus_clk;
+   boolhas_bus_rst;
int temp_offset;
int temp_scale;
unsigned inttp_mode_en;
@@ -140,6 +144,8 @@ struct sun4i_gpadc_iio {
struct mutexmutex;
struct sun4i_sensor_tzd tzds[MAX_SENSOR_COUNT];
struct device   *sensor_device;
+   struct clk  *bus_clk;
+   struct reset_control*reset;
 };
 
 #define SUN4I_GPADC_ADC_CHANNEL(_channel, _name) { \
@@ -564,14 +570,36 @@ static int sun4i_gpadc_probe_dt(struct platform_device 
*pdev,
if (IS_ERR(base))
return PTR_ERR(base);
 
-   info->regmap = devm_regmap_init_mmio(>dev, base,
-_gpadc_regmap_config);
+   if (info->data->has_bus_clk)
+   info->regmap = devm_regmap_init_mmio_clk(>dev, "bus",
+base,
+   _gpadc_regmap_config);
+   else
+   info->regmap = devm_regmap_init_mmio(>dev, base,
+   _gpadc_regmap_config);
+
if (IS_ERR(info->regmap)) {
ret = PTR_ERR(info->regmap);
dev_err(>dev, "failed to init regmap: %d\n", ret);
return ret;
}
 
+   if (info->data->has_bus_rst) {
+   info->reset = devm_reset_control_get(>dev, "bus");
+   if (IS_ERR(info->reset)) {
+   ret = PTR_ERR(info->reset);
+   return ret;
+   }
+   }
+
+   if (info->data->has_bus_clk) {
+   info->bus_clk = devm_clk_get(>dev, "bus");
+   if (IS_ERR(info->bus_clk)) {
+   ret = PTR_ERR(info->bus_clk);
+   return ret;
+   }
+   }
+
if (IS_ENABLED(CONFIG_THERMAL_OF))
info->sensor_device = >dev;
 
-- 
2.17.1



[PATCH 0/7] Add support for H6 thermal sensor

2019-05-03 Thread Yangtao Li
This patchset adds support for the H6 ths sensor.

Based on IIO-based thermal sensor driver for Allwinner H3 and A83T SoC,
thx to Philipp Rossak's work.

TODO: calibrate thermal sensor by using information from sid.

Yangtao Li (7):
  iio: adc: sun4i-gpadc: rework for support multiple thermal sensor
  iio: adc: sun4i-gpadc: introduce temp_data in gpadc_data
  iio: adc: sun4i-gpadc: introduce gpadc_enable and gpadc_disable in
gpadc_data
  iio: adc: sun4i-gpadc-iio: support clocks and reset
  dt-bindings: mfd: Add H6 GPADC binding
  iio: adc: sun4i-gpadc-iio: add support for H6 thermal sensor
  iio: adc: sun4i-gpadc-iio convert to SPDX license tags

 .../devicetree/bindings/mfd/sun4i-gpadc.txt   |  27 ++-
 drivers/iio/adc/sun4i-gpadc-iio.c | 208 +++---
 include/linux/mfd/sun4i-gpadc.h   |   9 +
 3 files changed, 213 insertions(+), 31 deletions(-)

-- 
2.17.1



[PATCH 6/7] iio: adc: sun4i-gpadc-iio: add support for H6 thermal sensor

2019-05-03 Thread Yangtao Li
This patch adds support for the H6 ths sensor.

TODO: calibrate thermal sensor by using information from sid.

Signed-off-by: Yangtao Li 
---
 drivers/iio/adc/sun4i-gpadc-iio.c | 65 +++
 include/linux/mfd/sun4i-gpadc.h   |  9 +
 2 files changed, 74 insertions(+)

diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c 
b/drivers/iio/adc/sun4i-gpadc-iio.c
index f24eb76d65c0..9b6fc592f54c 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -120,6 +120,20 @@ static const struct gpadc_data sun8i_a33_gpadc_data = {
.temp_data_base = SUN4I_GPADC_TEMP_DATA,
 };
 
+static int sun50i_gpadc_disable(struct sun4i_gpadc_iio *info);
+static int sun50i_gpadc_enable(struct sun4i_gpadc_iio *info);
+
+static const struct gpadc_data sun50i_h6_gpadc_data = {
+   .temp_offset = -2809,
+   .temp_scale = -67,
+   .has_bus_clk = true,
+   .has_bus_rst = true,
+   .gpadc_enable = sun50i_gpadc_enable,
+   .gpadc_disable = sun50i_gpadc_disable,
+   .sensor_count = 2,
+   .temp_data_base = SUN50I_H6_GPADC_TEMP_DATA,
+};
+
 struct sun4i_sensor_tzd {
struct sun4i_gpadc_iio  *info;
struct thermal_zone_device  *tzd;
@@ -452,6 +466,53 @@ static int sun4i_gpadc_enable(struct sun4i_gpadc_iio *info)
return 0;
 }
 
+static int sun50i_gpadc_enable(struct sun4i_gpadc_iio *info)
+{
+   int ret, val;
+
+   ret = reset_control_deassert(info->reset);
+   if (ret)
+   return ret;
+
+   ret = clk_prepare_enable(info->bus_clk);
+   if (ret)
+   goto assert_reset;
+
+   /*
+* clkin = 24MHz
+* T acquire = clkin / (SUN50I_GPADC_CTRL0_T_ACQ + 1)
+*   = 20us
+*/
+   regmap_write(info->regmap, SUN4I_GPADC_CTRL0,
+SUN50I_GPADC_CTRL0_T_ACQ(479));
+   /* average over 4 samples */
+   regmap_write(info->regmap, SUN50I_H6_GPADC_CTRL3,
+SUN4I_GPADC_CTRL3_FILTER_EN |
+SUN4I_GPADC_CTRL3_FILTER_TYPE(1));
+   /* period = (SUN50I_GPADC_TPR_TEMP_PERIOD + 1) * 4096 / clkin; ~10ms */
+   regmap_write(info->regmap, SUN50I_GPADC_TPR,
+SUN50I_GPADC_TPR_TEMP_PERIOD(58));
+   /* TODO: calibrate ths */
+   /* enable sensor */
+   val = GENMASK(info->data->sensor_count - 1, 0);
+   regmap_write(info->regmap, SUN4I_GPADC_CTRL1, val);
+
+   return 0;
+
+assert_reset:
+   reset_control_assert(info->reset);
+
+   return ret;
+}
+
+static int sun50i_gpadc_disable(struct sun4i_gpadc_iio *info)
+{
+   clk_disable_unprepare(info->bus_clk);
+   reset_control_assert(info->reset);
+
+   return 0;
+}
+
 static int sun4i_gpadc_runtime_suspend(struct device *dev)
 {
struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
@@ -546,6 +607,10 @@ static const struct of_device_id sun4i_gpadc_of_id[] = {
.compatible = "allwinner,sun8i-a33-ths",
.data = _a33_gpadc_data,
},
+   {
+   .compatible = "allwinner,sun50i-h6-ths",
+   .data = _h6_gpadc_data,
+   },
{ /* sentinel */ }
 };
 
diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
index 139872c2e0fe..f505013e9c0d 100644
--- a/include/linux/mfd/sun4i-gpadc.h
+++ b/include/linux/mfd/sun4i-gpadc.h
@@ -19,6 +19,9 @@
 #define SUN4I_GPADC_CTRL0_FS_DIV(x)((GENMASK(3, 0) & (x)) 
<< 16)
 #define SUN4I_GPADC_CTRL0_T_ACQ(x) (GENMASK(15, 0) & (x))
 
+/* TP_CTRL0 bits for sun50i SOCs */
+#define SUN50I_GPADC_CTRL0_T_ACQ(x)((GENMASK(15, 0) & (x)) 
<< 16)
+
 #define SUN4I_GPADC_CTRL1  0x04
 
 #define SUN4I_GPADC_CTRL1_STYLUS_UP_DEBOUNCE(x)((GENMASK(7, 0) 
& (x)) << 12)
@@ -49,6 +52,9 @@
 #define SUN4I_GPADC_CTRL2_PRE_MEA_EN   BIT(24)
 #define SUN4I_GPADC_CTRL2_PRE_MEA_THRE_CNT(x)  (GENMASK(23, 0) & (x))
 
+#define SUN50I_GPADC_TPR   0x08
+#define SUN50I_GPADC_TPR_TEMP_PERIOD(x)((GENMASK(19, 
0) & (x)) << 12)
+
 #define SUN4I_GPADC_CTRL3  0x0c
 
 #define SUN4I_GPADC_CTRL3_FILTER_ENBIT(2)
@@ -84,6 +90,9 @@
 #define SUN4I_GPADC_TEMP_DATA  0x20
 #define SUN4I_GPADC_DATA   0x24
 
+#define SUN50I_H6_GPADC_CTRL3  0x30
+#define SUN50I_H6_GPADC_TEMP_DATA  0xc0
+
 #define SUN4I_GPADC_IRQ_FIFO_DATA  0
 #define SUN4I_GPADC_IRQ_TEMP_DATA  1
 
-- 
2.17.1



[PATCH 5/7] dt-bindings: mfd: Add H6 GPADC binding

2019-05-03 Thread Yangtao Li
This patch adds documentation for the H6 GPADC binding.

Signed-off-by: Yangtao Li 
---
 .../devicetree/bindings/mfd/sun4i-gpadc.txt   | 27 +--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt 
b/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt
index 86dd8191b04c..eeaf27eb8abd 100644
--- a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt
+++ b/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt
@@ -5,11 +5,22 @@ and sometimes as a touchscreen controller.
 
 Required properties:
   - compatible: "allwinner,sun8i-a33-ths",
+   "allwinner,sun50i-h6-ths",
   - reg: mmio address range of the chip,
-  - #thermal-sensor-cells: shall be 0,
+  - #thermal-sensor-cells: shall be 0 for sun8i-a33-ths,
+  shall be 1 for sun50i-h6-ths,
   - #io-channel-cells: shall be 0,
 
-Example:
+Optional properties:
+  - clocks: Must contain an entry for each entry in clock-names.
+   See common clock-bindings.txt for details.
+  - clock-names: A list of clock names. For sun50i-h6-ths, it must contain
+"bus".
+  - resets: Must contain an entry for each entry in reset-names.
+   See ../reset/reset.txt for details.
+  - reset-names: For sun50i-h6-ths, it must contain "bus".
+
+Example1:
ths: ths@1c25000 {
compatible = "allwinner,sun8i-a33-ths";
reg = <0x01c25000 0x100>;
@@ -17,6 +28,18 @@ Example:
#io-channel-cells = <0>;
};
 
+Example2:
+   ths: ths@1c25000 {
+   compatible = "allwinner,sun50i-h6-ths";
+   reg = <0x05070400 0x100>;
+   clocks = < CLK_BUS_THS>;
+   clock-names = "bus";
+   resets = < RST_BUS_THS>;
+   reset-names = "bus";
+   #thermal-sensor-cells = <1>;
+   #io-channel-cells = <0>;
+   };
+
 sun4i, sun5i and sun6i SoCs are also supported via the older binding:
 
 sun4i resistive touchscreen controller
-- 
2.17.1



[PATCH 3/7] iio: adc: sun4i-gpadc: introduce gpadc_enable and gpadc_disable in gpadc_data

2019-05-03 Thread Yangtao Li
Different sensors may have different enable and disable functions, so
introduce enable and disable in gpadc_data to support soc specific
function.

Signed-off-by: Yangtao Li 
---
 drivers/iio/adc/sun4i-gpadc-iio.c | 37 ++-
 1 file changed, 31 insertions(+), 6 deletions(-)

diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c 
b/drivers/iio/adc/sun4i-gpadc-iio.c
index b41ec0d5964d..de6b8556a549 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -49,6 +49,8 @@ static unsigned int sun6i_gpadc_chan_select(unsigned int chan)
return SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(chan);
 }
 
+struct sun4i_gpadc_iio;
+
 struct gpadc_data {
int temp_offset;
int temp_scale;
@@ -56,10 +58,15 @@ struct gpadc_data {
unsigned inttp_adc_select;
unsigned int(*adc_chan_select)(unsigned int chan);
unsigned intadc_chan_mask;
+   int (*gpadc_enable)(struct sun4i_gpadc_iio *info);
+   int (*gpadc_disable)(struct sun4i_gpadc_iio *info);
unsigned intsensor_count;
unsigned inttemp_data_base;
 };
 
+static int sun4i_gpadc_disable(struct sun4i_gpadc_iio *info);
+static int sun4i_gpadc_enable(struct sun4i_gpadc_iio *info);
+
 static const struct gpadc_data sun4i_gpadc_data = {
.temp_offset = -1932,
.temp_scale = 133,
@@ -67,6 +74,8 @@ static const struct gpadc_data sun4i_gpadc_data = {
.tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
.adc_chan_select = _gpadc_chan_select,
.adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
+   .gpadc_enable = sun4i_gpadc_enable,
+   .gpadc_disable = sun4i_gpadc_disable,
.sensor_count = 1,
.temp_data_base = SUN4I_GPADC_TEMP_DATA,
 };
@@ -78,6 +87,8 @@ static const struct gpadc_data sun5i_gpadc_data = {
.tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
.adc_chan_select = _gpadc_chan_select,
.adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
+   .gpadc_enable = sun4i_gpadc_enable,
+   .gpadc_disable = sun4i_gpadc_disable,
.sensor_count = 1,
.temp_data_base = SUN4I_GPADC_TEMP_DATA,
 };
@@ -89,6 +100,8 @@ static const struct gpadc_data sun6i_gpadc_data = {
.tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT,
.adc_chan_select = _gpadc_chan_select,
.adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK,
+   .gpadc_enable = sun4i_gpadc_enable,
+   .gpadc_disable = sun4i_gpadc_disable,
.sensor_count = 1,
.temp_data_base = SUN4I_GPADC_TEMP_DATA,
 };
@@ -97,6 +110,8 @@ static const struct gpadc_data sun8i_a33_gpadc_data = {
.temp_offset = -1662,
.temp_scale = 162,
.tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN,
+   .gpadc_enable = sun4i_gpadc_enable,
+   .gpadc_disable = sun4i_gpadc_disable,
.sensor_count = 1,
.temp_data_base = SUN4I_GPADC_TEMP_DATA,
 };
@@ -402,10 +417,8 @@ static irqreturn_t sun4i_gpadc_fifo_data_irq_handler(int 
irq, void *dev_id)
return IRQ_HANDLED;
 }
 
-static int sun4i_gpadc_runtime_suspend(struct device *dev)
+static int sun4i_gpadc_disable(struct sun4i_gpadc_iio *info)
 {
-   struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
-
/* Disable the ADC on IP */
regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0);
/* Disable temperature sensor on IP */
@@ -414,10 +427,8 @@ static int sun4i_gpadc_runtime_suspend(struct device *dev)
return 0;
 }
 
-static int sun4i_gpadc_runtime_resume(struct device *dev)
+static int sun4i_gpadc_enable(struct sun4i_gpadc_iio *info)
 {
-   struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
-
/* clkin = 6MHz */
regmap_write(info->regmap, SUN4I_GPADC_CTRL0,
 SUN4I_GPADC_CTRL0_ADC_CLK_DIVIDER(2) |
@@ -435,6 +446,20 @@ static int sun4i_gpadc_runtime_resume(struct device *dev)
return 0;
 }
 
+static int sun4i_gpadc_runtime_suspend(struct device *dev)
+{
+   struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
+
+   return info->data->gpadc_disable(info);
+}
+
+static int sun4i_gpadc_runtime_resume(struct device *dev)
+{
+   struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
+
+   return info->data->gpadc_enable(info);
+}
+
 static int sun4i_gpadc_get_temp(void *data, int *temp)
 {
struct sun4i_sensor_tzd *tzd = data;
-- 
2.17.1



[PATCH 1/7] iio: adc: sun4i-gpadc: rework for support multiple thermal sensor

2019-05-03 Thread Yangtao Li
For some SOCs, there are more than one thermal sensor, and there are
currently four sensors on the A80. So we need to do some work in order
to support multiple thermal sensors:

  1) add sensor_count in gpadc_data.
  2) introduce sun4i_sensor_tzd in sun4i_gpadc_iio, to support multiple
 thermal_zone_device and distinguish between different sensors.
  3) modify read temperature and initialization function.

Signed-off-by: Yangtao Li 
---
 drivers/iio/adc/sun4i-gpadc-iio.c | 61 +++
 1 file changed, 45 insertions(+), 16 deletions(-)

diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c 
b/drivers/iio/adc/sun4i-gpadc-iio.c
index 04d7147e0110..844fd52bd22f 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -56,6 +56,7 @@ struct gpadc_data {
unsigned inttp_adc_select;
unsigned int(*adc_chan_select)(unsigned int chan);
unsigned intadc_chan_mask;
+   unsigned intsensor_count;
 };
 
 static const struct gpadc_data sun4i_gpadc_data = {
@@ -65,6 +66,7 @@ static const struct gpadc_data sun4i_gpadc_data = {
.tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
.adc_chan_select = _gpadc_chan_select,
.adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
+   .sensor_count = 1,
 };
 
 static const struct gpadc_data sun5i_gpadc_data = {
@@ -74,6 +76,7 @@ static const struct gpadc_data sun5i_gpadc_data = {
.tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
.adc_chan_select = _gpadc_chan_select,
.adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
+   .sensor_count = 1,
 };
 
 static const struct gpadc_data sun6i_gpadc_data = {
@@ -83,14 +86,24 @@ static const struct gpadc_data sun6i_gpadc_data = {
.tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT,
.adc_chan_select = _gpadc_chan_select,
.adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK,
+   .sensor_count = 1,
 };
 
 static const struct gpadc_data sun8i_a33_gpadc_data = {
.temp_offset = -1662,
.temp_scale = 162,
.tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN,
+   .sensor_count = 1,
 };
 
+struct sun4i_sensor_tzd {
+   struct sun4i_gpadc_iio  *info;
+   struct thermal_zone_device  *tzd;
+   unsigned intsensor_id;
+};
+
+#define MAX_SENSOR_COUNT   4
+
 struct sun4i_gpadc_iio {
struct iio_dev  *indio_dev;
struct completion   completion;
@@ -105,7 +118,7 @@ struct sun4i_gpadc_iio {
boolno_irq;
/* prevents concurrent reads of temperature and ADC */
struct mutexmutex;
-   struct thermal_zone_device  *tzd;
+   struct sun4i_sensor_tzd tzds[MAX_SENSOR_COUNT];
struct device   *sensor_device;
 };
 
@@ -270,7 +283,8 @@ static int sun4i_gpadc_adc_read(struct iio_dev *indio_dev, 
int channel,
return sun4i_gpadc_read(indio_dev, channel, val, info->fifo_data_irq);
 }
 
-static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val)
+static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val,
+unsigned int sensor)
 {
struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
 
@@ -324,7 +338,7 @@ static int sun4i_gpadc_read_raw(struct iio_dev *indio_dev,
ret = sun4i_gpadc_adc_read(indio_dev, chan->channel,
   val);
else
-   ret = sun4i_gpadc_temp_read(indio_dev, val);
+   ret = sun4i_gpadc_temp_read(indio_dev, val, 0);
 
if (ret)
return ret;
@@ -417,10 +431,11 @@ static int sun4i_gpadc_runtime_resume(struct device *dev)
 
 static int sun4i_gpadc_get_temp(void *data, int *temp)
 {
-   struct sun4i_gpadc_iio *info = data;
+   struct sun4i_sensor_tzd *tzd = data;
+   struct sun4i_gpadc_iio *info = tzd->info;
int val, scale, offset;
 
-   if (sun4i_gpadc_temp_read(info->indio_dev, ))
+   if (sun4i_gpadc_temp_read(info->indio_dev, , tzd->sensor_id))
return -ETIMEDOUT;
 
sun4i_gpadc_temp_scale(info->indio_dev, );
@@ -609,6 +624,28 @@ static int sun4i_gpadc_probe_mfd(struct platform_device 
*pdev,
return 0;
 }
 
+static int sun4i_sensor_init(struct sun4i_gpadc_iio *info)
+{
+   int i = 0;
+
+   for (; i < info->data->sensor_count; i++) {
+   info->tzds[i].info = info;
+   info->tzds[i].sensor_id = i;
+   info->tzds[i].tzd = devm_thermal_zone_of_sensor_register(
+   info->sensor_device, i, >tzds[i],
+   _ts_tz_ops);
+
+   if (IS_ERR(info->tzds[i].tzd)) {
+   dev_err(info->sensor_device,
+ 

[PATCH 7/7] iio: adc: sun4i-gpadc-iio convert to SPDX license tags

2019-05-03 Thread Yangtao Li
Updates license to use SPDX-License-Identifier.

Signed-off-by: Yangtao Li 
---
 drivers/iio/adc/sun4i-gpadc-iio.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c 
b/drivers/iio/adc/sun4i-gpadc-iio.c
index 9b6fc592f54c..cf2bf3ab3342 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /* ADC driver for sunxi platforms' (A10, A13 and A31) GPADC
  *
  * Copyright (c) 2016 Quentin Schulz 
  *
- * This program is free software; you can redistribute it and/or modify it 
under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- *
  * The Allwinner SoCs all have an ADC that can also act as a touchscreen
  * controller and a thermal sensor.
  * The thermal sensor works only when the ADC acts as a touchscreen controller
-- 
2.17.1



[PATCH 2/7] iio: adc: sun4i-gpadc: introduce temp_data in gpadc_data

2019-05-03 Thread Yangtao Li
For some SOCs, the temperature data register start address may be
different, so introduce temp_data in gpadc_data.

Also modify read temperature to support multiple sensor.

Signed-off-by: Yangtao Li 
---
 drivers/iio/adc/sun4i-gpadc-iio.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c 
b/drivers/iio/adc/sun4i-gpadc-iio.c
index 844fd52bd22f..b41ec0d5964d 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -57,6 +57,7 @@ struct gpadc_data {
unsigned int(*adc_chan_select)(unsigned int chan);
unsigned intadc_chan_mask;
unsigned intsensor_count;
+   unsigned inttemp_data_base;
 };
 
 static const struct gpadc_data sun4i_gpadc_data = {
@@ -67,6 +68,7 @@ static const struct gpadc_data sun4i_gpadc_data = {
.adc_chan_select = _gpadc_chan_select,
.adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
.sensor_count = 1,
+   .temp_data_base = SUN4I_GPADC_TEMP_DATA,
 };
 
 static const struct gpadc_data sun5i_gpadc_data = {
@@ -77,6 +79,7 @@ static const struct gpadc_data sun5i_gpadc_data = {
.adc_chan_select = _gpadc_chan_select,
.adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
.sensor_count = 1,
+   .temp_data_base = SUN4I_GPADC_TEMP_DATA,
 };
 
 static const struct gpadc_data sun6i_gpadc_data = {
@@ -87,6 +90,7 @@ static const struct gpadc_data sun6i_gpadc_data = {
.adc_chan_select = _gpadc_chan_select,
.adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK,
.sensor_count = 1,
+   .temp_data_base = SUN4I_GPADC_TEMP_DATA,
 };
 
 static const struct gpadc_data sun8i_a33_gpadc_data = {
@@ -94,6 +98,7 @@ static const struct gpadc_data sun8i_a33_gpadc_data = {
.temp_scale = 162,
.tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN,
.sensor_count = 1,
+   .temp_data_base = SUN4I_GPADC_TEMP_DATA,
 };
 
 struct sun4i_sensor_tzd {
@@ -291,7 +296,8 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, 
int *val,
if (info->no_irq) {
pm_runtime_get_sync(indio_dev->dev.parent);
 
-   regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val);
+   regmap_read(info->regmap, info->data->temp_data_base +
+   0x4 * sensor, val);
 
pm_runtime_mark_last_busy(indio_dev->dev.parent);
pm_runtime_put_autosuspend(indio_dev->dev.parent);
-- 
2.17.1



  1   2   3   4   5   >