diff options
author | Enric Balletbo i Serra <enric.balletbo@collabora.com> | 2019-03-21 19:14:38 -0400 |
---|---|---|
committer | MyungJoo Ham <myungjoo.ham@samsung.com> | 2019-04-15 20:29:18 -0400 |
commit | 9173c5ceb035aab28171cd74dfddf27f47213b99 (patch) | |
tree | 119a090f9d37e7281c6d807b18c838b3b1131ffa | |
parent | adfe3b76608ffe547af5a74415f15499b798f32a (diff) |
PM / devfreq: rk3399_dmc: Pass ODT and auto power down parameters to TF-A.
Trusted Firmware-A (TF-A) for rk3399 implements a SiP call to get the
on-die termination (ODT) and auto power down parameters from kernel,
this patch adds the functionality to do this. Also, if DDR clock
frequency is lower than the on-die termination (ODT) disable frequency
this driver should disable the DDR ODT.
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Gaƫl PORTAY <gael.portay@collabora.com>
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
-rw-r--r-- | drivers/devfreq/rk3399_dmc.c | 71 | ||||
-rw-r--r-- | include/soc/rockchip/rockchip_sip.h | 1 |
2 files changed, 71 insertions, 1 deletions
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c index a228dad2bee4..567c034d0301 100644 --- a/drivers/devfreq/rk3399_dmc.c +++ b/drivers/devfreq/rk3399_dmc.c | |||
@@ -18,14 +18,17 @@ | |||
18 | #include <linux/devfreq.h> | 18 | #include <linux/devfreq.h> |
19 | #include <linux/devfreq-event.h> | 19 | #include <linux/devfreq-event.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/mfd/syscon.h> | ||
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
22 | #include <linux/of.h> | 23 | #include <linux/of.h> |
23 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
24 | #include <linux/pm_opp.h> | 25 | #include <linux/pm_opp.h> |
26 | #include <linux/regmap.h> | ||
25 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
26 | #include <linux/rwsem.h> | 28 | #include <linux/rwsem.h> |
27 | #include <linux/suspend.h> | 29 | #include <linux/suspend.h> |
28 | 30 | ||
31 | #include <soc/rockchip/rk3399_grf.h> | ||
29 | #include <soc/rockchip/rockchip_sip.h> | 32 | #include <soc/rockchip/rockchip_sip.h> |
30 | 33 | ||
31 | struct dram_timing { | 34 | struct dram_timing { |
@@ -69,8 +72,11 @@ struct rk3399_dmcfreq { | |||
69 | struct mutex lock; | 72 | struct mutex lock; |
70 | struct dram_timing timing; | 73 | struct dram_timing timing; |
71 | struct regulator *vdd_center; | 74 | struct regulator *vdd_center; |
75 | struct regmap *regmap_pmu; | ||
72 | unsigned long rate, target_rate; | 76 | unsigned long rate, target_rate; |
73 | unsigned long volt, target_volt; | 77 | unsigned long volt, target_volt; |
78 | unsigned int odt_dis_freq; | ||
79 | int odt_pd_arg0, odt_pd_arg1; | ||
74 | }; | 80 | }; |
75 | 81 | ||
76 | static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, | 82 | static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, |
@@ -80,6 +86,8 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, | |||
80 | struct dev_pm_opp *opp; | 86 | struct dev_pm_opp *opp; |
81 | unsigned long old_clk_rate = dmcfreq->rate; | 87 | unsigned long old_clk_rate = dmcfreq->rate; |
82 | unsigned long target_volt, target_rate; | 88 | unsigned long target_volt, target_rate; |
89 | struct arm_smccc_res res; | ||
90 | bool odt_enable = false; | ||
83 | int err; | 91 | int err; |
84 | 92 | ||
85 | opp = devfreq_recommended_opp(dev, freq, flags); | 93 | opp = devfreq_recommended_opp(dev, freq, flags); |
@@ -95,6 +103,19 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, | |||
95 | 103 | ||
96 | mutex_lock(&dmcfreq->lock); | 104 | mutex_lock(&dmcfreq->lock); |
97 | 105 | ||
106 | if (target_rate >= dmcfreq->odt_dis_freq) | ||
107 | odt_enable = true; | ||
108 | |||
109 | /* | ||
110 | * This makes a SMC call to the TF-A to set the DDR PD (power-down) | ||
111 | * timings and to enable or disable the ODT (on-die termination) | ||
112 | * resistors. | ||
113 | */ | ||
114 | arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, dmcfreq->odt_pd_arg0, | ||
115 | dmcfreq->odt_pd_arg1, | ||
116 | ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD, | ||
117 | odt_enable, 0, 0, 0, &res); | ||
118 | |||
98 | /* | 119 | /* |
99 | * If frequency scaling from low to high, adjust voltage first. | 120 | * If frequency scaling from low to high, adjust voltage first. |
100 | * If frequency scaling from high to low, adjust frequency first. | 121 | * If frequency scaling from high to low, adjust frequency first. |
@@ -294,11 +315,13 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev) | |||
294 | { | 315 | { |
295 | struct arm_smccc_res res; | 316 | struct arm_smccc_res res; |
296 | struct device *dev = &pdev->dev; | 317 | struct device *dev = &pdev->dev; |
297 | struct device_node *np = pdev->dev.of_node; | 318 | struct device_node *np = pdev->dev.of_node, *node; |
298 | struct rk3399_dmcfreq *data; | 319 | struct rk3399_dmcfreq *data; |
299 | int ret, index, size; | 320 | int ret, index, size; |
300 | uint32_t *timing; | 321 | uint32_t *timing; |
301 | struct dev_pm_opp *opp; | 322 | struct dev_pm_opp *opp; |
323 | u32 ddr_type; | ||
324 | u32 val; | ||
302 | 325 | ||
303 | data = devm_kzalloc(dev, sizeof(struct rk3399_dmcfreq), GFP_KERNEL); | 326 | data = devm_kzalloc(dev, sizeof(struct rk3399_dmcfreq), GFP_KERNEL); |
304 | if (!data) | 327 | if (!data) |
@@ -354,11 +377,57 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev) | |||
354 | } | 377 | } |
355 | } | 378 | } |
356 | 379 | ||
380 | node = of_parse_phandle(np, "rockchip,pmu", 0); | ||
381 | if (node) { | ||
382 | data->regmap_pmu = syscon_node_to_regmap(node); | ||
383 | if (IS_ERR(data->regmap_pmu)) | ||
384 | return PTR_ERR(data->regmap_pmu); | ||
385 | } | ||
386 | |||
387 | regmap_read(data->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); | ||
388 | ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) & | ||
389 | RK3399_PMUGRF_DDRTYPE_MASK; | ||
390 | |||
391 | switch (ddr_type) { | ||
392 | case RK3399_PMUGRF_DDRTYPE_DDR3: | ||
393 | data->odt_dis_freq = data->timing.ddr3_odt_dis_freq; | ||
394 | break; | ||
395 | case RK3399_PMUGRF_DDRTYPE_LPDDR3: | ||
396 | data->odt_dis_freq = data->timing.lpddr3_odt_dis_freq; | ||
397 | break; | ||
398 | case RK3399_PMUGRF_DDRTYPE_LPDDR4: | ||
399 | data->odt_dis_freq = data->timing.lpddr4_odt_dis_freq; | ||
400 | break; | ||
401 | default: | ||
402 | return -EINVAL; | ||
403 | }; | ||
404 | |||
357 | arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, 0, 0, | 405 | arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, 0, 0, |
358 | ROCKCHIP_SIP_CONFIG_DRAM_INIT, | 406 | ROCKCHIP_SIP_CONFIG_DRAM_INIT, |
359 | 0, 0, 0, 0, &res); | 407 | 0, 0, 0, 0, &res); |
360 | 408 | ||
361 | /* | 409 | /* |
410 | * In TF-A there is a platform SIP call to set the PD (power-down) | ||
411 | * timings and to enable or disable the ODT (on-die termination). | ||
412 | * This call needs three arguments as follows: | ||
413 | * | ||
414 | * arg0: | ||
415 | * bit[0-7] : sr_idle | ||
416 | * bit[8-15] : sr_mc_gate_idle | ||
417 | * bit[16-31] : standby idle | ||
418 | * arg1: | ||
419 | * bit[0-11] : pd_idle | ||
420 | * bit[16-27] : srpd_lite_idle | ||
421 | * arg2: | ||
422 | * bit[0] : odt enable | ||
423 | */ | ||
424 | data->odt_pd_arg0 = (data->timing.sr_idle & 0xff) | | ||
425 | ((data->timing.sr_mc_gate_idle & 0xff) << 8) | | ||
426 | ((data->timing.standby_idle & 0xffff) << 16); | ||
427 | data->odt_pd_arg1 = (data->timing.pd_idle & 0xfff) | | ||
428 | ((data->timing.srpd_lite_idle & 0xfff) << 16); | ||
429 | |||
430 | /* | ||
362 | * We add a devfreq driver to our parent since it has a device tree node | 431 | * We add a devfreq driver to our parent since it has a device tree node |
363 | * with operating points. | 432 | * with operating points. |
364 | */ | 433 | */ |
diff --git a/include/soc/rockchip/rockchip_sip.h b/include/soc/rockchip/rockchip_sip.h index 7e28092c4d3d..ad9482c56797 100644 --- a/include/soc/rockchip/rockchip_sip.h +++ b/include/soc/rockchip/rockchip_sip.h | |||
@@ -23,5 +23,6 @@ | |||
23 | #define ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE 0x05 | 23 | #define ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE 0x05 |
24 | #define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06 | 24 | #define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06 |
25 | #define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07 | 25 | #define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07 |
26 | #define ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD 0x08 | ||
26 | 27 | ||
27 | #endif | 28 | #endif |