PM / devfreq: rockchip_dmc: add support for rk3368
authorFinley Xiao <finley.xiao@rock-chips.com>
Tue, 2 May 2017 11:56:03 +0000 (19:56 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 4 May 2017 04:02:45 +0000 (12:02 +0800)
This adds the necessary data for handling dmcfreq on the rk3368.

Change-Id: Ie202cbaa3b27e52b22a5efc57c6e108fbd03a20a
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt
drivers/devfreq/rockchip_dmc.c
include/dt-bindings/clock/ddr.h [deleted file]
include/dt-bindings/clock/rockchip-ddr.h [new file with mode: 0644]

index 8f3b4dd4941e917d250ccac19c5cb2298bd306d7..edb650ef5addeef8633fc1d3e99c86145f3683a1 100644 (file)
@@ -2,6 +2,7 @@
 
 Required properties:
 - compatible: Should be one of the following.
+  - "rockchip,rk3368-dmc" - for RK3368 SoCs.
   - "rockchip,rk3399-dmc" - for RK3399 SoCs.
 - devfreq-events: Node to get DDR loading, Refer to
                  Documentation/devicetree/bindings/devfreq/rockchip-dfi.txt
index 0d838e49620291b5304f7976f04349337f345bcc..938be121e11e06b35c4efb24b6c90645ed7e1da6 100644 (file)
@@ -12,6 +12,7 @@
  * more details.
  */
 
+#include <dt-bindings/clock/rockchip-ddr.h>
 #include <linux/arm-smccc.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/pm_opp.h>
 #include <linux/regulator/consumer.h>
+#include <linux/rockchip/rockchip_sip.h>
 #include <linux/rwsem.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
 
 #include <soc/rockchip/rkfb_dmc.h>
 #include <soc/rockchip/rockchip_sip.h>
+#include <soc/rockchip/scpi.h>
+
+#define FIQ_INIT_HANDLER       (0x1)
+#define FIQ_CPU_TGT_BOOT       (0x0) /* to booting cpu */
+#define FIQ_NUM_FOR_DCF                (143) /* NA irq map to fiq for dcf */
+
+struct rk3368_dram_timing {
+       u32 dram_spd_bin;
+       u32 sr_idle;
+       u32 pd_idle;
+       u32 dram_dll_dis_freq;
+       u32 phy_dll_dis_freq;
+       u32 dram_odt_dis_freq;
+       u32 phy_odt_dis_freq;
+       u32 ddr3_drv;
+       u32 ddr3_odt;
+       u32 lpddr3_drv;
+       u32 lpddr3_odt;
+       u32 lpddr2_drv;
+       u32 phy_clk_drv;
+       u32 phy_cmd_drv;
+       u32 phy_dqs_drv;
+       u32 phy_odt;
+};
 
 struct rk3399_dram_timing {
        unsigned int ddr3_speed_bin;
@@ -281,6 +307,139 @@ static int rockchip_dmcfreq_init_freq_table(struct device *dev,
        return 0;
 }
 
+static struct rk3368_dram_timing *of_get_rk3368_timings(struct device *dev,
+                                                       struct device_node *np)
+{
+       struct rk3368_dram_timing *timing = NULL;
+       struct device_node *np_tim;
+       int ret;
+
+       np_tim = of_parse_phandle(np, "ddr_timing", 0);
+       if (np_tim) {
+               timing = devm_kzalloc(dev, sizeof(*timing), GFP_KERNEL);
+               if (!timing)
+                       goto err;
+
+               ret |= of_property_read_u32(np_tim, "dram_spd_bin",
+                                           &timing->dram_spd_bin);
+               ret |= of_property_read_u32(np_tim, "sr_idle",
+                                           &timing->sr_idle);
+               ret |= of_property_read_u32(np_tim, "pd_idle",
+                                           &timing->pd_idle);
+               ret |= of_property_read_u32(np_tim, "dram_dll_disb_freq",
+                                           &timing->dram_dll_dis_freq);
+               ret |= of_property_read_u32(np_tim, "phy_dll_disb_freq",
+                                           &timing->phy_dll_dis_freq);
+               ret |= of_property_read_u32(np_tim, "dram_odt_disb_freq",
+                                           &timing->dram_odt_dis_freq);
+               ret |= of_property_read_u32(np_tim, "phy_odt_disb_freq",
+                                           &timing->phy_odt_dis_freq);
+               ret |= of_property_read_u32(np_tim, "ddr3_drv",
+                                           &timing->ddr3_drv);
+               ret |= of_property_read_u32(np_tim, "ddr3_odt",
+                                           &timing->ddr3_odt);
+               ret |= of_property_read_u32(np_tim, "lpddr3_drv",
+                                           &timing->lpddr3_drv);
+               ret |= of_property_read_u32(np_tim, "lpddr3_odt",
+                                           &timing->lpddr3_odt);
+               ret |= of_property_read_u32(np_tim, "lpddr2_drv",
+                                           &timing->lpddr2_drv);
+               ret |= of_property_read_u32(np_tim, "phy_clk_drv",
+                                           &timing->phy_clk_drv);
+               ret |= of_property_read_u32(np_tim, "phy_cmd_drv",
+                                           &timing->phy_cmd_drv);
+               ret |= of_property_read_u32(np_tim, "phy_dqs_drv",
+                                           &timing->phy_dqs_drv);
+               ret |= of_property_read_u32(np_tim, "phy_odt",
+                                           &timing->phy_odt);
+               if (ret) {
+                       devm_kfree(dev, timing);
+                       goto err;
+               }
+               of_node_put(np_tim);
+               return timing;
+       }
+
+err:
+       if (timing) {
+               devm_kfree(dev, timing);
+               timing = NULL;
+       }
+       of_node_put(np_tim);
+       return timing;
+}
+
+static int rk3368_dmc_init(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = pdev->dev.of_node;
+       struct arm_smccc_res res;
+       struct rk3368_dram_timing *dram_timing;
+       struct clk *pclk_phy, *pclk_upctl;
+       int ret;
+       u32 dram_spd_bin;
+       u32 addr_mcu_el3;
+       u32 dclk_mode;
+       u32 lcdc_type;
+
+       pclk_phy = devm_clk_get(dev, "pclk_phy");
+       if (IS_ERR(pclk_phy)) {
+               dev_err(dev, "Cannot get the clk pclk_phy\n");
+               return PTR_ERR(pclk_phy);
+       };
+       ret = clk_prepare_enable(pclk_phy);
+       if (ret < 0) {
+               dev_err(dev, "failed to prepare/enable pclk_phy\n");
+               return ret;
+       }
+       pclk_upctl = devm_clk_get(dev, "pclk_upctl");
+       if (IS_ERR(pclk_phy)) {
+               dev_err(dev, "Cannot get the clk pclk_upctl\n");
+               return PTR_ERR(pclk_upctl);
+       };
+       ret = clk_prepare_enable(pclk_upctl);
+       if (ret < 0) {
+               dev_err(dev, "failed to prepare/enable pclk_upctl\n");
+               return ret;
+       }
+
+       /*
+        * Get dram timing and pass it to arm trust firmware,
+        * the dram drvier in arm trust firmware will get these
+        * timing and to do dram initial.
+        */
+       dram_timing = of_get_rk3368_timings(dev, np);
+       if (dram_timing) {
+               dram_spd_bin = dram_timing->dram_spd_bin;
+               if (scpi_ddr_send_timing((u32 *)dram_timing,
+                                        sizeof(struct rk3368_dram_timing)))
+                       dev_err(dev, "send ddr timing timeout\n");
+       } else {
+               dev_err(dev, "get ddr timing from dts error\n");
+               dram_spd_bin = DDR3_DEFAULT;
+       }
+
+       res = sip_smc_mcu_el3fiq(FIQ_INIT_HANDLER,
+                                FIQ_NUM_FOR_DCF,
+                                FIQ_CPU_TGT_BOOT);
+       if ((res.a0) || (res.a1 == 0) || (res.a1 > 0x80000))
+               dev_err(dev, "Trust version error, pls check trust version\n");
+       addr_mcu_el3 = res.a1;
+
+       if (of_property_read_u32(np, "vop-dclk-mode", &dclk_mode) == 0)
+               scpi_ddr_dclk_mode(dclk_mode);
+
+       lcdc_type = 7;
+
+       if (scpi_ddr_init(dram_spd_bin, 0, lcdc_type,
+                         addr_mcu_el3))
+               dev_err(dev, "ddr init error\n");
+       else
+               dev_dbg(dev, ("%s out\n"), __func__);
+
+       return 0;
+}
+
 static struct rk3399_dram_timing *of_get_rk3399_timings(struct device *dev,
                                                        struct device_node *np)
 {
@@ -405,6 +564,7 @@ static int rk3399_dmc_init(struct platform_device *pdev)
 }
 
 static const struct of_device_id rockchip_dmcfreq_of_match[] = {
+       { .compatible = "rockchip,rk3368-dmc", .data = rk3368_dmc_init },
        { .compatible = "rockchip,rk3399-dmc", .data = rk3399_dmc_init },
        { },
 };
diff --git a/include/dt-bindings/clock/ddr.h b/include/dt-bindings/clock/ddr.h
deleted file mode 100755 (executable)
index cfc3a9d..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *
- * Copyright (C) 2011-2014 ROCKCHIP, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_ROCKCHIP_DDR_H
-#define __MACH_ROCKCHIP_DDR_H
-
-#define DDR3_800D   (0)     // 5-5-5
-#define DDR3_800E   (1)     // 6-6-6
-#define DDR3_1066E  (2)     // 6-6-6
-#define DDR3_1066F  (3)     // 7-7-7
-#define DDR3_1066G  (4)     // 8-8-8
-#define DDR3_1333F  (5)     // 7-7-7
-#define DDR3_1333G  (6)     // 8-8-8
-#define DDR3_1333H  (7)     // 9-9-9
-#define DDR3_1333J  (8)     // 10-10-10
-#define DDR3_1600G  (9)     // 8-8-8
-#define DDR3_1600H  (10)    // 9-9-9
-#define DDR3_1600J  (11)    // 10-10-10
-#define DDR3_1600K  (12)    // 11-11-11
-#define DDR3_1866J  (13)    // 10-10-10
-#define DDR3_1866K  (14)    // 11-11-11
-#define DDR3_1866L  (15)    // 12-12-12
-#define DDR3_1866M  (16)    // 13-13-13
-#define DDR3_2133K  (17)    // 11-11-11
-#define DDR3_2133L  (18)    // 12-12-12
-#define DDR3_2133M  (19)    // 13-13-13
-#define DDR3_2133N  (20)    // 14-14-14
-#define DDR3_DEFAULT (21)
-#define DDR_DDR2     (22)
-#define DDR_LPDDR    (23)
-#define DDR_LPDDR2   (24)
-
-#define PAUSE_CPU_STACK_SIZE   16
-
-#endif
diff --git a/include/dt-bindings/clock/rockchip-ddr.h b/include/dt-bindings/clock/rockchip-ddr.h
new file mode 100644 (file)
index 0000000..f28f14f
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright (C) 2017 ROCKCHIP, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_DDR_H
+#define _DT_BINDINGS_CLOCK_ROCKCHIP_DDR_H
+
+#define DDR3_800D   (0)     /* 5-5-5 */
+#define DDR3_800E   (1)     /* 6-6-6 */
+#define DDR3_1066E  (2)     /* 6-6-6 */
+#define DDR3_1066F  (3)     /* 7-7-7 */
+#define DDR3_1066G  (4)     /* 8-8-8 */
+#define DDR3_1333F  (5)     /* 7-7-7 */
+#define DDR3_1333G  (6)     /* 8-8-8 */
+#define DDR3_1333H  (7)     /* 9-9-9 */
+#define DDR3_1333J  (8)     /* 10-10-10 */
+#define DDR3_1600G  (9)     /* 8-8-8 */
+#define DDR3_1600H  (10)    /* 9-9-9 */
+#define DDR3_1600J  (11)    /* 10-10-10 */
+#define DDR3_1600K  (12)    /* 11-11-11 */
+#define DDR3_1866J  (13)    /* 10-10-10 */
+#define DDR3_1866K  (14)    /* 11-11-11 */
+#define DDR3_1866L  (15)    /* 12-12-12 */
+#define DDR3_1866M  (16)    /* 13-13-13 */
+#define DDR3_2133K  (17)    /* 11-11-11 */
+#define DDR3_2133L  (18)    /* 12-12-12 */
+#define DDR3_2133M  (19)    /* 13-13-13 */
+#define DDR3_2133N  (20)    /* 14-14-14 */
+#define DDR3_DEFAULT (21)
+#define DDR_DDR2     (22)
+#define DDR_LPDDR    (23)
+#define DDR_LPDDR2   (24)
+
+#define PAUSE_CPU_STACK_SIZE   16
+
+#endif