Commit 17ece345 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc

Pull MMC updates from Ulf Hansson:
 "MMC core:
   - Add support to enable irq wake for slot gpio
   - Remove MMC_CAP2_HC_ERASE_SZ and make it the default behaviour
   - Improve R1 response error checks for stop commands
   - Cleanup and clarify some MMC specific code
   - Keep card runtime resumed while adding SDIO function devices
   - Use device_property_read instead of of_property_read in mmc_of_parse()
   - Move boot partition locking into a driver op to enable proper I/O scheduling
   - Move multi/single-ioctl() to use block layer to enable proper I/O scheduling
   - Delete bounce buffer Kconfig option
   - Improve the eMMC HW reset support provided via the eMMC pwrseq
   - Add host API to manage SDIO IRQs from a workqueue

  MMC host:
   - dw_mmc: Drop support for multiple slots
   - dw_mmc: Use device_property_read instead of of_property_read
   - dw_mmc-rockchip: Optional improved tuning to greatly decrease tuning time
   - dw_mmc: Prevent rpm suspend for SDIO IRQs instead of always for SDIO cards
   - dw_mmc: Convert to use MMC_CAP2_SDIO_IRQ_NOTHREAD for SDIO IRQs
   - omap_hsmmc: Convert to mmc regulator APIs to consolidate code
   - omap_hsmmc: Deprecate "vmmc_aux" in DT and use "vqmmc" instead
   - tmio: make sure SDIO gets reinitialized after resume
   - sdhi: add CMD23 support to R-Car Gen2 & Gen3
   - tmio: add CMD23 support
   - sdhi/tmio: Refactor code and rename files to simplify Kconfig options
   - sdhci-pci: Enable card detect wake for Intel BYT-related SD controllers
   - sdhci-pci: Add support for Intel CNP
   - sdhci-esdhc-imx: Remove ENGcm07207 workaround - allow multi block transfers
   - sdhci-esdhc-imx: Allow all supported prescaler values
   - sdhci-esdhc-imx: Fix DAT line software reset
   - sdhci-esdhc: Add SDHCI_QUIRK_32BIT_DMA_ADDR
   - atmel-mci: Drop AVR32 support"

* tag 'mmc-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (86 commits)
  mmc: dw_mmc: remove the unnecessary slot variable
  mmc: dw_mmc: use the 'slot' instead of 'cur_slot'
  mmc: dw_mmc: remove the 'id' arguments about functions relevant to slot
  mmc: dw_mmc: change the array of slots
  mmc: dw_mmc: remove the loop about finding slots
  mmc: dw_mmc: deprecated the "num-slots" property
  mmc: dw_mmc-rockchip: parse rockchip, desired-num-phases from DT
  dt-bindings: rockchip-dw-mshc: add optional rockchip, desired-num-phases
  mmc: renesas-sdhi: improve checkpatch cleanness
  mmc: tmio: improve checkpatch cleanness
  mmc: sdhci-pci: Enable card detect wake for Intel BYT-related SD controllers
  mmc: slot-gpio: Add support to enable irq wake on cd_irq
  mmc: core: Remove MMC_CAP2_HC_ERASE_SZ
  mmc: core: for data errors, take response of stop cmd into account
  mmc: core: check also R1 response for stop commands
  mmc: core: Clarify code for sending CSD
  mmc: core: Drop mmc_all_send_cid() and use mmc_send_cxd_native() instead
  mmc: core: Re-factor code for sending CID
  mmc: core: Remove redundant code in mmc_send_cid()
  mmc: core: Make mmc_can_reset() static
  ...
parents 650fc870 e47c0b96
...@@ -15,6 +15,7 @@ Required Properties: ...@@ -15,6 +15,7 @@ Required Properties:
- "rockchip,rk3288-dw-mshc": for Rockchip RK3288 - "rockchip,rk3288-dw-mshc": for Rockchip RK3288
- "rockchip,rv1108-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RV1108 - "rockchip,rv1108-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RV1108
- "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3036 - "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3036
- "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3328
- "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3368 - "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3368
- "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3399 - "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3399
...@@ -31,6 +32,10 @@ Optional Properties: ...@@ -31,6 +32,10 @@ Optional Properties:
probing, low speeds or in case where all phases work at tuning time. probing, low speeds or in case where all phases work at tuning time.
If not specified 0 deg will be used. If not specified 0 deg will be used.
* rockchip,desired-num-phases: The desired number of times that the host
execute tuning when needed. If not specified, the host will do tuning
for 360 times, namely tuning for each degree.
Example: Example:
rkdwmmc0@12200000 { rkdwmmc0@12200000 {
......
...@@ -18,7 +18,7 @@ Required properties: ...@@ -18,7 +18,7 @@ Required properties:
Optional properties: Optional properties:
ti,dual-volt: boolean, supports dual voltage cards ti,dual-volt: boolean, supports dual voltage cards
<supply-name>-supply: phandle to the regulator device tree node <supply-name>-supply: phandle to the regulator device tree node
"supply-name" examples are "vmmc", "vmmc_aux" etc "supply-name" examples are "vmmc", "vmmc_aux"(deprecated)/"vqmmc" etc
ti,non-removable: non-removable slot (like eMMC) ti,non-removable: non-removable slot (like eMMC)
ti,needs-special-reset: Requires a special softreset sequence ti,needs-special-reset: Requires a special softreset sequence
ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed
......
...@@ -12915,7 +12915,7 @@ M: Wolfram Sang <wsa+renesas@sang-engineering.com> ...@@ -12915,7 +12915,7 @@ M: Wolfram Sang <wsa+renesas@sang-engineering.com>
L: linux-mmc@vger.kernel.org L: linux-mmc@vger.kernel.org
S: Supported S: Supported
F: drivers/mmc/host/tmio_mmc* F: drivers/mmc/host/tmio_mmc*
F: drivers/mmc/host/sh_mobile_sdhi.c F: drivers/mmc/host/renesas_sdhi*
F: include/linux/mfd/tmio.h F: include/linux/mfd/tmio.h
TMP401 HARDWARE MONITOR DRIVER TMP401 HARDWARE MONITOR DRIVER
......
...@@ -74,16 +74,6 @@ w3cbw003c_wifi_nreset: regulator-w3cbw003c-wifi-nreset { ...@@ -74,16 +74,6 @@ w3cbw003c_wifi_nreset: regulator-w3cbw003c-wifi-nreset {
gpio = <&gpio1 16 GPIO_ACTIVE_HIGH>; /* gpio_16: WiFi nReset */ gpio = <&gpio1 16 GPIO_ACTIVE_HIGH>; /* gpio_16: WiFi nReset */
startup-delay-us = <10000>; startup-delay-us = <10000>;
}; };
/* Regulator to trigger the nReset signal of the Bluetooth module */
w3cbw003c_bt_nreset: regulator-w3cbw003c-bt-nreset {
compatible = "regulator-fixed";
regulator-name = "regulator-w3cbw003c-bt-nreset";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio6 4 GPIO_ACTIVE_HIGH>; /* gpio_164: BT nReset */
startup-delay-us = <10000>;
};
}; };
&omap3_pmx_core { &omap3_pmx_core {
...@@ -191,7 +181,6 @@ &mmc2 { ...@@ -191,7 +181,6 @@ &mmc2 {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&mmc2_pins>; pinctrl-0 = <&mmc2_pins>;
vmmc-supply = <&w3cbw003c_npoweron>; vmmc-supply = <&w3cbw003c_npoweron>;
vqmmc-supply = <&w3cbw003c_bt_nreset>;
vmmc_aux-supply = <&w3cbw003c_wifi_nreset>; vmmc_aux-supply = <&w3cbw003c_wifi_nreset>;
bus-width = <4>; bus-width = <4>;
cap-sdio-irq; cap-sdio-irq;
......
...@@ -61,24 +61,6 @@ config MMC_BLOCK_MINORS ...@@ -61,24 +61,6 @@ config MMC_BLOCK_MINORS
If unsure, say 8 here. If unsure, say 8 here.
config MMC_BLOCK_BOUNCE
bool "Use bounce buffer for simple hosts"
depends on MMC_BLOCK
default y
help
SD/MMC is a high latency protocol where it is crucial to
send large requests in order to get high performance. Many
controllers, however, are restricted to continuous memory
(i.e. they can't do scatter-gather), something the kernel
rarely can provide.
Say Y here to help these restricted hosts by bouncing
requests back and forth from a large buffer. You will get
a big performance gain at the cost of up to 64 KiB of
physical memory.
If unsure, say Y here.
config SDIO_UART config SDIO_UART
tristate "SDIO UART/GPS class support" tristate "SDIO UART/GPS class support"
depends on TTY depends on TTY
......
This diff is collapsed.
...@@ -53,12 +53,6 @@ ...@@ -53,12 +53,6 @@
/* If the device is not responding */ /* If the device is not responding */
#define MMC_CORE_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ #define MMC_CORE_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
/*
* Background operations can take a long time, depending on the housekeeping
* operations the card has to perform.
*/
#define MMC_BKOPS_MAX_TIMEOUT (4 * 60 * 1000) /* max time to wait in ms */
/* The max erase timeout, used when host->max_busy_timeout isn't specified */ /* The max erase timeout, used when host->max_busy_timeout isn't specified */
#define MMC_ERASE_TIMEOUT_MS (60 * 1000) /* 60 s */ #define MMC_ERASE_TIMEOUT_MS (60 * 1000) /* 60 s */
...@@ -362,74 +356,6 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) ...@@ -362,74 +356,6 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
return 0; return 0;
} }
/**
* mmc_start_bkops - start BKOPS for supported cards
* @card: MMC card to start BKOPS
* @form_exception: A flag to indicate if this function was
* called due to an exception raised by the card
*
* Start background operations whenever requested.
* When the urgent BKOPS bit is set in a R1 command response
* then background operations should be started immediately.
*/
void mmc_start_bkops(struct mmc_card *card, bool from_exception)
{
int err;
int timeout;
bool use_busy_signal;
if (!card->ext_csd.man_bkops_en || mmc_card_doing_bkops(card))
return;
err = mmc_read_bkops_status(card);
if (err) {
pr_err("%s: Failed to read bkops status: %d\n",
mmc_hostname(card->host), err);
return;
}
if (!card->ext_csd.raw_bkops_status)
return;
if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 &&
from_exception)
return;
mmc_claim_host(card->host);
if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) {
timeout = MMC_BKOPS_MAX_TIMEOUT;
use_busy_signal = true;
} else {
timeout = 0;
use_busy_signal = false;
}
mmc_retune_hold(card->host);
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BKOPS_START, 1, timeout, 0,
use_busy_signal, true, false);
if (err) {
pr_warn("%s: Error %d starting bkops\n",
mmc_hostname(card->host), err);
mmc_retune_release(card->host);
goto out;
}
/*
* For urgent bkops status (LEVEL_2 and more)
* bkops executed synchronously, otherwise
* the operation is in progress
*/
if (!use_busy_signal)
mmc_card_set_doing_bkops(card);
else
mmc_retune_release(card->host);
out:
mmc_release_host(card->host);
}
EXPORT_SYMBOL(mmc_start_bkops);
/* /*
* mmc_wait_data_done() - done callback for data request * mmc_wait_data_done() - done callback for data request
* @mrq: done data request * @mrq: done data request
...@@ -748,71 +674,6 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) ...@@ -748,71 +674,6 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
} }
EXPORT_SYMBOL(mmc_wait_for_req); EXPORT_SYMBOL(mmc_wait_for_req);
/**
* mmc_interrupt_hpi - Issue for High priority Interrupt
* @card: the MMC card associated with the HPI transfer
*
* Issued High Priority Interrupt, and check for card status
* until out-of prg-state.
*/
int mmc_interrupt_hpi(struct mmc_card *card)
{
int err;
u32 status;
unsigned long prg_wait;
if (!card->ext_csd.hpi_en) {
pr_info("%s: HPI enable bit unset\n", mmc_hostname(card->host));
return 1;
}
mmc_claim_host(card->host);
err = mmc_send_status(card, &status);
if (err) {
pr_err("%s: Get card status fail\n", mmc_hostname(card->host));
goto out;
}
switch (R1_CURRENT_STATE(status)) {
case R1_STATE_IDLE:
case R1_STATE_READY:
case R1_STATE_STBY:
case R1_STATE_TRAN:
/*
* In idle and transfer states, HPI is not needed and the caller
* can issue the next intended command immediately
*/
goto out;
case R1_STATE_PRG:
break;
default:
/* In all other states, it's illegal to issue HPI */
pr_debug("%s: HPI cannot be sent. Card state=%d\n",
mmc_hostname(card->host), R1_CURRENT_STATE(status));
err = -EINVAL;
goto out;
}
err = mmc_send_hpi_cmd(card, &status);
if (err)
goto out;
prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time);
do {
err = mmc_send_status(card, &status);
if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN)
break;
if (time_after(jiffies, prg_wait))
err = -ETIMEDOUT;
} while (!err);
out:
mmc_release_host(card->host);
return err;
}
EXPORT_SYMBOL(mmc_interrupt_hpi);
/** /**
* mmc_wait_for_cmd - start a command and wait for completion * mmc_wait_for_cmd - start a command and wait for completion
* @host: MMC host to start command * @host: MMC host to start command
...@@ -842,53 +703,6 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries ...@@ -842,53 +703,6 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries
EXPORT_SYMBOL(mmc_wait_for_cmd); EXPORT_SYMBOL(mmc_wait_for_cmd);
/**
* mmc_stop_bkops - stop ongoing BKOPS
* @card: MMC card to check BKOPS
*
* Send HPI command to stop ongoing background operations to
* allow rapid servicing of foreground operations, e.g. read/
* writes. Wait until the card comes out of the programming state
* to avoid errors in servicing read/write requests.
*/
int mmc_stop_bkops(struct mmc_card *card)
{
int err = 0;
err = mmc_interrupt_hpi(card);
/*
* If err is EINVAL, we can't issue an HPI.
* It should complete the BKOPS.
*/
if (!err || (err == -EINVAL)) {
mmc_card_clr_doing_bkops(card);
mmc_retune_release(card->host);
err = 0;
}
return err;
}
EXPORT_SYMBOL(mmc_stop_bkops);
int mmc_read_bkops_status(struct mmc_card *card)
{
int err;
u8 *ext_csd;
mmc_claim_host(card->host);
err = mmc_get_ext_csd(card, &ext_csd);
mmc_release_host(card->host);
if (err)
return err;
card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS];
card->ext_csd.raw_exception_status = ext_csd[EXT_CSD_EXP_EVENTS_STATUS];
kfree(ext_csd);
return 0;
}
EXPORT_SYMBOL(mmc_read_bkops_status);
/** /**
* mmc_set_data_timeout - set the timeout for a data command * mmc_set_data_timeout - set the timeout for a data command
* @data: data phase for command * @data: data phase for command
...@@ -2597,6 +2411,8 @@ EXPORT_SYMBOL(mmc_set_blockcount); ...@@ -2597,6 +2411,8 @@ EXPORT_SYMBOL(mmc_set_blockcount);
static void mmc_hw_reset_for_init(struct mmc_host *host) static void mmc_hw_reset_for_init(struct mmc_host *host)
{ {
mmc_pwrseq_reset(host);
if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
return; return;
host->ops->hw_reset(host); host->ops->hw_reset(host);
...@@ -2836,8 +2652,11 @@ void mmc_stop_host(struct mmc_host *host) ...@@ -2836,8 +2652,11 @@ void mmc_stop_host(struct mmc_host *host)
host->removed = 1; host->removed = 1;
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
#endif #endif
if (host->slot.cd_irq >= 0) if (host->slot.cd_irq >= 0) {
if (host->slot.cd_wake_enabled)
disable_irq_wake(host->slot.cd_irq);
disable_irq(host->slot.cd_irq); disable_irq(host->slot.cd_irq);
}
host->rescan_disable = 1; host->rescan_disable = 1;
cancel_delayed_work_sync(&host->detect); cancel_delayed_work_sync(&host->detect);
...@@ -2913,27 +2732,6 @@ int mmc_power_restore_host(struct mmc_host *host) ...@@ -2913,27 +2732,6 @@ int mmc_power_restore_host(struct mmc_host *host)
} }
EXPORT_SYMBOL(mmc_power_restore_host); EXPORT_SYMBOL(mmc_power_restore_host);
/*
* Flush the cache to the non-volatile storage.
*/
int mmc_flush_cache(struct mmc_card *card)
{
int err = 0;
if (mmc_card_mmc(card) &&
(card->ext_csd.cache_size > 0) &&
(card->ext_csd.cache_ctrl & 1)) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_FLUSH_CACHE, 1, 0);
if (err)
pr_err("%s: cache flush error %d\n",
mmc_hostname(card->host), err);
}
return err;
}
EXPORT_SYMBOL(mmc_flush_cache);
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
/* Do the card removal on suspend if card is assumed removeable /* Do the card removal on suspend if card is assumed removeable
* Do that in pm notifier while userspace isn't yet frozen, so we will be able * Do that in pm notifier while userspace isn't yet frozen, so we will be able
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "host.h" #include "host.h"
#include "slot-gpio.h" #include "slot-gpio.h"
#include "pwrseq.h" #include "pwrseq.h"
#include "sdio_ops.h"
#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
...@@ -176,19 +177,17 @@ static void mmc_retune_timer(unsigned long data) ...@@ -176,19 +177,17 @@ static void mmc_retune_timer(unsigned long data)
*/ */
int mmc_of_parse(struct mmc_host *host) int mmc_of_parse(struct mmc_host *host)
{ {
struct device_node *np; struct device *dev = host->parent;
u32 bus_width; u32 bus_width;
int ret; int ret;
bool cd_cap_invert, cd_gpio_invert = false; bool cd_cap_invert, cd_gpio_invert = false;
bool ro_cap_invert, ro_gpio_invert = false; bool ro_cap_invert, ro_gpio_invert = false;
if (!host->parent || !host->parent->of_node) if (!dev || !dev_fwnode(dev))
return 0; return 0;
np = host->parent->of_node;
/* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */ /* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */
if (of_property_read_u32(np, "bus-width", &bus_width) < 0) { if (device_property_read_u32(dev, "bus-width", &bus_width) < 0) {
dev_dbg(host->parent, dev_dbg(host->parent,
"\"bus-width\" property is missing, assuming 1 bit.\n"); "\"bus-width\" property is missing, assuming 1 bit.\n");
bus_width = 1; bus_width = 1;
...@@ -210,7 +209,7 @@ int mmc_of_parse(struct mmc_host *host) ...@@ -210,7 +209,7 @@ int mmc_of_parse(struct mmc_host *host)
} }
/* f_max is obtained from the optional "max-frequency" property */ /* f_max is obtained from the optional "max-frequency" property */
of_property_read_u32(np, "max-frequency", &host->f_max); device_property_read_u32(dev, "max-frequency", &host->f_max);
/* /*
* Configure CD and WP pins. They are both by default active low to * Configure CD and WP pins. They are both by default active low to
...@@ -225,12 +224,12 @@ int mmc_of_parse(struct mmc_host *host) ...@@ -225,12 +224,12 @@ int mmc_of_parse(struct mmc_host *host)
*/ */
/* Parse Card Detection */ /* Parse Card Detection */
if (of_property_read_bool(np, "non-removable")) { if (device_property_read_bool(dev, "non-removable")) {
host->caps |= MMC_CAP_NONREMOVABLE; host->caps |= MMC_CAP_NONREMOVABLE;
} else { } else {
cd_cap_invert = of_property_read_bool(np, "cd-inverted"); cd_cap_invert = device_property_read_bool(dev, "cd-inverted");
if (of_property_read_bool(np, "broken-cd")) if (device_property_read_bool(dev, "broken-cd"))
host->caps |= MMC_CAP_NEEDS_POLL; host->caps |= MMC_CAP_NEEDS_POLL;
ret = mmc_gpiod_request_cd(host, "cd", 0, true, ret = mmc_gpiod_request_cd(host, "cd", 0, true,
...@@ -256,7 +255,7 @@ int mmc_of_parse(struct mmc_host *host) ...@@ -256,7 +255,7 @@ int mmc_of_parse(struct mmc_host *host)
} }
/* Parse Write Protection */ /* Parse Write Protection */
ro_cap_invert = of_property_read_bool(np, "wp-inverted"); ro_cap_invert = device_property_read_bool(dev, "wp-inverted");
ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert); ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert);
if (!ret) if (!ret)
...@@ -264,64 +263,64 @@ int mmc_of_parse(struct mmc_host *host) ...@@ -264,64 +263,64 @@ int mmc_of_parse(struct mmc_host *host)
else if (ret != -ENOENT && ret != -ENOSYS) else if (ret != -ENOENT && ret != -ENOSYS)
return ret; return ret;
if (of_property_read_bool(np, "disable-wp")) if (device_property_read_bool(dev, "disable-wp"))
host->caps2 |= MMC_CAP2_NO_WRITE_PROTECT; host->caps2 |= MMC_CAP2_NO_WRITE_PROTECT;
/* See the comment on CD inversion above */ /* See the comment on CD inversion above */
if (ro_cap_invert ^ ro_gpio_invert) if (ro_cap_invert ^ ro_gpio_invert)
host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
if (of_property_read_bool(np, "cap-sd-highspeed")) if (device_property_read_bool(dev, "cap-sd-highspeed"))
host->caps |= MMC_CAP_SD_HIGHSPEED; host->caps |= MMC_CAP_SD_HIGHSPEED;
if (of_property_read_bool(np, "cap-mmc-highspeed")) if (device_property_read_bool(dev, "cap-mmc-highspeed"))
host->caps |= MMC_CAP_MMC_HIGHSPEED; host->caps |= MMC_CAP_MMC_HIGHSPEED;
if (of_property_read_bool(np, "sd-uhs-sdr12")) if (device_property_read_bool(dev, "sd-uhs-sdr12"))
host->caps |= MMC_CAP_UHS_SDR12; host->caps |= MMC_CAP_UHS_SDR12;
if (of_property_read_bool(np, "sd-uhs-sdr25")) if (device_property_read_bool(dev, "sd-uhs-sdr25"))
host->caps |= MMC_CAP_UHS_SDR25; host->caps |= MMC_CAP_UHS_SDR25;
if (of_property_read_bool(np, "sd-uhs-sdr50")) if (device_property_read_bool(dev, "sd-uhs-sdr50"))
host->caps |= MMC_CAP_UHS_SDR50; host->caps |= MMC_CAP_UHS_SDR50;
if (of_property_read_bool(np, "sd-uhs-sdr104")) if (device_property_read_bool(dev, "sd-uhs-sdr104"))
host->caps |= MMC_CAP_UHS_SDR104; host->caps |= MMC_CAP_UHS_SDR104;
if (of_property_read_bool(np, "sd-uhs-ddr50")) if (device_property_read_bool(dev, "sd-uhs-ddr50"))
host->caps |= MMC_CAP_UHS_DDR50; host->caps |= MMC_CAP_UHS_DDR50;
if (of_property_read_bool(np, "cap-power-off-card")) if (device_property_read_bool(dev, "cap-power-off-card"))
host->caps |= MMC_CAP_POWER_OFF_CARD; host->caps |= MMC_CAP_POWER_OFF_CARD;
if (of_property_read_bool(np, "cap-mmc-hw-reset")) if (device_property_read_bool(dev, "cap-mmc-hw-reset"))
host->caps |= MMC_CAP_HW_RESET; host->caps |= MMC_CAP_HW_RESET;
if (of_property_read_bool(np, "cap-sdio-irq")) if (device_property_read_bool(dev, "cap-sdio-irq"))
host->caps |= MMC_CAP_SDIO_IRQ; host->caps |= MMC_CAP_SDIO_IRQ;
if (of_property_read_bool(np, "full-pwr-cycle")) if (device_property_read_bool(dev, "full-pwr-cycle"))
host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE; host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE;
if (of_property_read_bool(np, "keep-power-in-suspend")) if (device_property_read_bool(dev, "keep-power-in-suspend"))
host->pm_caps |= MMC_PM_KEEP_POWER; host->pm_caps |= MMC_PM_KEEP_POWER;
if (of_property_read_bool(np, "wakeup-source") || if (device_property_read_bool(dev, "wakeup-source") ||
of_property_read_bool(np, "enable-sdio-wakeup")) /* legacy */ device_property_read_bool(dev, "enable-sdio-wakeup")) /* legacy */
host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
if (of_property_read_bool(np, "mmc-ddr-3_3v")) if (device_property_read_bool(dev, "mmc-ddr-3_3v"))
host->caps |= MMC_CAP_3_3V_DDR; host->caps |= MMC_CAP_3_3V_DDR;
if (of_property_read_bool(np, "mmc-ddr-1_8v")) if (device_property_read_bool(dev, "mmc-ddr-1_8v"))
host->caps |= MMC_CAP_1_8V_DDR; host->caps |= MMC_CAP_1_8V_DDR;
if (of_property_read_bool(np, "mmc-ddr-1_2v")) if (device_property_read_bool(dev, "mmc-ddr-1_2v"))
host->caps |= MMC_CAP_1_2V_DDR; host->caps |= MMC_CAP_1_2V_DDR;
if (of_property_read_bool(np, "mmc-hs200-1_8v")) if (device_property_read_bool(dev, "mmc-hs200-1_8v"))
host->caps2 |= MMC_CAP2_HS200_1_8V_SDR; host->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
if (of_property_read_bool(np, "mmc-hs200-1_2v")) if (device_property_read_bool(dev, "mmc-hs200-1_2v"))
host->caps2 |= MMC_CAP2_HS200_1_2V_SDR; host->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
if (of_property_read_bool(np, "mmc-hs400-1_8v")) if (device_property_read_bool(dev, "mmc-hs400-1_8v"))
host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR; host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR;
if (of_property_read_bool(np, "mmc-hs400-1_2v")) if (device_property_read_bool(dev, "mmc-hs400-1_2v"))
host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR; host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
if (of_property_read_bool(np, "mmc-hs400-enhanced-strobe")) if (device_property_read_bool(dev, "mmc-hs400-enhanced-strobe"))
host->caps2 |= MMC_CAP2_HS400_ES; host->caps2 |= MMC_CAP2_HS400_ES;
if (of_property_read_bool(np, "no-sdio")) if (device_property_read_bool(dev, "no-sdio"))
host->caps2 |= MMC_CAP2_NO_SDIO; host->caps2 |= MMC_CAP2_NO_SDIO;
if (of_property_read_bool(np, "no-sd")) if (device_property_read_bool(dev, "no-sd"))
host->caps2 |= MMC_CAP2_NO_SD; host->caps2 |= MMC_CAP2_NO_SD;
if (of_property_read_bool(np, "no-mmc")) if (device_property_read_bool(dev, "no-mmc"))
host->caps2 |= MMC_CAP2_NO_MMC; host->caps2 |= MMC_CAP2_NO_MMC;
host->dsr_req = !of_property_read_u32(np, "dsr", &host->dsr); host->dsr_req = !device_property_read_u32(dev, "dsr", &host->dsr);
if (host->dsr_req && (host->dsr & ~0xffff)) { if (host->dsr_req && (host->dsr & ~0xffff)) {
dev_err(host->parent, dev_err(host->parent,
"device tree specified broken value for DSR: 0x%x, ignoring\n", "device tree specified broken value for DSR: 0x%x, ignoring\n",
...@@ -379,6 +378,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) ...@@ -379,6 +378,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
spin_lock_init(&host->lock); spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq); init_waitqueue_head(&host->wq);
INIT_DELAYED_WORK(&host->detect, mmc_rescan); INIT_DELAYED_WORK(&host->detect, mmc_rescan);
INIT_DELAYED_WORK(&host->sdio_irq_work, sdio_irq_work);
setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host); setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host);
/* /*
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "mmc_ops.h" #include "mmc_ops.h"
#include "quirks.h" #include "quirks.h"
#include "sd_ops.h" #include "sd_ops.h"
#include "pwrseq.h"
#define DEFAULT_CMD6_TIMEOUT_MS 500 #define DEFAULT_CMD6_TIMEOUT_MS 500
...@@ -1555,10 +1556,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ...@@ -1555,10 +1556,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
/* /*
* Fetch CID from card. * Fetch CID from card.
*/ */
if (mmc_host_is_spi(host))
err = mmc_send_cid(host, cid); err = mmc_send_cid(host, cid);
else
err = mmc_all_send_cid(host, cid);
if (err) if (err)
goto err; goto err;
...@@ -1653,12 +1651,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ...@@ -1653,12 +1651,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
mmc_set_erase_size(card); mmc_set_erase_size(card);
} }
/* /* Enable ERASE_GRP_DEF. This bit is lost after a reset or power off. */
* If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF if (card->ext_csd.rev >= 3) {
* bit. This bit will be lost every time after a reset or power off.
*/
if (card->ext_csd.partition_setting_completed ||
(card->ext_csd.rev >= 3 && (host->caps2 & MMC_CAP2_HC_ERASE_SZ))) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_ERASE_GROUP_DEF, 1, EXT_CSD_ERASE_GROUP_DEF, 1,
card->ext_csd.generic_cmd6_time); card->ext_csd.generic_cmd6_time);
...@@ -2096,7 +2090,7 @@ static int mmc_runtime_resume(struct mmc_host *host) ...@@ -2096,7 +2090,7 @@ static int mmc_runtime_resume(struct mmc_host *host)
return 0; return 0;
} }
int mmc_can_reset(struct mmc_card *card) static int mmc_can_reset(struct mmc_card *card)
{ {
u8 rst_n_function; u8 rst_n_function;
...@@ -2105,7 +2099,6 @@ int mmc_can_reset(struct mmc_card *card) ...@@ -2105,7 +2099,6 @@ int mmc_can_reset(struct mmc_card *card)
return 0; return 0;
return 1; return 1;
} }
EXPORT_SYMBOL(mmc_can_reset);
static int mmc_reset(struct mmc_host *host) static int mmc_reset(struct mmc_host *host)
{ {
...@@ -2127,6 +2120,7 @@ static int mmc_reset(struct mmc_host *host) ...@@ -2127,6 +2120,7 @@ static int mmc_reset(struct mmc_host *host)
} else { } else {
/* Do a brute force power cycle */ /* Do a brute force power cycle */
mmc_power_cycle(host, card->ocr); mmc_power_cycle(host, card->ocr);
mmc_pwrseq_reset(host);
} }
return mmc_init_card(host, card->ocr, card); return mmc_init_card(host, card->ocr, card);
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/mmc/mmc.h> #include <linux/mmc/mmc.h>
#include "core.h" #include "core.h"
#include "card.h"
#include "host.h" #include "host.h"
#include "mmc_ops.h" #include "mmc_ops.h"
...@@ -54,7 +55,7 @@ static const u8 tuning_blk_pattern_8bit[] = { ...@@ -54,7 +55,7 @@ static const u8 tuning_blk_pattern_8bit[] = {
0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
}; };
int mmc_send_status(struct mmc_card *card, u32 *status) int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries)
{ {
int err; int err;
struct mmc_command cmd = {}; struct mmc_command cmd = {};
...@@ -64,7 +65,7 @@ int mmc_send_status(struct mmc_card *card, u32 *status) ...@@ -64,7 +65,7 @@ int mmc_send_status(struct mmc_card *card, u32 *status)
cmd.arg = card->rca << 16; cmd.arg = card->rca << 16;
cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); err = mmc_wait_for_cmd(card->host, &cmd, retries);
if (err) if (err)
return err; return err;
...@@ -76,6 +77,12 @@ int mmc_send_status(struct mmc_card *card, u32 *status) ...@@ -76,6 +77,12 @@ int mmc_send_status(struct mmc_card *card, u32 *status)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(__mmc_send_status);
int mmc_send_status(struct mmc_card *card, u32 *status)
{
return __mmc_send_status(card, status, MMC_CMD_RETRIES);
}
static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
{ {
...@@ -200,24 +207,6 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) ...@@ -200,24 +207,6 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
return err; return err;
} }
int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
{
int err;
struct mmc_command cmd = {};
cmd.opcode = MMC_ALL_SEND_CID;
cmd.arg = 0;
cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
if (err)
return err;
memcpy(cid, cmd.resp, sizeof(u32) * 4);
return 0;
}
int mmc_set_relative_addr(struct mmc_card *card) int mmc_set_relative_addr(struct mmc_card *card)
{ {
struct mmc_command cmd = {}; struct mmc_command cmd = {};
...@@ -302,15 +291,11 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, ...@@ -302,15 +291,11 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
return 0; return 0;
} }
int mmc_send_csd(struct mmc_card *card, u32 *csd) static int mmc_spi_send_csd(struct mmc_card *card, u32 *csd)
{ {
int ret, i; int ret, i;
__be32 *csd_tmp; __be32 *csd_tmp;
if (!mmc_host_is_spi(card->host))
return mmc_send_cxd_native(card->host, card->rca << 16,
csd, MMC_SEND_CSD);
csd_tmp = kzalloc(16, GFP_KERNEL); csd_tmp = kzalloc(16, GFP_KERNEL);
if (!csd_tmp) if (!csd_tmp)
return -ENOMEM; return -ENOMEM;
...@@ -327,18 +312,20 @@ int mmc_send_csd(struct mmc_card *card, u32 *csd) ...@@ -327,18 +312,20 @@ int mmc_send_csd(struct mmc_card *card, u32 *csd)
return ret; return ret;
} }
int mmc_send_cid(struct mmc_host *host, u32 *cid) int mmc_send_csd(struct mmc_card *card, u32 *csd)
{
if (mmc_host_is_spi(card->host))
return mmc_spi_send_csd(card, csd);
return mmc_send_cxd_native(card->host, card->rca << 16, csd,
MMC_SEND_CSD);
}
static int mmc_spi_send_cid(struct mmc_host *host, u32 *cid)
{ {
int ret, i; int ret, i;
__be32 *cid_tmp; __be32 *cid_tmp;
if (!mmc_host_is_spi(host)) {
if (!host->card)
return -EINVAL;
return mmc_send_cxd_native(host, host->card->rca << 16,
cid, MMC_SEND_CID);
}
cid_tmp = kzalloc(16, GFP_KERNEL); cid_tmp = kzalloc(16, GFP_KERNEL);
if (!cid_tmp) if (!cid_tmp)
return -ENOMEM; return -ENOMEM;
...@@ -355,6 +342,14 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid) ...@@ -355,6 +342,14 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid)
return ret; return ret;
} }
int mmc_send_cid(struct mmc_host *host, u32 *cid)
{
if (mmc_host_is_spi(host))
return mmc_spi_send_cid(host, cid);
return mmc_send_cxd_native(host, 0, cid, MMC_ALL_SEND_CID);
}
int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
{ {
int err; int err;
...@@ -800,7 +795,7 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width) ...@@ -800,7 +795,7 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width)
return mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width); return mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width);
} }
int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) static int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)
{ {
struct mmc_command cmd = {}; struct mmc_command cmd = {};
unsigned int opcode; unsigned int opcode;
...@@ -834,11 +829,208 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) ...@@ -834,11 +829,208 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)
return 0; return 0;
} }
/**
* mmc_interrupt_hpi - Issue for High priority Interrupt
* @card: the MMC card associated with the HPI transfer
*
* Issued High Priority Interrupt, and check for card status
* until out-of prg-state.
*/
int mmc_interrupt_hpi(struct mmc_card *card)
{
int err;
u32 status;
unsigned long prg_wait;
if (!card->ext_csd.hpi_en) {
pr_info("%s: HPI enable bit unset\n", mmc_hostname(card->host));
return 1;
}
mmc_claim_host(card->host);
err = mmc_send_status(card, &status);
if (err) {
pr_err("%s: Get card status fail\n", mmc_hostname(card->host));
goto out;
}
switch (R1_CURRENT_STATE(status)) {
case R1_STATE_IDLE:
case R1_STATE_READY:
case R1_STATE_STBY:
case R1_STATE_TRAN:
/*
* In idle and transfer states, HPI is not needed and the caller
* can issue the next intended command immediately
*/
goto out;
case R1_STATE_PRG:
break;
default:
/* In all other states, it's illegal to issue HPI */
pr_debug("%s: HPI cannot be sent. Card state=%d\n",
mmc_hostname(card->host), R1_CURRENT_STATE(status));
err = -EINVAL;
goto out;
}
err = mmc_send_hpi_cmd(card, &status);
if (err)
goto out;
prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time);
do {
err = mmc_send_status(card, &status);
if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN)
break;
if (time_after(jiffies, prg_wait))
err = -ETIMEDOUT;
} while (!err);
out:
mmc_release_host(card->host);
return err;
}
int mmc_can_ext_csd(struct mmc_card *card) int mmc_can_ext_csd(struct mmc_card *card)
{ {
return (card && card->csd.mmca_vsn > CSD_SPEC_VER_3); return (card && card->csd.mmca_vsn > CSD_SPEC_VER_3);
} }
/**
* mmc_stop_bkops - stop ongoing BKOPS
* @card: MMC card to check BKOPS
*
* Send HPI command to stop ongoing background operations to
* allow rapid servicing of foreground operations, e.g. read/
* writes. Wait until the card comes out of the programming state
* to avoid errors in servicing read/write requests.
*/
int mmc_stop_bkops(struct mmc_card *card)
{
int err = 0;
err = mmc_interrupt_hpi(card);
/*
* If err is EINVAL, we can't issue an HPI.
* It should complete the BKOPS.
*/
if (!err || (err == -EINVAL)) {
mmc_card_clr_doing_bkops(card);
mmc_retune_release(card->host);
err = 0;
}
return err;
}
static int mmc_read_bkops_status(struct mmc_card *card)
{
int err;
u8 *ext_csd;
mmc_claim_host(card->host);
err = mmc_get_ext_csd(card, &ext_csd);
mmc_release_host(card->host);
if (err)
return err;
card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS];
card->ext_csd.raw_exception_status = ext_csd[EXT_CSD_EXP_EVENTS_STATUS];
kfree(ext_csd);
return 0;
}
/**
* mmc_start_bkops - start BKOPS for supported cards
* @card: MMC card to start BKOPS
* @form_exception: A flag to indicate if this function was
* called due to an exception raised by the card
*
* Start background operations whenever requested.
* When the urgent BKOPS bit is set in a R1 command response
* then background operations should be started immediately.
*/
void mmc_start_bkops(struct mmc_card *card, bool from_exception)
{
int err;
int timeout;
bool use_busy_signal;
if (!card->ext_csd.man_bkops_en || mmc_card_doing_bkops(card))
return;
err = mmc_read_bkops_status(card);
if (err) {
pr_err("%s: Failed to read bkops status: %d\n",
mmc_hostname(card->host), err);
return;
}
if (!card->ext_csd.raw_bkops_status)
return;
if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 &&
from_exception)
return;
mmc_claim_host(card->host);
if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) {
timeout = MMC_OPS_TIMEOUT_MS;
use_busy_signal = true;
} else {
timeout = 0;
use_busy_signal = false;
}
mmc_retune_hold(card->host);
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BKOPS_START, 1, timeout, 0,
use_busy_signal, true, false);
if (err) {
pr_warn("%s: Error %d starting bkops\n",
mmc_hostname(card->host), err);
mmc_retune_release(card->host);
goto out;
}
/*
* For urgent bkops status (LEVEL_2 and more)
* bkops executed synchronously, otherwise
* the operation is in progress
*/
if (!use_busy_signal)
mmc_card_set_doing_bkops(card);
else
mmc_retune_release(card->host);
out:
mmc_release_host(card->host);
}
/*
* Flush the cache to the non-volatile storage.
*/
int mmc_flush_cache(struct mmc_card *card)
{
int err = 0;
if (mmc_card_mmc(card) &&
(card->ext_csd.cache_size > 0) &&
(card->ext_csd.cache_ctrl & 1)) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_FLUSH_CACHE, 1, 0);
if (err)
pr_err("%s: cache flush error %d\n",
mmc_hostname(card->host), err);
}
return err;
}
EXPORT_SYMBOL(mmc_flush_cache);
static int mmc_cmdq_switch(struct mmc_card *card, bool enable) static int mmc_cmdq_switch(struct mmc_card *card, bool enable)
{ {
u8 val = enable ? EXT_CSD_CMDQ_MODE_ENABLED : 0; u8 val = enable ? EXT_CSD_CMDQ_MODE_ENABLED : 0;
......
...@@ -22,15 +22,14 @@ int mmc_deselect_cards(struct mmc_host *host); ...@@ -22,15 +22,14 @@ int mmc_deselect_cards(struct mmc_host *host);
int mmc_set_dsr(struct mmc_host *host); int mmc_set_dsr(struct mmc_host *host);
int mmc_go_idle(struct mmc_host *host); int mmc_go_idle(struct mmc_host *host);
int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_all_send_cid(struct mmc_host *host, u32 *cid);
int mmc_set_relative_addr(struct mmc_card *card); int mmc_set_relative_addr(struct mmc_card *card);
int mmc_send_csd(struct mmc_card *card, u32 *csd); int mmc_send_csd(struct mmc_card *card, u32 *csd);
int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries);
int mmc_send_status(struct mmc_card *card, u32 *status); int mmc_send_status(struct mmc_card *card, u32 *status);
int mmc_send_cid(struct mmc_host *host, u32 *cid); int mmc_send_cid(struct mmc_host *host, u32 *cid);
int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
int mmc_spi_set_crc(struct mmc_host *host, int use_crc); int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
int mmc_bus_test(struct mmc_card *card, u8 bus_width); int mmc_bus_test(struct mmc_card *card, u8 bus_width);
int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
int mmc_interrupt_hpi(struct mmc_card *card); int mmc_interrupt_hpi(struct mmc_card *card);
int mmc_can_ext_csd(struct mmc_card *card); int mmc_can_ext_csd(struct mmc_card *card);
int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
...@@ -42,9 +41,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, ...@@ -42,9 +41,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
unsigned int timeout_ms); unsigned int timeout_ms);
int mmc_stop_bkops(struct mmc_card *card); int mmc_stop_bkops(struct mmc_card *card);
int mmc_read_bkops_status(struct mmc_card *card);
void mmc_start_bkops(struct mmc_card *card, bool from_exception); void mmc_start_bkops(struct mmc_card *card, bool from_exception);
int mmc_can_reset(struct mmc_card *card);
int mmc_flush_cache(struct mmc_card *card); int mmc_flush_cache(struct mmc_card *card);
int mmc_cmdq_enable(struct mmc_card *card); int mmc_cmdq_enable(struct mmc_card *card);
int mmc_cmdq_disable(struct mmc_card *card); int mmc_cmdq_disable(struct mmc_card *card);
......
...@@ -3220,8 +3220,6 @@ static int __mmc_test_register_dbgfs_file(struct mmc_card *card, ...@@ -3220,8 +3220,6 @@ static int __mmc_test_register_dbgfs_file(struct mmc_card *card,
df = kmalloc(sizeof(*df), GFP_KERNEL); df = kmalloc(sizeof(*df), GFP_KERNEL);
if (!df) { if (!df) {
debugfs_remove(file); debugfs_remove(file);
dev_err(&card->dev,
"Can't allocate memory for internal usage.\n");
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -76,6 +76,14 @@ void mmc_pwrseq_power_off(struct mmc_host *host) ...@@ -76,6 +76,14 @@ void mmc_pwrseq_power_off(struct mmc_host *host)
pwrseq->ops->power_off(host); pwrseq->ops->power_off(host);
} }
void mmc_pwrseq_reset(struct mmc_host *host)
{
struct mmc_pwrseq *pwrseq = host->pwrseq;
if (pwrseq && pwrseq->ops->reset)
pwrseq->ops->reset(host);
}
void mmc_pwrseq_free(struct mmc_host *host) void mmc_pwrseq_free(struct mmc_host *host)
{ {
struct mmc_pwrseq *pwrseq = host->pwrseq; struct mmc_pwrseq *pwrseq = host->pwrseq;
......
...@@ -18,6 +18,7 @@ struct mmc_pwrseq_ops { ...@@ -18,6 +18,7 @@ struct mmc_pwrseq_ops {
void (*pre_power_on)(struct mmc_host *host); void (*pre_power_on)(struct mmc_host *host);
void (*post_power_on)(struct mmc_host *host); void (*post_power_on)(struct mmc_host *host);
void (*power_off)(struct mmc_host *host); void (*power_off)(struct mmc_host *host);
void (*reset)(struct mmc_host *host);
}; };
struct mmc_pwrseq { struct mmc_pwrseq {
...@@ -36,6 +37,7 @@ int mmc_pwrseq_alloc(struct mmc_host *host); ...@@ -36,6 +37,7 @@ int mmc_pwrseq_alloc(struct mmc_host *host);
void mmc_pwrseq_pre_power_on(struct mmc_host *host); void mmc_pwrseq_pre_power_on(struct mmc_host *host);
void mmc_pwrseq_post_power_on(struct mmc_host *host); void mmc_pwrseq_post_power_on(struct mmc_host *host);
void mmc_pwrseq_power_off(struct mmc_host *host); void mmc_pwrseq_power_off(struct mmc_host *host);
void mmc_pwrseq_reset(struct mmc_host *host);
void mmc_pwrseq_free(struct mmc_host *host); void mmc_pwrseq_free(struct mmc_host *host);
#else #else
...@@ -49,6 +51,7 @@ static inline int mmc_pwrseq_alloc(struct mmc_host *host) { return 0; } ...@@ -49,6 +51,7 @@ static inline int mmc_pwrseq_alloc(struct mmc_host *host) { return 0; }
static inline void mmc_pwrseq_pre_power_on(struct mmc_host *host) {} static inline void mmc_pwrseq_pre_power_on(struct mmc_host *host) {}
static inline void mmc_pwrseq_post_power_on(struct mmc_host *host) {} static inline void mmc_pwrseq_post_power_on(struct mmc_host *host) {}
static inline void mmc_pwrseq_power_off(struct mmc_host *host) {} static inline void mmc_pwrseq_power_off(struct mmc_host *host) {}
static inline void mmc_pwrseq_reset(struct mmc_host *host) {}
static inline void mmc_pwrseq_free(struct mmc_host *host) {} static inline void mmc_pwrseq_free(struct mmc_host *host) {}
#endif #endif
......
...@@ -56,7 +56,7 @@ static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, ...@@ -56,7 +56,7 @@ static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this,
} }
static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = {
.post_power_on = mmc_pwrseq_emmc_reset, .reset = mmc_pwrseq_emmc_reset,
}; };
static int mmc_pwrseq_emmc_probe(struct platform_device *pdev) static int mmc_pwrseq_emmc_probe(struct platform_device *pdev)
......
...@@ -40,35 +40,6 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) ...@@ -40,35 +40,6 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
return BLKPREP_OK; return BLKPREP_OK;
} }
struct mmc_queue_req *mmc_queue_req_find(struct mmc_queue *mq,
struct request *req)
{
struct mmc_queue_req *mqrq;
int i = ffz(mq->qslots);
if (i >= mq->qdepth)
return NULL;
mqrq = &mq->mqrq[i];
WARN_ON(mqrq->req || mq->qcnt >= mq->qdepth ||
test_bit(mqrq->task_id, &mq->qslots));
mqrq->req = req;
mq->qcnt += 1;
__set_bit(mqrq->task_id, &mq->qslots);
return mqrq;
}
void mmc_queue_req_free(struct mmc_queue *mq,
struct mmc_queue_req *mqrq)
{
WARN_ON(!mqrq->req || mq->qcnt < 1 ||
!test_bit(mqrq->task_id, &mq->qslots));
mqrq->req = NULL;
mq->qcnt -= 1;
__clear_bit(mqrq->task_id, &mq->qslots);
}
static int mmc_queue_thread(void *d) static int mmc_queue_thread(void *d)
{ {
struct mmc_queue *mq = d; struct mmc_queue *mq = d;
...@@ -149,11 +120,11 @@ static void mmc_request_fn(struct request_queue *q) ...@@ -149,11 +120,11 @@ static void mmc_request_fn(struct request_queue *q)
wake_up_process(mq->thread); wake_up_process(mq->thread);
} }
static struct scatterlist *mmc_alloc_sg(int sg_len) static struct scatterlist *mmc_alloc_sg(int sg_len, gfp_t gfp)
{ {
struct scatterlist *sg; struct scatterlist *sg;
sg = kmalloc_array(sg_len, sizeof(*sg), GFP_KERNEL); sg = kmalloc_array(sg_len, sizeof(*sg), gfp);
if (sg) if (sg)
sg_init_table(sg, sg_len); sg_init_table(sg, sg_len);
...@@ -179,86 +150,11 @@ static void mmc_queue_setup_discard(struct request_queue *q, ...@@ -179,86 +150,11 @@ static void mmc_queue_setup_discard(struct request_queue *q,
queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q); queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q);
} }
static void mmc_queue_req_free_bufs(struct mmc_queue_req *mqrq)
{
kfree(mqrq->bounce_sg);
mqrq->bounce_sg = NULL;
kfree(mqrq->sg);
mqrq->sg = NULL;
kfree(mqrq->bounce_buf);
mqrq->bounce_buf = NULL;
}
static void mmc_queue_reqs_free_bufs(struct mmc_queue_req *mqrq, int qdepth)
{
int i;
for (i = 0; i < qdepth; i++)
mmc_queue_req_free_bufs(&mqrq[i]);
}
static void mmc_queue_free_mqrqs(struct mmc_queue_req *mqrq, int qdepth)
{
mmc_queue_reqs_free_bufs(mqrq, qdepth);
kfree(mqrq);
}
static struct mmc_queue_req *mmc_queue_alloc_mqrqs(int qdepth)
{
struct mmc_queue_req *mqrq;
int i;
mqrq = kcalloc(qdepth, sizeof(*mqrq), GFP_KERNEL);
if (mqrq) {
for (i = 0; i < qdepth; i++)
mqrq[i].task_id = i;
}
return mqrq;
}
#ifdef CONFIG_MMC_BLOCK_BOUNCE
static int mmc_queue_alloc_bounce_bufs(struct mmc_queue_req *mqrq, int qdepth,
unsigned int bouncesz)
{
int i;
for (i = 0; i < qdepth; i++) {
mqrq[i].bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
if (!mqrq[i].bounce_buf)
return -ENOMEM;
mqrq[i].sg = mmc_alloc_sg(1);
if (!mqrq[i].sg)
return -ENOMEM;
mqrq[i].bounce_sg = mmc_alloc_sg(bouncesz / 512);
if (!mqrq[i].bounce_sg)
return -ENOMEM;
}
return 0;
}
static bool mmc_queue_alloc_bounce(struct mmc_queue_req *mqrq, int qdepth,
unsigned int bouncesz)
{
int ret;
ret = mmc_queue_alloc_bounce_bufs(mqrq, qdepth, bouncesz);
if (ret)
mmc_queue_reqs_free_bufs(mqrq, qdepth);
return !ret;
}
static unsigned int mmc_queue_calc_bouncesz(struct mmc_host *host) static unsigned int mmc_queue_calc_bouncesz(struct mmc_host *host)
{ {
unsigned int bouncesz = MMC_QUEUE_BOUNCESZ; unsigned int bouncesz = MMC_QUEUE_BOUNCESZ;
if (host->max_segs != 1) if (host->max_segs != 1 || (host->caps & MMC_CAP_NO_BOUNCE_BUFF))
return 0; return 0;
if (bouncesz > host->max_req_size) if (bouncesz > host->max_req_size)
...@@ -273,84 +169,58 @@ static unsigned int mmc_queue_calc_bouncesz(struct mmc_host *host) ...@@ -273,84 +169,58 @@ static unsigned int mmc_queue_calc_bouncesz(struct mmc_host *host)
return bouncesz; return bouncesz;
} }
#else
static inline bool mmc_queue_alloc_bounce(struct mmc_queue_req *mqrq,
int qdepth, unsigned int bouncesz)
{
return false;
}
static unsigned int mmc_queue_calc_bouncesz(struct mmc_host *host) /**
{ * mmc_init_request() - initialize the MMC-specific per-request data
return 0; * @q: the request queue
} * @req: the request
#endif * @gfp: memory allocation policy
*/
static int mmc_queue_alloc_sgs(struct mmc_queue_req *mqrq, int qdepth, static int mmc_init_request(struct request_queue *q, struct request *req,
int max_segs) gfp_t gfp)
{ {
int i; struct mmc_queue_req *mq_rq = req_to_mmc_queue_req(req);
struct mmc_queue *mq = q->queuedata;
struct mmc_card *card = mq->card;
struct mmc_host *host = card->host;
for (i = 0; i < qdepth; i++) { if (card->bouncesz) {
mqrq[i].sg = mmc_alloc_sg(max_segs); mq_rq->bounce_buf = kmalloc(card->bouncesz, gfp);
if (!mqrq[i].sg) if (!mq_rq->bounce_buf)
return -ENOMEM;
if (card->bouncesz > 512) {
mq_rq->sg = mmc_alloc_sg(1, gfp);
if (!mq_rq->sg)
return -ENOMEM;
mq_rq->bounce_sg = mmc_alloc_sg(card->bouncesz / 512,
gfp);
if (!mq_rq->bounce_sg)
return -ENOMEM;
}
} else {
mq_rq->bounce_buf = NULL;
mq_rq->bounce_sg = NULL;
mq_rq->sg = mmc_alloc_sg(host->max_segs, gfp);
if (!mq_rq->sg)
return -ENOMEM; return -ENOMEM;
} }
return 0; return 0;
} }
void mmc_queue_free_shared_queue(struct mmc_card *card) static void mmc_exit_request(struct request_queue *q, struct request *req)
{
if (card->mqrq) {
mmc_queue_free_mqrqs(card->mqrq, card->qdepth);
card->mqrq = NULL;
}
}
static int __mmc_queue_alloc_shared_queue(struct mmc_card *card, int qdepth)
{ {
struct mmc_host *host = card->host; struct mmc_queue_req *mq_rq = req_to_mmc_queue_req(req);
struct mmc_queue_req *mqrq;
unsigned int bouncesz;
int ret = 0;
if (card->mqrq)
return -EINVAL;
mqrq = mmc_queue_alloc_mqrqs(qdepth);
if (!mqrq)
return -ENOMEM;
card->mqrq = mqrq;
card->qdepth = qdepth;
bouncesz = mmc_queue_calc_bouncesz(host);
if (bouncesz && !mmc_queue_alloc_bounce(mqrq, qdepth, bouncesz)) {
bouncesz = 0;
pr_warn("%s: unable to allocate bounce buffers\n",
mmc_card_name(card));
}
card->bouncesz = bouncesz; /* It is OK to kfree(NULL) so this will be smooth */
kfree(mq_rq->bounce_sg);
mq_rq->bounce_sg = NULL;
if (!bouncesz) { kfree(mq_rq->bounce_buf);
ret = mmc_queue_alloc_sgs(mqrq, qdepth, host->max_segs); mq_rq->bounce_buf = NULL;
if (ret)
goto out_err;
}
return ret;
out_err: kfree(mq_rq->sg);
mmc_queue_free_shared_queue(card); mq_rq->sg = NULL;
return ret;
}
int mmc_queue_alloc_shared_queue(struct mmc_card *card)
{
return __mmc_queue_alloc_shared_queue(card, 2);
} }
/** /**
...@@ -373,13 +243,21 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, ...@@ -373,13 +243,21 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
mq->card = card; mq->card = card;
mq->queue = blk_init_queue(mmc_request_fn, lock); mq->queue = blk_alloc_queue(GFP_KERNEL);
if (!mq->queue) if (!mq->queue)
return -ENOMEM; return -ENOMEM;
mq->queue->queue_lock = lock;
mq->mqrq = card->mqrq; mq->queue->request_fn = mmc_request_fn;
mq->qdepth = card->qdepth; mq->queue->init_rq_fn = mmc_init_request;
mq->queue->exit_rq_fn = mmc_exit_request;
mq->queue->cmd_size = sizeof(struct mmc_queue_req);
mq->queue->queuedata = mq; mq->queue->queuedata = mq;
mq->qcnt = 0;
ret = blk_init_allocated_queue(mq->queue);
if (ret) {
blk_cleanup_queue(mq->queue);
return ret;
}
blk_queue_prep_rq(mq->queue, mmc_prep_request); blk_queue_prep_rq(mq->queue, mmc_prep_request);
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
...@@ -387,6 +265,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, ...@@ -387,6 +265,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
if (mmc_can_erase(card)) if (mmc_can_erase(card))
mmc_queue_setup_discard(mq->queue, card); mmc_queue_setup_discard(mq->queue, card);
card->bouncesz = mmc_queue_calc_bouncesz(host);
if (card->bouncesz) { if (card->bouncesz) {
blk_queue_max_hw_sectors(mq->queue, card->bouncesz / 512); blk_queue_max_hw_sectors(mq->queue, card->bouncesz / 512);
blk_queue_max_segments(mq->queue, card->bouncesz / 512); blk_queue_max_segments(mq->queue, card->bouncesz / 512);
...@@ -412,7 +291,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, ...@@ -412,7 +291,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
return 0; return 0;
cleanup_queue: cleanup_queue:
mq->mqrq = NULL;
blk_cleanup_queue(mq->queue); blk_cleanup_queue(mq->queue);
return ret; return ret;
} }
...@@ -434,7 +312,6 @@ void mmc_cleanup_queue(struct mmc_queue *mq) ...@@ -434,7 +312,6 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
blk_start_queue(q); blk_start_queue(q);
spin_unlock_irqrestore(q->queue_lock, flags); spin_unlock_irqrestore(q->queue_lock, flags);
mq->mqrq = NULL;
mq->card = NULL; mq->card = NULL;
} }
EXPORT_SYMBOL(mmc_cleanup_queue); EXPORT_SYMBOL(mmc_cleanup_queue);
...@@ -491,12 +368,13 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq) ...@@ -491,12 +368,13 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
unsigned int sg_len; unsigned int sg_len;
size_t buflen; size_t buflen;
struct scatterlist *sg; struct scatterlist *sg;
struct request *req = mmc_queue_req_to_req(mqrq);
int i; int i;
if (!mqrq->bounce_buf) if (!mqrq->bounce_buf)
return blk_rq_map_sg(mq->queue, mqrq->req, mqrq->sg); return blk_rq_map_sg(mq->queue, req, mqrq->sg);
sg_len = blk_rq_map_sg(mq->queue, mqrq->req, mqrq->bounce_sg); sg_len = blk_rq_map_sg(mq->queue, req, mqrq->bounce_sg);
mqrq->bounce_sg_len = sg_len; mqrq->bounce_sg_len = sg_len;
...@@ -518,7 +396,7 @@ void mmc_queue_bounce_pre(struct mmc_queue_req *mqrq) ...@@ -518,7 +396,7 @@ void mmc_queue_bounce_pre(struct mmc_queue_req *mqrq)
if (!mqrq->bounce_buf) if (!mqrq->bounce_buf)
return; return;
if (rq_data_dir(mqrq->req) != WRITE) if (rq_data_dir(mmc_queue_req_to_req(mqrq)) != WRITE)
return; return;
sg_copy_to_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len, sg_copy_to_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
...@@ -534,7 +412,7 @@ void mmc_queue_bounce_post(struct mmc_queue_req *mqrq) ...@@ -534,7 +412,7 @@ void mmc_queue_bounce_post(struct mmc_queue_req *mqrq)
if (!mqrq->bounce_buf) if (!mqrq->bounce_buf)
return; return;
if (rq_data_dir(mqrq->req) != READ) if (rq_data_dir(mmc_queue_req_to_req(mqrq)) != READ)
return; return;
sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len, sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
......
...@@ -3,19 +3,25 @@ ...@@ -3,19 +3,25 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/blk-mq.h>
#include <linux/mmc/core.h> #include <linux/mmc/core.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
static inline bool mmc_req_is_special(struct request *req) static inline struct mmc_queue_req *req_to_mmc_queue_req(struct request *rq)
{ {
return req && return blk_mq_rq_to_pdu(rq);
(req_op(req) == REQ_OP_FLUSH || }
req_op(req) == REQ_OP_DISCARD ||
req_op(req) == REQ_OP_SECURE_ERASE); struct mmc_queue_req;
static inline struct request *mmc_queue_req_to_req(struct mmc_queue_req *mqr)
{
return blk_mq_rq_from_pdu(mqr);
} }
struct task_struct; struct task_struct;
struct mmc_blk_data; struct mmc_blk_data;
struct mmc_blk_ioc_data;
struct mmc_blk_request { struct mmc_blk_request {
struct mmc_request mrq; struct mmc_request mrq;
...@@ -26,15 +32,27 @@ struct mmc_blk_request { ...@@ -26,15 +32,27 @@ struct mmc_blk_request {
int retune_retry_done; int retune_retry_done;
}; };
/**
* enum mmc_drv_op - enumerates the operations in the mmc_queue_req
* @MMC_DRV_OP_IOCTL: ioctl operation
* @MMC_DRV_OP_BOOT_WP: write protect boot partitions
*/
enum mmc_drv_op {
MMC_DRV_OP_IOCTL,
MMC_DRV_OP_BOOT_WP,
};
struct mmc_queue_req { struct mmc_queue_req {
struct request *req;
struct mmc_blk_request brq; struct mmc_blk_request brq;
struct scatterlist *sg; struct scatterlist *sg;
char *bounce_buf; char *bounce_buf;
struct scatterlist *bounce_sg; struct scatterlist *bounce_sg;
unsigned int bounce_sg_len; unsigned int bounce_sg_len;
struct mmc_async_req areq; struct mmc_async_req areq;
int task_id; enum mmc_drv_op drv_op;
int drv_op_result;
struct mmc_blk_ioc_data **idata;
unsigned int ioc_count;
}; };
struct mmc_queue { struct mmc_queue {
...@@ -45,14 +63,15 @@ struct mmc_queue { ...@@ -45,14 +63,15 @@ struct mmc_queue {
bool asleep; bool asleep;
struct mmc_blk_data *blkdata; struct mmc_blk_data *blkdata;
struct request_queue *queue; struct request_queue *queue;
struct mmc_queue_req *mqrq; /*
int qdepth; * FIXME: this counter is not a very reliable way of keeping
* track of how many requests that are ongoing. Switch to just
* letting the block core keep track of requests and per-request
* associated mmc_queue_req data.
*/
int qcnt; int qcnt;
unsigned long qslots;
}; };
extern int mmc_queue_alloc_shared_queue(struct mmc_card *card);
extern void mmc_queue_free_shared_queue(struct mmc_card *card);
extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *, extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
const char *); const char *);
extern void mmc_cleanup_queue(struct mmc_queue *); extern void mmc_cleanup_queue(struct mmc_queue *);
...@@ -66,8 +85,4 @@ extern void mmc_queue_bounce_post(struct mmc_queue_req *); ...@@ -66,8 +85,4 @@ extern void mmc_queue_bounce_post(struct mmc_queue_req *);
extern int mmc_access_rpmb(struct mmc_queue *); extern int mmc_access_rpmb(struct mmc_queue *);
extern struct mmc_queue_req *mmc_queue_req_find(struct mmc_queue *,
struct request *);
extern void mmc_queue_req_free(struct mmc_queue *, struct mmc_queue_req *);
#endif #endif
...@@ -294,12 +294,8 @@ static int mmc_read_switch(struct mmc_card *card) ...@@ -294,12 +294,8 @@ static int mmc_read_switch(struct mmc_card *card)
err = -EIO; err = -EIO;
status = kmalloc(64, GFP_KERNEL); status = kmalloc(64, GFP_KERNEL);
if (!status) { if (!status)
pr_err("%s: could not allocate a buffer for "
"switch capabilities.\n",
mmc_hostname(card->host));
return -ENOMEM; return -ENOMEM;
}
/* /*
* Find out the card's support bits with a mode 0 operation. * Find out the card's support bits with a mode 0 operation.
...@@ -359,11 +355,8 @@ int mmc_sd_switch_hs(struct mmc_card *card) ...@@ -359,11 +355,8 @@ int mmc_sd_switch_hs(struct mmc_card *card)
return 0; return 0;
status = kmalloc(64, GFP_KERNEL); status = kmalloc(64, GFP_KERNEL);
if (!status) { if (!status)
pr_err("%s: could not allocate a buffer for "
"switch capabilities.\n", mmc_hostname(card->host));
return -ENOMEM; return -ENOMEM;
}
err = mmc_sd_switch(card, 1, 0, 1, status); err = mmc_sd_switch(card, 1, 0, 1, status);
if (err) if (err)
...@@ -596,11 +589,8 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) ...@@ -596,11 +589,8 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
return 0; return 0;
status = kmalloc(64, GFP_KERNEL); status = kmalloc(64, GFP_KERNEL);
if (!status) { if (!status)
pr_err("%s: could not allocate a buffer for "
"switch capabilities.\n", mmc_hostname(card->host));
return -ENOMEM; return -ENOMEM;
}
/* Set 4-bit bus width */ /* Set 4-bit bus width */
if ((card->host->caps & MMC_CAP_4_BIT_DATA) && if ((card->host->caps & MMC_CAP_4_BIT_DATA) &&
...@@ -798,11 +788,7 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr) ...@@ -798,11 +788,7 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
} }
} }
if (mmc_host_is_spi(host))
err = mmc_send_cid(host, cid); err = mmc_send_cid(host, cid);
else
err = mmc_all_send_cid(host, cid);
return err; return err;
} }
......
...@@ -1103,6 +1103,12 @@ int mmc_attach_sdio(struct mmc_host *host) ...@@ -1103,6 +1103,12 @@ int mmc_attach_sdio(struct mmc_host *host)
* Enable runtime PM only if supported by host+card+board * Enable runtime PM only if supported by host+card+board
*/ */
if (host->caps & MMC_CAP_POWER_OFF_CARD) { if (host->caps & MMC_CAP_POWER_OFF_CARD) {
/*
* Do not allow runtime suspend until after SDIO function
* devices are added.
*/
pm_runtime_get_noresume(&card->dev);
/* /*
* Let runtime PM core know our card is active * Let runtime PM core know our card is active
*/ */
...@@ -1155,18 +1161,22 @@ int mmc_attach_sdio(struct mmc_host *host) ...@@ -1155,18 +1161,22 @@ int mmc_attach_sdio(struct mmc_host *host)
goto remove_added; goto remove_added;
} }
if (host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_put(&card->dev);
mmc_claim_host(host); mmc_claim_host(host);
return 0; return 0;
remove_added:
/* Remove without lock if the device has been added. */
mmc_sdio_remove(host);
mmc_claim_host(host);
remove: remove:
/* And with lock if it hasn't been added. */
mmc_release_host(host); mmc_release_host(host);
if (host->card) remove_added:
/*
* The devices are being deleted so it is not necessary to disable
* runtime PM. Similarly we also don't pm_runtime_put() the SDIO card
* because it needs to be active to remove any function devices that
* were probed, and after that it gets deleted.
*/
mmc_sdio_remove(host); mmc_sdio_remove(host);
mmc_claim_host(host); mmc_claim_host(host);
err: err:
......
...@@ -95,12 +95,30 @@ static int process_sdio_pending_irqs(struct mmc_host *host) ...@@ -95,12 +95,30 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
void sdio_run_irqs(struct mmc_host *host) void sdio_run_irqs(struct mmc_host *host)
{ {
mmc_claim_host(host); mmc_claim_host(host);
if (host->sdio_irqs) {
host->sdio_irq_pending = true; host->sdio_irq_pending = true;
process_sdio_pending_irqs(host); process_sdio_pending_irqs(host);
if (host->ops->ack_sdio_irq)
host->ops->ack_sdio_irq(host);
}
mmc_release_host(host); mmc_release_host(host);
} }
EXPORT_SYMBOL_GPL(sdio_run_irqs); EXPORT_SYMBOL_GPL(sdio_run_irqs);
void sdio_irq_work(struct work_struct *work)
{
struct mmc_host *host =
container_of(work, struct mmc_host, sdio_irq_work.work);
sdio_run_irqs(host);
}
void sdio_signal_irq(struct mmc_host *host)
{
queue_delayed_work(system_wq, &host->sdio_irq_work, 0);
}
EXPORT_SYMBOL_GPL(sdio_signal_irq);
static int sdio_irq_thread(void *_host) static int sdio_irq_thread(void *_host)
{ {
struct mmc_host *host = _host; struct mmc_host *host = _host;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
struct mmc_host; struct mmc_host;
struct mmc_card; struct mmc_card;
struct work_struct;
int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
...@@ -25,6 +26,7 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, ...@@ -25,6 +26,7 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz); unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz);
int sdio_reset(struct mmc_host *host); int sdio_reset(struct mmc_host *host);
unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz); unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz);
void sdio_irq_work(struct work_struct *work);
static inline bool sdio_is_io_busy(u32 opcode, u32 arg) static inline bool sdio_is_io_busy(u32 opcode, u32 arg)
{ {
......
...@@ -151,6 +151,8 @@ void mmc_gpiod_request_cd_irq(struct mmc_host *host) ...@@ -151,6 +151,8 @@ void mmc_gpiod_request_cd_irq(struct mmc_host *host)
if (irq < 0) if (irq < 0)
host->caps |= MMC_CAP_NEEDS_POLL; host->caps |= MMC_CAP_NEEDS_POLL;
else if ((host->caps & MMC_CAP_CD_WAKE) && !enable_irq_wake(irq))
host->slot.cd_wake_enabled = true;
} }
EXPORT_SYMBOL(mmc_gpiod_request_cd_irq); EXPORT_SYMBOL(mmc_gpiod_request_cd_irq);
......
...@@ -408,11 +408,11 @@ config MMC_AU1X ...@@ -408,11 +408,11 @@ config MMC_AU1X
config MMC_ATMELMCI config MMC_ATMELMCI
tristate "Atmel SD/MMC Driver (Multimedia Card Interface)" tristate "Atmel SD/MMC Driver (Multimedia Card Interface)"
depends on AVR32 || ARCH_AT91 depends on ARCH_AT91
help help
This selects the Atmel Multimedia Card Interface driver. If This selects the Atmel Multimedia Card Interface driver.
you have an AT32 (AVR32) or AT91 platform with a Multimedia If you have an AT91 platform with a Multimedia Card slot,
Card slot, say Y or M here. say Y or M here.
If unsure, say N. If unsure, say N.
...@@ -571,13 +571,13 @@ config MMC_TMIO ...@@ -571,13 +571,13 @@ config MMC_TMIO
T7L66XB and also HTC ASIC3 T7L66XB and also HTC ASIC3
config MMC_SDHI config MMC_SDHI
tristate "SH-Mobile SDHI SD/SDIO controller support" tristate "Renesas SDHI SD/SDIO controller support"
depends on SUPERH || ARM || ARM64 depends on SUPERH || ARM || ARM64
depends on SUPERH || ARCH_RENESAS || COMPILE_TEST depends on SUPERH || ARCH_RENESAS || COMPILE_TEST
select MMC_TMIO_CORE select MMC_TMIO_CORE
help help
This provides support for the SDHI SD/SDIO controller found in This provides support for the SDHI SD/SDIO controller found in
SuperH and ARM SH-Mobile SoCs Renesas SuperH, ARM and ARM64 based SoCs
config MMC_CB710 config MMC_CB710
tristate "ENE CB710 MMC/SD Interface support" tristate "ENE CB710 MMC/SD Interface support"
......
...@@ -36,9 +36,7 @@ obj-$(CONFIG_MMC_S3C) += s3cmci.o ...@@ -36,9 +36,7 @@ obj-$(CONFIG_MMC_S3C) += s3cmci.o
obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o
obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
obj-$(CONFIG_MMC_TMIO_CORE) += tmio_mmc_core.o obj-$(CONFIG_MMC_TMIO_CORE) += tmio_mmc_core.o
tmio_mmc_core-y := tmio_mmc_pio.o obj-$(CONFIG_MMC_SDHI) += renesas_sdhi_core.o renesas_sdhi_sys_dmac.o
tmio_mmc_core-$(subst m,y,$(CONFIG_MMC_SDHI)) += tmio_mmc_dma.o
obj-$(CONFIG_MMC_SDHI) += sh_mobile_sdhi.o
obj-$(CONFIG_MMC_CB710) += cb710-mmc.o obj-$(CONFIG_MMC_CB710) += cb710-mmc.o
obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o
obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
/* /*
* Superset of MCI IP registers integrated in Atmel AVR32 and AT91 Processors * Superset of MCI IP registers integrated in Atmel AT91 Processor
* Registers and bitfields marked with [2] are only available in MCI2 * Registers and bitfields marked with [2] are only available in MCI2
*/ */
...@@ -172,13 +172,6 @@ ...@@ -172,13 +172,6 @@
#define atmci_writel(port, reg, value) \ #define atmci_writel(port, reg, value) \
__raw_writel((value), (port)->regs + reg) __raw_writel((value), (port)->regs + reg)
/* On AVR chips the Peripheral DMA Controller is not connected to MCI. */
#ifdef CONFIG_AVR32
# define ATMCI_PDC_CONNECTED 0
#else
# define ATMCI_PDC_CONNECTED 1
#endif
#define AUTOSUSPEND_DELAY 50 #define AUTOSUSPEND_DELAY 50
#define ATMCI_DATA_ERROR_FLAGS (ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE) #define ATMCI_DATA_ERROR_FLAGS (ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE)
...@@ -667,10 +660,8 @@ atmci_of_init(struct platform_device *pdev) ...@@ -667,10 +660,8 @@ atmci_of_init(struct platform_device *pdev)
} }
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) { if (!pdata)
dev_err(&pdev->dev, "could not allocate memory for pdata\n");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
for_each_child_of_node(np, cnp) { for_each_child_of_node(np, cnp) {
if (of_property_read_u32(cnp, "reg", &slot_id)) { if (of_property_read_u32(cnp, "reg", &slot_id)) {
...@@ -1549,21 +1540,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -1549,21 +1540,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
break; break;
default: default:
/*
* TODO: None of the currently available AVR32-based
* boards allow MMC power to be turned off. Implement
* power control when this can be tested properly.
*
* We also need to hook this into the clock management
* somehow so that newly inserted cards aren't
* subjected to a fast clock before we have a chance
* to figure out what the maximum rate is. Currently,
* there's no way to avoid this, and there never will
* be for boards that don't support power control.
*/
break; break;
} }
} }
static int atmci_get_ro(struct mmc_host *mmc) static int atmci_get_ro(struct mmc_host *mmc)
...@@ -2464,7 +2442,7 @@ static void atmci_get_cap(struct atmel_mci *host) ...@@ -2464,7 +2442,7 @@ static void atmci_get_cap(struct atmel_mci *host)
"version: 0x%x\n", version); "version: 0x%x\n", version);
host->caps.has_dma_conf_reg = 0; host->caps.has_dma_conf_reg = 0;
host->caps.has_pdc = ATMCI_PDC_CONNECTED; host->caps.has_pdc = 1;
host->caps.has_cfg_reg = 0; host->caps.has_cfg_reg = 0;
host->caps.has_cstor_reg = 0; host->caps.has_cstor_reg = 0;
host->caps.has_highspeed = 0; host->caps.has_highspeed = 0;
......
...@@ -1172,7 +1172,10 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq) ...@@ -1172,7 +1172,10 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
if (mrq->data && !is_power_of_2(mrq->data->blksz)) { if (mrq->data && !is_power_of_2(mrq->data->blksz)) {
dev_err(dev, "unsupported block size (%d bytes)\n", dev_err(dev, "unsupported block size (%d bytes)\n",
mrq->data->blksz); mrq->data->blksz);
if (mrq->cmd)
mrq->cmd->error = -EINVAL; mrq->cmd->error = -EINVAL;
mmc_request_done(mmc, mrq); mmc_request_done(mmc, mrq);
return; return;
} }
...@@ -1194,7 +1197,10 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq) ...@@ -1194,7 +1197,10 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
readl(host->ioaddr + SDCMD) & SDCMD_CMD_MASK, readl(host->ioaddr + SDCMD) & SDCMD_CMD_MASK,
edm); edm);
bcm2835_dumpregs(host); bcm2835_dumpregs(host);
if (mrq->cmd)
mrq->cmd->error = -EILSEQ; mrq->cmd->error = -EILSEQ;
bcm2835_finish_request(host); bcm2835_finish_request(host);
mutex_unlock(&host->mutex); mutex_unlock(&host->mutex);
return; return;
...@@ -1207,7 +1213,7 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq) ...@@ -1207,7 +1213,7 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
if (!host->use_busy) if (!host->use_busy)
bcm2835_finish_command(host); bcm2835_finish_command(host);
} }
} else if (bcm2835_send_command(host, mrq->cmd)) { } else if (mrq->cmd && bcm2835_send_command(host, mrq->cmd)) {
if (host->data && host->dma_desc) { if (host->data && host->dma_desc) {
/* DMA transfer starts now, PIO starts after irq */ /* DMA transfer starts now, PIO starts after irq */
bcm2835_start_dma(host); bcm2835_start_dma(host);
......
...@@ -1035,10 +1035,12 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host) ...@@ -1035,10 +1035,12 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host)
* We only have a 3.3v supply, we cannot support any * We only have a 3.3v supply, we cannot support any
* of the UHS modes. We do support the high speed DDR * of the UHS modes. We do support the high speed DDR
* modes up to 52MHz. * modes up to 52MHz.
*
* Disable bounce buffers for max_segs = 1
*/ */
mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
MMC_CAP_ERASE | MMC_CAP_CMD23 | MMC_CAP_POWER_OFF_CARD | MMC_CAP_ERASE | MMC_CAP_CMD23 | MMC_CAP_POWER_OFF_CARD |
MMC_CAP_3_3V_DDR; MMC_CAP_3_3V_DDR | MMC_CAP_NO_BOUNCE_BUFF;
if (host->use_sg) if (host->use_sg)
mmc->max_segs = 16; mmc->max_segs = 16;
......
...@@ -157,8 +157,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing) ...@@ -157,8 +157,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
* HOLD register should be bypassed in case there is no phase shift * HOLD register should be bypassed in case there is no phase shift
* applied on CMD/DATA that is sent to the card. * applied on CMD/DATA that is sent to the card.
*/ */
if (!SDMMC_CLKSEL_GET_DRV_WD3(clksel) && host->cur_slot) if (!SDMMC_CLKSEL_GET_DRV_WD3(clksel) && host->slot)
set_bit(DW_MMC_CARD_NO_USE_HOLD, &host->cur_slot->flags); set_bit(DW_MMC_CARD_NO_USE_HOLD, &host->slot->flags);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
...@@ -25,6 +25,7 @@ struct dw_mci_rockchip_priv_data { ...@@ -25,6 +25,7 @@ struct dw_mci_rockchip_priv_data {
struct clk *drv_clk; struct clk *drv_clk;
struct clk *sample_clk; struct clk *sample_clk;
int default_sample_phase; int default_sample_phase;
int num_phases;
}; };
static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios) static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
...@@ -133,8 +134,8 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios) ...@@ -133,8 +134,8 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
} }
} }
#define NUM_PHASES 360 #define TUNING_ITERATION_TO_PHASE(i, num_phases) \
#define TUNING_ITERATION_TO_PHASE(i) (DIV_ROUND_UP((i) * 360, NUM_PHASES)) (DIV_ROUND_UP((i) * 360, num_phases))
static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode) static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
{ {
...@@ -159,13 +160,15 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode) ...@@ -159,13 +160,15 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
return -EIO; return -EIO;
} }
ranges = kmalloc_array(NUM_PHASES / 2 + 1, sizeof(*ranges), GFP_KERNEL); ranges = kmalloc_array(priv->num_phases / 2 + 1,
sizeof(*ranges), GFP_KERNEL);
if (!ranges) if (!ranges)
return -ENOMEM; return -ENOMEM;
/* Try each phase and extract good ranges */ /* Try each phase and extract good ranges */
for (i = 0; i < NUM_PHASES; ) { for (i = 0; i < priv->num_phases; ) {
clk_set_phase(priv->sample_clk, TUNING_ITERATION_TO_PHASE(i)); clk_set_phase(priv->sample_clk,
TUNING_ITERATION_TO_PHASE(i, priv->num_phases));
v = !mmc_send_tuning(mmc, opcode, NULL); v = !mmc_send_tuning(mmc, opcode, NULL);
...@@ -179,7 +182,7 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode) ...@@ -179,7 +182,7 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
if (v) { if (v) {
ranges[range_count-1].end = i; ranges[range_count-1].end = i;
i++; i++;
} else if (i == NUM_PHASES - 1) { } else if (i == priv->num_phases - 1) {
/* No extra skipping rules if we're at the end */ /* No extra skipping rules if we're at the end */
i++; i++;
} else { } else {
...@@ -188,11 +191,11 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode) ...@@ -188,11 +191,11 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
* one since testing bad phases is slow. Skip * one since testing bad phases is slow. Skip
* 20 degrees. * 20 degrees.
*/ */
i += DIV_ROUND_UP(20 * NUM_PHASES, 360); i += DIV_ROUND_UP(20 * priv->num_phases, 360);
/* Always test the last one */ /* Always test the last one */
if (i >= NUM_PHASES) if (i >= priv->num_phases)
i = NUM_PHASES - 1; i = priv->num_phases - 1;
} }
prev_v = v; prev_v = v;
...@@ -210,7 +213,7 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode) ...@@ -210,7 +213,7 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
range_count--; range_count--;
} }
if (ranges[0].start == 0 && ranges[0].end == NUM_PHASES - 1) { if (ranges[0].start == 0 && ranges[0].end == priv->num_phases - 1) {
clk_set_phase(priv->sample_clk, priv->default_sample_phase); clk_set_phase(priv->sample_clk, priv->default_sample_phase);
dev_info(host->dev, "All phases work, using default phase %d.", dev_info(host->dev, "All phases work, using default phase %d.",
priv->default_sample_phase); priv->default_sample_phase);
...@@ -222,7 +225,7 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode) ...@@ -222,7 +225,7 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
int len = (ranges[i].end - ranges[i].start + 1); int len = (ranges[i].end - ranges[i].start + 1);
if (len < 0) if (len < 0)
len += NUM_PHASES; len += priv->num_phases;
if (longest_range_len < len) { if (longest_range_len < len) {
longest_range_len = len; longest_range_len = len;
...@@ -230,25 +233,30 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode) ...@@ -230,25 +233,30 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
} }
dev_dbg(host->dev, "Good phase range %d-%d (%d len)\n", dev_dbg(host->dev, "Good phase range %d-%d (%d len)\n",
TUNING_ITERATION_TO_PHASE(ranges[i].start), TUNING_ITERATION_TO_PHASE(ranges[i].start,
TUNING_ITERATION_TO_PHASE(ranges[i].end), priv->num_phases),
TUNING_ITERATION_TO_PHASE(ranges[i].end,
priv->num_phases),
len len
); );
} }
dev_dbg(host->dev, "Best phase range %d-%d (%d len)\n", dev_dbg(host->dev, "Best phase range %d-%d (%d len)\n",
TUNING_ITERATION_TO_PHASE(ranges[longest_range].start), TUNING_ITERATION_TO_PHASE(ranges[longest_range].start,
TUNING_ITERATION_TO_PHASE(ranges[longest_range].end), priv->num_phases),
TUNING_ITERATION_TO_PHASE(ranges[longest_range].end,
priv->num_phases),
longest_range_len longest_range_len
); );
middle_phase = ranges[longest_range].start + longest_range_len / 2; middle_phase = ranges[longest_range].start + longest_range_len / 2;
middle_phase %= NUM_PHASES; middle_phase %= priv->num_phases;
dev_info(host->dev, "Successfully tuned phase to %d\n", dev_info(host->dev, "Successfully tuned phase to %d\n",
TUNING_ITERATION_TO_PHASE(middle_phase)); TUNING_ITERATION_TO_PHASE(middle_phase, priv->num_phases));
clk_set_phase(priv->sample_clk, clk_set_phase(priv->sample_clk,
TUNING_ITERATION_TO_PHASE(middle_phase)); TUNING_ITERATION_TO_PHASE(middle_phase,
priv->num_phases));
free: free:
kfree(ranges); kfree(ranges);
...@@ -264,6 +272,10 @@ static int dw_mci_rk3288_parse_dt(struct dw_mci *host) ...@@ -264,6 +272,10 @@ static int dw_mci_rk3288_parse_dt(struct dw_mci *host)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
if (of_property_read_u32(np, "rockchip,desired-num-phases",
&priv->num_phases))
priv->num_phases = 360;
if (of_property_read_u32(np, "rockchip,default-sample-phase", if (of_property_read_u32(np, "rockchip,default-sample-phase",
&priv->default_sample_phase)) &priv->default_sample_phase))
priv->default_sample_phase = 0; priv->default_sample_phase = 0;
......
This diff is collapsed.
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#include <linux/reset.h> #include <linux/reset.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#define MAX_MCI_SLOTS 2
enum dw_mci_state { enum dw_mci_state {
STATE_IDLE = 0, STATE_IDLE = 0,
STATE_SENDING_CMD, STATE_SENDING_CMD,
...@@ -134,7 +132,6 @@ struct dw_mci_dma_slave { ...@@ -134,7 +132,6 @@ struct dw_mci_dma_slave {
* ======= * =======
* *
* @lock is a softirq-safe spinlock protecting @queue as well as * @lock is a softirq-safe spinlock protecting @queue as well as
* @cur_slot, @mrq and @state. These must always be updated
* at the same time while holding @lock. * at the same time while holding @lock.
* *
* @irq_lock is an irq-safe spinlock protecting the INTMASK register * @irq_lock is an irq-safe spinlock protecting the INTMASK register
...@@ -170,7 +167,6 @@ struct dw_mci { ...@@ -170,7 +167,6 @@ struct dw_mci {
struct scatterlist *sg; struct scatterlist *sg;
struct sg_mapping_iter sg_miter; struct sg_mapping_iter sg_miter;
struct dw_mci_slot *cur_slot;
struct mmc_request *mrq; struct mmc_request *mrq;
struct mmc_command *cmd; struct mmc_command *cmd;
struct mmc_data *data; struct mmc_data *data;
...@@ -206,7 +202,6 @@ struct dw_mci { ...@@ -206,7 +202,6 @@ struct dw_mci {
u32 bus_hz; u32 bus_hz;
u32 current_speed; u32 current_speed;
u32 num_slots;
u32 fifoth_val; u32 fifoth_val;
u16 verid; u16 verid;
struct device *dev; struct device *dev;
...@@ -215,7 +210,7 @@ struct dw_mci { ...@@ -215,7 +210,7 @@ struct dw_mci {
void *priv; void *priv;
struct clk *biu_clk; struct clk *biu_clk;
struct clk *ciu_clk; struct clk *ciu_clk;
struct dw_mci_slot *slot[MAX_MCI_SLOTS]; struct dw_mci_slot *slot;
/* FIFO push and pull */ /* FIFO push and pull */
int fifo_depth; int fifo_depth;
......
...@@ -1774,7 +1774,7 @@ static int msdc_drv_remove(struct platform_device *pdev) ...@@ -1774,7 +1774,7 @@ static int msdc_drv_remove(struct platform_device *pdev)
pm_runtime_disable(host->dev); pm_runtime_disable(host->dev);
pm_runtime_put_noidle(host->dev); pm_runtime_put_noidle(host->dev);
dma_free_coherent(&pdev->dev, dma_free_coherent(&pdev->dev,
sizeof(struct mt_gpdma_desc), 2 * sizeof(struct mt_gpdma_desc),
host->dma.gpd, host->dma.gpd_addr); host->dma.gpd, host->dma.gpd_addr);
dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct mt_bdma_desc), dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct mt_bdma_desc),
host->dma.bd, host->dma.bd_addr); host->dma.bd, host->dma.bd_addr);
......
...@@ -250,14 +250,14 @@ static int omap_hsmmc_enable_supply(struct mmc_host *mmc) ...@@ -250,14 +250,14 @@ static int omap_hsmmc_enable_supply(struct mmc_host *mmc)
struct omap_hsmmc_host *host = mmc_priv(mmc); struct omap_hsmmc_host *host = mmc_priv(mmc);
struct mmc_ios *ios = &mmc->ios; struct mmc_ios *ios = &mmc->ios;
if (mmc->supply.vmmc) { if (!IS_ERR(mmc->supply.vmmc)) {
ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
if (ret) if (ret)
return ret; return ret;
} }
/* Enable interface voltage rail, if needed */ /* Enable interface voltage rail, if needed */
if (mmc->supply.vqmmc && !host->vqmmc_enabled) { if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) {
ret = regulator_enable(mmc->supply.vqmmc); ret = regulator_enable(mmc->supply.vqmmc);
if (ret) { if (ret) {
dev_err(mmc_dev(mmc), "vmmc_aux reg enable failed\n"); dev_err(mmc_dev(mmc), "vmmc_aux reg enable failed\n");
...@@ -269,7 +269,7 @@ static int omap_hsmmc_enable_supply(struct mmc_host *mmc) ...@@ -269,7 +269,7 @@ static int omap_hsmmc_enable_supply(struct mmc_host *mmc)
return 0; return 0;
err_vqmmc: err_vqmmc:
if (mmc->supply.vmmc) if (!IS_ERR(mmc->supply.vmmc))
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
return ret; return ret;
...@@ -281,7 +281,7 @@ static int omap_hsmmc_disable_supply(struct mmc_host *mmc) ...@@ -281,7 +281,7 @@ static int omap_hsmmc_disable_supply(struct mmc_host *mmc)
int status; int status;
struct omap_hsmmc_host *host = mmc_priv(mmc); struct omap_hsmmc_host *host = mmc_priv(mmc);
if (mmc->supply.vqmmc && host->vqmmc_enabled) { if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) {
ret = regulator_disable(mmc->supply.vqmmc); ret = regulator_disable(mmc->supply.vqmmc);
if (ret) { if (ret) {
dev_err(mmc_dev(mmc), "vmmc_aux reg disable failed\n"); dev_err(mmc_dev(mmc), "vmmc_aux reg disable failed\n");
...@@ -290,7 +290,7 @@ static int omap_hsmmc_disable_supply(struct mmc_host *mmc) ...@@ -290,7 +290,7 @@ static int omap_hsmmc_disable_supply(struct mmc_host *mmc)
host->vqmmc_enabled = 0; host->vqmmc_enabled = 0;
} }
if (mmc->supply.vmmc) { if (!IS_ERR(mmc->supply.vmmc)) {
ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
if (ret) if (ret)
goto err_set_ocr; goto err_set_ocr;
...@@ -299,7 +299,7 @@ static int omap_hsmmc_disable_supply(struct mmc_host *mmc) ...@@ -299,7 +299,7 @@ static int omap_hsmmc_disable_supply(struct mmc_host *mmc)
return 0; return 0;
err_set_ocr: err_set_ocr:
if (mmc->supply.vqmmc) { if (!IS_ERR(mmc->supply.vqmmc)) {
status = regulator_enable(mmc->supply.vqmmc); status = regulator_enable(mmc->supply.vqmmc);
if (status) if (status)
dev_err(mmc_dev(mmc), "vmmc_aux re-enable failed\n"); dev_err(mmc_dev(mmc), "vmmc_aux re-enable failed\n");
...@@ -313,7 +313,7 @@ static int omap_hsmmc_set_pbias(struct omap_hsmmc_host *host, bool power_on, ...@@ -313,7 +313,7 @@ static int omap_hsmmc_set_pbias(struct omap_hsmmc_host *host, bool power_on,
{ {
int ret; int ret;
if (!host->pbias) if (IS_ERR(host->pbias))
return 0; return 0;
if (power_on) { if (power_on) {
...@@ -363,7 +363,7 @@ static int omap_hsmmc_set_power(struct omap_hsmmc_host *host, int power_on, ...@@ -363,7 +363,7 @@ static int omap_hsmmc_set_power(struct omap_hsmmc_host *host, int power_on,
* If we don't see a Vcc regulator, assume it's a fixed * If we don't see a Vcc regulator, assume it's a fixed
* voltage always-on regulator. * voltage always-on regulator.
*/ */
if (!mmc->supply.vmmc) if (IS_ERR(mmc->supply.vmmc))
return 0; return 0;
if (mmc_pdata(host)->before_set_reg) if (mmc_pdata(host)->before_set_reg)
...@@ -415,7 +415,7 @@ static int omap_hsmmc_disable_boot_regulator(struct regulator *reg) ...@@ -415,7 +415,7 @@ static int omap_hsmmc_disable_boot_regulator(struct regulator *reg)
{ {
int ret; int ret;
if (!reg) if (IS_ERR(reg))
return 0; return 0;
if (regulator_is_enabled(reg)) { if (regulator_is_enabled(reg)) {
...@@ -466,36 +466,27 @@ static int omap_hsmmc_disable_boot_regulators(struct omap_hsmmc_host *host) ...@@ -466,36 +466,27 @@ static int omap_hsmmc_disable_boot_regulators(struct omap_hsmmc_host *host)
static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
{ {
int ocr_value = 0;
int ret; int ret;
struct mmc_host *mmc = host->mmc; struct mmc_host *mmc = host->mmc;
if (mmc_pdata(host)->set_power) if (mmc_pdata(host)->set_power)
return 0; return 0;
mmc->supply.vmmc = devm_regulator_get_optional(host->dev, "vmmc"); ret = mmc_regulator_get_supply(mmc);
if (IS_ERR(mmc->supply.vmmc)) { if (ret == -EPROBE_DEFER)
ret = PTR_ERR(mmc->supply.vmmc);
if ((ret != -ENODEV) && host->dev->of_node)
return ret; return ret;
dev_dbg(host->dev, "unable to get vmmc regulator %ld\n",
PTR_ERR(mmc->supply.vmmc));
mmc->supply.vmmc = NULL;
} else {
ocr_value = mmc_regulator_get_ocrmask(mmc->supply.vmmc);
if (ocr_value > 0)
mmc_pdata(host)->ocr_mask = ocr_value;
}
/* Allow an aux regulator */ /* Allow an aux regulator */
mmc->supply.vqmmc = devm_regulator_get_optional(host->dev, "vmmc_aux"); if (IS_ERR(mmc->supply.vqmmc)) {
mmc->supply.vqmmc = devm_regulator_get_optional(host->dev,
"vmmc_aux");
if (IS_ERR(mmc->supply.vqmmc)) { if (IS_ERR(mmc->supply.vqmmc)) {
ret = PTR_ERR(mmc->supply.vqmmc); ret = PTR_ERR(mmc->supply.vqmmc);
if ((ret != -ENODEV) && host->dev->of_node) if ((ret != -ENODEV) && host->dev->of_node)
return ret; return ret;
dev_dbg(host->dev, "unable to get vmmc_aux regulator %ld\n", dev_dbg(host->dev, "unable to get vmmc_aux regulator %ld\n",
PTR_ERR(mmc->supply.vqmmc)); PTR_ERR(mmc->supply.vqmmc));
mmc->supply.vqmmc = NULL; }
} }
host->pbias = devm_regulator_get_optional(host->dev, "pbias"); host->pbias = devm_regulator_get_optional(host->dev, "pbias");
...@@ -508,7 +499,6 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) ...@@ -508,7 +499,6 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
} }
dev_dbg(host->dev, "unable to get pbias regulator %ld\n", dev_dbg(host->dev, "unable to get pbias regulator %ld\n",
PTR_ERR(host->pbias)); PTR_ERR(host->pbias));
host->pbias = NULL;
} }
/* For eMMC do not power off when not in sleep state */ /* For eMMC do not power off when not in sleep state */
...@@ -2146,6 +2136,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) ...@@ -2146,6 +2136,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
if (ret) if (ret)
goto err_irq; goto err_irq;
if (!mmc->ocr_avail)
mmc->ocr_avail = mmc_pdata(host)->ocr_mask; mmc->ocr_avail = mmc_pdata(host)->ocr_mask;
omap_hsmmc_disable_irq(host); omap_hsmmc_disable_irq(host);
......
...@@ -702,7 +702,11 @@ static int pxamci_probe(struct platform_device *pdev) ...@@ -702,7 +702,11 @@ static int pxamci_probe(struct platform_device *pdev)
pxamci_init_ocr(host); pxamci_init_ocr(host);
mmc->caps = 0; /*
* This architecture used to disable bounce buffers through its
* defconfig, now it is done at runtime as a host property.
*/
mmc->caps = MMC_CAP_NO_BOUNCE_BUFF;
host->cmdat = 0; host->cmdat = 0;
if (!cpu_is_pxa25x()) { if (!cpu_is_pxa25x()) {
mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
......
/*
* Renesas Mobile SDHI
*
* Copyright (C) 2017 Horms Solutions Ltd., Simon Horman
* Copyright (C) 2017 Renesas Electronics Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef RENESAS_SDHI_H
#define RENESAS_SDHI_H
#include <linux/platform_device.h>
#include "tmio_mmc.h"
struct renesas_sdhi_scc {
unsigned long clk_rate; /* clock rate for SDR104 */
u32 tap; /* sampling clock position for SDR104 */
};
struct renesas_sdhi_of_data {
unsigned long tmio_flags;
u32 tmio_ocr_mask;
unsigned long capabilities;
unsigned long capabilities2;
enum dma_slave_buswidth dma_buswidth;
dma_addr_t dma_rx_offset;
unsigned int bus_shift;
int scc_offset;
struct renesas_sdhi_scc *taps;
int taps_num;
};
int renesas_sdhi_probe(struct platform_device *pdev,
const struct tmio_mmc_dma_ops *dma_ops);
int renesas_sdhi_remove(struct platform_device *pdev);
#endif
...@@ -274,7 +274,6 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = { ...@@ -274,7 +274,6 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
.caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR | MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |
MMC_CAP_CMD_DURING_TFR | MMC_CAP_WAIT_WHILE_BUSY, MMC_CAP_CMD_DURING_TFR | MMC_CAP_WAIT_WHILE_BUSY,
.caps2 = MMC_CAP2_HC_ERASE_SZ,
.flags = SDHCI_ACPI_RUNTIME_PM, .flags = SDHCI_ACPI_RUNTIME_PM,
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
...@@ -396,9 +395,6 @@ static int sdhci_acpi_probe(struct platform_device *pdev) ...@@ -396,9 +395,6 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
if (child->status.present && child->status.enabled) if (child->status.present && child->status.enabled)
acpi_device_fix_up_power(child); acpi_device_fix_up_power(child);
if (acpi_bus_get_status(device) || !device->status.present)
return -ENODEV;
if (sdhci_acpi_byt_defer(dev)) if (sdhci_acpi_byt_defer(dev))
return -EPROBE_DEFER; return -EPROBE_DEFER;
......
...@@ -89,9 +89,6 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) ...@@ -89,9 +89,6 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
goto err_clk; goto err_clk;
} }
/* Enable MMC_CAP2_HC_ERASE_SZ for better max discard calculations */
host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ;
sdhci_get_of_property(pdev); sdhci_get_of_property(pdev);
mmc_of_parse(host->mmc); mmc_of_parse(host->mmc);
......
This diff is collapsed.
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*/ */
#define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \ #define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
SDHCI_QUIRK_32BIT_DMA_ADDR | \
SDHCI_QUIRK_NO_BUSY_IRQ | \ SDHCI_QUIRK_NO_BUSY_IRQ | \
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
SDHCI_QUIRK_PIO_NEEDS_DELAY | \ SDHCI_QUIRK_PIO_NEEDS_DELAY | \
......
...@@ -638,7 +638,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev) ...@@ -638,7 +638,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
ret = mmc_of_parse(host->mmc); ret = mmc_of_parse(host->mmc);
if (ret) { if (ret) {
dev_err(&pdev->dev, "parsing dt failed (%u)\n", ret); dev_err(&pdev->dev, "parsing dt failed (%d)\n", ret);
goto unreg_clk; goto unreg_clk;
} }
......
This diff is collapsed.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#define __SDHCI_PCI_H #define __SDHCI_PCI_H
/* /*
* PCI device IDs * PCI device IDs, sub IDs
*/ */
#define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 #define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809
...@@ -37,6 +37,50 @@ ...@@ -37,6 +37,50 @@
#define PCI_DEVICE_ID_INTEL_GLK_SD 0x31ca #define PCI_DEVICE_ID_INTEL_GLK_SD 0x31ca
#define PCI_DEVICE_ID_INTEL_GLK_EMMC 0x31cc #define PCI_DEVICE_ID_INTEL_GLK_EMMC 0x31cc
#define PCI_DEVICE_ID_INTEL_GLK_SDIO 0x31d0 #define PCI_DEVICE_ID_INTEL_GLK_SDIO 0x31d0
#define PCI_DEVICE_ID_INTEL_CNP_EMMC 0x9dc4
#define PCI_DEVICE_ID_INTEL_CNP_SD 0x9df5
#define PCI_DEVICE_ID_INTEL_CNPH_SD 0xa375
#define PCI_DEVICE_ID_SYSKONNECT_8000 0x8000
#define PCI_DEVICE_ID_VIA_95D0 0x95d0
#define PCI_DEVICE_ID_REALTEK_5250 0x5250
#define PCI_SUBDEVICE_ID_NI_7884 0x7884
/*
* PCI device class and mask
*/
#define SYSTEM_SDHCI (PCI_CLASS_SYSTEM_SDHCI << 8)
#define PCI_CLASS_MASK 0xFFFF00
/*
* Macros for PCI device-description
*/
#define _PCI_VEND(vend) PCI_VENDOR_ID_##vend
#define _PCI_DEV(vend, dev) PCI_DEVICE_ID_##vend##_##dev
#define _PCI_SUBDEV(subvend, subdev) PCI_SUBDEVICE_ID_##subvend##_##subdev
#define SDHCI_PCI_DEVICE(vend, dev, cfg) { \
.vendor = _PCI_VEND(vend), .device = _PCI_DEV(vend, dev), \
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, \
.driver_data = (kernel_ulong_t)&(sdhci_##cfg) \
}
#define SDHCI_PCI_SUBDEVICE(vend, dev, subvend, subdev, cfg) { \
.vendor = _PCI_VEND(vend), .device = _PCI_DEV(vend, dev), \
.subvendor = _PCI_VEND(subvend), \
.subdevice = _PCI_SUBDEV(subvend, subdev), \
.driver_data = (kernel_ulong_t)&(sdhci_##cfg) \
}
#define SDHCI_PCI_DEVICE_CLASS(vend, cl, cl_msk, cfg) { \
.vendor = _PCI_VEND(vend), .device = PCI_ANY_ID, \
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, \
.class = (cl), .class_mask = (cl_msk), \
.driver_data = (kernel_ulong_t)&(sdhci_##cfg) \
}
/* /*
* PCI registers * PCI registers
......
...@@ -256,9 +256,6 @@ static int sdricoh_blockio(struct sdricoh_host *host, int read, ...@@ -256,9 +256,6 @@ static int sdricoh_blockio(struct sdricoh_host *host, int read,
} }
} }
if (len)
return -EIO;
return 0; return 0;
} }
......
/* /*
* linux/drivers/mmc/host/tmio_mmc.c * Driver for the MMC / SD / SDIO cell found in:
*
* TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
* *
* Copyright (C) 2017 Renesas Electronics Corporation
* Copyright (C) 2017 Horms Solutions, Simon Horman
* Copyright (C) 2007 Ian Molton * Copyright (C) 2007 Ian Molton
* Copyright (C) 2004 Ian Molton * Copyright (C) 2004 Ian Molton
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*
* Driver for the MMC / SD / SDIO cell found in:
*
* TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
*/ */
#include <linux/device.h> #include <linux/device.h>
...@@ -99,7 +99,7 @@ static int tmio_mmc_probe(struct platform_device *pdev) ...@@ -99,7 +99,7 @@ static int tmio_mmc_probe(struct platform_device *pdev)
/* SD control register space size is 0x200, 0x400 for bus_shift=1 */ /* SD control register space size is 0x200, 0x400 for bus_shift=1 */
host->bus_shift = resource_size(res) >> 10; host->bus_shift = resource_size(res) >> 10;
ret = tmio_mmc_host_probe(host, pdata); ret = tmio_mmc_host_probe(host, pdata, NULL);
if (ret) if (ret)
goto host_free; goto host_free;
...@@ -132,6 +132,7 @@ static int tmio_mmc_remove(struct platform_device *pdev) ...@@ -132,6 +132,7 @@ static int tmio_mmc_remove(struct platform_device *pdev)
if (mmc) { if (mmc) {
struct tmio_mmc_host *host = mmc_priv(mmc); struct tmio_mmc_host *host = mmc_priv(mmc);
tmio_mmc_host_remove(host); tmio_mmc_host_remove(host);
if (cell->disable) if (cell->disable)
cell->disable(pdev); cell->disable(pdev);
...@@ -145,8 +146,7 @@ static int tmio_mmc_remove(struct platform_device *pdev) ...@@ -145,8 +146,7 @@ static int tmio_mmc_remove(struct platform_device *pdev)
static const struct dev_pm_ops tmio_mmc_dev_pm_ops = { static const struct dev_pm_ops tmio_mmc_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(tmio_mmc_suspend, tmio_mmc_resume) SET_SYSTEM_SLEEP_PM_OPS(tmio_mmc_suspend, tmio_mmc_resume)
SET_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend, SET_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend,
tmio_mmc_host_runtime_resume, tmio_mmc_host_runtime_resume, NULL)
NULL)
}; };
static struct platform_driver tmio_mmc_driver = { static struct platform_driver tmio_mmc_driver = {
......
This diff is collapsed.
...@@ -2107,7 +2107,8 @@ static int vub300_probe(struct usb_interface *interface, ...@@ -2107,7 +2107,8 @@ static int vub300_probe(struct usb_interface *interface,
usb_string(udev, udev->descriptor.iSerialNumber, serial_number, usb_string(udev, udev->descriptor.iSerialNumber, serial_number,
sizeof(serial_number)); sizeof(serial_number));
dev_info(&udev->dev, "probing VID:PID(%04X:%04X) %s %s %s\n", dev_info(&udev->dev, "probing VID:PID(%04X:%04X) %s %s %s\n",
udev->descriptor.idVendor, udev->descriptor.idProduct, le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct),
manufacturer, product, serial_number); manufacturer, product, serial_number);
command_out_urb = usb_alloc_urb(0, GFP_KERNEL); command_out_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!command_out_urb) { if (!command_out_urb) {
......
This diff is collapsed.
...@@ -305,9 +305,7 @@ struct mmc_card { ...@@ -305,9 +305,7 @@ struct mmc_card {
struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */ struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
unsigned int nr_parts; unsigned int nr_parts;
struct mmc_queue_req *mqrq; /* Shared queue structure */
unsigned int bouncesz; /* Bounce buffer size */ unsigned int bouncesz; /* Bounce buffer size */
int qdepth; /* Shared queue depth */
}; };
static inline bool mmc_large_sector(struct mmc_card *card) static inline bool mmc_large_sector(struct mmc_card *card)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment