Skip to content

Commit f10335f

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 6a96969 commit f10335f

File tree

1 file changed

+136
-3
lines changed

1 file changed

+136
-3
lines changed

src/cpufreq.c

Lines changed: 136 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,33 @@ 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;
109148
case T8103 ... T8122:
110149
case T6000 ... T6034:
111150
default:
@@ -172,6 +211,44 @@ void cpufreq_fixup_cluster(const struct cluster_t *cluster)
172211
}
173212
}
174213

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+
175252
static const struct cluster_t t8103_clusters[] = {
176253
{"ECPU", 0x210e00000, false, 1, 5},
177254
{"PCPU", 0x211e00000, true, 1, 7},
@@ -227,6 +304,23 @@ static const struct cluster_t t6031_clusters[] = {
227304
const struct cluster_t *cpufreq_get_clusters(void)
228305
{
229306
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;
230324
case T8103:
231325
return t8103_clusters;
232326
case T6000:
@@ -249,6 +343,27 @@ const struct cluster_t *cpufreq_get_clusters(void)
249343
}
250344
}
251345

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+
252367
static const struct feat_t t8103_features[] = {
253368
{"cpu-apsc", CLUSTER_PSTATE, CLUSTER_PSTATE_M1_APSC_DIS, 0, CLUSTER_PSTATE_APSC_BUSY, false},
254369
{"ppt-thrtl", 0x48400, 0, BIT(63), 0, false},
@@ -295,6 +410,20 @@ static const struct feat_t t6031_features[] = {
295410
const struct feat_t *cpufreq_get_features(void)
296411
{
297412
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;
298427
case T8103:
299428
case T6000 ... T6002:
300429
return t8103_features;
@@ -322,6 +451,10 @@ int cpufreq_init(void)
322451
if (!cluster || !features)
323452
return -1;
324453

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

0 commit comments

Comments
 (0)