MMC core:

- Convert drivers to use the ->remove_new() callback
  - Propagate the removable attribute for the card's device
 
 MMC host:
  - Convert drivers to use the ->remove_new() callback
  - atmel-mci: Convert to gpio descriptors and cleanup the code
  - davinci: Make SDIO irq truly optional
  - renesas_sdhi: Register irqs before registering controller
  - sdhci: Simplify the sdhci_pltfm_* interface a bit
  - sdhci-esdhc-imx: Improve support for the 1.8V errata
  - sdhci-of-at91: Add support for the microchip sam9x7 variant
  - sdhci-of-dwcmshc: Add support for runtime PM
  - sdhci-pci-o2micro: Add support for the new Bayhub GG8 variant
  - sdhci-sprd: Add support for SD high-speed mode tuning
  - uniphier-sd: Register irqs before registering controller
 -----BEGIN PGP SIGNATURE-----
 
 iQJLBAABCgA1FiEEugLDXPmKSktSkQsV/iaEJXNYjCkFAmTsjhEXHHVsZi5oYW5z
 c29uQGxpbmFyby5vcmcACgkQ/iaEJXNYjClEFw/+M+3T0mb5NEgEyq6++Jz/erSQ
 jMMy1y+ESRspVtQRh5tvPRH2PtJG1pK8vAkm8RD1ghYG5ST3qhpfPfadB5nAxm5v
 bEbfrYZFUabsTQ/xBR9RScHFEYqNvNx8mzPPJqLgYQcXZe2Xh1xAtMZhqCSsMHWb
 j8jBJyPtKWEUasLeFf5ZTcCpsvDe3ekLmqOkFa/E8YekCQHLzFRGQ+6nHZ8WRLQ8
 hCs49+Pe8rTgJccDxjvm0k3CY5wejAfCOCrvca59Fp3s/Nu5jSEpuJaVTJsBLKmx
 7RuaJkKfy/CgleC28fkmMBWUid+CdrKvQmGwelsECLFU7jVc9sqaPA9g8Bn8rQtK
 MtpcY9FzT94RJvIUPQmoIUgDWod30hCqgFhVorwTUr/2RknW9l1qqcKyKCDGkmyA
 2fprMP6xizTOVQr5mioe5TojICpTWOKrvQQc+4HoF4YTK7s6gTAeeV2ahUoA4wnQ
 b/OTGU9AzcsUSPZL0UTvlbzhz2g3ng2/PLOEQ+YeibV8XI5gTmVSRdaHnxGlYVVv
 LDgVu7TLnlpknPAb5Jun6P5RI7zf7mjy7No3TEaYmVtjQuRkpt5PKesJQtp5SwNa
 dyFX2RGzsz2e3v5e34UNASLas9qfG8zFkZcLBa+EvvefJBhjK7K5a8oB1sAyl9bc
 zPn+gbGCDvJT3Qg+k1Q=
 =ktYf
 -----END PGP SIGNATURE-----

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

Pull MMC updates from Ulf Hansson:
 "MMC core:
   - Convert drivers to use the ->remove_new() callback
   - Propagate the removable attribute for the card's device

  MMC host:
   - Convert drivers to use the ->remove_new() callback
   - atmel-mci: Convert to gpio descriptors and cleanup the code
   - davinci: Make SDIO irq truly optional
   - renesas_sdhi: Register irqs before registering controller
   - sdhci: Simplify the sdhci_pltfm_* interface a bit
   - sdhci-esdhc-imx: Improve support for the 1.8V errata
   - sdhci-of-at91: Add support for the microchip sam9x7 variant
   - sdhci-of-dwcmshc: Add support for runtime PM
   - sdhci-pci-o2micro: Add support for the new Bayhub GG8 variant
   - sdhci-sprd: Add support for SD high-speed mode tuning
   - uniphier-sd: Register irqs before registering controller"

* tag 'mmc-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (108 commits)
  mmc: atmel-mci: Move card detect gpio polarity quirk to gpiolib
  mmc: atmel-mci: move atmel MCI header file
  mmc: atmel-mci: Convert to gpio descriptors
  mmc: sdhci-sprd: Add SD HS mode online tuning
  mmc: core: Add host specific tuning support for SD HS mode
  mmc: sdhci-of-dwcmshc: Add runtime PM operations
  mmc: sdhci-of-dwcmshc: Add error handling in dwcmshc_resume
  mmc: sdhci-esdhc-imx: improve ESDHC_FLAG_ERR010450
  mmc: sdhci-pltfm: Rename sdhci_pltfm_register()
  mmc: sdhci-pltfm: Remove sdhci_pltfm_unregister()
  mmc: sdhci-st: Use sdhci_pltfm_remove()
  mmc: sdhci-pxav2: Use sdhci_pltfm_remove()
  mmc: sdhci-of-sparx5: Use sdhci_pltfm_remove()
  mmc: sdhci-of-hlwd: Use sdhci_pltfm_remove()
  mmc: sdhci-of-esdhc: Use sdhci_pltfm_remove()
  mmc: sdhci-of-at91: Use sdhci_pltfm_remove()
  mmc: sdhci-of-arasan: Use sdhci_pltfm_remove()
  mmc: sdhci-iproc: Use sdhci_pltfm_remove()
  mmc: sdhci_f_sdh30: Use sdhci_pltfm_remove()
  mmc: sdhci-dove: Use sdhci_pltfm_remove()
  ...
This commit is contained in:
Linus Torvalds 2023-08-29 09:56:24 -07:00
commit 995cda6210
90 changed files with 814 additions and 577 deletions

View file

@ -160,6 +160,12 @@ properties:
description:
The MIO bank number in which the command and data lines are configured.
iommus:
maxItems: 1
power-domains:
maxItems: 1
dependencies:
'#clock-cells': [ clock-output-names ]

View file

@ -269,7 +269,7 @@ properties:
post-power-on-delay-ms:
description:
It was invented for MMC pwrseq-simple which could be referred to
mmc-pwrseq-simple.txt. But now it\'s reused as a tunable delay
mmc-pwrseq-simple.yaml. But now it\'s reused as a tunable delay
waiting for I/O signalling and card power supply to be stable,
regardless of whether pwrseq-simple is used. Default to 10ms if
no available.

View file

@ -91,16 +91,6 @@ properties:
should switch dat1 pin to GPIO mode.
maxItems: 1
assigned-clocks:
description:
PLL of the source clock.
maxItems: 1
assigned-clock-parents:
description:
parent of source clock, used for HS400 mode to get 400Mhz source clock.
maxItems: 1
hs400-ds-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:

View file

@ -5,11 +5,13 @@ Documentation/devicetree/bindings/mmc/mmc.txt and the properties used by the
sdhci-of-at91 driver.
Required properties:
- compatible: Must be "atmel,sama5d2-sdhci" or "microchip,sam9x60-sdhci".
- compatible: Must be "atmel,sama5d2-sdhci" or "microchip,sam9x60-sdhci"
or "microchip,sam9x7-sdhci", "microchip,sam9x60-sdhci".
- clocks: Phandlers to the clocks.
- clock-names: Must be "hclock", "multclk", "baseclk" for
"atmel,sama5d2-sdhci".
Must be "hclock", "multclk" for "microchip,sam9x60-sdhci".
Must be "hclock", "multclk" for "microchip,sam9x7-sdhci".
Optional properties:
- assigned-clocks: The same with "multclk".

View file

@ -209,6 +209,8 @@ static void of_gpio_set_polarity_by_property(const struct device_node *np,
const char *propname,
enum of_gpio_flags *flags)
{
const struct device_node *np_compat = np;
const struct device_node *np_propname = np;
static const struct {
const char *compatible;
const char *gpio_propname;
@ -252,15 +254,29 @@ static void of_gpio_set_polarity_by_property(const struct device_node *np,
#if IS_ENABLED(CONFIG_REGULATOR_GPIO)
{ "regulator-gpio", "enable-gpio", "enable-active-high" },
{ "regulator-gpio", "enable-gpios", "enable-active-high" },
#endif
#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
{ "atmel,hsmci", "cd-gpios", "cd-inverted" },
#endif
};
unsigned int i;
bool active_high;
#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
/*
* The Atmel HSMCI has compatible property in the parent node and
* gpio property in a child node
*/
if (of_device_is_compatible(np->parent, "atmel,hsmci")) {
np_compat = np->parent;
np_propname = np;
}
#endif
for (i = 0; i < ARRAY_SIZE(gpios); i++) {
if (of_device_is_compatible(np, gpios[i].compatible) &&
if (of_device_is_compatible(np_compat, gpios[i].compatible) &&
!strcmp(propname, gpios[i].gpio_propname)) {
active_high = of_property_read_bool(np,
active_high = of_property_read_bool(np_propname,
gpios[i].polarity_propname);
of_gpio_quirk_polarity(np, active_high, flags);
break;

View file

@ -918,17 +918,9 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
struct scatterlist sg;
cmd.opcode = MMC_APP_CMD;
cmd.arg = card->rca << 16;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 0);
err = mmc_app_cmd(card->host, card);
if (err)
return err;
if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
return -EIO;
memset(&cmd, 0, sizeof(struct mmc_command));
cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
cmd.arg = 0;
@ -3026,7 +3018,6 @@ static void mmc_blk_remove(struct mmc_card *card)
pm_runtime_disable(&card->dev);
pm_runtime_put_noidle(&card->dev);
mmc_blk_remove_req(md);
dev_set_drvdata(&card->dev, NULL);
destroy_workqueue(card->complete_wq);
}

View file

@ -310,6 +310,9 @@ int mmc_add_card(struct mmc_card *card)
dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);
dev_set_removable(&card->dev,
mmc_card_is_removable(card->host) ?
DEVICE_REMOVABLE : DEVICE_FIXED);
switch (card->type) {
case MMC_TYPE_MMC:

View file

@ -32,7 +32,6 @@ int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode,
u32 args, void *buf, unsigned len);
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_cid(struct mmc_host *host, u32 *cid);
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);

View file

@ -90,14 +90,12 @@ static int mmc_pwrseq_emmc_probe(struct platform_device *pdev)
return mmc_pwrseq_register(&pwrseq->pwrseq);
}
static int mmc_pwrseq_emmc_remove(struct platform_device *pdev)
static void mmc_pwrseq_emmc_remove(struct platform_device *pdev)
{
struct mmc_pwrseq_emmc *pwrseq = platform_get_drvdata(pdev);
unregister_restart_handler(&pwrseq->reset_nb);
mmc_pwrseq_unregister(&pwrseq->pwrseq);
return 0;
}
static const struct of_device_id mmc_pwrseq_emmc_of_match[] = {
@ -109,7 +107,7 @@ MODULE_DEVICE_TABLE(of, mmc_pwrseq_emmc_of_match);
static struct platform_driver mmc_pwrseq_emmc_driver = {
.probe = mmc_pwrseq_emmc_probe,
.remove = mmc_pwrseq_emmc_remove,
.remove_new = mmc_pwrseq_emmc_remove,
.driver = {
.name = "pwrseq_emmc",
.of_match_table = mmc_pwrseq_emmc_of_match,

View file

@ -113,18 +113,16 @@ static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev)
return mmc_pwrseq_register(&pwrseq->pwrseq);
}
static int mmc_pwrseq_sd8787_remove(struct platform_device *pdev)
static void mmc_pwrseq_sd8787_remove(struct platform_device *pdev)
{
struct mmc_pwrseq_sd8787 *pwrseq = platform_get_drvdata(pdev);
mmc_pwrseq_unregister(&pwrseq->pwrseq);
return 0;
}
static struct platform_driver mmc_pwrseq_sd8787_driver = {
.probe = mmc_pwrseq_sd8787_probe,
.remove = mmc_pwrseq_sd8787_remove,
.remove_new = mmc_pwrseq_sd8787_remove,
.driver = {
.name = "pwrseq_sd8787",
.of_match_table = mmc_pwrseq_sd8787_of_match,

View file

@ -142,18 +142,16 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
return mmc_pwrseq_register(&pwrseq->pwrseq);
}
static int mmc_pwrseq_simple_remove(struct platform_device *pdev)
static void mmc_pwrseq_simple_remove(struct platform_device *pdev)
{
struct mmc_pwrseq_simple *pwrseq = platform_get_drvdata(pdev);
mmc_pwrseq_unregister(&pwrseq->pwrseq);
return 0;
}
static struct platform_driver mmc_pwrseq_simple_driver = {
.probe = mmc_pwrseq_simple_probe,
.remove = mmc_pwrseq_simple_remove,
.remove_new = mmc_pwrseq_simple_remove,
.driver = {
.name = "pwrseq_simple",
.of_match_table = mmc_pwrseq_simple_of_match,

View file

@ -1518,6 +1518,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
*/
mmc_set_clock(host, mmc_sd_get_max_clock(card));
if (host->ios.timing == MMC_TIMING_SD_HS &&
host->ops->prepare_sd_hs_tuning) {
err = host->ops->prepare_sd_hs_tuning(host, card);
if (err)
goto free_card;
}
/*
* Switch to wider bus (if supported).
*/
@ -1529,6 +1536,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
}
if (host->ios.timing == MMC_TIMING_SD_HS &&
host->ops->execute_sd_hs_tuning) {
err = host->ops->execute_sd_hs_tuning(host, card);
if (err)
goto free_card;
}
}
cont:
if (!oldcard) {

View file

@ -323,6 +323,7 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group,
return mmc_send_adtc_data(card, card->host, SD_SWITCH, cmd_args, resp,
64);
}
EXPORT_SYMBOL_GPL(mmc_sd_switch);
int mmc_app_sd_status(struct mmc_card *card, void *ssr)
{

View file

@ -19,8 +19,6 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr);
int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr);
int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca);
int mmc_app_send_scr(struct mmc_card *card);
int mmc_sd_switch(struct mmc_card *card, int mode, int group,
u8 value, u8 *resp);
int mmc_app_sd_status(struct mmc_card *card, void *ssr);
int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card);

View file

@ -1125,7 +1125,7 @@ static int alcor_pci_sdmmc_drv_probe(struct platform_device *pdev)
return ret;
}
static int alcor_pci_sdmmc_drv_remove(struct platform_device *pdev)
static void alcor_pci_sdmmc_drv_remove(struct platform_device *pdev)
{
struct alcor_sdmmc_host *host = dev_get_drvdata(&pdev->dev);
struct mmc_host *mmc = mmc_from_priv(host);
@ -1136,8 +1136,6 @@ static int alcor_pci_sdmmc_drv_remove(struct platform_device *pdev)
alcor_hw_uninit(host);
mmc_remove_host(mmc);
mmc_free_host(mmc);
return 0;
}
#ifdef CONFIG_PM_SLEEP
@ -1177,7 +1175,7 @@ MODULE_DEVICE_TABLE(platform, alcor_pci_sdmmc_ids);
static struct platform_driver alcor_pci_sdmmc_driver = {
.probe = alcor_pci_sdmmc_drv_probe,
.remove = alcor_pci_sdmmc_drv_remove,
.remove_new = alcor_pci_sdmmc_drv_remove,
.id_table = alcor_pci_sdmmc_ids,
.driver = {
.name = DRV_NAME_ALCOR_PCI_SDMMC,

View file

@ -11,15 +11,14 @@
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/irq.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/scatterlist.h>
#include <linux/seq_file.h>
@ -30,7 +29,6 @@
#include <linux/mmc/host.h>
#include <linux/mmc/sdio.h>
#include <linux/atmel-mci.h>
#include <linux/atmel_pdc.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
@ -40,6 +38,8 @@
#include <asm/io.h>
#include <asm/unaligned.h>
#define ATMCI_MAX_NR_SLOTS 2
/*
* Superset of MCI IP registers integrated in Atmel AT91 Processor
* Registers and bitfields marked with [2] are only available in MCI2
@ -201,6 +201,40 @@ enum atmci_pdc_buf {
PDC_SECOND_BUF,
};
/**
* struct mci_slot_pdata - board-specific per-slot configuration
* @bus_width: Number of data lines wired up the slot
* @detect_pin: GPIO pin wired to the card detect switch
* @wp_pin: GPIO pin wired to the write protect sensor
* @non_removable: The slot is not removable, only detect once
*
* If a given slot is not present on the board, @bus_width should be
* set to 0. The other fields are ignored in this case.
*
* Any pins that aren't available should be set to a negative value.
*
* Note that support for multiple slots is experimental -- some cards
* might get upset if we don't get the clock management exactly right.
* But in most cases, it should work just fine.
*/
struct mci_slot_pdata {
unsigned int bus_width;
struct gpio_desc *detect_pin;
struct gpio_desc *wp_pin;
bool non_removable;
};
/**
* struct mci_platform_data - board-specific MMC/SDcard configuration
* @dma_slave: DMA slave interface to use in data transfers.
* @slot: Per-slot configuration data.
*/
struct mci_platform_data {
void *dma_slave;
dma_filter_fn dma_filter;
struct mci_slot_pdata slot[ATMCI_MAX_NR_SLOTS];
};
struct atmel_mci_caps {
bool has_dma_conf_reg;
bool has_pdc;
@ -369,7 +403,6 @@ struct atmel_mci {
* available.
* @wp_pin: GPIO pin used for card write protect sending, or negative
* if not available.
* @detect_is_active_high: The state of the detect pin when it is active.
* @detect_timer: Timer used for debouncing @detect_pin interrupts.
*/
struct atmel_mci_slot {
@ -388,9 +421,8 @@ struct atmel_mci_slot {
#define ATMCI_CARD_NEED_INIT 1
#define ATMCI_SHUTDOWN 2
int detect_pin;
int wp_pin;
bool detect_is_active_high;
struct gpio_desc *detect_pin;
struct gpio_desc *wp_pin;
struct timer_list detect_timer;
};
@ -608,6 +640,7 @@ atmci_of_init(struct platform_device *pdev)
struct device_node *cnp;
struct mci_platform_data *pdata;
u32 slot_id;
int err;
if (!np) {
dev_err(&pdev->dev, "device node not found\n");
@ -637,16 +670,27 @@ atmci_of_init(struct platform_device *pdev)
pdata->slot[slot_id].bus_width = 1;
pdata->slot[slot_id].detect_pin =
of_get_named_gpio(cnp, "cd-gpios", 0);
pdata->slot[slot_id].detect_is_active_high =
of_property_read_bool(cnp, "cd-inverted");
devm_fwnode_gpiod_get(&pdev->dev, of_fwnode_handle(cnp),
"cd", GPIOD_IN, "cd-gpios");
err = PTR_ERR_OR_ZERO(pdata->slot[slot_id].detect_pin);
if (err) {
if (err != -ENOENT)
return ERR_PTR(err);
pdata->slot[slot_id].detect_pin = NULL;
}
pdata->slot[slot_id].non_removable =
of_property_read_bool(cnp, "non-removable");
pdata->slot[slot_id].wp_pin =
of_get_named_gpio(cnp, "wp-gpios", 0);
devm_fwnode_gpiod_get(&pdev->dev, of_fwnode_handle(cnp),
"wp", GPIOD_IN, "wp-gpios");
err = PTR_ERR_OR_ZERO(pdata->slot[slot_id].wp_pin);
if (err) {
if (err != -ENOENT)
return ERR_PTR(err);
pdata->slot[slot_id].wp_pin = NULL;
}
}
return pdata;
@ -1509,8 +1553,8 @@ static int atmci_get_ro(struct mmc_host *mmc)
int read_only = -ENOSYS;
struct atmel_mci_slot *slot = mmc_priv(mmc);
if (gpio_is_valid(slot->wp_pin)) {
read_only = gpio_get_value(slot->wp_pin);
if (slot->wp_pin) {
read_only = gpiod_get_value(slot->wp_pin);
dev_dbg(&mmc->class_dev, "card is %s\n",
read_only ? "read-only" : "read-write");
}
@ -1523,9 +1567,8 @@ static int atmci_get_cd(struct mmc_host *mmc)
int present = -ENOSYS;
struct atmel_mci_slot *slot = mmc_priv(mmc);
if (gpio_is_valid(slot->detect_pin)) {
present = !(gpio_get_value(slot->detect_pin) ^
slot->detect_is_active_high);
if (slot->detect_pin) {
present = gpiod_get_value_cansleep(slot->detect_pin);
dev_dbg(&mmc->class_dev, "card is %spresent\n",
present ? "" : "not ");
}
@ -1637,9 +1680,8 @@ static void atmci_detect_change(struct timer_list *t)
if (test_bit(ATMCI_SHUTDOWN, &slot->flags))
return;
enable_irq(gpio_to_irq(slot->detect_pin));
present = !(gpio_get_value(slot->detect_pin) ^
slot->detect_is_active_high);
enable_irq(gpiod_to_irq(slot->detect_pin));
present = gpiod_get_value_cansleep(slot->detect_pin);
present_old = test_bit(ATMCI_CARD_PRESENT, &slot->flags);
dev_vdbg(&slot->mmc->class_dev, "detect change: %d (was %d)\n",
@ -2230,16 +2272,15 @@ static int atmci_init_slot(struct atmel_mci *host,
slot->host = host;
slot->detect_pin = slot_data->detect_pin;
slot->wp_pin = slot_data->wp_pin;
slot->detect_is_active_high = slot_data->detect_is_active_high;
slot->sdc_reg = sdc_reg;
slot->sdio_irq = sdio_irq;
dev_dbg(&mmc->class_dev,
"slot[%u]: bus_width=%u, detect_pin=%d, "
"detect_is_active_high=%s, wp_pin=%d\n",
id, slot_data->bus_width, slot_data->detect_pin,
slot_data->detect_is_active_high ? "true" : "false",
slot_data->wp_pin);
id, slot_data->bus_width, desc_to_gpio(slot_data->detect_pin),
!gpiod_is_active_low(slot_data->detect_pin) ? "true" : "false",
desc_to_gpio(slot_data->wp_pin));
mmc->ops = &atmci_ops;
mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512);
@ -2275,31 +2316,22 @@ static int atmci_init_slot(struct atmel_mci *host,
/* Assume card is present initially */
set_bit(ATMCI_CARD_PRESENT, &slot->flags);
if (gpio_is_valid(slot->detect_pin)) {
if (devm_gpio_request(&host->pdev->dev, slot->detect_pin,
"mmc_detect")) {
dev_dbg(&mmc->class_dev, "no detect pin available\n");
slot->detect_pin = -EBUSY;
} else if (gpio_get_value(slot->detect_pin) ^
slot->detect_is_active_high) {
if (slot->detect_pin) {
if (!gpiod_get_value_cansleep(slot->detect_pin))
clear_bit(ATMCI_CARD_PRESENT, &slot->flags);
}
} else {
dev_dbg(&mmc->class_dev, "no detect pin available\n");
}
if (!gpio_is_valid(slot->detect_pin)) {
if (!slot->detect_pin) {
if (slot_data->non_removable)
mmc->caps |= MMC_CAP_NONREMOVABLE;
else
mmc->caps |= MMC_CAP_NEEDS_POLL;
}
if (gpio_is_valid(slot->wp_pin)) {
if (devm_gpio_request(&host->pdev->dev, slot->wp_pin,
"mmc_wp")) {
dev_dbg(&mmc->class_dev, "no WP pin available\n");
slot->wp_pin = -EBUSY;
}
}
if (!slot->wp_pin)
dev_dbg(&mmc->class_dev, "no WP pin available\n");
host->slot[id] = slot;
mmc_regulator_get_supply(mmc);
@ -2309,18 +2341,18 @@ static int atmci_init_slot(struct atmel_mci *host,
return ret;
}
if (gpio_is_valid(slot->detect_pin)) {
if (slot->detect_pin) {
timer_setup(&slot->detect_timer, atmci_detect_change, 0);
ret = request_irq(gpio_to_irq(slot->detect_pin),
atmci_detect_interrupt,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"mmc-detect", slot);
ret = request_irq(gpiod_to_irq(slot->detect_pin),
atmci_detect_interrupt,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"mmc-detect", slot);
if (ret) {
dev_dbg(&mmc->class_dev,
"could not request IRQ %d for detect pin\n",
gpio_to_irq(slot->detect_pin));
slot->detect_pin = -EBUSY;
gpiod_to_irq(slot->detect_pin));
slot->detect_pin = NULL;
}
}
@ -2339,10 +2371,8 @@ static void atmci_cleanup_slot(struct atmel_mci_slot *slot,
mmc_remove_host(slot->mmc);
if (gpio_is_valid(slot->detect_pin)) {
int pin = slot->detect_pin;
free_irq(gpio_to_irq(pin), slot);
if (slot->detect_pin) {
free_irq(gpiod_to_irq(slot->detect_pin), slot);
del_timer_sync(&slot->detect_timer);
}
@ -2600,7 +2630,7 @@ static int atmci_probe(struct platform_device *pdev)
return ret;
}
static int atmci_remove(struct platform_device *pdev)
static void atmci_remove(struct platform_device *pdev)
{
struct atmel_mci *host = platform_get_drvdata(pdev);
unsigned int i;
@ -2630,8 +2660,6 @@ static int atmci_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
return 0;
}
#ifdef CONFIG_PM
@ -2664,7 +2692,7 @@ static const struct dev_pm_ops atmci_dev_pm_ops = {
static struct platform_driver atmci_driver = {
.probe = atmci_probe,
.remove = atmci_remove,
.remove_new = atmci_remove,
.driver = {
.name = "atmel_mci",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -1114,7 +1114,7 @@ static int au1xmmc_probe(struct platform_device *pdev)
return ret;
}
static int au1xmmc_remove(struct platform_device *pdev)
static void au1xmmc_remove(struct platform_device *pdev)
{
struct au1xmmc_host *host = platform_get_drvdata(pdev);
@ -1153,7 +1153,6 @@ static int au1xmmc_remove(struct platform_device *pdev)
mmc_free_host(host->mmc);
}
return 0;
}
#ifdef CONFIG_PM
@ -1185,7 +1184,7 @@ static int au1xmmc_resume(struct platform_device *pdev)
static struct platform_driver au1xmmc_driver = {
.probe = au1xmmc_probe,
.remove = au1xmmc_remove,
.remove_new = au1xmmc_remove,
.suspend = au1xmmc_suspend,
.resume = au1xmmc_resume,
.driver = {

View file

@ -1431,7 +1431,7 @@ static int bcm2835_probe(struct platform_device *pdev)
return ret;
}
static int bcm2835_remove(struct platform_device *pdev)
static void bcm2835_remove(struct platform_device *pdev)
{
struct bcm2835_host *host = platform_get_drvdata(pdev);
struct mmc_host *mmc = mmc_from_priv(host);
@ -1449,8 +1449,6 @@ static int bcm2835_remove(struct platform_device *pdev)
dma_release_channel(host->dma_chan_rxtx);
mmc_free_host(mmc);
return 0;
}
static const struct of_device_id bcm2835_match[] = {
@ -1461,7 +1459,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_match);
static struct platform_driver bcm2835_driver = {
.probe = bcm2835_probe,
.remove = bcm2835_remove,
.remove_new = bcm2835_remove,
.driver = {
.name = "sdhost-bcm2835",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -13,7 +13,9 @@
#include <linux/mmc/mmc.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <asm/octeon/octeon.h>
#include "cavium.h"
@ -294,7 +296,7 @@ static int octeon_mmc_probe(struct platform_device *pdev)
return ret;
}
static int octeon_mmc_remove(struct platform_device *pdev)
static void octeon_mmc_remove(struct platform_device *pdev)
{
struct cvm_mmc_host *host = platform_get_drvdata(pdev);
u64 dma_cfg;
@ -309,7 +311,6 @@ static int octeon_mmc_remove(struct platform_device *pdev)
writeq(dma_cfg, host->dma_base + MIO_EMM_DMA_CFG(host));
octeon_mmc_set_shared_power(host, 0);
return 0;
}
static const struct of_device_id octeon_mmc_match[] = {
@ -325,7 +326,7 @@ MODULE_DEVICE_TABLE(of, octeon_mmc_match);
static struct platform_driver octeon_mmc_driver = {
.probe = octeon_mmc_probe,
.remove = octeon_mmc_remove,
.remove_new = octeon_mmc_remove,
.driver = {
.name = KBUILD_MODNAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
#include "cavium.h"

View file

@ -745,7 +745,7 @@ static int cb710_mmc_init(struct platform_device *pdev)
return err;
}
static int cb710_mmc_exit(struct platform_device *pdev)
static void cb710_mmc_exit(struct platform_device *pdev)
{
struct cb710_slot *slot = cb710_pdev_to_slot(pdev);
struct mmc_host *mmc = cb710_slot_to_mmc(slot);
@ -766,13 +766,12 @@ static int cb710_mmc_exit(struct platform_device *pdev)
tasklet_kill(&reader->finish_req_tasklet);
mmc_free_host(mmc);
return 0;
}
static struct platform_driver cb710_mmc_driver = {
.driver.name = "cb710-mmc",
.probe = cb710_mmc_init,
.remove = cb710_mmc_exit,
.remove_new = cb710_mmc_exit,
#ifdef CONFIG_PM
.suspend = cb710_mmc_suspend,
.resume = cb710_mmc_resume,

View file

@ -21,7 +21,6 @@
#include <linux/dma-mapping.h>
#include <linux/mmc/mmc.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/interrupt.h>
@ -1257,7 +1256,7 @@ static int davinci_mmcsd_probe(struct platform_device *pdev)
host->use_dma = use_dma;
host->mmc_irq = irq;
host->sdio_irq = platform_get_irq(pdev, 1);
host->sdio_irq = platform_get_irq_optional(pdev, 1);
if (host->use_dma) {
ret = davinci_acquire_dma_channels(host);
@ -1345,7 +1344,7 @@ static int davinci_mmcsd_probe(struct platform_device *pdev)
return ret;
}
static int __exit davinci_mmcsd_remove(struct platform_device *pdev)
static void __exit davinci_mmcsd_remove(struct platform_device *pdev)
{
struct mmc_davinci_host *host = platform_get_drvdata(pdev);
@ -1354,8 +1353,6 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev)
davinci_release_dma_channels(host);
clk_disable_unprepare(host->clk);
mmc_free_host(host->mmc);
return 0;
}
#ifdef CONFIG_PM
@ -1402,7 +1399,7 @@ static struct platform_driver davinci_mmcsd_driver = {
.of_match_table = davinci_mmc_dt_ids,
},
.probe = davinci_mmcsd_probe,
.remove = __exit_p(davinci_mmcsd_remove),
.remove_new = __exit_p(davinci_mmcsd_remove),
.id_table = davinci_mmc_devtype,
};

View file

@ -664,15 +664,13 @@ static int dw_mci_exynos_probe(struct platform_device *pdev)
return 0;
}
static int dw_mci_exynos_remove(struct platform_device *pdev)
static void dw_mci_exynos_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
dw_mci_pltfm_remove(pdev);
return 0;
}
static const struct dev_pm_ops dw_mci_exynos_pmops = {
@ -685,7 +683,7 @@ static const struct dev_pm_ops dw_mci_exynos_pmops = {
static struct platform_driver dw_mci_exynos_pltfm_driver = {
.probe = dw_mci_exynos_probe,
.remove = dw_mci_exynos_remove,
.remove_new = dw_mci_exynos_remove,
.driver = {
.name = "dwmmc_exynos",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -171,7 +171,7 @@ static int dw_mci_hi3798cv200_probe(struct platform_device *pdev)
return dw_mci_pltfm_register(pdev, &hi3798cv200_data);
}
static int dw_mci_hi3798cv200_remove(struct platform_device *pdev)
static void dw_mci_hi3798cv200_remove(struct platform_device *pdev)
{
struct dw_mci *host = platform_get_drvdata(pdev);
struct hi3798cv200_priv *priv = host->priv;
@ -180,8 +180,6 @@ static int dw_mci_hi3798cv200_remove(struct platform_device *pdev)
clk_disable_unprepare(priv->sample_clk);
dw_mci_pltfm_remove(pdev);
return 0;
}
static const struct of_device_id dw_mci_hi3798cv200_match[] = {
@ -192,7 +190,7 @@ static const struct of_device_id dw_mci_hi3798cv200_match[] = {
MODULE_DEVICE_TABLE(of, dw_mci_hi3798cv200_match);
static struct platform_driver dw_mci_hi3798cv200_driver = {
.probe = dw_mci_hi3798cv200_probe,
.remove = dw_mci_hi3798cv200_remove,
.remove_new = dw_mci_hi3798cv200_remove,
.driver = {
.name = "dwmmc_hi3798cv200",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -371,15 +371,13 @@ static int dw_mci_rockchip_probe(struct platform_device *pdev)
return 0;
}
static int dw_mci_rockchip_remove(struct platform_device *pdev)
static void dw_mci_rockchip_remove(struct platform_device *pdev)
{
pm_runtime_get_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
dw_mci_pltfm_remove(pdev);
return 0;
}
static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = {
@ -392,7 +390,7 @@ static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = {
static struct platform_driver dw_mci_rockchip_pltfm_driver = {
.probe = dw_mci_rockchip_probe,
.remove = dw_mci_rockchip_remove,
.remove_new = dw_mci_rockchip_remove,
.driver = {
.name = "dwmmc_rockchip",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -1163,7 +1163,7 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
return ret;
}
static int jz4740_mmc_remove(struct platform_device *pdev)
static void jz4740_mmc_remove(struct platform_device *pdev)
{
struct jz4740_mmc_host *host = platform_get_drvdata(pdev);
@ -1179,8 +1179,6 @@ static int jz4740_mmc_remove(struct platform_device *pdev)
jz4740_mmc_release_dma_channels(host);
mmc_free_host(host->mmc);
return 0;
}
static int jz4740_mmc_suspend(struct device *dev)
@ -1198,7 +1196,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend,
static struct platform_driver jz4740_mmc_driver = {
.probe = jz4740_mmc_probe,
.remove = jz4740_mmc_remove,
.remove_new = jz4740_mmc_remove,
.driver = {
.name = "jz4740-mmc",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -629,12 +629,11 @@ static int litex_mmc_probe(struct platform_device *pdev)
return 0;
}
static int litex_mmc_remove(struct platform_device *pdev)
static void litex_mmc_remove(struct platform_device *pdev)
{
struct litex_mmc_host *host = platform_get_drvdata(pdev);
mmc_remove_host(host->mmc);
return 0;
}
static const struct of_device_id litex_match[] = {
@ -645,7 +644,7 @@ MODULE_DEVICE_TABLE(of, litex_match);
static struct platform_driver litex_mmc_driver = {
.probe = litex_mmc_probe,
.remove = litex_mmc_remove,
.remove_new = litex_mmc_remove,
.driver = {
.name = "litex-mmc",
.of_match_table = litex_match,

View file

@ -11,7 +11,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/iopoll.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
#include <linux/dma-mapping.h>
@ -948,9 +948,6 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
return IRQ_NONE;
}
if (WARN_ON(!host))
return IRQ_NONE;
/* ack all raised interrupts */
writel(status, host->regs + SD_EMMC_STATUS);
@ -1297,7 +1294,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
return ret;
}
static int meson_mmc_remove(struct platform_device *pdev)
static void meson_mmc_remove(struct platform_device *pdev)
{
struct meson_host *host = dev_get_drvdata(&pdev->dev);
@ -1308,8 +1305,6 @@ static int meson_mmc_remove(struct platform_device *pdev)
free_irq(host->irq, host);
clk_disable_unprepare(host->mmc_clk);
return 0;
}
static const struct meson_mmc_data meson_gx_data = {
@ -1340,7 +1335,7 @@ MODULE_DEVICE_TABLE(of, meson_mmc_of_match);
static struct platform_driver meson_mmc_driver = {
.probe = meson_mmc_probe,
.remove = meson_mmc_remove,
.remove_new = meson_mmc_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -880,7 +880,7 @@ static int meson_mx_sdhc_probe(struct platform_device *pdev)
return ret;
}
static int meson_mx_sdhc_remove(struct platform_device *pdev)
static void meson_mx_sdhc_remove(struct platform_device *pdev)
{
struct meson_mx_sdhc_host *host = platform_get_drvdata(pdev);
@ -889,8 +889,6 @@ static int meson_mx_sdhc_remove(struct platform_device *pdev)
meson_mx_sdhc_disable_clks(host->mmc);
clk_disable_unprepare(host->pclk);
return 0;
}
static const struct meson_mx_sdhc_data meson_mx_sdhc_data_meson8 = {
@ -925,7 +923,7 @@ MODULE_DEVICE_TABLE(of, meson_mx_sdhc_of_match);
static struct platform_driver meson_mx_sdhc_driver = {
.probe = meson_mx_sdhc_probe,
.remove = meson_mx_sdhc_remove,
.remove_new = meson_mx_sdhc_remove,
.driver = {
.name = "meson-mx-sdhc",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -728,7 +728,7 @@ static int meson_mx_mmc_probe(struct platform_device *pdev)
return ret;
}
static int meson_mx_mmc_remove(struct platform_device *pdev)
static void meson_mx_mmc_remove(struct platform_device *pdev)
{
struct meson_mx_mmc_host *host = platform_get_drvdata(pdev);
struct device *slot_dev = mmc_dev(host->mmc);
@ -743,8 +743,6 @@ static int meson_mx_mmc_remove(struct platform_device *pdev)
clk_disable_unprepare(host->core_clk);
mmc_free_host(host->mmc);
return 0;
}
static const struct of_device_id meson_mx_mmc_of_match[] = {
@ -756,7 +754,7 @@ MODULE_DEVICE_TABLE(of, meson_mx_mmc_of_match);
static struct platform_driver meson_mx_mmc_driver = {
.probe = meson_mx_mmc_probe,
.remove = meson_mx_mmc_remove,
.remove_new = meson_mx_mmc_remove,
.driver = {
.name = "meson-mx-sdio",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -764,7 +764,8 @@ static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd,
}
retries--;
}
dev_dbg(mmc_dev(host->mmc), "no busy signalling in time\n");
dev_dbg(mmc_dev(host->mmc),
"no busy signalling in time CMD%02x\n", cmd->opcode);
ux500_busy_clear_mask_done(host);
break;
@ -786,7 +787,8 @@ static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd,
host->busy_state = MMCI_BUSY_WAITING_FOR_END_IRQ;
} else {
dev_dbg(mmc_dev(host->mmc),
"lost busy status when waiting for busy start IRQ\n");
"lost busy status when waiting for busy start IRQ CMD%02x\n",
cmd->opcode);
cancel_delayed_work(&host->ux500_busy_timeout_work);
ux500_busy_clear_mask_done(host);
}
@ -800,13 +802,14 @@ static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd,
ux500_busy_clear_mask_done(host);
} else {
dev_dbg(mmc_dev(host->mmc),
"busy status still asserted when handling busy end IRQ - will keep waiting\n");
"busy status still asserted when handling busy end IRQ - will keep waiting CMD%02x\n",
cmd->opcode);
}
break;
default:
dev_dbg(mmc_dev(host->mmc), "fell through on state %d\n",
host->busy_state);
dev_dbg(mmc_dev(host->mmc), "fell through on state %d, CMD%02x\n",
host->busy_state, cmd->opcode);
break;
}
@ -1533,6 +1536,20 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
}
}
static char *ux500_state_str(struct mmci_host *host)
{
switch (host->busy_state) {
case MMCI_BUSY_WAITING_FOR_START_IRQ:
return "waiting for start IRQ";
case MMCI_BUSY_WAITING_FOR_END_IRQ:
return "waiting for end IRQ";
case MMCI_BUSY_DONE:
return "not waiting for IRQs";
default:
return "unknown";
}
}
/*
* This busy timeout worker is used to "kick" the command IRQ if a
* busy detect IRQ fails to appear in reasonable time. Only used on
@ -1548,12 +1565,18 @@ static void ux500_busy_timeout_work(struct work_struct *work)
spin_lock_irqsave(&host->lock, flags);
if (host->cmd) {
dev_dbg(mmc_dev(host->mmc), "timeout waiting for busy IRQ\n");
/* If we are still busy let's tag on a cmd-timeout error. */
status = readl(host->base + MMCISTATUS);
if (status & host->variant->busy_detect_flag)
if (status & host->variant->busy_detect_flag) {
status |= MCI_CMDTIMEOUT;
dev_err(mmc_dev(host->mmc),
"timeout in state %s still busy with CMD%02x\n",
ux500_state_str(host), host->cmd->opcode);
} else {
dev_err(mmc_dev(host->mmc),
"timeout in state %s waiting for busy CMD%02x\n",
ux500_state_str(host), host->cmd->opcode);
}
mmci_cmd_irq(host, host->cmd, status);
}

View file

@ -687,13 +687,11 @@ static int moxart_probe(struct platform_device *pdev)
return ret;
}
static int moxart_remove(struct platform_device *pdev)
static void moxart_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = dev_get_drvdata(&pdev->dev);
struct moxart_host *host = mmc_priv(mmc);
dev_set_drvdata(&pdev->dev, NULL);
if (!IS_ERR_OR_NULL(host->dma_chan_tx))
dma_release_channel(host->dma_chan_tx);
if (!IS_ERR_OR_NULL(host->dma_chan_rx))
@ -705,8 +703,6 @@ static int moxart_remove(struct platform_device *pdev)
writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF,
host->base + REG_CLOCK_CONTROL);
mmc_free_host(mmc);
return 0;
}
static const struct of_device_id moxart_mmc_match[] = {
@ -718,7 +714,7 @@ MODULE_DEVICE_TABLE(of, moxart_mmc_match);
static struct platform_driver moxart_mmc_driver = {
.probe = moxart_probe,
.remove = moxart_remove,
.remove_new = moxart_remove,
.driver = {
.name = "mmc-moxart",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -12,9 +12,7 @@
#include <linux/iopoll.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
@ -2887,7 +2885,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
return ret;
}
static int msdc_drv_remove(struct platform_device *pdev)
static void msdc_drv_remove(struct platform_device *pdev)
{
struct mmc_host *mmc;
struct msdc_host *host;
@ -2911,8 +2909,6 @@ static int msdc_drv_remove(struct platform_device *pdev)
host->dma.bd, host->dma.bd_addr);
mmc_free_host(mmc);
return 0;
}
static void msdc_save_reg(struct msdc_host *host)
@ -3054,7 +3050,7 @@ static const struct dev_pm_ops msdc_dev_pm_ops = {
static struct platform_driver mt_msdc_driver = {
.probe = msdc_drv_probe,
.remove = msdc_drv_remove,
.remove_new = msdc_drv_remove,
.driver = {
.name = "mtk-msdc",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -796,7 +796,7 @@ static int mvsd_probe(struct platform_device *pdev)
return ret;
}
static int mvsd_remove(struct platform_device *pdev)
static void mvsd_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
@ -809,8 +809,6 @@ static int mvsd_remove(struct platform_device *pdev)
if (!IS_ERR(host->clk))
clk_disable_unprepare(host->clk);
mmc_free_host(mmc);
return 0;
}
static const struct of_device_id mvsdio_dt_ids[] = {
@ -821,7 +819,7 @@ MODULE_DEVICE_TABLE(of, mvsdio_dt_ids);
static struct platform_driver mvsd_driver = {
.probe = mvsd_probe,
.remove = mvsd_remove,
.remove_new = mvsd_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -31,7 +31,6 @@
#include <linux/dmaengine.h>
#include <linux/types.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_dma.h>
#include <linux/mmc/slot-gpio.h>
@ -989,7 +988,6 @@ static int mxcmci_probe(struct platform_device *pdev)
pr_info("i.MX/MPC512x SDHC driver\n");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@ -1000,7 +998,7 @@ static int mxcmci_probe(struct platform_device *pdev)
host = mmc_priv(mmc);
host->base = devm_ioremap_resource(&pdev->dev, res);
host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(host->base)) {
ret = PTR_ERR(host->base);
goto out_free;
@ -1164,7 +1162,7 @@ static int mxcmci_probe(struct platform_device *pdev)
return ret;
}
static int mxcmci_remove(struct platform_device *pdev)
static void mxcmci_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct mxcmci_host *host = mmc_priv(mmc);
@ -1181,8 +1179,6 @@ static int mxcmci_remove(struct platform_device *pdev)
clk_disable_unprepare(host->clk_ipg);
mmc_free_host(mmc);
return 0;
}
static int mxcmci_suspend(struct device *dev)
@ -1216,7 +1212,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume);
static struct platform_driver mxcmci_driver = {
.probe = mxcmci_probe,
.remove = mxcmci_remove,
.remove_new = mxcmci_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -11,7 +11,6 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@ -674,7 +673,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
return ret;
}
static int mxs_mmc_remove(struct platform_device *pdev)
static void mxs_mmc_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct mxs_mmc_host *host = mmc_priv(mmc);
@ -688,8 +687,6 @@ static int mxs_mmc_remove(struct platform_device *pdev)
clk_disable_unprepare(ssp->clk);
mmc_free_host(mmc);
return 0;
}
#ifdef CONFIG_PM_SLEEP
@ -717,7 +714,7 @@ static SIMPLE_DEV_PM_OPS(mxs_mmc_pm_ops, mxs_mmc_suspend, mxs_mmc_resume);
static struct platform_driver mxs_mmc_driver = {
.probe = mxs_mmc_probe,
.remove = mxs_mmc_remove,
.remove_new = mxs_mmc_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -1506,7 +1506,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
return ret;
}
static int mmc_omap_remove(struct platform_device *pdev)
static void mmc_omap_remove(struct platform_device *pdev)
{
struct mmc_omap_host *host = platform_get_drvdata(pdev);
int i;
@ -1532,8 +1532,6 @@ static int mmc_omap_remove(struct platform_device *pdev)
dma_release_channel(host->dma_rx);
destroy_workqueue(host->mmc_omap_wq);
return 0;
}
#if IS_BUILTIN(CONFIG_OF)
@ -1546,7 +1544,7 @@ MODULE_DEVICE_TABLE(of, mmc_omap_match);
static struct platform_driver mmc_omap_driver = {
.probe = mmc_omap_probe,
.remove = mmc_omap_remove,
.remove_new = mmc_omap_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -1790,14 +1790,11 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
return -ENXIO;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENXIO;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
base = devm_ioremap_resource(&pdev->dev, res);
base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(base))
return PTR_ERR(base);
@ -1982,7 +1979,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
return ret;
}
static int omap_hsmmc_remove(struct platform_device *pdev)
static void omap_hsmmc_remove(struct platform_device *pdev)
{
struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
@ -2000,8 +1997,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
clk_disable_unprepare(host->dbclk);
mmc_free_host(host->mmc);
return 0;
}
#ifdef CONFIG_PM_SLEEP
@ -2126,7 +2121,7 @@ static const struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
static struct platform_driver omap_hsmmc_driver = {
.probe = omap_hsmmc_probe,
.remove = omap_hsmmc_remove,
.remove_new = omap_hsmmc_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -16,8 +16,9 @@
#include <linux/interrupt.h>
#include <linux/mmc/host.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/spinlock.h>
@ -667,7 +668,7 @@ static int owl_mmc_probe(struct platform_device *pdev)
return ret;
}
static int owl_mmc_remove(struct platform_device *pdev)
static void owl_mmc_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct owl_mmc_host *owl_host = mmc_priv(mmc);
@ -676,8 +677,6 @@ static int owl_mmc_remove(struct platform_device *pdev)
disable_irq(owl_host->irq);
dma_release_channel(owl_host->dma);
mmc_free_host(mmc);
return 0;
}
static const struct of_device_id owl_mmc_of_match[] = {
@ -693,7 +692,7 @@ static struct platform_driver owl_mmc_driver = {
.of_match_table = owl_mmc_of_match,
},
.probe = owl_mmc_probe,
.remove = owl_mmc_remove,
.remove_new = owl_mmc_remove,
};
module_platform_driver(owl_mmc_driver);

View file

@ -30,7 +30,6 @@
#include <linux/gpio/consumer.h>
#include <linux/gfp.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/soc/pxa/cpu.h>
#include <linux/sizes.h>
@ -612,7 +611,6 @@ static int pxamci_probe(struct platform_device *pdev)
struct resource *r;
int ret, irq;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@ -685,14 +683,14 @@ static int pxamci_probe(struct platform_device *pdev)
}
spin_lock_init(&host->lock);
host->res = r;
host->imask = MMC_I_MASK_ALL;
host->base = devm_ioremap_resource(dev, r);
host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
if (IS_ERR(host->base)) {
ret = PTR_ERR(host->base);
goto out;
}
host->res = r;
/*
* Ensure that the host controller is shut down, and setup
@ -784,7 +782,7 @@ static int pxamci_probe(struct platform_device *pdev)
return ret;
}
static int pxamci_remove(struct platform_device *pdev)
static void pxamci_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
@ -808,13 +806,11 @@ static int pxamci_remove(struct platform_device *pdev)
mmc_free_host(mmc);
}
return 0;
}
static struct platform_driver pxamci_driver = {
.probe = pxamci_probe,
.remove = pxamci_remove,
.remove_new = pxamci_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -101,5 +101,5 @@ int renesas_sdhi_probe(struct platform_device *pdev,
const struct tmio_mmc_dma_ops *dma_ops,
const struct renesas_sdhi_of_data *of_data,
const struct renesas_sdhi_quirks *quirks);
int renesas_sdhi_remove(struct platform_device *pdev);
void renesas_sdhi_remove(struct platform_device *pdev);
#endif

View file

@ -983,12 +983,12 @@ int renesas_sdhi_probe(struct platform_device *pdev,
}
host->write16_hook = renesas_sdhi_write16_hook;
host->clk_enable = renesas_sdhi_clk_enable;
host->clk_disable = renesas_sdhi_clk_disable;
host->set_clock = renesas_sdhi_set_clock;
host->multi_io_quirk = renesas_sdhi_multi_io_quirk;
host->dma_ops = dma_ops;
host->write16_hook = renesas_sdhi_write16_hook;
host->clk_enable = renesas_sdhi_clk_enable;
host->clk_disable = renesas_sdhi_clk_disable;
host->set_clock = renesas_sdhi_set_clock;
host->multi_io_quirk = renesas_sdhi_multi_io_quirk;
host->dma_ops = dma_ops;
if (sdhi_has_quirk(priv, hs400_disabled))
host->mmc->caps2 &= ~(MMC_CAP2_HS400 | MMC_CAP2_HS400_ES);
@ -1006,6 +1006,8 @@ int renesas_sdhi_probe(struct platform_device *pdev,
host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27;
host->sdcard_irq_mask_all = TMIO_MASK_ALL_RCAR2;
host->reset = renesas_sdhi_reset;
} else {
host->sdcard_irq_mask_all = TMIO_MASK_ALL;
}
/* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */
@ -1100,9 +1102,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
host->ops.hs400_complete = renesas_sdhi_hs400_complete;
}
ret = tmio_mmc_host_probe(host);
if (ret < 0)
goto edisclk;
sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask_all);
num_irqs = platform_irq_count(pdev);
if (num_irqs < 0) {
@ -1129,6 +1129,10 @@ int renesas_sdhi_probe(struct platform_device *pdev,
goto eirq;
}
ret = tmio_mmc_host_probe(host);
if (ret < 0)
goto edisclk;
dev_info(&pdev->dev, "%s base at %pa, max clock rate %u MHz\n",
mmc_hostname(host->mmc), &res->start, host->mmc->f_max / 1000000);
@ -1145,15 +1149,13 @@ int renesas_sdhi_probe(struct platform_device *pdev,
}
EXPORT_SYMBOL_GPL(renesas_sdhi_probe);
int renesas_sdhi_remove(struct platform_device *pdev)
void renesas_sdhi_remove(struct platform_device *pdev)
{
struct tmio_mmc_host *host = platform_get_drvdata(pdev);
tmio_mmc_host_remove(host);
renesas_sdhi_clk_disable(host);
tmio_mmc_host_free(host);
return 0;
}
EXPORT_SYMBOL_GPL(renesas_sdhi_remove);

View file

@ -15,7 +15,8 @@
#include <linux/mmc/host.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pagemap.h>
#include <linux/scatterlist.h>
#include <linux/sys_soc.h>
@ -609,7 +610,7 @@ static struct platform_driver renesas_internal_dmac_sdhi_driver = {
.of_match_table = renesas_sdhi_internal_dmac_of_match,
},
.probe = renesas_sdhi_internal_dmac_probe,
.remove = renesas_sdhi_remove,
.remove_new = renesas_sdhi_remove,
};
module_platform_driver(renesas_internal_dmac_sdhi_driver);

View file

@ -15,7 +15,8 @@
#include <linux/mmc/host.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pagemap.h>
#include <linux/scatterlist.h>
#include <linux/sys_soc.h>
@ -470,7 +471,7 @@ static struct platform_driver renesas_sys_dmac_sdhi_driver = {
.of_match_table = renesas_sdhi_sys_dmac_of_match,
},
.probe = renesas_sdhi_sys_dmac_probe,
.remove = renesas_sdhi_remove,
.remove_new = renesas_sdhi_remove,
};
module_platform_driver(renesas_sys_dmac_sdhi_driver);

View file

@ -1523,15 +1523,12 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
return 0;
}
static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
static void rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
{
struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
struct rtsx_pcr *pcr;
struct mmc_host *mmc;
if (!host)
return 0;
pcr = host->pcr;
pcr->slots[RTSX_SD_CARD].p_dev = NULL;
pcr->slots[RTSX_SD_CARD].card_event = NULL;
@ -1566,8 +1563,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
dev_dbg(&(pdev->dev),
": Realtek PCI-E SDMMC controller has been removed\n");
return 0;
}
static const struct platform_device_id rtsx_pci_sdmmc_ids[] = {
@ -1581,7 +1576,7 @@ MODULE_DEVICE_TABLE(platform, rtsx_pci_sdmmc_ids);
static struct platform_driver rtsx_pci_sdmmc_driver = {
.probe = rtsx_pci_sdmmc_drv_probe,
.remove = rtsx_pci_sdmmc_drv_remove,
.remove_new = rtsx_pci_sdmmc_drv_remove,
.id_table = rtsx_pci_sdmmc_ids,
.driver = {
.name = DRV_NAME_RTSX_PCI_SDMMC,

View file

@ -1379,13 +1379,13 @@ static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev)
return 0;
}
static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev)
static void rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev)
{
struct rtsx_usb_sdmmc *host = platform_get_drvdata(pdev);
struct mmc_host *mmc;
if (!host)
return 0;
return;
mmc = host->mmc;
host->host_removal = true;
@ -1415,8 +1415,6 @@ static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev)
dev_dbg(&(pdev->dev),
": Realtek USB SD/MMC module has been removed\n");
return 0;
}
#ifdef CONFIG_PM
@ -1455,7 +1453,7 @@ MODULE_DEVICE_TABLE(platform, rtsx_usb_sdmmc_ids);
static struct platform_driver rtsx_usb_sdmmc_driver = {
.probe = rtsx_usb_sdmmc_drv_probe,
.remove = rtsx_usb_sdmmc_drv_remove,
.remove_new = rtsx_usb_sdmmc_drv_remove,
.id_table = rtsx_usb_sdmmc_ids,
.driver = {
.name = "rtsx_usb_sdmmc",

View file

@ -917,7 +917,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
return err;
}
static int sdhci_acpi_remove(struct platform_device *pdev)
static void sdhci_acpi_remove(struct platform_device *pdev)
{
struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
@ -939,8 +939,6 @@ static int sdhci_acpi_remove(struct platform_device *pdev)
c->slot->free_slot(pdev);
sdhci_free_host(c->host);
return 0;
}
static void __maybe_unused sdhci_acpi_reset_signal_voltage_if_needed(
@ -1033,7 +1031,7 @@ static struct platform_driver sdhci_acpi_driver = {
.pm = &sdhci_acpi_pm_ops,
},
.probe = sdhci_acpi_probe,
.remove = sdhci_acpi_remove,
.remove_new = sdhci_acpi_remove,
};
module_platform_driver(sdhci_acpi_driver);

View file

@ -11,7 +11,6 @@
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/mmc/slot-gpio.h>
#include "sdhci-pltfm.h"
@ -311,6 +310,16 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev)
return ret;
}
static void sdhci_bcm_kona_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct clk *clk = pltfm_host->clk;
sdhci_pltfm_remove(pdev);
clk_disable_unprepare(clk);
}
static struct platform_driver sdhci_bcm_kona_driver = {
.driver = {
.name = "sdhci-kona",
@ -319,7 +328,7 @@ static struct platform_driver sdhci_bcm_kona_driver = {
.of_match_table = sdhci_bcm_kona_of_match,
},
.probe = sdhci_bcm_kona_probe,
.remove = sdhci_pltfm_unregister,
.remove_new = sdhci_bcm_kona_remove,
};
module_platform_driver(sdhci_bcm_kona_driver);

View file

@ -264,23 +264,17 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "Probe found match for %s\n", match->compatible);
clk = devm_clk_get_optional(&pdev->dev, NULL);
clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
if (IS_ERR(clk))
return dev_err_probe(&pdev->dev, PTR_ERR(clk),
"Failed to get clock from Device Tree\n");
res = clk_prepare_enable(clk);
if (res)
return res;
"Failed to get and enable clock from Device Tree\n");
memset(&brcmstb_pdata, 0, sizeof(brcmstb_pdata));
brcmstb_pdata.ops = match_priv->ops;
host = sdhci_pltfm_init(pdev, &brcmstb_pdata,
sizeof(struct sdhci_brcmstb_priv));
if (IS_ERR(host)) {
res = PTR_ERR(host);
goto err_clk;
}
if (IS_ERR(host))
return PTR_ERR(host);
pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host);
@ -369,9 +363,7 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
err:
sdhci_pltfm_free(pdev);
err_clk:
clk_disable_unprepare(base_clk);
clk_disable_unprepare(clk);
return res;
}
@ -430,7 +422,7 @@ static struct platform_driver sdhci_brcmstb_driver = {
.of_match_table = of_match_ptr(sdhci_brcm_of_match),
},
.probe = sdhci_brcmstb_probe,
.remove = sdhci_pltfm_unregister,
.remove_new = sdhci_pltfm_remove,
.shutdown = sdhci_brcmstb_shutdown,
};

View file

@ -11,7 +11,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include "sdhci-pltfm.h"
@ -487,14 +487,10 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
static const u16 version = SDHCI_SPEC_400 << SDHCI_SPEC_VER_SHIFT;
clk = devm_clk_get(dev, NULL);
clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(clk))
return PTR_ERR(clk);
ret = clk_prepare_enable(clk);
if (ret)
return ret;
data = of_device_get_match_data(dev);
if (!data)
data = &sdhci_cdns_drv_data;
@ -502,10 +498,8 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
nr_phy_params = sdhci_cdns_phy_param_count(dev->of_node);
host = sdhci_pltfm_init(pdev, &data->pltfm_data,
struct_size(priv, phy_params, nr_phy_params));
if (IS_ERR(host)) {
ret = PTR_ERR(host);
goto disable_clk;
}
if (IS_ERR(host))
return PTR_ERR(host);
pltfm_host = sdhci_priv(host);
pltfm_host->clk = clk;
@ -556,9 +550,6 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
return 0;
free:
sdhci_pltfm_free(pdev);
disable_clk:
clk_disable_unprepare(clk);
return ret;
}
@ -617,7 +608,7 @@ static struct platform_driver sdhci_cdns_driver = {
.of_match_table = sdhci_cdns_match,
},
.probe = sdhci_cdns_probe,
.remove = sdhci_pltfm_unregister,
.remove_new = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_cdns_driver);

View file

@ -75,10 +75,7 @@ static int sdhci_dove_probe(struct platform_device *pdev)
return PTR_ERR(host);
pltfm_host = sdhci_priv(host);
pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
if (!IS_ERR(pltfm_host->clk))
clk_prepare_enable(pltfm_host->clk);
pltfm_host->clk = devm_clk_get_enabled(&pdev->dev, NULL);
ret = mmc_of_parse(host->mmc);
if (ret)
@ -91,7 +88,6 @@ static int sdhci_dove_probe(struct platform_device *pdev)
return 0;
err_sdhci_add:
clk_disable_unprepare(pltfm_host->clk);
sdhci_pltfm_free(pdev);
return ret;
}
@ -110,7 +106,7 @@ static struct platform_driver sdhci_dove_driver = {
.of_match_table = sdhci_dove_of_match_table,
},
.probe = sdhci_dove_probe,
.remove = sdhci_pltfm_unregister,
.remove_new = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_dove_driver);

View file

@ -22,7 +22,7 @@
#include <linux/mmc/sdio.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include "sdhci-cqhci.h"
@ -171,8 +171,8 @@
#define ESDHC_FLAG_HS400 BIT(9)
/*
* The IP has errata ERR010450
* uSDHC: Due to the I/O timing limit, for SDR mode, SD card clock can't
* exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz.
* uSDHC: At 1.8V due to the I/O timing limit, for SDR mode, SD card
* clock can't exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz.
*/
#define ESDHC_FLAG_ERR010450 BIT(10)
/* The IP supports HS400ES mode */
@ -961,7 +961,8 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
| ESDHC_CLOCK_MASK);
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) {
if ((imx_data->socdata->flags & ESDHC_FLAG_ERR010450) &&
(!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V))) {
unsigned int max_clock;
max_clock = imx_data->is_ddr ? 45000000 : 150000000;
@ -1802,7 +1803,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
return err;
}
static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
static void sdhci_esdhc_imx_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -1824,8 +1825,6 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
cpu_latency_qos_remove_request(&imx_data->pm_qos_req);
sdhci_pltfm_free(pdev);
return 0;
}
#ifdef CONFIG_PM_SLEEP
@ -1986,7 +1985,7 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
.pm = &sdhci_esdhc_pmops,
},
.probe = sdhci_esdhc_imx_probe,
.remove = sdhci_esdhc_imx_remove,
.remove_new = sdhci_esdhc_imx_remove,
};
module_platform_driver(sdhci_esdhc_imx_driver);

View file

@ -489,7 +489,7 @@ static int sdhci_esdhc_mcf_probe(struct platform_device *pdev)
return err;
}
static int sdhci_esdhc_mcf_remove(struct platform_device *pdev)
static void sdhci_esdhc_mcf_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -502,8 +502,6 @@ static int sdhci_esdhc_mcf_remove(struct platform_device *pdev)
clk_disable_unprepare(mcf_data->clk_per);
sdhci_pltfm_free(pdev);
return 0;
}
static struct platform_driver sdhci_esdhc_mcf_driver = {
@ -512,7 +510,7 @@ static struct platform_driver sdhci_esdhc_mcf_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = sdhci_esdhc_mcf_probe,
.remove = sdhci_esdhc_mcf_remove,
.remove_new = sdhci_esdhc_mcf_remove,
};
module_platform_driver(sdhci_esdhc_mcf_driver);

View file

@ -10,7 +10,7 @@
#include <linux/module.h>
#include <linux/mmc/host.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "sdhci-pltfm.h"
struct sdhci_iproc_data {
@ -386,16 +386,11 @@ static int sdhci_iproc_probe(struct platform_device *pdev)
host->mmc->caps |= iproc_host->data->mmc_caps;
if (dev->of_node) {
pltfm_host->clk = devm_clk_get(dev, NULL);
pltfm_host->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(pltfm_host->clk)) {
ret = PTR_ERR(pltfm_host->clk);
goto err;
}
ret = clk_prepare_enable(pltfm_host->clk);
if (ret) {
dev_err(dev, "failed to enable host clk\n");
goto err;
}
}
if (iproc_host->data->missing_caps) {
@ -406,13 +401,10 @@ static int sdhci_iproc_probe(struct platform_device *pdev)
ret = sdhci_add_host(host);
if (ret)
goto err_clk;
goto err;
return 0;
err_clk:
if (dev->of_node)
clk_disable_unprepare(pltfm_host->clk);
err:
sdhci_pltfm_free(pdev);
return ret;
@ -432,7 +424,7 @@ static struct platform_driver sdhci_iproc_driver = {
.pm = &sdhci_pltfm_pmops,
},
.probe = sdhci_iproc_probe,
.remove = sdhci_pltfm_unregister,
.remove_new = sdhci_pltfm_remove,
.shutdown = sdhci_iproc_shutdown,
};
module_platform_driver(sdhci_iproc_driver);

View file

@ -313,7 +313,7 @@ static int sdhci_milbeaut_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_milbeaut_remove(struct platform_device *pdev)
static void sdhci_milbeaut_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct f_sdhost_priv *priv = sdhci_priv(host);
@ -326,18 +326,16 @@ static int sdhci_milbeaut_remove(struct platform_device *pdev)
sdhci_free_host(host);
platform_set_drvdata(pdev, NULL);
return 0;
}
static struct platform_driver sdhci_milbeaut_driver = {
.driver = {
.name = "sdhci-milbeaut",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = of_match_ptr(mlb_dt_ids),
.of_match_table = mlb_dt_ids,
},
.probe = sdhci_milbeaut_probe,
.remove = sdhci_milbeaut_remove,
.remove_new = sdhci_milbeaut_remove,
};
module_platform_driver(sdhci_milbeaut_driver);

View file

@ -6,7 +6,6 @@
*/
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/delay.h>
#include <linux/mmc/mmc.h>
#include <linux/pm_runtime.h>
@ -15,6 +14,7 @@
#include <linux/iopoll.h>
#include <linux/regulator/consumer.h>
#include <linux/interconnect.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/reset.h>
@ -2668,7 +2668,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_msm_remove(struct platform_device *pdev)
static void sdhci_msm_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -2687,7 +2687,6 @@ static int sdhci_msm_remove(struct platform_device *pdev)
if (!IS_ERR(msm_host->bus_clk))
clk_disable_unprepare(msm_host->bus_clk);
sdhci_pltfm_free(pdev);
return 0;
}
static __maybe_unused int sdhci_msm_runtime_suspend(struct device *dev)
@ -2740,7 +2739,7 @@ static const struct dev_pm_ops sdhci_msm_pm_ops = {
static struct platform_driver sdhci_msm_driver = {
.probe = sdhci_msm_probe,
.remove = sdhci_msm_remove,
.remove_new = sdhci_msm_remove,
.driver = {
.name = "sdhci_msm",
.of_match_table = sdhci_msm_dt_match,

View file

@ -18,11 +18,11 @@
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/of.h>
#include <linux/firmware/xlnx-zynqmp.h>
#include "cqhci.h"
@ -2016,12 +2016,13 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_arasan_remove(struct platform_device *pdev)
static void sdhci_arasan_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
struct clk *clk_ahb = sdhci_arasan->clk_ahb;
struct clk *clk_xin = pltfm_host->clk;
if (!IS_ERR(sdhci_arasan->phy)) {
if (sdhci_arasan->is_phy_on)
@ -2031,11 +2032,10 @@ static int sdhci_arasan_remove(struct platform_device *pdev)
sdhci_arasan_unregister_sdclk(&pdev->dev);
sdhci_pltfm_unregister(pdev);
sdhci_pltfm_remove(pdev);
clk_disable_unprepare(clk_xin);
clk_disable_unprepare(clk_ahb);
return 0;
}
static struct platform_driver sdhci_arasan_driver = {
@ -2046,7 +2046,7 @@ static struct platform_driver sdhci_arasan_driver = {
.pm = &sdhci_arasan_dev_pm_ops,
},
.probe = sdhci_arasan_probe,
.remove = sdhci_arasan_remove,
.remove_new = sdhci_arasan_remove,
};
module_platform_driver(sdhci_arasan_driver);

View file

@ -450,22 +450,19 @@ static int aspeed_sdhci_probe(struct platform_device *pdev)
return ret;
}
static int aspeed_sdhci_remove(struct platform_device *pdev)
static void aspeed_sdhci_remove(struct platform_device *pdev)
{
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_host *host;
int dead = 0;
host = platform_get_drvdata(pdev);
pltfm_host = sdhci_priv(host);
sdhci_remove_host(host, dead);
sdhci_remove_host(host, 0);
clk_disable_unprepare(pltfm_host->clk);
sdhci_pltfm_free(pdev);
return 0;
}
static const struct aspeed_sdhci_pdata ast2400_sdhci_pdata = {
@ -521,7 +518,7 @@ static struct platform_driver aspeed_sdhci_driver = {
.of_match_table = aspeed_sdhci_of_match,
},
.probe = aspeed_sdhci_probe,
.remove = aspeed_sdhci_remove,
.remove_new = aspeed_sdhci_remove,
};
static int aspeed_sdc_probe(struct platform_device *pdev)
@ -574,13 +571,11 @@ static int aspeed_sdc_probe(struct platform_device *pdev)
return ret;
}
static int aspeed_sdc_remove(struct platform_device *pdev)
static void aspeed_sdc_remove(struct platform_device *pdev)
{
struct aspeed_sdc *sdc = dev_get_drvdata(&pdev->dev);
clk_disable_unprepare(sdc->clk);
return 0;
}
static const struct of_device_id aspeed_sdc_of_match[] = {
@ -600,7 +595,7 @@ static struct platform_driver aspeed_sdc_driver = {
.of_match_table = aspeed_sdc_of_match,
},
.probe = aspeed_sdc_probe,
.remove = aspeed_sdc_remove,
.remove_new = aspeed_sdc_remove,
};
#if defined(CONFIG_MMC_SDHCI_OF_ASPEED_TEST)

View file

@ -17,7 +17,7 @@
#include <linux/mmc/slot-gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
@ -443,7 +443,7 @@ static int sdhci_at91_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_at91_remove(struct platform_device *pdev)
static void sdhci_at91_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -456,13 +456,11 @@ static int sdhci_at91_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
sdhci_pltfm_unregister(pdev);
sdhci_pltfm_remove(pdev);
clk_disable_unprepare(gck);
clk_disable_unprepare(hclock);
clk_disable_unprepare(mainck);
return 0;
}
static struct platform_driver sdhci_at91_driver = {
@ -473,7 +471,7 @@ static struct platform_driver sdhci_at91_driver = {
.pm = &sdhci_at91_dev_pm_ops,
},
.probe = sdhci_at91_probe,
.remove = sdhci_at91_remove,
.remove_new = sdhci_at91_remove,
};
module_platform_driver(sdhci_at91_driver);

View file

@ -14,7 +14,8 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/sizes.h>
@ -548,9 +549,13 @@ static int dwcmshc_probe(struct platform_device *pdev)
host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
err = sdhci_setup_host(host);
if (err)
goto err_clk;
goto err_rpm;
if (rk_priv)
dwcmshc_rk35xx_postinit(host, priv);
@ -559,10 +564,15 @@ static int dwcmshc_probe(struct platform_device *pdev)
if (err)
goto err_setup_host;
pm_runtime_put(dev);
return 0;
err_setup_host:
sdhci_cleanup_host(host);
err_rpm:
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
err_clk:
clk_disable_unprepare(pltfm_host->clk);
clk_disable_unprepare(priv->bus_clk);
@ -574,7 +584,7 @@ static int dwcmshc_probe(struct platform_device *pdev)
return err;
}
static int dwcmshc_remove(struct platform_device *pdev)
static void dwcmshc_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -589,8 +599,6 @@ static int dwcmshc_remove(struct platform_device *pdev)
clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
rk_priv->rockchip_clks);
sdhci_pltfm_free(pdev);
return 0;
}
#ifdef CONFIG_PM_SLEEP
@ -602,6 +610,8 @@ static int dwcmshc_suspend(struct device *dev)
struct rk35xx_priv *rk_priv = priv->priv;
int ret;
pm_runtime_resume(dev);
ret = sdhci_suspend_host(host);
if (ret)
return ret;
@ -632,21 +642,84 @@ static int dwcmshc_resume(struct device *dev)
if (!IS_ERR(priv->bus_clk)) {
ret = clk_prepare_enable(priv->bus_clk);
if (ret)
return ret;
goto disable_clk;
}
if (rk_priv) {
ret = clk_bulk_prepare_enable(RK35xx_MAX_CLKS,
rk_priv->rockchip_clks);
if (ret)
return ret;
goto disable_bus_clk;
}
return sdhci_resume_host(host);
ret = sdhci_resume_host(host);
if (ret)
goto disable_rockchip_clks;
return 0;
disable_rockchip_clks:
if (rk_priv)
clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
rk_priv->rockchip_clks);
disable_bus_clk:
if (!IS_ERR(priv->bus_clk))
clk_disable_unprepare(priv->bus_clk);
disable_clk:
clk_disable_unprepare(pltfm_host->clk);
return ret;
}
#endif
static SIMPLE_DEV_PM_OPS(dwcmshc_pmops, dwcmshc_suspend, dwcmshc_resume);
#ifdef CONFIG_PM
static void dwcmshc_enable_card_clk(struct sdhci_host *host)
{
u16 ctrl;
ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
if ((ctrl & SDHCI_CLOCK_INT_EN) && !(ctrl & SDHCI_CLOCK_CARD_EN)) {
ctrl |= SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL);
}
}
static void dwcmshc_disable_card_clk(struct sdhci_host *host)
{
u16 ctrl;
ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
if (ctrl & SDHCI_CLOCK_CARD_EN) {
ctrl &= ~SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL);
}
}
static int dwcmshc_runtime_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
dwcmshc_disable_card_clk(host);
return 0;
}
static int dwcmshc_runtime_resume(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
dwcmshc_enable_card_clk(host);
return 0;
}
#endif
static const struct dev_pm_ops dwcmshc_pmops = {
SET_SYSTEM_SLEEP_PM_OPS(dwcmshc_suspend, dwcmshc_resume)
SET_RUNTIME_PM_OPS(dwcmshc_runtime_suspend,
dwcmshc_runtime_resume, NULL)
};
static struct platform_driver sdhci_dwcmshc_driver = {
.driver = {
@ -657,7 +730,7 @@ static struct platform_driver sdhci_dwcmshc_driver = {
.pm = &dwcmshc_pmops,
},
.probe = dwcmshc_probe,
.remove = dwcmshc_remove,
.remove_new = dwcmshc_remove,
};
module_platform_driver(sdhci_dwcmshc_driver);

View file

@ -1521,7 +1521,7 @@ static struct platform_driver sdhci_esdhc_driver = {
.pm = &esdhc_of_dev_pm_ops,
},
.probe = sdhci_esdhc_probe,
.remove = sdhci_pltfm_unregister,
.remove_new = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_esdhc_driver);

View file

@ -68,7 +68,7 @@ static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
static int sdhci_hlwd_probe(struct platform_device *pdev)
{
return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata, 0);
return sdhci_pltfm_init_and_add_host(pdev, &sdhci_hlwd_pdata, 0);
}
static const struct of_device_id sdhci_hlwd_of_match[] = {
@ -85,7 +85,7 @@ static struct platform_driver sdhci_hlwd_driver = {
.pm = &sdhci_pltfm_pmops,
},
.probe = sdhci_hlwd_probe,
.remove = sdhci_pltfm_unregister,
.remove_new = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_hlwd_driver);

View file

@ -13,9 +13,9 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/of_device.h>
#include <linux/mfd/syscon.h>
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include "sdhci-pltfm.h"
@ -184,15 +184,12 @@ static int sdhci_sparx5_probe(struct platform_device *pdev)
sdhci_sparx5 = sdhci_pltfm_priv(pltfm_host);
sdhci_sparx5->host = host;
pltfm_host->clk = devm_clk_get(&pdev->dev, "core");
pltfm_host->clk = devm_clk_get_enabled(&pdev->dev, "core");
if (IS_ERR(pltfm_host->clk)) {
ret = PTR_ERR(pltfm_host->clk);
dev_err(&pdev->dev, "failed to get core clk: %d\n", ret);
dev_err(&pdev->dev, "failed to get and enable core clk: %d\n", ret);
goto free_pltfm;
}
ret = clk_prepare_enable(pltfm_host->clk);
if (ret)
goto free_pltfm;
if (!of_property_read_u32(np, "microchip,clock-delay", &value) &&
(value > 0 && value <= MSHC_DLY_CC_MAX))
@ -202,13 +199,13 @@ static int sdhci_sparx5_probe(struct platform_device *pdev)
ret = mmc_of_parse(host->mmc);
if (ret)
goto err_clk;
goto free_pltfm;
sdhci_sparx5->cpu_ctrl = syscon_regmap_lookup_by_compatible(syscon);
if (IS_ERR(sdhci_sparx5->cpu_ctrl)) {
dev_err(&pdev->dev, "No CPU syscon regmap !\n");
ret = PTR_ERR(sdhci_sparx5->cpu_ctrl);
goto err_clk;
goto free_pltfm;
}
if (sdhci_sparx5->delay_clock >= 0)
@ -225,7 +222,7 @@ static int sdhci_sparx5_probe(struct platform_device *pdev)
ret = sdhci_add_host(host);
if (ret)
goto err_clk;
goto free_pltfm;
/* Set AXI bus master to use un-cached access (for DMA) */
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA) &&
@ -239,8 +236,6 @@ static int sdhci_sparx5_probe(struct platform_device *pdev)
return ret;
err_clk:
clk_disable_unprepare(pltfm_host->clk);
free_pltfm:
sdhci_pltfm_free(pdev);
return ret;
@ -260,7 +255,7 @@ static struct platform_driver sdhci_sparx5_driver = {
.pm = &sdhci_pltfm_pmops,
},
.probe = sdhci_sparx5_probe,
.remove = sdhci_pltfm_unregister,
.remove_new = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_sparx5_driver);

View file

@ -11,7 +11,6 @@
#include <linux/mmc/slot-gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@ -1394,7 +1393,7 @@ static int sdhci_omap_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_omap_remove(struct platform_device *pdev)
static void sdhci_omap_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct sdhci_host *host = platform_get_drvdata(pdev);
@ -1408,8 +1407,6 @@ static int sdhci_omap_remove(struct platform_device *pdev)
/* Ensure device gets disabled despite userspace sysfs config */
pm_runtime_force_suspend(dev);
sdhci_pltfm_free(pdev);
return 0;
}
#ifdef CONFIG_PM
@ -1478,7 +1475,7 @@ static const struct dev_pm_ops sdhci_omap_dev_pm_ops = {
static struct platform_driver sdhci_omap_driver = {
.probe = sdhci_omap_probe,
.remove = sdhci_omap_remove,
.remove_new = sdhci_omap_remove,
.driver = {
.name = "sdhci-omap",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -1898,6 +1898,10 @@ static const struct pci_device_id pci_ids[] = {
SDHCI_PCI_DEVICE(O2, SDS1, o2),
SDHCI_PCI_DEVICE(O2, SEABIRD0, o2),
SDHCI_PCI_DEVICE(O2, SEABIRD1, o2),
SDHCI_PCI_DEVICE(O2, GG8_9860, o2),
SDHCI_PCI_DEVICE(O2, GG8_9861, o2),
SDHCI_PCI_DEVICE(O2, GG8_9862, o2),
SDHCI_PCI_DEVICE(O2, GG8_9863, o2),
SDHCI_PCI_DEVICE(ARASAN, PHY_EMMC, arasan),
SDHCI_PCI_DEVICE(SYNOPSYS, DWC_MSHC, snps),
SDHCI_PCI_DEVICE(GLI, 9750, gl9750),

View file

@ -21,6 +21,7 @@
* O2Micro device registers
*/
#define O2_SD_PCIE_SWITCH 0x54
#define O2_SD_MISC_REG5 0x64
#define O2_SD_LD0_CTRL 0x68
#define O2_SD_DEV_CTRL 0x88
@ -36,6 +37,7 @@
#define O2_SD_INF_MOD 0xF1
#define O2_SD_MISC_CTRL4 0xFC
#define O2_SD_MISC_CTRL 0x1C0
#define O2_SD_EXP_INT_REG 0x1E0
#define O2_SD_PWR_FORCE_L0 0x0002
#define O2_SD_TUNING_CTRL 0x300
#define O2_SD_PLL_SETTING 0x304
@ -49,6 +51,9 @@
#define O2_SD_UHS2_L1_CTRL 0x35C
#define O2_SD_FUNC_REG3 0x3E0
#define O2_SD_FUNC_REG4 0x3E4
#define O2_SD_PARA_SET_REG1 0x444
#define O2_SD_VDDX_CTRL_REG 0x508
#define O2_SD_GPIO_CTRL_REG1 0x510
#define O2_SD_LED_ENABLE BIT(6)
#define O2_SD_FREG0_LEDOFF BIT(13)
#define O2_SD_SEL_DLL BIT(16)
@ -334,33 +339,45 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
scratch |= O2_SD_PWR_FORCE_L0;
sdhci_writew(host, scratch, O2_SD_MISC_CTRL);
/* Stop clk */
reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
reg_val &= ~SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL);
/* Update output phase */
switch (chip->pdev->device) {
case PCI_DEVICE_ID_O2_SDS0:
case PCI_DEVICE_ID_O2_SEABIRD0:
case PCI_DEVICE_ID_O2_SEABIRD1:
case PCI_DEVICE_ID_O2_SDS1:
case PCI_DEVICE_ID_O2_FUJIN2:
/* Stop clk */
reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
reg_val &= ~SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL);
if ((host->timing == MMC_TIMING_MMC_HS200) ||
(host->timing == MMC_TIMING_UHS_SDR104)) {
/* UnLock WP */
pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
scratch_8 &= 0x7f;
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
if (host->timing == MMC_TIMING_MMC_HS200 ||
host->timing == MMC_TIMING_UHS_SDR104) {
/* UnLock WP */
pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
scratch_8 &= 0x7f;
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
/* Set pcr 0x354[16] to choose dll clock, and set the default phase */
pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &reg_val);
reg_val &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK);
reg_val |= (O2_SD_SEL_DLL | O2_SD_FIX_PHASE);
pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, reg_val);
/* Set pcr 0x354[16] to choose dll clock, and set the default phase */
pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &reg_val);
reg_val &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK);
reg_val |= (O2_SD_SEL_DLL | O2_SD_FIX_PHASE);
pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, reg_val);
/* Lock WP */
pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
scratch_8 |= 0x80;
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
/* Lock WP */
pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8);
scratch_8 |= 0x80;
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8);
}
/* Start clk */
reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
reg_val |= SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL);
break;
default:
break;
}
/* Start clk */
reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
reg_val |= SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL);
/* wait DLL lock, timeout value 5ms */
if (readx_poll_timeout(sdhci_o2_pll_dll_wdt_control, host,
@ -563,6 +580,7 @@ static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock)
u16 clk;
u8 scratch;
u32 scratch_32;
u32 dmdn_208m, dmdn_200m;
struct sdhci_pci_slot *slot = sdhci_priv(host);
struct sdhci_pci_chip *chip = slot->chip;
@ -578,16 +596,27 @@ static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock)
scratch &= 0x7f;
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
if (chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9860 ||
chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9861 ||
chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9862 ||
chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9863) {
dmdn_208m = 0x2c500000;
dmdn_200m = 0x25200000;
} else {
dmdn_208m = 0x2c280000;
dmdn_200m = 0x25100000;
}
if ((host->timing == MMC_TIMING_UHS_SDR104) && (clock == 200000000)) {
pci_read_config_dword(chip->pdev, O2_SD_PLL_SETTING, &scratch_32);
if ((scratch_32 & 0xFFFF0000) != 0x2c280000)
o2_pci_set_baseclk(chip, 0x2c280000);
if ((scratch_32 & 0xFFFF0000) != dmdn_208m)
o2_pci_set_baseclk(chip, dmdn_208m);
} else {
pci_read_config_dword(chip->pdev, O2_SD_PLL_SETTING, &scratch_32);
if ((scratch_32 & 0xFFFF0000) != 0x25100000)
o2_pci_set_baseclk(chip, 0x25100000);
if ((scratch_32 & 0xFFFF0000) != dmdn_200m)
o2_pci_set_baseclk(chip, dmdn_200m);
}
pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32);
@ -603,6 +632,67 @@ static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock)
sdhci_o2_enable_clk(host, clk);
}
static int sdhci_pci_o2_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct sdhci_host *host = mmc_priv(mmc);
struct sdhci_pci_slot *slot = sdhci_priv(host);
struct sdhci_pci_chip *chip = slot->chip;
u8 scratch8;
u16 scratch16;
int ret;
/* Disable clock */
sdhci_writeb(host, 0, SDHCI_CLOCK_CONTROL);
/* Set VDD2 voltage*/
scratch8 = sdhci_readb(host, SDHCI_POWER_CONTROL);
scratch8 &= 0x0F;
if (host->mmc->ios.timing == MMC_TIMING_SD_EXP_1_2V &&
host->mmc->caps2 & MMC_CAP2_SD_EXP_1_2V) {
scratch8 |= SDHCI_VDD2_POWER_ON | SDHCI_VDD2_POWER_120;
} else {
scratch8 |= SDHCI_VDD2_POWER_ON | SDHCI_VDD2_POWER_180;
}
sdhci_writeb(host, scratch8, SDHCI_POWER_CONTROL);
/* UnLock WP */
pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch8);
scratch8 &= 0x7f;
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch8);
/* Wait for express card clkreqn assert */
ret = read_poll_timeout(sdhci_readb, scratch8, !(scratch8 & BIT(0)),
1, 30000, false, host, O2_SD_EXP_INT_REG);
if (!ret) {
/* Switch to PCIe mode */
scratch16 = sdhci_readw(host, O2_SD_PCIE_SWITCH);
scratch16 |= BIT(8);
sdhci_writew(host, scratch16, O2_SD_PCIE_SWITCH);
} else {
/* Power off VDD2 voltage*/
scratch8 = sdhci_readb(host, SDHCI_POWER_CONTROL);
scratch8 &= 0x0F;
sdhci_writeb(host, scratch8, SDHCI_POWER_CONTROL);
/* Keep mode as UHSI */
pci_read_config_word(chip->pdev, O2_SD_PARA_SET_REG1, &scratch16);
scratch16 &= ~BIT(11);
pci_write_config_word(chip->pdev, O2_SD_PARA_SET_REG1, scratch16);
host->mmc->ios.timing = MMC_TIMING_LEGACY;
pr_info("%s: Express card initialization failed, falling back to Legacy\n",
mmc_hostname(host->mmc));
}
/* Lock WP */
pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch8);
scratch8 |= 0x80;
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch8);
return 0;
}
static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
{
struct sdhci_pci_chip *chip;
@ -624,6 +714,11 @@ static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
if (caps & SDHCI_CAN_DO_8BIT)
host->mmc->caps |= MMC_CAP_8_BIT_DATA;
host->quirks2 |= SDHCI_QUIRK2_BROKEN_DDR50;
sdhci_pci_o2_enable_msi(chip, host);
host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning;
switch (chip->pdev->device) {
case PCI_DEVICE_ID_O2_SDS0:
case PCI_DEVICE_ID_O2_SEABIRD0:
@ -634,10 +729,6 @@ static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
if (reg & 0x1)
host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
host->quirks2 |= SDHCI_QUIRK2_BROKEN_DDR50;
sdhci_pci_o2_enable_msi(chip, host);
if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) {
ret = pci_read_config_dword(chip->pdev,
O2_SD_MISC_SETTING, &reg);
@ -663,15 +754,22 @@ static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
}
host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning;
if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
break;
/* set dll watch dog timer */
reg = sdhci_readl(host, O2_SD_VENDOR_SETTING2);
reg |= (1 << 12);
sdhci_writel(host, reg, O2_SD_VENDOR_SETTING2);
break;
case PCI_DEVICE_ID_O2_GG8_9860:
case PCI_DEVICE_ID_O2_GG8_9861:
case PCI_DEVICE_ID_O2_GG8_9862:
case PCI_DEVICE_ID_O2_GG8_9863:
host->mmc->caps2 |= MMC_CAP2_NO_SDIO | MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V;
host->mmc->caps |= MMC_CAP_HW_RESET;
host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd;
host->mmc_host_ops.init_sd_express = sdhci_pci_o2_init_sd_express;
break;
default:
break;
@ -684,6 +782,7 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
{
int ret;
u8 scratch;
u16 scratch16;
u32 scratch_32;
switch (chip->pdev->device) {
@ -893,6 +992,46 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
scratch |= 0x80;
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
break;
case PCI_DEVICE_ID_O2_GG8_9860:
case PCI_DEVICE_ID_O2_GG8_9861:
case PCI_DEVICE_ID_O2_GG8_9862:
case PCI_DEVICE_ID_O2_GG8_9863:
/* UnLock WP */
ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch);
if (ret)
return ret;
scratch &= 0x7f;
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
/* Select mode switch source as software control */
pci_read_config_word(chip->pdev, O2_SD_PARA_SET_REG1, &scratch16);
scratch16 &= 0xF8FF;
scratch16 |= BIT(9);
pci_write_config_word(chip->pdev, O2_SD_PARA_SET_REG1, scratch16);
/* set VDD1 supply source */
pci_read_config_word(chip->pdev, O2_SD_VDDX_CTRL_REG, &scratch16);
scratch16 &= 0xFFE3;
scratch16 |= BIT(3);
pci_write_config_word(chip->pdev, O2_SD_VDDX_CTRL_REG, scratch16);
/* Set host drive strength*/
scratch16 = 0x0025;
pci_write_config_word(chip->pdev, O2_SD_PLL_SETTING, scratch16);
/* Set output delay*/
pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32);
scratch_32 &= 0xFF0FFF00;
scratch_32 |= 0x00B0003B;
pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, scratch_32);
/* Lock WP */
ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch);
if (ret)
return ret;
scratch |= 0x80;
pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
break;
}
return 0;

View file

@ -11,6 +11,10 @@
#define PCI_DEVICE_ID_O2_FUJIN2 0x8520
#define PCI_DEVICE_ID_O2_SEABIRD0 0x8620
#define PCI_DEVICE_ID_O2_SEABIRD1 0x8621
#define PCI_DEVICE_ID_O2_GG8_9860 0x9860
#define PCI_DEVICE_ID_O2_GG8_9861 0x9861
#define PCI_DEVICE_ID_O2_GG8_9862 0x9862
#define PCI_DEVICE_ID_O2_GG8_9863 0x9863
#define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809
#define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a

View file

@ -210,7 +210,7 @@ static int pic32_sdhci_probe(struct platform_device *pdev)
return ret;
}
static int pic32_sdhci_remove(struct platform_device *pdev)
static void pic32_sdhci_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct pic32_sdhci_priv *sdhci_pdata = sdhci_priv(host);
@ -221,8 +221,6 @@ static int pic32_sdhci_remove(struct platform_device *pdev)
clk_disable_unprepare(sdhci_pdata->base_clk);
clk_disable_unprepare(sdhci_pdata->sys_clk);
sdhci_pltfm_free(pdev);
return 0;
}
static const struct of_device_id pic32_sdhci_id_table[] = {
@ -238,7 +236,7 @@ static struct platform_driver pic32_sdhci_driver = {
.of_match_table = of_match_ptr(pic32_sdhci_id_table),
},
.probe = pic32_sdhci_probe,
.remove = pic32_sdhci_remove,
.remove_new = pic32_sdhci_remove,
};
module_platform_driver(pic32_sdhci_driver);

View file

@ -166,9 +166,9 @@ void sdhci_pltfm_free(struct platform_device *pdev)
}
EXPORT_SYMBOL_GPL(sdhci_pltfm_free);
int sdhci_pltfm_register(struct platform_device *pdev,
const struct sdhci_pltfm_data *pdata,
size_t priv_size)
int sdhci_pltfm_init_and_add_host(struct platform_device *pdev,
const struct sdhci_pltfm_data *pdata,
size_t priv_size)
{
struct sdhci_host *host;
int ret = 0;
@ -185,21 +185,17 @@ int sdhci_pltfm_register(struct platform_device *pdev,
return ret;
}
EXPORT_SYMBOL_GPL(sdhci_pltfm_register);
EXPORT_SYMBOL_GPL(sdhci_pltfm_init_and_add_host);
int sdhci_pltfm_unregister(struct platform_device *pdev)
void sdhci_pltfm_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
sdhci_remove_host(host, dead);
clk_disable_unprepare(pltfm_host->clk);
sdhci_pltfm_free(pdev);
return 0;
}
EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister);
EXPORT_SYMBOL_GPL(sdhci_pltfm_remove);
#ifdef CONFIG_PM_SLEEP
int sdhci_pltfm_suspend(struct device *dev)

View file

@ -99,10 +99,10 @@ extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
size_t priv_size);
extern void sdhci_pltfm_free(struct platform_device *pdev);
extern int sdhci_pltfm_register(struct platform_device *pdev,
const struct sdhci_pltfm_data *pdata,
size_t priv_size);
extern int sdhci_pltfm_unregister(struct platform_device *pdev);
extern int sdhci_pltfm_init_and_add_host(struct platform_device *pdev,
const struct sdhci_pltfm_data *pdata,
size_t priv_size);
extern void sdhci_pltfm_remove(struct platform_device *pdev);
extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host);

View file

@ -19,7 +19,6 @@
#include <linux/platform_data/pxa_sdhci.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/mmc.h>
#include <linux/pinctrl/consumer.h>
@ -269,26 +268,21 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(host);
pxav2_host = sdhci_pltfm_priv(pltfm_host);
clk = devm_clk_get(dev, "io");
if (IS_ERR(clk) && PTR_ERR(clk) != -EPROBE_DEFER)
clk = devm_clk_get(dev, NULL);
clk = devm_clk_get_optional_enabled(dev, "io");
if (!clk)
clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
dev_err_probe(dev, ret, "failed to get io clock\n");
goto free;
}
pltfm_host->clk = clk;
ret = clk_prepare_enable(clk);
if (ret) {
dev_err(dev, "failed to enable io clock\n");
goto free;
}
clk_core = devm_clk_get_optional_enabled(dev, "core");
if (IS_ERR(clk_core)) {
ret = PTR_ERR(clk_core);
dev_err_probe(dev, ret, "failed to enable core clock\n");
goto disable_clk;
goto free;
}
host->quirks = SDHCI_QUIRK_BROKEN_ADMA
@ -340,12 +334,10 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
ret = sdhci_add_host(host);
if (ret)
goto disable_clk;
goto free;
return 0;
disable_clk:
clk_disable_unprepare(clk);
free:
sdhci_pltfm_free(pdev);
return ret;
@ -359,7 +351,7 @@ static struct platform_driver sdhci_pxav2_driver = {
.pm = &sdhci_pltfm_pmops,
},
.probe = sdhci_pxav2_probe,
.remove = sdhci_pltfm_unregister,
.remove_new = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_pxav2_driver);

View file

@ -470,7 +470,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_pxav3_remove(struct platform_device *pdev)
static void sdhci_pxav3_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -486,8 +486,6 @@ static int sdhci_pxav3_remove(struct platform_device *pdev)
clk_disable_unprepare(pxa->clk_core);
sdhci_pltfm_free(pdev);
return 0;
}
#ifdef CONFIG_PM_SLEEP
@ -570,7 +568,7 @@ static struct platform_driver sdhci_pxav3_driver = {
.pm = &sdhci_pxav3_pmops,
},
.probe = sdhci_pxav3_probe,
.remove = sdhci_pxav3_remove,
.remove_new = sdhci_pxav3_remove,
};
module_platform_driver(sdhci_pxav3_driver);

View file

@ -20,7 +20,6 @@
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
@ -668,7 +667,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_s3c_remove(struct platform_device *pdev)
static void sdhci_s3c_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_s3c *sc = sdhci_priv(host);
@ -688,8 +687,6 @@ static int sdhci_s3c_remove(struct platform_device *pdev)
clk_disable_unprepare(sc->clk_io);
sdhci_free_host(host);
return 0;
}
#ifdef CONFIG_PM_SLEEP
@ -776,7 +773,7 @@ MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match);
static struct platform_driver sdhci_s3c_driver = {
.probe = sdhci_s3c_probe,
.remove = sdhci_s3c_remove,
.remove_new = sdhci_s3c_remove,
.id_table = sdhci_s3c_driver_ids,
.driver = {
.name = "s3c-sdhci",

View file

@ -117,7 +117,7 @@ static int sdhci_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_remove(struct platform_device *pdev)
static void sdhci_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct spear_sdhci *sdhci = sdhci_priv(host);
@ -131,8 +131,6 @@ static int sdhci_remove(struct platform_device *pdev)
sdhci_remove_host(host, dead);
clk_disable_unprepare(sdhci->clk);
sdhci_free_host(host);
return 0;
}
#ifdef CONFIG_PM_SLEEP
@ -170,23 +168,21 @@ static int sdhci_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(sdhci_pm_ops, sdhci_suspend, sdhci_resume);
#ifdef CONFIG_OF
static const struct of_device_id sdhci_spear_id_table[] = {
{ .compatible = "st,spear300-sdhci" },
{}
};
MODULE_DEVICE_TABLE(of, sdhci_spear_id_table);
#endif
static struct platform_driver sdhci_driver = {
.driver = {
.name = "sdhci",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.pm = &sdhci_pm_ops,
.of_match_table = of_match_ptr(sdhci_spear_id_table),
.of_match_table = sdhci_spear_id_table,
},
.probe = sdhci_probe,
.remove = sdhci_remove,
.remove_new = sdhci_remove,
};
module_platform_driver(sdhci_driver);

View file

@ -9,9 +9,10 @@
#include <linux/dma-mapping.h>
#include <linux/highmem.h>
#include <linux/iopoll.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
@ -73,6 +74,11 @@
#define SDHCI_SPRD_CLK_DEF_RATE 26000000
#define SDHCI_SPRD_PHY_DLL_CLK 52000000
#define SDHCI_SPRD_MAX_RANGE 0xff
#define SDHCI_SPRD_CMD_DLY_MASK GENMASK(15, 8)
#define SDHCI_SPRD_POSRD_DLY_MASK GENMASK(23, 16)
#define SDHCI_SPRD_CPST_EN GENMASK(27, 24)
struct sdhci_sprd_host {
u32 version;
struct clk *clk_sdio;
@ -86,6 +92,11 @@ struct sdhci_sprd_host {
u32 phy_delay[MMC_TIMING_MMC_HS400 + 2];
};
enum sdhci_sprd_tuning_type {
SDHCI_SPRD_TUNING_SD_HS_CMD,
SDHCI_SPRD_TUNING_SD_HS_DATA,
};
struct sdhci_sprd_phy_cfg {
const char *property;
u8 timing;
@ -533,6 +544,138 @@ static void sdhci_sprd_hs400_enhanced_strobe(struct mmc_host *mmc,
SDHCI_SPRD_REG_32_DLL_DLY);
}
static int mmc_send_tuning_cmd(struct mmc_card *card)
{
return mmc_send_status(card, NULL);
}
static int mmc_send_tuning_data(struct mmc_card *card)
{
u8 *status;
int ret;
status = kmalloc(64, GFP_KERNEL);
if (!status)
return -ENOMEM;
ret = mmc_sd_switch(card, 0, 0, 0, status);
kfree(status);
return ret;
}
static int sdhci_sprd_get_best_clk_sample(struct mmc_host *mmc, u8 *value)
{
int range_end = SDHCI_SPRD_MAX_RANGE;
int range_length = 0;
int middle_range = 0;
int count = 0;
int i;
for (i = 0; i <= SDHCI_SPRD_MAX_RANGE; i++) {
if (value[i]) {
pr_debug("%s: tuning ok: %d\n", mmc_hostname(mmc), i);
count++;
} else {
pr_debug("%s: tuning fail: %d\n", mmc_hostname(mmc), i);
if (range_length < count) {
range_length = count;
range_end = i - 1;
count = 0;
}
}
}
if (!count)
return -EIO;
if (count > range_length) {
range_length = count;
range_end = i - 1;
}
middle_range = range_end - (range_length - 1) / 2;
return middle_range;
}
static int sdhci_sprd_tuning(struct mmc_host *mmc, struct mmc_card *card,
enum sdhci_sprd_tuning_type type)
{
struct sdhci_host *host = mmc_priv(mmc);
struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host);
u32 *p = sprd_host->phy_delay;
u32 dll_cfg, dll_dly;
int best_clk_sample;
int err = 0;
u8 *value;
int i;
value = kmalloc(SDHCI_SPRD_MAX_RANGE + 1, GFP_KERNEL);
if (!value)
return -ENOMEM;
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
dll_cfg = sdhci_readl(host, SDHCI_SPRD_REG_32_DLL_CFG);
dll_cfg &= ~SDHCI_SPRD_CPST_EN;
sdhci_writel(host, dll_cfg, SDHCI_SPRD_REG_32_DLL_CFG);
dll_dly = p[mmc->ios.timing];
for (i = 0; i <= SDHCI_SPRD_MAX_RANGE; i++) {
if (type == SDHCI_SPRD_TUNING_SD_HS_CMD) {
dll_dly &= ~SDHCI_SPRD_CMD_DLY_MASK;
dll_dly |= ((i << 8) & SDHCI_SPRD_CMD_DLY_MASK);
} else {
dll_dly &= ~SDHCI_SPRD_POSRD_DLY_MASK;
dll_dly |= ((i << 16) & SDHCI_SPRD_POSRD_DLY_MASK);
}
sdhci_writel(host, dll_dly, SDHCI_SPRD_REG_32_DLL_DLY);
if (type == SDHCI_SPRD_TUNING_SD_HS_CMD)
value[i] = !mmc_send_tuning_cmd(card);
else
value[i] = !mmc_send_tuning_data(card);
}
best_clk_sample = sdhci_sprd_get_best_clk_sample(mmc, value);
if (best_clk_sample < 0) {
dev_err(mmc_dev(host->mmc), "all tuning phase fail!\n");
goto out;
}
if (type == SDHCI_SPRD_TUNING_SD_HS_CMD) {
p[mmc->ios.timing] &= ~SDHCI_SPRD_CMD_DLY_MASK;
p[mmc->ios.timing] |= ((best_clk_sample << 8) & SDHCI_SPRD_CMD_DLY_MASK);
} else {
p[mmc->ios.timing] &= ~(SDHCI_SPRD_POSRD_DLY_MASK);
p[mmc->ios.timing] |= ((best_clk_sample << 16) & SDHCI_SPRD_POSRD_DLY_MASK);
}
pr_debug("%s: the best clk sample %d, delay value 0x%08x\n",
mmc_hostname(host->mmc), best_clk_sample, p[mmc->ios.timing]);
out:
sdhci_writel(host, p[mmc->ios.timing], SDHCI_SPRD_REG_32_DLL_DLY);
kfree(value);
return err;
}
static int sdhci_sprd_prepare_sd_hs_cmd_tuning(struct mmc_host *mmc, struct mmc_card *card)
{
return sdhci_sprd_tuning(mmc, card, SDHCI_SPRD_TUNING_SD_HS_CMD);
}
static int sdhci_sprd_execute_sd_hs_data_tuning(struct mmc_host *mmc, struct mmc_card *card)
{
return sdhci_sprd_tuning(mmc, card, SDHCI_SPRD_TUNING_SD_HS_DATA);
}
static void sdhci_sprd_phy_param_parse(struct sdhci_sprd_host *sprd_host,
struct device_node *np)
{
@ -577,6 +720,11 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
host->mmc_host_ops.request = sdhci_sprd_request;
host->mmc_host_ops.hs400_enhanced_strobe =
sdhci_sprd_hs400_enhanced_strobe;
host->mmc_host_ops.prepare_sd_hs_tuning =
sdhci_sprd_prepare_sd_hs_cmd_tuning;
host->mmc_host_ops.execute_sd_hs_tuning =
sdhci_sprd_execute_sd_hs_data_tuning;
/*
* We can not use the standard ops to change and detect the voltage
* signal for Spreadtrum SD host controller, since our voltage regulator
@ -720,7 +868,7 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_sprd_remove(struct platform_device *pdev)
static void sdhci_sprd_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host);
@ -732,8 +880,6 @@ static int sdhci_sprd_remove(struct platform_device *pdev)
clk_disable_unprepare(sprd_host->clk_2x_enable);
sdhci_pltfm_free(pdev);
return 0;
}
static const struct of_device_id sdhci_sprd_of_match[] = {
@ -800,7 +946,7 @@ static const struct dev_pm_ops sdhci_sprd_pm_ops = {
static struct platform_driver sdhci_sprd_driver = {
.probe = sdhci_sprd_probe,
.remove = sdhci_sprd_remove,
.remove_new = sdhci_sprd_remove,
.driver = {
.name = "sdhci_sprd_r11",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -348,7 +348,6 @@ static int sdhci_st_probe(struct platform_device *pdev)
struct clk *clk, *icnclk;
int ret = 0;
u16 host_version;
struct resource *res;
struct reset_control *rstc;
clk = devm_clk_get(&pdev->dev, "mmc");
@ -397,9 +396,7 @@ static int sdhci_st_probe(struct platform_device *pdev)
}
/* Configure the FlashSS Top registers for setting eMMC TX/RX delay */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"top-mmc-delay");
pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res);
pdata->top_ioaddr = devm_platform_ioremap_resource_byname(pdev, "top-mmc-delay");
if (IS_ERR(pdata->top_ioaddr))
pdata->top_ioaddr = NULL;
@ -434,20 +431,20 @@ static int sdhci_st_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_st_remove(struct platform_device *pdev)
static void sdhci_st_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
struct reset_control *rstc = pdata->rstc;
struct clk *clk = pltfm_host->clk;
sdhci_pltfm_unregister(pdev);
sdhci_pltfm_remove(pdev);
clk_disable_unprepare(pdata->icnclk);
clk_disable_unprepare(clk);
reset_control_assert(rstc);
return 0;
}
#ifdef CONFIG_PM_SLEEP
@ -510,7 +507,7 @@ MODULE_DEVICE_TABLE(of, st_sdhci_match);
static struct platform_driver sdhci_st_driver = {
.probe = sdhci_st_probe,
.remove = sdhci_st_remove,
.remove_new = sdhci_st_remove,
.driver = {
.name = "sdhci-st",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -19,7 +19,6 @@
#include <linux/mmc/mmc.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
@ -1818,7 +1817,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
return rc;
}
static int sdhci_tegra_remove(struct platform_device *pdev)
static void sdhci_tegra_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -1834,8 +1833,6 @@ static int sdhci_tegra_remove(struct platform_device *pdev)
clk_disable_unprepare(tegra_host->tmclk);
sdhci_pltfm_free(pdev);
return 0;
}
static int __maybe_unused sdhci_tegra_runtime_suspend(struct device *dev)
@ -1933,7 +1930,7 @@ static struct platform_driver sdhci_tegra_driver = {
.pm = &sdhci_tegra_dev_pm_ops,
},
.probe = sdhci_tegra_probe,
.remove = sdhci_tegra_remove,
.remove_new = sdhci_tegra_remove,
};
module_platform_driver(sdhci_tegra_driver);

View file

@ -578,7 +578,7 @@ static int xenon_probe(struct platform_device *pdev)
return err;
}
static int xenon_remove(struct platform_device *pdev)
static void xenon_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@ -595,8 +595,6 @@ static int xenon_remove(struct platform_device *pdev)
clk_disable_unprepare(pltfm_host->clk);
sdhci_pltfm_free(pdev);
return 0;
}
#ifdef CONFIG_PM_SLEEP
@ -705,7 +703,7 @@ static struct platform_driver sdhci_xenon_driver = {
.pm = &sdhci_xenon_dev_pm_ops,
},
.probe = xenon_probe,
.remove = xenon_remove,
.remove_new = xenon_remove,
};
module_platform_driver(sdhci_xenon_driver);

View file

@ -866,22 +866,22 @@ static int sdhci_am654_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_am654_remove(struct platform_device *pdev)
static void sdhci_am654_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct device *dev = &pdev->dev;
int ret;
ret = pm_runtime_resume_and_get(&pdev->dev);
ret = pm_runtime_get_sync(dev);
if (ret < 0)
return ret;
dev_err(dev, "pm_runtime_get_sync() Failed\n");
sdhci_remove_host(host, true);
clk_disable_unprepare(pltfm_host->clk);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
sdhci_pltfm_free(pdev);
return 0;
}
#ifdef CONFIG_PM
@ -993,7 +993,7 @@ static struct platform_driver sdhci_am654_driver = {
.of_match_table = sdhci_am654_of_match,
},
.probe = sdhci_am654_probe,
.remove = sdhci_am654_remove,
.remove_new = sdhci_am654_remove,
};
module_platform_driver(sdhci_am654_driver);

View file

@ -206,7 +206,7 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev)
return ret;
}
static int sdhci_f_sdh30_remove(struct platform_device *pdev)
static void sdhci_f_sdh30_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
@ -214,13 +214,11 @@ static int sdhci_f_sdh30_remove(struct platform_device *pdev)
struct reset_control *rst = priv->rst;
struct clk *clk = priv->clk;
sdhci_pltfm_unregister(pdev);
sdhci_pltfm_remove(pdev);
reset_control_assert(rst);
clk_disable_unprepare(clk);
clk_disable_unprepare(clk_iface);
return 0;
}
#ifdef CONFIG_OF
@ -248,8 +246,8 @@ static struct platform_driver sdhci_f_sdh30_driver = {
.acpi_match_table = ACPI_PTR(f_sdh30_acpi_ids),
.pm = &sdhci_pltfm_pmops,
},
.probe = sdhci_f_sdh30_probe,
.remove = sdhci_f_sdh30_remove,
.probe = sdhci_f_sdh30_probe,
.remove_new = sdhci_f_sdh30_remove,
};
module_platform_driver(sdhci_f_sdh30_driver);

View file

@ -46,7 +46,6 @@
#include <linux/mmc/slot-gpio.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/pagemap.h>
#include <linux/platform_data/sh_mmcif.h>
#include <linux/platform_device.h>
@ -1509,7 +1508,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
return ret;
}
static int sh_mmcif_remove(struct platform_device *pdev)
static void sh_mmcif_remove(struct platform_device *pdev)
{
struct sh_mmcif_host *host = platform_get_drvdata(pdev);
@ -1533,8 +1532,6 @@ static int sh_mmcif_remove(struct platform_device *pdev)
mmc_free_host(host->mmc);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;
}
#ifdef CONFIG_PM_SLEEP
@ -1561,7 +1558,7 @@ static const struct dev_pm_ops sh_mmcif_dev_pm_ops = {
static struct platform_driver sh_mmcif_driver = {
.probe = sh_mmcif_probe,
.remove = sh_mmcif_remove,
.remove_new = sh_mmcif_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -885,7 +885,7 @@ static int spmmc_drv_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(host->rstc), "rst get fail\n");
host->irq = platform_get_irq(pdev, 0);
if (host->irq <= 0)
if (host->irq < 0)
return host->irq;
ret = devm_request_threaded_irq(&pdev->dev, host->irq,
@ -939,7 +939,7 @@ static int spmmc_drv_probe(struct platform_device *pdev)
return ret;
}
static int spmmc_drv_remove(struct platform_device *dev)
static void spmmc_drv_remove(struct platform_device *dev)
{
struct spmmc_host *host = platform_get_drvdata(dev);
@ -948,9 +948,6 @@ static int spmmc_drv_remove(struct platform_device *dev)
clk_disable_unprepare(host->clk);
pm_runtime_put_noidle(&dev->dev);
pm_runtime_disable(&dev->dev);
platform_set_drvdata(dev, NULL);
return 0;
}
static int spmmc_pm_runtime_suspend(struct device *dev)
@ -985,7 +982,7 @@ MODULE_DEVICE_TABLE(of, spmmc_of_table);
static struct platform_driver spmmc_driver = {
.probe = spmmc_drv_probe,
.remove = spmmc_drv_remove,
.remove_new = spmmc_drv_remove,
.driver = {
.name = "spmmc",
.pm = pm_ptr(&spmmc_pm_ops),

View file

@ -1486,7 +1486,7 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
return ret;
}
static int sunxi_mmc_remove(struct platform_device *pdev)
static void sunxi_mmc_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct sunxi_mmc_host *host = mmc_priv(mmc);
@ -1499,8 +1499,6 @@ static int sunxi_mmc_remove(struct platform_device *pdev)
}
dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
mmc_free_host(mmc);
return 0;
}
#ifdef CONFIG_PM
@ -1556,7 +1554,7 @@ static struct platform_driver sunxi_mmc_driver = {
.pm = &sunxi_mmc_pm_ops,
},
.probe = sunxi_mmc_probe,
.remove = sunxi_mmc_remove,
.remove_new = sunxi_mmc_remove,
};
module_platform_driver(sunxi_mmc_driver);

View file

@ -13,7 +13,6 @@
#include <linux/mmc/host.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@ -706,19 +705,19 @@ static int uniphier_sd_probe(struct platform_device *pdev)
tmio_data->max_segs = 1;
tmio_data->max_blk_count = U16_MAX;
ret = tmio_mmc_host_probe(host);
if (ret)
goto disable_clk;
sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, TMIO_MASK_ALL);
ret = devm_request_irq(dev, irq, tmio_mmc_irq, IRQF_SHARED,
dev_name(dev), host);
if (ret)
goto remove_host;
goto disable_clk;
ret = tmio_mmc_host_probe(host);
if (ret)
goto disable_clk;
return 0;
remove_host:
tmio_mmc_host_remove(host);
disable_clk:
uniphier_sd_clk_disable(host);
free_host:
@ -727,15 +726,13 @@ static int uniphier_sd_probe(struct platform_device *pdev)
return ret;
}
static int uniphier_sd_remove(struct platform_device *pdev)
static void uniphier_sd_remove(struct platform_device *pdev)
{
struct tmio_mmc_host *host = platform_get_drvdata(pdev);
tmio_mmc_host_remove(host);
uniphier_sd_clk_disable(host);
tmio_mmc_host_free(host);
return 0;
}
static const struct of_device_id uniphier_sd_match[] = {
@ -757,7 +754,7 @@ MODULE_DEVICE_TABLE(of, uniphier_sd_match);
static struct platform_driver uniphier_sd_driver = {
.probe = uniphier_sd_probe,
.remove = uniphier_sd_remove,
.remove_new = uniphier_sd_remove,
.driver = {
.name = "uniphier-sd",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -1884,7 +1884,7 @@ static int usdhi6_probe(struct platform_device *pdev)
return ret;
}
static int usdhi6_remove(struct platform_device *pdev)
static void usdhi6_remove(struct platform_device *pdev)
{
struct usdhi6_host *host = platform_get_drvdata(pdev);
@ -1895,13 +1895,11 @@ static int usdhi6_remove(struct platform_device *pdev)
usdhi6_dma_release(host);
clk_disable_unprepare(host->clk);
mmc_free_host(host->mmc);
return 0;
}
static struct platform_driver usdhi6_driver = {
.probe = usdhi6_probe,
.remove = usdhi6_remove,
.remove_new = usdhi6_remove,
.driver = {
.name = "usdhi6rol0",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -1160,7 +1160,6 @@ static int via_sd_probe(struct pci_dev *pcidev,
unmap:
iounmap(sdhost->mmiobase);
free_mmc_host:
dev_set_drvdata(&pcidev->dev, NULL);
mmc_free_host(mmc);
release:
pci_release_regions(pcidev);
@ -1212,7 +1211,6 @@ static void via_sd_remove(struct pci_dev *pcidev)
writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
iounmap(sdhost->mmiobase);
dev_set_drvdata(&pcidev->dev, NULL);
mmc_free_host(sdhost->mmc);
pci_release_regions(pcidev);
pci_disable_device(pcidev);

View file

@ -1264,8 +1264,6 @@ static void wbsd_free_mmc(struct device *dev)
del_timer_sync(&host->ignore_timer);
mmc_free_host(mmc);
dev_set_drvdata(dev, NULL);
}
/*
@ -1756,11 +1754,9 @@ static int wbsd_probe(struct platform_device *dev)
return wbsd_init(&dev->dev, param_io, param_irq, param_dma, 0);
}
static int wbsd_remove(struct platform_device *dev)
static void wbsd_remove(struct platform_device *dev)
{
wbsd_shutdown(&dev->dev, 0);
return 0;
}
/*
@ -1902,8 +1898,7 @@ static struct platform_device *wbsd_device;
static struct platform_driver wbsd_driver = {
.probe = wbsd_probe,
.remove = wbsd_remove,
.remove_new = wbsd_remove,
.suspend = wbsd_platform_suspend,
.resume = wbsd_platform_resume,
.driver = {

View file

@ -21,7 +21,6 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_device.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
@ -880,7 +879,7 @@ static int wmt_mci_probe(struct platform_device *pdev)
return ret;
}
static int wmt_mci_remove(struct platform_device *pdev)
static void wmt_mci_remove(struct platform_device *pdev)
{
struct mmc_host *mmc;
struct wmt_mci_priv *priv;
@ -918,8 +917,6 @@ static int wmt_mci_remove(struct platform_device *pdev)
mmc_free_host(mmc);
dev_info(&pdev->dev, "WMT MCI device removed\n");
return 0;
}
#ifdef CONFIG_PM
@ -989,7 +986,7 @@ static const struct dev_pm_ops wmt_mci_pm = {
static struct platform_driver wmt_mci_driver = {
.probe = wmt_mci_probe,
.remove = wmt_mci_remove,
.remove_new = wmt_mci_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View file

@ -1,46 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LINUX_ATMEL_MCI_H
#define __LINUX_ATMEL_MCI_H
#include <linux/types.h>
#include <linux/dmaengine.h>
#define ATMCI_MAX_NR_SLOTS 2
/**
* struct mci_slot_pdata - board-specific per-slot configuration
* @bus_width: Number of data lines wired up the slot
* @detect_pin: GPIO pin wired to the card detect switch
* @wp_pin: GPIO pin wired to the write protect sensor
* @detect_is_active_high: The state of the detect pin when it is active
* @non_removable: The slot is not removable, only detect once
*
* If a given slot is not present on the board, @bus_width should be
* set to 0. The other fields are ignored in this case.
*
* Any pins that aren't available should be set to a negative value.
*
* Note that support for multiple slots is experimental -- some cards
* might get upset if we don't get the clock management exactly right.
* But in most cases, it should work just fine.
*/
struct mci_slot_pdata {
unsigned int bus_width;
int detect_pin;
int wp_pin;
bool detect_is_active_high;
bool non_removable;
};
/**
* struct mci_platform_data - board-specific MMC/SDcard configuration
* @dma_slave: DMA slave interface to use in data transfers.
* @slot: Per-slot configuration data.
*/
struct mci_platform_data {
void *dma_slave;
dma_filter_fn dma_filter;
struct mci_slot_pdata slot[ATMCI_MAX_NR_SLOTS];
};
#endif /* __LINUX_ATMEL_MCI_H */

View file

@ -184,6 +184,12 @@ struct mmc_host_ops {
/* Execute HS400 tuning depending host driver */
int (*execute_hs400_tuning)(struct mmc_host *host, struct mmc_card *card);
/* Optional callback to prepare for SD high-speed tuning */
int (*prepare_sd_hs_tuning)(struct mmc_host *host, struct mmc_card *card);
/* Optional callback to execute SD high-speed tuning */
int (*execute_sd_hs_tuning)(struct mmc_host *host, struct mmc_card *card);
/* Prepare switch to DDR during the HS400 init sequence */
int (*hs400_prepare_ddr)(struct mmc_host *host);
@ -665,6 +671,8 @@ static inline void mmc_debugfs_err_stats_inc(struct mmc_host *host,
host->err_stats[stat] += 1;
}
int mmc_sd_switch(struct mmc_card *card, int mode, int group, u8 value, u8 *resp);
int mmc_send_status(struct mmc_card *card, u32 *status);
int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error);
int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode);
int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);