164 lines
4.5 KiB
Diff
164 lines
4.5 KiB
Diff
|
From 0d7dd2b992c85d554809b34e70a127c25e3362c6 Mon Sep 17 00:00:00 2001
|
||
|
From: Ondrej Jirman <megous@megous.com>
|
||
|
Date: Tue, 8 Sep 2020 02:51:57 +0200
|
||
|
Subject: [PATCH 261/478] misc: modem-power: Add blocking variant of sysfs
|
||
|
power state update function
|
||
|
|
||
|
Makes writing modem powerup scripts easier.
|
||
|
|
||
|
Signed-off-by: Ondrej Jirman <megous@megous.com>
|
||
|
---
|
||
|
drivers/misc/modem-power.c | 77 +++++++++++++++++++++++++-------------
|
||
|
1 file changed, 50 insertions(+), 27 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/misc/modem-power.c b/drivers/misc/modem-power.c
|
||
|
index 5cb4e76c78ef..68aa7ecc6a3a 100644
|
||
|
--- a/drivers/misc/modem-power.c
|
||
|
+++ b/drivers/misc/modem-power.c
|
||
|
@@ -944,14 +944,7 @@ static void mpwr_power_down(struct mpwr_dev* mpwr)
|
||
|
|
||
|
dev_info(dev, "powering down");
|
||
|
|
||
|
- set_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
|
||
|
- sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
|
||
|
-
|
||
|
ret = mpwr->variant->power_down(mpwr);
|
||
|
-
|
||
|
- clear_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
|
||
|
- sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
|
||
|
-
|
||
|
if (ret) {
|
||
|
dev_err(dev, "power down failed");
|
||
|
} else {
|
||
|
@@ -978,14 +971,7 @@ static void mpwr_power_up(struct mpwr_dev* mpwr)
|
||
|
|
||
|
dev_info(dev, "powering up");
|
||
|
|
||
|
- set_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
|
||
|
- sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
|
||
|
-
|
||
|
ret = mpwr->variant->power_up(mpwr);
|
||
|
-
|
||
|
- clear_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
|
||
|
- sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
|
||
|
-
|
||
|
if (ret) {
|
||
|
dev_err(dev, "power up failed");
|
||
|
} else {
|
||
|
@@ -1099,9 +1085,27 @@ static void mpwr_work_handler(struct work_struct *work)
|
||
|
|
||
|
mutex_unlock(&mpwr->modem_lock);
|
||
|
|
||
|
+ clear_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
|
||
|
+ sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
|
||
|
+ wake_up(&mpwr->wait);
|
||
|
+
|
||
|
pm_relax(mpwr->dev);
|
||
|
}
|
||
|
|
||
|
+static void mpwr_request_power_change(struct mpwr_dev* mpwr, int request)
|
||
|
+{
|
||
|
+ unsigned long flags;
|
||
|
+
|
||
|
+ set_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
|
||
|
+ sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
|
||
|
+
|
||
|
+ spin_lock_irqsave(&mpwr->lock, flags);
|
||
|
+ mpwr->last_request = request;
|
||
|
+ spin_unlock_irqrestore(&mpwr->lock, flags);
|
||
|
+
|
||
|
+ queue_work(mpwr->wq, &mpwr->power_work);
|
||
|
+}
|
||
|
+
|
||
|
static irqreturn_t mpwr_gpio_isr(int irq, void *dev_id)
|
||
|
{
|
||
|
struct mpwr_dev *mpwr = dev_id;
|
||
|
@@ -1162,7 +1166,6 @@ static ssize_t powered_store(struct device *dev,
|
||
|
const char *buf, size_t len)
|
||
|
{
|
||
|
struct mpwr_dev *mpwr = platform_get_drvdata(to_platform_device(dev));
|
||
|
- unsigned long flags;
|
||
|
bool status;
|
||
|
int ret;
|
||
|
|
||
|
@@ -1170,11 +1173,35 @@ static ssize_t powered_store(struct device *dev,
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
|
||
|
- spin_lock_irqsave(&mpwr->lock, flags);
|
||
|
- mpwr->last_request = status ? MPWR_REQ_PWUP : MPWR_REQ_PWDN;
|
||
|
- spin_unlock_irqrestore(&mpwr->lock, flags);
|
||
|
+ mpwr_request_power_change(mpwr, status ? MPWR_REQ_PWUP : MPWR_REQ_PWDN);
|
||
|
|
||
|
- queue_work(mpwr->wq, &mpwr->power_work);
|
||
|
+ return len;
|
||
|
+}
|
||
|
+
|
||
|
+static ssize_t powered_blocking_store(struct device *dev,
|
||
|
+ struct device_attribute *attr,
|
||
|
+ const char *buf, size_t len)
|
||
|
+{
|
||
|
+ struct mpwr_dev *mpwr = platform_get_drvdata(to_platform_device(dev));
|
||
|
+ bool status;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ ret = kstrtobool(buf, &status);
|
||
|
+ if (ret)
|
||
|
+ return ret;
|
||
|
+
|
||
|
+ mpwr_request_power_change(mpwr, status ? MPWR_REQ_PWUP : MPWR_REQ_PWDN);
|
||
|
+
|
||
|
+ ret = wait_event_interruptible_timeout(mpwr->wait,
|
||
|
+ !test_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags),
|
||
|
+ msecs_to_jiffies(60000));
|
||
|
+ if (ret <= 0) {
|
||
|
+ dev_err(mpwr->dev, "Power state change timeout\n");
|
||
|
+ return -EIO;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!!status != !!test_bit(MPWR_F_POWERED, mpwr->flags))
|
||
|
+ return -EIO;
|
||
|
|
||
|
return len;
|
||
|
}
|
||
|
@@ -1260,25 +1287,20 @@ static ssize_t hard_reset_store(struct device *dev,
|
||
|
const char *buf, size_t len)
|
||
|
{
|
||
|
struct mpwr_dev *mpwr = platform_get_drvdata(to_platform_device(dev));
|
||
|
- unsigned long flags;
|
||
|
bool val;
|
||
|
int ret;
|
||
|
|
||
|
ret = kstrtobool(buf, &val);
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
-
|
||
|
- if (val) {
|
||
|
- spin_lock_irqsave(&mpwr->lock, flags);
|
||
|
- mpwr->last_request = MPWR_REQ_RESET;
|
||
|
- spin_unlock_irqrestore(&mpwr->lock, flags);
|
||
|
- queue_work(mpwr->wq, &mpwr->power_work);
|
||
|
- }
|
||
|
+ if (val)
|
||
|
+ mpwr_request_power_change(mpwr, MPWR_REQ_RESET);
|
||
|
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
static DEVICE_ATTR_RW(powered);
|
||
|
+static DEVICE_ATTR_WO(powered_blocking);
|
||
|
static DEVICE_ATTR_RW(dumb_powerup);
|
||
|
static DEVICE_ATTR_RW(wait_rdy);
|
||
|
static DEVICE_ATTR_RO(killswitched);
|
||
|
@@ -1287,6 +1309,7 @@ static DEVICE_ATTR_WO(hard_reset);
|
||
|
|
||
|
static struct attribute *mpwr_attrs[] = {
|
||
|
&dev_attr_powered.attr,
|
||
|
+ &dev_attr_powered_blocking.attr,
|
||
|
&dev_attr_dumb_powerup.attr,
|
||
|
&dev_attr_wait_rdy.attr,
|
||
|
&dev_attr_killswitched.attr,
|
||
|
--
|
||
|
2.35.3
|
||
|
|