From 990b7b2229bf3cfe8fff1b7f32a66ec5e0c25460 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 27 Mar 2017 20:13:24 +0800 Subject: [PATCH] PM / devfreq: rk3399_dmc: rename driver to 'rockchip_dmc' In future it will be modified to support more rockchip platforms. Change-Id: I5cd7ce555eefe08b12fbfcda8ef445c4b169e8c6 Signed-off-by: Finley Xiao --- .../bindings/devfreq/rk3399_dmc.txt | 215 -------- drivers/devfreq/Kconfig | 6 +- drivers/devfreq/Makefile | 2 +- drivers/devfreq/rk3399_dmc.c | 516 ------------------ drivers/devfreq/rockchip_dmc.c | 75 +-- include/soc/rockchip/rockchip_dmc.h | 21 +- include/soc/rockchip/rockchip_sip.h | 7 +- 7 files changed, 50 insertions(+), 792 deletions(-) delete mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt delete mode 100644 drivers/devfreq/rk3399_dmc.c diff --git a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt deleted file mode 100644 index a10d1f6d85c6..000000000000 --- a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt +++ /dev/null @@ -1,215 +0,0 @@ -* Rockchip rk3399 DMC (Dynamic Memory Controller) device - -Required properties: -- compatible: Must be "rockchip,rk3399-dmc". -- devfreq-events: Node to get DDR loading, Refer to - Documentation/devicetree/bindings/devfreq/event/ - rockchip-dfi.txt -- clocks: Phandles for clock specified in "clock-names" property -- clock-names : The name of clock used by the DFI, must be - "pclk_ddr_mon"; -- operating-points-v2: Refer to Documentation/devicetree/bindings/opp/opp.txt - for details. -- center-supply: DMC supply node. -- status: Marks the node enabled/disabled. - -Optional properties: -- interrupts: The CPU interrupt number. The interrupt specifier - format depends on the interrupt controller. - It should be a DCF interrupt. When DDR DVFS finishes - a DCF interrupt is triggered. -- rockchip,pmu: Phandle to the syscon managing the "PMU general register - files". - -Following properties relate to DDR timing: - -- rockchip,dram_speed_bin : Value reference include/dt-bindings/clock/rk3399-ddr.h, - it selects the DDR3 cl-trp-trcd type. It must be - set according to "Speed Bin" in DDR3 datasheet, - DO NOT use a smaller "Speed Bin" than specified - for the DDR3 being used. - -- rockchip,pd_idle : Configure the PD_IDLE value. Defines the - power-down idle period in which memories are - placed into power-down mode if bus is idle - for PD_IDLE DFI clock cycles. - -- rockchip,sr_idle : Configure the SR_IDLE value. Defines the - self-refresh idle period in which memories are - placed into self-refresh mode if bus is idle - for SR_IDLE * 1024 DFI clock cycles (DFI - clocks freq is half of DRAM clock), default - value is "0". - -- rockchip,sr_mc_gate_idle : Defines the memory self-refresh and controller - clock gating idle period. Memories are placed - into self-refresh mode and memory controller - clock arg gating started if bus is idle for - sr_mc_gate_idle*1024 DFI clock cycles. - -- rockchip,srpd_lite_idle : Defines the self-refresh power down idle - period in which memories are placed into - self-refresh power down mode if bus is idle - for srpd_lite_idle * 1024 DFI clock cycles. - This parameter is for LPDDR4 only. - -- rockchip,standby_idle : Defines the standby idle period in which - memories are placed into self-refresh mode. - The controller, pi, PHY and DRAM clock will - be gated if bus is idle for standby_idle * DFI - clock cycles. - -- rockchip,dram_dll_dis_freq : Defines the DDR3 DLL bypass frequency in MHz. - When DDR frequency is less than DRAM_DLL_DISB_FREQ, - DDR3 DLL will be bypassed. Note: if DLL was bypassed, - the odt will also stop working. - -- rockchip,phy_dll_dis_freq : Defines the PHY dll bypass frequency in - MHz (Mega Hz). When DDR frequency is less than - DRAM_DLL_DISB_FREQ, PHY DLL will be bypassed. - Note: PHY DLL and PHY ODT are independent. - -- rockchip,ddr3_odt_dis_freq : When the DRAM type is DDR3, this parameter defines - the ODT disable frequency in MHz (Mega Hz). - when the DDR frequency is less then ddr3_odt_dis_freq, - the ODT on the DRAM side and controller side are - both disabled. - -- rockchip,ddr3_drv : When the DRAM type is DDR3, this parameter defines - the DRAM side driver strength in ohms. Default - value is DDR3_DS_40ohm. - -- rockchip,ddr3_odt : When the DRAM type is DDR3, this parameter defines - the DRAM side ODT strength in ohms. Default value - is DDR3_ODT_120ohm. - -- rockchip,phy_ddr3_ca_drv : When the DRAM type is DDR3, this parameter defines - the phy side CA line (incluing command line, - address line and clock line) driver strength. - Default value is PHY_DRV_ODT_40. - -- rockchip,phy_ddr3_dq_drv : When the DRAM type is DDR3, this parameter defines - the PHY side DQ line (including DQS/DQ/DM line) - driver strength. Default value is PHY_DRV_ODT_40. - -- rockchip,phy_ddr3_odt : When the DRAM type is DDR3, this parameter defines - the PHY side ODT strength. Default value is - PHY_DRV_ODT_240. - -- rockchip,lpddr3_odt_dis_freq : When the DRAM type is LPDDR3, this parameter defines - then ODT disable frequency in MHz (Mega Hz). - When DDR frequency is less then ddr3_odt_dis_freq, - the ODT on the DRAM side and controller side are - both disabled. - -- rockchip,lpddr3_drv : When the DRAM type is LPDDR3, this parameter defines - the DRAM side driver strength in ohms. Default - value is LP3_DS_34ohm. - -- rockchip,lpddr3_odt : When the DRAM type is LPDDR3, this parameter defines - the DRAM side ODT strength in ohms. Default value - is LP3_ODT_240ohm. - -- rockchip,phy_lpddr3_ca_drv : When the DRAM type is LPDDR3, this parameter defines - the PHY side CA line (including command line, - address line and clock line) driver strength. - Default value is PHY_DRV_ODT_40. - -- rockchip,phy_lpddr3_dq_drv : When the DRAM type is LPDDR3, this parameter defines - the PHY side DQ line (including DQS/DQ/DM line) - driver strength. Default value is - PHY_DRV_ODT_40. - -- rockchip,phy_lpddr3_odt : When dram type is LPDDR3, this parameter define - the phy side odt strength, default value is - PHY_DRV_ODT_240. - -- rockchip,lpddr4_odt_dis_freq : When the DRAM type is LPDDR4, this parameter - defines the ODT disable frequency in - MHz (Mega Hz). When the DDR frequency is less then - ddr3_odt_dis_freq, the ODT on the DRAM side and - controller side are both disabled. - -- rockchip,lpddr4_drv : When the DRAM type is LPDDR4, this parameter defines - the DRAM side driver strength in ohms. Default - value is LP4_PDDS_60ohm. - -- rockchip,lpddr4_dq_odt : When the DRAM type is LPDDR4, this parameter defines - the DRAM side ODT on DQS/DQ line strength in ohms. - Default value is LP4_DQ_ODT_40ohm. - -- rockchip,lpddr4_ca_odt : When the DRAM type is LPDDR4, this parameter defines - the DRAM side ODT on CA line strength in ohms. - Default value is LP4_CA_ODT_40ohm. - -- rockchip,phy_lpddr4_ca_drv : When the DRAM type is LPDDR4, this parameter defines - the PHY side CA line (including command address - line) driver strength. Default value is - PHY_DRV_ODT_40. - -- rockchip,phy_lpddr4_ck_cs_drv : When the DRAM type is LPDDR4, this parameter defines - the PHY side clock line and CS line driver - strength. Default value is PHY_DRV_ODT_80. - -- rockchip,phy_lpddr4_dq_drv : When the DRAM type is LPDDR4, this parameter defines - the PHY side DQ line (including DQS/DQ/DM line) - driver strength. Default value is PHY_DRV_ODT_80. - -- rockchip,phy_lpddr4_odt : When the DRAM type is LPDDR4, this parameter defines - the PHY side ODT strength. Default value is - PHY_DRV_ODT_60. - -Example: - dmc_opp_table: dmc_opp_table { - compatible = "operating-points-v2"; - - opp00 { - opp-hz = /bits/ 64 <300000000>; - opp-microvolt = <900000>; - }; - opp01 { - opp-hz = /bits/ 64 <666000000>; - opp-microvolt = <900000>; - }; - }; - - dmc: dmc { - compatible = "rockchip,rk3399-dmc"; - devfreq-events = <&dfi>; - interrupts = ; - clocks = <&cru SCLK_DDRCLK>; - clock-names = "dmc_clk"; - operating-points-v2 = <&dmc_opp_table>; - center-supply = <&ppvar_centerlogic>; - upthreshold = <15>; - downdifferential = <10>; - rockchip,ddr3_speed_bin = <21>; - rockchip,pd_idle = <0x40>; - rockchip,sr_idle = <0x2>; - rockchip,sr_mc_gate_idle = <0x3>; - rockchip,srpd_lite_idle = <0x4>; - rockchip,standby_idle = <0x2000>; - rockchip,dram_dll_dis_freq = <300>; - rockchip,phy_dll_dis_freq = <125>; - rockchip,auto_pd_dis_freq = <666>; - rockchip,ddr3_odt_dis_freq = <333>; - rockchip,ddr3_drv = ; - rockchip,ddr3_odt = ; - rockchip,phy_ddr3_ca_drv = ; - rockchip,phy_ddr3_dq_drv = ; - rockchip,phy_ddr3_odt = ; - rockchip,lpddr3_odt_dis_freq = <333>; - rockchip,lpddr3_drv = ; - rockchip,lpddr3_odt = ; - rockchip,phy_lpddr3_ca_drv = ; - rockchip,phy_lpddr3_dq_drv = ; - rockchip,phy_lpddr3_odt = ; - rockchip,lpddr4_odt_dis_freq = <333>; - rockchip,lpddr4_drv = ; - rockchip,lpddr4_dq_odt = ; - rockchip,lpddr4_ca_odt = ; - rockchip,phy_lpddr4_ca_drv = ; - rockchip,phy_lpddr4_ck_cs_drv = ; - rockchip,phy_lpddr4_dq_drv = ; - rockchip,phy_lpddr4_odt = ; - }; diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index ba864cb2ab1f..79217edf629a 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -137,15 +137,15 @@ config ARM_ROCKCHIP_BUS_DEVFREQ help This adds the DEVFREQ driver for the ROCKCHIP BUS. -config ARM_RK3399_DMC_DEVFREQ - tristate "ARM RK3399 DMC DEVFREQ Driver" +config ARM_ROCKCHIP_DMC_DEVFREQ + tristate "ARM ROCKCHIP DMC DEVFREQ Driver" depends on (ARCH_ROCKCHIP && HAVE_ARM_SMCCC) || \ (COMPILE_TEST && HAVE_ARM_SMCCC) select DEVFREQ_EVENT_ROCKCHIP_DFI select DEVFREQ_GOV_SIMPLE_ONDEMAND select PM_DEVFREQ_EVENT help - This adds the DEVFREQ driver for the RK3399 DMC(Dynamic Memory Controller). + This adds the DEVFREQ driver for the ROCKCHIP DMC(Dynamic Memory Controller). It sets the frequency for the memory controller and reads the usage counts from hardware. diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile index 5f429dbe025d..1061fb5923f8 100644 --- a/drivers/devfreq/Makefile +++ b/drivers/devfreq/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o obj-$(CONFIG_ARM_ROCKCHIP_BUS_DEVFREQ) += rockchip_bus.o -obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o +obj-$(CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ) += rockchip_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c deleted file mode 100644 index 2e912166a993..000000000000 --- a/drivers/devfreq/rk3399_dmc.c +++ /dev/null @@ -1,516 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd. - * Author: Lin Huang - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -struct dram_timing { - unsigned int ddr3_speed_bin; - unsigned int pd_idle; - unsigned int sr_idle; - unsigned int sr_mc_gate_idle; - unsigned int srpd_lite_idle; - unsigned int standby_idle; - unsigned int auto_pd_dis_freq; - unsigned int dram_dll_dis_freq; - unsigned int phy_dll_dis_freq; - unsigned int ddr3_odt_dis_freq; - unsigned int ddr3_drv; - unsigned int ddr3_odt; - unsigned int phy_ddr3_ca_drv; - unsigned int phy_ddr3_dq_drv; - unsigned int phy_ddr3_odt; - unsigned int lpddr3_odt_dis_freq; - unsigned int lpddr3_drv; - unsigned int lpddr3_odt; - unsigned int phy_lpddr3_ca_drv; - unsigned int phy_lpddr3_dq_drv; - unsigned int phy_lpddr3_odt; - unsigned int lpddr4_odt_dis_freq; - unsigned int lpddr4_drv; - unsigned int lpddr4_dq_odt; - unsigned int lpddr4_ca_odt; - unsigned int phy_lpddr4_ca_drv; - unsigned int phy_lpddr4_ck_cs_drv; - unsigned int phy_lpddr4_dq_drv; - unsigned int phy_lpddr4_odt; -}; - -struct rk3399_dmcfreq { - struct device *dev; - struct devfreq *devfreq; - struct devfreq_simple_ondemand_data ondemand_data; - struct clk *dmc_clk; - struct devfreq_event_dev *edev; - struct mutex lock; - struct dram_timing timing; - struct regulator *vdd_center; - struct regmap *regmap_pmu; - unsigned long rate, target_rate; - unsigned long volt, target_volt; - unsigned int odt_dis_freq; - int odt_pd_arg0, odt_pd_arg1; -}; - -static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, - u32 flags) -{ - struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev); - struct dev_pm_opp *opp; - unsigned long old_clk_rate = dmcfreq->rate; - unsigned long target_volt, target_rate; - struct arm_smccc_res res; - bool odt_enable = false; - int err; - - opp = devfreq_recommended_opp(dev, freq, flags); - if (IS_ERR(opp)) - return PTR_ERR(opp); - - target_rate = dev_pm_opp_get_freq(opp); - target_volt = dev_pm_opp_get_voltage(opp); - dev_pm_opp_put(opp); - - if (dmcfreq->rate == target_rate) - return 0; - - mutex_lock(&dmcfreq->lock); - - if (dmcfreq->regmap_pmu) { - if (target_rate >= dmcfreq->odt_dis_freq) - odt_enable = true; - - /* - * This makes a SMC call to the TF-A to set the DDR PD - * (power-down) timings and to enable or disable the - * ODT (on-die termination) resistors. - */ - arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, dmcfreq->odt_pd_arg0, - dmcfreq->odt_pd_arg1, - ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD, - odt_enable, 0, 0, 0, &res); - } - - /* - * If frequency scaling from low to high, adjust voltage first. - * If frequency scaling from high to low, adjust frequency first. - */ - if (old_clk_rate < target_rate) { - err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, - target_volt); - if (err) { - dev_err(dev, "Cannot set voltage %lu uV\n", - target_volt); - goto out; - } - } - - err = clk_set_rate(dmcfreq->dmc_clk, target_rate); - if (err) { - dev_err(dev, "Cannot set frequency %lu (%d)\n", target_rate, - err); - regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, - dmcfreq->volt); - goto out; - } - - /* - * Check the dpll rate, - * There only two result we will get, - * 1. Ddr frequency scaling fail, we still get the old rate. - * 2. Ddr frequency scaling sucessful, we get the rate we set. - */ - dmcfreq->rate = clk_get_rate(dmcfreq->dmc_clk); - - /* If get the incorrect rate, set voltage to old value. */ - if (dmcfreq->rate != target_rate) { - dev_err(dev, "Got wrong frequency, Request %lu, Current %lu\n", - target_rate, dmcfreq->rate); - regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, - dmcfreq->volt); - goto out; - } else if (old_clk_rate > target_rate) - err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, - target_volt); - if (err) - dev_err(dev, "Cannot set voltage %lu uV\n", target_volt); - - dmcfreq->rate = target_rate; - dmcfreq->volt = target_volt; - -out: - mutex_unlock(&dmcfreq->lock); - return err; -} - -static int rk3399_dmcfreq_get_dev_status(struct device *dev, - struct devfreq_dev_status *stat) -{ - struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev); - struct devfreq_event_data edata; - int ret = 0; - - ret = devfreq_event_get_event(dmcfreq->edev, &edata); - if (ret < 0) - return ret; - - stat->current_frequency = dmcfreq->rate; - stat->busy_time = edata.load_count; - stat->total_time = edata.total_count; - - return ret; -} - -static int rk3399_dmcfreq_get_cur_freq(struct device *dev, unsigned long *freq) -{ - struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev); - - *freq = dmcfreq->rate; - - return 0; -} - -static struct devfreq_dev_profile rk3399_devfreq_dmc_profile = { - .polling_ms = 200, - .target = rk3399_dmcfreq_target, - .get_dev_status = rk3399_dmcfreq_get_dev_status, - .get_cur_freq = rk3399_dmcfreq_get_cur_freq, -}; - -static __maybe_unused int rk3399_dmcfreq_suspend(struct device *dev) -{ - struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev); - int ret = 0; - - ret = devfreq_event_disable_edev(dmcfreq->edev); - if (ret < 0) { - dev_err(dev, "failed to disable the devfreq-event devices\n"); - return ret; - } - - ret = devfreq_suspend_device(dmcfreq->devfreq); - if (ret < 0) { - dev_err(dev, "failed to suspend the devfreq devices\n"); - return ret; - } - - return 0; -} - -static __maybe_unused int rk3399_dmcfreq_resume(struct device *dev) -{ - struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev); - int ret = 0; - - ret = devfreq_event_enable_edev(dmcfreq->edev); - if (ret < 0) { - dev_err(dev, "failed to enable the devfreq-event devices\n"); - return ret; - } - - ret = devfreq_resume_device(dmcfreq->devfreq); - if (ret < 0) { - dev_err(dev, "failed to resume the devfreq devices\n"); - return ret; - } - return ret; -} - -static SIMPLE_DEV_PM_OPS(rk3399_dmcfreq_pm, rk3399_dmcfreq_suspend, - rk3399_dmcfreq_resume); - -static int of_get_ddr_timings(struct dram_timing *timing, - struct device_node *np) -{ - int ret = 0; - - ret = of_property_read_u32(np, "rockchip,ddr3_speed_bin", - &timing->ddr3_speed_bin); - ret |= of_property_read_u32(np, "rockchip,pd_idle", - &timing->pd_idle); - ret |= of_property_read_u32(np, "rockchip,sr_idle", - &timing->sr_idle); - ret |= of_property_read_u32(np, "rockchip,sr_mc_gate_idle", - &timing->sr_mc_gate_idle); - ret |= of_property_read_u32(np, "rockchip,srpd_lite_idle", - &timing->srpd_lite_idle); - ret |= of_property_read_u32(np, "rockchip,standby_idle", - &timing->standby_idle); - ret |= of_property_read_u32(np, "rockchip,auto_pd_dis_freq", - &timing->auto_pd_dis_freq); - ret |= of_property_read_u32(np, "rockchip,dram_dll_dis_freq", - &timing->dram_dll_dis_freq); - ret |= of_property_read_u32(np, "rockchip,phy_dll_dis_freq", - &timing->phy_dll_dis_freq); - ret |= of_property_read_u32(np, "rockchip,ddr3_odt_dis_freq", - &timing->ddr3_odt_dis_freq); - ret |= of_property_read_u32(np, "rockchip,ddr3_drv", - &timing->ddr3_drv); - ret |= of_property_read_u32(np, "rockchip,ddr3_odt", - &timing->ddr3_odt); - ret |= of_property_read_u32(np, "rockchip,phy_ddr3_ca_drv", - &timing->phy_ddr3_ca_drv); - ret |= of_property_read_u32(np, "rockchip,phy_ddr3_dq_drv", - &timing->phy_ddr3_dq_drv); - ret |= of_property_read_u32(np, "rockchip,phy_ddr3_odt", - &timing->phy_ddr3_odt); - ret |= of_property_read_u32(np, "rockchip,lpddr3_odt_dis_freq", - &timing->lpddr3_odt_dis_freq); - ret |= of_property_read_u32(np, "rockchip,lpddr3_drv", - &timing->lpddr3_drv); - ret |= of_property_read_u32(np, "rockchip,lpddr3_odt", - &timing->lpddr3_odt); - ret |= of_property_read_u32(np, "rockchip,phy_lpddr3_ca_drv", - &timing->phy_lpddr3_ca_drv); - ret |= of_property_read_u32(np, "rockchip,phy_lpddr3_dq_drv", - &timing->phy_lpddr3_dq_drv); - ret |= of_property_read_u32(np, "rockchip,phy_lpddr3_odt", - &timing->phy_lpddr3_odt); - ret |= of_property_read_u32(np, "rockchip,lpddr4_odt_dis_freq", - &timing->lpddr4_odt_dis_freq); - ret |= of_property_read_u32(np, "rockchip,lpddr4_drv", - &timing->lpddr4_drv); - ret |= of_property_read_u32(np, "rockchip,lpddr4_dq_odt", - &timing->lpddr4_dq_odt); - ret |= of_property_read_u32(np, "rockchip,lpddr4_ca_odt", - &timing->lpddr4_ca_odt); - ret |= of_property_read_u32(np, "rockchip,phy_lpddr4_ca_drv", - &timing->phy_lpddr4_ca_drv); - ret |= of_property_read_u32(np, "rockchip,phy_lpddr4_ck_cs_drv", - &timing->phy_lpddr4_ck_cs_drv); - ret |= of_property_read_u32(np, "rockchip,phy_lpddr4_dq_drv", - &timing->phy_lpddr4_dq_drv); - ret |= of_property_read_u32(np, "rockchip,phy_lpddr4_odt", - &timing->phy_lpddr4_odt); - - return ret; -} - -static int rk3399_dmcfreq_probe(struct platform_device *pdev) -{ - struct arm_smccc_res res; - struct device *dev = &pdev->dev; - struct device_node *np = pdev->dev.of_node, *node; - struct rk3399_dmcfreq *data; - int ret, index, size; - uint32_t *timing; - struct dev_pm_opp *opp; - u32 ddr_type; - u32 val; - - data = devm_kzalloc(dev, sizeof(struct rk3399_dmcfreq), GFP_KERNEL); - if (!data) - return -ENOMEM; - - mutex_init(&data->lock); - - data->vdd_center = devm_regulator_get(dev, "center"); - if (IS_ERR(data->vdd_center)) { - if (PTR_ERR(data->vdd_center) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - dev_err(dev, "Cannot get the regulator \"center\"\n"); - return PTR_ERR(data->vdd_center); - } - - data->dmc_clk = devm_clk_get(dev, "dmc_clk"); - if (IS_ERR(data->dmc_clk)) { - if (PTR_ERR(data->dmc_clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - dev_err(dev, "Cannot get the clk dmc_clk\n"); - return PTR_ERR(data->dmc_clk); - } - - data->edev = devfreq_event_get_edev_by_phandle(dev, "devfreq-events", 0); - if (IS_ERR(data->edev)) - return -EPROBE_DEFER; - - ret = devfreq_event_enable_edev(data->edev); - if (ret < 0) { - dev_err(dev, "failed to enable devfreq-event devices\n"); - return ret; - } - - /* - * Get dram timing and pass it to arm trust firmware, - * the dram driver in arm trust firmware will get these - * timing and to do dram initial. - */ - if (!of_get_ddr_timings(&data->timing, np)) { - timing = &data->timing.ddr3_speed_bin; - size = sizeof(struct dram_timing) / 4; - for (index = 0; index < size; index++) { - arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, *timing++, index, - ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM, - 0, 0, 0, 0, &res); - if (res.a0) { - dev_err(dev, "Failed to set dram param: %ld\n", - res.a0); - ret = -EINVAL; - goto err_edev; - } - } - } - - node = of_parse_phandle(np, "rockchip,pmu", 0); - if (!node) - goto no_pmu; - - data->regmap_pmu = syscon_node_to_regmap(node); - of_node_put(node); - if (IS_ERR(data->regmap_pmu)) { - ret = PTR_ERR(data->regmap_pmu); - goto err_edev; - } - - regmap_read(data->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); - ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) & - RK3399_PMUGRF_DDRTYPE_MASK; - - switch (ddr_type) { - case RK3399_PMUGRF_DDRTYPE_DDR3: - data->odt_dis_freq = data->timing.ddr3_odt_dis_freq; - break; - case RK3399_PMUGRF_DDRTYPE_LPDDR3: - data->odt_dis_freq = data->timing.lpddr3_odt_dis_freq; - break; - case RK3399_PMUGRF_DDRTYPE_LPDDR4: - data->odt_dis_freq = data->timing.lpddr4_odt_dis_freq; - break; - default: - ret = -EINVAL; - goto err_edev; - }; - -no_pmu: - arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, 0, 0, - ROCKCHIP_SIP_CONFIG_DRAM_INIT, - 0, 0, 0, 0, &res); - - /* - * In TF-A there is a platform SIP call to set the PD (power-down) - * timings and to enable or disable the ODT (on-die termination). - * This call needs three arguments as follows: - * - * arg0: - * bit[0-7] : sr_idle - * bit[8-15] : sr_mc_gate_idle - * bit[16-31] : standby idle - * arg1: - * bit[0-11] : pd_idle - * bit[16-27] : srpd_lite_idle - * arg2: - * bit[0] : odt enable - */ - data->odt_pd_arg0 = (data->timing.sr_idle & 0xff) | - ((data->timing.sr_mc_gate_idle & 0xff) << 8) | - ((data->timing.standby_idle & 0xffff) << 16); - data->odt_pd_arg1 = (data->timing.pd_idle & 0xfff) | - ((data->timing.srpd_lite_idle & 0xfff) << 16); - - /* - * We add a devfreq driver to our parent since it has a device tree node - * with operating points. - */ - if (dev_pm_opp_of_add_table(dev)) { - dev_err(dev, "Invalid operating-points in device tree.\n"); - ret = -EINVAL; - goto err_edev; - } - - of_property_read_u32(np, "upthreshold", - &data->ondemand_data.upthreshold); - of_property_read_u32(np, "downdifferential", - &data->ondemand_data.downdifferential); - - data->rate = clk_get_rate(data->dmc_clk); - - opp = devfreq_recommended_opp(dev, &data->rate, 0); - if (IS_ERR(opp)) { - ret = PTR_ERR(opp); - goto err_free_opp; - } - - data->rate = dev_pm_opp_get_freq(opp); - data->volt = dev_pm_opp_get_voltage(opp); - dev_pm_opp_put(opp); - - rk3399_devfreq_dmc_profile.initial_freq = data->rate; - - data->devfreq = devm_devfreq_add_device(dev, - &rk3399_devfreq_dmc_profile, - DEVFREQ_GOV_SIMPLE_ONDEMAND, - &data->ondemand_data); - if (IS_ERR(data->devfreq)) { - ret = PTR_ERR(data->devfreq); - goto err_free_opp; - } - - devm_devfreq_register_opp_notifier(dev, data->devfreq); - - data->dev = dev; - platform_set_drvdata(pdev, data); - - return 0; - -err_free_opp: - dev_pm_opp_of_remove_table(&pdev->dev); -err_edev: - devfreq_event_disable_edev(data->edev); - - return ret; -} - -static int rk3399_dmcfreq_remove(struct platform_device *pdev) -{ - struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(&pdev->dev); - - /* - * Before remove the opp table we need to unregister the opp notifier. - */ - devm_devfreq_unregister_opp_notifier(dmcfreq->dev, dmcfreq->devfreq); - dev_pm_opp_of_remove_table(dmcfreq->dev); - - return 0; -} - -static const struct of_device_id rk3399dmc_devfreq_of_match[] = { - { .compatible = "rockchip,rk3399-dmc" }, - { }, -}; -MODULE_DEVICE_TABLE(of, rk3399dmc_devfreq_of_match); - -static struct platform_driver rk3399_dmcfreq_driver = { - .probe = rk3399_dmcfreq_probe, - .remove = rk3399_dmcfreq_remove, - .driver = { - .name = "rk3399-dmc-freq", - .pm = &rk3399_dmcfreq_pm, - .of_match_table = rk3399dmc_devfreq_of_match, - }, -}; -module_platform_driver(rk3399_dmcfreq_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Lin Huang "); -MODULE_DESCRIPTION("RK3399 dmcfreq driver with devfreq framework"); diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 963ad64b8112..4cb817617498 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -194,6 +193,7 @@ struct rockchip_dmcfreq { int (*set_msch_readlatency)(unsigned int rl); }; +static struct rockchip_dmcfreq *rk_dmcfreq; static struct pm_qos_request pm_qos; static DECLARE_RWSEM(rockchip_dmcfreq_sem); @@ -1208,7 +1208,7 @@ int rockchip_dmcfreq_wait_complete(void) * CPUs only enter WFI when idle to make sure that * FIQn can quick response. */ - pm_qos_update_request(&pm_qos, 0); + cpu_latency_qos_update_request(&pm_qos, 0); if (wait_ctrl.dcf_en == 1) { /* start dcf */ @@ -1224,7 +1224,7 @@ int rockchip_dmcfreq_wait_complete(void) wait_event_timeout(wait_ctrl.wait_wq, (wait_ctrl.wait_flag == 0), msecs_to_jiffies(wait_ctrl.wait_time_out_ms)); - pm_qos_update_request(&pm_qos, PM_QOS_DEFAULT_VALUE); + cpu_latency_qos_update_request(&pm_qos, PM_QOS_DEFAULT_VALUE); disable_irq(wait_ctrl.complt_irq); return 0; @@ -1982,37 +1982,37 @@ static __maybe_unused int rv1126_dmc_init(struct platform_device *pdev, } static const struct of_device_id rockchip_dmcfreq_of_match[] = { -#ifdef CONFIG_CPU_PX30 +#if IS_ENABLED(CONFIG_CPU_PX30) { .compatible = "rockchip,px30-dmc", .data = px30_dmc_init }, #endif -#ifdef CONFIG_CPU_RK1808 +#if IS_ENABLED(CONFIG_CPU_RK1808) { .compatible = "rockchip,rk1808-dmc", .data = rk1808_dmc_init }, #endif -#ifdef CONFIG_CPU_RK312X +#if IS_ENABLED(CONFIG_CPU_RK312X) { .compatible = "rockchip,rk3128-dmc", .data = rk3128_dmc_init }, #endif -#ifdef CONFIG_CPU_RK322X +#if IS_ENABLED(CONFIG_CPU_RK322X) { .compatible = "rockchip,rk3228-dmc", .data = rk3228_dmc_init }, #endif -#ifdef CONFIG_CPU_RK3288 +#if IS_ENABLED(CONFIG_CPU_RK3288) { .compatible = "rockchip,rk3288-dmc", .data = rk3288_dmc_init }, #endif -#ifdef CONFIG_CPU_RK3308 +#if IS_ENABLED(CONFIG_CPU_RK3308) { .compatible = "rockchip,rk3308-dmc", .data = NULL }, #endif -#ifdef CONFIG_CPU_RK3328 +#if IS_ENABLED(CONFIG_CPU_RK3328) { .compatible = "rockchip,rk3328-dmc", .data = rk3328_dmc_init }, #endif -#ifdef CONFIG_CPU_RK3368 +#if IS_ENABLED(CONFIG_CPU_RK3368) { .compatible = "rockchip,rk3368-dmc", .data = rk3368_dmc_init }, #endif -#ifdef CONFIG_CPU_RK3399 +#if IS_ENABLED(CONFIG_CPU_RK3399) { .compatible = "rockchip,rk3399-dmc", .data = rk3399_dmc_init }, #endif -#ifdef CONFIG_CPU_RK3568 +#if IS_ENABLED(CONFIG_CPU_RK3568) { .compatible = "rockchip,rk3568-dmc", .data = rk3568_dmc_init }, #endif -#ifdef CONFIG_CPU_RV1126 +#if IS_ENABLED(CONFIG_CPU_RV1126) { .compatible = "rockchip,rv1126-dmc", .data = rv1126_dmc_init }, #endif { }, @@ -2473,31 +2473,23 @@ static void rockchip_dmcfreq_msch_rl_init(struct rockchip_dmcfreq *dmcfreq) rockchip_dmcfreq_set_msch_rl_work); } -void rockchip_dmcfreq_vop_bandwidth_update(struct devfreq *devfreq, - unsigned int bw_mbyte, - unsigned int plane_num) +void rockchip_dmcfreq_vop_bandwidth_update(struct dmcfreq_vop_info *vop_info) { - struct device *dev; - struct rockchip_dmcfreq *dmcfreq; + struct rockchip_dmcfreq *dmcfreq = rk_dmcfreq; unsigned long vop_last_rate, target = 0; unsigned int readlatency = 0; int i; - if (!devfreq) - return; - - dev = devfreq->dev.parent; - dmcfreq = dev_get_drvdata(dev); if (!dmcfreq) return; if (!dmcfreq->vop_pn_rl_tbl || !dmcfreq->set_msch_readlatency) goto vop_bw_tbl; for (i = 0; dmcfreq->vop_pn_rl_tbl[i].rl != CPUFREQ_TABLE_END; i++) { - if (plane_num >= dmcfreq->vop_pn_rl_tbl[i].pn) + if (vop_info->plane_num >= dmcfreq->vop_pn_rl_tbl[i].pn) readlatency = dmcfreq->vop_pn_rl_tbl[i].rl; } - dev_dbg(dmcfreq->dev, "pn=%u\n", plane_num); + dev_dbg(dmcfreq->dev, "pn=%u\n", vop_info->plane_num); if (readlatency) { cancel_delayed_work_sync(&dmcfreq->msch_rl_work); dmcfreq->is_msch_rl_work_started = false; @@ -2515,11 +2507,11 @@ vop_bw_tbl: return; for (i = 0; dmcfreq->vop_bw_tbl[i].freq != CPUFREQ_TABLE_END; i++) { - if (bw_mbyte >= dmcfreq->vop_bw_tbl[i].min) + if (vop_info->bw_mbyte >= dmcfreq->vop_bw_tbl[i].min) target = dmcfreq->vop_bw_tbl[i].freq; } - dev_dbg(dmcfreq->dev, "bw=%u\n", bw_mbyte); + dev_dbg(dmcfreq->dev, "bw=%u\n", vop_info->bw_mbyte); if (!target || target == dmcfreq->vop_req_rate) return; @@ -2532,25 +2524,17 @@ vop_bw_tbl: } EXPORT_SYMBOL(rockchip_dmcfreq_vop_bandwidth_update); -int rockchip_dmcfreq_vop_bandwidth_request(struct devfreq *devfreq, - unsigned int bw_mbyte) +int rockchip_dmcfreq_vop_bandwidth_request(struct dmcfreq_vop_info *vop_info) { - struct device *dev; - struct rockchip_dmcfreq *dmcfreq; + struct rockchip_dmcfreq *dmcfreq = rk_dmcfreq; unsigned long target = 0; int i; - if (!devfreq) - return 0; - - dev = devfreq->dev.parent; - dmcfreq = dev_get_drvdata(dev); - if (!dmcfreq || !dmcfreq->auto_freq_en || !dmcfreq->vop_bw_tbl) return 0; for (i = 0; dmcfreq->vop_bw_tbl[i].freq != CPUFREQ_TABLE_END; i++) { - if (bw_mbyte <= dmcfreq->vop_bw_tbl[i].max) { + if (vop_info->bw_mbyte <= dmcfreq->vop_bw_tbl[i].max) { target = dmcfreq->vop_bw_tbl[i].freq; break; } @@ -2676,8 +2660,8 @@ static int devfreq_dmc_ondemand_handler(struct devfreq *devfreq, devfreq_monitor_stop(devfreq); break; - case DEVFREQ_GOV_INTERVAL: - devfreq_interval_update(devfreq, (unsigned int *)data); + case DEVFREQ_GOV_UPDATE_INTERVAL: + devfreq_update_interval(devfreq, (unsigned int *)data); break; case DEVFREQ_GOV_SUSPEND: @@ -2760,7 +2744,7 @@ static int rockchip_dmcfreq_get_event(struct rockchip_dmcfreq *dmcfreq) struct device_node *events_np, *np = dev->of_node; int i, j, count, available_count = 0; - count = devfreq_event_get_edev_count(dev); + count = devfreq_event_get_edev_count(dev, "devfreq-events"); if (count < 0) { dev_dbg(dev, "failed to get count of devfreq-event dev\n"); return 0; @@ -2795,7 +2779,7 @@ static int rockchip_dmcfreq_get_event(struct rockchip_dmcfreq *dmcfreq) return -EINVAL; } dmcfreq->edev[j] = - devfreq_event_get_edev_by_phandle(dev, i); + devfreq_event_get_edev_by_phandle(dev, "devfreq-events", i); if (IS_ERR(dmcfreq->edev[j])) return -EPROBE_DEFER; j++; @@ -3250,8 +3234,7 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) return rockchip_dmcfreq_set_volt_only(data); } - pm_qos_add_request(&pm_qos, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_DEFAULT_VALUE); + cpu_latency_qos_add_request(&pm_qos, PM_QOS_DEFAULT_VALUE); platform_set_drvdata(pdev, data); ret = devfreq_add_governor(&devfreq_dmc_ondemand); @@ -3274,6 +3257,8 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) rockchip_set_system_status(SYS_STATUS_NORMAL); + rk_dmcfreq = data; + return 0; } diff --git a/include/soc/rockchip/rockchip_dmc.h b/include/soc/rockchip/rockchip_dmc.h index b2a74003bd3c..1076b3a7c152 100644 --- a/include/soc/rockchip/rockchip_dmc.h +++ b/include/soc/rockchip/rockchip_dmc.h @@ -31,16 +31,18 @@ #define SCREEN_DUAL_LVDS_10BIT 12 #define SCREEN_DP 13 -#ifdef CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ +struct dmcfreq_vop_info { + unsigned int bw_mbyte; + unsigned int plane_num; +}; + +#if IS_ENABLED(CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ) void rockchip_dmcfreq_lock(void); void rockchip_dmcfreq_lock_nested(void); void rockchip_dmcfreq_unlock(void); int rockchip_dmcfreq_wait_complete(void); -int rockchip_dmcfreq_vop_bandwidth_request(struct devfreq *devfreq, - unsigned int bw_mbyte); -void rockchip_dmcfreq_vop_bandwidth_update(struct devfreq *devfreq, - unsigned int bw_mbyte, - unsigned int plane_num); +int rockchip_dmcfreq_vop_bandwidth_request(struct dmcfreq_vop_info *vop_info); +void rockchip_dmcfreq_vop_bandwidth_update(struct dmcfreq_vop_info *vop_info); #else static inline void rockchip_dmcfreq_lock(void) @@ -61,16 +63,13 @@ static inline int rockchip_dmcfreq_wait_complete(void) } static inline int -rockchip_dmcfreq_vop_bandwidth_request(struct devfreq *devfreq, - unsigned int bw_mbyte) +rockchip_dmcfreq_vop_bandwidth_request(struct dmcfreq_vop_info *vop_info) { return 0; } static inline void -rockchip_dmcfreq_vop_bandwidth_update(struct devfreq *devfreq, - unsigned int bw_mbyte, - unsigned int plane_num) +rockchip_dmcfreq_vop_bandwidth_update(struct dmcfreq_vop_info *vop_info) { } #endif diff --git a/include/soc/rockchip/rockchip_sip.h b/include/soc/rockchip/rockchip_sip.h index c46a9ae2a2ab..1be62bb7a68a 100644 --- a/include/soc/rockchip/rockchip_sip.h +++ b/include/soc/rockchip/rockchip_sip.h @@ -15,6 +15,11 @@ #define ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE 0x05 #define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06 #define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07 -#define ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD 0x08 +#define ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION 0x08 +#define ROCKCHIP_SIP_CONFIG_DRAM_POST_SET_RATE 0x09 +#define ROCKCHIP_SIP_CONFIG_DRAM_SET_MSCH_RL 0x0a +#define ROCKCHIP_SIP_CONFIG_DRAM_DEBUG 0x0b +#define ROCKCHIP_SIP_CONFIG_MCU_START 0x0c +#define ROCKCHIP_SIP_CONFIG_DRAM_GET_FREQ_INFO 0x0e #endif