Skip to content

Commit 2050cda

Browse files
committed
Update fvmap.c
1 parent 543a591 commit 2050cda

1 file changed

Lines changed: 147 additions & 53 deletions

File tree

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

Lines changed: 147 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <linux/types.h>
22
#include <linux/kernel.h>
33
#include <linux/slab.h>
4+
#include <linux/string.h>
45
#include <linux/io.h>
56
#include <linux/debugfs.h>
67
#include <linux/uaccess.h>
@@ -13,6 +14,7 @@
1314
#include "ra.h"
1415

1516
#define FVMAP_SIZE (SZ_8K)
17+
#define FVMAP_EXTRA_SIZE SZ_1K
1618
#define STEP_UV (6250)
1719

1820
void __iomem *fvmap_base;
@@ -21,6 +23,8 @@ void __iomem *sram_fvmap_base;
2123
static int init_margin_table[MAX_MARGIN_ID];
2224
static int volt_offset_percent = 0;
2325
static int percent_margin_table[MAX_MARGIN_ID];
26+
static size_t fvmap_alloc_offset;
27+
static size_t fvmap_alloc_limit;
2428

2529
static int __init get_mif_volt(char *str)
2630
{
@@ -220,6 +224,75 @@ static int __init get_percent_margin_volt(char *str)
220224
}
221225
early_param("volt_offset_percent", get_percent_margin_volt);
222226

227+
static void *fvmap_alloc_extra(size_t size, size_t align)
228+
{
229+
void *ptr;
230+
231+
fvmap_alloc_offset = ALIGN(fvmap_alloc_offset, align);
232+
if (fvmap_alloc_offset + size > fvmap_alloc_limit)
233+
return NULL;
234+
235+
ptr = fvmap_base + fvmap_alloc_offset;
236+
fvmap_alloc_offset += size;
237+
238+
return ptr;
239+
}
240+
241+
static bool fvmap_extend_g3d(struct fvmap_header *fvmap_header,
242+
void __iomem *map_base, void __iomem *sram_base,
243+
struct vclk *vclk)
244+
{
245+
const int old_lv = fvmap_header->num_of_lv;
246+
const int new_lv = 13;
247+
struct rate_volt_header *old_rv, *new_rv;
248+
struct dvfs_table *old_tbl, *new_tbl;
249+
int members = fvmap_header->num_of_members;
250+
251+
if (old_lv >= new_lv)
252+
return false;
253+
254+
old_rv = sram_base + fvmap_header->o_ratevolt;
255+
new_rv = fvmap_alloc_extra(sizeof(struct rate_volt) * new_lv,
256+
__alignof__(struct rate_volt));
257+
if (!new_rv) {
258+
pr_err("[%s] g3d: no space for extended rate/volt table\n",
259+
__func__);
260+
return false;
261+
}
262+
263+
/* insert OC level at the top and shift existing entries down */
264+
new_rv->table[0].rate = 754000;
265+
new_rv->table[0].volt = old_rv->table[0].volt;
266+
memcpy(&new_rv->table[1], &old_rv->table[0],
267+
sizeof(struct rate_volt) * old_lv);
268+
269+
old_tbl = sram_base + fvmap_header->o_tables;
270+
new_tbl = fvmap_alloc_extra(members * new_lv, 1);
271+
if (!new_tbl) {
272+
pr_err("[%s] g3d: no space for extended dvfs table\n",
273+
__func__);
274+
return false;
275+
}
276+
277+
memcpy(&new_tbl->val[0], &old_tbl->val[0], members);
278+
memcpy(&new_tbl->val[members], &old_tbl->val[0], members * old_lv);
279+
280+
fvmap_header->o_ratevolt = (unsigned short)((void *)new_rv - map_base);
281+
fvmap_header->o_tables = (unsigned short)((void *)new_tbl - map_base);
282+
fvmap_header->num_of_lv = new_lv;
283+
if (fvmap_header->init_lv < new_lv)
284+
fvmap_header->init_lv += 1;
285+
286+
pr_info("dvfs_g3d: extended FV table %d -> %d levels (OC 754MHz)\n",
287+
old_lv, new_lv);
288+
289+
/* update vclk names to reflect new size */
290+
if (vclk)
291+
vclk->num_of_lv = new_lv;
292+
293+
return true;
294+
}
295+
223296
int fvmap_set_raw_voltage_table(unsigned int id, int uV)
224297
{
225298
struct fvmap_header *fvmap_header;
@@ -306,47 +379,48 @@ static int get_vclk_id_from_margin_id(int margin_id)
306379
int size = cmucal_get_list_size(ACPM_VCLK_TYPE);
307380
int i;
308381
struct vclk *vclk;
382+
bool g3d_extended;
309383

310-
for (i = 0; i < size; i++) {
384+
for (i = 0; i < size; i++) {
311385
vclk = cmucal_get_node(ACPM_VCLK_TYPE | i);
312386

313387
if (vclk->margin_id == margin_id)
314388
return i;
315-
}
389+
}
316390

317-
return -EINVAL;
391+
return -EINVAL;
318392
}
319393

320394
#define attr_percent(margin_id, type) \
321395
static ssize_t show_##type##_percent \
322396
(struct kobject *kobj, struct kobj_attribute *attr, char *buf) \
323397
{ \
324-
return snprintf(buf, PAGE_SIZE, "%d\n", percent_margin_table[margin_id]); \
398+
return snprintf(buf, PAGE_SIZE, "%d\n", percent_margin_table[margin_id]); \
325399
} \
326400
\
327401
static ssize_t store_##type##_percent \
328402
(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) \
329403
{ \
330-
int input, vclk_id; \
404+
int input, vclk_id; \
331405
\
332-
if (!sscanf(buf, "%d", &input)) \
406+
if (!sscanf(buf, "%d", &input)) \
333407
return -EINVAL; \
334408
\
335-
if (input < -100 || input > 100) \
409+
if (input < -100 || input > 100) \
336410
return -EINVAL; \
337411
\
338-
vclk_id = get_vclk_id_from_margin_id(margin_id); \
339-
if (vclk_id == -EINVAL) \
412+
vclk_id = get_vclk_id_from_margin_id(margin_id); \
413+
if (vclk_id == -EINVAL) \
340414
return vclk_id; \
341-
percent_margin_table[margin_id] = input; \
342-
cal_dfs_set_volt_margin(vclk_id | ACPM_VCLK_TYPE, input); \
415+
percent_margin_table[margin_id] = input; \
416+
cal_dfs_set_volt_margin(vclk_id | ACPM_VCLK_TYPE, input); \
343417
\
344-
return count; \
418+
return count; \
345419
} \
346420
\
347421
static struct kobj_attribute type##_percent = \
348422
__ATTR(type##_percent, 0600, \
349-
show_##type##_percent, store_##type##_percent)
423+
show_##type##_percent, store_##type##_percent)
350424

351425
attr_percent(MARGIN_MIF, mif_margin);
352426
attr_percent(MARGIN_INT, int_margin);
@@ -366,48 +440,50 @@ attr_percent(MARGIN_NPU, npu_margin);
366440
attr_percent(MARGIN_MFC, mfc_margin);
367441

368442
static struct attribute *percent_margin_attrs[] = {
369-
&mif_margin_percent.attr,
370-
&int_margin_percent.attr,
371-
&big_margin_percent.attr,
372-
&mid_margin_percent.attr,
373-
&lit_margin_percent.attr,
374-
&g3d_margin_percent.attr,
375-
&intcam_margin_percent.attr,
376-
&cam_margin_percent.attr,
377-
&disp_margin_percent.attr,
378-
&cp_margin_percent.attr,
379-
&fsys0_margin_percent.attr,
380-
&aud_margin_percent.attr,
381-
&iva_margin_percent.attr,
382-
&score_margin_percent.attr,
383-
&npu_margin_percent.attr,
384-
&mfc_margin_percent.attr,
385-
NULL,
443+
&mif_margin_percent.attr,
444+
&int_margin_percent.attr,
445+
&big_margin_percent.attr,
446+
&mid_margin_percent.attr,
447+
&lit_margin_percent.attr,
448+
&g3d_margin_percent.attr,
449+
&intcam_margin_percent.attr,
450+
&cam_margin_percent.attr,
451+
&disp_margin_percent.attr,
452+
&cp_margin_percent.attr,
453+
&fsys0_margin_percent.attr,
454+
&aud_margin_percent.attr,
455+
&iva_margin_percent.attr,
456+
&score_margin_percent.attr,
457+
&npu_margin_percent.attr,
458+
&mfc_margin_percent.attr,
459+
NULL,
386460
};
387461

388462
static const struct attribute_group percent_margin_group = {
389-
.attrs = percent_margin_attrs,
463+
.attrs = percent_margin_attrs,
390464
};
391465

392466
static void fvmap_copy_from_sram(void __iomem *map_base, void __iomem *sram_base)
393467
{
394-
volatile struct fvmap_header *fvmap_header, *header;
395-
struct rate_volt_header *old, *new;
396-
struct dvfs_table *old_param, *new_param;
397-
struct clocks *clks;
398-
struct pll_header *plls;
399-
struct vclk *vclk;
400-
unsigned int member_addr;
401-
unsigned int blk_idx, param_idx;
402-
int size, margin;
403-
int i, j, k;
404-
405-
fvmap_header = map_base;
406-
header = sram_base;
407-
408-
size = cmucal_get_list_size(ACPM_VCLK_TYPE);
409-
410-
for (i = 0; i < size; i++) {
468+
volatile struct fvmap_header *fvmap_header, *header;
469+
struct rate_volt_header *old, *new;
470+
struct dvfs_table *old_param, *new_param;
471+
struct clocks *clks;
472+
struct pll_header *plls;
473+
struct vclk *vclk;
474+
bool g3d_extended;
475+
unsigned int member_addr;
476+
unsigned int blk_idx, param_idx;
477+
unsigned short orig_o_ratevolt, orig_o_tables;
478+
int size, margin;
479+
int i, j, k;
480+
481+
fvmap_header = map_base;
482+
header = sram_base;
483+
484+
size = cmucal_get_list_size(ACPM_VCLK_TYPE);
485+
486+
for (i = 0; i < size; i++) {
411487
/* load fvmap info */
412488
fvmap_header[i].dvfs_type = header[i].dvfs_type;
413489
fvmap_header[i].num_of_lv = header[i].num_of_lv;
@@ -426,16 +502,26 @@ static void fvmap_copy_from_sram(void __iomem *map_base, void __iomem *sram_base
426502
fvmap_header[i].o_members = header[i].o_members;
427503
fvmap_header[i].o_ratevolt = header[i].o_ratevolt;
428504
fvmap_header[i].o_tables = header[i].o_tables;
505+
orig_o_ratevolt = fvmap_header[i].o_ratevolt;
506+
orig_o_tables = fvmap_header[i].o_tables;
429507

430508
vclk = cmucal_get_node(ACPM_VCLK_TYPE | i);
431509
if (vclk == NULL)
432-
continue;
510+
continue;
511+
512+
g3d_extended = false;
513+
514+
if (!strncmp(vclk->name, "dvfs_g3d", 8))
515+
g3d_extended = fvmap_extend_g3d(&fvmap_header[i], map_base, sram_base, vclk);
433516
pr_info("dvfs_type : %s - id : %x\n",
434-
vclk->name, fvmap_header[i].dvfs_type);
517+
vclk->name, fvmap_header[i].dvfs_type);
435518
pr_info(" num_of_lv : %d\n", fvmap_header[i].num_of_lv);
436519
pr_info(" num_of_members : %d\n", fvmap_header[i].num_of_members);
437520

438-
old = sram_base + fvmap_header[i].o_ratevolt;
521+
if (g3d_extended)
522+
old = map_base + fvmap_header[i].o_ratevolt;
523+
else
524+
old = sram_base + orig_o_ratevolt;
439525
new = map_base + fvmap_header[i].o_ratevolt;
440526

441527
check_percent_margin(old, fvmap_header[i].num_of_lv);
@@ -478,7 +564,10 @@ static void fvmap_copy_from_sram(void __iomem *map_base, void __iomem *sram_base
478564
volt_offset_percent);
479565
}
480566

481-
old_param = sram_base + fvmap_header[i].o_tables;
567+
if (g3d_extended)
568+
old_param = map_base + fvmap_header[i].o_tables;
569+
else
570+
old_param = sram_base + orig_o_tables;
482571
new_param = map_base + fvmap_header[i].o_tables;
483572
for (j = 0; j < fvmap_header[i].num_of_lv; j++) {
484573
for (k = 0; k < fvmap_header[i].num_of_members; k++) {
@@ -500,11 +589,16 @@ int fvmap_init(void __iomem *sram_base)
500589
{
501590
void __iomem *map_base;
502591
struct kobject *kobj;
592+
size_t alloc_size;
593+
594+
alloc_size = FVMAP_SIZE + FVMAP_EXTRA_SIZE;
503595

504-
map_base = kzalloc(FVMAP_SIZE, GFP_KERNEL);
596+
map_base = kzalloc(alloc_size, GFP_KERNEL);
505597

506598
fvmap_base = map_base;
507599
sram_fvmap_base = sram_base;
600+
fvmap_alloc_offset = FVMAP_SIZE;
601+
fvmap_alloc_limit = alloc_size;
508602
pr_info("%s:fvmap initialize %p\n", __func__, sram_base);
509603
fvmap_copy_from_sram(map_base, sram_base);
510604

0 commit comments

Comments
 (0)