From 3aacbd51b7928ae4dc2aad37396f20ebac3d8337 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 2 May 2017 19:56:03 +0800 Subject: [PATCH] PM / devfreq: rockchip_dmc: add support for rk3368 This adds the necessary data for handling dmcfreq on the rk3368. Change-Id: Ie202cbaa3b27e52b22a5efc57c6e108fbd03a20a Signed-off-by: Finley Xiao --- .../bindings/devfreq/rockchip_dmc.txt | 1 + drivers/devfreq/rockchip_dmc.c | 160 ++++++++++++++++++ include/dt-bindings/clock/ddr.h | 47 ----- include/dt-bindings/clock/rockchip-ddr.h | 47 +++++ 4 files changed, 208 insertions(+), 47 deletions(-) delete mode 100755 include/dt-bindings/clock/ddr.h create mode 100644 include/dt-bindings/clock/rockchip-ddr.h diff --git a/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt b/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt index 8f3b4dd4941e..edb650ef5add 100644 --- a/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt +++ b/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt @@ -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 diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 0d838e496202..938be121e11e 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -12,6 +12,7 @@ * more details. */ +#include #include #include #include @@ -23,12 +24,37 @@ #include #include #include +#include #include #include #include #include #include +#include + +#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 index cfc3a9d45636..000000000000 --- a/include/dt-bindings/clock/ddr.h +++ /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 index 000000000000..f28f14f1151e --- /dev/null +++ b/include/dt-bindings/clock/rockchip-ddr.h @@ -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 -- 2.34.1