Skip to content

Commit ad865f8

Browse files
committed
cpufreq: Add Apple A7-A11, T2 SoC support
- A7-A8X uses 3 bits only for pstate, and PS1 mask is GENMASK(24, 22) - Add tunables, mainly the voltage control register in PMGR (iBoot boots us with voltage changes seemingly disabled, with obvious disastrous outcome trying to switch to high P-states) - Skip writes to offset 0x4xxxx from cluster->base for A7-A11, T2. The range starting from 0x40000 from cluster->base does not exist in ADT /arm-io/pmgr, so it probably does not exist for those older chips. This includes the 0x440f8 and ppt-thrtl writes. Signed-off-by: Nick Chan <towinchenmi@gmail.com>
1 parent 072089d commit ad865f8

File tree

1 file changed

+139
-5
lines changed

1 file changed

+139
-5
lines changed

src/cpufreq.c

Lines changed: 139 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,13 @@
1919
#define CLUSTER_PSTATE_DESIRED2 GENMASK(15, 12)
2020
#define CLUSTER_PSTATE_APSC_BUSY BIT(7)
2121
#define CLUSTER_PSTATE_DESIRED1 GENMASK(4, 0)
22+
#define CLUSTER_PSTATE_DESIRED1_S5L8960X GENMASK(24, 22)
2223

23-
#define CLUSTER_SWITCH_TIMEOUT 100
24+
#define PMGR_VOLTAGE_CTL_OFF_S5L8960X 0x20c00
25+
#define PMGR_VOLTAGE_CTL_OFF_T7000 0x23000
26+
#define PMGR_VOLTAGE_CTL_OFF_S8000 0xa0000
27+
28+
#define CLUSTER_SWITCH_TIMEOUT 400
2429

2530
struct cluster_t {
2631
const char *name;
@@ -41,7 +46,10 @@ struct feat_t {
4146

4247
static u32 pstate_reg_to_pstate(u64 val) {
4348
switch (chip_id) {
44-
case T8103...T8122:
49+
case S5L8960X:
50+
case T7000...T7001:
51+
return FIELD_GET(CLUSTER_PSTATE_DESIRED1_S5L8960X, val);
52+
case S8000...T8122:
4553
case T6000...T6034:
4654
default:
4755
return FIELD_GET(CLUSTER_PSTATE_DESIRED1, val);
@@ -54,7 +62,12 @@ static int set_pstate(const struct cluster_t *cluster, uint32_t pstate)
5462

5563
if (pstate_reg_to_pstate(val) != pstate) {
5664
switch (chip_id) {
57-
case T8103:
65+
case S5L8960X:
66+
case T7000...T7001:
67+
val &= ~CLUSTER_PSTATE_DESIRED1_S5L8960X;
68+
val |= CLUSTER_PSTATE_SET | FIELD_PREP(CLUSTER_PSTATE_DESIRED1_S5L8960X, pstate);
69+
break;
70+
case S8000...T8103:
5871
case T6000...T6002:
5972
val &= ~CLUSTER_PSTATE_DESIRED2;
6073
val |= CLUSTER_PSTATE_SET | FIELD_PREP(CLUSTER_PSTATE_DESIRED2, pstate);
@@ -104,9 +117,36 @@ int cpufreq_init_cluster(const struct cluster_t *cluster, const struct feat_t *f
104117
}
105118
}
106119

120+
int pmgr_path[8];
121+
u64 pmgr_reg;
122+
123+
if (adt_path_offset_trace(adt, "/arm-io/pmgr", pmgr_path) < 0) {
124+
printf("Error getting /arm-io/pmgr node\n");
125+
return -1;
126+
}
127+
128+
if (adt_get_reg(adt, pmgr_path, "reg", 0, &pmgr_reg, NULL) < 0) {
129+
printf("Error getting /arm-io/pmgr regs\n");
130+
return -1;
131+
}
132+
107133
switch (chip_id) {
108-
case T8103...T8122:
109-
case T6000...T6034:
134+
case S5L8960X:
135+
write32(pmgr_reg + PMGR_VOLTAGE_CTL_OFF_S5L8960X, 1);
136+
break;
137+
case T7000...T7001:
138+
write32(pmgr_reg + PMGR_VOLTAGE_CTL_OFF_T7000, 1);
139+
break;
140+
case S8000...T8015:
141+
/*
142+
* On T8015 this will result in the register being written
143+
* two times (for two clusters). However, this is fine.
144+
*/
145+
write32(pmgr_reg + PMGR_VOLTAGE_CTL_OFF_S8000, 1);
146+
break;
147+
break;
148+
case T8103...T8122:
149+
case T6000...T6034:
110150
default:
111151
/* Unknown */
112152
write64(cluster->base + 0x440f8, 1);
@@ -171,6 +211,44 @@ void cpufreq_fixup_cluster(const struct cluster_t *cluster)
171211
}
172212
}
173213

214+
static const struct cluster_t s5l8960x_clusters[] = {
215+
{"CPU", 0x202200000, false, 2, 6},
216+
{},
217+
};
218+
219+
static const struct cluster_t t7000_clusters[] = {
220+
{"CPU", 0x202200000, false, 2, 5},
221+
{},
222+
};
223+
224+
static const struct cluster_t t7001_clusters[] = {
225+
{"CPU", 0x202200000, false, 2, 7},
226+
{},
227+
};
228+
229+
static const struct cluster_t s8000_clusters[] = {
230+
{"CPU", 0x202200000, false, 2, 7},
231+
{},
232+
};
233+
234+
static const struct cluster_t t8010_clusters[] = {
235+
/* Fused cluster, kernel expects E-core entry */
236+
{"CPU", 0x202f00000, false, 2, 4},
237+
{},
238+
};
239+
240+
static const struct cluster_t t8012_clusters[] = {
241+
/* Fused cluster, kernel expects P-core entry */
242+
{"CPU", 0x202f00000, false, 6, 10},
243+
{},
244+
};
245+
246+
static const struct cluster_t t8015_clusters[] = {
247+
{"ECPU", 0x208e00000, false, 2, 6},
248+
{"PCPU", 0x208e80000, true, 2, 7},
249+
{},
250+
};
251+
174252
static const struct cluster_t t8103_clusters[] = {
175253
{"ECPU", 0x210e00000, false, 1, 5},
176254
{"PCPU", 0x211e00000, true, 1, 7},
@@ -226,6 +304,23 @@ static const struct cluster_t t6031_clusters[] = {
226304
const struct cluster_t *cpufreq_get_clusters(void)
227305
{
228306
switch (chip_id) {
307+
case S5L8960X:
308+
return s5l8960x_clusters;
309+
case T7000:
310+
return t7000_clusters;
311+
case T7001:
312+
return t7001_clusters;
313+
case S8000:
314+
case S8001:
315+
case S8003:
316+
return s8000_clusters;
317+
case T8010:
318+
case T8011:
319+
return t8010_clusters;
320+
case T8012:
321+
return t8012_clusters;
322+
case T8015:
323+
return t8015_clusters;
229324
case T8103:
230325
return t8103_clusters;
231326
case T6000:
@@ -248,6 +343,27 @@ const struct cluster_t *cpufreq_get_clusters(void)
248343
}
249344
}
250345

346+
static const struct feat_t s5l8960x_features[] = {
347+
{},
348+
};
349+
350+
static const struct feat_t s8000_features[] = {
351+
{"cpu-apsc", CLUSTER_PSTATE, CLUSTER_PSTATE_M1_APSC_DIS, 0, CLUSTER_PSTATE_APSC_BUSY, false},
352+
{},
353+
};
354+
355+
static const struct feat_t t8010_features[] = {
356+
{"cpu-apsc", CLUSTER_PSTATE, CLUSTER_PSTATE_M1_APSC_DIS, 0, CLUSTER_PSTATE_APSC_BUSY, false},
357+
{},
358+
};
359+
360+
static const struct feat_t t8015_features[] = {
361+
{"cpu-apsc", CLUSTER_PSTATE, CLUSTER_PSTATE_M1_APSC_DIS, 0, CLUSTER_PSTATE_APSC_BUSY, false},
362+
{"cpu-fixed-freq-pll-relock", CLUSTER_PSTATE, 0, CLUSTER_PSTATE_FIXED_FREQ_PLL_RECLOCK, 0,
363+
false},
364+
{},
365+
};
366+
251367
static const struct feat_t t8103_features[] = {
252368
{"cpu-apsc", CLUSTER_PSTATE, CLUSTER_PSTATE_M1_APSC_DIS, 0, CLUSTER_PSTATE_APSC_BUSY, false},
253369
{"ppt-thrtl", 0x48400, 0, BIT(63), 0, false},
@@ -294,6 +410,20 @@ static const struct feat_t t6031_features[] = {
294410
const struct feat_t *cpufreq_get_features(void)
295411
{
296412
switch (chip_id) {
413+
case S5L8960X:
414+
case T7000:
415+
case T7001:
416+
return s5l8960x_features;
417+
case S8000:
418+
case S8001:
419+
case S8003:
420+
return s8000_features;
421+
case T8010:
422+
case T8011:
423+
case T8012:
424+
return t8010_features;
425+
case T8015:
426+
return t8015_features;
297427
case T8103:
298428
case T6000 ... T6002:
299429
return t8103_features;
@@ -321,6 +451,10 @@ int cpufreq_init(void)
321451
if (!cluster || !features)
322452
return -1;
323453

454+
/* Without this, CLUSTER_PSTATE_BUSY gets stuck */
455+
if (chip_id == T8012 || chip_id == T8015)
456+
pmgr_power_on(0, "SPMI");
457+
324458
bool err = false;
325459
while (cluster->base) {
326460
err |= cpufreq_init_cluster(cluster++, features);

0 commit comments

Comments
 (0)