linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RESEND PATCH] thermal: mediatek: add suspend/resume callback
@ 2019-10-09  9:35 michael.kao
  2019-10-13 17:50 ` Daniel Lezcano
  0 siblings, 1 reply; 11+ messages in thread
From: michael.kao @ 2019-10-09  9:35 UTC (permalink / raw)
  To: michael.kao, Zhang Rui, Eduardo Valentin, Daniel Lezcano,
	Rob Herring, Mark Rutland, Matthias Brugger, hsinyi
  Cc: linux-pm, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, Louis Yu

From: Louis Yu <louis.yu@mediatek.com>

Add suspend/resume callback to disable/enable Mediatek thermal sensor
respectively. Since thermal power domain is off in suspend, thermal driver
needs re-initialization during resume.

Signed-off-by: Louis Yu <louis.yu@mediatek.com>
Signed-off-by: Michael Kao <michael.kao@mediatek.com>
---
This patch series base on these patches [1][2].

[1]thermal: mediatek: mt8183: fix bank number settings (https://patchwork.kernel.org/patch/10938817/)
[2]thermal: mediatek: add another get_temp ops for thermal sensors (https://patchwork.kernel.org/patch/10938829/)

 drivers/thermal/mtk_thermal.c | 134 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 125 insertions(+), 9 deletions(-)

diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
index 6bdd9c2..22ff2cf 100644
--- a/drivers/thermal/mtk_thermal.c
+++ b/drivers/thermal/mtk_thermal.c
@@ -22,6 +22,7 @@
 #include <linux/thermal.h>
 #include <linux/reset.h>
 #include <linux/types.h>
+#include <linux/iopoll.h>
 
 /* AUXADC Registers */
 #define AUXADC_CON1_SET_V	0x008
@@ -31,6 +32,8 @@
 
 #define APMIXED_SYS_TS_CON1	0x604
 
+#define APMIXED_SYS_TS_CON1_BUFFER_OFF	0x30
+
 /* Thermal Controller Registers */
 #define TEMP_MONCTL0		0x000
 #define TEMP_MONCTL1		0x004
@@ -38,6 +41,7 @@
 #define TEMP_MONIDET0		0x014
 #define TEMP_MONIDET1		0x018
 #define TEMP_MSRCTL0		0x038
+#define TEMP_MSRCTL1		0x03c
 #define TEMP_AHBPOLL		0x040
 #define TEMP_AHBTO		0x044
 #define TEMP_ADCPNP0		0x048
@@ -87,6 +91,9 @@
 #define TEMP_ADCVALIDMASK_VALID_HIGH		BIT(5)
 #define TEMP_ADCVALIDMASK_VALID_POS(bit)	(bit)
 
+#define TEMP_MSRCTL1_BUS_STA	(BIT(0) | BIT(7))
+#define TEMP_MSRCTL1_SENSING_POINTS_PAUSE	0x10E
+
 /* MT8173 thermal sensors */
 #define MT8173_TS1	0
 #define MT8173_TS2	1
@@ -258,6 +265,10 @@ struct mtk_thermal_data {
 struct mtk_thermal {
 	struct device *dev;
 	void __iomem *thermal_base;
+	void __iomem *apmixed_base;
+	void __iomem *auxadc_base;
+	u64 apmixed_phys_base;
+	u64 auxadc_phys_base;
 
 	struct clk *clk_peri_therm;
 	struct clk *clk_auxadc;
@@ -787,6 +798,42 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
 	mtk_thermal_put_bank(bank);
 }
 
+static int mtk_thermal_disable_sensing(struct mtk_thermal *mt, int num)
+{
+	struct mtk_thermal_bank *bank = &mt->banks[num];
+	u32 val;
+	unsigned long timeout;
+	void __iomem *addr;
+	int ret = 0;
+
+	bank->id = num;
+	bank->mt = mt;
+
+	mtk_thermal_get_bank(bank);
+
+	val = readl(mt->thermal_base + TEMP_MSRCTL1);
+	/* pause periodic temperature measurement for sensing points */
+	writel(val | TEMP_MSRCTL1_SENSING_POINTS_PAUSE,
+	       mt->thermal_base + TEMP_MSRCTL1);
+
+	/* wait until temperature measurement bus idle */
+	timeout = jiffies + HZ;
+	addr = mt->thermal_base + TEMP_MSRCTL1;
+
+	ret = readl_poll_timeout(addr, val, (val & TEMP_MSRCTL1_BUS_STA) == 0x0,
+				 0, timeout);
+	if (ret < 0)
+		goto out;
+
+	/* disable periodic temperature meausrement on sensing points */
+	writel(0x0, mt->thermal_base + TEMP_MONCTL0);
+
+out:
+	mtk_thermal_put_bank(bank);
+
+	return ret;
+}
+
 static u64 of_get_phys_base(struct device_node *np)
 {
 	u64 size64;
@@ -909,7 +956,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 	struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
 	struct mtk_thermal *mt;
 	struct resource *res;
-	u64 auxadc_phys_base, apmixed_phys_base;
 	struct thermal_zone_device *tzdev;
 	struct mtk_thermal_zone *tz;
 
@@ -946,11 +992,11 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	auxadc_phys_base = of_get_phys_base(auxadc);
+	mt->auxadc_phys_base = of_get_phys_base(auxadc);
 
 	of_node_put(auxadc);
 
-	if (auxadc_phys_base == OF_BAD_ADDR) {
+	if (mt->auxadc_phys_base == OF_BAD_ADDR) {
 		dev_err(&pdev->dev, "Can't get auxadc phys address\n");
 		return -EINVAL;
 	}
@@ -961,11 +1007,12 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	apmixed_phys_base = of_get_phys_base(apmixedsys);
+	mt->apmixed_phys_base = of_get_phys_base(apmixedsys);
+	mt->apmixed_base = of_iomap(apmixedsys, 0);
 
 	of_node_put(apmixedsys);
 
-	if (apmixed_phys_base == OF_BAD_ADDR) {
+	if (mt->apmixed_phys_base == OF_BAD_ADDR) {
 		dev_err(&pdev->dev, "Can't get auxadc phys address\n");
 		return -EINVAL;
 	}
@@ -977,19 +1024,19 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 	ret = clk_prepare_enable(mt->clk_auxadc);
 	if (ret) {
 		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
-		return ret;
+		goto err_disable_clk_auxadc;
 	}
 
 	ret = clk_prepare_enable(mt->clk_peri_therm);
 	if (ret) {
 		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
-		goto err_disable_clk_auxadc;
+		goto err_disable_clk_peri_therm;
 	}
 
 	for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
 		for (i = 0; i < mt->conf->num_banks; i++)
-			mtk_thermal_init_bank(mt, i, apmixed_phys_base,
-					      auxadc_phys_base, ctrl_id);
+			mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
+					      mt->auxadc_phys_base, ctrl_id);
 
 	platform_set_drvdata(pdev, mt);
 
@@ -1033,11 +1080,80 @@ static int mtk_thermal_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int __maybe_unused mtk_thermal_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mtk_thermal *mt = platform_get_drvdata(pdev);
+	int i, ret;
+
+	for (i = 0; i < mt->conf->num_banks; i++) {
+		ret = mtk_thermal_disable_sensing(mt, i);
+		if (ret)
+			goto out;
+	}
+
+	/* disable buffer */
+	writel(readl(mt->apmixed_base + APMIXED_SYS_TS_CON1) |
+	       APMIXED_SYS_TS_CON1_BUFFER_OFF,
+	       mt->apmixed_base + APMIXED_SYS_TS_CON1);
+
+	clk_disable_unprepare(mt->clk_peri_therm);
+	clk_disable_unprepare(mt->clk_auxadc);
+
+	return 0;
+
+out:
+	dev_err(&pdev->dev, "Failed to wait until bus idle\n");
+
+	return ret;
+}
+
+static int __maybe_unused mtk_thermal_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mtk_thermal *mt = platform_get_drvdata(pdev);
+	int i, ret, ctrl_id;
+
+	ret = device_reset(&pdev->dev);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(mt->clk_auxadc);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
+		goto err_disable_clk_auxadc;
+	}
+
+	ret = clk_prepare_enable(mt->clk_peri_therm);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
+		goto err_disable_clk_peri_therm;
+	}
+
+	for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
+		for (i = 0; i < mt->conf->num_banks; i++)
+			mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
+					      mt->auxadc_phys_base, ctrl_id);
+
+	return 0;
+
+err_disable_clk_peri_therm:
+	clk_disable_unprepare(mt->clk_peri_therm);
+err_disable_clk_auxadc:
+	clk_disable_unprepare(mt->clk_auxadc);
+
+	return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(mtk_thermal_pm_ops,
+			 mtk_thermal_suspend, mtk_thermal_resume);
+
 static struct platform_driver mtk_thermal_driver = {
 	.probe = mtk_thermal_probe,
 	.remove = mtk_thermal_remove,
 	.driver = {
 		.name = "mtk-thermal",
+		.pm = &mtk_thermal_pm_ops,
 		.of_match_table = mtk_thermal_of_match,
 	},
 };
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [RESEND PATCH] thermal: mediatek: add suspend/resume callback
  2019-10-09  9:35 [RESEND PATCH] thermal: mediatek: add suspend/resume callback michael.kao
@ 2019-10-13 17:50 ` Daniel Lezcano
  2019-11-01  1:31   ` Michael Kao
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Lezcano @ 2019-10-13 17:50 UTC (permalink / raw)
  To: michael.kao, Zhang Rui, Eduardo Valentin, Rob Herring,
	Mark Rutland, Matthias Brugger, hsinyi
  Cc: linux-pm, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, Louis Yu

On 09/10/2019 11:35, michael.kao@mediatek.com wrote:
> From: Louis Yu <louis.yu@mediatek.com>
> 
> Add suspend/resume callback to disable/enable Mediatek thermal sensor
> respectively. Since thermal power domain is off in suspend, thermal driver
> needs re-initialization during resume.
> 
> Signed-off-by: Louis Yu <louis.yu@mediatek.com>
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> ---
> This patch series base on these patches [1][2].
> 
> [1]thermal: mediatek: mt8183: fix bank number settings (https://patchwork.kernel.org/patch/10938817/)
> [2]thermal: mediatek: add another get_temp ops for thermal sensors (https://patchwork.kernel.org/patch/10938829/)

There is no new version with the comments take into account. Did I miss
something?


-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RESEND PATCH] thermal: mediatek: add suspend/resume callback
  2019-10-13 17:50 ` Daniel Lezcano
@ 2019-11-01  1:31   ` Michael Kao
  2019-11-01  8:46     ` Daniel Lezcano
  0 siblings, 1 reply; 11+ messages in thread
From: Michael Kao @ 2019-11-01  1:31 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland,
	Matthias Brugger, hsinyi, linux-pm, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek, Louis Yu

On Sun, 2019-10-13 at 19:50 +0200, Daniel Lezcano wrote:
> On 09/10/2019 11:35, michael.kao@mediatek.com wrote:
> > From: Louis Yu <louis.yu@mediatek.com>
> > 
> > Add suspend/resume callback to disable/enable Mediatek thermal sensor
> > respectively. Since thermal power domain is off in suspend, thermal driver
> > needs re-initialization during resume.
> > 
> > Signed-off-by: Louis Yu <louis.yu@mediatek.com>
> > Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> > ---
> > This patch series base on these patches [1][2].
> > 
> > [1]thermal: mediatek: mt8183: fix bank number settings (https://patchwork.kernel.org/patch/10938817/)
> > [2]thermal: mediatek: add another get_temp ops for thermal sensors (https://patchwork.kernel.org/patch/10938829/)
> 
> There is no new version with the comments take into account. Did I miss
> something?
> 
> The patch base on Kenrel 5.4. I resend to linux-pm. The original patch is at linux-mediatek only.



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RESEND PATCH] thermal: mediatek: add suspend/resume callback
  2019-11-01  1:31   ` Michael Kao
@ 2019-11-01  8:46     ` Daniel Lezcano
  0 siblings, 0 replies; 11+ messages in thread
From: Daniel Lezcano @ 2019-11-01  8:46 UTC (permalink / raw)
  To: Michael Kao
  Cc: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland,
	Matthias Brugger, hsinyi, linux-pm, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek, Louis Yu

On 01/11/2019 02:31, Michael Kao wrote:
> On Sun, 2019-10-13 at 19:50 +0200, Daniel Lezcano wrote:
>> On 09/10/2019 11:35, michael.kao@mediatek.com wrote:
>>> From: Louis Yu <louis.yu@mediatek.com>
>>>
>>> Add suspend/resume callback to disable/enable Mediatek thermal sensor
>>> respectively. Since thermal power domain is off in suspend, thermal driver
>>> needs re-initialization during resume.
>>>
>>> Signed-off-by: Louis Yu <louis.yu@mediatek.com>
>>> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
>>> ---
>>> This patch series base on these patches [1][2].
>>>
>>> [1]thermal: mediatek: mt8183: fix bank number settings (https://patchwork.kernel.org/patch/10938817/)
>>> [2]thermal: mediatek: add another get_temp ops for thermal sensors (https://patchwork.kernel.org/patch/10938829/)
>>
>> There is no new version with the comments take into account. Did I miss
>> something?
>>
>> The patch base on Kenrel 5.4. I resend to linux-pm. The original patch is at linux-mediatek only.

Sorry I don't get your anwser, can you rephrase it ?

-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RESEND PATCH] thermal: mediatek: add suspend/resume callback
  2020-05-14  8:46   ` Michael Kao
@ 2020-07-07  8:47     ` Michael Kao
  0 siblings, 0 replies; 11+ messages in thread
From: Michael Kao @ 2020-07-07  8:47 UTC (permalink / raw)
  To: Zhang Rui
  Cc: Daniel Lezcano, Mark Rutland, devicetree, srv_heupstream,
	linux-pm, Louis Yu (游政錕),
	linux-kernel, Eduardo Valentin, Rob Herring, linux-mediatek,
	hsinyi, Matthias Brugger, linux-arm-kernel

On Thu, 2020-05-14 at 16:46 +0800, Michael Kao wrote:
> On Wed, 2020-04-08 at 17:05 +0800, Michael Kao (高振翔) wrote:
> > From: Louis Yu <louis.yu@mediatek.com>
> > 
> > Add suspend/resume callback to disable/enable Mediatek thermal sensor
> > respectively. Since thermal power domain is off in suspend, thermal driver
> > needs re-initialization during resume.
> > 
> > Signed-off-by: Louis Yu <louis.yu@mediatek.com>
> > Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> > ---
> >  drivers/thermal/mtk_thermal.c | 152 ++++++++++++++++++++++++++++++----
> >  1 file changed, 134 insertions(+), 18 deletions(-)
> > 
> > diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
> > index 76e30603d4d5..36fd35fac733 100644
> > --- a/drivers/thermal/mtk_thermal.c
> > +++ b/drivers/thermal/mtk_thermal.c
> > @@ -22,6 +22,7 @@
> >  #include <linux/thermal.h>
> >  #include <linux/reset.h>
> >  #include <linux/types.h>
> > +#include <linux/iopoll.h>
> > 
> >  /* AUXADC Registers */
> >  #define AUXADC_CON1_SET_V      0x008
> > @@ -31,6 +32,8 @@
> > 
> >  #define APMIXED_SYS_TS_CON1    0x604
> > 
> > +#define APMIXED_SYS_TS_CON1_BUFFER_OFF 0x30
> > +
> >  /* Thermal Controller Registers */
> >  #define TEMP_MONCTL0           0x000
> >  #define TEMP_MONCTL1           0x004
> > @@ -38,6 +41,7 @@
> >  #define TEMP_MONIDET0          0x014
> >  #define TEMP_MONIDET1          0x018
> >  #define TEMP_MSRCTL0           0x038
> > +#define TEMP_MSRCTL1           0x03c
> >  #define TEMP_AHBPOLL           0x040
> >  #define TEMP_AHBTO             0x044
> >  #define TEMP_ADCPNP0           0x048
> > @@ -87,6 +91,9 @@
> >  #define TEMP_ADCVALIDMASK_VALID_HIGH           BIT(5)
> >  #define TEMP_ADCVALIDMASK_VALID_POS(bit)       (bit)
> > 
> > +#define TEMP_MSRCTL1_BUS_STA   (BIT(0) | BIT(7))
> > +#define TEMP_MSRCTL1_SENSING_POINTS_PAUSE      0x10E
> > +
> >  /* MT8173 thermal sensors */
> >  #define MT8173_TS1     0
> >  #define MT8173_TS2     1
> > @@ -250,6 +257,10 @@ struct mtk_thermal_data {
> >  struct mtk_thermal {
> >         struct device *dev;
> >         void __iomem *thermal_base;
> > +       void __iomem *apmixed_base;
> > +       void __iomem *auxadc_base;
> > +       u64 apmixed_phys_base;
> > +       u64 auxadc_phys_base;
> > 
> >         struct clk *clk_peri_therm;
> >         struct clk *clk_auxadc;
> > @@ -541,13 +552,13 @@ static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw)
> >  }
> > 
> >  /**
> > - * mtk_thermal_get_bank - get bank
> > + * mtk_thermal_lock_bank - get bank
> >   * @bank:      The bank
> >   *
> >   * The bank registers are banked, we have to select a bank in the
> >   * PTPCORESEL register to access it.
> >   */
> > -static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
> > +static void mtk_thermal_lock_bank(struct mtk_thermal_bank *bank)
> >  {
> >         struct mtk_thermal *mt = bank->mt;
> >         u32 val;
> > @@ -563,12 +574,12 @@ static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
> >  }
> > 
> >  /**
> > - * mtk_thermal_put_bank - release bank
> > + * mtk_thermal_unlock_bank - release bank
> >   * @bank:      The bank
> >   *
> > - * release a bank previously taken with mtk_thermal_get_bank,
> > + * release a bank previously taken with mtk_thermal_lock_bank,
> >   */
> > -static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
> > +static void mtk_thermal_unlock_bank(struct mtk_thermal_bank *bank)
> >  {
> >         struct mtk_thermal *mt = bank->mt;
> > 
> > @@ -622,11 +633,11 @@ static int mtk_read_temp(void *data, int *temperature)
> >         for (i = 0; i < mt->conf->num_banks; i++) {
> >                 struct mtk_thermal_bank *bank = &mt->banks[i];
> > 
> > -               mtk_thermal_get_bank(bank);
> > +               mtk_thermal_lock_bank(bank);
> > 
> >                 tempmax = max(tempmax, mtk_thermal_bank_temperature(bank));
> > 
> > -               mtk_thermal_put_bank(bank);
> > +               mtk_thermal_unlock_bank(bank);
> >         }
> > 
> >         *temperature = tempmax;
> > @@ -652,7 +663,7 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
> >         bank->id = num;
> >         bank->mt = mt;
> > 
> > -       mtk_thermal_get_bank(bank);
> > +       mtk_thermal_lock_bank(bank);
> > 
> >         /* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */
> >         writel(TEMP_MONCTL1_PERIOD_UNIT(12), controller_base + TEMP_MONCTL1);
> > @@ -743,7 +754,43 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
> >                TEMP_ADCWRITECTRL_ADC_MUX_WRITE,
> >                controller_base + TEMP_ADCWRITECTRL);
> > 
> > -       mtk_thermal_put_bank(bank);
> > +       mtk_thermal_unlock_bank(bank);
> > +}
> > +
> > +static int mtk_thermal_disable_sensing(struct mtk_thermal *mt, int num)
> > +{
> > +       struct mtk_thermal_bank *bank = &mt->banks[num];
> > +       u32 val;
> > +       unsigned long timeout;
> > +       void __iomem *addr;
> > +       int ret = 0;
> > +
> > +       bank->id = num;
> > +       bank->mt = mt;
> > +
> > +       mtk_thermal_lock_bank(bank);
> > +
> > +       val = readl(mt->thermal_base + TEMP_MSRCTL1);
> > +       /* pause periodic temperature measurement for sensing points */
> > +       writel(val | TEMP_MSRCTL1_SENSING_POINTS_PAUSE,
> > +              mt->thermal_base + TEMP_MSRCTL1);
> > +
> > +       /* wait until temperature measurement bus idle */
> > +       timeout = jiffies + HZ;
> > +       addr = mt->thermal_base + TEMP_MSRCTL1;
> > +
> > +       ret = readl_poll_timeout(addr, val, (val & TEMP_MSRCTL1_BUS_STA) == 0x0,
> > +                                0, timeout);
> > +       if (ret < 0)
> > +               goto out;
> > +
> > +       /* disable periodic temperature measurement on sensing points */
> > +       writel(0x0, mt->thermal_base + TEMP_MONCTL0);
> > +
> > +out:
> > +       mtk_thermal_unlock_bank(bank);
> > +
> > +       return ret;
> >  }
> > 
> >  static u64 of_get_phys_base(struct device_node *np)
> > @@ -868,7 +915,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
> >         struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
> >         struct mtk_thermal *mt;
> >         struct resource *res;
> > -       u64 auxadc_phys_base, apmixed_phys_base;
> >         struct thermal_zone_device *tzdev;
> > 
> >         mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
> > @@ -904,11 +950,11 @@ static int mtk_thermal_probe(struct platform_device *pdev)
> >                 return -ENODEV;
> >         }
> > 
> > -       auxadc_phys_base = of_get_phys_base(auxadc);
> > +       mt->auxadc_phys_base = of_get_phys_base(auxadc);
> > 
> >         of_node_put(auxadc);
> > 
> > -       if (auxadc_phys_base == OF_BAD_ADDR) {
> > +       if (mt->auxadc_phys_base == OF_BAD_ADDR) {
> >                 dev_err(&pdev->dev, "Can't get auxadc phys address\n");
> >                 return -EINVAL;
> >         }
> > @@ -919,11 +965,12 @@ static int mtk_thermal_probe(struct platform_device *pdev)
> >                 return -ENODEV;
> >         }
> > 
> > -       apmixed_phys_base = of_get_phys_base(apmixedsys);
> > +       mt->apmixed_phys_base = of_get_phys_base(apmixedsys);
> > +       mt->apmixed_base = of_iomap(apmixedsys, 0);
> > 
> >         of_node_put(apmixedsys);
> > 
> > -       if (apmixed_phys_base == OF_BAD_ADDR) {
> > +       if (mt->apmixed_phys_base == OF_BAD_ADDR) {
> >                 dev_err(&pdev->dev, "Can't get auxadc phys address\n");
> >                 return -EINVAL;
> >         }
> > @@ -935,19 +982,19 @@ static int mtk_thermal_probe(struct platform_device *pdev)
> >         ret = clk_prepare_enable(mt->clk_auxadc);
> >         if (ret) {
> >                 dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
> > -               return ret;
> > +               goto err_disable_clk_auxadc;
> >         }
> > 
> >         ret = clk_prepare_enable(mt->clk_peri_therm);
> >         if (ret) {
> >                 dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
> > -               goto err_disable_clk_auxadc;
> > +               goto err_disable_clk_peri_therm;
> >         }
> > 
> >         for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
> >                 for (i = 0; i < mt->conf->num_banks; i++)
> > -                       mtk_thermal_init_bank(mt, i, apmixed_phys_base,
> > -                                             auxadc_phys_base, ctrl_id);
> > +                       mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
> > +                                             mt->auxadc_phys_base, ctrl_id);
> > 
> >         platform_set_drvdata(pdev, mt);
> > 
> > @@ -978,11 +1025,80 @@ static int mtk_thermal_remove(struct platform_device *pdev)
> >         return 0;
> >  }
> > 
> > +static int __maybe_unused mtk_thermal_suspend(struct device *dev)
> > +{
> > +       struct platform_device *pdev = to_platform_device(dev);
> > +       struct mtk_thermal *mt = platform_get_drvdata(pdev);
> > +       int i, ret;
> > +
> > +       for (i = 0; i < mt->conf->num_banks; i++) {
> > +               ret = mtk_thermal_disable_sensing(mt, i);
> > +               if (ret)
> > +                       goto out;
> > +       }
> > +
Hi Daniel,

When you run suspend, we just have to disable thermal sensors.
But if we probe or resume, we need to config these sensors to
the right bank and thermal controller.
Because we read temperature by thermal controllers and banks
instead of reading temperature by sensor directly.
And the sensors placed at different banks need to be configed
first before reading temperature by mtk_thermal_bank_temperature.
> > +       /* disable buffer */
> > +       writel(readl(mt->apmixed_base + APMIXED_SYS_TS_CON1) |
> > +              APMIXED_SYS_TS_CON1_BUFFER_OFF,
> > +              mt->apmixed_base + APMIXED_SYS_TS_CON1);
> > +
> > +       clk_disable_unprepare(mt->clk_peri_therm);
> > +       clk_disable_unprepare(mt->clk_auxadc);
> > +
> > +       return 0;
> > +
> > +out:
> > +       dev_err(&pdev->dev, "Failed to wait until bus idle\n");
> > +
> > +       return ret;
> > +}
> > +
> > +static int __maybe_unused mtk_thermal_resume(struct device *dev)
> > +{
> > +       struct platform_device *pdev = to_platform_device(dev);
> > +       struct mtk_thermal *mt = platform_get_drvdata(pdev);
> > +       int i, ret, ctrl_id;
> > +
> > +       ret = device_reset(&pdev->dev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       ret = clk_prepare_enable(mt->clk_auxadc);
> > +       if (ret) {
> > +               dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
> > +               goto err_disable_clk_auxadc;
> > +       }
> > +
> > +       ret = clk_prepare_enable(mt->clk_peri_therm);
> > +       if (ret) {
> > +               dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
> > +               goto err_disable_clk_peri_therm;
> > +       }
> > +
> > +       for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
> > +               for (i = 0; i < mt->conf->num_banks; i++)
> > +                       mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
> > +                                             mt->auxadc_phys_base, ctrl_id);
> > +
> > +       return 0;
> > +
> > +err_disable_clk_peri_therm:
> > +       clk_disable_unprepare(mt->clk_peri_therm);
> > +err_disable_clk_auxadc:
> > +       clk_disable_unprepare(mt->clk_auxadc);
> > +
> > +       return ret;
> > +}
> > +
> > +static SIMPLE_DEV_PM_OPS(mtk_thermal_pm_ops,
> > +                        mtk_thermal_suspend, mtk_thermal_resume);
> > +
> >  static struct platform_driver mtk_thermal_driver = {
> >         .probe = mtk_thermal_probe,
> >         .remove = mtk_thermal_remove,
> >         .driver = {
> >                 .name = "mtk-thermal",
> > +               .pm = &mtk_thermal_pm_ops,
> >                 .of_match_table = mtk_thermal_of_match,
> >         },
> >  };
> > --
> > 2.18.0
> > 
> Hi Daniel,
> Just gently ping.    Many thanks.
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RESEND PATCH] thermal: mediatek: add suspend/resume callback
  2020-04-08  9:05 ` [RESEND PATCH] " Michael Kao
  2020-05-14  8:46   ` Michael Kao
@ 2020-05-22 19:08   ` Daniel Lezcano
  1 sibling, 0 replies; 11+ messages in thread
From: Daniel Lezcano @ 2020-05-22 19:08 UTC (permalink / raw)
  To: Michael Kao, Zhang Rui, Eduardo Valentin, Rob Herring,
	Mark Rutland, Matthias Brugger, hsinyi, linux-pm, srv_heupstream
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek, Louis Yu

On 08/04/2020 11:05, Michael Kao wrote:
> From: Louis Yu <louis.yu@mediatek.com>
> 
> Add suspend/resume callback to disable/enable Mediatek thermal sensor
> respectively. Since thermal power domain is off in suspend, thermal driver
> needs re-initialization during resume.
> 
> Signed-off-by: Louis Yu <louis.yu@mediatek.com>
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>

[ ... ]

> +static int __maybe_unused mtk_thermal_suspend(struct device *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct mtk_thermal *mt = platform_get_drvdata(pdev);
> +	int i, ret;
> +

Why is there a multi-controller loop in the probe and resume functions
and not here?

> +	for (i = 0; i < mt->conf->num_banks; i++) {
> +		ret = mtk_thermal_disable_sensing(mt, i);
> +		if (ret)
> +			goto out;
> +	}
> +
> +	/* disable buffer */
> +	writel(readl(mt->apmixed_base + APMIXED_SYS_TS_CON1) |
> +	       APMIXED_SYS_TS_CON1_BUFFER_OFF,
> +	       mt->apmixed_base + APMIXED_SYS_TS_CON1);
> +
> +	clk_disable_unprepare(mt->clk_peri_therm);
> +	clk_disable_unprepare(mt->clk_auxadc);
> +
> +	return 0;
> +
> +out:
> +	dev_err(&pdev->dev, "Failed to wait until bus idle\n");
> +
> +	return ret;
> +}
> +
> +static int __maybe_unused mtk_thermal_resume(struct device *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct mtk_thermal *mt = platform_get_drvdata(pdev);
> +	int i, ret, ctrl_id;
> +
> +	ret = device_reset(&pdev->dev);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_prepare_enable(mt->clk_auxadc);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
> +		goto err_disable_clk_auxadc;
> +	}
> +
> +	ret = clk_prepare_enable(mt->clk_peri_therm);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
> +		goto err_disable_clk_peri_therm;
> +	}
> +
> +	for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
> +		for (i = 0; i < mt->conf->num_banks; i++)
> +			mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
> +					      mt->auxadc_phys_base, ctrl_id);
> +
> +	return 0;
> +
> +err_disable_clk_peri_therm:
> +	clk_disable_unprepare(mt->clk_peri_therm);
> +err_disable_clk_auxadc:
> +	clk_disable_unprepare(mt->clk_auxadc);
> +
> +	return ret;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(mtk_thermal_pm_ops,
> +			 mtk_thermal_suspend, mtk_thermal_resume);
> +
>  static struct platform_driver mtk_thermal_driver = {
>  	.probe = mtk_thermal_probe,
>  	.remove = mtk_thermal_remove,
>  	.driver = {
>  		.name = "mtk-thermal",
> +		.pm = &mtk_thermal_pm_ops,
>  		.of_match_table = mtk_thermal_of_match,
>  	},
>  };
> 


-- 
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RESEND PATCH] thermal: mediatek: add suspend/resume callback
  2020-04-08  9:05 ` [RESEND PATCH] " Michael Kao
@ 2020-05-14  8:46   ` Michael Kao
  2020-07-07  8:47     ` Michael Kao
  2020-05-22 19:08   ` Daniel Lezcano
  1 sibling, 1 reply; 11+ messages in thread
From: Michael Kao @ 2020-05-14  8:46 UTC (permalink / raw)
  To: Zhang Rui, Daniel Lezcano
  Cc: Eduardo Valentin, Daniel Lezcano, Rob Herring, Mark Rutland,
	Matthias Brugger, hsinyi, linux-pm, srv_heupstream, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek,
	Louis Yu (游政錕)

On Wed, 2020-04-08 at 17:05 +0800, Michael Kao (高振翔) wrote:
> From: Louis Yu <louis.yu@mediatek.com>
> 
> Add suspend/resume callback to disable/enable Mediatek thermal sensor
> respectively. Since thermal power domain is off in suspend, thermal driver
> needs re-initialization during resume.
> 
> Signed-off-by: Louis Yu <louis.yu@mediatek.com>
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> ---
>  drivers/thermal/mtk_thermal.c | 152 ++++++++++++++++++++++++++++++----
>  1 file changed, 134 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
> index 76e30603d4d5..36fd35fac733 100644
> --- a/drivers/thermal/mtk_thermal.c
> +++ b/drivers/thermal/mtk_thermal.c
> @@ -22,6 +22,7 @@
>  #include <linux/thermal.h>
>  #include <linux/reset.h>
>  #include <linux/types.h>
> +#include <linux/iopoll.h>
> 
>  /* AUXADC Registers */
>  #define AUXADC_CON1_SET_V      0x008
> @@ -31,6 +32,8 @@
> 
>  #define APMIXED_SYS_TS_CON1    0x604
> 
> +#define APMIXED_SYS_TS_CON1_BUFFER_OFF 0x30
> +
>  /* Thermal Controller Registers */
>  #define TEMP_MONCTL0           0x000
>  #define TEMP_MONCTL1           0x004
> @@ -38,6 +41,7 @@
>  #define TEMP_MONIDET0          0x014
>  #define TEMP_MONIDET1          0x018
>  #define TEMP_MSRCTL0           0x038
> +#define TEMP_MSRCTL1           0x03c
>  #define TEMP_AHBPOLL           0x040
>  #define TEMP_AHBTO             0x044
>  #define TEMP_ADCPNP0           0x048
> @@ -87,6 +91,9 @@
>  #define TEMP_ADCVALIDMASK_VALID_HIGH           BIT(5)
>  #define TEMP_ADCVALIDMASK_VALID_POS(bit)       (bit)
> 
> +#define TEMP_MSRCTL1_BUS_STA   (BIT(0) | BIT(7))
> +#define TEMP_MSRCTL1_SENSING_POINTS_PAUSE      0x10E
> +
>  /* MT8173 thermal sensors */
>  #define MT8173_TS1     0
>  #define MT8173_TS2     1
> @@ -250,6 +257,10 @@ struct mtk_thermal_data {
>  struct mtk_thermal {
>         struct device *dev;
>         void __iomem *thermal_base;
> +       void __iomem *apmixed_base;
> +       void __iomem *auxadc_base;
> +       u64 apmixed_phys_base;
> +       u64 auxadc_phys_base;
> 
>         struct clk *clk_peri_therm;
>         struct clk *clk_auxadc;
> @@ -541,13 +552,13 @@ static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw)
>  }
> 
>  /**
> - * mtk_thermal_get_bank - get bank
> + * mtk_thermal_lock_bank - get bank
>   * @bank:      The bank
>   *
>   * The bank registers are banked, we have to select a bank in the
>   * PTPCORESEL register to access it.
>   */
> -static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
> +static void mtk_thermal_lock_bank(struct mtk_thermal_bank *bank)
>  {
>         struct mtk_thermal *mt = bank->mt;
>         u32 val;
> @@ -563,12 +574,12 @@ static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
>  }
> 
>  /**
> - * mtk_thermal_put_bank - release bank
> + * mtk_thermal_unlock_bank - release bank
>   * @bank:      The bank
>   *
> - * release a bank previously taken with mtk_thermal_get_bank,
> + * release a bank previously taken with mtk_thermal_lock_bank,
>   */
> -static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
> +static void mtk_thermal_unlock_bank(struct mtk_thermal_bank *bank)
>  {
>         struct mtk_thermal *mt = bank->mt;
> 
> @@ -622,11 +633,11 @@ static int mtk_read_temp(void *data, int *temperature)
>         for (i = 0; i < mt->conf->num_banks; i++) {
>                 struct mtk_thermal_bank *bank = &mt->banks[i];
> 
> -               mtk_thermal_get_bank(bank);
> +               mtk_thermal_lock_bank(bank);
> 
>                 tempmax = max(tempmax, mtk_thermal_bank_temperature(bank));
> 
> -               mtk_thermal_put_bank(bank);
> +               mtk_thermal_unlock_bank(bank);
>         }
> 
>         *temperature = tempmax;
> @@ -652,7 +663,7 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
>         bank->id = num;
>         bank->mt = mt;
> 
> -       mtk_thermal_get_bank(bank);
> +       mtk_thermal_lock_bank(bank);
> 
>         /* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */
>         writel(TEMP_MONCTL1_PERIOD_UNIT(12), controller_base + TEMP_MONCTL1);
> @@ -743,7 +754,43 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
>                TEMP_ADCWRITECTRL_ADC_MUX_WRITE,
>                controller_base + TEMP_ADCWRITECTRL);
> 
> -       mtk_thermal_put_bank(bank);
> +       mtk_thermal_unlock_bank(bank);
> +}
> +
> +static int mtk_thermal_disable_sensing(struct mtk_thermal *mt, int num)
> +{
> +       struct mtk_thermal_bank *bank = &mt->banks[num];
> +       u32 val;
> +       unsigned long timeout;
> +       void __iomem *addr;
> +       int ret = 0;
> +
> +       bank->id = num;
> +       bank->mt = mt;
> +
> +       mtk_thermal_lock_bank(bank);
> +
> +       val = readl(mt->thermal_base + TEMP_MSRCTL1);
> +       /* pause periodic temperature measurement for sensing points */
> +       writel(val | TEMP_MSRCTL1_SENSING_POINTS_PAUSE,
> +              mt->thermal_base + TEMP_MSRCTL1);
> +
> +       /* wait until temperature measurement bus idle */
> +       timeout = jiffies + HZ;
> +       addr = mt->thermal_base + TEMP_MSRCTL1;
> +
> +       ret = readl_poll_timeout(addr, val, (val & TEMP_MSRCTL1_BUS_STA) == 0x0,
> +                                0, timeout);
> +       if (ret < 0)
> +               goto out;
> +
> +       /* disable periodic temperature measurement on sensing points */
> +       writel(0x0, mt->thermal_base + TEMP_MONCTL0);
> +
> +out:
> +       mtk_thermal_unlock_bank(bank);
> +
> +       return ret;
>  }
> 
>  static u64 of_get_phys_base(struct device_node *np)
> @@ -868,7 +915,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>         struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
>         struct mtk_thermal *mt;
>         struct resource *res;
> -       u64 auxadc_phys_base, apmixed_phys_base;
>         struct thermal_zone_device *tzdev;
> 
>         mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
> @@ -904,11 +950,11 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>                 return -ENODEV;
>         }
> 
> -       auxadc_phys_base = of_get_phys_base(auxadc);
> +       mt->auxadc_phys_base = of_get_phys_base(auxadc);
> 
>         of_node_put(auxadc);
> 
> -       if (auxadc_phys_base == OF_BAD_ADDR) {
> +       if (mt->auxadc_phys_base == OF_BAD_ADDR) {
>                 dev_err(&pdev->dev, "Can't get auxadc phys address\n");
>                 return -EINVAL;
>         }
> @@ -919,11 +965,12 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>                 return -ENODEV;
>         }
> 
> -       apmixed_phys_base = of_get_phys_base(apmixedsys);
> +       mt->apmixed_phys_base = of_get_phys_base(apmixedsys);
> +       mt->apmixed_base = of_iomap(apmixedsys, 0);
> 
>         of_node_put(apmixedsys);
> 
> -       if (apmixed_phys_base == OF_BAD_ADDR) {
> +       if (mt->apmixed_phys_base == OF_BAD_ADDR) {
>                 dev_err(&pdev->dev, "Can't get auxadc phys address\n");
>                 return -EINVAL;
>         }
> @@ -935,19 +982,19 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>         ret = clk_prepare_enable(mt->clk_auxadc);
>         if (ret) {
>                 dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
> -               return ret;
> +               goto err_disable_clk_auxadc;
>         }
> 
>         ret = clk_prepare_enable(mt->clk_peri_therm);
>         if (ret) {
>                 dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
> -               goto err_disable_clk_auxadc;
> +               goto err_disable_clk_peri_therm;
>         }
> 
>         for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
>                 for (i = 0; i < mt->conf->num_banks; i++)
> -                       mtk_thermal_init_bank(mt, i, apmixed_phys_base,
> -                                             auxadc_phys_base, ctrl_id);
> +                       mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
> +                                             mt->auxadc_phys_base, ctrl_id);
> 
>         platform_set_drvdata(pdev, mt);
> 
> @@ -978,11 +1025,80 @@ static int mtk_thermal_remove(struct platform_device *pdev)
>         return 0;
>  }
> 
> +static int __maybe_unused mtk_thermal_suspend(struct device *dev)
> +{
> +       struct platform_device *pdev = to_platform_device(dev);
> +       struct mtk_thermal *mt = platform_get_drvdata(pdev);
> +       int i, ret;
> +
> +       for (i = 0; i < mt->conf->num_banks; i++) {
> +               ret = mtk_thermal_disable_sensing(mt, i);
> +               if (ret)
> +                       goto out;
> +       }
> +
> +       /* disable buffer */
> +       writel(readl(mt->apmixed_base + APMIXED_SYS_TS_CON1) |
> +              APMIXED_SYS_TS_CON1_BUFFER_OFF,
> +              mt->apmixed_base + APMIXED_SYS_TS_CON1);
> +
> +       clk_disable_unprepare(mt->clk_peri_therm);
> +       clk_disable_unprepare(mt->clk_auxadc);
> +
> +       return 0;
> +
> +out:
> +       dev_err(&pdev->dev, "Failed to wait until bus idle\n");
> +
> +       return ret;
> +}
> +
> +static int __maybe_unused mtk_thermal_resume(struct device *dev)
> +{
> +       struct platform_device *pdev = to_platform_device(dev);
> +       struct mtk_thermal *mt = platform_get_drvdata(pdev);
> +       int i, ret, ctrl_id;
> +
> +       ret = device_reset(&pdev->dev);
> +       if (ret)
> +               return ret;
> +
> +       ret = clk_prepare_enable(mt->clk_auxadc);
> +       if (ret) {
> +               dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
> +               goto err_disable_clk_auxadc;
> +       }
> +
> +       ret = clk_prepare_enable(mt->clk_peri_therm);
> +       if (ret) {
> +               dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
> +               goto err_disable_clk_peri_therm;
> +       }
> +
> +       for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
> +               for (i = 0; i < mt->conf->num_banks; i++)
> +                       mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
> +                                             mt->auxadc_phys_base, ctrl_id);
> +
> +       return 0;
> +
> +err_disable_clk_peri_therm:
> +       clk_disable_unprepare(mt->clk_peri_therm);
> +err_disable_clk_auxadc:
> +       clk_disable_unprepare(mt->clk_auxadc);
> +
> +       return ret;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(mtk_thermal_pm_ops,
> +                        mtk_thermal_suspend, mtk_thermal_resume);
> +
>  static struct platform_driver mtk_thermal_driver = {
>         .probe = mtk_thermal_probe,
>         .remove = mtk_thermal_remove,
>         .driver = {
>                 .name = "mtk-thermal",
> +               .pm = &mtk_thermal_pm_ops,
>                 .of_match_table = mtk_thermal_of_match,
>         },
>  };
> --
> 2.18.0
> 
Hi Daniel,
Just gently ping.    Many thanks.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [RESEND PATCH] thermal: mediatek: add suspend/resume callback
  2020-04-08  9:05 [RESEND PATCH 0/1] " Michael Kao
@ 2020-04-08  9:05 ` Michael Kao
  2020-05-14  8:46   ` Michael Kao
  2020-05-22 19:08   ` Daniel Lezcano
  0 siblings, 2 replies; 11+ messages in thread
From: Michael Kao @ 2020-04-08  9:05 UTC (permalink / raw)
  To: michael.kao, Zhang Rui, Eduardo Valentin, Daniel Lezcano,
	Rob Herring, Mark Rutland, Matthias Brugger, hsinyi, linux-pm,
	srv_heupstream
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek, Louis Yu

From: Louis Yu <louis.yu@mediatek.com>

Add suspend/resume callback to disable/enable Mediatek thermal sensor
respectively. Since thermal power domain is off in suspend, thermal driver
needs re-initialization during resume.

Signed-off-by: Louis Yu <louis.yu@mediatek.com>
Signed-off-by: Michael Kao <michael.kao@mediatek.com>
---
 drivers/thermal/mtk_thermal.c | 152 ++++++++++++++++++++++++++++++----
 1 file changed, 134 insertions(+), 18 deletions(-)

diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
index 76e30603d4d5..36fd35fac733 100644
--- a/drivers/thermal/mtk_thermal.c
+++ b/drivers/thermal/mtk_thermal.c
@@ -22,6 +22,7 @@
 #include <linux/thermal.h>
 #include <linux/reset.h>
 #include <linux/types.h>
+#include <linux/iopoll.h>
 
 /* AUXADC Registers */
 #define AUXADC_CON1_SET_V	0x008
@@ -31,6 +32,8 @@
 
 #define APMIXED_SYS_TS_CON1	0x604
 
+#define APMIXED_SYS_TS_CON1_BUFFER_OFF	0x30
+
 /* Thermal Controller Registers */
 #define TEMP_MONCTL0		0x000
 #define TEMP_MONCTL1		0x004
@@ -38,6 +41,7 @@
 #define TEMP_MONIDET0		0x014
 #define TEMP_MONIDET1		0x018
 #define TEMP_MSRCTL0		0x038
+#define TEMP_MSRCTL1		0x03c
 #define TEMP_AHBPOLL		0x040
 #define TEMP_AHBTO		0x044
 #define TEMP_ADCPNP0		0x048
@@ -87,6 +91,9 @@
 #define TEMP_ADCVALIDMASK_VALID_HIGH		BIT(5)
 #define TEMP_ADCVALIDMASK_VALID_POS(bit)	(bit)
 
+#define TEMP_MSRCTL1_BUS_STA	(BIT(0) | BIT(7))
+#define TEMP_MSRCTL1_SENSING_POINTS_PAUSE	0x10E
+
 /* MT8173 thermal sensors */
 #define MT8173_TS1	0
 #define MT8173_TS2	1
@@ -250,6 +257,10 @@ struct mtk_thermal_data {
 struct mtk_thermal {
 	struct device *dev;
 	void __iomem *thermal_base;
+	void __iomem *apmixed_base;
+	void __iomem *auxadc_base;
+	u64 apmixed_phys_base;
+	u64 auxadc_phys_base;
 
 	struct clk *clk_peri_therm;
 	struct clk *clk_auxadc;
@@ -541,13 +552,13 @@ static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw)
 }
 
 /**
- * mtk_thermal_get_bank - get bank
+ * mtk_thermal_lock_bank - get bank
  * @bank:	The bank
  *
  * The bank registers are banked, we have to select a bank in the
  * PTPCORESEL register to access it.
  */
-static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
+static void mtk_thermal_lock_bank(struct mtk_thermal_bank *bank)
 {
 	struct mtk_thermal *mt = bank->mt;
 	u32 val;
@@ -563,12 +574,12 @@ static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
 }
 
 /**
- * mtk_thermal_put_bank - release bank
+ * mtk_thermal_unlock_bank - release bank
  * @bank:	The bank
  *
- * release a bank previously taken with mtk_thermal_get_bank,
+ * release a bank previously taken with mtk_thermal_lock_bank,
  */
-static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
+static void mtk_thermal_unlock_bank(struct mtk_thermal_bank *bank)
 {
 	struct mtk_thermal *mt = bank->mt;
 
@@ -622,11 +633,11 @@ static int mtk_read_temp(void *data, int *temperature)
 	for (i = 0; i < mt->conf->num_banks; i++) {
 		struct mtk_thermal_bank *bank = &mt->banks[i];
 
-		mtk_thermal_get_bank(bank);
+		mtk_thermal_lock_bank(bank);
 
 		tempmax = max(tempmax, mtk_thermal_bank_temperature(bank));
 
-		mtk_thermal_put_bank(bank);
+		mtk_thermal_unlock_bank(bank);
 	}
 
 	*temperature = tempmax;
@@ -652,7 +663,7 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
 	bank->id = num;
 	bank->mt = mt;
 
-	mtk_thermal_get_bank(bank);
+	mtk_thermal_lock_bank(bank);
 
 	/* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */
 	writel(TEMP_MONCTL1_PERIOD_UNIT(12), controller_base + TEMP_MONCTL1);
@@ -743,7 +754,43 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
 	       TEMP_ADCWRITECTRL_ADC_MUX_WRITE,
 	       controller_base + TEMP_ADCWRITECTRL);
 
-	mtk_thermal_put_bank(bank);
+	mtk_thermal_unlock_bank(bank);
+}
+
+static int mtk_thermal_disable_sensing(struct mtk_thermal *mt, int num)
+{
+	struct mtk_thermal_bank *bank = &mt->banks[num];
+	u32 val;
+	unsigned long timeout;
+	void __iomem *addr;
+	int ret = 0;
+
+	bank->id = num;
+	bank->mt = mt;
+
+	mtk_thermal_lock_bank(bank);
+
+	val = readl(mt->thermal_base + TEMP_MSRCTL1);
+	/* pause periodic temperature measurement for sensing points */
+	writel(val | TEMP_MSRCTL1_SENSING_POINTS_PAUSE,
+	       mt->thermal_base + TEMP_MSRCTL1);
+
+	/* wait until temperature measurement bus idle */
+	timeout = jiffies + HZ;
+	addr = mt->thermal_base + TEMP_MSRCTL1;
+
+	ret = readl_poll_timeout(addr, val, (val & TEMP_MSRCTL1_BUS_STA) == 0x0,
+				 0, timeout);
+	if (ret < 0)
+		goto out;
+
+	/* disable periodic temperature measurement on sensing points */
+	writel(0x0, mt->thermal_base + TEMP_MONCTL0);
+
+out:
+	mtk_thermal_unlock_bank(bank);
+
+	return ret;
 }
 
 static u64 of_get_phys_base(struct device_node *np)
@@ -868,7 +915,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 	struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
 	struct mtk_thermal *mt;
 	struct resource *res;
-	u64 auxadc_phys_base, apmixed_phys_base;
 	struct thermal_zone_device *tzdev;
 
 	mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
@@ -904,11 +950,11 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	auxadc_phys_base = of_get_phys_base(auxadc);
+	mt->auxadc_phys_base = of_get_phys_base(auxadc);
 
 	of_node_put(auxadc);
 
-	if (auxadc_phys_base == OF_BAD_ADDR) {
+	if (mt->auxadc_phys_base == OF_BAD_ADDR) {
 		dev_err(&pdev->dev, "Can't get auxadc phys address\n");
 		return -EINVAL;
 	}
@@ -919,11 +965,12 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	apmixed_phys_base = of_get_phys_base(apmixedsys);
+	mt->apmixed_phys_base = of_get_phys_base(apmixedsys);
+	mt->apmixed_base = of_iomap(apmixedsys, 0);
 
 	of_node_put(apmixedsys);
 
-	if (apmixed_phys_base == OF_BAD_ADDR) {
+	if (mt->apmixed_phys_base == OF_BAD_ADDR) {
 		dev_err(&pdev->dev, "Can't get auxadc phys address\n");
 		return -EINVAL;
 	}
@@ -935,19 +982,19 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 	ret = clk_prepare_enable(mt->clk_auxadc);
 	if (ret) {
 		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
-		return ret;
+		goto err_disable_clk_auxadc;
 	}
 
 	ret = clk_prepare_enable(mt->clk_peri_therm);
 	if (ret) {
 		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
-		goto err_disable_clk_auxadc;
+		goto err_disable_clk_peri_therm;
 	}
 
 	for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
 		for (i = 0; i < mt->conf->num_banks; i++)
-			mtk_thermal_init_bank(mt, i, apmixed_phys_base,
-					      auxadc_phys_base, ctrl_id);
+			mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
+					      mt->auxadc_phys_base, ctrl_id);
 
 	platform_set_drvdata(pdev, mt);
 
@@ -978,11 +1025,80 @@ static int mtk_thermal_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int __maybe_unused mtk_thermal_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mtk_thermal *mt = platform_get_drvdata(pdev);
+	int i, ret;
+
+	for (i = 0; i < mt->conf->num_banks; i++) {
+		ret = mtk_thermal_disable_sensing(mt, i);
+		if (ret)
+			goto out;
+	}
+
+	/* disable buffer */
+	writel(readl(mt->apmixed_base + APMIXED_SYS_TS_CON1) |
+	       APMIXED_SYS_TS_CON1_BUFFER_OFF,
+	       mt->apmixed_base + APMIXED_SYS_TS_CON1);
+
+	clk_disable_unprepare(mt->clk_peri_therm);
+	clk_disable_unprepare(mt->clk_auxadc);
+
+	return 0;
+
+out:
+	dev_err(&pdev->dev, "Failed to wait until bus idle\n");
+
+	return ret;
+}
+
+static int __maybe_unused mtk_thermal_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mtk_thermal *mt = platform_get_drvdata(pdev);
+	int i, ret, ctrl_id;
+
+	ret = device_reset(&pdev->dev);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(mt->clk_auxadc);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
+		goto err_disable_clk_auxadc;
+	}
+
+	ret = clk_prepare_enable(mt->clk_peri_therm);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
+		goto err_disable_clk_peri_therm;
+	}
+
+	for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
+		for (i = 0; i < mt->conf->num_banks; i++)
+			mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
+					      mt->auxadc_phys_base, ctrl_id);
+
+	return 0;
+
+err_disable_clk_peri_therm:
+	clk_disable_unprepare(mt->clk_peri_therm);
+err_disable_clk_auxadc:
+	clk_disable_unprepare(mt->clk_auxadc);
+
+	return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(mtk_thermal_pm_ops,
+			 mtk_thermal_suspend, mtk_thermal_resume);
+
 static struct platform_driver mtk_thermal_driver = {
 	.probe = mtk_thermal_probe,
 	.remove = mtk_thermal_remove,
 	.driver = {
 		.name = "mtk-thermal",
+		.pm = &mtk_thermal_pm_ops,
 		.of_match_table = mtk_thermal_of_match,
 	},
 };
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [RESEND][PATCH] thermal: mediatek: add suspend/resume callback
  2019-12-19  9:24 ` [RESEND][PATCH] " Michael Kao
  2019-12-27  8:56   ` Michael Kao
@ 2020-01-09 23:37   ` Daniel Lezcano
  1 sibling, 0 replies; 11+ messages in thread
From: Daniel Lezcano @ 2020-01-09 23:37 UTC (permalink / raw)
  To: Michael Kao, Zhang Rui, Eduardo Valentin, Rob Herring,
	Mark Rutland, Matthias Brugger, hsinyi, linux-pm, srv_heupstream
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek, Louis Yu

On 19/12/2019 10:24, Michael Kao wrote:
> From: Louis Yu <louis.yu@mediatek.com>
> 
> Add suspend/resume callback to disable/enable Mediatek thermal sensor
> respectively. Since thermal power domain is off in suspend, thermal driver
> needs re-initialization during resume.
> 
> Signed-off-by: Louis Yu <louis.yu@mediatek.com>
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> ---
>  drivers/thermal/mtk_thermal.c | 134 +++++++++++++++++++++++++++++++---
>  1 file changed, 125 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
> index acf4854cbb8b..2bb8b13591aa 100644
> --- a/drivers/thermal/mtk_thermal.c
> +++ b/drivers/thermal/mtk_thermal.c
> @@ -22,6 +22,7 @@
>  #include <linux/thermal.h>
>  #include <linux/reset.h>
>  #include <linux/types.h>
> +#include <linux/iopoll.h>
>  
>  /* AUXADC Registers */
>  #define AUXADC_CON1_SET_V	0x008
> @@ -31,6 +32,8 @@
>  
>  #define APMIXED_SYS_TS_CON1	0x604
>  
> +#define APMIXED_SYS_TS_CON1_BUFFER_OFF	0x30
> +
>  /* Thermal Controller Registers */
>  #define TEMP_MONCTL0		0x000
>  #define TEMP_MONCTL1		0x004
> @@ -38,6 +41,7 @@
>  #define TEMP_MONIDET0		0x014
>  #define TEMP_MONIDET1		0x018
>  #define TEMP_MSRCTL0		0x038
> +#define TEMP_MSRCTL1		0x03c
>  #define TEMP_AHBPOLL		0x040
>  #define TEMP_AHBTO		0x044
>  #define TEMP_ADCPNP0		0x048
> @@ -87,6 +91,9 @@
>  #define TEMP_ADCVALIDMASK_VALID_HIGH		BIT(5)
>  #define TEMP_ADCVALIDMASK_VALID_POS(bit)	(bit)
>  
> +#define TEMP_MSRCTL1_BUS_STA	(BIT(0) | BIT(7))
> +#define TEMP_MSRCTL1_SENSING_POINTS_PAUSE	0x10E
> +
>  /* MT8173 thermal sensors */
>  #define MT8173_TS1	0
>  #define MT8173_TS2	1
> @@ -250,6 +257,10 @@ struct mtk_thermal_data {
>  struct mtk_thermal {
>  	struct device *dev;
>  	void __iomem *thermal_base;
> +	void __iomem *apmixed_base;
> +	void __iomem *auxadc_base;
> +	u64 apmixed_phys_base;
> +	u64 auxadc_phys_base;
>  
>  	struct clk *clk_peri_therm;
>  	struct clk *clk_auxadc;
> @@ -746,6 +757,42 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
>  	mtk_thermal_put_bank(bank);
>  }
>  
> +static int mtk_thermal_disable_sensing(struct mtk_thermal *mt, int num)
> +{
> +	struct mtk_thermal_bank *bank = &mt->banks[num];
> +	u32 val;
> +	unsigned long timeout;
> +	void __iomem *addr;
> +	int ret = 0;
> +
> +	bank->id = num;
> +	bank->mt = mt;

Can you explain why this is done?

> +	mtk_thermal_get_bank(bank);

I'm not comfortable with this call. The underlying code is calling
mutex_lock, I suspect it can potentially deadlock the board.

Why do you need a mutex? Isn't a spin_lock enough?

Please take also the opportunity to rename to lock_bank / unlock_bank.
get and put are usually for refcounting.

> +	val = readl(mt->thermal_base + TEMP_MSRCTL1);
> +	/* pause periodic temperature measurement for sensing points */
> +	writel(val | TEMP_MSRCTL1_SENSING_POINTS_PAUSE,
> +	       mt->thermal_base + TEMP_MSRCTL1);
> +
> +	/* wait until temperature measurement bus idle */
> +	timeout = jiffies + HZ;
> +	addr = mt->thermal_base + TEMP_MSRCTL1;
> +
> +	ret = readl_poll_timeout(addr, val, (val & TEMP_MSRCTL1_BUS_STA) == 0x0,
> +				 0, timeout);
> +	if (ret < 0)
> +		goto out;
> +
> +	/* disable periodic temperature meausrement on sensing points */

s/meausrement/measurement/

> +	writel(0x0, mt->thermal_base + TEMP_MONCTL0);
> +
> +out:
> +	mtk_thermal_put_bank(bank);
> +
> +	return ret;
> +}
> +
>  static u64 of_get_phys_base(struct device_node *np)
>  {
>  	u64 size64;
> @@ -868,7 +915,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>  	struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
>  	struct mtk_thermal *mt;
>  	struct resource *res;
> -	u64 auxadc_phys_base, apmixed_phys_base;
>  	struct thermal_zone_device *tzdev;
>  
>  	mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
> @@ -904,11 +950,11 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>  		return -ENODEV;
>  	}
>  
> -	auxadc_phys_base = of_get_phys_base(auxadc);
> +	mt->auxadc_phys_base = of_get_phys_base(auxadc);
>  
>  	of_node_put(auxadc);
>  
> -	if (auxadc_phys_base == OF_BAD_ADDR) {
> +	if (mt->auxadc_phys_base == OF_BAD_ADDR) {
>  		dev_err(&pdev->dev, "Can't get auxadc phys address\n");
>  		return -EINVAL;
>  	}
> @@ -919,11 +965,12 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>  		return -ENODEV;
>  	}
>  
> -	apmixed_phys_base = of_get_phys_base(apmixedsys);
> +	mt->apmixed_phys_base = of_get_phys_base(apmixedsys);
> +	mt->apmixed_base = of_iomap(apmixedsys, 0);
>  
>  	of_node_put(apmixedsys);
>  
> -	if (apmixed_phys_base == OF_BAD_ADDR) {
> +	if (mt->apmixed_phys_base == OF_BAD_ADDR) {
>  		dev_err(&pdev->dev, "Can't get auxadc phys address\n");
>  		return -EINVAL;
>  	}
> @@ -935,19 +982,19 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>  	ret = clk_prepare_enable(mt->clk_auxadc);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
> -		return ret;
> +		goto err_disable_clk_auxadc;
>  	}
>  
>  	ret = clk_prepare_enable(mt->clk_peri_therm);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
> -		goto err_disable_clk_auxadc;
> +		goto err_disable_clk_peri_therm;
>  	}
>  
>  	for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
>  		for (i = 0; i < mt->conf->num_banks; i++)
> -			mtk_thermal_init_bank(mt, i, apmixed_phys_base,
> -					      auxadc_phys_base, ctrl_id);
> +			mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
> +					      mt->auxadc_phys_base, ctrl_id);
>  
>  	platform_set_drvdata(pdev, mt);
>  
> @@ -978,11 +1025,80 @@ static int mtk_thermal_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +static int __maybe_unused mtk_thermal_suspend(struct device *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct mtk_thermal *mt = platform_get_drvdata(pdev);
> +	int i, ret;
> +
> +	for (i = 0; i < mt->conf->num_banks; i++) {
> +		ret = mtk_thermal_disable_sensing(mt, i);
> +		if (ret)
> +			goto out;
> +	}
> +
> +	/* disable buffer */
> +	writel(readl(mt->apmixed_base + APMIXED_SYS_TS_CON1) |
> +	       APMIXED_SYS_TS_CON1_BUFFER_OFF,
> +	       mt->apmixed_base + APMIXED_SYS_TS_CON1);
> +
> +	clk_disable_unprepare(mt->clk_peri_therm);
> +	clk_disable_unprepare(mt->clk_auxadc);
> +
> +	return 0;
> +
> +out:
> +	dev_err(&pdev->dev, "Failed to wait until bus idle\n");
> +
> +	return ret;
> +}
> +
> +static int __maybe_unused mtk_thermal_resume(struct device *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct mtk_thermal *mt = platform_get_drvdata(pdev);
> +	int i, ret, ctrl_id;
> +
> +	ret = device_reset(&pdev->dev);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_prepare_enable(mt->clk_auxadc);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
> +		goto err_disable_clk_auxadc;
> +	}
> +
> +	ret = clk_prepare_enable(mt->clk_peri_therm);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
> +		goto err_disable_clk_peri_therm;
> +	}
> +
> +	for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
> +		for (i = 0; i < mt->conf->num_banks; i++)
> +			mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
> +					      mt->auxadc_phys_base, ctrl_id);
> +
> +	return 0;
> +
> +err_disable_clk_peri_therm:
> +	clk_disable_unprepare(mt->clk_peri_therm);
> +err_disable_clk_auxadc:
> +	clk_disable_unprepare(mt->clk_auxadc);
> +
> +	return ret;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(mtk_thermal_pm_ops,
> +			 mtk_thermal_suspend, mtk_thermal_resume);
> +
>  static struct platform_driver mtk_thermal_driver = {
>  	.probe = mtk_thermal_probe,
>  	.remove = mtk_thermal_remove,
>  	.driver = {
>  		.name = "mtk-thermal",
> +		.pm = &mtk_thermal_pm_ops,
>  		.of_match_table = mtk_thermal_of_match,
>  	},
>  };
> 


-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RESEND][PATCH] thermal: mediatek: add suspend/resume callback
  2019-12-19  9:24 ` [RESEND][PATCH] " Michael Kao
@ 2019-12-27  8:56   ` Michael Kao
  2020-01-09 23:37   ` Daniel Lezcano
  1 sibling, 0 replies; 11+ messages in thread
From: Michael Kao @ 2019-12-27  8:56 UTC (permalink / raw)
  To: Zhang Rui
  Cc: Eduardo Valentin, Daniel Lezcano, Rob Herring, Mark Rutland,
	Matthias Brugger, hsinyi, linux-pm, srv_heupstream, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, Louis Yu

Hi Daniel,
Just gentle ping. Many thanks.


On Thu, 2019-12-19 at 17:24 +0800, Michael Kao wrote:
> From: Louis Yu <louis.yu@mediatek.com>
> 
> Add suspend/resume callback to disable/enable Mediatek thermal sensor
> respectively. Since thermal power domain is off in suspend, thermal driver
> needs re-initialization during resume.
> 
> Signed-off-by: Louis Yu <louis.yu@mediatek.com>
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> ---
>  drivers/thermal/mtk_thermal.c | 134 +++++++++++++++++++++++++++++++---
>  1 file changed, 125 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
> index acf4854cbb8b..2bb8b13591aa 100644
> --- a/drivers/thermal/mtk_thermal.c
> +++ b/drivers/thermal/mtk_thermal.c
> @@ -22,6 +22,7 @@
>  #include <linux/thermal.h>
>  #include <linux/reset.h>
>  #include <linux/types.h>
> +#include <linux/iopoll.h>
>  
>  /* AUXADC Registers */
>  #define AUXADC_CON1_SET_V	0x008
> @@ -31,6 +32,8 @@
>  
>  #define APMIXED_SYS_TS_CON1	0x604
>  
> +#define APMIXED_SYS_TS_CON1_BUFFER_OFF	0x30
> +
>  /* Thermal Controller Registers */
>  #define TEMP_MONCTL0		0x000
>  #define TEMP_MONCTL1		0x004
> @@ -38,6 +41,7 @@
>  #define TEMP_MONIDET0		0x014
>  #define TEMP_MONIDET1		0x018
>  #define TEMP_MSRCTL0		0x038
> +#define TEMP_MSRCTL1		0x03c
>  #define TEMP_AHBPOLL		0x040
>  #define TEMP_AHBTO		0x044
>  #define TEMP_ADCPNP0		0x048
> @@ -87,6 +91,9 @@
>  #define TEMP_ADCVALIDMASK_VALID_HIGH		BIT(5)
>  #define TEMP_ADCVALIDMASK_VALID_POS(bit)	(bit)
>  
> +#define TEMP_MSRCTL1_BUS_STA	(BIT(0) | BIT(7))
> +#define TEMP_MSRCTL1_SENSING_POINTS_PAUSE	0x10E
> +
>  /* MT8173 thermal sensors */
>  #define MT8173_TS1	0
>  #define MT8173_TS2	1
> @@ -250,6 +257,10 @@ struct mtk_thermal_data {
>  struct mtk_thermal {
>  	struct device *dev;
>  	void __iomem *thermal_base;
> +	void __iomem *apmixed_base;
> +	void __iomem *auxadc_base;
> +	u64 apmixed_phys_base;
> +	u64 auxadc_phys_base;
>  
>  	struct clk *clk_peri_therm;
>  	struct clk *clk_auxadc;
> @@ -746,6 +757,42 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
>  	mtk_thermal_put_bank(bank);
>  }
>  
> +static int mtk_thermal_disable_sensing(struct mtk_thermal *mt, int num)
> +{
> +	struct mtk_thermal_bank *bank = &mt->banks[num];
> +	u32 val;
> +	unsigned long timeout;
> +	void __iomem *addr;
> +	int ret = 0;
> +
> +	bank->id = num;
> +	bank->mt = mt;
> +
> +	mtk_thermal_get_bank(bank);
> +
> +	val = readl(mt->thermal_base + TEMP_MSRCTL1);
> +	/* pause periodic temperature measurement for sensing points */
> +	writel(val | TEMP_MSRCTL1_SENSING_POINTS_PAUSE,
> +	       mt->thermal_base + TEMP_MSRCTL1);
> +
> +	/* wait until temperature measurement bus idle */
> +	timeout = jiffies + HZ;
> +	addr = mt->thermal_base + TEMP_MSRCTL1;
> +
> +	ret = readl_poll_timeout(addr, val, (val & TEMP_MSRCTL1_BUS_STA) == 0x0,
> +				 0, timeout);
> +	if (ret < 0)
> +		goto out;
> +
> +	/* disable periodic temperature meausrement on sensing points */
> +	writel(0x0, mt->thermal_base + TEMP_MONCTL0);
> +
> +out:
> +	mtk_thermal_put_bank(bank);
> +
> +	return ret;
> +}
> +
>  static u64 of_get_phys_base(struct device_node *np)
>  {
>  	u64 size64;
> @@ -868,7 +915,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>  	struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
>  	struct mtk_thermal *mt;
>  	struct resource *res;
> -	u64 auxadc_phys_base, apmixed_phys_base;
>  	struct thermal_zone_device *tzdev;
>  
>  	mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
> @@ -904,11 +950,11 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>  		return -ENODEV;
>  	}
>  
> -	auxadc_phys_base = of_get_phys_base(auxadc);
> +	mt->auxadc_phys_base = of_get_phys_base(auxadc);
>  
>  	of_node_put(auxadc);
>  
> -	if (auxadc_phys_base == OF_BAD_ADDR) {
> +	if (mt->auxadc_phys_base == OF_BAD_ADDR) {
>  		dev_err(&pdev->dev, "Can't get auxadc phys address\n");
>  		return -EINVAL;
>  	}
> @@ -919,11 +965,12 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>  		return -ENODEV;
>  	}
>  
> -	apmixed_phys_base = of_get_phys_base(apmixedsys);
> +	mt->apmixed_phys_base = of_get_phys_base(apmixedsys);
> +	mt->apmixed_base = of_iomap(apmixedsys, 0);
>  
>  	of_node_put(apmixedsys);
>  
> -	if (apmixed_phys_base == OF_BAD_ADDR) {
> +	if (mt->apmixed_phys_base == OF_BAD_ADDR) {
>  		dev_err(&pdev->dev, "Can't get auxadc phys address\n");
>  		return -EINVAL;
>  	}
> @@ -935,19 +982,19 @@ static int mtk_thermal_probe(struct platform_device *pdev)
>  	ret = clk_prepare_enable(mt->clk_auxadc);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
> -		return ret;
> +		goto err_disable_clk_auxadc;
>  	}
>  
>  	ret = clk_prepare_enable(mt->clk_peri_therm);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
> -		goto err_disable_clk_auxadc;
> +		goto err_disable_clk_peri_therm;
>  	}
>  
>  	for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
>  		for (i = 0; i < mt->conf->num_banks; i++)
> -			mtk_thermal_init_bank(mt, i, apmixed_phys_base,
> -					      auxadc_phys_base, ctrl_id);
> +			mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
> +					      mt->auxadc_phys_base, ctrl_id);
>  
>  	platform_set_drvdata(pdev, mt);
>  
> @@ -978,11 +1025,80 @@ static int mtk_thermal_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +static int __maybe_unused mtk_thermal_suspend(struct device *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct mtk_thermal *mt = platform_get_drvdata(pdev);
> +	int i, ret;
> +
> +	for (i = 0; i < mt->conf->num_banks; i++) {
> +		ret = mtk_thermal_disable_sensing(mt, i);
> +		if (ret)
> +			goto out;
> +	}
> +
> +	/* disable buffer */
> +	writel(readl(mt->apmixed_base + APMIXED_SYS_TS_CON1) |
> +	       APMIXED_SYS_TS_CON1_BUFFER_OFF,
> +	       mt->apmixed_base + APMIXED_SYS_TS_CON1);
> +
> +	clk_disable_unprepare(mt->clk_peri_therm);
> +	clk_disable_unprepare(mt->clk_auxadc);
> +
> +	return 0;
> +
> +out:
> +	dev_err(&pdev->dev, "Failed to wait until bus idle\n");
> +
> +	return ret;
> +}
> +
> +static int __maybe_unused mtk_thermal_resume(struct device *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct mtk_thermal *mt = platform_get_drvdata(pdev);
> +	int i, ret, ctrl_id;
> +
> +	ret = device_reset(&pdev->dev);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_prepare_enable(mt->clk_auxadc);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
> +		goto err_disable_clk_auxadc;
> +	}
> +
> +	ret = clk_prepare_enable(mt->clk_peri_therm);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
> +		goto err_disable_clk_peri_therm;
> +	}
> +
> +	for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
> +		for (i = 0; i < mt->conf->num_banks; i++)
> +			mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
> +					      mt->auxadc_phys_base, ctrl_id);
> +
> +	return 0;
> +
> +err_disable_clk_peri_therm:
> +	clk_disable_unprepare(mt->clk_peri_therm);
> +err_disable_clk_auxadc:
> +	clk_disable_unprepare(mt->clk_auxadc);
> +
> +	return ret;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(mtk_thermal_pm_ops,
> +			 mtk_thermal_suspend, mtk_thermal_resume);
> +
>  static struct platform_driver mtk_thermal_driver = {
>  	.probe = mtk_thermal_probe,
>  	.remove = mtk_thermal_remove,
>  	.driver = {
>  		.name = "mtk-thermal",
> +		.pm = &mtk_thermal_pm_ops,
>  		.of_match_table = mtk_thermal_of_match,
>  	},
>  };


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [RESEND][PATCH] thermal: mediatek: add suspend/resume callback
  2019-12-19  9:24 [RESEND] " Michael Kao
@ 2019-12-19  9:24 ` Michael Kao
  2019-12-27  8:56   ` Michael Kao
  2020-01-09 23:37   ` Daniel Lezcano
  0 siblings, 2 replies; 11+ messages in thread
From: Michael Kao @ 2019-12-19  9:24 UTC (permalink / raw)
  To: Zhang Rui, Eduardo Valentin, Daniel Lezcano, Rob Herring,
	Mark Rutland, Matthias Brugger, hsinyi, linux-pm, srv_heupstream
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
	Louis Yu, Michael Kao

From: Louis Yu <louis.yu@mediatek.com>

Add suspend/resume callback to disable/enable Mediatek thermal sensor
respectively. Since thermal power domain is off in suspend, thermal driver
needs re-initialization during resume.

Signed-off-by: Louis Yu <louis.yu@mediatek.com>
Signed-off-by: Michael Kao <michael.kao@mediatek.com>
---
 drivers/thermal/mtk_thermal.c | 134 +++++++++++++++++++++++++++++++---
 1 file changed, 125 insertions(+), 9 deletions(-)

diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
index acf4854cbb8b..2bb8b13591aa 100644
--- a/drivers/thermal/mtk_thermal.c
+++ b/drivers/thermal/mtk_thermal.c
@@ -22,6 +22,7 @@
 #include <linux/thermal.h>
 #include <linux/reset.h>
 #include <linux/types.h>
+#include <linux/iopoll.h>
 
 /* AUXADC Registers */
 #define AUXADC_CON1_SET_V	0x008
@@ -31,6 +32,8 @@
 
 #define APMIXED_SYS_TS_CON1	0x604
 
+#define APMIXED_SYS_TS_CON1_BUFFER_OFF	0x30
+
 /* Thermal Controller Registers */
 #define TEMP_MONCTL0		0x000
 #define TEMP_MONCTL1		0x004
@@ -38,6 +41,7 @@
 #define TEMP_MONIDET0		0x014
 #define TEMP_MONIDET1		0x018
 #define TEMP_MSRCTL0		0x038
+#define TEMP_MSRCTL1		0x03c
 #define TEMP_AHBPOLL		0x040
 #define TEMP_AHBTO		0x044
 #define TEMP_ADCPNP0		0x048
@@ -87,6 +91,9 @@
 #define TEMP_ADCVALIDMASK_VALID_HIGH		BIT(5)
 #define TEMP_ADCVALIDMASK_VALID_POS(bit)	(bit)
 
+#define TEMP_MSRCTL1_BUS_STA	(BIT(0) | BIT(7))
+#define TEMP_MSRCTL1_SENSING_POINTS_PAUSE	0x10E
+
 /* MT8173 thermal sensors */
 #define MT8173_TS1	0
 #define MT8173_TS2	1
@@ -250,6 +257,10 @@ struct mtk_thermal_data {
 struct mtk_thermal {
 	struct device *dev;
 	void __iomem *thermal_base;
+	void __iomem *apmixed_base;
+	void __iomem *auxadc_base;
+	u64 apmixed_phys_base;
+	u64 auxadc_phys_base;
 
 	struct clk *clk_peri_therm;
 	struct clk *clk_auxadc;
@@ -746,6 +757,42 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
 	mtk_thermal_put_bank(bank);
 }
 
+static int mtk_thermal_disable_sensing(struct mtk_thermal *mt, int num)
+{
+	struct mtk_thermal_bank *bank = &mt->banks[num];
+	u32 val;
+	unsigned long timeout;
+	void __iomem *addr;
+	int ret = 0;
+
+	bank->id = num;
+	bank->mt = mt;
+
+	mtk_thermal_get_bank(bank);
+
+	val = readl(mt->thermal_base + TEMP_MSRCTL1);
+	/* pause periodic temperature measurement for sensing points */
+	writel(val | TEMP_MSRCTL1_SENSING_POINTS_PAUSE,
+	       mt->thermal_base + TEMP_MSRCTL1);
+
+	/* wait until temperature measurement bus idle */
+	timeout = jiffies + HZ;
+	addr = mt->thermal_base + TEMP_MSRCTL1;
+
+	ret = readl_poll_timeout(addr, val, (val & TEMP_MSRCTL1_BUS_STA) == 0x0,
+				 0, timeout);
+	if (ret < 0)
+		goto out;
+
+	/* disable periodic temperature meausrement on sensing points */
+	writel(0x0, mt->thermal_base + TEMP_MONCTL0);
+
+out:
+	mtk_thermal_put_bank(bank);
+
+	return ret;
+}
+
 static u64 of_get_phys_base(struct device_node *np)
 {
 	u64 size64;
@@ -868,7 +915,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 	struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
 	struct mtk_thermal *mt;
 	struct resource *res;
-	u64 auxadc_phys_base, apmixed_phys_base;
 	struct thermal_zone_device *tzdev;
 
 	mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
@@ -904,11 +950,11 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	auxadc_phys_base = of_get_phys_base(auxadc);
+	mt->auxadc_phys_base = of_get_phys_base(auxadc);
 
 	of_node_put(auxadc);
 
-	if (auxadc_phys_base == OF_BAD_ADDR) {
+	if (mt->auxadc_phys_base == OF_BAD_ADDR) {
 		dev_err(&pdev->dev, "Can't get auxadc phys address\n");
 		return -EINVAL;
 	}
@@ -919,11 +965,12 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	apmixed_phys_base = of_get_phys_base(apmixedsys);
+	mt->apmixed_phys_base = of_get_phys_base(apmixedsys);
+	mt->apmixed_base = of_iomap(apmixedsys, 0);
 
 	of_node_put(apmixedsys);
 
-	if (apmixed_phys_base == OF_BAD_ADDR) {
+	if (mt->apmixed_phys_base == OF_BAD_ADDR) {
 		dev_err(&pdev->dev, "Can't get auxadc phys address\n");
 		return -EINVAL;
 	}
@@ -935,19 +982,19 @@ static int mtk_thermal_probe(struct platform_device *pdev)
 	ret = clk_prepare_enable(mt->clk_auxadc);
 	if (ret) {
 		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
-		return ret;
+		goto err_disable_clk_auxadc;
 	}
 
 	ret = clk_prepare_enable(mt->clk_peri_therm);
 	if (ret) {
 		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
-		goto err_disable_clk_auxadc;
+		goto err_disable_clk_peri_therm;
 	}
 
 	for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
 		for (i = 0; i < mt->conf->num_banks; i++)
-			mtk_thermal_init_bank(mt, i, apmixed_phys_base,
-					      auxadc_phys_base, ctrl_id);
+			mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
+					      mt->auxadc_phys_base, ctrl_id);
 
 	platform_set_drvdata(pdev, mt);
 
@@ -978,11 +1025,80 @@ static int mtk_thermal_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int __maybe_unused mtk_thermal_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mtk_thermal *mt = platform_get_drvdata(pdev);
+	int i, ret;
+
+	for (i = 0; i < mt->conf->num_banks; i++) {
+		ret = mtk_thermal_disable_sensing(mt, i);
+		if (ret)
+			goto out;
+	}
+
+	/* disable buffer */
+	writel(readl(mt->apmixed_base + APMIXED_SYS_TS_CON1) |
+	       APMIXED_SYS_TS_CON1_BUFFER_OFF,
+	       mt->apmixed_base + APMIXED_SYS_TS_CON1);
+
+	clk_disable_unprepare(mt->clk_peri_therm);
+	clk_disable_unprepare(mt->clk_auxadc);
+
+	return 0;
+
+out:
+	dev_err(&pdev->dev, "Failed to wait until bus idle\n");
+
+	return ret;
+}
+
+static int __maybe_unused mtk_thermal_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mtk_thermal *mt = platform_get_drvdata(pdev);
+	int i, ret, ctrl_id;
+
+	ret = device_reset(&pdev->dev);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(mt->clk_auxadc);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
+		goto err_disable_clk_auxadc;
+	}
+
+	ret = clk_prepare_enable(mt->clk_peri_therm);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
+		goto err_disable_clk_peri_therm;
+	}
+
+	for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
+		for (i = 0; i < mt->conf->num_banks; i++)
+			mtk_thermal_init_bank(mt, i, mt->apmixed_phys_base,
+					      mt->auxadc_phys_base, ctrl_id);
+
+	return 0;
+
+err_disable_clk_peri_therm:
+	clk_disable_unprepare(mt->clk_peri_therm);
+err_disable_clk_auxadc:
+	clk_disable_unprepare(mt->clk_auxadc);
+
+	return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(mtk_thermal_pm_ops,
+			 mtk_thermal_suspend, mtk_thermal_resume);
+
 static struct platform_driver mtk_thermal_driver = {
 	.probe = mtk_thermal_probe,
 	.remove = mtk_thermal_remove,
 	.driver = {
 		.name = "mtk-thermal",
+		.pm = &mtk_thermal_pm_ops,
 		.of_match_table = mtk_thermal_of_match,
 	},
 };
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2020-07-07  8:47 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-09  9:35 [RESEND PATCH] thermal: mediatek: add suspend/resume callback michael.kao
2019-10-13 17:50 ` Daniel Lezcano
2019-11-01  1:31   ` Michael Kao
2019-11-01  8:46     ` Daniel Lezcano
2019-12-19  9:24 [RESEND] " Michael Kao
2019-12-19  9:24 ` [RESEND][PATCH] " Michael Kao
2019-12-27  8:56   ` Michael Kao
2020-01-09 23:37   ` Daniel Lezcano
2020-04-08  9:05 [RESEND PATCH 0/1] " Michael Kao
2020-04-08  9:05 ` [RESEND PATCH] " Michael Kao
2020-05-14  8:46   ` Michael Kao
2020-07-07  8:47     ` Michael Kao
2020-05-22 19:08   ` Daniel Lezcano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).