From patchwork Fri Jul 21 14:35:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Quentin Schulz X-Patchwork-Id: 108487 Delivered-To: patch@linaro.org Received: by 10.140.101.44 with SMTP id t41csp941956qge; Fri, 21 Jul 2017 08:41:14 -0700 (PDT) X-Received: by 10.84.247.1 with SMTP id n1mr8573157pll.314.1500651674165; Fri, 21 Jul 2017 08:41:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500651674; cv=none; d=google.com; s=arc-20160816; b=U8vjnuDxljWkPm0Oogdzmwtck+3oiYEnejVWvfPz9+a1NQSnYpH3U16sJEptWBofKI PDNJngiFwGlSu2bPY1RbPVYrHGRGPvmPjt3ncX5A9mCUwiWYJG6iGYYkrCmW5QI45Ija DuWNJ9XjvZ1W9j880VIC1zWepO9+jyvfjEzRcEX00P96BUM3MOrP10G+S4b550zlV3cj rF1/xFyHc1xGfVozthUrzatGExG9bM+xnoRhrdbnEBqTSrEDHiumVUlynlcyK1rqrl00 Qz8AAPAblg8LnBpCelon1ulJXFPc5N1lrivygpwlRtPYTjgVAeKJee5wRnPmtxJQ1R4L BGWA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=RrUk50kXYKNQhpe9qa3TGxjgxwTiagWN5f9CiMJ+yNA=; b=oC01n5l8zIk/dSk91rcWFlH0CwGk0lnHK6wb+W8f4Giqc7BC7cSRlrvWr2lfJcgvRp JU7ujj7RZp92bwcCRXdO3cH4M98Iu175ars2GjnX7hoPHZ/FtNQED302+5N/wyHbBpLn 6rmUXXtyYKJBKrUqt+OrNCgZR941rXLzfuzy4NlHQUMdX1EoEUyAbTFLGxaWx9DeYIxr DgxF8ObFyNQSkagtZN2ov0ftfTzXmJutKVMhNCIhKzh//gz9jB7dZbJMjCAJirsP3GSL WQUyjwC4r5x/GawcGpGTYc+JlGiK64p9LoonjfhzrwEjmR17MqtZERbV0JlrwO79GEBA hNQQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g3si3228225plb.210.2017.07.21.08.41.13; Fri, 21 Jul 2017 08:41:14 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754217AbdGUPht (ORCPT + 25 others); Fri, 21 Jul 2017 11:37:49 -0400 Received: from mail.free-electrons.com ([62.4.15.54]:43808 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751643AbdGUOfV (ORCPT ); Fri, 21 Jul 2017 10:35:21 -0400 Received: by mail.free-electrons.com (Postfix, from userid 110) id 723D221EF0; Fri, 21 Jul 2017 16:35:18 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.free-electrons.com (Postfix) with ESMTPSA id 16F5221DB9; Fri, 21 Jul 2017 16:35:18 +0200 (CEST) From: Quentin Schulz To: ulf.hansson@linaro.org, gregkh@linuxfoundation.org Cc: Hans de Goede , linus.walleij@linaro.org, shawn.lin@rock-chips.com, adrian.hunter@intel.com, baolin.wang@linaro.org, maxime.ripard@free-electrons.com, thomas.petazzoni@free-electrons.com, linux-kernel@vger.kernel.org, linux-mmc@vger.kernel.org, devel@driverdev.osuosl.org, icenowy@aosc.xyz, wens@csie.org Subject: [PATCH 2/2] mmc: Add mmc_force_detect_change_begin / _end functions Date: Fri, 21 Jul 2017 16:35:02 +0200 Message-Id: <20170721143502.1991-3-quentin.schulz@free-electrons.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170721143502.1991-1-quentin.schulz@free-electrons.com> References: <20170721143502.1991-1-quentin.schulz@free-electrons.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Hans de Goede Some sdio devices have a multiple stage bring-up process. Specifically the esp8089 (for which an out of tree driver is available) loads firmware on the first call to its sdio-drivers' probe function and then resets the device causing it to reboot from its RAM with the new firmware. When this sdio device reboots it comes back up in 1 bit 400 KHz mode again, and we need to walk through the whole ios negatiation and sdio setup again. There are 2 problems with this: 1) Typically these devices are soldered onto some (ARM) tablet / SBC PCB and as such are described in devicetree as "non-removable", which causes the mmc-core to scan them only once and not poll for the device dropping of the bus. Normally this is the right thing todo but in the eso8089 example we need the mmc-core to notice the module has disconnected (since it is now in 1 bit mode again it will not talk to the host in 4 bit mode). This can be worked around by using "broken-cd" in devicetree instead of "non-removable", but that is not a proper fix since the device really is non-removable. 2) When the mmc-core detects the device has disconnected it will poweroff the device, causing the RAM loaded firmware to be lost. This can be worked around in devicetree by using regulator-always-on (and avoiding the use of mmc-pwrseq), but again that is more of a hack then a proper fix. This commmit fixes 1) by adding a mmc_force_detect_change function which will cause scanning for device removal / insertion until a new device is detected. 2) Is fixed by a keep_power flag to the mmc_force_detect_change function which when set causes the mmc-core to keep the power to the device on during the rescan. Cc: Icenowy Zheng Cc: Maxime Ripard Cc: Chen-Yu Tsai Signed-off-by: Hans de Goede --- drivers/mmc/core/core.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- include/linux/mmc/host.h | 7 +++++++ 2 files changed, 49 insertions(+), 5 deletions(-) -- 2.11.0 diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 26431267a3e2..103badde910b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1620,8 +1620,11 @@ int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr, */ void mmc_power_up(struct mmc_host *host, u32 ocr) { - if (host->ios.power_mode == MMC_POWER_ON) + if (host->ios.power_mode == MMC_POWER_ON) { + if (host->ios.clock == 0) + goto set_clock; return; + } mmc_pwrseq_pre_power_on(host); @@ -1646,6 +1649,7 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) mmc_pwrseq_post_power_on(host); +set_clock: host->ios.clock = host->f_init; host->ios.power_mode = MMC_POWER_ON; @@ -1663,6 +1667,11 @@ void mmc_power_off(struct mmc_host *host) if (host->ios.power_mode == MMC_POWER_OFF) return; + if (host->rescan_keep_power) { + mmc_set_clock(host, 0); + return; + } + mmc_pwrseq_power_off(host); host->ios.clock = 0; @@ -1804,6 +1813,27 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay) } EXPORT_SYMBOL(mmc_detect_change); +/** + * mmc_force_detect_change - force rescanning of a MMC socket even if + * it is non-removable + * @host: host to rescan + * @delay: optional delay to wait before detection (jiffies) + * @keep_power: if set do not turn of vdd / call pwrseq_off during rescan + * + * MMC drivers which need non-removable sdio devices to be rescanned + * (e.g. because the device reboots its fw after a firmware upload), + * can call this to force scanning the MMC socket for changes, even + * if it is non-removable. + */ +void mmc_force_detect_change(struct mmc_host *host, unsigned long delay, + bool keep_power) +{ + host->rescan_force = 1; + host->rescan_keep_power = keep_power; + _mmc_detect_change(host, delay, false); +} +EXPORT_SYMBOL(mmc_force_detect_change); + void mmc_init_erase(struct mmc_card *card) { unsigned int sz; @@ -2566,7 +2596,8 @@ void mmc_rescan(struct work_struct *work) return; /* If there is a non-removable card registered, only scan once */ - if (!mmc_card_is_removable(host) && host->rescan_entered) + if (!mmc_card_is_removable(host) && host->rescan_entered && + !host->rescan_force) return; host->rescan_entered = 1; @@ -2583,7 +2614,8 @@ void mmc_rescan(struct work_struct *work) * if there is a _removable_ card registered, check whether it is * still present */ - if (host->bus_ops && !host->bus_dead && mmc_card_is_removable(host)) + if (host->bus_ops && !host->bus_dead && + (mmc_card_is_removable(host) || host->rescan_force)) host->bus_ops->detect(host); host->detect_change = 0; @@ -2616,15 +2648,20 @@ void mmc_rescan(struct work_struct *work) } for (i = 0; i < ARRAY_SIZE(freqs); i++) { - if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) + if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) { + if (host->rescan_force) { + host->rescan_force = 0; + host->rescan_keep_power = 0; + } break; + } if (freqs[i] <= host->f_min) break; } mmc_release_host(host); out: - if (host->caps & MMC_CAP_NEEDS_POLL) + if ((host->caps & MMC_CAP_NEEDS_POLL) || host->rescan_force) mmc_schedule_delayed_work(&host->detect, HZ); } diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index ebd1cebbef0c..d56d79867bbd 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -338,6 +338,8 @@ struct mmc_host { int rescan_disable; /* disable card detection */ int rescan_entered; /* used with nonremovable devices */ + int rescan_force; /* force rescan of (nonremovable) devices */ + int rescan_keep_power; /* Do not power off card */ int need_retune; /* re-tuning is needed */ int hold_retune; /* hold off re-tuning */ @@ -420,6 +422,11 @@ int mmc_power_save_host(struct mmc_host *host); int mmc_power_restore_host(struct mmc_host *host); void mmc_detect_change(struct mmc_host *, unsigned long delay); + +/* HdG: HACK HACK HACK do not upstream */ +#define MMC_HAS_FORCE_DETECT_CHANGE +void mmc_force_detect_change(struct mmc_host *host, unsigned long delay, + bool keep_power); void mmc_request_done(struct mmc_host *, struct mmc_request *); void mmc_command_done(struct mmc_host *host, struct mmc_request *mrq);