diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index 264925381deb..bda868058e9c 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -65,7 +65,7 @@ static struct early_suspend aocec_suspend_handler; #define CEC_FRAME_DELAY msecs_to_jiffies(400) -#define CEC_DEV_NAME "aocec" +#define CEC_DEV_NAME "cec" #define CEC_POWER_ON (0 << 0) #define CEC_EARLY_SUSPEND (1 << 0) @@ -484,6 +484,49 @@ static inline void cecrx_clear_irq(unsigned int flags) writel(flags, cec_dev->cec_reg + AO_CECB_INTR_CLR); } +/* max length = 14+1 */ +#define OSD_NAME_DEV 1 +const uint8_t dev_osd_name[1][16] = { + {1, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x63, 0x61, 0x73, 0x74}, +}; + +const uint8_t dev_vendor_id[1][3] = { + {0, 0, 0}, +}; + +static bool cec_message_op(unsigned char *msg, unsigned char len) +{ + int i, j; + + if (((msg[0] & 0xf0) >> 4) == cec_dev->cec_info.log_addr) { + CEC_ERR("bad iniator with self:%s", msg_log_buf); + return false; + } + switch (msg[1]) { + case 0x47: + /* OSD name */ + if (len > 16) + break; + for (j = 0; j < OSD_NAME_DEV; j++) { + for (i = 2; i < len; i++) { + if (msg[i] != dev_osd_name[j][i-1]) + break; + } + if (i == len) { + cec_set_dev_info(dev_osd_name[j][0]); + CEC_INFO("specific dev:%d", dev_osd_name[j][0]); + } + } + break; + case 0x87: + /* verdor ID */ + break; + default: + break; + } + return true; +} + static int cecb_pick_msg(unsigned char *msg, unsigned char *out_len) { int i, size; @@ -500,11 +543,10 @@ static int cecb_pick_msg(unsigned char *msg, unsigned char *out_len) /* clr CEC lock bit */ hdmirx_cec_write(DWC_CEC_LOCK, 0); CEC_INFO("%s", msg_log_buf); - if (((msg[0] & 0xf0) >> 4) == cec_dev->cec_info.log_addr) { - *out_len = 0; - CEC_ERR("bad iniator with self:%s", msg_log_buf); - } else + if (cec_message_op(msg, len)) *out_len = len; + else + *out_len = 0; pin_status = 1; return 0; } @@ -521,6 +563,8 @@ void cecb_irq_handle(void) /* clear irq */ if (intr_cec != 0) cecrx_clear_irq(intr_cec); + else + CEC_INFO_L(L_1, "err cec intsts:0\n"); if (cec_dev->plat_data->ee_to_ao) shift = 16; @@ -654,7 +698,7 @@ static void ao_cecb_init(void) /* Release SW reset */ cec_set_reg_bits(AO_CECB_GEN_CNTL, 0, 0, 1); - if (cec_dev->plat_data->chip_id >= CEC_CHIP_ID_TL1) { + if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) { reg = 0; reg |= (0 << 6);/*curb_err_init*/ reg |= (0 << 5);/*en_chk_sbitlow*/ @@ -2627,11 +2671,6 @@ static ssize_t hdmitx_cec_write(struct file *f, const char __user *buf, if (cec_cfg & CEC_FUNC_CFG_CEC_ON) { /*cec module on*/ ret = cec_ll_tx(tempbuf, size); - if (ret == CEC_FAIL_NACK) { - return -1; - } else { - return size; - } } else { CEC_ERR("err:cec module disabled\n"); } @@ -3016,7 +3055,9 @@ static char *aml_cec_class_devnode(struct device *dev, umode_t *mode) { if (mode) { *mode = 0666; - } + CEC_INFO("mode is %x\n", *mode); + } else + CEC_INFO("mode is null\n"); return NULL; } diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index e5f5fbb95f71..5613c5cf66f3 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -23,7 +23,7 @@ #define CEC_DRIVER_VERSION "Ver 2019/3/25\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) -#define CEC_DEV_NAME "aocec" +#define CEC_DEV_NAME "cec" #define CEC_EARLY_SUSPEND (1 << 0) #define CEC_DEEP_SUSPEND (1 << 1) @@ -494,7 +494,8 @@ extern uint32_t hdmirx_rd_dwc(uint16_t addr); extern void hdmirx_wr_dwc(uint16_t addr, uint32_t data); extern unsigned int rd_reg_hhi(unsigned int offset); extern void wr_reg_hhi(unsigned int offset, unsigned int val); - +extern int cec_set_dev_info(uint8_t dev_idx); +int __attribute__((weak))cec_set_dev_info(uint8_t dev_idx); #else static inline unsigned long hdmirx_rd_top(unsigned long addr) { diff --git a/drivers/amlogic/cpufreq/meson-cpufreq.c b/drivers/amlogic/cpufreq/meson-cpufreq.c index 2f0c26edfd3f..019ab621d695 100644 --- a/drivers/amlogic/cpufreq/meson-cpufreq.c +++ b/drivers/amlogic/cpufreq/meson-cpufreq.c @@ -43,6 +43,16 @@ #include "../../base/power/opp/opp.h" #include "meson-cpufreq.h" +#ifdef CONFIG_ARCH_MESON64_ODROIDN2 +#define OF_NODE_CPU_OPP_0 "/cpu_opp_table0/" /* Core A53 */ +#define OF_NODE_CPU_OPP_1 "/cpu_opp_table1/" /* Core A73 */ + +static unsigned long max_freq[2] = { + 1896000, /* defalut freq for A53 is 1.896GHz */ + 1800000 /* defalut freq for A73 is 1.800GHz */ +}; +#endif + static unsigned int meson_cpufreq_get_rate(unsigned int cpu) { @@ -261,7 +271,10 @@ static int meson_cpufreq_set_target(struct cpufreq_policy *policy, } } + freqs.old = freq_old / 1000; + freqs.new = freq_new / 1000; /*scale clock frequency*/ + cpufreq_freq_transition_begin(policy, &freqs); ret = meson_cpufreq_set_rate(policy, cur_cluster, freq_new / 1000); if (ret) { @@ -274,6 +287,7 @@ static int meson_cpufreq_set_target(struct cpufreq_policy *policy, } return ret; } + cpufreq_freq_transition_end(policy, &freqs, ret); /*cpufreq down,change voltage after frequency*/ if (freq_new < freq_old) { ret = meson_regulator_set_volate(cpu_reg, volt_old, @@ -281,8 +295,12 @@ static int meson_cpufreq_set_target(struct cpufreq_policy *policy, if (ret) { pr_err("failed to scale volt %u %u down: %d\n", volt_new, volt_tol, ret); - meson_cpufreq_set_rate(policy, cur_cluster, + freqs.old = freq_new / 1000; + freqs.new = freq_old / 1000; + cpufreq_freq_transition_begin(policy, &freqs); + ret = meson_cpufreq_set_rate(policy, cur_cluster, freq_old / 1000); + cpufreq_freq_transition_end(policy, &freqs, ret); } } @@ -368,6 +386,69 @@ int choose_cpufreq_tables_index(const struct device_node *np, u32 cur_cluster) return ret; } + +static int meson_cpufreq_transition_notifier(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = data; + struct meson_cpufreq_driver_data *cpufreq_data = + to_meson_dvfs_cpu_nb(nb); + struct cpufreq_policy *policy = cpufreq_data->policy; + struct clk *dsu_clk = cpufreq_data->clk_dsu; + struct clk *dsu_cpu_parent = policy->clk; + struct clk *dsu_pre_parent = cpufreq_data->clk_dsu_pre; + int ret = 0; + static bool first_set = true; + + if (!dsu_clk || !dsu_cpu_parent || !dsu_pre_parent) + return 0; + + pr_debug("%s,event %ld,freq->old_rate =%u,freq->new_rate =%u!\n", + __func__, val, freq->old, freq->new); + switch (val) { + case CPUFREQ_PRECHANGE: + if (freq->new > MID_RATE) { + pr_debug("%s,dsu clk switch parent to dsu pre!\n", + __func__); + if (first_set) { + clk_set_rate(dsu_pre_parent, MID_RATE * 1000); + first_set = false; + pr_info("first set gp1 pll to 1.5G!\n"); + } + if (__clk_get_enable_count(dsu_pre_parent) == 0) { + ret = clk_prepare_enable(dsu_pre_parent); + if (ret) { + pr_err("%s: CPU%d gp1 pll enable failed\n", + __func__, policy->cpu); + return ret; + } + } + + ret = clk_set_parent(dsu_clk, dsu_pre_parent); + } + + return ret; + case CPUFREQ_POSTCHANGE: + if (freq->new <= MID_RATE) { + pr_debug("%s,dsu clk switch parent to cpu!\n", + __func__); + ret = clk_set_parent(dsu_clk, dsu_cpu_parent); + if (__clk_get_enable_count(dsu_pre_parent) >= 1) + clk_disable_unprepare(dsu_pre_parent); + + } + + return ret; + default: + return 0; + } + return 0; +} + +static struct notifier_block meson_cpufreq_notifier_block = { + .notifier_call = meson_cpufreq_transition_notifier, +}; + /* CPU initialization */ static int meson_cpufreq_init(struct cpufreq_policy *policy) { @@ -377,10 +458,14 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) struct regulator *cpu_reg = NULL; struct meson_cpufreq_driver_data *cpufreq_data; struct clk *low_freq_clk_p, *high_freq_clk_p = NULL; + struct clk *dsu_clk, *dsu_pre_parent; unsigned int transition_latency = CPUFREQ_ETERNAL; unsigned int volt_tol = 0; unsigned long freq_hz = 0; int cpu = 0, ret = 0, tables_index; +#ifdef CONFIG_ARCH_MESON64_ODROIDN2 + int i = 0; +#endif if (!policy) { pr_err("invalid cpufreq_policy\n"); @@ -441,6 +526,18 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) goto free_clk; } + dsu_clk = of_clk_get_by_name(np, DSU_CLK); + if (IS_ERR(dsu_clk)) { + dsu_clk = NULL; + pr_debug("%s: ignor dsu clk!\n", __func__); + } + + dsu_pre_parent = of_clk_get_by_name(np, DSU_PRE_PARENT); + if (IS_ERR(dsu_pre_parent)) { + dsu_pre_parent = NULL; + pr_debug("%s: ignor dsu pre parent clk!\n", __func__); + } + cpu_reg = devm_regulator_get(cpu_dev, CORE_SUPPLY); if (IS_ERR(cpu_reg)) { pr_err("%s:failed to get regulator, %ld\n", __func__, @@ -495,11 +592,22 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) if (of_property_read_u32(np, "clock-latency", &transition_latency)) policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + cpufreq_data->freq_transition = meson_cpufreq_notifier_block; + ret = cpufreq_register_notifier(&cpufreq_data->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); + if (ret) { + dev_err(cpu_dev, "failed to register cpufreq notifier!\n"); + goto fail_cpufreq_unregister; + } + cpufreq_data->cpu_dev = cpu_dev; cpufreq_data->low_freq_clk_p = low_freq_clk_p; cpufreq_data->high_freq_clk_p = high_freq_clk_p; + cpufreq_data->clk_dsu = dsu_clk; + cpufreq_data->clk_dsu_pre = dsu_pre_parent; cpufreq_data->reg = cpu_reg; cpufreq_data->volt_tol = volt_tol; + cpufreq_data->policy = policy; policy->driver_data = cpufreq_data; policy->clk = clk[cur_cluster]; policy->cpuinfo.transition_latency = transition_latency; @@ -520,6 +628,9 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu); return ret; +fail_cpufreq_unregister: + cpufreq_unregister_notifier(&cpufreq_data->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); free_opp_table: if (policy->freq_table != NULL) { dev_pm_opp_free_cpufreq_table(cpu_dev, @@ -638,7 +749,8 @@ static struct cpufreq_driver meson_cpufreq_driver = { .name = "arm-big-little", .flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY | - CPUFREQ_NEED_INITIAL_FREQ_CHECK, + CPUFREQ_NEED_INITIAL_FREQ_CHECK | + CPUFREQ_ASYNC_NOTIFICATION, .verify = cpufreq_generic_frequency_table_verify, .target_index = meson_cpufreq_set_target, .get = meson_cpufreq_get_rate, @@ -649,8 +761,6 @@ static struct cpufreq_driver meson_cpufreq_driver = { .resume = meson_cpufreq_resume, }; -static int meson_cpufreq_register_notifier(void) { return 0; } -static int meson_cpufreq_unregister_notifier(void) { return 0; } static int meson_cpufreq_probe(struct platform_device *pdev) { struct device *cpu_dev; @@ -688,14 +798,6 @@ static int meson_cpufreq_probe(struct platform_device *pdev) if (ret) { pr_err("%s: Failed registering platform driver, err: %d\n", __func__, ret); - } else { - ret = meson_cpufreq_register_notifier(); - if (ret) { - cpufreq_unregister_driver(&meson_cpufreq_driver); - } else { - pr_err("%s: Registered platform drive\n", - __func__); - } } return ret; @@ -703,8 +805,6 @@ static int meson_cpufreq_probe(struct platform_device *pdev) static int meson_cpufreq_remove(struct platform_device *pdev) { - meson_cpufreq_unregister_notifier(); - return cpufreq_unregister_driver(&meson_cpufreq_driver); } diff --git a/drivers/amlogic/cpufreq/meson-cpufreq.h b/drivers/amlogic/cpufreq/meson-cpufreq.h index be5002697042..d5508c5a3f37 100644 --- a/drivers/amlogic/cpufreq/meson-cpufreq.h +++ b/drivers/amlogic/cpufreq/meson-cpufreq.h @@ -27,6 +27,10 @@ #define CORE_CLK "core_clk" #define LOW_FREQ_CLK_PARENT "low_freq_clk_parent" #define HIGH_FREQ_CLK_PARENT "high_freq_clk_parent" +#define DSU_CLK "dsu_clk" +#define DSU_PRE_PARENT "dsu_pre_parent" +#define to_meson_dvfs_cpu_nb(_nb) container_of(_nb, \ + struct meson_cpufreq_driver_data, freq_transition) static struct clk *clk[MAX_CLUSTERS]; static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS]; @@ -38,6 +42,8 @@ static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS]; /*mid rate for set parent,Khz*/ static unsigned int mid_rate = (1000 * 1000); static unsigned int gap_rate = (10 * 1000 * 1000); +static struct cpufreq_freqs freqs; +#define MID_RATE (1500 * 1000) /*whether use different tables or not*/ bool cpufreq_tables_supply; @@ -53,10 +59,14 @@ enum cpufreq_index { struct meson_cpufreq_driver_data { struct device *cpu_dev; struct regulator *reg; + struct cpufreq_policy *policy; /* voltage tolerance in percentage */ unsigned int volt_tol; struct clk *high_freq_clk_p; struct clk *low_freq_clk_p; + struct clk *clk_dsu; + struct clk *clk_dsu_pre; + struct notifier_block freq_transition; }; static struct mutex cluster_lock[MAX_CLUSTERS]; diff --git a/drivers/amlogic/efuse/efuse_hw64.c b/drivers/amlogic/efuse/efuse_hw64.c index 4e4ae939300c..f73959033bf9 100644 --- a/drivers/amlogic/efuse/efuse_hw64.c +++ b/drivers/amlogic/efuse/efuse_hw64.c @@ -33,7 +33,7 @@ #include #include -static long meson_efuse_fn_smc(struct efuse_hal_api_arg *arg) +static long meson64_efuse_fn_smc(struct efuse_hal_api_arg *arg) { long ret; unsigned int cmd, offset, size; @@ -71,7 +71,7 @@ static long meson_efuse_fn_smc(struct efuse_hal_api_arg *arg) return 0; } -int meson_trustzone_efuse(struct efuse_hal_api_arg *arg) +int meson64_trustzone_efuse(struct efuse_hal_api_arg *arg) { int ret; struct cpumask org_cpumask; @@ -103,7 +103,7 @@ unsigned long efuse_aml_sec_boot_check(unsigned long nType, memcpy((void *)sharemem_input_base, (const void *)pBuffer, nLength); - __flush_dcache_area(sharemem_input_base, nLength); + //__flush_dcache_area(sharemem_input_base, nLength); asm __volatile__("" : : : "memory"); @@ -137,7 +137,7 @@ unsigned long efuse_amlogic_set(char *buf, size_t count) return ret; } -ssize_t meson_trustzone_efuse_get_max(struct efuse_hal_api_arg *arg) +ssize_t meson64_trustzone_efuse_get_max(struct efuse_hal_api_arg *arg) { ssize_t ret; unsigned int cmd; @@ -193,7 +193,7 @@ ssize_t _efuse_read(char *buf, size_t count, loff_t *ppos) arg.size = count; arg.buffer = (unsigned long)buf; arg.retcnt = (unsigned long)&retcnt; - ret = meson_trustzone_efuse(&arg); + ret = meson64_trustzone_efuse(&arg); if (ret == 0) { *ppos += retcnt; return retcnt; @@ -217,7 +217,7 @@ ssize_t _efuse_write(const char *buf, size_t count, loff_t *ppos) arg.buffer = (unsigned long)buf; arg.retcnt = (unsigned long)&retcnt; - ret = meson_trustzone_efuse(&arg); + ret = meson64_trustzone_efuse(&arg); if (ret == 0) { *ppos = retcnt; return retcnt;