From 79a7e75223d9bf51a663da2cef8e3fa0d73014b5 Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Mon, 8 Apr 2024 11:25:40 +0800 Subject: [PATCH] mfd: rk806: Enable vdc irq wakeup system This function is mainly used for ultra suspend mode, which wakes up the system through the VDC interrupt of the PMIC by plugging in the charger. Signed-off-by: shengfei Xu Change-Id: I9c5ab1aeb067f4d0290f9a153675c3b4b5887920 --- drivers/mfd/rk806-core.c | 57 +++++++++++++++++++++++++++++++++++++++ include/linux/mfd/rk806.h | 1 + 2 files changed, 58 insertions(+) diff --git a/drivers/mfd/rk806-core.c b/drivers/mfd/rk806-core.c index 1ab83fbf397c..869653d67cfb 100644 --- a/drivers/mfd/rk806-core.c +++ b/drivers/mfd/rk806-core.c @@ -614,6 +614,58 @@ static int rk806_low_power_irqs(struct rk806 *rk806) return 0; } +static irqreturn_t rk806_vdc_irq(int irq, void *data) +{ + struct rk806 *rk806 = data; + + pm_wakeup_dev_event(rk806->dev, 2000, false); + return IRQ_HANDLED; +} + +static void rk806_vdc_irqs_init(struct rk806 *rk806) +{ + int ret, vdc_irq_fall, vdc_irq_rise; + + if (!rk806->pdata->vdc_wakeup_enable) + return; + + vdc_irq_rise = regmap_irq_get_virq(rk806->irq_data, RK806_IRQ_VDC_RISE); + if (vdc_irq_rise < 0) { + dev_err(rk806->dev, "RK806: IRQ_VDC_RISE get failed!\n"); + return; + } + + ret = devm_request_threaded_irq(rk806->dev, vdc_irq_rise, + NULL, + rk806_vdc_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "rk806_vdc_rise", rk806); + if (ret) { + dev_err(rk806->dev, "rk806: vdc_irq_rise request failed!\n"); + return; + } + enable_irq_wake(vdc_irq_rise); + + vdc_irq_fall = regmap_irq_get_virq(rk806->irq_data, RK806_IRQ_VDC_FALL); + if (vdc_irq_fall < 0) { + dev_err(rk806->dev, "RK806: IRQ_VDC_FALL get failed!\n"); + return; + } + + ret = devm_request_threaded_irq(rk806->dev, vdc_irq_fall, + NULL, + rk806_vdc_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "rk806_vdc_fall", rk806); + if (ret) { + dev_err(rk806->dev, "rk806: vdc_irq_fall request failed!\n"); + return; + } + enable_irq_wake(vdc_irq_fall); + device_init_wakeup(rk806->dev, true); +} + + static int rk806_parse_dt(struct rk806 *rk806) { struct rk806_platform_data *pdata; @@ -627,6 +679,7 @@ static int rk806_parse_dt(struct rk806 *rk806) pdata->shutdown_temperture_threshold = 160; pdata->hotdie_temperture_threshold = 115; pdata->force_shutdown_enable = 1; + pdata->vdc_wakeup_enable = 0; ret = device_property_read_u32(dev, "low_voltage_threshold", @@ -678,6 +731,9 @@ static int rk806_parse_dt(struct rk806 *rk806) if (device_property_read_bool(dev, "pwron-on-time-500ms")) rk806_field_write(rk806, PWRON_ON_TIME, 0x00); + if (device_property_read_bool(dev, "vdc-wakeup-enable")) + pdata->vdc_wakeup_enable = 1; + return 0; } @@ -706,6 +762,7 @@ static int rk806_init(struct rk806 *rk806) rk806_field_write(rk806, ENB2_2M, 0x01); rk806_low_power_irqs(rk806); + rk806_vdc_irqs_init(rk806); return 0; } diff --git a/include/linux/mfd/rk806.h b/include/linux/mfd/rk806.h index 7735121592c8..e6181bb24257 100644 --- a/include/linux/mfd/rk806.h +++ b/include/linux/mfd/rk806.h @@ -491,6 +491,7 @@ struct rk806_platform_data { int force_shutdown_enable; int shutdown_temperture_threshold; int hotdie_temperture_threshold; + int vdc_wakeup_enable; }; struct rk806_pin_info {