brintos

brintos / linux-shallow public Read only

0
0
Text · 9.5 KiB · b66b637 Raw
402 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  linux/drivers/mmc/core/sdio_bus.c4 *5 *  Copyright 2007 Pierre Ossman6 *7 * SDIO function driver model8 */9 10#include <linux/device.h>11#include <linux/err.h>12#include <linux/export.h>13#include <linux/slab.h>14#include <linux/pm_runtime.h>15#include <linux/pm_domain.h>16#include <linux/acpi.h>17#include <linux/sysfs.h>18 19#include <linux/mmc/card.h>20#include <linux/mmc/host.h>21#include <linux/mmc/sdio_func.h>22#include <linux/of.h>23 24#include "core.h"25#include "card.h"26#include "sdio_cis.h"27#include "sdio_bus.h"28 29#define to_sdio_driver(d)	container_of_const(d, struct sdio_driver, drv)30 31/* show configuration fields */32#define sdio_config_attr(field, format_string, args...)			\33static ssize_t								\34field##_show(struct device *dev, struct device_attribute *attr, char *buf)				\35{									\36	struct sdio_func *func;						\37									\38	func = dev_to_sdio_func (dev);					\39	return sysfs_emit(buf, format_string, args);			\40}									\41static DEVICE_ATTR_RO(field)42 43sdio_config_attr(class, "0x%02x\n", func->class);44sdio_config_attr(vendor, "0x%04x\n", func->vendor);45sdio_config_attr(device, "0x%04x\n", func->device);46sdio_config_attr(revision, "%u.%u\n", func->major_rev, func->minor_rev);47sdio_config_attr(modalias, "sdio:c%02Xv%04Xd%04X\n", func->class, func->vendor, func->device);48 49#define sdio_info_attr(num)									\50static ssize_t info##num##_show(struct device *dev, struct device_attribute *attr, char *buf)	\51{												\52	struct sdio_func *func = dev_to_sdio_func(dev);						\53												\54	if (num > func->num_info)								\55		return -ENODATA;								\56	if (!func->info[num - 1][0])								\57		return 0;									\58	return sysfs_emit(buf, "%s\n", func->info[num - 1]);					\59}												\60static DEVICE_ATTR_RO(info##num)61 62sdio_info_attr(1);63sdio_info_attr(2);64sdio_info_attr(3);65sdio_info_attr(4);66 67static struct attribute *sdio_dev_attrs[] = {68	&dev_attr_class.attr,69	&dev_attr_vendor.attr,70	&dev_attr_device.attr,71	&dev_attr_revision.attr,72	&dev_attr_info1.attr,73	&dev_attr_info2.attr,74	&dev_attr_info3.attr,75	&dev_attr_info4.attr,76	&dev_attr_modalias.attr,77	NULL,78};79ATTRIBUTE_GROUPS(sdio_dev);80 81static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,82	const struct sdio_device_id *id)83{84	if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class)85		return NULL;86	if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor)87		return NULL;88	if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device)89		return NULL;90	return id;91}92 93static const struct sdio_device_id *sdio_match_device(struct sdio_func *func,94	const struct sdio_driver *sdrv)95{96	const struct sdio_device_id *ids;97 98	ids = sdrv->id_table;99 100	if (ids) {101		while (ids->class || ids->vendor || ids->device) {102			if (sdio_match_one(func, ids))103				return ids;104			ids++;105		}106	}107 108	return NULL;109}110 111static int sdio_bus_match(struct device *dev, const struct device_driver *drv)112{113	struct sdio_func *func = dev_to_sdio_func(dev);114	const struct sdio_driver *sdrv = to_sdio_driver(drv);115 116	if (sdio_match_device(func, sdrv))117		return 1;118 119	return 0;120}121 122static int123sdio_bus_uevent(const struct device *dev, struct kobj_uevent_env *env)124{125	const struct sdio_func *func = dev_to_sdio_func(dev);126	unsigned int i;127 128	if (add_uevent_var(env,129			"SDIO_CLASS=%02X", func->class))130		return -ENOMEM;131 132	if (add_uevent_var(env,133			"SDIO_ID=%04X:%04X", func->vendor, func->device))134		return -ENOMEM;135 136	if (add_uevent_var(env,137			"SDIO_REVISION=%u.%u", func->major_rev, func->minor_rev))138		return -ENOMEM;139 140	for (i = 0; i < func->num_info; i++) {141		if (add_uevent_var(env, "SDIO_INFO%u=%s", i+1, func->info[i]))142			return -ENOMEM;143	}144 145	if (add_uevent_var(env,146			"MODALIAS=sdio:c%02Xv%04Xd%04X",147			func->class, func->vendor, func->device))148		return -ENOMEM;149 150	return 0;151}152 153static int sdio_bus_probe(struct device *dev)154{155	struct sdio_driver *drv = to_sdio_driver(dev->driver);156	struct sdio_func *func = dev_to_sdio_func(dev);157	const struct sdio_device_id *id;158	int ret;159 160	id = sdio_match_device(func, drv);161	if (!id)162		return -ENODEV;163 164	ret = dev_pm_domain_attach(dev, false);165	if (ret)166		return ret;167 168	atomic_inc(&func->card->sdio_funcs_probed);169 170	/* Unbound SDIO functions are always suspended.171	 * During probe, the function is set active and the usage count172	 * is incremented.  If the driver supports runtime PM,173	 * it should call pm_runtime_put_noidle() in its probe routine and174	 * pm_runtime_get_noresume() in its remove routine.175	 */176	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {177		ret = pm_runtime_get_sync(dev);178		if (ret < 0)179			goto disable_runtimepm;180	}181 182	/* Set the default block size so the driver is sure it's something183	 * sensible. */184	sdio_claim_host(func);185	if (mmc_card_removed(func->card))186		ret = -ENOMEDIUM;187	else188		ret = sdio_set_block_size(func, 0);189	sdio_release_host(func);190	if (ret)191		goto disable_runtimepm;192 193	ret = drv->probe(func, id);194	if (ret)195		goto disable_runtimepm;196 197	return 0;198 199disable_runtimepm:200	atomic_dec(&func->card->sdio_funcs_probed);201	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)202		pm_runtime_put_noidle(dev);203	dev_pm_domain_detach(dev, false);204	return ret;205}206 207static void sdio_bus_remove(struct device *dev)208{209	struct sdio_driver *drv = to_sdio_driver(dev->driver);210	struct sdio_func *func = dev_to_sdio_func(dev);211 212	/* Make sure card is powered before invoking ->remove() */213	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)214		pm_runtime_get_sync(dev);215 216	drv->remove(func);217	atomic_dec(&func->card->sdio_funcs_probed);218 219	if (func->irq_handler) {220		pr_warn("WARNING: driver %s did not remove its interrupt handler!\n",221			drv->name);222		sdio_claim_host(func);223		sdio_release_irq(func);224		sdio_release_host(func);225	}226 227	/* First, undo the increment made directly above */228	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)229		pm_runtime_put_noidle(dev);230 231	/* Then undo the runtime PM settings in sdio_bus_probe() */232	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)233		pm_runtime_put_sync(dev);234 235	dev_pm_domain_detach(dev, false);236}237 238static const struct dev_pm_ops sdio_bus_pm_ops = {239	SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)240	SET_RUNTIME_PM_OPS(241		pm_generic_runtime_suspend,242		pm_generic_runtime_resume,243		NULL244	)245};246 247static const struct bus_type sdio_bus_type = {248	.name		= "sdio",249	.dev_groups	= sdio_dev_groups,250	.match		= sdio_bus_match,251	.uevent		= sdio_bus_uevent,252	.probe		= sdio_bus_probe,253	.remove		= sdio_bus_remove,254	.pm		= &sdio_bus_pm_ops,255};256 257int sdio_register_bus(void)258{259	return bus_register(&sdio_bus_type);260}261 262void sdio_unregister_bus(void)263{264	bus_unregister(&sdio_bus_type);265}266 267/**268 *	__sdio_register_driver - register a function driver269 *	@drv: SDIO function driver270 *	@owner: owning module/driver271 */272int __sdio_register_driver(struct sdio_driver *drv, struct module *owner)273{274	drv->drv.name = drv->name;275	drv->drv.bus = &sdio_bus_type;276	drv->drv.owner = owner;277 278	return driver_register(&drv->drv);279}280EXPORT_SYMBOL_GPL(__sdio_register_driver);281 282/**283 *	sdio_unregister_driver - unregister a function driver284 *	@drv: SDIO function driver285 */286void sdio_unregister_driver(struct sdio_driver *drv)287{288	drv->drv.bus = &sdio_bus_type;289	driver_unregister(&drv->drv);290}291EXPORT_SYMBOL_GPL(sdio_unregister_driver);292 293static void sdio_release_func(struct device *dev)294{295	struct sdio_func *func = dev_to_sdio_func(dev);296 297	if (!(func->card->quirks & MMC_QUIRK_NONSTD_SDIO))298		sdio_free_func_cis(func);299 300	/*301	 * We have now removed the link to the tuples in the302	 * card structure, so remove the reference.303	 */304	put_device(&func->card->dev);305 306	kfree(func->info);307	kfree(func->tmpbuf);308	kfree(func);309}310 311/*312 * Allocate and initialise a new SDIO function structure.313 */314struct sdio_func *sdio_alloc_func(struct mmc_card *card)315{316	struct sdio_func *func;317 318	func = kzalloc(sizeof(struct sdio_func), GFP_KERNEL);319	if (!func)320		return ERR_PTR(-ENOMEM);321 322	/*323	 * allocate buffer separately to make sure it's properly aligned for324	 * DMA usage (incl. 64 bit DMA)325	 */326	func->tmpbuf = kmalloc(4, GFP_KERNEL);327	if (!func->tmpbuf) {328		kfree(func);329		return ERR_PTR(-ENOMEM);330	}331 332	func->card = card;333 334	device_initialize(&func->dev);335 336	/*337	 * We may link to tuples in the card structure,338	 * we need make sure we have a reference to it.339	 */340	get_device(&func->card->dev);341 342	func->dev.parent = &card->dev;343	func->dev.bus = &sdio_bus_type;344	func->dev.release = sdio_release_func;345 346	return func;347}348 349#ifdef CONFIG_ACPI350static void sdio_acpi_set_handle(struct sdio_func *func)351{352	struct mmc_host *host = func->card->host;353	u64 addr = ((u64)host->slotno << 16) | func->num;354 355	acpi_preset_companion(&func->dev, ACPI_COMPANION(host->parent), addr);356}357#else358static inline void sdio_acpi_set_handle(struct sdio_func *func) {}359#endif360 361static void sdio_set_of_node(struct sdio_func *func)362{363	struct mmc_host *host = func->card->host;364 365	func->dev.of_node = mmc_of_find_child_device(host, func->num);366}367 368/*369 * Register a new SDIO function with the driver model.370 */371int sdio_add_func(struct sdio_func *func)372{373	int ret;374 375	dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);376 377	sdio_set_of_node(func);378	sdio_acpi_set_handle(func);379	device_enable_async_suspend(&func->dev);380	ret = device_add(&func->dev);381	if (ret == 0)382		sdio_func_set_present(func);383 384	return ret;385}386 387/*388 * Unregister a SDIO function with the driver model, and389 * (eventually) free it.390 * This function can be called through error paths where sdio_add_func() was391 * never executed (because a failure occurred at an earlier point).392 */393void sdio_remove_func(struct sdio_func *func)394{395	if (sdio_func_present(func))396		device_del(&func->dev);397 398	of_node_put(func->dev.of_node);399	put_device(&func->dev);400}401 402