rk3368 DDR: using unified smc call and get trust firmware version function
[firefly-linux-kernel-4.4.55.git] / drivers / devfreq / ddr_rk3368.c
index 56d3b679475f0c3359bb18aa0530a5b5d3a15338..b465e48c7c47786c412aa67649567e2dfe16d410 100644 (file)
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <asm/compiler.h>
+#include <dt-bindings/clock/ddr.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
 #include <linux/of.h>
-#include <linux/of_address.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-#include <linux/cpu.h>
-#include <dt-bindings/clock/ddr.h>
-#include <linux/rockchip/common.h>
-#include <linux/rockchip/cpu.h>
-#include <linux/rockchip/cru.h>
-#include <linux/rockchip/dvfs.h>
-#include <linux/rockchip/grf.h>
-#include <linux/rockchip/iomap.h>
-#include <linux/rockchip/pmu.h>
 #include <linux/rk_fb.h>
+#include <linux/rockchip/common.h>
+#include <linux/rockchip/psci.h>
 #include <linux/scpi_protocol.h>
 
 #define GRF_DDRC0_CON0    0x600
 #define GRF_SOC_STATUS5  0x494
 #define DDR_PCTL_TOGCNT_1U  0xc0
 
+#define FIQ_CPU_TGT_BOOT               0x0 /* to booting cpu */
+#define FIQ_NUM_FOR_DCF                (143)  /*NA irq map to fiq for dcf*/
+
+
+#define DDR_VERSION                    "V1.02 20150907"
+
 enum ddr_bandwidth_id {
        ddrbw_wr_num = 0,
        ddrbw_rd_num,
@@ -64,14 +56,29 @@ struct rockchip_ddr {
 
 static struct rockchip_ddr *ddr_data = NULL;
 
+static int _ddr_recalc_rate(void)
+{
+       int ddr_freq;
+
+       regmap_read(ddr_data->ddrpctl_regs, DDR_PCTL_TOGCNT_1U,
+                   &ddr_freq);
+       ddr_freq = ddr_freq * 2 * 1000000;
+       return ddr_freq;
+}
+
 static int _ddr_change_freq(u32 n_mhz)
 {
        u32 ret;
+       u32 lcdc_type;
+       struct rk_lcdc_driver *lcdc_dev = NULL;
 
        printk(KERN_DEBUG pr_fmt("In func %s,freq=%dMHz\n"), __func__, n_mhz);
-       if (scpi_ddr_set_clk_rate(n_mhz))
+       lcdc_dev = rk_get_lcdc_drv("lcdc0");
+       lcdc_type = lcdc_dev ? (u32)lcdc_dev->cur_screen->type : 0;
+       printk(KERN_DEBUG pr_fmt("lcdc type:%d\n"), lcdc_type);
+       if (scpi_ddr_set_clk_rate(n_mhz, lcdc_type))
                pr_info("set ddr freq timeout\n");
-       ret = scpi_ddr_get_clk_rate();
+       ret = _ddr_recalc_rate() / 1000000;
        printk(KERN_DEBUG pr_fmt("Func %s out,freq=%dMHz\n"), __func__, ret);
        return ret;
 }
@@ -81,11 +88,6 @@ static long _ddr_round_rate(u32 n_mhz)
        return (n_mhz / 12) * 12;
 }
 
-static int _ddr_recalc_rate(void)
-{
-       return (1000000 * scpi_ddr_get_clk_rate());
-}
-
 static void _ddr_set_auto_self_refresh(bool en)
 {
        if (scpi_ddr_set_auto_self_refresh(en))
@@ -244,14 +246,24 @@ end:
        ddr_monitor_start();
 }
 
-static void ddr_init(u32 dram_speed_bin, u32 freq)
+static void ddr_init(u32 dram_speed_bin, u32 freq, u32 addr_mcu_el3)
 {
        int lcdc_type;
+       static u32 addr = 0;
 
-       lcdc_type = rockchip_get_screen_type();
+       struct rk_lcdc_driver *lcdc_dev = NULL;
+
+       if (addr == 0)
+               addr = addr_mcu_el3;
+
+       lcdc_dev = rk_get_lcdc_drv("lcdc0");
+       if (lcdc_dev == NULL)
+               lcdc_type = 0;
+       else
+               lcdc_type = (u32)lcdc_dev->cur_screen->type;
        printk(KERN_DEBUG pr_fmt("In Func:%s,dram_speed_bin:%d,freq:%d,lcdc_type:%d\n"),
               __func__, dram_speed_bin, freq, lcdc_type);
-       if (scpi_ddr_init(dram_speed_bin, freq, lcdc_type))
+       if (scpi_ddr_init(dram_speed_bin, freq, lcdc_type, addr))
                pr_info("ddr init error\n");
        else
                printk(KERN_DEBUG pr_fmt("%s out\n"), __func__);
@@ -259,14 +271,43 @@ static void ddr_init(u32 dram_speed_bin, u32 freq)
 
 static int ddr_init_resume(struct platform_device *pdev)
 {
-       ddr_init(DDR3_DEFAULT, 0);
+       ddr_init(DDR3_DEFAULT, 0, 0);
        return 0;
 }
+#define RKTF_VER_MAJOR(ver) (((ver) >> 16) & 0xffff)
+#define RKTF_VER_MINOR(ver) ((ver) & 0xffff)
+/* valid ver */
+#define RKTF_VLDVER_MAJOR (1)
+#define RKTF_VLDVER_MINOR (5)
+
+static int __init rockchip_tf_ver_check(void)
+{
+       u32 version;
+
+       version = rockchip_psci_smc_get_tf_ver();
+       if (((RKTF_VER_MAJOR(version) == RKTF_VLDVER_MAJOR) &&
+            (RKTF_VER_MINOR(version) >= RKTF_VLDVER_MINOR)) ||
+           (RKTF_VER_MAJOR(version) > RKTF_VLDVER_MAJOR))
+               return 0;
+
+       pr_err("read tf version 0x%x!\n", version);
+
+       do {
+               mdelay(1000);
+               pr_err("trusted firmware need to update to(%d.%d) or is invaild!\n",
+                      RKTF_VLDVER_MAJOR, RKTF_VLDVER_MINOR);
+       } while (1);
+
+       return 0;
+}
+
 
 static int __init rockchip_ddr_probe(struct platform_device *pdev)
 {
+       u32 addr_mcu_el3;
        struct device_node *np;
 
+       pr_info("Rockchip DDR Initialize, verision: "DDR_VERSION"\n");
        np = pdev->dev.of_node;
        ddr_data =
            devm_kzalloc(&pdev->dev, sizeof(struct rockchip_ddr), GFP_KERNEL);
@@ -306,7 +347,13 @@ static int __init rockchip_ddr_probe(struct platform_device *pdev)
        ddr_set_auto_self_refresh = _ddr_set_auto_self_refresh;
        ddr_bandwidth_get = _ddr_bandwidth_get;
        ddr_recalc_rate = _ddr_recalc_rate;
-       ddr_init(DDR3_DEFAULT, 0);
+       rockchip_tf_ver_check();
+       addr_mcu_el3 = rockchip_psci_smc_write(PSCI_SIP_EL3FIQ_CFG,
+                                              FIQ_NUM_FOR_DCF,
+                                              FIQ_CPU_TGT_BOOT, 0);
+       if ((addr_mcu_el3 == 0) || (addr_mcu_el3 > 0x80000))
+               pr_info("Trust version error, pls check trust version\n");
+       ddr_init(DDR3_DEFAULT, 0, addr_mcu_el3);
        pr_info("%s: success\n", __func__);
        return 0;
 }