* Tony Lindgren <tony@xxxxxxxxxxx> [181206 07:48]: > * Johan Hovold <johan@xxxxxxxxxx> [181206 06:00]: > > How do switch modes by the way? > > The flash mode gets enabled with the control GPIOs. I just > did a quick test patch for phy-mapphone-mdm6600 using module > param for that. Then additionally the modem USB can be > multiplexed to the PC by configuring mode in phy-cpcap-usb > but I don't have a patch for that. FYI, below is the test patch against next I used for switching between normal mode and flash mode with a module param flash_mode if somebody wants to play with it. For flashing the modem, Android update-binary does it to deal with the signed modem firmware, I don't know of the details what happens there. Kishon, is there maybe some phy framework sysfs property we could use for switching phy modes? Regards, Tony 8< ----------------------- diff --git a/drivers/phy/motorola/phy-mapphone-mdm6600.c b/drivers/phy/motorola/phy-mapphone-mdm6600.c --- a/drivers/phy/motorola/phy-mapphone-mdm6600.c +++ b/drivers/phy/motorola/phy-mapphone-mdm6600.c @@ -80,6 +80,10 @@ enum phy_mdm6600_status { PHY_MDM6600_STATUS_UNDEFINED, }; +static bool flash_mode; +module_param(flash_mode, bool, 0); +MODULE_PARM_DESC(flash_mode, "Start mdm6600 in flash mode"); + static const char * const phy_mdm6600_status_name[] = { "off", "busy", "qc_dl", "ram_dl", "awake", @@ -249,6 +253,9 @@ static irqreturn_t phy_mdm6600_wakeirq_thread(int irq, void *data) struct phy_mdm6600 *ddata = data; struct gpio_desc *mode_gpio1; + if (flash_mode) + return IRQ_NONE; + mode_gpio1 = ddata->mode_gpios->desc[PHY_MDM6600_MODE1]; dev_dbg(ddata->dev, "OOB wake on mode_gpio1: %i\n", gpiod_get_value(mode_gpio1)); @@ -377,8 +384,13 @@ static int phy_mdm6600_device_power_on(struct phy_mdm6600 *ddata) * to configure USB flashing mode later on based on a module * parameter. */ - gpiod_set_value_cansleep(mode_gpio0, 0); - gpiod_set_value_cansleep(mode_gpio1, 0); + if (flash_mode) { + gpiod_set_value_cansleep(mode_gpio0, 1); + gpiod_set_value_cansleep(mode_gpio1, 1); + } else { + gpiod_set_value_cansleep(mode_gpio0, 0); + gpiod_set_value_cansleep(mode_gpio1, 0); + } /* Request start-up mode */ phy_mdm6600_cmd(ddata, PHY_MDM6600_CMD_NO_BYPASS); @@ -414,7 +426,12 @@ static int phy_mdm6600_device_power_on(struct phy_mdm6600 *ddata) dev_err(ddata->dev, "Timed out powering up\n"); } - /* Reconfigure mode1 GPIO as input for OOB wake */ + /* Maybe reconfigure mode1 GPIO as input for OOB wake? */ + if (flash_mode) { + dev_info(ddata->dev, "Started in flash mode\n"); + goto done; + } + gpiod_direction_input(mode_gpio1); wakeirq = gpiod_to_irq(mode_gpio1); @@ -431,7 +448,7 @@ static int phy_mdm6600_device_power_on(struct phy_mdm6600 *ddata) if (error) dev_warn(ddata->dev, "no modem wakeirq irq%i: %i\n", wakeirq, error); - +done: ddata->running = true; return error; @@ -499,6 +516,9 @@ static void phy_mdm6600_modem_wake(struct work_struct *work) { struct phy_mdm6600 *ddata; + if (flash_mode) + return; + ddata = container_of(work, struct phy_mdm6600, modem_wake_work.work); phy_mdm6600_wake_modem(ddata); schedule_delayed_work(&ddata->modem_wake_work, @@ -509,6 +529,9 @@ static int __maybe_unused phy_mdm6600_runtime_suspend(struct device *dev) { struct phy_mdm6600 *ddata = dev_get_drvdata(dev); + if (flash_mode) + return 0; + cancel_delayed_work_sync(&ddata->modem_wake_work); ddata->awake = false; @@ -519,6 +542,9 @@ static int __maybe_unused phy_mdm6600_runtime_resume(struct device *dev) { struct phy_mdm6600 *ddata = dev_get_drvdata(dev); + if (flash_mode) + return 0; + phy_mdm6600_modem_wake(&ddata->modem_wake_work.work); ddata->awake = true; -- 2.19.2