1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
|
From 031573a8a1e73b0ac548812c10c3e426c2b4ce61 Mon Sep 17 00:00:00 2001
From: Yuantian Tang <andy.tang@nxp.com>
Date: Tue, 15 Oct 2019 20:08:58 +0800
Subject: [PATCH] thermal: qoriq: add thermal monitor unit version 2 support
Thermal Monitor Unit v2 is introduced on new Layscape SoC.
Compared to v1, TMUv2 has a little different register layout
and digital output is fairly linear.
Signed-off-by: Yuantian Tang <andy.tang@nxp.com>
Reviewed-by: Anson Huang <Anson.Huang@nxp.com>
---
drivers/thermal/qoriq_thermal.c | 118 ++++++++++++++++++++++++++++++++--------
1 file changed, 96 insertions(+), 22 deletions(-)
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -16,6 +16,15 @@
#define SITES_MAX 16
#define TMU_TEMP_PASSIVE_COOL_DELTA 10000
+#define TMR_DISABLE 0x0
+#define TMR_ME 0x80000000
+#define TMR_ALPF 0x0c000000
+#define TMR_ALPF_V2 0x03000000
+#define TMTMIR_DEFAULT 0x0000000f
+#define TIER_DISABLE 0x0
+#define TEUMR0_V2 0x51009c00
+#define TMU_VER1 0x1
+#define TMU_VER2 0x2
/*
* QorIQ TMU Registers
@@ -26,17 +35,12 @@ struct qoriq_tmu_site_regs {
u8 res0[0x8];
};
-struct qoriq_tmu_regs {
+struct qoriq_tmu_regs_v1 {
u32 tmr; /* Mode Register */
-#define TMR_DISABLE 0x0
-#define TMR_ME 0x80000000
-#define TMR_ALPF 0x0c000000
u32 tsr; /* Status Register */
u32 tmtmir; /* Temperature measurement interval Register */
-#define TMTMIR_DEFAULT 0x0000000f
u8 res0[0x14];
u32 tier; /* Interrupt Enable Register */
-#define TIER_DISABLE 0x0
u32 tidr; /* Interrupt Detect Register */
u32 tiscr; /* Interrupt Site Capture Register */
u32 ticscr; /* Interrupt Critical Site Capture Register */
@@ -56,12 +60,52 @@ struct qoriq_tmu_regs {
u32 ipbrr0; /* IP Block Revision Register 0 */
u32 ipbrr1; /* IP Block Revision Register 1 */
u8 res6[0x310];
- u32 ttr0cr; /* Temperature Range 0 Control Register */
- u32 ttr1cr; /* Temperature Range 1 Control Register */
- u32 ttr2cr; /* Temperature Range 2 Control Register */
- u32 ttr3cr; /* Temperature Range 3 Control Register */
+ u32 ttrcr[4]; /* Temperature Range Control Register */
};
+struct qoriq_tmu_regs_v2 {
+ u32 tmr; /* Mode Register */
+ u32 tsr; /* Status Register */
+ u32 tmsr; /* monitor site register */
+ u32 tmtmir; /* Temperature measurement interval Register */
+ u8 res0[0x10];
+ u32 tier; /* Interrupt Enable Register */
+ u32 tidr; /* Interrupt Detect Register */
+ u8 res1[0x8];
+ u32 tiiscr; /* interrupt immediate site capture register */
+ u32 tiascr; /* interrupt average site capture register */
+ u32 ticscr; /* Interrupt Critical Site Capture Register */
+ u32 res2;
+ u32 tmhtcr; /* monitor high temperature capture register */
+ u32 tmltcr; /* monitor low temperature capture register */
+ u32 tmrtrcr; /* monitor rising temperature rate capture register */
+ u32 tmftrcr; /* monitor falling temperature rate capture register */
+ u32 tmhtitr; /* High Temperature Immediate Threshold */
+ u32 tmhtatr; /* High Temperature Average Threshold */
+ u32 tmhtactr; /* High Temperature Average Crit Threshold */
+ u32 res3;
+ u32 tmltitr; /* monitor low temperature immediate threshold */
+ u32 tmltatr; /* monitor low temperature average threshold register */
+ u32 tmltactr; /* monitor low temperature average critical threshold */
+ u32 res4;
+ u32 tmrtrctr; /* monitor rising temperature rate critical threshold */
+ u32 tmftrctr; /* monitor falling temperature rate critical threshold*/
+ u8 res5[0x8];
+ u32 ttcfgr; /* Temperature Configuration Register */
+ u32 tscfgr; /* Sensor Configuration Register */
+ u8 res6[0x78];
+ struct qoriq_tmu_site_regs site[SITES_MAX];
+ u8 res7[0x9f8];
+ u32 ipbrr0; /* IP Block Revision Register 0 */
+ u32 ipbrr1; /* IP Block Revision Register 1 */
+ u8 res8[0x300];
+ u32 teumr0;
+ u32 teumr1;
+ u32 teumr2;
+ u32 res9;
+ u32 ttrcr[4]; /* Temperature Range Control Register */
+ };
+
struct qoriq_tmu_data;
/*
@@ -77,7 +121,9 @@ struct qoriq_sensor {
};
struct qoriq_tmu_data {
- struct qoriq_tmu_regs __iomem *regs;
+ int ver;
+ struct qoriq_tmu_regs_v1 __iomem *regs;
+ struct qoriq_tmu_regs_v2 __iomem *regs_v2;
struct clk *clk;
bool little_endian;
struct qoriq_sensor *sensor[SITES_MAX];
@@ -210,12 +256,23 @@ static int qoriq_tmu_register_tmu_zone(s
qdata->sensor[id]->temp_critical = trip[1].temperature;
}
- sites |= 0x1 << (15 - id);
+ if (qdata->ver == TMU_VER1)
+ sites |= 0x1 << (15 - id);
+ else
+ sites |= 0x1 << id;
}
/* Enable monitoring */
- if (sites != 0)
- tmu_write(qdata, sites | TMR_ME | TMR_ALPF, &qdata->regs->tmr);
+ if (sites != 0) {
+ if (qdata->ver == TMU_VER1) {
+ tmu_write(qdata, sites | TMR_ME | TMR_ALPF,
+ &qdata->regs->tmr);
+ } else {
+ tmu_write(qdata, sites, &qdata->regs_v2->tmsr);
+ tmu_write(qdata, TMR_ME | TMR_ALPF_V2,
+ &qdata->regs_v2->tmr);
+ }
+ }
return 0;
}
@@ -228,16 +285,21 @@ static int qoriq_tmu_calibration(struct
struct device_node *np = pdev->dev.of_node;
struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
- if (of_property_read_u32_array(np, "fsl,tmu-range", range, 4)) {
- dev_err(&pdev->dev, "missing calibration range.\n");
- return -ENODEV;
+ len = of_property_count_u32_elems(np, "fsl,tmu-range");
+ if (len < 0 || len > 4) {
+ dev_err(&pdev->dev, "invalid range data.\n");
+ return len;
+ }
+
+ val = of_property_read_u32_array(np, "fsl,tmu-range", range, len);
+ if (val != 0) {
+ dev_err(&pdev->dev, "failed to read range data.\n");
+ return val;
}
/* Init temperature range registers */
- tmu_write(data, range[0], &data->regs->ttr0cr);
- tmu_write(data, range[1], &data->regs->ttr1cr);
- tmu_write(data, range[2], &data->regs->ttr2cr);
- tmu_write(data, range[3], &data->regs->ttr3cr);
+ for (i = 0; i < len; i++)
+ tmu_write(data, range[i], &data->regs->ttrcr[i]);
calibration = of_get_property(np, "fsl,tmu-calibration", &len);
if (calibration == NULL || len % 8) {
@@ -261,7 +323,12 @@ static void qoriq_tmu_init_device(struct
tmu_write(data, TIER_DISABLE, &data->regs->tier);
/* Set update_interval */
- tmu_write(data, TMTMIR_DEFAULT, &data->regs->tmtmir);
+ if (data->ver == TMU_VER1) {
+ tmu_write(data, TMTMIR_DEFAULT, &data->regs->tmtmir);
+ } else {
+ tmu_write(data, TMTMIR_DEFAULT, &data->regs_v2->tmtmir);
+ tmu_write(data, TEUMR0_V2, &data->regs_v2->teumr0);
+ }
/* Disable monitoring */
tmu_write(data, TMR_DISABLE, &data->regs->tmr);
@@ -270,6 +337,7 @@ static void qoriq_tmu_init_device(struct
static int qoriq_tmu_probe(struct platform_device *pdev)
{
int ret;
+ u32 ver;
struct qoriq_tmu_data *data;
struct device_node *np = pdev->dev.of_node;
@@ -298,6 +366,12 @@ static int qoriq_tmu_probe(struct platfo
return ret;
}
+ /* version register offset at: 0xbf8 on both v1 and v2 */
+ ver = tmu_read(data, &data->regs->ipbrr0);
+ data->ver = (ver >> 8) & 0xff;
+ if (data->ver == TMU_VER2)
+ data->regs_v2 = (void __iomem *)data->regs;
+
qoriq_tmu_init_device(data); /* TMU initialization */
ret = qoriq_tmu_calibration(pdev); /* TMU calibration */
|