summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTony Xie <tony.xie@rock-chips.com>2018-04-07 16:01:46 +0800
committerTao Huang <huangtao@rock-chips.com>2018-04-26 16:44:24 +0800
commit5c1ca8c14c865913247164d225ce9792298caf25 (patch)
tree50b763ac44364eb1c70a97337ef71732d491757f /drivers
parent46cb48d1dca64daca199f964d517cb22bb550549 (diff)
PM / devfreq: rockchip_dmc: support wait_complete.
Change-Id: Ie3f173f632068f261b84a204bbd36b26b10e1981 Signed-off-by: Tony Xie <tony.xie@rock-chips.com> Signed-off-by: YouMin Chen <cym@rock-chips.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/rockchip/clk-ddr.c5
-rw-r--r--drivers/devfreq/rockchip_dmc.c65
2 files changed, 67 insertions, 3 deletions
diff --git a/drivers/clk/rockchip/clk-ddr.c b/drivers/clk/rockchip/clk-ddr.c
index 3e3b65732e7a..90d40388bb9b 100644
--- a/drivers/clk/rockchip/clk-ddr.c
+++ b/drivers/clk/rockchip/clk-ddr.c
@@ -23,6 +23,7 @@
#include <linux/of.h>
#include <linux/rockchip/rockchip_sip.h>
#include <linux/slab.h>
+#include <soc/rockchip/rockchip_dmc.h>
#include <soc/rockchip/rockchip_sip.h>
#include <soc/rockchip/scpi.h>
#include <uapi/drm/drm_mode.h>
@@ -219,6 +220,7 @@ struct share_params {
* 0: never wait flag1
*/
u32 wait_flag0;
+ u32 complt_hwirq;
/* if need, add parameter after */
};
@@ -261,6 +263,9 @@ static int rockchip_ddrclk_sip_set_rate_v2(struct clk_hw *hw,
res = sip_smc_dram(SHARE_PAGE_TYPE_DDR, 0,
ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE);
+ if ((int)res.a1 == SIP_RET_SET_RATE_TIMEOUT)
+ rockchip_dmcfreq_wait_complete();
+
return res.a0;
}
diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c
index f8916bd9659c..79a634812051 100644
--- a/drivers/devfreq/rockchip_dmc.c
+++ b/drivers/devfreq/rockchip_dmc.c
@@ -28,8 +28,10 @@
#include <linux/fb.h>
#include <linux/input.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/reboot.h>
@@ -100,6 +102,7 @@ struct share_params {
* 0: never wait flag1
*/
u32 wait_flag0;
+ u32 complt_hwirq;
/* if need, add parameter after */
};
@@ -1578,16 +1581,50 @@ static int rockchip_ddr_set_auto_self_refresh(uint32_t en)
return res.a0;
}
+struct dmcfreq_wait_ctrl_t {
+ wait_queue_head_t wait_wq;
+ int wait_flag;
+ int wait_en;
+ int wait_time_out_ms;
+};
+
+static struct dmcfreq_wait_ctrl_t wait_ctrl;
+
+static irqreturn_t wait_complete_irq(int irqno, void *dev_id)
+{
+ struct dmcfreq_wait_ctrl_t *ctrl = dev_id;
+
+ ctrl->wait_flag = 0;
+ wake_up(&ctrl->wait_wq);
+ return IRQ_HANDLED;
+}
+
+int rockchip_dmcfreq_wait_complete(void)
+{
+ if (!wait_ctrl.wait_en) {
+ pr_err("%s: Do not support time out!\n", __func__);
+ return 0;
+ }
+ wait_ctrl.wait_flag = -1;
+ wait_event_timeout(wait_ctrl.wait_wq, (wait_ctrl.wait_flag == 0),
+ msecs_to_jiffies(wait_ctrl.wait_time_out_ms));
+ return 0;
+}
+
static int px30_dmc_init(struct platform_device *pdev,
struct rockchip_dmcfreq *dmcfreq)
{
struct arm_smccc_res res;
u32 size;
+ int ret;
+ int complt_irq;
+ u32 complt_hwirq;
+ struct irq_data *complt_irq_data;
res = sip_smc_dram(0, 0,
ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION);
dev_notice(&pdev->dev, "current ATF version 0x%lx!\n", res.a1);
- if (res.a0 || res.a1 < 0x101) {
+ if (res.a0 || res.a1 < 0x103) {
dev_err(&pdev->dev,
"trusted firmware need to update or is invalid!\n");
return -ENXIO;
@@ -1610,6 +1647,28 @@ static int px30_dmc_init(struct platform_device *pdev,
of_get_px30_timings(&pdev->dev, pdev->dev.of_node,
(uint32_t *)ddr_psci_param);
+ init_waitqueue_head(&wait_ctrl.wait_wq);
+ wait_ctrl.wait_en = 1;
+ wait_ctrl.wait_time_out_ms = 17 * 5;
+
+ complt_irq = platform_get_irq_byname(pdev, "complete_irq");
+ if (complt_irq < 0) {
+ dev_err(&pdev->dev, "no IRQ for complete_irq: %d\n",
+ complt_irq);
+ return complt_irq;
+ }
+
+ ret = devm_request_irq(&pdev->dev, complt_irq, wait_complete_irq,
+ 0, dev_name(&pdev->dev), &wait_ctrl);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "cannot request complete_irq\n");
+ return ret;
+ }
+
+ complt_irq_data = irq_get_irq_data(complt_irq);
+ complt_hwirq = irqd_to_hwirq(complt_irq_data);
+ ddr_psci_param->complt_hwirq = complt_hwirq;
+
res = sip_smc_dram(SHARE_PAGE_TYPE_DDR, 0,
ROCKCHIP_SIP_CONFIG_DRAM_INIT);
if (res.a0) {
@@ -2995,8 +3054,6 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev)
dev_err(dev, "failed to register input handler\n");
}
- rockchip_set_system_status(SYS_STATUS_NORMAL);
-
ret = ddr_power_model_simple_init(data);
if (!ret) {
@@ -3012,6 +3069,8 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev)
}
}
+ rockchip_set_system_status(SYS_STATUS_NORMAL);
+
return 0;
}