sdio_bus.c 8.0 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 201 202 203 204 205 206 207 208 209 210 211

#ifdef CONFIG_PM_SLEEP
static int pm_no_operation(struct device *dev)
{
	/*
	 * Prevent the PM core from calling SDIO device drivers' suspend
	 * callback routines, which it is not supposed to do, by using this
	 * empty function as the bus type suspend callaback for SDIO.
	 */
	return 0;
}
#endif

212
static const struct dev_pm_ops sdio_bus_pm_ops = {
213
	SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
214 215 216
	SET_RUNTIME_PM_OPS(
		pm_generic_runtime_suspend,
		pm_generic_runtime_resume,
217
		NULL
218 219 220 221 222
	)
};

#define SDIO_PM_OPS_PTR	(&sdio_bus_pm_ops)

223
#else /* !CONFIG_PM */
224 225 226

#define SDIO_PM_OPS_PTR	NULL

227
#endif /* !CONFIG_PM */
228

P
Pierre Ossman 已提交
229 230
static struct bus_type sdio_bus_type = {
	.name		= "sdio",
231
	.dev_groups	= sdio_dev_groups,
P
Pierre Ossman 已提交
232 233 234 235
	.match		= sdio_bus_match,
	.uevent		= sdio_bus_uevent,
	.probe		= sdio_bus_probe,
	.remove		= sdio_bus_remove,
236
	.pm		= SDIO_PM_OPS_PTR,
P
Pierre Ossman 已提交
237 238 239 240 241 242 243 244 245 246 247 248
};

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

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

P
Pierre Ossman 已提交
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
/**
 *	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 已提交
272 273 274
static void sdio_release_func(struct device *dev)
{
	struct sdio_func *func = dev_to_sdio_func(dev);
275

276
	sdio_free_func_cis(func);
P
Pierre Ossman 已提交
277

278
	kfree(func->info);
P
Pierre Ossman 已提交
279

P
Pierre Ossman 已提交
280 281 282 283 284 285 286 287 288 289
	kfree(func);
}

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

290
	func = kzalloc(sizeof(struct sdio_func), GFP_KERNEL);
P
Pierre Ossman 已提交
291 292 293 294 295 296 297 298 299 300 301 302 303 304
	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;
}

305 306 307 308 309 310
#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;

311
	acpi_preset_companion(&func->dev, ACPI_COMPANION(host->parent), addr);
312 313 314 315 316
}
#else
static inline void sdio_acpi_set_handle(struct sdio_func *func) {}
#endif

P
Pierre Ossman 已提交
317 318 319 320 321 322 323
/*
 * Register a new SDIO function with the driver model.
 */
int sdio_add_func(struct sdio_func *func)
{
	int ret;

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

326
	sdio_acpi_set_handle(func);
P
Pierre Ossman 已提交
327
	ret = device_add(&func->dev);
328
	if (ret == 0) {
P
Pierre Ossman 已提交
329
		sdio_func_set_present(func);
330 331
		acpi_dev_pm_attach(&func->dev, false);
	}
P
Pierre Ossman 已提交
332 333 334 335 336 337 338

	return ret;
}

/*
 * Unregister a SDIO function with the driver model, and
 * (eventually) free it.
339 340
 * 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 已提交
341 342 343
 */
void sdio_remove_func(struct sdio_func *func)
{
344 345
	if (!sdio_func_present(func))
		return;
P
Pierre Ossman 已提交
346

347
	acpi_dev_pm_detach(&func->dev, false);
348
	device_del(&func->dev);
P
Pierre Ossman 已提交
349 350 351
	put_device(&func->dev);
}