Skip to content

Commit 7b7d61f

Browse files
committed
Update fvmap.c
1 parent 2bd37ae commit 7b7d61f

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

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

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,97 @@ static int __init get_percent_margin_volt(char *str)
220220
}
221221
early_param("volt_offset_percent", get_percent_margin_volt);
222222

223+
static void *fvmap_alloc_extra(size_t size, size_t align)
224+
{
225+
void *ptr;
226+
227+
fvmap_alloc_offset = ALIGN(fvmap_alloc_offset, align);
228+
if (fvmap_alloc_offset + size > fvmap_alloc_limit)
229+
return NULL;
230+
231+
ptr = fvmap_base + fvmap_alloc_offset;
232+
fvmap_alloc_offset += size;
233+
234+
return ptr;
235+
}
236+
237+
static bool fvmap_extend_g3d(struct fvmap_header *fvmap_header,
238+
void __iomem *map_base, void __iomem *sram_base,
239+
struct vclk *vclk)
240+
{
241+
const unsigned int oc_rate = 754000;
242+
const int old_lv = fvmap_header->num_of_lv;
243+
int new_lv = 13;
244+
struct rate_volt_header *old_rv, *new_rv;
245+
struct dvfs_table *old_tbl, *new_tbl;
246+
int members = fvmap_header->num_of_members;
247+
bool have_oc;
248+
249+
old_rv = sram_base + fvmap_header->o_ratevolt;
250+
have_oc = old_lv > 0 && old_rv->table[0].rate == oc_rate;
251+
252+
if (old_lv >= new_lv && have_oc)
253+
return false;
254+
255+
if (old_lv >= new_lv)
256+
new_lv = old_lv + 1;
257+
258+
new_rv = fvmap_alloc_extra(sizeof(struct rate_volt) * new_lv,
259+
__alignof__(struct rate_volt));
260+
if (!new_rv) {
261+
pr_err("[%s] g3d: no space for extended rate/volt table\n",
262+
__func__);
263+
return false;
264+
}
265+
266+
/* insert OC level at the top and shift existing entries down */
267+
new_rv->table[0].rate = oc_rate;
268+
new_rv->table[0].volt = old_rv->table[0].volt;
269+
memcpy(&new_rv->table[1], &old_rv->table[0],
270+
sizeof(struct rate_volt) * old_lv);
271+
272+
old_tbl = sram_base + fvmap_header->o_tables;
273+
new_tbl = fvmap_alloc_extra(members * new_lv, 1);
274+
if (!new_tbl) {
275+
pr_err("[%s] g3d: no space for extended dvfs table\n",
276+
__func__);
277+
return false;
278+
}
279+
280+
memcpy(&new_tbl->val[0], &old_tbl->val[0], members);
281+
memcpy(&new_tbl->val[members], &old_tbl->val[0], members * old_lv);
282+
283+
fvmap_header->o_ratevolt = (unsigned short)((void *)new_rv - map_base);
284+
fvmap_header->o_tables = (unsigned short)((void *)new_tbl - map_base);
285+
fvmap_header->num_of_lv = new_lv;
286+
if (fvmap_header->init_lv < new_lv)
287+
fvmap_header->init_lv += 1;
288+
289+
pr_info("dvfs_g3d: extended FV table %d -> %d levels (OC 754MHz)\n",
290+
old_lv, new_lv);
291+
292+
/* update vclk LUT to expose the new OC rate to CAL/clients */
293+
if (vclk && vclk->lut) {
294+
int lut_sz = vclk->num_rates;
295+
int copy_lv = min(new_lv - 1, old_lv);
296+
int idx;
297+
298+
if (lut_sz < new_lv)
299+
lut_sz = new_lv;
300+
301+
for (idx = min(lut_sz - 1, copy_lv); idx > 0; idx--)
302+
vclk->lut[idx].rate = vclk->lut[idx - 1].rate;
303+
304+
vclk->lut[0].rate = oc_rate;
305+
vclk->num_rates = max(vclk->num_rates, (unsigned int)new_lv);
306+
vclk->max_freq = max(vclk->max_freq, oc_rate);
307+
vclk->min_freq = min(vclk->min_freq,
308+
new_rv->table[new_lv - 1].rate);
309+
}
310+
311+
return true;
312+
}
313+
223314
int fvmap_set_raw_voltage_table(unsigned int id, int uV)
224315
{
225316
struct fvmap_header *fvmap_header;

0 commit comments

Comments
 (0)