vpu: add vpu support for g12a

PD#156734: vpu: add vpu support for g12a

Change-Id: I65f559e34408a6c2ecf2ff8b34a3fe1f9d1e440a
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
This commit is contained in:
Evoke Zhang
2017-12-29 22:11:10 +08:00
committed by Yixun Lan
parent 294a05a220
commit 231a12fb9c
13 changed files with 271 additions and 78 deletions

View File

@@ -208,7 +208,7 @@
&clkc CLKID_VPU_P1_MUX
&clkc CLKID_VPU_MUX>;
clock-names = "vapb_clk",
"vpu_intr",
"vpu_intr_gate",
"vpu_clk0",
"vpu_clk1",
"vpu_clk";

View File

@@ -430,7 +430,7 @@
<&clkc CLKID_VPU_P1_COMP>,
<&clkc CLKID_VPU_MUX>;
clock-names = "vapb_clk",
"vpu_intr",
"vpu_intr_gate",
"vpu_clk0",
"vpu_clk1",
"vpu_clk";

View File

@@ -430,7 +430,7 @@
<&clkc CLKID_VPU_P1_COMP>,
<&clkc CLKID_VPU_MUX>;
clock-names = "vapb_clk",
"vpu_intr",
"vpu_intr_gate",
"vpu_clk0",
"vpu_clk1",
"vpu_clk";

View File

@@ -426,7 +426,7 @@
<&clkc CLKID_VPU_P1_COMP>,
<&clkc CLKID_VPU_MUX>;
clock-names = "vapb_clk",
"vpu_intr",
"vpu_intr_gate",
"vpu_clk0",
"vpu_clk1",
"vpu_clk";

View File

@@ -426,7 +426,7 @@
<&clkc CLKID_VPU_P1_COMP>,
<&clkc CLKID_VPU_MUX>;
clock-names = "vapb_clk",
"vpu_intr",
"vpu_intr_gate",
"vpu_clk0",
"vpu_clk1",
"vpu_clk";

View File

@@ -199,6 +199,25 @@
cpuinfo_cmd = <0x82000044>;
};
vpu {
compatible = "amlogic, vpu-g12a";
dev_name = "vpu";
status = "okay";
clocks = <&clkc CLKID_VAPB_MUX>,
<&clkc CLKID_VPU_INTR>,
<&clkc CLKID_VPU_P0_COMP>,
<&clkc CLKID_VPU_P1_COMP>,
<&clkc CLKID_VPU_MUX>;
clock-names = "vapb_clk",
"vpu_intr_gate",
"vpu_clk0",
"vpu_clk1",
"vpu_clk";
clk_level = <7>;
/* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */
/* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */
};
pinctrl_aobus: pinctrl@ff800014{
compatible = "amlogic,meson-g12a-aobus-pinctrl";
#address-cells = <2>;

View File

@@ -287,7 +287,7 @@
<&clkc CLKID_VPU_P1_COMP>,
<&clkc CLKID_VPU_MUX>;
clock-names = "vapb_clk",
"vpu_intr",
"vpu_intr_gate",
"gp_pll",
"vpu_clk0",
"vpu_clk1",

View File

@@ -370,7 +370,7 @@
<&clkc CLKID_VPU_P1_COMP>,
<&clkc CLKID_VPU_MUX>;
clock-names = "vapb_clk",
"vpu_intr",
"vpu_intr_gate",
"gp_pll",
"vpu_clk0",
"vpu_clk1",

View File

@@ -286,7 +286,7 @@
<&clkc CLKID_VPU_P1_COMP>,
<&clkc CLKID_VPU_MUX>;
clock-names = "vapb_clk",
"vpu_intr",
"vpu_intr_gate",
"gp_pll",
"vpu_clk0",
"vpu_clk1",

View File

@@ -36,7 +36,8 @@
/* v01: initial version */
/* v02: add axg support */
/* v03: add txlx support */
#define VPU_VERION "v03"
/* v04: add g12a support */
#define VPU_VERION "v04"
int vpu_debug_print_flag;
static spinlock_t vpu_mem_lock;
@@ -93,7 +94,7 @@ static unsigned int get_vpu_clk_level(unsigned int video_clk)
int i;
for (i = 0; i < vpu_conf.data->clk_level_max; i++) {
if (video_clk <= vpu_clk_table[i][0])
if (video_clk <= vpu_clk_table[i].freq)
break;
}
clk_level = i;
@@ -101,46 +102,93 @@ static unsigned int get_vpu_clk_level(unsigned int video_clk)
return clk_level;
}
unsigned int get_vpu_clk(void)
static unsigned int get_fclk_div_freq(unsigned int mux_id)
{
unsigned long clk_freq;
unsigned long fclk, clk_source;
unsigned long mux, div;
struct fclk_div_s *fclk_div;
unsigned int fclk, div, clk_source = 0;
unsigned int i;
fclk = CLK_FPLL_FREQ * 1000000;
mux = vpu_hiu_getb(HHI_VPU_CLK_CNTL, 9, 3);
switch (mux) {
case FCLK_DIV4:
case FCLK_DIV3:
case FCLK_DIV5:
case FCLK_DIV7:
clk_source = ((fclk * 100 / fclk_div_table[mux]) + 99) / 100;
break;
case GPLL_CLK:
clk_source = vpu_clk_table[8][0];
break;
default:
clk_source = 0;
break;
for (i = 0; i < FCLK_DIV_MAX; i++) {
fclk_div = vpu_conf.data->fclk_div_table + i;
if (fclk_div->fclk_id == mux_id) {
div = fclk_div->fclk_div;
clk_source = fclk / div;
break;
}
if (fclk_div->fclk_id == FCLK_DIV_MAX)
break;
}
div = vpu_hiu_getb(HHI_VPU_CLK_CNTL, 0, 7) + 1;
clk_freq = ((clk_source * 100 / div) + 99) / 100;
return clk_source;
}
return (unsigned int)clk_freq;
static unsigned int get_vpu_clk_mux_id(void)
{
struct fclk_div_s *fclk_div;
unsigned int i, mux, mux_id;
mux = vpu_hiu_getb(HHI_VPU_CLK_CNTL, 9, 3);
mux_id = mux;
for (i = 0; i < FCLK_DIV_MAX; i++) {
fclk_div = vpu_conf.data->fclk_div_table + i;
if (fclk_div->fclk_mux == mux) {
mux_id = fclk_div->fclk_id;
break;
}
if (fclk_div->fclk_id == FCLK_DIV_MAX)
break;
}
return mux_id;
}
unsigned int get_vpu_clk(void)
{
unsigned int clk_freq;
unsigned int clk_source, div;
unsigned int mux_id;
if (IS_ERR_OR_NULL(vpu_conf.vpu_clk)) {
VPUERR("%s: vpu_clk\n", __func__);
mux_id = get_vpu_clk_mux_id();
switch (mux_id) {
case FCLK_DIV4:
case FCLK_DIV3:
case FCLK_DIV5:
case FCLK_DIV7:
clk_source = get_fclk_div_freq(mux_id);
break;
case GPLL_CLK:
clk_source = vpu_clk_table[8].freq;
break;
default:
clk_source = 0;
break;
}
div = vpu_hiu_getb(HHI_VPU_CLK_CNTL, 0, 7) + 1;
clk_freq = clk_source / div;
return clk_freq;
}
clk_freq = clk_get_rate(vpu_conf.vpu_clk);
return clk_freq;
}
static int switch_gp_pll(int flag)
{
unsigned int clk;
if ((vpu_conf.gp_pll == NULL) || (IS_ERR(vpu_conf.gp_pll))) {
if (IS_ERR_OR_NULL(vpu_conf.gp_pll)) {
VPUERR("%s: gp_pll\n", __func__);
return -1;
}
if (flag) { /* enable */
clk = vpu_clk_table[8][0];
clk = vpu_clk_table[8].freq;
clk_set_rate(vpu_conf.gp_pll, clk);
clk_prepare_enable(vpu_conf.gp_pll);
} else { /* disable */
@@ -152,15 +200,14 @@ static int switch_gp_pll(int flag)
static int adjust_vpu_clk(unsigned int clk_level)
{
unsigned int mux, clk;
unsigned int clk;
int ret = 0;
ret = vpu_chip_valid_check();
if (ret)
return -1;
mux = vpu_clk_table[vpu_conf.clk_level][1];
if (mux == GPLL_CLK) {
if (vpu_clk_table[vpu_conf.clk_level].mux == GPLL_CLK) {
if (vpu_conf.data->gp_pll_valid == 0) {
VPUERR("gp_pll is invalid\n");
return -1;
@@ -173,9 +220,9 @@ static int adjust_vpu_clk(unsigned int clk_level)
}
}
if ((IS_ERR(vpu_conf.vpu_clk0)) ||
(IS_ERR(vpu_conf.vpu_clk1)) ||
(IS_ERR(vpu_conf.vpu_clk))) {
if ((IS_ERR_OR_NULL(vpu_conf.vpu_clk0)) ||
(IS_ERR_OR_NULL(vpu_conf.vpu_clk1)) ||
(IS_ERR_OR_NULL(vpu_conf.vpu_clk))) {
VPUERR("%s: vpu_clk\n", __func__);
return -1;
}
@@ -183,12 +230,12 @@ static int adjust_vpu_clk(unsigned int clk_level)
vpu_conf.clk_level = clk_level;
/* step 1: switch to 2nd vpu clk patch */
clk = vpu_clk_table[vpu_conf.data->clk_level_dft][0];
clk = vpu_clk_table[vpu_conf.data->clk_level_dft].freq;
clk_set_rate(vpu_conf.vpu_clk1, clk);
clk_set_parent(vpu_conf.vpu_clk, vpu_conf.vpu_clk1);
udelay(10);
/* step 2: adjust 1st vpu clk frequency */
clk = vpu_clk_table[vpu_conf.clk_level][0];
clk = vpu_clk_table[vpu_conf.clk_level].freq;
clk_set_rate(vpu_conf.vpu_clk0, clk);
udelay(20);
/* step 3: switch back to 1st vpu clk patch */
@@ -196,7 +243,7 @@ static int adjust_vpu_clk(unsigned int clk_level)
clk = clk_get_rate(vpu_conf.vpu_clk);
VPUPR("set vpu clk: %uHz(%d), readback: %uHz(0x%x)\n",
vpu_clk_table[vpu_conf.clk_level][0], vpu_conf.clk_level,
vpu_clk_table[vpu_conf.clk_level].freq, vpu_conf.clk_level,
clk, (vpu_hiu_read(HHI_VPU_CLK_CNTL)));
return ret;
@@ -205,7 +252,7 @@ static int adjust_vpu_clk(unsigned int clk_level)
static int set_vpu_clk(unsigned int vclk)
{
int ret = 0;
unsigned int clk_level;
unsigned int clk_level, clk;
mutex_lock(&vpu_clk_mutex);
@@ -227,7 +274,9 @@ static int set_vpu_clk(unsigned int vclk)
#endif
}
if (get_vpu_clk() != vpu_clk_table[clk_level][0])
clk = get_vpu_clk();
if ((clk > (vpu_clk_table[clk_level].freq + VPU_CLK_TOLERANCE)) ||
(clk < (vpu_clk_table[clk_level].freq - VPU_CLK_TOLERANCE)))
ret = adjust_vpu_clk(clk_level);
set_vpu_clk_limit:
@@ -269,7 +318,7 @@ unsigned int get_vpu_clk_vmod(unsigned int vmod)
if (vmod < VPU_MOD_MAX) {
vpu_clk = vpu_conf.clk_vmod[vmod];
vpu_clk = vpu_clk_table[vpu_clk][0];
vpu_clk = vpu_clk_table[vpu_clk].freq;
} else {
vpu_clk = 0;
VPUERR("invalid vmod\n");
@@ -333,7 +382,7 @@ int request_vpu_clk_vmod(unsigned int vclk, unsigned int vmod)
if (vpu_debug_print_flag) {
VPUPR("request vpu clk: %s %uHz\n",
vpu_mod_table[vmod],
vpu_clk_table[clk_level][0]);
vpu_clk_table[clk_level].freq);
dump_stack();
}
@@ -601,6 +650,10 @@ void switch_vpu_clk_gate_vmod(unsigned int vmod, int flag)
/* *********************************************** */
static const char *vpu_usage_str = {
"Usage:\n"
" echo w <reg> <data> > reg ; write data to vcbus reg\n"
" echo r <reg> > reg ; read vcbus reg\n"
" echo d <reg> <num> > reg ; dump vcbus regs\n"
"\n"
" echo r > mem ; read vpu memory power down status\n"
" echo w <vmod> <flag> > mem ; write vpu memory power down\n"
" <flag>: 0=power up, 1=power down\n"
@@ -640,7 +693,8 @@ static ssize_t vpu_clk_debug(struct class *class, struct class_attribute *attr,
switch (buf[0]) {
case 'g': /* get */
VPUPR("get current clk: %uHz\n", get_vpu_clk());
VPUPR("get current clk: %uHz(0x%08x)\n",
get_vpu_clk(), (vpu_hiu_read(HHI_VPU_CLK_CNTL)));
break;
case 's': /* set */
tmp[0] = 4;
@@ -683,12 +737,12 @@ static ssize_t vpu_clk_debug(struct class *class, struct class_attribute *attr,
if (ret == 1) {
VPUPR("clk holdings:\n");
pr_info("%s: %uHz(%u)\n", vpu_mod_table[tmp[0]],
vpu_clk_table[vpu_conf.clk_vmod[tmp[0]]][0],
vpu_clk_table[vpu_conf.clk_vmod[tmp[0]]].freq,
vpu_conf.clk_vmod[tmp[0]]);
} else {
n = get_vpu_clk_level_max_vmod();
VPUPR("clk max holdings: %uHz(%u)\n",
vpu_clk_table[n][0], n);
vpu_clk_table[n].freq, n);
}
break;
default:
@@ -845,7 +899,10 @@ static ssize_t vpu_debug_info(struct class *class,
{
unsigned int level_max, clk;
ssize_t len = 0;
int i, ret;
int ret;
#ifdef CONFIG_VPU_DYNAMIC_ADJ
int i;
#endif
ret = vpu_chip_valid_check();
if (ret) {
@@ -853,11 +910,7 @@ static ssize_t vpu_debug_info(struct class *class,
return len;
}
if (IS_ERR(vpu_conf.vpu_clk)) {
VPUERR("%s: vpu_clk\n", __func__);
clk = get_vpu_clk();
} else
clk = clk_get_rate(vpu_conf.vpu_clk);
clk = get_vpu_clk();
level_max = vpu_conf.data->clk_level_max - 1;
len = sprintf(buf, "driver version: %s(%d-%s)\n",
@@ -869,10 +922,10 @@ static ssize_t vpu_debug_info(struct class *class,
"clk_level dft: %d(%dHz)\n"
"clk_level max: %d(%dHz)\n\n",
clk,
vpu_conf.clk_level, vpu_clk_table[vpu_conf.clk_level][0],
vpu_conf.clk_level, vpu_clk_table[vpu_conf.clk_level].freq,
vpu_conf.data->clk_level_dft,
vpu_clk_table[vpu_conf.data->clk_level_dft][0],
level_max, vpu_clk_table[level_max][0]);
vpu_clk_table[vpu_conf.data->clk_level_dft].freq,
level_max, vpu_clk_table[level_max].freq);
len += sprintf(buf+len, "mem_pd:\n"
" mem_pd0: 0x%08x\n",
@@ -886,6 +939,7 @@ static ssize_t vpu_debug_info(struct class *class,
vpu_hiu_read(HHI_VPU_MEM_PD_REG2));
}
#ifdef CONFIG_VPU_DYNAMIC_ADJ
if (vpu_conf.clk_vmod) {
len += sprintf(buf+len, "\nclk_vmod:\n");
for (i = 0; i < VPU_MOD_MAX; i++) {
@@ -893,17 +947,69 @@ static ssize_t vpu_debug_info(struct class *class,
i, vpu_conf.clk_vmod[i]);
}
}
#endif
len += sprintf(buf+len, "\n");
return len;
}
static ssize_t vpu_debug_reg_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
int ret = 0;
unsigned int reg32 = 0, data32 = 0;
int i;
switch (buf[0]) {
case 'w':
ret = sscanf(buf, "w %x %x", &reg32, &data32);
if (ret == 2) {
vpu_vcbus_write(reg32, data32);
pr_info("write vcbus[0x%04x]=0x%08x, readback 0x%08x\n",
reg32, data32, vpu_vcbus_read(reg32));
} else {
pr_info("invalid data\n");
return -EINVAL;
}
break;
case 'r':
ret = sscanf(buf, "r %x", &reg32);
if (ret == 1) {
pr_info("read vcbus[0x%04x] = 0x%08x\n",
reg32, vpu_vcbus_read(reg32));
} else {
pr_info("invalid data\n");
return -EINVAL;
}
break;
case 'd':
ret = sscanf(buf, "d %x %d", &reg32, &data32);
if (ret == 2) {
pr_info("dump vcbus regs:\n");
for (i = 0; i < data32; i++) {
pr_info("[0x%04x] = 0x%08x\n",
(reg32 + i), vpu_vcbus_read(reg32 + i));
}
} else {
pr_info("invalid data\n");
return -EINVAL;
}
break;
default:
pr_info("wrong command\n");
break;
}
return count;
}
static struct class_attribute vpu_debug_class_attrs[] = {
__ATTR(clk, 0644, vpu_debug_help, vpu_clk_debug),
__ATTR(mem, 0644, vpu_debug_help, vpu_mem_debug),
__ATTR(gate, 0644, vpu_debug_help, vpu_clk_gate_debug),
__ATTR(test, 0644, vpu_debug_help, vpu_test_debug),
__ATTR(print, 0644, vpu_debug_help, vpu_print_debug),
__ATTR(reg, 0644, vpu_debug_help, vpu_debug_reg_store),
__ATTR(info, 0444, vpu_debug_info, NULL),
__ATTR(help, 0444, vpu_debug_help, NULL),
};
@@ -914,7 +1020,7 @@ static int creat_vpu_debug_class(void)
int i;
vpu_debug_class = class_create(THIS_MODULE, "vpu");
if (IS_ERR(vpu_debug_class)) {
if (IS_ERR_OR_NULL(vpu_debug_class)) {
VPUERR("create vpu_debug_class failed\n");
return -1;
}
@@ -944,11 +1050,16 @@ static int remove_vpu_debug_class(void)
#ifdef CONFIG_PM
static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
{
VPUPR("suspend clk: %uHz(0x%x)\n",
get_vpu_clk(), (vpu_hiu_read(HHI_VPU_CLK_CNTL)));
return 0;
}
static int vpu_resume(struct platform_device *pdev)
{
VPUPR("resume clk: %uHz(0x%x)\n",
get_vpu_clk(), (vpu_hiu_read(HHI_VPU_CLK_CNTL)));
set_vpu_clk(vpu_conf.clk_level);
return 0;
}
#endif
@@ -977,7 +1088,7 @@ static int get_vpu_config(struct platform_device *pdev)
vpu_conf.clk_level = val;
}
VPUPR("load vpu_clk: %uHz(%u)\n",
vpu_clk_table[val][0], vpu_conf.clk_level);
vpu_clk_table[val].freq, vpu_conf.clk_level);
return ret;
}
@@ -988,20 +1099,20 @@ static void vpu_clktree_init(struct device *dev)
/* init & enable vapb_clk */
clk_vapb = devm_clk_get(dev, "vapb_clk");
if (IS_ERR(clk_vapb))
if (IS_ERR_OR_NULL(clk_vapb))
VPUERR("%s: vapb_clk\n", __func__);
else
clk_prepare_enable(clk_vapb);
clk_vpu_intr = devm_clk_get(dev, "vpu_intr");
if (IS_ERR(clk_vpu_intr))
VPUERR("%s: vpu_intr\n", __func__);
clk_vpu_intr = devm_clk_get(dev, "vpu_intr_gate");
if (IS_ERR_OR_NULL(clk_vpu_intr))
VPUERR("%s: vpu_intr_gate\n", __func__);
else
clk_prepare_enable(clk_vpu_intr);
if (vpu_conf.data->gp_pll_valid) {
vpu_conf.gp_pll = devm_clk_get(dev, "gp_pll");
if (IS_ERR(vpu_conf.gp_pll))
if (IS_ERR_OR_NULL(vpu_conf.gp_pll))
VPUERR("%s: gp_pll\n", __func__);
}
@@ -1009,9 +1120,9 @@ static void vpu_clktree_init(struct device *dev)
vpu_conf.vpu_clk0 = devm_clk_get(dev, "vpu_clk0");
vpu_conf.vpu_clk1 = devm_clk_get(dev, "vpu_clk1");
vpu_conf.vpu_clk = devm_clk_get(dev, "vpu_clk");
if ((IS_ERR(vpu_conf.vpu_clk0)) ||
(IS_ERR(vpu_conf.vpu_clk1)) ||
(IS_ERR(vpu_conf.vpu_clk))) {
if ((IS_ERR_OR_NULL(vpu_conf.vpu_clk0)) ||
(IS_ERR_OR_NULL(vpu_conf.vpu_clk1)) ||
(IS_ERR_OR_NULL(vpu_conf.vpu_clk))) {
VPUERR("%s: vpu_clk\n", __func__);
} else {
clk_set_parent(vpu_conf.vpu_clk, vpu_conf.vpu_clk0);
@@ -1026,6 +1137,8 @@ static struct vpu_data_s vpu_data_gxb = {
.chip_name = "gxbb",
.clk_level_dft = CLK_LEVEL_DFT_GXBB,
.clk_level_max = CLK_LEVEL_MAX_GXBB,
.fclk_div_table = fclk_div_table_gxb,
.gp_pll_valid = 1,
.mem_pd_reg1_valid = 1,
.mem_pd_reg2_valid = 0,
@@ -1043,6 +1156,8 @@ static struct vpu_data_s vpu_data_gxtvbb = {
.chip_name = "gxtvbb",
.clk_level_dft = CLK_LEVEL_DFT_GXTVBB,
.clk_level_max = CLK_LEVEL_MAX_GXTVBB,
.fclk_div_table = fclk_div_table_gxb,
.gp_pll_valid = 1,
.mem_pd_reg1_valid = 1,
.mem_pd_reg2_valid = 0,
@@ -1060,6 +1175,8 @@ static struct vpu_data_s vpu_data_gxl = {
.chip_name = "gxl",
.clk_level_dft = CLK_LEVEL_DFT_GXL,
.clk_level_max = CLK_LEVEL_MAX_GXL,
.fclk_div_table = fclk_div_table_gxb,
.gp_pll_valid = 1,
.mem_pd_reg1_valid = 1,
.mem_pd_reg2_valid = 1,
@@ -1077,6 +1194,8 @@ static struct vpu_data_s vpu_data_gxm = {
.chip_name = "gxm",
.clk_level_dft = CLK_LEVEL_DFT_GXM,
.clk_level_max = CLK_LEVEL_MAX_GXM,
.fclk_div_table = fclk_div_table_gxb,
.gp_pll_valid = 1,
.mem_pd_reg1_valid = 1,
.mem_pd_reg2_valid = 1,
@@ -1094,6 +1213,8 @@ static struct vpu_data_s vpu_data_txlx = {
.chip_name = "txlx",
.clk_level_dft = CLK_LEVEL_DFT_TXLX,
.clk_level_max = CLK_LEVEL_MAX_TXLX,
.fclk_div_table = fclk_div_table_gxb,
.gp_pll_valid = 1,
.mem_pd_reg1_valid = 1,
.mem_pd_reg2_valid = 1,
@@ -1111,6 +1232,8 @@ static struct vpu_data_s vpu_data_axg = {
.chip_name = "axg",
.clk_level_dft = CLK_LEVEL_DFT_AXG,
.clk_level_max = CLK_LEVEL_MAX_AXG,
.fclk_div_table = fclk_div_table_gxb,
.gp_pll_valid = 0,
.mem_pd_reg1_valid = 0,
.mem_pd_reg2_valid = 0,
@@ -1123,6 +1246,25 @@ static struct vpu_data_s vpu_data_axg = {
.clk_gate_table = vpu_clk_gate_axg,
};
static struct vpu_data_s vpu_data_g12a = {
.chip_type = VPU_CHIP_G12A,
.chip_name = "g12a",
.clk_level_dft = CLK_LEVEL_DFT_G12A,
.clk_level_max = CLK_LEVEL_MAX_G12A,
.fclk_div_table = fclk_div_table_g12a,
.gp_pll_valid = 0,
.mem_pd_reg1_valid = 1,
.mem_pd_reg2_valid = 1,
.mem_pd_table_cnt =
sizeof(vpu_mem_pd_gxl) / sizeof(struct vpu_ctrl_s),
.clk_gate_table_cnt =
sizeof(vpu_clk_gate_gxl) / sizeof(struct vpu_ctrl_s),
.mem_pd_table = vpu_mem_pd_gxl,
.clk_gate_table = vpu_clk_gate_gxl,
};
static const struct of_device_id vpu_of_table[] = {
{
.compatible = "amlogic, vpu-gxbb",
@@ -1148,6 +1290,10 @@ static const struct of_device_id vpu_of_table[] = {
.compatible = "amlogic, vpu-axg",
.data = &vpu_data_axg,
},
{
.compatible = "amlogic, vpu-g12a",
.data = &vpu_data_g12a,
},
{},
};

View File

@@ -32,9 +32,22 @@ enum vpu_chip_e {
VPU_CHIP_GXM,
VPU_CHIP_TXLX,
VPU_CHIP_AXG,
VPU_CHIP_G12A,
VPU_CHIP_MAX,
};
struct fclk_div_s {
unsigned int fclk_id;
unsigned int fclk_mux;
unsigned int fclk_div;
};
struct vpu_clk_s {
unsigned int freq;
unsigned int mux;
unsigned int div;
};
struct vpu_ctrl_s {
unsigned int vmod;
unsigned int reg;
@@ -47,6 +60,7 @@ struct vpu_data_s {
const char *chip_name;
unsigned char clk_level_dft;
unsigned char clk_level_max;
struct fclk_div_s *fclk_div_table;
unsigned char gp_pll_valid;
unsigned char mem_pd_reg1_valid;

View File

@@ -60,6 +60,11 @@
#define CLK_LEVEL_DFT_AXG 3
#define CLK_LEVEL_MAX_AXG 4
/* G12A */
/* freq max=666M, default=666M */
#define CLK_LEVEL_DFT_G12A 7
#define CLK_LEVEL_MAX_G12A 8
/* vpu clk setting */
enum vpu_mux_e {
FCLK_DIV4 = 0,
@@ -70,17 +75,29 @@ enum vpu_mux_e {
VID_PLL_CLK,
VID2_PLL_CLK,
GPLL_CLK,
FCLK_DIV_MAX,
};
static unsigned int fclk_div_table[] = {
4, /* mux 0 */
3, /* mux 1 */
5, /* mux 2 */
7, /* mux 3 */
2, /* invalid */
static struct fclk_div_s fclk_div_table_gxb[] = {
/* id, mux, div */
{FCLK_DIV4, 0, 4},
{FCLK_DIV3, 1, 3},
{FCLK_DIV5, 2, 5},
{FCLK_DIV7, 3, 7},
{FCLK_DIV_MAX, 8, 1},
};
static unsigned int vpu_clk_table[10][3] = {
static struct fclk_div_s fclk_div_table_g12a[] = {
/* id, mux, div */
{FCLK_DIV3, 0, 3},
{FCLK_DIV4, 1, 4},
{FCLK_DIV5, 2, 5},
{FCLK_DIV7, 3, 7},
{FCLK_DIV_MAX, 8, 1},
};
#define VPU_CLK_TOLERANCE 1000000 /* Hz */
static struct vpu_clk_s vpu_clk_table[] = {
/* frequency clk_mux div */
{100000000, FCLK_DIV5, 3}, /* 0 */
{166666667, FCLK_DIV3, 3}, /* 1 */

View File

@@ -76,9 +76,6 @@ static char *vpu_mod_table[] = {
"none",
"none",
"none",
"none",
"none",
"none",
};
#endif