mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-10 09:44:13 +00:00
kboot_gpu: Add preliminary T600x support
Signed-off-by: Asahi Lina <lina@asahilina.net>
This commit is contained in:
parent
6e99fde8f2
commit
3278d75453
1 changed files with 98 additions and 20 deletions
118
src/kboot_gpu.c
118
src/kboot_gpu.c
|
@ -14,8 +14,71 @@
|
|||
return -1; \
|
||||
} while (0)
|
||||
|
||||
#define MAX_PSTATES 16
|
||||
#define MAX_CLUSTERS 8
|
||||
|
||||
struct perf_state {
|
||||
u32 freq;
|
||||
u32 volt;
|
||||
};
|
||||
|
||||
u32 t8103_pwr_scale[] = {0, 63, 80, 108, 150, 198, 210};
|
||||
|
||||
int calc_power_t8103(int sgx, u32 count, u32 table_count, const struct perf_state *perf_states,
|
||||
u32 *max_pwr)
|
||||
{
|
||||
UNUSED(sgx);
|
||||
|
||||
u32 pwr_scale_count = ARRAY_SIZE(t8103_pwr_scale);
|
||||
|
||||
if (table_count != 1)
|
||||
bail("ADT: GPU: expected 1 perf state table but got %d\n", table_count);
|
||||
|
||||
if (count != pwr_scale_count)
|
||||
bail("ADT: GPU: expected %d perf states but got %d\n", pwr_scale_count, count);
|
||||
|
||||
for (u32 i = 0; i < pwr_scale_count; i++)
|
||||
max_pwr[i] = (u32)perf_states[i].volt * (u32)t8103_pwr_scale[i] * 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 t6000_pwr_scale[] = {0, 15, 19, 25, 34, 50, 100};
|
||||
|
||||
int calc_power_t600x(int sgx, u32 count, u32 table_count, const struct perf_state *perf_states,
|
||||
u32 *max_pwr)
|
||||
{
|
||||
UNUSED(sgx);
|
||||
UNUSED(perf_states);
|
||||
|
||||
u32 nclusters = 0;
|
||||
switch (chip_id) {
|
||||
case T6000:
|
||||
nclusters = 2;
|
||||
break;
|
||||
case T6001:
|
||||
nclusters = 4;
|
||||
break;
|
||||
case T6002:
|
||||
nclusters = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
u32 pwr_scale_count = ARRAY_SIZE(t6000_pwr_scale);
|
||||
|
||||
if (table_count != nclusters)
|
||||
bail("ADT: GPU: expected %d perf state tables but got %d\n", nclusters, table_count);
|
||||
|
||||
if (count != pwr_scale_count)
|
||||
bail("ADT: GPU: expected %d perf states but got %d\n", pwr_scale_count, count);
|
||||
|
||||
for (u32 i = 0; i < pwr_scale_count; i++) {
|
||||
max_pwr[i] = t6000_pwr_scale[i] * 1667430 * nclusters / 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dt_set_region(void *dt, int sgx, const char *name, const char *path)
|
||||
{
|
||||
u64 base, size;
|
||||
|
@ -46,12 +109,17 @@ static int dt_set_region(void *dt, int sgx, const char *name, const char *path)
|
|||
|
||||
int dt_set_gpu(void *dt)
|
||||
{
|
||||
u32 *pwr_scale;
|
||||
u32 pwr_scale_count;
|
||||
int (*calc_power)(int sgx, u32 count, u32 table_count, const struct perf_state *perf,
|
||||
u32 *max_pwr);
|
||||
|
||||
switch (chip_id) {
|
||||
case T8103:
|
||||
pwr_scale = t8103_pwr_scale;
|
||||
pwr_scale_count = ARRAY_SIZE(t8103_pwr_scale);
|
||||
calc_power = calc_power_t8103;
|
||||
break;
|
||||
case T6000:
|
||||
case T6001:
|
||||
case T6002:
|
||||
calc_power = calc_power_t600x;
|
||||
break;
|
||||
default:
|
||||
printf("ADT: GPU: unsupported chip!\n");
|
||||
|
@ -81,42 +149,52 @@ int dt_set_gpu(void *dt)
|
|||
if (ADT_GETPROP(adt, sgx, "perf-state-count", &perf_state_count) < 0 || !perf_state_count)
|
||||
bail("ADT: GPU: missing perf-state-count\n");
|
||||
|
||||
if (perf_state_count != pwr_scale_count)
|
||||
bail("ADT: GPU: expected %d perf states but got %d\n", pwr_scale_count, perf_state_count);
|
||||
u32 perf_state_table_count;
|
||||
if (ADT_GETPROP(adt, sgx, "perf-state-table-count", &perf_state_table_count) < 0 ||
|
||||
!perf_state_table_count)
|
||||
bail("ADT: GPU: missing perf-state-table-count\n");
|
||||
|
||||
if (perf_state_count > MAX_PSTATES)
|
||||
bail("ADT: GPU: perf-state-count too large\n");
|
||||
|
||||
if (perf_state_table_count > MAX_CLUSTERS)
|
||||
bail("ADT: GPU: perf-state-table-count too large\n");
|
||||
|
||||
u32 perf_states_len;
|
||||
const struct {
|
||||
u32 freq;
|
||||
u32 volt;
|
||||
} * perf_states;
|
||||
const struct perf_state *perf_states;
|
||||
|
||||
perf_states = adt_getprop(adt, sgx, "perf-states", &perf_states_len);
|
||||
if (!perf_states || perf_states_len != sizeof(*perf_states) * perf_state_count)
|
||||
if (!perf_states ||
|
||||
perf_states_len != sizeof(*perf_states) * perf_state_count * perf_state_table_count)
|
||||
bail("ADT: GPU: invalid perf-states length\n");
|
||||
|
||||
u64 max_pwr[16];
|
||||
u32 max_pwr[MAX_PSTATES];
|
||||
|
||||
for (u32 i = 0; i < pwr_scale_count; i++)
|
||||
max_pwr[i] = (u64)perf_states[i].volt * (u64)pwr_scale[i];
|
||||
|
||||
for (u32 i = 0; i < pwr_scale_count; i++)
|
||||
max_pwr[i] = 100 * max_pwr[i] / max_pwr[pwr_scale_count - 1];
|
||||
if (calc_power(sgx, perf_state_count, perf_state_table_count, perf_states, max_pwr))
|
||||
return -1;
|
||||
|
||||
u32 i = 0;
|
||||
int opp;
|
||||
fdt_for_each_subnode(opp, dt, opps)
|
||||
{
|
||||
fdt32_t volts[MAX_CLUSTERS];
|
||||
|
||||
for (u32 j = 0; j < perf_state_table_count; j++) {
|
||||
volts[j] = cpu_to_fdt32(perf_states[i + j * perf_state_count].volt * 1000);
|
||||
}
|
||||
|
||||
if (i >= perf_state_count)
|
||||
bail("FDT: GPU: Expected %d operating points, but found more\n", perf_state_count);
|
||||
|
||||
if (fdt_setprop_inplace_u32(dt, opp, "opp-microvolt", perf_states[i].volt * 1000))
|
||||
if (fdt_setprop_inplace(dt, opp, "opp-microvolt", &volts,
|
||||
sizeof(u32) * perf_state_table_count))
|
||||
bail("FDT: GPU: Failed to set opp-microvolt for PS %d\n", i);
|
||||
|
||||
if (fdt_setprop_inplace_u64(dt, opp, "opp-hz", perf_states[i].freq))
|
||||
bail("FDT: GPU: Failed to set opp-hz for PS %d\n", i);
|
||||
|
||||
if (fdt_setprop_inplace_u32(dt, opp, "apple,opp-rel-power", max_pwr[i]))
|
||||
bail("FDT: GPU: Failed to set apple,opp-rel-power for PS %d\n", i);
|
||||
if (fdt_setprop_inplace_u32(dt, opp, "opp-microwatt", max_pwr[i]))
|
||||
bail("FDT: GPU: Failed to set opp-microwatt for PS %d\n", i);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue