From 0a34eb1232490d5e15764696c8e2c49fed9153c8 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Thu, 17 Sep 2020 00:10:50 +0200 Subject: [PATCH 186/351] misc: modem-power: Add fastboot powerup mode This may work with a patched bootloader from https://github.com/Biktorgj Signed-off-by: Ondrej Jirman --- drivers/misc/modem-power.c | 53 +++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/drivers/misc/modem-power.c b/drivers/misc/modem-power.c index 1a1ba4bf7841..aee4479b0d6a 100644 --- a/drivers/misc/modem-power.c +++ b/drivers/misc/modem-power.c @@ -178,6 +178,7 @@ enum { MPWR_F_GOT_PDN, /* config options */ MPWR_F_DUMB_POWERUP, + MPWR_F_FASTBOOT_POWERUP, /* file */ MPWR_F_OPEN, MPWR_F_OVERFLOW, @@ -386,11 +387,13 @@ static int mpwr_eg25_power_up(struct mpwr_dev* mpwr) { struct gpio_desc *pwrkey_gpio = mpwr_eg25_get_pwrkey_gpio(mpwr); bool wakeup_ok, status_ok; - bool needs_restart = false; + bool needs_restart = false, fastboot; u32 speed = 115200; int ret, i, off; ktime_t start; + fastboot = test_and_clear_bit(MPWR_F_FASTBOOT_POWERUP, mpwr->flags); + if (regulator_is_enabled(mpwr->regulator)) dev_warn(mpwr->dev, "regulator was already enabled during powerup"); @@ -405,7 +408,14 @@ static int mpwr_eg25_power_up(struct mpwr_dev* mpwr) /* Drive default gpio signals during powerup */ gpiod_direction_output(mpwr->host_ready_gpio, 1); - gpiod_direction_output(mpwr->enable_gpio, 1); + /* #W_DISABLE must be left pulled up during modem power up + * early on, because opensource bootloader uses this signal to enter + * fastboot mode when it's pulled down. + * + * This should be 1 for normal powerup and 0 for fastboot mode with + * special Biktor's firmware. + */ + gpiod_direction_output(mpwr->enable_gpio, !fastboot); gpiod_direction_output(mpwr->sleep_gpio, 0); gpiod_direction_output(mpwr->reset_gpio, 0); gpiod_direction_output(pwrkey_gpio, 0); @@ -419,6 +429,10 @@ static int mpwr_eg25_power_up(struct mpwr_dev* mpwr) msleep(200); gpiod_set_value(pwrkey_gpio, 0); + /* skip modem killswitch status checks in fastboot bootloader entry mode */ + if (fastboot) + goto open_serdev; + /* Switch status key to input, in case it's multiplexed with pwrkey. */ gpiod_direction_input(mpwr->status_gpio); @@ -464,6 +478,7 @@ static int mpwr_eg25_power_up(struct mpwr_dev* mpwr) if (test_and_clear_bit(MPWR_F_KILLSWITCHED, mpwr->flags)) sysfs_notify(&mpwr->dev->kobj, NULL, "killswitched"); +open_serdev: /* open serial console */ ret = serdev_device_open(mpwr->serdev); if (ret) { @@ -480,7 +495,7 @@ static int mpwr_eg25_power_up(struct mpwr_dev* mpwr) goto err_shutdown; } - if (test_bit(MPWR_F_DUMB_POWERUP, mpwr->flags)) + if (test_bit(MPWR_F_DUMB_POWERUP, mpwr->flags) || fastboot) goto powered_up; ret = mpwr_serdev_at_cmd_with_retry_ignore_timeout(mpwr, "AT&FE0", 1000, 30); @@ -1230,6 +1245,36 @@ static ssize_t dumb_powerup_store(struct device *dev, return len; } +static ssize_t fastboot_powerup_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mpwr_dev *mpwr = platform_get_drvdata(to_platform_device(dev)); + + return scnprintf(buf, PAGE_SIZE, "%u\n", + !!test_bit(MPWR_F_FASTBOOT_POWERUP, mpwr->flags)); +} + +static ssize_t fastboot_powerup_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 val; + int ret; + + ret = kstrtobool(buf, &val); + if (ret) + return ret; + + if (val) { + dev_warn(mpwr->dev, "Fastboot powerup needs a special bootloader!\n"); + set_bit(MPWR_F_FASTBOOT_POWERUP, mpwr->flags); + } else + clear_bit(MPWR_F_FASTBOOT_POWERUP, mpwr->flags); + + return len; +} + static ssize_t killswitched_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1268,6 +1313,7 @@ static ssize_t hard_reset_store(struct device *dev, static DEVICE_ATTR_RW(powered); static DEVICE_ATTR_WO(powered_blocking); static DEVICE_ATTR_RW(dumb_powerup); +static DEVICE_ATTR_RW(fastboot_powerup); static DEVICE_ATTR_RO(killswitched); static DEVICE_ATTR_RO(is_busy); static DEVICE_ATTR_WO(hard_reset); @@ -1276,6 +1322,7 @@ static struct attribute *mpwr_attrs[] = { &dev_attr_powered.attr, &dev_attr_powered_blocking.attr, &dev_attr_dumb_powerup.attr, + &dev_attr_fastboot_powerup.attr, &dev_attr_killswitched.attr, &dev_attr_is_busy.attr, &dev_attr_hard_reset.attr, -- 2.34.0