Skip to content

Commit 9014dce

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 580c96d commit 9014dce

File tree

1 file changed

+137
-3
lines changed

1 file changed

+137
-3
lines changed

src/cpufreq.c

Lines changed: 137 additions & 3 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,7 +47,10 @@ struct feat_t {
4247
static u32 pstate_reg_to_pstate(u64 val)
4348
{
4449
switch (chip_id) {
45-
case T8103 ... T8122:
50+
case S5L8960X:
51+
case T7000 ... T7001:
52+
return FIELD_GET(CLUSTER_PSTATE_DESIRED1_S5L8960X, val);
53+
case S8000 ... T8122:
4654
case T6000 ... T6034:
4755
default:
4856
return FIELD_GET(CLUSTER_PSTATE_DESIRED1, val);
@@ -55,7 +63,12 @@ static int set_pstate(const struct cluster_t *cluster, uint32_t pstate)
5563

5664
if (pstate_reg_to_pstate(val) != pstate) {
5765
switch (chip_id) {
58-
case T8103:
66+
case S5L8960X:
67+
case T7000 ... T7001:
68+
val &= ~CLUSTER_PSTATE_DESIRED1_S5L8960X;
69+
val |= CLUSTER_PSTATE_SET | FIELD_PREP(CLUSTER_PSTATE_DESIRED1_S5L8960X, pstate);
70+
break;
71+
case S8000 ... T8103:
5972
case T6000 ... T6002:
6073
val &= ~CLUSTER_PSTATE_DESIRED2;
6174
val |= CLUSTER_PSTATE_SET | FIELD_PREP(CLUSTER_PSTATE_DESIRED2, pstate);
@@ -105,7 +118,34 @@ int cpufreq_init_cluster(const struct cluster_t *cluster, const struct feat_t *f
105118
}
106119
}
107120

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

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

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

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

0 commit comments

Comments
 (0)