18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/drivers/mmc/core/bus.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2003 Russell King, All Rights Reserved. 68c2ecf20Sopenharmony_ci * Copyright (C) 2007 Pierre Ossman 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * MMC card bus driver model 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/export.h> 128c2ecf20Sopenharmony_ci#include <linux/device.h> 138c2ecf20Sopenharmony_ci#include <linux/err.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/stat.h> 168c2ecf20Sopenharmony_ci#include <linux/of.h> 178c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <linux/mmc/card.h> 208c2ecf20Sopenharmony_ci#include <linux/mmc/host.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "core.h" 238c2ecf20Sopenharmony_ci#include "card.h" 248c2ecf20Sopenharmony_ci#include "host.h" 258c2ecf20Sopenharmony_ci#include "sdio_cis.h" 268c2ecf20Sopenharmony_ci#include "bus.h" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic ssize_t type_show(struct device *dev, 318c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci struct mmc_card *card = mmc_dev_to_card(dev); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci switch (card->type) { 368c2ecf20Sopenharmony_ci case MMC_TYPE_MMC: 378c2ecf20Sopenharmony_ci return sprintf(buf, "MMC\n"); 388c2ecf20Sopenharmony_ci case MMC_TYPE_SD: 398c2ecf20Sopenharmony_ci return sprintf(buf, "SD\n"); 408c2ecf20Sopenharmony_ci case MMC_TYPE_SDIO: 418c2ecf20Sopenharmony_ci return sprintf(buf, "SDIO\n"); 428c2ecf20Sopenharmony_ci case MMC_TYPE_SD_COMBO: 438c2ecf20Sopenharmony_ci return sprintf(buf, "SDcombo\n"); 448c2ecf20Sopenharmony_ci default: 458c2ecf20Sopenharmony_ci return -EFAULT; 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(type); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic struct attribute *mmc_dev_attrs[] = { 518c2ecf20Sopenharmony_ci &dev_attr_type.attr, 528c2ecf20Sopenharmony_ci NULL, 538c2ecf20Sopenharmony_ci}; 548c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(mmc_dev); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* 578c2ecf20Sopenharmony_ci * This currently matches any MMC driver to any MMC card - drivers 588c2ecf20Sopenharmony_ci * themselves make the decision whether to drive this card in their 598c2ecf20Sopenharmony_ci * probe method. 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_cistatic int mmc_bus_match(struct device *dev, struct device_driver *drv) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci return 1; 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic int 678c2ecf20Sopenharmony_cimmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci struct mmc_card *card = mmc_dev_to_card(dev); 708c2ecf20Sopenharmony_ci const char *type; 718c2ecf20Sopenharmony_ci unsigned int i; 728c2ecf20Sopenharmony_ci int retval = 0; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci switch (card->type) { 758c2ecf20Sopenharmony_ci case MMC_TYPE_MMC: 768c2ecf20Sopenharmony_ci type = "MMC"; 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci case MMC_TYPE_SD: 798c2ecf20Sopenharmony_ci type = "SD"; 808c2ecf20Sopenharmony_ci break; 818c2ecf20Sopenharmony_ci case MMC_TYPE_SDIO: 828c2ecf20Sopenharmony_ci type = "SDIO"; 838c2ecf20Sopenharmony_ci break; 848c2ecf20Sopenharmony_ci case MMC_TYPE_SD_COMBO: 858c2ecf20Sopenharmony_ci type = "SDcombo"; 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci default: 888c2ecf20Sopenharmony_ci type = NULL; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci if (type) { 928c2ecf20Sopenharmony_ci retval = add_uevent_var(env, "MMC_TYPE=%s", type); 938c2ecf20Sopenharmony_ci if (retval) 948c2ecf20Sopenharmony_ci return retval; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci if (card->type == MMC_TYPE_SDIO || card->type == MMC_TYPE_SD_COMBO) { 988c2ecf20Sopenharmony_ci retval = add_uevent_var(env, "SDIO_ID=%04X:%04X", 998c2ecf20Sopenharmony_ci card->cis.vendor, card->cis.device); 1008c2ecf20Sopenharmony_ci if (retval) 1018c2ecf20Sopenharmony_ci return retval; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci retval = add_uevent_var(env, "SDIO_REVISION=%u.%u", 1048c2ecf20Sopenharmony_ci card->major_rev, card->minor_rev); 1058c2ecf20Sopenharmony_ci if (retval) 1068c2ecf20Sopenharmony_ci return retval; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci for (i = 0; i < card->num_info; i++) { 1098c2ecf20Sopenharmony_ci retval = add_uevent_var(env, "SDIO_INFO%u=%s", i+1, card->info[i]); 1108c2ecf20Sopenharmony_ci if (retval) 1118c2ecf20Sopenharmony_ci return retval; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci /* 1168c2ecf20Sopenharmony_ci * SDIO (non-combo) cards are not handled by mmc_block driver and do not 1178c2ecf20Sopenharmony_ci * have accessible CID register which used by mmc_card_name() function. 1188c2ecf20Sopenharmony_ci */ 1198c2ecf20Sopenharmony_ci if (card->type == MMC_TYPE_SDIO) 1208c2ecf20Sopenharmony_ci return 0; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); 1238c2ecf20Sopenharmony_ci if (retval) 1248c2ecf20Sopenharmony_ci return retval; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* 1278c2ecf20Sopenharmony_ci * Request the mmc_block device. Note: that this is a direct request 1288c2ecf20Sopenharmony_ci * for the module it carries no information as to what is inserted. 1298c2ecf20Sopenharmony_ci */ 1308c2ecf20Sopenharmony_ci retval = add_uevent_var(env, "MODALIAS=mmc:block"); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci return retval; 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic int mmc_bus_probe(struct device *dev) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci struct mmc_driver *drv = to_mmc_driver(dev->driver); 1388c2ecf20Sopenharmony_ci struct mmc_card *card = mmc_dev_to_card(dev); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci return drv->probe(card); 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic int mmc_bus_remove(struct device *dev) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci struct mmc_driver *drv = to_mmc_driver(dev->driver); 1468c2ecf20Sopenharmony_ci struct mmc_card *card = mmc_dev_to_card(dev); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci drv->remove(card); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci return 0; 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic void mmc_bus_shutdown(struct device *dev) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci struct mmc_driver *drv = to_mmc_driver(dev->driver); 1568c2ecf20Sopenharmony_ci struct mmc_card *card = mmc_dev_to_card(dev); 1578c2ecf20Sopenharmony_ci struct mmc_host *host = card->host; 1588c2ecf20Sopenharmony_ci int ret; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (dev->driver && drv->shutdown) 1618c2ecf20Sopenharmony_ci drv->shutdown(card); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci if (host->bus_ops->shutdown) { 1648c2ecf20Sopenharmony_ci ret = host->bus_ops->shutdown(host); 1658c2ecf20Sopenharmony_ci if (ret) 1668c2ecf20Sopenharmony_ci pr_warn("%s: error %d during shutdown\n", 1678c2ecf20Sopenharmony_ci mmc_hostname(host), ret); 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 1728c2ecf20Sopenharmony_cistatic int mmc_bus_suspend(struct device *dev) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci struct mmc_card *card = mmc_dev_to_card(dev); 1758c2ecf20Sopenharmony_ci struct mmc_host *host = card->host; 1768c2ecf20Sopenharmony_ci int ret; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci ret = pm_generic_suspend(dev); 1798c2ecf20Sopenharmony_ci if (ret) 1808c2ecf20Sopenharmony_ci return ret; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci ret = host->bus_ops->suspend(host); 1838c2ecf20Sopenharmony_ci if (ret) 1848c2ecf20Sopenharmony_ci pm_generic_resume(dev); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci return ret; 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cistatic int mmc_bus_resume(struct device *dev) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci struct mmc_card *card = mmc_dev_to_card(dev); 1928c2ecf20Sopenharmony_ci struct mmc_host *host = card->host; 1938c2ecf20Sopenharmony_ci int ret; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci ret = host->bus_ops->resume(host); 1968c2ecf20Sopenharmony_ci if (ret) 1978c2ecf20Sopenharmony_ci pr_warn("%s: error %d during resume (card was removed?)\n", 1988c2ecf20Sopenharmony_ci mmc_hostname(host), ret); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci ret = pm_generic_resume(dev); 2018c2ecf20Sopenharmony_ci return ret; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci#endif 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 2068c2ecf20Sopenharmony_cistatic int mmc_runtime_suspend(struct device *dev) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci struct mmc_card *card = mmc_dev_to_card(dev); 2098c2ecf20Sopenharmony_ci struct mmc_host *host = card->host; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci return host->bus_ops->runtime_suspend(host); 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic int mmc_runtime_resume(struct device *dev) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci struct mmc_card *card = mmc_dev_to_card(dev); 2178c2ecf20Sopenharmony_ci struct mmc_host *host = card->host; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci return host->bus_ops->runtime_resume(host); 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci#endif /* !CONFIG_PM */ 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic const struct dev_pm_ops mmc_bus_pm_ops = { 2248c2ecf20Sopenharmony_ci SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, NULL) 2258c2ecf20Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume) 2268c2ecf20Sopenharmony_ci}; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic struct bus_type mmc_bus_type = { 2298c2ecf20Sopenharmony_ci .name = "mmc", 2308c2ecf20Sopenharmony_ci .dev_groups = mmc_dev_groups, 2318c2ecf20Sopenharmony_ci .match = mmc_bus_match, 2328c2ecf20Sopenharmony_ci .uevent = mmc_bus_uevent, 2338c2ecf20Sopenharmony_ci .probe = mmc_bus_probe, 2348c2ecf20Sopenharmony_ci .remove = mmc_bus_remove, 2358c2ecf20Sopenharmony_ci .shutdown = mmc_bus_shutdown, 2368c2ecf20Sopenharmony_ci .pm = &mmc_bus_pm_ops, 2378c2ecf20Sopenharmony_ci}; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ciint mmc_register_bus(void) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci return bus_register(&mmc_bus_type); 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_civoid mmc_unregister_bus(void) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci bus_unregister(&mmc_bus_type); 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci/** 2508c2ecf20Sopenharmony_ci * mmc_register_driver - register a media driver 2518c2ecf20Sopenharmony_ci * @drv: MMC media driver 2528c2ecf20Sopenharmony_ci */ 2538c2ecf20Sopenharmony_ciint mmc_register_driver(struct mmc_driver *drv) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci drv->drv.bus = &mmc_bus_type; 2568c2ecf20Sopenharmony_ci return driver_register(&drv->drv); 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mmc_register_driver); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci/** 2628c2ecf20Sopenharmony_ci * mmc_unregister_driver - unregister a media driver 2638c2ecf20Sopenharmony_ci * @drv: MMC media driver 2648c2ecf20Sopenharmony_ci */ 2658c2ecf20Sopenharmony_civoid mmc_unregister_driver(struct mmc_driver *drv) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci drv->drv.bus = &mmc_bus_type; 2688c2ecf20Sopenharmony_ci driver_unregister(&drv->drv); 2698c2ecf20Sopenharmony_ci} 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mmc_unregister_driver); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_cistatic void mmc_release_card(struct device *dev) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci struct mmc_card *card = mmc_dev_to_card(dev); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci sdio_free_common_cis(card); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci kfree(card->info); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci kfree(card); 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci/* 2858c2ecf20Sopenharmony_ci * Allocate and initialise a new MMC card structure. 2868c2ecf20Sopenharmony_ci */ 2878c2ecf20Sopenharmony_cistruct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci struct mmc_card *card; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL); 2928c2ecf20Sopenharmony_ci if (!card) 2938c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci card->host = host; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci device_initialize(&card->dev); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci card->dev.parent = mmc_classdev(host); 3008c2ecf20Sopenharmony_ci card->dev.bus = &mmc_bus_type; 3018c2ecf20Sopenharmony_ci card->dev.release = mmc_release_card; 3028c2ecf20Sopenharmony_ci card->dev.type = type; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci return card; 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci/* 3088c2ecf20Sopenharmony_ci * Register a new MMC card with the driver model. 3098c2ecf20Sopenharmony_ci */ 3108c2ecf20Sopenharmony_ciint mmc_add_card(struct mmc_card *card) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci int ret; 3138c2ecf20Sopenharmony_ci const char *type; 3148c2ecf20Sopenharmony_ci const char *uhs_bus_speed_mode = ""; 3158c2ecf20Sopenharmony_ci static const char *const uhs_speeds[] = { 3168c2ecf20Sopenharmony_ci [UHS_SDR12_BUS_SPEED] = "SDR12 ", 3178c2ecf20Sopenharmony_ci [UHS_SDR25_BUS_SPEED] = "SDR25 ", 3188c2ecf20Sopenharmony_ci [UHS_SDR50_BUS_SPEED] = "SDR50 ", 3198c2ecf20Sopenharmony_ci [UHS_SDR104_BUS_SPEED] = "SDR104 ", 3208c2ecf20Sopenharmony_ci [UHS_DDR50_BUS_SPEED] = "DDR50 ", 3218c2ecf20Sopenharmony_ci }; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci switch (card->type) { 3278c2ecf20Sopenharmony_ci case MMC_TYPE_MMC: 3288c2ecf20Sopenharmony_ci type = "MMC"; 3298c2ecf20Sopenharmony_ci break; 3308c2ecf20Sopenharmony_ci case MMC_TYPE_SD: 3318c2ecf20Sopenharmony_ci type = "SD"; 3328c2ecf20Sopenharmony_ci if (mmc_card_blockaddr(card)) { 3338c2ecf20Sopenharmony_ci if (mmc_card_ext_capacity(card)) 3348c2ecf20Sopenharmony_ci type = "SDXC"; 3358c2ecf20Sopenharmony_ci else 3368c2ecf20Sopenharmony_ci type = "SDHC"; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci break; 3398c2ecf20Sopenharmony_ci case MMC_TYPE_SDIO: 3408c2ecf20Sopenharmony_ci type = "SDIO"; 3418c2ecf20Sopenharmony_ci break; 3428c2ecf20Sopenharmony_ci case MMC_TYPE_SD_COMBO: 3438c2ecf20Sopenharmony_ci type = "SD-combo"; 3448c2ecf20Sopenharmony_ci if (mmc_card_blockaddr(card)) 3458c2ecf20Sopenharmony_ci type = "SDHC-combo"; 3468c2ecf20Sopenharmony_ci break; 3478c2ecf20Sopenharmony_ci default: 3488c2ecf20Sopenharmony_ci type = "?"; 3498c2ecf20Sopenharmony_ci break; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci if (mmc_card_uhs(card) && 3538c2ecf20Sopenharmony_ci (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) 3548c2ecf20Sopenharmony_ci uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci if (mmc_host_is_spi(card->host)) { 3578c2ecf20Sopenharmony_ci pr_info("%s: new %s%s%s card on SPI\n", 3588c2ecf20Sopenharmony_ci mmc_hostname(card->host), 3598c2ecf20Sopenharmony_ci mmc_card_hs(card) ? "high speed " : "", 3608c2ecf20Sopenharmony_ci mmc_card_ddr52(card) ? "DDR " : "", 3618c2ecf20Sopenharmony_ci type); 3628c2ecf20Sopenharmony_ci } else { 3638c2ecf20Sopenharmony_ci pr_info("%s: new %s%s%s%s%s%s card at address %04x\n", 3648c2ecf20Sopenharmony_ci mmc_hostname(card->host), 3658c2ecf20Sopenharmony_ci mmc_card_uhs(card) ? "ultra high speed " : 3668c2ecf20Sopenharmony_ci (mmc_card_hs(card) ? "high speed " : ""), 3678c2ecf20Sopenharmony_ci mmc_card_hs400(card) ? "HS400 " : 3688c2ecf20Sopenharmony_ci (mmc_card_hs200(card) ? "HS200 " : ""), 3698c2ecf20Sopenharmony_ci mmc_card_hs400es(card) ? "Enhanced strobe " : "", 3708c2ecf20Sopenharmony_ci mmc_card_ddr52(card) ? "DDR " : "", 3718c2ecf20Sopenharmony_ci uhs_bus_speed_mode, type, card->rca); 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 3758c2ecf20Sopenharmony_ci mmc_add_card_debugfs(card); 3768c2ecf20Sopenharmony_ci#endif 3778c2ecf20Sopenharmony_ci card->dev.of_node = mmc_of_find_child_device(card->host, 0); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci device_enable_async_suspend(&card->dev); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci ret = device_add(&card->dev); 3828c2ecf20Sopenharmony_ci if (ret) 3838c2ecf20Sopenharmony_ci return ret; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci mmc_card_set_present(card); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci return 0; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci/* 3918c2ecf20Sopenharmony_ci * Unregister a new MMC card with the driver model, and 3928c2ecf20Sopenharmony_ci * (eventually) free it. 3938c2ecf20Sopenharmony_ci */ 3948c2ecf20Sopenharmony_civoid mmc_remove_card(struct mmc_card *card) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci struct mmc_host *host = card->host; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 3998c2ecf20Sopenharmony_ci mmc_remove_card_debugfs(card); 4008c2ecf20Sopenharmony_ci#endif 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci if (mmc_card_present(card)) { 4038c2ecf20Sopenharmony_ci if (mmc_host_is_spi(card->host)) { 4048c2ecf20Sopenharmony_ci pr_info("%s: SPI card removed\n", 4058c2ecf20Sopenharmony_ci mmc_hostname(card->host)); 4068c2ecf20Sopenharmony_ci } else { 4078c2ecf20Sopenharmony_ci pr_info("%s: card %04x removed\n", 4088c2ecf20Sopenharmony_ci mmc_hostname(card->host), card->rca); 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci device_del(&card->dev); 4118c2ecf20Sopenharmony_ci of_node_put(card->dev.of_node); 4128c2ecf20Sopenharmony_ci } 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci if (host->cqe_enabled) { 4158c2ecf20Sopenharmony_ci host->cqe_ops->cqe_disable(host); 4168c2ecf20Sopenharmony_ci host->cqe_enabled = false; 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci put_device(&card->dev); 4208c2ecf20Sopenharmony_ci} 421