Skip to content

Commit c72f0ae

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 7d6119d commit c72f0ae

File tree

1 file changed

+158
-2
lines changed

1 file changed

+158
-2
lines changed

src/cpufreq.c

Lines changed: 158 additions & 2 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;
@@ -42,6 +47,17 @@ struct feat_t {
4247
static u32 pstate_reg_to_pstate(u64 val)
4348
{
4449
switch (chip_id) {
50+
case S5L8960X:
51+
case T7000:
52+
case T7001:
53+
return FIELD_GET(CLUSTER_PSTATE_DESIRED1_S5L8960X, val);
54+
case S8000:
55+
case S8001:
56+
case S8003:
57+
case T8010:
58+
case T8011:
59+
case T8012:
60+
case T8015:
4561
case T8103:
4662
case T6000:
4763
case T6001:
@@ -64,6 +80,19 @@ static int set_pstate(const struct cluster_t *cluster, uint32_t pstate)
6480

6581
if (pstate_reg_to_pstate(val) != pstate) {
6682
switch (chip_id) {
83+
case S5L8960X:
84+
case T7000:
85+
case T7001:
86+
val &= ~CLUSTER_PSTATE_DESIRED1_S5L8960X;
87+
val |= CLUSTER_PSTATE_SET | FIELD_PREP(CLUSTER_PSTATE_DESIRED1_S5L8960X, pstate);
88+
break;
89+
case S8000:
90+
case S8001:
91+
case S8003:
92+
case T8010:
93+
case T8011:
94+
case T8012:
95+
case T8015:
6796
case T8103:
6897
case T6000:
6998
case T6001:
@@ -121,12 +150,45 @@ int cpufreq_init_cluster(const struct cluster_t *cluster, const struct feat_t *f
121150
}
122151
}
123152

153+
int pmgr_path[8];
154+
u64 pmgr_reg;
155+
156+
if (adt_path_offset_trace(adt, "/arm-io/pmgr", pmgr_path) < 0) {
157+
printf("Error getting /arm-io/pmgr node\n");
158+
return -1;
159+
}
160+
161+
if (adt_get_reg(adt, pmgr_path, "reg", 0, &pmgr_reg, NULL) < 0) {
162+
printf("Error getting /arm-io/pmgr regs\n");
163+
return -1;
164+
}
165+
124166
switch (chip_id) {
167+
case S5L8960X:
168+
write32(pmgr_reg + PMGR_VOLTAGE_CTL_OFF_S5L8960X, 1);
169+
break;
170+
case T7000:
171+
case T7001:
172+
write32(pmgr_reg + PMGR_VOLTAGE_CTL_OFF_T7000, 1);
173+
break;
174+
case S8000:
175+
case S8001:
176+
case S8003:
177+
case T8010:
178+
case T8011:
179+
case T8012:
180+
case T8015:
181+
/*
182+
* On T8015 this will result in the register being written
183+
* two times (for two clusters). However, this is fine.
184+
*/
185+
write32(pmgr_reg + PMGR_VOLTAGE_CTL_OFF_S8000, 1);
186+
break;
125187
case T8103:
188+
case T8112:
126189
case T6000:
127190
case T6001:
128191
case T6002:
129-
case T8112:
130192
case T6020:
131193
case T6021:
132194
case T6022:
@@ -201,6 +263,44 @@ void cpufreq_fixup_cluster(const struct cluster_t *cluster)
201263
}
202264
}
203265

266+
static const struct cluster_t s5l8960x_clusters[] = {
267+
{"CPU", 0x202200000, false, 2, 6},
268+
{},
269+
};
270+
271+
static const struct cluster_t t7000_clusters[] = {
272+
{"CPU", 0x202200000, false, 2, 5},
273+
{},
274+
};
275+
276+
static const struct cluster_t t7001_clusters[] = {
277+
{"CPU", 0x202200000, false, 2, 7},
278+
{},
279+
};
280+
281+
static const struct cluster_t s8000_clusters[] = {
282+
{"CPU", 0x202200000, false, 2, 7},
283+
{},
284+
};
285+
286+
static const struct cluster_t t8010_clusters[] = {
287+
/* Fused cluster, kernel expects E-core entry */
288+
{"CPU", 0x202f00000, false, 2, 4},
289+
{},
290+
};
291+
292+
static const struct cluster_t t8012_clusters[] = {
293+
/* Fused cluster, kernel expects P-core entry */
294+
{"CPU", 0x202f00000, false, 6, 10},
295+
{},
296+
};
297+
298+
static const struct cluster_t t8015_clusters[] = {
299+
{"ECPU", 0x208e00000, false, 2, 6},
300+
{"PCPU", 0x208e80000, true, 2, 7},
301+
{},
302+
};
303+
204304
static const struct cluster_t t8103_clusters[] = {
205305
{"ECPU", 0x210e00000, false, 1, 5},
206306
{"PCPU", 0x211e00000, true, 1, 7},
@@ -256,6 +356,23 @@ static const struct cluster_t t6031_clusters[] = {
256356
const struct cluster_t *cpufreq_get_clusters(void)
257357
{
258358
switch (chip_id) {
359+
case S5L8960X:
360+
return s5l8960x_clusters;
361+
case T7000:
362+
return t7000_clusters;
363+
case T7001:
364+
return t7001_clusters;
365+
case S8000:
366+
case S8001:
367+
case S8003:
368+
return s8000_clusters;
369+
case T8010:
370+
case T8011:
371+
return t8010_clusters;
372+
case T8012:
373+
return t8012_clusters;
374+
case T8015:
375+
return t8015_clusters;
259376
case T8103:
260377
return t8103_clusters;
261378
case T6000:
@@ -278,6 +395,27 @@ const struct cluster_t *cpufreq_get_clusters(void)
278395
}
279396
}
280397

398+
static const struct feat_t s5l8960x_features[] = {
399+
{},
400+
};
401+
402+
static const struct feat_t s8000_features[] = {
403+
{"cpu-apsc", CLUSTER_PSTATE, CLUSTER_PSTATE_M1_APSC_DIS, 0, CLUSTER_PSTATE_APSC_BUSY, false},
404+
{},
405+
};
406+
407+
static const struct feat_t t8010_features[] = {
408+
{"cpu-apsc", CLUSTER_PSTATE, CLUSTER_PSTATE_M1_APSC_DIS, 0, CLUSTER_PSTATE_APSC_BUSY, false},
409+
{},
410+
};
411+
412+
static const struct feat_t t8015_features[] = {
413+
{"cpu-apsc", CLUSTER_PSTATE, CLUSTER_PSTATE_M1_APSC_DIS, 0, CLUSTER_PSTATE_APSC_BUSY, false},
414+
{"cpu-fixed-freq-pll-relock", CLUSTER_PSTATE, 0, CLUSTER_PSTATE_FIXED_FREQ_PLL_RECLOCK, 0,
415+
false},
416+
{},
417+
};
418+
281419
static const struct feat_t t8103_features[] = {
282420
{"cpu-apsc", CLUSTER_PSTATE, CLUSTER_PSTATE_M1_APSC_DIS, 0, CLUSTER_PSTATE_APSC_BUSY, false},
283421
{"ppt-thrtl", 0x48400, 0, BIT(63), 0, false},
@@ -324,6 +462,20 @@ static const struct feat_t t6031_features[] = {
324462
const struct feat_t *cpufreq_get_features(void)
325463
{
326464
switch (chip_id) {
465+
case S5L8960X:
466+
case T7000:
467+
case T7001:
468+
return s5l8960x_features;
469+
case S8000:
470+
case S8001:
471+
case S8003:
472+
return s8000_features;
473+
case T8010:
474+
case T8011:
475+
case T8012:
476+
return t8010_features;
477+
case T8015:
478+
return t8015_features;
327479
case T8103:
328480
case T6000:
329481
case T6001:
@@ -353,6 +505,10 @@ int cpufreq_init(void)
353505
if (!cluster || !features)
354506
return -1;
355507

508+
/* Without this, CLUSTER_PSTATE_BUSY gets stuck */
509+
if (chip_id == T8012 || chip_id == T8015)
510+
pmgr_power_on(0, "SPMI");
511+
356512
bool err = false;
357513
while (cluster->base) {
358514
err |= cpufreq_init_cluster(cluster++, features);

0 commit comments

Comments
 (0)