2023-04-20 09:24:33

by Wolfram Sang

[permalink] [raw]
Subject: [PATCH RFT v2 0/3] drivers/thermal/rcar_gen3_thermal: add Gen4 fuse support

R-Car Gen4 has the fuse registers at different locations and with
different names, but with the same purpose. So, first refactor IP core
differences into a 'info' struct, then add the fuse_read callback to it.

Changes since RFT v1:
* Patches are rebased on top of thermal-next as of today.
* Added tags from Niklas (thanks!)

They have been tested on R-Car H3 ES2.0 and M3-N against regressions.
Actual testing of the new fuses on Gen4 still needs to be done because I
don't have access to such HW.

@Shimoda-san: maybe the BSP team or Test team can test these patches?
A branch for testing can be found here:
git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git renesas/for-thermal

Looking forward to other review comments, too, of course.

Happy hacking,

Wolfram

Wolfram Sang (3):
drivers/thermal/rcar_gen3_thermal: introduce 'info' structure
drivers/thermal/rcar_gen3_thermal: refactor reading fuses into
seprarate function
drivers/thermal/rcar_gen3_thermal: add reading fuses for Gen4

drivers/thermal/rcar_gen3_thermal.c | 141 ++++++++++++++++++++--------
1 file changed, 102 insertions(+), 39 deletions(-)

--
2.30.2


2023-04-20 09:24:49

by Wolfram Sang

[permalink] [raw]
Subject: [PATCH RFT v2 2/3] drivers/thermal/rcar_gen3_thermal: refactor reading fuses into seprarate function

Gen4 will be very different, so refactor Gen3 access into separate call
first.

Signed-off-by: Wolfram Sang <[email protected]>
Reviewed-by: Niklas Söderlund <[email protected]>
---
drivers/thermal/rcar_gen3_thermal.c | 60 +++++++++++++++++------------
1 file changed, 36 insertions(+), 24 deletions(-)

diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c
index e9b0aa0a2016..39b382ee08c8 100644
--- a/drivers/thermal/rcar_gen3_thermal.c
+++ b/drivers/thermal/rcar_gen3_thermal.c
@@ -66,8 +66,11 @@ struct equation_coefs {
int b2;
};

+struct rcar_gen3_thermal_priv;
+
struct rcar_thermal_info {
int ths_tj_1;
+ void (*read_fuses)(struct rcar_gen3_thermal_priv *priv);
};

struct rcar_gen3_thermal_tsc {
@@ -241,6 +244,34 @@ static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data)
return IRQ_HANDLED;
}

+static void rcar_gen3_thermal_read_fuses_gen3(struct rcar_gen3_thermal_priv *priv)
+{
+ unsigned int i;
+
+ /*
+ * Set the pseudo calibration points with fused values.
+ * PTAT is shared between all TSCs but only fused for the first
+ * TSC while THCODEs are fused for each TSC.
+ */
+ priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT1) &
+ GEN3_FUSE_MASK;
+ priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT2) &
+ GEN3_FUSE_MASK;
+ priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT3) &
+ GEN3_FUSE_MASK;
+
+ for (i = 0; i < priv->num_tscs; i++) {
+ struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
+
+ tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE1) &
+ GEN3_FUSE_MASK;
+ tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE2) &
+ GEN3_FUSE_MASK;
+ tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE3) &
+ GEN3_FUSE_MASK;
+ }
+}
+
static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
{
unsigned int i;
@@ -248,7 +279,8 @@ static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)

/* If fuses are not set, fallback to pseudo values. */
thscp = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_THSCP);
- if ((thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) {
+ if (!priv->info->read_fuses ||
+ (thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) {
/* Default THCODE values in case FUSEs are not set. */
static const int thcodes[TSC_MAX_NUM][3] = {
{ 3397, 2800, 2221 },
@@ -273,29 +305,7 @@ static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
return false;
}

- /*
- * Set the pseudo calibration points with fused values.
- * PTAT is shared between all TSCs but only fused for the first
- * TSC while THCODEs are fused for each TSC.
- */
- priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT1) &
- GEN3_FUSE_MASK;
- priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT2) &
- GEN3_FUSE_MASK;
- priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT3) &
- GEN3_FUSE_MASK;
-
- for (i = 0; i < priv->num_tscs; i++) {
- struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
-
- tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE1) &
- GEN3_FUSE_MASK;
- tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE2) &
- GEN3_FUSE_MASK;
- tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE3) &
- GEN3_FUSE_MASK;
- }
-
+ priv->info->read_fuses(priv);
return true;
}

@@ -325,10 +335,12 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv *priv,

static const struct rcar_thermal_info rcar_m3w_thermal_info = {
.ths_tj_1 = 116,
+ .read_fuses = rcar_gen3_thermal_read_fuses_gen3,
};

static const struct rcar_thermal_info rcar_gen3_thermal_info = {
.ths_tj_1 = 126,
+ .read_fuses = rcar_gen3_thermal_read_fuses_gen3,
};

static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
--
2.30.2

2023-04-20 09:24:50

by Wolfram Sang

[permalink] [raw]
Subject: [PATCH RFT v2 1/3] drivers/thermal/rcar_gen3_thermal: introduce 'info' structure

More items to describe the TSCs are needed soon, so encapsulate the
current 'ths_tj_1' item into a struct.

Signed-off-by: Wolfram Sang <[email protected]>
Reviewed-by: Niklas Söderlund <[email protected]>
---
drivers/thermal/rcar_gen3_thermal.c | 41 ++++++++++++++++++-----------
1 file changed, 26 insertions(+), 15 deletions(-)

diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c
index 42a4724d3920..e9b0aa0a2016 100644
--- a/drivers/thermal/rcar_gen3_thermal.c
+++ b/drivers/thermal/rcar_gen3_thermal.c
@@ -66,6 +66,10 @@ struct equation_coefs {
int b2;
};

+struct rcar_thermal_info {
+ int ths_tj_1;
+};
+
struct rcar_gen3_thermal_tsc {
void __iomem *base;
struct thermal_zone_device *zone;
@@ -79,6 +83,7 @@ struct rcar_gen3_thermal_priv {
struct thermal_zone_device_ops ops;
unsigned int num_tscs;
int ptat[3];
+ const struct rcar_thermal_info *info;
};

static inline u32 rcar_gen3_thermal_read(struct rcar_gen3_thermal_tsc *tsc,
@@ -318,52 +323,58 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv *priv,
usleep_range(1000, 2000);
}

-static const int rcar_gen3_ths_tj_1 = 126;
-static const int rcar_gen3_ths_tj_1_m3_w = 116;
+static const struct rcar_thermal_info rcar_m3w_thermal_info = {
+ .ths_tj_1 = 116,
+};
+
+static const struct rcar_thermal_info rcar_gen3_thermal_info = {
+ .ths_tj_1 = 126,
+};
+
static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
{
.compatible = "renesas,r8a774a1-thermal",
- .data = &rcar_gen3_ths_tj_1_m3_w,
+ .data = &rcar_m3w_thermal_info,
},
{
.compatible = "renesas,r8a774b1-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a774e1-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a7795-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a7796-thermal",
- .data = &rcar_gen3_ths_tj_1_m3_w,
+ .data = &rcar_m3w_thermal_info,
},
{
.compatible = "renesas,r8a77961-thermal",
- .data = &rcar_gen3_ths_tj_1_m3_w,
+ .data = &rcar_m3w_thermal_info,
},
{
.compatible = "renesas,r8a77965-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a77980-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a779a0-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a779f0-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{
.compatible = "renesas,r8a779g0-thermal",
- .data = &rcar_gen3_ths_tj_1,
+ .data = &rcar_gen3_thermal_info,
},
{},
};
@@ -418,7 +429,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
{
struct rcar_gen3_thermal_priv *priv;
struct device *dev = &pdev->dev;
- const int *ths_tj_1 = of_device_get_match_data(dev);
struct resource *res;
struct thermal_zone_device *zone;
unsigned int i;
@@ -430,6 +440,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)

priv->ops = rcar_gen3_tz_of_ops;

+ priv->info = of_device_get_match_data(dev);
platform_set_drvdata(pdev, priv);

if (rcar_gen3_thermal_request_irqs(priv, pdev))
@@ -469,7 +480,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];

rcar_gen3_thermal_init(priv, tsc);
- rcar_gen3_thermal_calc_coefs(priv, tsc, *ths_tj_1);
+ rcar_gen3_thermal_calc_coefs(priv, tsc, priv->info->ths_tj_1);

zone = devm_thermal_of_zone_register(dev, i, tsc, &priv->ops);
if (IS_ERR(zone)) {
--
2.30.2

2023-04-20 09:25:08

by Wolfram Sang

[permalink] [raw]
Subject: [PATCH RFT v2 3/3] drivers/thermal/rcar_gen3_thermal: add reading fuses for Gen4

The registers are differently named and at different offsets, but their
functionality is the same as for Gen3.

Signed-off-by: Wolfram Sang <[email protected]>
Reviewed-by: Niklas Söderlund <[email protected]>
---
drivers/thermal/rcar_gen3_thermal.c | 44 +++++++++++++++++++++++++++--
1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c
index 39b382ee08c8..e01e27903e44 100644
--- a/drivers/thermal/rcar_gen3_thermal.c
+++ b/drivers/thermal/rcar_gen3_thermal.c
@@ -35,6 +35,12 @@
#define REG_GEN3_PTAT2 0x60
#define REG_GEN3_PTAT3 0x64
#define REG_GEN3_THSCP 0x68
+#define REG_GEN4_THSFMON00 0x180
+#define REG_GEN4_THSFMON01 0x184
+#define REG_GEN4_THSFMON02 0x188
+#define REG_GEN4_THSFMON15 0x1BC
+#define REG_GEN4_THSFMON16 0x1C0
+#define REG_GEN4_THSFMON17 0x1C4

/* IRQ{STR,MSK,EN} bits */
#define IRQ_TEMP1 BIT(0)
@@ -55,6 +61,7 @@

#define MCELSIUS(temp) ((temp) * 1000)
#define GEN3_FUSE_MASK 0xFFF
+#define GEN4_FUSE_MASK 0xFFF

#define TSC_MAX_NUM 5

@@ -272,6 +279,34 @@ static void rcar_gen3_thermal_read_fuses_gen3(struct rcar_gen3_thermal_priv *pri
}
}

+static void rcar_gen3_thermal_read_fuses_gen4(struct rcar_gen3_thermal_priv *priv)
+{
+ unsigned int i;
+
+ /*
+ * Set the pseudo calibration points with fused values.
+ * PTAT is shared between all TSCs but only fused for the first
+ * TSC while THCODEs are fused for each TSC.
+ */
+ priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON01) &
+ GEN4_FUSE_MASK;
+ priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON02) &
+ GEN4_FUSE_MASK;
+ priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON00) &
+ GEN4_FUSE_MASK;
+
+ for (i = 0; i < priv->num_tscs; i++) {
+ struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
+
+ tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON16) &
+ GEN4_FUSE_MASK;
+ tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON17) &
+ GEN4_FUSE_MASK;
+ tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON15) &
+ GEN4_FUSE_MASK;
+ }
+}
+
static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
{
unsigned int i;
@@ -343,6 +378,11 @@ static const struct rcar_thermal_info rcar_gen3_thermal_info = {
.read_fuses = rcar_gen3_thermal_read_fuses_gen3,
};

+static const struct rcar_thermal_info rcar_gen4_thermal_info = {
+ .ths_tj_1 = 126,
+ .read_fuses = rcar_gen3_thermal_read_fuses_gen4,
+};
+
static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
{
.compatible = "renesas,r8a774a1-thermal",
@@ -382,11 +422,11 @@ static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
},
{
.compatible = "renesas,r8a779f0-thermal",
- .data = &rcar_gen3_thermal_info,
+ .data = &rcar_gen4_thermal_info,
},
{
.compatible = "renesas,r8a779g0-thermal",
- .data = &rcar_gen3_thermal_info,
+ .data = &rcar_gen4_thermal_info,
},
{},
};
--
2.30.2

2023-04-21 08:19:05

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH RFT v2 3/3] drivers/thermal/rcar_gen3_thermal: add reading fuses for Gen4

Hello Wolfram-san,

> From: Wolfram Sang, Sent: Thursday, April 20, 2023 6:21 PM
>
> The registers are differently named and at different offsets, but their
> functionality is the same as for Gen3.
>
> Signed-off-by: Wolfram Sang <[email protected]>
> Reviewed-by: Niklas Söderlund <[email protected]>

Thank you for the patch!

> ---
> drivers/thermal/rcar_gen3_thermal.c | 44 +++++++++++++++++++++++++++--
> 1 file changed, 42 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c
> index 39b382ee08c8..e01e27903e44 100644
> --- a/drivers/thermal/rcar_gen3_thermal.c
> +++ b/drivers/thermal/rcar_gen3_thermal.c
> @@ -35,6 +35,12 @@
> #define REG_GEN3_PTAT2 0x60
> #define REG_GEN3_PTAT3 0x64
> #define REG_GEN3_THSCP 0x68
> +#define REG_GEN4_THSFMON00 0x180
> +#define REG_GEN4_THSFMON01 0x184
> +#define REG_GEN4_THSFMON02 0x188
> +#define REG_GEN4_THSFMON15 0x1BC
> +#define REG_GEN4_THSFMON16 0x1C0
> +#define REG_GEN4_THSFMON17 0x1C4
>
> /* IRQ{STR,MSK,EN} bits */
> #define IRQ_TEMP1 BIT(0)
> @@ -55,6 +61,7 @@
>
> #define MCELSIUS(temp) ((temp) * 1000)
> #define GEN3_FUSE_MASK 0xFFF
> +#define GEN4_FUSE_MASK 0xFFF
>
> #define TSC_MAX_NUM 5
>
> @@ -272,6 +279,34 @@ static void rcar_gen3_thermal_read_fuses_gen3(struct rcar_gen3_thermal_priv *pri
> }
> }
>
> +static void rcar_gen3_thermal_read_fuses_gen4(struct rcar_gen3_thermal_priv *priv)
> +{
> + unsigned int i;
> +
> + /*
> + * Set the pseudo calibration points with fused values.
> + * PTAT is shared between all TSCs but only fused for the first
> + * TSC while THCODEs are fused for each TSC.
> + */
> + priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON01) &
> + GEN4_FUSE_MASK;

s/REG_GEN4_THSFMON01/REG_GEN4_THSFMON16/

According to the table in 13.3.3.4 of R-Car {S4,V4H} Hardware manuals:

PTAT1 PTAT_PF_U_SR1 bits (of THSFMON16 register)
PTAT2 PTAT_PF_R_SR1 bits (of THSFMON17 register)
PTAT3 PTAT_PF_L_SR1 bits (of THSFMON15 register)
THCODE1 THCODE_U_SR1 bits (of THSFMON01 register)
THCODE2 THCODE_R_SR1 bits (of THSFMON02 register)
THCODE3 THCODE_L_SR1 bits (of THSFMON00 register)

Otherwise, calculated the temperature value was incorrect.

> + priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON02) &
> + GEN4_FUSE_MASK;

s/REG_GEN4_THSFMON02/THSFMON17/

> + priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON00) &
> + GEN4_FUSE_MASK;

s/REG_GEN4_THSFMON00/THSFMON15/

> +
> + for (i = 0; i < priv->num_tscs; i++) {
> + struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
> +
> + tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON16) &
> + GEN4_FUSE_MASK;

s/REG_GEN4_THSFMON16/THSFMON01/

> + tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON17) &
> + GEN4_FUSE_MASK;

s/REG_GEN4_THSFMON17/THSFMON02/

> + tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON15) &
> + GEN4_FUSE_MASK;

s/REG_GEN4_THSFMON15/THSFMON00/

Best regards,
Yoshihiro Shimoda

> + }
> +}
> +
> static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv)
> {
> unsigned int i;
> @@ -343,6 +378,11 @@ static const struct rcar_thermal_info rcar_gen3_thermal_info = {
> .read_fuses = rcar_gen3_thermal_read_fuses_gen3,
> };
>
> +static const struct rcar_thermal_info rcar_gen4_thermal_info = {
> + .ths_tj_1 = 126,
> + .read_fuses = rcar_gen3_thermal_read_fuses_gen4,
> +};
> +
> static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
> {
> .compatible = "renesas,r8a774a1-thermal",
> @@ -382,11 +422,11 @@ static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
> },
> {
> .compatible = "renesas,r8a779f0-thermal",
> - .data = &rcar_gen3_thermal_info,
> + .data = &rcar_gen4_thermal_info,
> },
> {
> .compatible = "renesas,r8a779g0-thermal",
> - .data = &rcar_gen3_thermal_info,
> + .data = &rcar_gen4_thermal_info,
> },
> {},
> };
> --
> 2.30.2

2023-05-11 19:23:47

by Wolfram Sang

[permalink] [raw]
Subject: Re: [PATCH RFT v2 3/3] drivers/thermal/rcar_gen3_thermal: add reading fuses for Gen4


> > + priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON01) &
> > + GEN4_FUSE_MASK;
>
> s/REG_GEN4_THSFMON01/REG_GEN4_THSFMON16/
>
> According to the table in 13.3.3.4 of R-Car {S4,V4H} Hardware manuals:
>
> PTAT1 PTAT_PF_U_SR1 bits (of THSFMON16 register)
> PTAT2 PTAT_PF_R_SR1 bits (of THSFMON17 register)
> PTAT3 PTAT_PF_L_SR1 bits (of THSFMON15 register)
> THCODE1 THCODE_U_SR1 bits (of THSFMON01 register)
> THCODE2 THCODE_R_SR1 bits (of THSFMON02 register)
> THCODE3 THCODE_L_SR1 bits (of THSFMON00 register)

Oops, you are right, I mixed the two blocks :/ I'll send a fixed version
right away!


Attachments:
(No filename) (645.00 B)
signature.asc (849.00 B)
Download all attachments