Skip to content

Commit e55f9b8

Browse files
committed
add table mod back
1 parent 3bbc8a2 commit e55f9b8

4 files changed

Lines changed: 480 additions & 4 deletions

File tree

drivers/soc/samsung/cal-if/cal-if.c

Lines changed: 173 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "ra.h"
1616
#include "acpm_dvfs.h"
1717
#include "fvmap.h"
18+
#include "gpu_dvfs_overrides.h"
1819
#include "asv.h"
1920

2021
#include "pmucal_system.h"
@@ -29,14 +30,39 @@
2930

3031
static DEFINE_SPINLOCK(pmucal_cpu_lock);
3132

33+
static bool cal_is_gpu_dvfs_id(unsigned int id)
34+
{
35+
struct vclk *vclk;
36+
37+
vclk = cmucal_get_node(id);
38+
if (!vclk || !vclk->name)
39+
return false;
40+
41+
return !strcmp(vclk->name, "dvfs_g3d");
42+
}
43+
3244
unsigned int cal_clk_is_enabled(unsigned int id)
3345
{
3446
return 0;
3547
}
3648

3749
unsigned long cal_dfs_get_max_freq(unsigned int id)
3850
{
39-
return vclk_get_max_freq(id);
51+
struct vclk *vclk;
52+
unsigned long highest_override;
53+
54+
if (!cal_is_gpu_dvfs_id(id))
55+
return vclk_get_max_freq(id);
56+
57+
if (!gpu_dvfs_has_overrides())
58+
return vclk_get_max_freq(id);
59+
60+
highest_override = gpu_dvfs_override_highest_rate();
61+
vclk = cmucal_get_node(id);
62+
if (vclk && vclk->lut && highest_override > vclk->max_freq)
63+
vclk->max_freq = highest_override;
64+
65+
return highest_override ? highest_override : vclk_get_max_freq(id);
4066
}
4167

4268
unsigned long cal_dfs_get_min_freq(unsigned int id)
@@ -118,9 +144,62 @@ unsigned long cal_dfs_get_rate(unsigned int id)
118144
int cal_dfs_get_rate_table(unsigned int id, unsigned long *table)
119145
{
120146
int ret;
147+
struct vclk *vclk;
148+
size_t override_idx;
121149

122150
ret = vclk_get_rate_table(id, table);
123151

152+
if (!cal_is_gpu_dvfs_id(id) || ret <= 0 || !gpu_dvfs_has_overrides())
153+
return ret;
154+
155+
vclk = cmucal_get_node(id);
156+
if (!vclk || !vclk->lut)
157+
return ret;
158+
159+
if (ret > vclk->num_rates)
160+
ret = vclk->num_rates;
161+
162+
for (override_idx = 0; override_idx < gpu_dvfs_override_count(); override_idx++) {
163+
const struct gpu_dvfs_override_entry *entry;
164+
bool found = false;
165+
int insert_idx = vclk->num_rates;
166+
int idx;
167+
168+
entry = gpu_dvfs_override_get(override_idx);
169+
if (!entry)
170+
continue;
171+
172+
for (idx = 0; idx < ret; idx++) {
173+
if (table[idx] == entry->rate_khz) {
174+
found = true;
175+
break;
176+
}
177+
}
178+
179+
if (found)
180+
continue;
181+
182+
for (idx = 0; idx < vclk->num_rates; idx++) {
183+
if (vclk->lut[idx].rate == entry->rate_khz) {
184+
insert_idx = idx;
185+
break;
186+
}
187+
188+
if (insert_idx == vclk->num_rates && vclk->lut[idx].rate < entry->rate_khz)
189+
insert_idx = idx;
190+
}
191+
192+
if (insert_idx > ret)
193+
insert_idx = ret;
194+
195+
if (ret < vclk->num_rates) {
196+
for (idx = ret; idx > insert_idx; idx--)
197+
table[idx] = table[idx - 1];
198+
ret++;
199+
}
200+
201+
table[insert_idx] = entry->rate_khz;
202+
}
124203
return ret;
125204
}
126205

@@ -339,7 +418,99 @@ extern int cal_is_lastcore_detecting(unsigned int cpu)
339418

340419
int cal_dfs_get_asv_table(unsigned int id, unsigned int *table)
341420
{
342-
return fvmap_get_voltage_table(id, table);
421+
int entries;
422+
struct vclk *vclk;
423+
size_t override_count = 0;
424+
size_t override_idx;
425+
struct gpu_override_plan {
426+
const struct gpu_dvfs_override_entry *entry;
427+
int index;
428+
} *plans = NULL;
429+
430+
entries = fvmap_get_voltage_table(id, table);
431+
432+
if (!cal_is_gpu_dvfs_id(id) || entries <= 0 || !gpu_dvfs_has_overrides())
433+
return entries;
434+
435+
vclk = cmucal_get_node(id);
436+
if (!vclk || !vclk->lut)
437+
return entries;
438+
439+
if (entries > vclk->num_rates)
440+
entries = vclk->num_rates;
441+
442+
override_count = gpu_dvfs_override_count();
443+
plans = kcalloc(override_count, sizeof(*plans), GFP_KERNEL);
444+
if (!plans)
445+
return entries;
446+
447+
for (override_idx = 0; override_idx < override_count; override_idx++) {
448+
const struct gpu_dvfs_override_entry *entry;
449+
int idx;
450+
451+
entry = gpu_dvfs_override_get(override_idx);
452+
if (!entry)
453+
continue;
454+
455+
for (idx = 0; idx < vclk->num_rates; idx++) {
456+
if (vclk->lut[idx].rate == entry->rate_khz) {
457+
plans[override_idx].entry = entry;
458+
plans[override_idx].index = idx;
459+
break;
460+
}
461+
}
462+
}
463+
464+
/* sort overrides by target index descending to keep shifts safe */
465+
for (override_idx = 0; override_idx < override_count; override_idx++) {
466+
size_t other;
467+
468+
if (!plans[override_idx].entry)
469+
continue;
470+
471+
for (other = override_idx + 1; other < override_count; other++) {
472+
if (!plans[other].entry)
473+
continue;
474+
475+
if (plans[other].index > plans[override_idx].index) {
476+
struct gpu_override_plan tmp = plans[override_idx];
477+
plans[override_idx] = plans[other];
478+
plans[other] = tmp;
479+
}
480+
}
481+
}
482+
483+
for (override_idx = 0; override_idx < override_count; override_idx++) {
484+
const struct gpu_dvfs_override_entry *entry = plans[override_idx].entry;
485+
int idx = plans[override_idx].index;
486+
int shift;
487+
488+
if (!entry)
489+
continue;
490+
491+
if (idx > entries)
492+
idx = entries;
493+
494+
if (idx >= entries) {
495+
if (entries < vclk->num_rates) {
496+
table[entries] = entry->volt_uv;
497+
entries++;
498+
}
499+
continue;
500+
}
501+
502+
if (entries < vclk->num_rates) {
503+
for (shift = entries; shift > idx; shift--)
504+
table[shift] = table[shift - 1];
505+
entries++;
506+
}
507+
508+
table[idx] = entry->volt_uv;
509+
}
510+
511+
kfree(plans);
512+
513+
return entries;
343514
}
344515

345516
void cal_dfs_set_volt_margin(unsigned int id, int volt)

drivers/soc/samsung/cal-if/fvmap.c

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "cmucal.h"
1515
#include "fvmap.h"
16+
#include "gpu_dvfs_overrides.h"
1617
#include "ra.h"
1718
#include "vclk.h"
1819

@@ -26,6 +27,37 @@ static int init_margin_table[MAX_MARGIN_ID];
2627
static int volt_offset_percent = 0;
2728
static int percent_margin_table[MAX_MARGIN_ID];
2829

30+
#define G3D_MANUAL_RATE(_mhz, _uv) {.rate = (_mhz) * 1000U, .volt = (_uv)}
31+
32+
static const struct rate_volt g3d_manual_ratevolt[] = {
33+
G3D_MANUAL_RATE(754, 800000),
34+
G3D_MANUAL_RATE(702, 775000),
35+
G3D_MANUAL_RATE(650, 750000),
36+
G3D_MANUAL_RATE(572, 725000),
37+
G3D_MANUAL_RATE(433, 700000),
38+
G3D_MANUAL_RATE(377, 675000),
39+
G3D_MANUAL_RATE(325, 650000),
40+
G3D_MANUAL_RATE(260, 625000),
41+
G3D_MANUAL_RATE(200, 600000),
42+
G3D_MANUAL_RATE(156, 575000),
43+
G3D_MANUAL_RATE(100, 550000),
44+
};
45+
46+
static size_t
47+
fvmap_ratevolt_capacity(const volatile struct fvmap_header *header) {
48+
size_t capacity = header->num_of_lv;
49+
50+
if (header->o_tables > header->o_ratevolt) {
51+
size_t ratevolt_capacity =
52+
(header->o_tables - header->o_ratevolt) / sizeof(struct rate_volt);
53+
54+
if (ratevolt_capacity && ratevolt_capacity < capacity)
55+
capacity = ratevolt_capacity;
56+
}
57+
58+
return capacity;
59+
}
60+
2961
static size_t
3062
fvmap_calculate_initial_usage(const volatile struct fvmap_header *header,
3163
int num_of_vclks) {
@@ -50,6 +82,35 @@ fvmap_calculate_initial_usage(const volatile struct fvmap_header *header,
5082
return ALIGN(max_offset, sizeof(u32));
5183
}
5284

85+
static void fvmap_apply_gpu_manual_table(volatile struct fvmap_header *header,
86+
struct rate_volt_header *rate_table,
87+
struct vclk *vclk) {
88+
size_t manual_count = ARRAY_SIZE(g3d_manual_ratevolt);
89+
size_t capacity = fvmap_ratevolt_capacity(header);
90+
size_t idx;
91+
92+
if (capacity < manual_count) {
93+
pr_warn(" G3D manual table truncated to %zu entries (capacity %zu)\n",
94+
capacity, manual_count);
95+
manual_count = capacity;
96+
}
97+
98+
if (!manual_count)
99+
return;
100+
101+
memcpy(rate_table->table, g3d_manual_ratevolt,
102+
manual_count * sizeof(struct rate_volt));
103+
header->num_of_lv = manual_count;
104+
105+
if (vclk && vclk->lut && vclk->num_rates < manual_count)
106+
vclk->num_rates = manual_count;
107+
108+
if (vclk && vclk->lut) {
109+
for (idx = 0; idx < manual_count && idx < vclk->num_rates; idx++)
110+
vclk->lut[idx].rate = g3d_manual_ratevolt[idx].rate;
111+
}
112+
}
113+
53114
static int __init get_mif_volt(char *str) {
54115
int volt;
55116

@@ -451,11 +512,60 @@ static void fvmap_copy_from_sram(void __iomem *map_base,
451512

452513
fw_lv = header[i].num_of_lv;
453514

515+
if (!strcmp(vclk->name, "dvfs_g3d")) {
516+
size_t manual_lv = ARRAY_SIZE(g3d_manual_ratevolt);
517+
size_t capacity = fvmap_ratevolt_capacity(&header[i]);
518+
519+
if (manual_lv > capacity) {
520+
size_t ratevolt_bytes = manual_lv * sizeof(struct rate_volt);
521+
size_t table_bytes = manual_lv * fvmap_header[i].num_of_members;
522+
size_t new_ratevolt_offset =
523+
ALIGN(next_free_offset, sizeof(struct rate_volt));
524+
size_t new_tables_offset =
525+
ALIGN(new_ratevolt_offset + ratevolt_bytes, sizeof(u32));
526+
size_t new_end = new_tables_offset + table_bytes;
527+
528+
if (new_end > FVMAP_SIZE) {
529+
pr_err(" G3D: unable to extend manual table, "
530+
"need %zu bytes, limit %lu – truncating\n",
531+
new_end, FVMAP_SIZE);
532+
manual_lv = capacity;
533+
} else {
534+
pr_info(" G3D: relocating rate/volt tables to 0x%zx "
535+
"to fit %zu entries\n",
536+
new_ratevolt_offset, manual_lv);
537+
fvmap_header[i].o_ratevolt = new_ratevolt_offset;
538+
fvmap_header[i].o_tables = new_tables_offset;
539+
next_free_offset = new_end;
540+
capacity = manual_lv;
541+
}
542+
}
543+
544+
if (manual_lv > capacity) {
545+
pr_warn(" G3D: manual table has %zu entries, "
546+
"FW/capacity only %zu – truncating!\n",
547+
manual_lv, capacity);
548+
manual_lv = capacity;
549+
}
550+
551+
pr_info(" G3D: using %zu levels from manual table "
552+
"(FW advertised %u)\n",
553+
manual_lv, fw_lv);
554+
555+
fvmap_header[i].num_of_lv = manual_lv;
556+
}
557+
454558
pr_info("dvfs_type : %s - id : %x\n", vclk->name,
455559
fvmap_header[i].dvfs_type);
456560
pr_info(" num_of_lv : %d\n", fvmap_header[i].num_of_lv);
457561
pr_info(" num_of_members : %d\n", fvmap_header[i].num_of_members);
458562

563+
if (!strcmp(vclk->name, "dvfs_g3d")) {
564+
pr_info(" G3D init level : %d\n", fvmap_header[i].init_lv);
565+
pr_info(" G3D volt_offset_percent : %d\n", volt_offset_percent);
566+
pr_info(" Using manual G3D rate/volt table\n");
567+
}
568+
459569
old = sram_base + header[i].o_ratevolt;
460570
new = map_base + fvmap_header[i].o_ratevolt;
461571

@@ -504,6 +614,10 @@ static void fvmap_copy_from_sram(void __iomem *map_base,
504614
new->table[j].volt, volt_offset_percent);
505615
}
506616

617+
if (!strcmp(vclk->name, "dvfs_g3d")) {
618+
fvmap_apply_gpu_manual_table(&fvmap_header[i], new, vclk);
619+
}
620+
507621
for (j = 0; j < fvmap_header[i].num_of_lv; j++) {
508622
pr_info(" lv : [%7d], volt = %d uV (%d %%) \n", new->table[j].rate,
509623
new->table[j].volt, volt_offset_percent);
@@ -526,6 +640,18 @@ static void fvmap_copy_from_sram(void __iomem *map_base,
526640
}
527641
}
528642

643+
if (!strcmp(vclk->name, "dvfs_g3d")) {
644+
size_t manual_lv = fvmap_header[i].num_of_lv;
645+
646+
if (manual_lv > fw_lv && fw_lv) {
647+
size_t stride = fvmap_header[i].num_of_members;
648+
649+
for (j = fw_lv; j < manual_lv; j++) {
650+
memcpy(&new_param->val[stride * j],
651+
&new_param->val[stride * (fw_lv - 1)], stride);
652+
}
653+
}
654+
}
529655
}
530656
}
531657

0 commit comments

Comments
 (0)