sdio_bus.c revision ed919b0125b26dcc052e44836f66e7e1f5c49c7e
1e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/*
2e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman *  linux/drivers/mmc/core/sdio_bus.c
3e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman *
4e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman *  Copyright 2007 Pierre Ossman
5e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman *
6e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * This program is free software; you can redistribute it and/or modify
7e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * it under the terms of the GNU General Public License as published by
8e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * the Free Software Foundation; either version 2 of the License, or (at
9e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * your option) any later version.
10e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman *
11e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * SDIO function driver model
12e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */
13e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
14e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/device.h>
15e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/err.h>
165a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
1780fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#include <linux/pm_runtime.h>
18e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
19e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/mmc/card.h>
20ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen#include <linux/mmc/host.h>
21e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/mmc/sdio_func.h>
22e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
23b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre#include "sdio_cis.h"
24e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include "sdio_bus.h"
25e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
26bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman/* show configuration fields */
27bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman#define sdio_config_attr(field, format_string)				\
28bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmanstatic ssize_t								\
29bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmanfield##_show(struct device *dev, struct device_attribute *attr, char *buf)				\
30bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman{									\
31bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	struct sdio_func *func;						\
32bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman									\
33bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	func = dev_to_sdio_func (dev);					\
34bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	return sprintf (buf, format_string, func->field);		\
35bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman}
36bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman
37bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmansdio_config_attr(class, "0x%02x\n");
38bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmansdio_config_attr(vendor, "0x%04x\n");
39bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmansdio_config_attr(device, "0x%04x\n");
40bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman
41bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmanstatic ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
42bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman{
43bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	struct sdio_func *func = dev_to_sdio_func (dev);
44bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman
45bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n",
46bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman			func->class, func->vendor, func->device);
47bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman}
48bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman
4922bfc979d38f57d5b10d141990175d8fc47f6775Adrian Bunkstatic struct device_attribute sdio_dev_attrs[] = {
50bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	__ATTR_RO(class),
51bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	__ATTR_RO(vendor),
52bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	__ATTR_RO(device),
53bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	__ATTR_RO(modalias),
54bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	__ATTR_NULL,
55bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman};
56bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman
573b38bea0d976513970f947806b08b9faca418e7aPierre Ossmanstatic const struct sdio_device_id *sdio_match_one(struct sdio_func *func,
583b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	const struct sdio_device_id *id)
593b38bea0d976513970f947806b08b9faca418e7aPierre Ossman{
603b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class)
613b38bea0d976513970f947806b08b9faca418e7aPierre Ossman		return NULL;
623b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor)
633b38bea0d976513970f947806b08b9faca418e7aPierre Ossman		return NULL;
643b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device)
653b38bea0d976513970f947806b08b9faca418e7aPierre Ossman		return NULL;
663b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	return id;
673b38bea0d976513970f947806b08b9faca418e7aPierre Ossman}
683b38bea0d976513970f947806b08b9faca418e7aPierre Ossman
693b38bea0d976513970f947806b08b9faca418e7aPierre Ossmanstatic const struct sdio_device_id *sdio_match_device(struct sdio_func *func,
703b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	struct sdio_driver *sdrv)
713b38bea0d976513970f947806b08b9faca418e7aPierre Ossman{
723b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	const struct sdio_device_id *ids;
733b38bea0d976513970f947806b08b9faca418e7aPierre Ossman
743b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	ids = sdrv->id_table;
753b38bea0d976513970f947806b08b9faca418e7aPierre Ossman
763b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	if (ids) {
773b38bea0d976513970f947806b08b9faca418e7aPierre Ossman		while (ids->class || ids->vendor || ids->device) {
783b38bea0d976513970f947806b08b9faca418e7aPierre Ossman			if (sdio_match_one(func, ids))
793b38bea0d976513970f947806b08b9faca418e7aPierre Ossman				return ids;
803b38bea0d976513970f947806b08b9faca418e7aPierre Ossman			ids++;
813b38bea0d976513970f947806b08b9faca418e7aPierre Ossman		}
823b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	}
833b38bea0d976513970f947806b08b9faca418e7aPierre Ossman
843b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	return NULL;
853b38bea0d976513970f947806b08b9faca418e7aPierre Ossman}
86e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
87e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_match(struct device *dev, struct device_driver *drv)
88e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
893b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	struct sdio_func *func = dev_to_sdio_func(dev);
903b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	struct sdio_driver *sdrv = to_sdio_driver(drv);
913b38bea0d976513970f947806b08b9faca418e7aPierre Ossman
923b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	if (sdio_match_device(func, sdrv))
933b38bea0d976513970f947806b08b9faca418e7aPierre Ossman		return 1;
943b38bea0d976513970f947806b08b9faca418e7aPierre Ossman
953b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	return 0;
96e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
97e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
98e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int
997ac0326c3fd3f7cd2426dbbce896a0f8c91b962fAl Virosdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
100e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
101d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman	struct sdio_func *func = dev_to_sdio_func(dev);
102d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman
1037ac0326c3fd3f7cd2426dbbce896a0f8c91b962fAl Viro	if (add_uevent_var(env,
104d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman			"SDIO_CLASS=%02X", func->class))
105d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman		return -ENOMEM;
106d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman
1077ac0326c3fd3f7cd2426dbbce896a0f8c91b962fAl Viro	if (add_uevent_var(env,
108d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman			"SDIO_ID=%04X:%04X", func->vendor, func->device))
109d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman		return -ENOMEM;
110d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman
1117ac0326c3fd3f7cd2426dbbce896a0f8c91b962fAl Viro	if (add_uevent_var(env,
112d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman			"MODALIAS=sdio:c%02Xv%04Xd%04X",
113d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman			func->class, func->vendor, func->device))
114d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman		return -ENOMEM;
115d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman
116e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return 0;
117e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
118e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
119e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_probe(struct device *dev)
120e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
1213b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	struct sdio_driver *drv = to_sdio_driver(dev->driver);
1223b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	struct sdio_func *func = dev_to_sdio_func(dev);
1233b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	const struct sdio_device_id *id;
1249a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel	int ret;
1253b38bea0d976513970f947806b08b9faca418e7aPierre Ossman
1263b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	id = sdio_match_device(func, drv);
1273b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	if (!id)
1283b38bea0d976513970f947806b08b9faca418e7aPierre Ossman		return -ENODEV;
1293b38bea0d976513970f947806b08b9faca418e7aPierre Ossman
13040bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	/* Unbound SDIO functions are always suspended.
13140bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	 * During probe, the function is set active and the usage count
13240bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	 * is incremented.  If the driver supports runtime PM,
13340bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	 * it should call pm_runtime_put_noidle() in its probe routine and
13440bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	 * pm_runtime_get_noresume() in its remove routine.
13540bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	 */
136ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
137ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen		ret = pm_runtime_get_sync(dev);
138ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen		if (ret < 0)
139ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen			goto out;
140ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen	}
14140bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen
1429a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel	/* Set the default block size so the driver is sure it's something
1439a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel	 * sensible. */
1449a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel	sdio_claim_host(func);
1459a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel	ret = sdio_set_block_size(func, 0);
1469a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel	sdio_release_host(func);
1479a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel	if (ret)
14840bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen		goto disable_runtimepm;
14940bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen
15040bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	ret = drv->probe(func, id);
15140bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	if (ret)
15240bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen		goto disable_runtimepm;
15340bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen
15440bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	return 0;
1559a08f82b3cc522f727ace580a2aaee5402435bc8David Vrabel
15640bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohendisable_runtimepm:
157ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
158ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen		pm_runtime_put_noidle(dev);
15940bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohenout:
16040bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	return ret;
161e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
162e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
163e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_remove(struct device *dev)
164e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
1653b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	struct sdio_driver *drv = to_sdio_driver(dev->driver);
1663b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	struct sdio_func *func = dev_to_sdio_func(dev);
167ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen	int ret = 0;
16840bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen
16940bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	/* Make sure card is powered before invoking ->remove() */
170ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
171ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen		ret = pm_runtime_get_sync(dev);
172ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen		if (ret < 0)
173ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen			goto out;
174ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen	}
1753b38bea0d976513970f947806b08b9faca418e7aPierre Ossman
1763b38bea0d976513970f947806b08b9faca418e7aPierre Ossman	drv->remove(func);
1773b38bea0d976513970f947806b08b9faca418e7aPierre Ossman
178d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre	if (func->irq_handler) {
179d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre		printk(KERN_WARNING "WARNING: driver %s did not remove "
180d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre			"its interrupt handler!\n", drv->name);
181d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre		sdio_claim_host(func);
182d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre		sdio_release_irq(func);
183d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre		sdio_release_host(func);
184d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre	}
185d1496c39e500857b8949cdb91af24e0eb8aae4d0Nicolas Pitre
18640bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	/* First, undo the increment made directly above */
187ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
188ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen		pm_runtime_put_noidle(dev);
18940bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen
19040bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	/* Then undo the runtime PM settings in sdio_bus_probe() */
191ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
192ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen		pm_runtime_put_noidle(dev);
19340bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen
19440bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohenout:
19540bba0c1ca83a370f749c8bc9afda71cf79ebd91Ohad Ben-Cohen	return ret;
196e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
197e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
19880fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#ifdef CONFIG_PM_RUNTIME
19980fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen
200ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohenstatic int sdio_bus_pm_prepare(struct device *dev)
201ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen{
202ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen	struct sdio_func *func = dev_to_sdio_func(dev);
203ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen
204ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	/*
205ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * Resume an SDIO device which was suspended at run time at this
206ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * point, in order to allow standard SDIO suspend/resume paths
207ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * to keep working as usual.
208ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 *
209ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * Ultimately, the SDIO driver itself will decide (in its
210ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * suspend handler, or lack thereof) whether the card should be
211ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * removed or kept, and if kept, at what power state.
212ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 *
213ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * At this point, PM core have increased our use count, so it's
214ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * safe to directly resume the device. After system is resumed
215ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * again, PM core will drop back its runtime PM use count, and if
216ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * needed device will be suspended again.
217ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 *
218ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * The end result is guaranteed to be a power state that is
219ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * coherent with the device's runtime PM use count.
220ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 *
221ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * The return value of pm_runtime_resume is deliberately unchecked
222ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * since there is little point in failing system suspend if a
223ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 * device can't be resumed.
224ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	 */
225ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
226ed919b0125b26dcc052e44836f66e7e1f5c49c7eOhad Ben-Cohen		pm_runtime_resume(dev);
227ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen
228ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	return 0;
229ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen}
230ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen
23180fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohenstatic const struct dev_pm_ops sdio_bus_pm_ops = {
23280fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen	SET_RUNTIME_PM_OPS(
23380fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen		pm_generic_runtime_suspend,
23480fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen		pm_generic_runtime_resume,
23580fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen		pm_generic_runtime_idle
23680fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen	)
237ed2a9785942b0986ac858f3f48d7fc5f7c7183deOhad Ben-Cohen	.prepare = sdio_bus_pm_prepare,
23880fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen};
23980fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen
24080fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#define SDIO_PM_OPS_PTR	(&sdio_bus_pm_ops)
24180fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen
24280fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#else /* !CONFIG_PM_RUNTIME */
24380fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen
24480fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#define SDIO_PM_OPS_PTR	NULL
24580fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen
24680fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen#endif /* !CONFIG_PM_RUNTIME */
24780fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen
248e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic struct bus_type sdio_bus_type = {
249e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.name		= "sdio",
250bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman	.dev_attrs	= sdio_dev_attrs,
251e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.match		= sdio_bus_match,
252e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.uevent		= sdio_bus_uevent,
253e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.probe		= sdio_bus_probe,
254e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.remove		= sdio_bus_remove,
25580fd933c44557c5261b80f8f8145b4fe071aeaf3Ohad Ben-Cohen	.pm		= SDIO_PM_OPS_PTR,
256e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman};
257e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
258e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_register_bus(void)
259e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
260e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return bus_register(&sdio_bus_type);
261e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
262e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
263e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_unregister_bus(void)
264e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
265e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	bus_unregister(&sdio_bus_type);
266e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
267e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
268f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/**
269f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman *	sdio_register_driver - register a function driver
270f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman *	@drv: SDIO function driver
271f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */
272f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanint sdio_register_driver(struct sdio_driver *drv)
273f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{
274f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman	drv->drv.name = drv->name;
275f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman	drv->drv.bus = &sdio_bus_type;
276f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman	return driver_register(&drv->drv);
277f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman}
278f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_register_driver);
279f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman
280f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/**
281f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman *	sdio_unregister_driver - unregister a function driver
282f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman *	@drv: SDIO function driver
283f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */
284f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanvoid sdio_unregister_driver(struct sdio_driver *drv)
285f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{
286f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman	drv->drv.bus = &sdio_bus_type;
287f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman	driver_unregister(&drv->drv);
288f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman}
289f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_unregister_driver);
290f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman
291e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic void sdio_release_func(struct device *dev)
292e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
293e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	struct sdio_func *func = dev_to_sdio_func(dev);
294b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre
2951a632f8cdc33e7f8edca352164f0c96a75d08f08Pierre Ossman	sdio_free_func_cis(func);
296e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
297759bdc7af450404382e937c76722ae8736daef92Pierre Ossman	if (func->info)
298759bdc7af450404382e937c76722ae8736daef92Pierre Ossman		kfree(func->info);
299759bdc7af450404382e937c76722ae8736daef92Pierre Ossman
300e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	kfree(func);
301e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
302e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
303e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/*
304e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Allocate and initialise a new SDIO function structure.
305e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */
306e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstruct sdio_func *sdio_alloc_func(struct mmc_card *card)
307e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
308e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	struct sdio_func *func;
309e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
3109f2fcf99394b34769e3243a7f42a0ba8d21fc774Mariusz Kozlowski	func = kzalloc(sizeof(struct sdio_func), GFP_KERNEL);
311e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	if (!func)
312e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman		return ERR_PTR(-ENOMEM);
313e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
314e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->card = card;
315e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
316e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	device_initialize(&func->dev);
317e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
318e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->dev.parent = &card->dev;
319e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->dev.bus = &sdio_bus_type;
320e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->dev.release = sdio_release_func;
321e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
322e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return func;
323e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
324e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
325e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/*
326e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Register a new SDIO function with the driver model.
327e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */
328e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_add_func(struct sdio_func *func)
329e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
330e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	int ret;
331e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
332d1b268630875a7713b5d468a0c03403c5b721c8eKay Sievers	dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
333e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
334e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	ret = device_add(&func->dev);
335e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	if (ret == 0)
336e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman		sdio_func_set_present(func);
337e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
338e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return ret;
339e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
340e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
341e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/*
342e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Unregister a SDIO function with the driver model, and
343e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * (eventually) free it.
3443d10a1ba0d37c8f5fd5afcdda00613fbb8a90bf5Daniel Drake * This function can be called through error paths where sdio_add_func() was
3453d10a1ba0d37c8f5fd5afcdda00613fbb8a90bf5Daniel Drake * never executed (because a failure occurred at an earlier point).
346e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */
347e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_remove_func(struct sdio_func *func)
348e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
3493d10a1ba0d37c8f5fd5afcdda00613fbb8a90bf5Daniel Drake	if (!sdio_func_present(func))
3503d10a1ba0d37c8f5fd5afcdda00613fbb8a90bf5Daniel Drake		return;
351e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
3523d10a1ba0d37c8f5fd5afcdda00613fbb8a90bf5Daniel Drake	device_del(&func->dev);
353e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	put_device(&func->dev);
354e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
355e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
356