/
0571-drivers-thermal-allwinner-add-h616-ths-support.patch
226 lines (215 loc) · 7.38 KB
/
0571-drivers-thermal-allwinner-add-h616-ths-support.patch
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
diff -Naur linux-5.12.9-old/drivers/cpufreq/sun50i-cpufreq-nvmem.c linux-5.12.9.new/drivers/cpufreq/sun50i-cpufreq-nvmem.c
--- linux-5.12.9-old/drivers/cpufreq/sun50i-cpufreq-nvmem.c 2021-06-03 09:09:52.000000000 +0200
+++ linux-5.12.9.new/drivers/cpufreq/sun50i-cpufreq-nvmem.c 2021-06-12 18:46:11.389983885 +0200
@@ -37,7 +37,6 @@
struct device *cpu_dev;
u32 *speedbin, efuse_value;
size_t len;
- int ret;
cpu_dev = get_cpu_device(0);
if (!cpu_dev)
@@ -47,9 +46,9 @@
if (!np)
return -ENOENT;
- ret = of_device_is_compatible(np,
- "allwinner,sun50i-h6-operating-points");
- if (!ret) {
+ if (of_device_is_compatible(np, "allwinner,sun50i-h6-operating-points")) {}
+ else if (of_device_is_compatible(np, "allwinner,sun50i-h616-operating-points")) {}
+ else {
of_node_put(np);
return -ENOENT;
}
@@ -165,6 +168,7 @@
static const struct of_device_id sun50i_cpufreq_match_list[] = {
{ .compatible = "allwinner,sun50i-h6" },
+ { .compatible = "allwinner,sun50i-h616" },
{}
};
MODULE_DEVICE_TABLE(of, sun50i_cpufreq_match_list);
diff -Naur linux-5.12.9-old/drivers/nvmem/sunxi_sid.c linux-5.12.9.new/drivers/nvmem/sunxi_sid.c
--- linux-5.12.9-old/drivers/nvmem/sunxi_sid.c 2021-06-03 09:09:52.000000000 +0200
+++ linux-5.12.9.new/drivers/nvmem/sunxi_sid.c 2021-06-09 22:42:11.389986676 +0200
@@ -194,6 +194,12 @@
.size = 0x200,
};
+static const struct sunxi_sid_cfg sun50i_h616_cfg = {
+ .value_offset = 0x200,
+ .size = 0x100,
+ .need_register_readout = true,
+};
+
static const struct of_device_id sunxi_sid_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-sid", .data = &sun4i_a10_cfg },
{ .compatible = "allwinner,sun7i-a20-sid", .data = &sun7i_a20_cfg },
@@ -202,6 +208,7 @@
{ .compatible = "allwinner,sun50i-a64-sid", .data = &sun50i_a64_cfg },
{ .compatible = "allwinner,sun50i-h5-sid", .data = &sun50i_a64_cfg },
{ .compatible = "allwinner,sun50i-h6-sid", .data = &sun50i_h6_cfg },
+ { .compatible = "allwinner,sun50i-h616-sid", .data = &sun50i_h616_cfg },
{/* sentinel */},
};
MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
diff -Naur linux-5.12.9-old/drivers/thermal/sun8i_thermal.c linux-5.12.9.new/drivers/thermal/sun8i_thermal.c
--- linux-5.12.9-old/drivers/thermal/sun8i_thermal.c 2021-06-03 09:09:52.000000000 +0200
+++ linux-5.12.9.new/drivers/thermal/sun8i_thermal.c 2021-06-12 15:48:06.637330025 +0200
@@ -6,6 +6,7 @@
* Based on the work of Icenowy Zheng <icenowy@aosc.io>
* Based on the work of Ondrej Jirman <megous@megous.com>
* Based on the work of Josef Gajdusek <atx@atx.name>
+ * H616 support added by Piotr Oniszczuk <piotr.oniszczuk@gmail.com>
*/
#include <linux/bitmap.h>
@@ -37,14 +38,15 @@
#define SUN8I_THS_TEMP_CALIB 0x74
#define SUN8I_THS_TEMP_DATA 0x80
+// H616 THS registers are the thesame like in H6 so we will reuse them for H616
#define SUN50I_THS_CTRL0 0x00
-#define SUN50I_H6_THS_ENABLE 0x04
+#define SUN50I_H6_THS_ENABLE 0x04
#define SUN50I_H6_THS_PC 0x08
#define SUN50I_H6_THS_DIC 0x10
#define SUN50I_H6_THS_DIS 0x20
#define SUN50I_H6_THS_MFC 0x30
-#define SUN50I_H6_THS_TEMP_CALIB 0xa0
-#define SUN50I_H6_THS_TEMP_DATA 0xc0
+#define SUN50I_H6_THS_TEMP_CALIB 0xa0
+#define SUN50I_H6_THS_TEMP_DATA 0xc0
#define SUN8I_THS_CTRL0_T_ACQ0(x) (GENMASK(15, 0) & (x))
#define SUN8I_THS_CTRL2_T_ACQ1(x) ((GENMASK(15, 0) & (x)) << 16)
@@ -94,9 +96,16 @@
static int sun8i_ths_calc_temp(struct ths_device *tmdev,
int id, int reg)
{
+ //printk("sensor:%d reg:%d offset:%d scale:%d\n", id, reg, tmdev->chip->offset, tmdev->chip->scale);
return tmdev->chip->offset - (reg * tmdev->chip->scale / 10);
}
+static int sun9i_ths_calc_temp(struct ths_device *tmdev,
+ int id, int reg)
+{
+ return tmdev->chip->offset + (reg * tmdev->chip->scale / 10);
+}
+
static int sun50i_h5_calc_temp(struct ths_device *tmdev,
int id, int reg)
{
@@ -278,6 +297,63 @@
return 0;
}
+static int sun50i_h616_ths_calibrate(struct ths_device *tmdev,
+ u16 *caldata, int callen)
+{
+ struct device *dev = tmdev->dev;
+ int i, ft_temp;
+
+ if (!caldata[0])
+ return -EINVAL;
+
+ /*
+ * h616 efuse THS calib. data layout:
+ *
+ * 0 11 16 27 32 43 48 57
+ * +----------+-----------+-----------+-----------+
+ * | temp | |sensor0| |sensor1| |sensor2| |
+ * +----------+-----------+-----------+-----------+
+ * ^ ^ ^
+ * | | |
+ * | | sensor3[11:8]
+ * | sensor3[7:4]
+ * sensor3[3:0]
+ *
+ * The calibration data on the H616 is the ambient temperature and
+ * sensor values that are filled during the factory test stage.
+ *
+ * The unit of stored FT temperature is 0.1 degreee celusis.
+ */
+ ft_temp = caldata[0] & FT_TEMP_MASK;
+
+ for (i = 0; i < tmdev->chip->sensor_num; i++) {
+ int delta, cdata, offset, reg;
+
+ if (i == 3)
+ reg = (caldata[1] >> 12)
+ | (caldata[2] >> 12 << 4)
+ | (caldata[3] >> 12 << 8);
+ else
+ reg = (int)caldata[i + 1] & TEMP_CALIB_MASK;
+
+ delta = (ft_temp * 100 - tmdev->chip->calc_temp(tmdev, i, reg)) / tmdev->chip->scale;
+ cdata = CALIBRATE_DEFAULT - delta;
+
+ if (cdata & ~TEMP_CALIB_MASK) {
+ dev_warn(dev, "sensor%d is not calibrated.\n", i);
+ continue;
+ }
+
+ offset = (i % 2) * 16;
+ regmap_update_bits(tmdev->regmap,
+ SUN50I_H6_THS_TEMP_CALIB + (i / 2 * 4),
+ 0xfff << offset,
+ cdata << offset);
+ }
+
+ return 0;
+}
+
static int sun8i_ths_calibrate(struct ths_device *tmdev)
{
struct nvmem_cell *calcell;
@@ -460,6 +536,30 @@
return 0;
}
+static int sun50i_h616_thermal_init(struct ths_device *tmdev)
+{
+ int val;
+
+ /*
+ * For sun50iw9p1:
+ * It is necessary that reg[0x03000000] bit[16] is 0.
+ */
+ regmap_write(tmdev->regmap, SUN50I_THS_CTRL0,
+ SUN8I_THS_CTRL0_T_ACQ0(47) | SUN8I_THS_CTRL2_T_ACQ1(479));
+ regmap_write(tmdev->regmap, SUN50I_H6_THS_MFC,
+ SUN50I_THS_FILTER_EN |
+ SUN50I_THS_FILTER_TYPE(1));
+ regmap_write(tmdev->regmap, SUN50I_H6_THS_PC,
+ SUN50I_H6_THS_PC_TEMP_PERIOD(365));
+ val = GENMASK(tmdev->chip->sensor_num - 1, 0);
+ regmap_write(tmdev->regmap, SUN50I_H6_THS_ENABLE, val);
+ /* thermal data interrupt enable */
+ val = GENMASK(tmdev->chip->sensor_num - 1, 0);
+ regmap_write(tmdev->regmap, SUN50I_H6_THS_DIC, val);
+
+ return 0;
+}
+
static int sun8i_ths_register(struct ths_device *tmdev)
{
int i;
@@ -628,6 +747,19 @@
.calc_temp = sun8i_ths_calc_temp,
};
+static const struct ths_thermal_chip sun50i_h616_ths = {
+ .sensor_num = 4,
+ .has_bus_clk_reset = true,
+ .ft_deviation = 8000,
+ .offset = -32550,
+ .scale = 806,
+ .temp_data_base = SUN50I_H6_THS_TEMP_DATA,
+ .calibrate = sun50i_h616_ths_calibrate,
+ .init = sun50i_h616_thermal_init,
+ .irq_ack = sun50i_h6_irq_ack,
+ .calc_temp = sun9i_ths_calc_temp,
+};
+
static const struct of_device_id of_ths_match[] = {
{ .compatible = "allwinner,sun8i-a83t-ths", .data = &sun8i_a83t_ths },
{ .compatible = "allwinner,sun8i-h3-ths", .data = &sun8i_h3_ths },
@@ -636,6 +768,7 @@
{ .compatible = "allwinner,sun50i-a100-ths", .data = &sun50i_a100_ths },
{ .compatible = "allwinner,sun50i-h5-ths", .data = &sun50i_h5_ths },
{ .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths },
+ { .compatible = "allwinner,sun50i-h616-ths", .data = &sun50i_h616_ths },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, of_ths_match);