diff options
author | Tony Xie <tony.xie@rock-chips.com> | 2018-04-07 16:01:46 +0800 |
---|---|---|
committer | Tao Huang <huangtao@rock-chips.com> | 2018-04-26 16:44:24 +0800 |
commit | 5c1ca8c14c865913247164d225ce9792298caf25 (patch) | |
tree | 50b763ac44364eb1c70a97337ef71732d491757f /drivers | |
parent | 46cb48d1dca64daca199f964d517cb22bb550549 (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.c | 5 | ||||
-rw-r--r-- | drivers/devfreq/rockchip_dmc.c | 65 |
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; } |