summaryrefslogtreecommitdiff
path: root/drivers/devfreq/rockchip_dmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/devfreq/rockchip_dmc.c')
-rw-r--r--drivers/devfreq/rockchip_dmc.c65
1 files changed, 62 insertions, 3 deletions
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;
}