Merge tag 'mmc-updates-for-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc

Pull MMC updates from Chris Ball:
 "MMC highlights for 3.15:

  Core:
   - CONFIG_MMC_UNSAFE_RESUME=y is now default behavior
   - DT bindings for SDHCI UHS, eMMC HS200, high-speed DDR, at 1.8/1.2V
   - Add GPIO descriptor based slot-gpio card detect API

  Drivers:
   - dw_mmc: Refactor SOCFPGA support as a variant inside dw_mmc-pltfm.c
   - mmci: Support HW busy detection on ux500
   - omap: Support MMC_ERASE
   - omap_hsmmc: Support MMC_PM_KEEP_POWER, MMC_PM_WAKE_SDIO_IRQ, (a)cmd23
   - rtsx: Support pre-req/post-req async
   - sdhci: Add support for Realtek RTS5250 controllers
   - sdhci-acpi: Add support for 80860F16, fix 80860F14/SDIO card detect
   - sdhci-msm: Add new driver for Qualcomm SDHCI chipset support
   - sdhci-pxav3: Add support for Marvell Armada 380 and 385 SoCs"

* tag 'mmc-updates-for-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (102 commits)
  mmc: sdhci-acpi: Intel SDIO has broken card detect
  mmc: sdhci-pxav3: add support for the Armada 38x SDHCI controller
  mmc: sdhci-msm: Add platform_execute_tuning implementation
  mmc: sdhci-msm: Initial support for Qualcomm chipsets
  mmc: sdhci-msm: Qualcomm SDHCI binding documentation
  sdhci: only reprogram retuning timer when flag is set
  mmc: rename ARCH_BCM to ARCH_BCM_MOBILE
  mmc: sdhci: Allow for irq being shared
  mmc: sdhci-acpi: Add device id 80860F16
  mmc: sdhci-acpi: Fix broken card detect for ACPI HID 80860F14
  mmc: slot-gpio: Add GPIO descriptor based CD GPIO API
  mmc: slot-gpio: Split out CD IRQ request into a separate function
  mmc: slot-gpio: Record GPIO descriptors instead of GPIO numbers
  Revert "dts: socfpga: Add support for SD/MMC on the SOCFPGA platform"
  mmc: sdhci-spear: use generic card detection gpio support
  mmc: sdhci-spear: remove support for power gpio
  mmc: sdhci-spear: simplify resource handling
  mmc: sdhci-spear: fix platform_data usage
  mmc: sdhci-spear: fix error handling paths for DT
  mmc: sdhci-bcm-kona: fix build errors when built-in
  ...
This commit is contained in:
Linus Torvalds
2014-04-09 08:39:39 -07:00
63 changed files with 2581 additions and 1170 deletions
@@ -26,9 +26,18 @@ Optional properties:
this system, even if the controller claims it is.
- cap-sd-highspeed: SD high-speed timing is supported
- cap-mmc-highspeed: MMC high-speed timing is supported
- sd-uhs-sdr12: SD UHS SDR12 speed is supported
- sd-uhs-sdr25: SD UHS SDR25 speed is supported
- sd-uhs-sdr50: SD UHS SDR50 speed is supported
- sd-uhs-sdr104: SD UHS SDR104 speed is supported
- sd-uhs-ddr50: SD UHS DDR50 speed is supported
- cap-power-off-card: powering off the card is safe
- cap-sdio-irq: enable SDIO IRQ signalling on this interface
- full-pwr-cycle: full power cycle of the card is supported
- mmc-highspeed-ddr-1_8v: eMMC high-speed DDR mode(1.8V I/O) is supported
- mmc-highspeed-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported
- mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
- mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
*NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
polarity properties, we have to fix the meaning of the "normal" and "inverted"
@@ -0,0 +1,55 @@
* Qualcomm SDHCI controller (sdhci-msm)
This file documents differences between the core properties in mmc.txt
and the properties used by the sdhci-msm driver.
Required properties:
- compatible: Should contain "qcom,sdhci-msm-v4".
- reg: Base address and length of the register in the following order:
- Host controller register map (required)
- SD Core register map (required)
- interrupts: Should contain an interrupt-specifiers for the interrupts:
- Host controller interrupt (required)
- pinctrl-names: Should contain only one value - "default".
- pinctrl-0: Should specify pin control groups used for this controller.
- clocks: A list of phandle + clock-specifier pairs for the clocks listed in clock-names.
- clock-names: Should contain the following:
"iface" - Main peripheral bus clock (PCLK/HCLK - AHB Bus clock) (required)
"core" - SDC MMC clock (MCLK) (required)
"bus" - SDCC bus voter clock (optional)
Example:
sdhc_1: sdhci@f9824900 {
compatible = "qcom,sdhci-msm-v4";
reg = <0xf9824900 0x11c>, <0xf9824000 0x800>;
interrupts = <0 123 0>;
bus-width = <8>;
non-removable;
vmmc = <&pm8941_l20>;
vqmmc = <&pm8941_s3>;
pinctrl-names = "default";
pinctrl-0 = <&sdc1_clk &sdc1_cmd &sdc1_data>;
clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>;
clock-names = "core", "iface";
};
sdhc_2: sdhci@f98a4900 {
compatible = "qcom,sdhci-msm-v4";
reg = <0xf98a4900 0x11c>, <0xf98a4000 0x800>;
interrupts = <0 125 0>;
bus-width = <4>;
cd-gpios = <&msmgpio 62 0x1>;
vmmc = <&pm8941_l21>;
vqmmc = <&pm8941_l13>;
pinctrl-names = "default";
pinctrl-0 = <&sdc2_clk &sdc2_cmd &sdc2_data>;
clocks = <&gcc GCC_SDCC2_APPS_CLK>, <&gcc GCC_SDCC2_AHB_CLK>;
clock-names = "core", "iface";
};
@@ -4,7 +4,14 @@ This file documents differences between the core properties in mmc.txt
and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers.
Required properties:
- compatible: Should be "mrvl,pxav2-mmc" or "mrvl,pxav3-mmc".
- compatible: Should be "mrvl,pxav2-mmc", "mrvl,pxav3-mmc" or
"marvell,armada-380-sdhci".
- reg:
* for "mrvl,pxav2-mmc" and "mrvl,pxav3-mmc", one register area for
the SDHCI registers.
* for "marvell,armada-380-sdhci", two register areas. The first one
for the SDHCI registers themselves, and the second one for the
AXI/Mbus bridge registers of the SDHCI unit.
Optional properties:
- mrvl,clk-delay-cycles: Specify a number of cycles to delay for tuning.
@@ -19,3 +26,11 @@ sdhci@d4280800 {
non-removable;
mrvl,clk-delay-cycles = <31>;
};
sdhci@d8000 {
compatible = "marvell,armada-380-sdhci";
reg = <0xd8000 0x1000>, <0xdc000 0x100>;
interrupts = <0 25 0x4>;
clocks = <&gateclk 17>;
mrvl,clk-delay-cycles = <0x1F>;
};
@@ -10,6 +10,7 @@ Required properties:
- compatible:
Should be "ti,omap2-hsmmc", for OMAP2 controllers
Should be "ti,omap3-hsmmc", for OMAP3 controllers
Should be "ti,omap3-pre-es3-hsmmc" for OMAP3 controllers pre ES3.0
Should be "ti,omap4-hsmmc", for OMAP4 controllers
- ti,hwmods: Must be "mmc<n>", n is controller instance starting 1
@@ -0,0 +1,27 @@
PBIAS internal regulator for SD card dual voltage i/o pads on OMAP SoCs.
Required properties:
- compatible:
- "ti,pbias-omap" for OMAP2, OMAP3, OMAP4, OMAP5, DRA7.
- reg: pbias register offset from syscon base and size of pbias register.
- syscon : phandle of the system control module
- regulator-name : should be
pbias_mmc_omap2430 for OMAP2430, OMAP3 SoCs
pbias_sim_omap3 for OMAP3 SoCs
pbias_mmc_omap4 for OMAP4 SoCs
pbias_mmc_omap5 for OMAP5 and DRA7 SoC
Optional properties:
- Any optional property defined in bindings/regulator/regulator.txt
Example:
pbias_regulator: pbias_regulator {
compatible = "ti,pbias-omap";
reg = <0 0x4>;
syscon = <&omap5_padconf_global>;
pbias_mmc_reg: pbias_mmc_omap5 {
regulator-name = "pbias_mmc_omap5";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3000000>;
};
+1
View File
@@ -5930,6 +5930,7 @@ F: include/linux/mfd/
MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
M: Chris Ball <chris@printf.net>
M: Ulf Hansson <ulf.hansson@linaro.org>
L: linux-mmc@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
S: Maintained
+17
View File
@@ -154,6 +154,22 @@
ti,hwmods = "counter_32k";
};
dra7_ctrl_general: tisyscon@4a002e00 {
compatible = "syscon";
reg = <0x4a002e00 0x7c>;
};
pbias_regulator: pbias_regulator {
compatible = "ti,pbias-omap";
reg = <0 0x4>;
syscon = <&dra7_ctrl_general>;
pbias_mmc_reg: pbias_mmc_omap5 {
regulator-name = "pbias_mmc_omap5";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3000000>;
};
};
dra7_pmx_core: pinmux@4a003400 {
compatible = "pinctrl-single";
reg = <0x4a003400 0x0464>;
@@ -543,6 +559,7 @@
dmas = <&sdma 61>, <&sdma 62>;
dma-names = "tx", "rx";
status = "disabled";
pbias-supply = <&pbias_mmc_reg>;
};
mmc2: mmc@480b4000 {
+17
View File
@@ -29,6 +29,22 @@
pinctrl-single,function-mask = <0x3f>;
};
omap2_scm_general: tisyscon@49002270 {
compatible = "syscon";
reg = <0x49002270 0x240>;
};
pbias_regulator: pbias_regulator {
compatible = "ti,pbias-omap";
reg = <0x230 0x4>;
syscon = <&omap2_scm_general>;
pbias_mmc_reg: pbias_mmc_omap2430 {
regulator-name = "pbias_mmc_omap2430";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3000000>;
};
};
gpio1: gpio@4900c000 {
compatible = "ti,omap2-gpio";
reg = <0x4900c000 0x200>;
@@ -188,6 +204,7 @@
ti,dual-volt;
dmas = <&sdma 61>, <&sdma 62>;
dma-names = "tx", "rx";
pbias-supply = <&pbias_mmc_reg>;
};
mmc2: mmc@480b4000 {
+23
View File
@@ -174,8 +174,20 @@
};
&mmc1 {
/* See 35xx errata 2.1.1.128 in SPRZ278F */
compatible = "ti,omap3-pre-es3-hsmmc";
vmmc-supply = <&vmmc1>;
bus-width = <4>;
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
};
&mmc2 {
status="disabled";
};
&mmc3 {
status="disabled";
};
&omap3_pmx_core {
@@ -209,6 +221,17 @@
0x174 (PIN_OUTPUT | MUX_MODE0) /* hsusb0_stp.hsusb0_stp */
>;
};
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.mmc1_clk */
OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.mmc1_cmd */
OMAP3_CORE1_IOPAD(0x2148, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.mmc1_dat0 */
OMAP3_CORE1_IOPAD(0x214A, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.mmc1_dat1 */
OMAP3_CORE1_IOPAD(0x214C, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.mmc1_dat2 */
OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.mmc1_dat3 */
>;
};
};
&usb_otg_hs {
+17
View File
@@ -181,6 +181,22 @@
pinctrl-single,function-mask = <0xff1f>;
};
omap3_scm_general: tisyscon@48002270 {
compatible = "syscon";
reg = <0x48002270 0x2f0>;
};
pbias_regulator: pbias_regulator {
compatible = "ti,pbias-omap";
reg = <0x2b0 0x4>;
syscon = <&omap3_scm_general>;
pbias_mmc_reg: pbias_mmc_omap2430 {
regulator-name = "pbias_mmc_omap2430";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3000000>;
};
};
gpio1: gpio@48310000 {
compatible = "ti,omap3-gpio";
reg = <0x48310000 0x200>;
@@ -395,6 +411,7 @@
ti,dual-volt;
dmas = <&sdma 61>, <&sdma 62>;
dma-names = "tx", "rx";
pbias-supply = <&pbias_mmc_reg>;
};
mmc2: mmc@480b4000 {
+17
View File
@@ -191,6 +191,22 @@
pinctrl-single,function-mask = <0x7fff>;
};
omap4_padconf_global: tisyscon@4a1005a0 {
compatible = "syscon";
reg = <0x4a1005a0 0x170>;
};
pbias_regulator: pbias_regulator {
compatible = "ti,pbias-omap";
reg = <0x60 0x4>;
syscon = <&omap4_padconf_global>;
pbias_mmc_reg: pbias_mmc_omap4 {
regulator-name = "pbias_mmc_omap4";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3000000>;
};
};
sdma: dma-controller@4a056000 {
compatible = "ti,omap4430-sdma";
reg = <0x4a056000 0x1000>;
@@ -427,6 +443,7 @@
ti,needs-special-reset;
dmas = <&sdma 61>, <&sdma 62>;
dma-names = "tx", "rx";
pbias-supply = <&pbias_mmc_reg>;
};
mmc2: mmc@480b4000 {
+17
View File
@@ -198,6 +198,22 @@
pinctrl-single,function-mask = <0x7fff>;
};
omap5_padconf_global: tisyscon@4a002da0 {
compatible = "syscon";
reg = <0x4A002da0 0xec>;
};
pbias_regulator: pbias_regulator {
compatible = "ti,pbias-omap";
reg = <0x60 0x4>;
syscon = <&omap5_padconf_global>;
pbias_mmc_reg: pbias_mmc_omap5 {
regulator-name = "pbias_mmc_omap5";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3000000>;
};
};
sdma: dma-controller@4a056000 {
compatible = "ti,omap4430-sdma";
reg = <0x4a056000 0x1000>;
@@ -480,6 +496,7 @@
ti,needs-special-reset;
dmas = <&sdma 61>, <&sdma 62>;
dma-names = "tx", "rx";
pbias-supply = <&pbias_mmc_reg>;
};
mmc2: mmc@480b4000 {
+2
View File
@@ -170,6 +170,7 @@ CONFIG_DRA752_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_OMAP_WATCHDOG=y
CONFIG_TWL4030_WATCHDOG=y
CONFIG_MFD_SYSCON=y
CONFIG_MFD_PALMAS=y
CONFIG_MFD_TPS65217=y
CONFIG_MFD_TPS65910=y
@@ -181,6 +182,7 @@ CONFIG_REGULATOR_TPS6507X=y
CONFIG_REGULATOR_TPS65217=y
CONFIG_REGULATOR_TPS65910=y
CONFIG_REGULATOR_TWL4030=y
CONFIG_REGULATOR_PBIAS=y
CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y
CONFIG_FB_MODE_HELPERS=y
+91 -41
View File
@@ -338,58 +338,28 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
int num_sg, bool read, int timeout)
{
struct completion trans_done;
u8 dir;
int err = 0, i, count;
int err = 0, count;
long timeleft;
unsigned long flags;
struct scatterlist *sg;
enum dma_data_direction dma_dir;
u32 val;
dma_addr_t addr;
unsigned int len;
dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
/* don't transfer data during abort processing */
if (pcr->remove_pci)
return -EINVAL;
if ((sglist == NULL) || (num_sg <= 0))
return -EINVAL;
if (read) {
dir = DEVICE_TO_HOST;
dma_dir = DMA_FROM_DEVICE;
} else {
dir = HOST_TO_DEVICE;
dma_dir = DMA_TO_DEVICE;
}
count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
if (count < 1) {
dev_err(&(pcr->pci->dev), "scatterlist map failed\n");
return -EINVAL;
}
dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
pcr->sgi = 0;
for_each_sg(sglist, sg, count, i) {
addr = sg_dma_address(sg);
len = sg_dma_len(sg);
rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1);
}
spin_lock_irqsave(&pcr->lock, flags);
pcr->done = &trans_done;
pcr->trans_result = TRANS_NOT_READY;
init_completion(&trans_done);
rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
spin_unlock_irqrestore(&pcr->lock, flags);
rtsx_pci_dma_transfer(pcr, sglist, count, read);
timeleft = wait_for_completion_interruptible_timeout(
&trans_done, msecs_to_jiffies(timeout));
if (timeleft <= 0) {
@@ -413,7 +383,7 @@ out:
pcr->done = NULL;
spin_unlock_irqrestore(&pcr->lock, flags);
dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read);
if ((err < 0) && (err != -ENODEV))
rtsx_pci_stop_cmd(pcr);
@@ -425,6 +395,73 @@ out:
}
EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
int num_sg, bool read)
{
enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
if (pcr->remove_pci)
return -EINVAL;
if ((sglist == NULL) || num_sg < 1)
return -EINVAL;
return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir);
}
EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg);
int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
int num_sg, bool read)
{
enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
if (pcr->remove_pci)
return -EINVAL;
if (sglist == NULL || num_sg < 1)
return -EINVAL;
dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir);
return num_sg;
}
EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg);
int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
int sg_count, bool read)
{
struct scatterlist *sg;
dma_addr_t addr;
unsigned int len;
int i;
u32 val;
u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE;
unsigned long flags;
if (pcr->remove_pci)
return -EINVAL;
if ((sglist == NULL) || (sg_count < 1))
return -EINVAL;
val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
pcr->sgi = 0;
for_each_sg(sglist, sg, sg_count, i) {
addr = sg_dma_address(sg);
len = sg_dma_len(sg);
rtsx_pci_add_sg_tbl(pcr, addr, len, i == sg_count - 1);
}
spin_lock_irqsave(&pcr->lock, flags);
rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
spin_unlock_irqrestore(&pcr->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer);
int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
{
int err;
@@ -836,6 +873,8 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
int_reg = rtsx_pci_readl(pcr, RTSX_BIPR);
/* Clear interrupt flag */
rtsx_pci_writel(pcr, RTSX_BIPR, int_reg);
dev_dbg(&pcr->pci->dev, "=========== BIPR 0x%8x ==========\n", int_reg);
if ((int_reg & pcr->bier) == 0) {
spin_unlock(&pcr->lock);
return IRQ_NONE;
@@ -866,17 +905,28 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
}
if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) {
if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) {
if (int_reg & (TRANS_FAIL_INT | DELINK_INT))
pcr->trans_result = TRANS_RESULT_FAIL;
if (pcr->done)
complete(pcr->done);
} else if (int_reg & TRANS_OK_INT) {
else if (int_reg & TRANS_OK_INT)
pcr->trans_result = TRANS_RESULT_OK;
if (pcr->done)
complete(pcr->done);
if (pcr->done)
complete(pcr->done);
if (int_reg & SD_EXIST) {
struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD];
if (slot && slot->done_transfer)
slot->done_transfer(slot->p_dev);
}
if (int_reg & MS_EXIST) {
struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD];
if (slot && slot->done_transfer)
slot->done_transfer(slot->p_dev);
}
}
if (pcr->card_inserted || pcr->card_removed)
schedule_delayed_work(&pcr->carddet_work,
msecs_to_jiffies(200));
+115 -66
View File
@@ -415,8 +415,7 @@ static int ioctl_do_sanitize(struct mmc_card *card)
{
int err;
if (!(mmc_can_sanitize(card) &&
(card->host->caps2 & MMC_CAP2_SANITIZE))) {
if (!mmc_can_sanitize(card)) {
pr_warn("%s: %s - SANITIZE is not supported\n",
mmc_hostname(card->host), __func__);
err = -EOPNOTSUPP;
@@ -722,19 +721,6 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
return result;
}
static int send_stop(struct mmc_card *card, u32 *status)
{
struct mmc_command cmd = {0};
int err;
cmd.opcode = MMC_STOP_TRANSMISSION;
cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 5);
if (err == 0)
*status = cmd.resp[0];
return err;
}
static int get_card_status(struct mmc_card *card, u32 *status, int retries)
{
struct mmc_command cmd = {0};
@@ -750,6 +736,99 @@ static int get_card_status(struct mmc_card *card, u32 *status, int retries)
return err;
}
static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
bool hw_busy_detect, struct request *req, int *gen_err)
{
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
int err = 0;
u32 status;
do {
err = get_card_status(card, &status, 5);
if (err) {
pr_err("%s: error %d requesting status\n",
req->rq_disk->disk_name, err);
return err;
}
if (status & R1_ERROR) {
pr_err("%s: %s: error sending status cmd, status %#x\n",
req->rq_disk->disk_name, __func__, status);
*gen_err = 1;
}
/* We may rely on the host hw to handle busy detection.*/
if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) &&
hw_busy_detect)
break;
/*
* Timeout if the device never becomes ready for data and never
* leaves the program state.
*/
if (time_after(jiffies, timeout)) {
pr_err("%s: Card stuck in programming state! %s %s\n",
mmc_hostname(card->host),
req->rq_disk->disk_name, __func__);
return -ETIMEDOUT;
}
/*
* Some cards mishandle the status bits,
* so make sure to check both the busy
* indication and the card state.
*/
} while (!(status & R1_READY_FOR_DATA) ||
(R1_CURRENT_STATE(status) == R1_STATE_PRG));
return err;
}
static int send_stop(struct mmc_card *card, unsigned int timeout_ms,
struct request *req, int *gen_err, u32 *stop_status)
{
struct mmc_host *host = card->host;
struct mmc_command cmd = {0};
int err;
bool use_r1b_resp = rq_data_dir(req) == WRITE;
/*
* Normally we use R1B responses for WRITE, but in cases where the host
* has specified a max_busy_timeout we need to validate it. A failure
* means we need to prevent the host from doing hw busy detection, which
* is done by converting to a R1 response instead.
*/
if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout))
use_r1b_resp = false;
cmd.opcode = MMC_STOP_TRANSMISSION;
if (use_r1b_resp) {
cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
cmd.busy_timeout = timeout_ms;
} else {
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
}
err = mmc_wait_for_cmd(host, &cmd, 5);
if (err)
return err;
*stop_status = cmd.resp[0];
/* No need to check card status in case of READ. */
if (rq_data_dir(req) == READ)
return 0;
if (!mmc_host_is_spi(host) &&
(*stop_status & R1_ERROR)) {
pr_err("%s: %s: general error sending stop command, resp %#x\n",
req->rq_disk->disk_name, __func__, *stop_status);
*gen_err = 1;
}
return card_busy_detect(card, timeout_ms, use_r1b_resp, req, gen_err);
}
#define ERR_NOMEDIUM 3
#define ERR_RETRY 2
#define ERR_ABORT 1
@@ -866,26 +945,21 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
*/
if (R1_CURRENT_STATE(status) == R1_STATE_DATA ||
R1_CURRENT_STATE(status) == R1_STATE_RCV) {
err = send_stop(card, &stop_status);
if (err)
err = send_stop(card,
DIV_ROUND_UP(brq->data.timeout_ns, 1000000),
req, gen_err, &stop_status);
if (err) {
pr_err("%s: error %d sending stop command\n",
req->rq_disk->disk_name, err);
/*
* If the stop cmd also timed out, the card is probably
* not present, so abort. Other errors are bad news too.
*/
if (err)
/*
* If the stop cmd also timed out, the card is probably
* not present, so abort. Other errors are bad news too.
*/
return ERR_ABORT;
}
if (stop_status & R1_CARD_ECC_FAILED)
*ecc_err = 1;
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
if (stop_status & R1_ERROR) {
pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
req->rq_disk->disk_name, __func__,
stop_status);
*gen_err = 1;
}
}
/* Check for set block count errors */
@@ -1157,8 +1231,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
* program mode, which we have to wait for it to complete.
*/
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
u32 status;
unsigned long timeout;
int err;
/* Check stop command response */
if (brq->stop.resp[0] & R1_ERROR) {
@@ -1168,39 +1241,10 @@ static int mmc_blk_err_check(struct mmc_card *card,
gen_err = 1;
}
timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
do {
int err = get_card_status(card, &status, 5);
if (err) {
pr_err("%s: error %d requesting status\n",
req->rq_disk->disk_name, err);
return MMC_BLK_CMD_ERR;
}
if (status & R1_ERROR) {
pr_err("%s: %s: general error sending status command, card status %#x\n",
req->rq_disk->disk_name, __func__,
status);
gen_err = 1;
}
/* Timeout if the device never becomes ready for data
* and never leaves the program state.
*/
if (time_after(jiffies, timeout)) {
pr_err("%s: Card stuck in programming state!"\
" %s %s\n", mmc_hostname(card->host),
req->rq_disk->disk_name, __func__);
return MMC_BLK_CMD_ERR;
}
/*
* Some cards mishandle the status bits,
* so make sure to check both the busy
* indication and the card state.
*/
} while (!(status & R1_READY_FOR_DATA) ||
(R1_CURRENT_STATE(status) == R1_STATE_PRG));
err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, false, req,
&gen_err);
if (err)
return MMC_BLK_CMD_ERR;
}
/* if general error occurs, retry the write operation. */
@@ -1335,7 +1379,6 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
brq->data.blksz = 512;
brq->stop.opcode = MMC_STOP_TRANSMISSION;
brq->stop.arg = 0;
brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
brq->data.blocks = blk_rq_sectors(req);
/*
@@ -1378,9 +1421,15 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
if (rq_data_dir(req) == READ) {
brq->cmd.opcode = readcmd;
brq->data.flags |= MMC_DATA_READ;
if (brq->mrq.stop)
brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 |
MMC_CMD_AC;
} else {
brq->cmd.opcode = writecmd;
brq->data.flags |= MMC_DATA_WRITE;
if (brq->mrq.stop)
brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B |
MMC_CMD_AC;
}
if (do_rel_wr)
-15
View File
@@ -2,21 +2,6 @@
# MMC core configuration
#
config MMC_UNSAFE_RESUME
bool "Assume MMC/SD cards are non-removable (DANGEROUS)"
help
If you say Y here, the MMC layer will assume that all cards
stayed in their respective slots during the suspend. The
normal behaviour is to remove them at suspend and
redetecting them at resume. Breaking this assumption will
in most cases result in data corruption.
This option is usually just for embedded systems which use
a MMC/SD card for rootfs. Most people should say N here.
This option sets a default which can be overridden by the
module parameter "removable=0" or "removable=1".
config MMC_CLKGATE
bool "MMC host clock gating"
help
+2 -10
View File
@@ -185,24 +185,16 @@ static int mmc_runtime_suspend(struct device *dev)
{
struct mmc_card *card = mmc_dev_to_card(dev);
struct mmc_host *host = card->host;
int ret = 0;
if (host->bus_ops->runtime_suspend)
ret = host->bus_ops->runtime_suspend(host);
return ret;
return host->bus_ops->runtime_suspend(host);
}
static int mmc_runtime_resume(struct device *dev)
{
struct mmc_card *card = mmc_dev_to_card(dev);
struct mmc_host *host = card->host;
int ret = 0;
if (host->bus_ops->runtime_resume)
ret = host->bus_ops->runtime_resume(host);
return ret;
return host->bus_ops->runtime_resume(host);
}
static int mmc_runtime_idle(struct device *dev)
+15 -72
View File
@@ -34,6 +34,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sd.h>
#include <linux/mmc/slot-gpio.h>
#include "core.h"
#include "bus.h"
@@ -64,23 +65,6 @@ static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
bool use_spi_crc = 1;
module_param(use_spi_crc, bool, 0);
/*
* We normally treat cards as removed during suspend if they are not
* known to be on a non-removable bus, to avoid the risk of writing
* back data to a different card after resume. Allow this to be
* overridden if necessary.
*/
#ifdef CONFIG_MMC_UNSAFE_RESUME
bool mmc_assume_removable;
#else
bool mmc_assume_removable = 1;
#endif
EXPORT_SYMBOL(mmc_assume_removable);
module_param_named(removable, mmc_assume_removable, bool, 0644);
MODULE_PARM_DESC(
removable,
"MMC/SD cards are removable and may be removed during suspend");
/*
* Internal function. Schedule delayed work in the MMC work queue.
*/
@@ -302,7 +286,8 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
}
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal, true);
EXT_CSD_BKOPS_START, 1, timeout,
use_busy_signal, true, false);
if (err) {
pr_warn("%s: Error %d starting bkops\n",
mmc_hostname(card->host), err);
@@ -1950,7 +1935,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
cmd.opcode = MMC_ERASE;
cmd.arg = arg;
cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
cmd.cmd_timeout_ms = mmc_erase_timeout(card, arg, qty);
cmd.busy_timeout = mmc_erase_timeout(card, arg, qty);
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err) {
pr_err("mmc_erase: erase error %d, status %#x\n",
@@ -2137,7 +2122,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card,
y = 0;
for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) {
timeout = mmc_erase_timeout(card, arg, qty + x);
if (timeout > host->max_discard_to)
if (timeout > host->max_busy_timeout)
break;
if (timeout < last_timeout)
break;
@@ -2169,7 +2154,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
struct mmc_host *host = card->host;
unsigned int max_discard, max_trim;
if (!host->max_discard_to)
if (!host->max_busy_timeout)
return UINT_MAX;
/*
@@ -2189,7 +2174,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
max_discard = 0;
}
pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n",
mmc_hostname(host), max_discard, host->max_discard_to);
mmc_hostname(host), max_discard, host->max_busy_timeout);
return max_discard;
}
EXPORT_SYMBOL(mmc_calc_max_discard);
@@ -2248,9 +2233,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
{
struct mmc_card *card = host->card;
if (!host->bus_ops->power_restore)
return -EOPNOTSUPP;
if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
return -EOPNOTSUPP;
@@ -2352,7 +2334,7 @@ int _mmc_detect_card_removed(struct mmc_host *host)
{
int ret;
if ((host->caps & MMC_CAP_NONREMOVABLE) || !host->bus_ops->alive)
if (host->caps & MMC_CAP_NONREMOVABLE)
return 0;
if (!host->card || mmc_card_removed(host->card))
@@ -2435,7 +2417,7 @@ 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_ops->detect && !host->bus_dead
if (host->bus_ops && !host->bus_dead
&& !(host->caps & MMC_CAP_NONREMOVABLE))
host->bus_ops->detect(host);
@@ -2490,6 +2472,7 @@ void mmc_start_host(struct mmc_host *host)
mmc_power_off(host);
else
mmc_power_up(host, host->ocr_avail);
mmc_gpiod_request_cd_irq(host);
_mmc_detect_change(host, 0, false);
}
@@ -2501,6 +2484,8 @@ void mmc_stop_host(struct mmc_host *host)
host->removed = 1;
spin_unlock_irqrestore(&host->lock, flags);
#endif
if (host->slot.cd_irq >= 0)
disable_irq(host->slot.cd_irq);
host->rescan_disable = 1;
cancel_delayed_work_sync(&host->detect);
@@ -2537,7 +2522,7 @@ int mmc_power_save_host(struct mmc_host *host)
mmc_bus_get(host);
if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
if (!host->bus_ops || host->bus_dead) {
mmc_bus_put(host);
return -EINVAL;
}
@@ -2563,7 +2548,7 @@ int mmc_power_restore_host(struct mmc_host *host)
mmc_bus_get(host);
if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
if (!host->bus_ops || host->bus_dead) {
mmc_bus_put(host);
return -EINVAL;
}
@@ -2582,12 +2567,8 @@ EXPORT_SYMBOL(mmc_power_restore_host);
*/
int mmc_flush_cache(struct mmc_card *card)
{
struct mmc_host *host = card->host;
int err = 0;
if (!(host->caps2 & MMC_CAP2_CACHE_CTRL))
return err;
if (mmc_card_mmc(card) &&
(card->ext_csd.cache_size > 0) &&
(card->ext_csd.cache_ctrl & 1)) {
@@ -2602,44 +2583,6 @@ int mmc_flush_cache(struct mmc_card *card)
}
EXPORT_SYMBOL(mmc_flush_cache);
/*
* Turn the cache ON/OFF.
* Turning the cache OFF shall trigger flushing of the data
* to the non-volatile storage.
* This function should be called with host claimed
*/
int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
{
struct mmc_card *card = host->card;
unsigned int timeout;
int err = 0;
if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
mmc_card_is_removable(host))
return err;
if (card && mmc_card_mmc(card) &&
(card->ext_csd.cache_size > 0)) {
enable = !!enable;
if (card->ext_csd.cache_ctrl ^ enable) {
timeout = enable ? card->ext_csd.generic_cmd6_time : 0;
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_CACHE_CTRL, enable, timeout);
if (err)
pr_err("%s: cache %s error %d\n",
mmc_hostname(card->host),
enable ? "on" : "off",
err);
else
card->ext_csd.cache_ctrl = enable;
}
}
return err;
}
EXPORT_SYMBOL(mmc_cache_ctrl);
#ifdef CONFIG_PM
/* Do the card removal on suspend if card is assumed removeable
@@ -2668,7 +2611,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
/* Validate prerequisites for suspend */
if (host->bus_ops->pre_suspend)
err = host->bus_ops->pre_suspend(host);
if (!err && host->bus_ops->suspend)
if (!err)
break;
/* Calling bus_ops->remove() with a claimed host can deadlock */
+18
View File
@@ -419,6 +419,16 @@ int mmc_of_parse(struct mmc_host *host)
host->caps |= MMC_CAP_SD_HIGHSPEED;
if (of_find_property(np, "cap-mmc-highspeed", &len))
host->caps |= MMC_CAP_MMC_HIGHSPEED;
if (of_find_property(np, "sd-uhs-sdr12", &len))
host->caps |= MMC_CAP_UHS_SDR12;
if (of_find_property(np, "sd-uhs-sdr25", &len))
host->caps |= MMC_CAP_UHS_SDR25;
if (of_find_property(np, "sd-uhs-sdr50", &len))
host->caps |= MMC_CAP_UHS_SDR50;
if (of_find_property(np, "sd-uhs-sdr104", &len))
host->caps |= MMC_CAP_UHS_SDR104;
if (of_find_property(np, "sd-uhs-ddr50", &len))
host->caps |= MMC_CAP_UHS_DDR50;
if (of_find_property(np, "cap-power-off-card", &len))
host->caps |= MMC_CAP_POWER_OFF_CARD;
if (of_find_property(np, "cap-sdio-irq", &len))
@@ -429,6 +439,14 @@ int mmc_of_parse(struct mmc_host *host)
host->pm_caps |= MMC_PM_KEEP_POWER;
if (of_find_property(np, "enable-sdio-wakeup", &len))
host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
if (of_find_property(np, "mmc-ddr-1_8v", &len))
host->caps |= MMC_CAP_1_8V_DDR;
if (of_find_property(np, "mmc-ddr-1_2v", &len))
host->caps |= MMC_CAP_1_2V_DDR;
if (of_find_property(np, "mmc-hs200-1_8v", &len))
host->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
if (of_find_property(np, "mmc-hs200-1_2v", &len))
host->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
return 0;
+28 -37
View File
@@ -856,8 +856,10 @@ static int mmc_select_hs200(struct mmc_card *card)
/* switch to HS200 mode if bus width set successfully */
if (!err)
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, 2, 0);
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, 2,
card->ext_csd.generic_cmd6_time,
true, true, true);
err:
return err;
}
@@ -1074,9 +1076,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
host->caps2 & MMC_CAP2_HS200)
err = mmc_select_hs200(card);
else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, 1,
card->ext_csd.generic_cmd6_time);
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, 1,
card->ext_csd.generic_cmd6_time,
true, true, true);
if (err && err != -EBADMSG)
goto free_card;
@@ -1287,8 +1290,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
* If cache size is higher than 0, this indicates
* the existence of cache and it can be turned on.
*/
if ((host->caps2 & MMC_CAP2_CACHE_CTRL) &&
card->ext_csd.cache_size > 0) {
if (card->ext_csd.cache_size > 0) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_CACHE_CTRL, 1,
card->ext_csd.generic_cmd6_time);
@@ -1356,11 +1358,9 @@ static int mmc_sleep(struct mmc_host *host)
{
struct mmc_command cmd = {0};
struct mmc_card *card = host->card;
unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000);
int err;
if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
return 0;
err = mmc_deselect_cards(host);
if (err)
return err;
@@ -1369,7 +1369,19 @@ static int mmc_sleep(struct mmc_host *host)
cmd.arg = card->rca << 16;
cmd.arg |= 1 << 15;
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
/*
* If the max_busy_timeout of the host is specified, validate it against
* the sleep cmd timeout. A failure means we need to prevent the host
* from doing hw busy detection, which is done by converting to a R1
* response instead of a R1B.
*/
if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) {
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
} else {
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
cmd.busy_timeout = timeout_ms;
}
err = mmc_wait_for_cmd(host, &cmd, 0);
if (err)
return err;
@@ -1380,8 +1392,8 @@ static int mmc_sleep(struct mmc_host *host)
* SEND_STATUS command to poll the status because that command (and most
* others) is invalid while the card sleeps.
*/
if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000));
if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
mmc_delay(timeout_ms);
return err;
}
@@ -1404,7 +1416,7 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_POWER_OFF_NOTIFICATION,
notify_type, timeout, true, false);
notify_type, timeout, true, false, false);
if (err)
pr_err("%s: Power Off Notification timed out, %u\n",
mmc_hostname(card->host), timeout);
@@ -1484,7 +1496,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
goto out;
}
err = mmc_cache_ctrl(host, 0);
err = mmc_flush_cache(host->card);
if (err)
goto out;
@@ -1634,16 +1646,6 @@ static int mmc_power_restore(struct mmc_host *host)
}
static const struct mmc_bus_ops mmc_ops = {
.remove = mmc_remove,
.detect = mmc_detect,
.suspend = NULL,
.resume = NULL,
.power_restore = mmc_power_restore,
.alive = mmc_alive,
.shutdown = mmc_shutdown,
};
static const struct mmc_bus_ops mmc_ops_unsafe = {
.remove = mmc_remove,
.detect = mmc_detect,
.suspend = mmc_suspend,
@@ -1655,17 +1657,6 @@ static const struct mmc_bus_ops mmc_ops_unsafe = {
.shutdown = mmc_shutdown,
};
static void mmc_attach_bus_ops(struct mmc_host *host)
{
const struct mmc_bus_ops *bus_ops;
if (!mmc_card_is_removable(host))
bus_ops = &mmc_ops_unsafe;
else
bus_ops = &mmc_ops;
mmc_attach_bus(host, bus_ops);
}
/*
* Starting point for MMC card init.
*/
@@ -1685,7 +1676,7 @@ int mmc_attach_mmc(struct mmc_host *host)
if (err)
return err;
mmc_attach_bus_ops(host);
mmc_attach_bus(host, &mmc_ops);
if (host->ocr_avail_mmc)
host->ocr_avail = host->ocr_avail_mmc;

Some files were not shown because too many files have changed in this diff Show More