sdio_bus.c 7.7 KB
Newer Older
P
Pierre Ossman 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 *  linux/drivers/mmc/core/sdio_bus.c
 *
 *  Copyright 2007 Pierre Ossman
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * SDIO function driver model
 */

#include <linux/device.h>
#include <linux/err.h>
16
#include <linux/export.h>
17
#include <linux/slab.h>
18
#include <linux/pm_runtime.h>
19
#include <linux/acpi.h>
P
Pierre Ossman 已提交
20 21

#include <linux/mmc/card.h>
22
#include <linux/mmc/host.h>
P
Pierre Ossman 已提交
23 24
#include <linux/mmc/sdio_func.h>

25
#include "sdio_cis.h"
P
Pierre Ossman 已提交
26 27
#include "sdio_bus.h"

P
Pierre Ossman 已提交
28 29 30 31 32 33 34 35 36
/* show configuration fields */
#define sdio_config_attr(field, format_string)				\
static ssize_t								\
field##_show(struct device *dev, struct device_attribute *attr, char *buf)				\
{									\
	struct sdio_func *func;						\
									\
	func = dev_to_sdio_func (dev);					\
	return sprintf (buf, format_string, func->field);		\
37 38
}									\
static DEVICE_ATTR_RO(field)
P
Pierre Ossman 已提交
39 40 41 42 43 44 45 46 47 48 49 50

sdio_config_attr(class, "0x%02x\n");
sdio_config_attr(vendor, "0x%04x\n");
sdio_config_attr(device, "0x%04x\n");

static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct sdio_func *func = dev_to_sdio_func (dev);

	return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n",
			func->class, func->vendor, func->device);
}
51 52 53 54 55 56 57 58
static DEVICE_ATTR_RO(modalias);

static struct attribute *sdio_dev_attrs[] = {
	&dev_attr_class.attr,
	&dev_attr_vendor.attr,
	&dev_attr_device.attr,
	&dev_attr_modalias.attr,
	NULL,
P
Pierre Ossman 已提交
59
};
60
ATTRIBUTE_GROUPS(sdio_dev);
P
Pierre Ossman 已提交
61

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,
	const struct sdio_device_id *id)
{
	if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class)
		return NULL;
	if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor)
		return NULL;
	if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device)
		return NULL;
	return id;
}

static const struct sdio_device_id *sdio_match_device(struct sdio_func *func,
	struct sdio_driver *sdrv)
{
	const struct sdio_device_id *ids;

	ids = sdrv->id_table;

	if (ids) {
		while (ids->class || ids->vendor || ids->device) {
			if (sdio_match_one(func, ids))
				return ids;
			ids++;
		}
	}

	return NULL;
}
P
Pierre Ossman 已提交
91 92 93

static int sdio_bus_match(struct device *dev, struct device_driver *drv)
{
94 95 96 97 98 99 100
	struct sdio_func *func = dev_to_sdio_func(dev);
	struct sdio_driver *sdrv = to_sdio_driver(drv);

	if (sdio_match_device(func, sdrv))
		return 1;

	return 0;
P
Pierre Ossman 已提交
101 102 103
}

static int
A
Al Viro 已提交
104
sdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
P
Pierre Ossman 已提交
105
{
P
Pierre Ossman 已提交
106 107
	struct sdio_func *func = dev_to_sdio_func(dev);

A
Al Viro 已提交
108
	if (add_uevent_var(env,
P
Pierre Ossman 已提交
109 110 111
			"SDIO_CLASS=%02X", func->class))
		return -ENOMEM;

A
Al Viro 已提交
112
	if (add_uevent_var(env, 
P
Pierre Ossman 已提交
113 114 115
			"SDIO_ID=%04X:%04X", func->vendor, func->device))
		return -ENOMEM;

A
Al Viro 已提交
116
	if (add_uevent_var(env,
P
Pierre Ossman 已提交
117 118 119 120
			"MODALIAS=sdio:c%02Xv%04Xd%04X",
			func->class, func->vendor, func->device))
		return -ENOMEM;

P
Pierre Ossman 已提交
121 122 123 124 125
	return 0;
}

static int sdio_bus_probe(struct device *dev)
{
126 127 128
	struct sdio_driver *drv = to_sdio_driver(dev->driver);
	struct sdio_func *func = dev_to_sdio_func(dev);
	const struct sdio_device_id *id;
129
	int ret;
130 131 132 133 134

	id = sdio_match_device(func, drv);
	if (!id)
		return -ENODEV;

135 136 137 138 139 140
	/* Unbound SDIO functions are always suspended.
	 * During probe, the function is set active and the usage count
	 * is incremented.  If the driver supports runtime PM,
	 * it should call pm_runtime_put_noidle() in its probe routine and
	 * pm_runtime_get_noresume() in its remove routine.
	 */
141 142 143
	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
		ret = pm_runtime_get_sync(dev);
		if (ret < 0)
144
			goto disable_runtimepm;
145
	}
146

147 148 149 150 151 152
	/* Set the default block size so the driver is sure it's something
	 * sensible. */
	sdio_claim_host(func);
	ret = sdio_set_block_size(func, 0);
	sdio_release_host(func);
	if (ret)
153 154 155 156 157 158 159
		goto disable_runtimepm;

	ret = drv->probe(func, id);
	if (ret)
		goto disable_runtimepm;

	return 0;
160

161
disable_runtimepm:
162 163
	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
		pm_runtime_put_noidle(dev);
164
	return ret;
P
Pierre Ossman 已提交
165 166 167 168
}

static int sdio_bus_remove(struct device *dev)
{
169 170
	struct sdio_driver *drv = to_sdio_driver(dev->driver);
	struct sdio_func *func = dev_to_sdio_func(dev);
171
	int ret = 0;
172 173

	/* Make sure card is powered before invoking ->remove() */
174 175
	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
		pm_runtime_get_sync(dev);
176 177 178

	drv->remove(func);

179
	if (func->irq_handler) {
180
		pr_warning("WARNING: driver %s did not remove "
181 182 183 184 185 186
			"its interrupt handler!\n", drv->name);
		sdio_claim_host(func);
		sdio_release_irq(func);
		sdio_release_host(func);
	}

187
	/* First, undo the increment made directly above */
188 189
	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
		pm_runtime_put_noidle(dev);
190 191

	/* Then undo the runtime PM settings in sdio_bus_probe() */
192
	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
193
		pm_runtime_put_sync(dev);
194 195

	return ret;
P
Pierre Ossman 已提交
196 197
}

198
#ifdef CONFIG_PM
199

200
static const struct dev_pm_ops sdio_bus_pm_ops = {
201
	SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)
202 203 204
	SET_RUNTIME_PM_OPS(
		pm_generic_runtime_suspend,
		pm_generic_runtime_resume,
205
		NULL
206 207 208 209 210
	)
};

#define SDIO_PM_OPS_PTR	(&sdio_bus_pm_ops)

211
#else /* !CONFIG_PM */
212 213 214

#define SDIO_PM_OPS_PTR	NULL

215
#endif /* !CONFIG_PM */
216

P
Pierre Ossman 已提交
217 218
static struct bus_type sdio_bus_type = {
	.name		= "sdio",
219
	.dev_groups	= sdio_dev_groups,
P
Pierre Ossman 已提交
220 221 222 223
	.match		= sdio_bus_match,
	.uevent		= sdio_bus_uevent,
	.probe		= sdio_bus_probe,
	.remove		= sdio_bus_remove,
224
	.pm		= SDIO_PM_OPS_PTR,
P
Pierre Ossman 已提交
225 226 227 228 229 230 231 232 233 234 235 236
};

int sdio_register_bus(void)
{
	return bus_register(&sdio_bus_type);
}

void sdio_unregister_bus(void)
{
	bus_unregister(&sdio_bus_type);
}

P
Pierre Ossman 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
/**
 *	sdio_register_driver - register a function driver
 *	@drv: SDIO function driver
 */
int sdio_register_driver(struct sdio_driver *drv)
{
	drv->drv.name = drv->name;
	drv->drv.bus = &sdio_bus_type;
	return driver_register(&drv->drv);
}
EXPORT_SYMBOL_GPL(sdio_register_driver);

/**
 *	sdio_unregister_driver - unregister a function driver
 *	@drv: SDIO function driver
 */
void sdio_unregister_driver(struct sdio_driver *drv)
{
	drv->drv.bus = &sdio_bus_type;
	driver_unregister(&drv->drv);
}
EXPORT_SYMBOL_GPL(sdio_unregister_driver);

P
Pierre Ossman 已提交
260 261 262
static void sdio_release_func(struct device *dev)
{
	struct sdio_func *func = dev_to_sdio_func(dev);
263

264
	sdio_free_func_cis(func);
P
Pierre Ossman 已提交
265

266
	kfree(func->info);
P
Pierre Ossman 已提交
267

P
Pierre Ossman 已提交
268 269 270 271 272 273 274 275 276 277
	kfree(func);
}

/*
 * Allocate and initialise a new SDIO function structure.
 */
struct sdio_func *sdio_alloc_func(struct mmc_card *card)
{
	struct sdio_func *func;

278
	func = kzalloc(sizeof(struct sdio_func), GFP_KERNEL);
P
Pierre Ossman 已提交
279 280 281 282 283 284 285 286 287 288 289 290 291 292
	if (!func)
		return ERR_PTR(-ENOMEM);

	func->card = card;

	device_initialize(&func->dev);

	func->dev.parent = &card->dev;
	func->dev.bus = &sdio_bus_type;
	func->dev.release = sdio_release_func;

	return func;
}

293 294 295 296 297 298
#ifdef CONFIG_ACPI
static void sdio_acpi_set_handle(struct sdio_func *func)
{
	struct mmc_host *host = func->card->host;
	u64 addr = (host->slotno << 16) | func->num;

299
	acpi_preset_companion(&func->dev, ACPI_COMPANION(host->parent), addr);
300 301 302 303 304
}
#else
static inline void sdio_acpi_set_handle(struct sdio_func *func) {}
#endif

P
Pierre Ossman 已提交
305 306 307 308 309 310 311
/*
 * Register a new SDIO function with the driver model.
 */
int sdio_add_func(struct sdio_func *func)
{
	int ret;

312
	dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
P
Pierre Ossman 已提交
313

314
	sdio_acpi_set_handle(func);
P
Pierre Ossman 已提交
315
	ret = device_add(&func->dev);
316
	if (ret == 0) {
P
Pierre Ossman 已提交
317
		sdio_func_set_present(func);
318
		dev_pm_domain_attach(&func->dev, false);
319
	}
P
Pierre Ossman 已提交
320 321 322 323 324 325 326

	return ret;
}

/*
 * Unregister a SDIO function with the driver model, and
 * (eventually) free it.
327 328
 * This function can be called through error paths where sdio_add_func() was
 * never executed (because a failure occurred at an earlier point).
P
Pierre Ossman 已提交
329 330 331
 */
void sdio_remove_func(struct sdio_func *func)
{
332 333
	if (!sdio_func_present(func))
		return;
P
Pierre Ossman 已提交
334

335
	dev_pm_domain_detach(&func->dev, false);
336
	device_del(&func->dev);
P
Pierre Ossman 已提交
337 338 339
	put_device(&func->dev);
}