sdio_bus.c 7.8 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/slab.h>
17
#include <linux/pm_runtime.h>
P
Pierre Ossman 已提交
18 19 20 21

#include <linux/mmc/card.h>
#include <linux/mmc/sdio_func.h>

22
#include "sdio_cis.h"
P
Pierre Ossman 已提交
23 24
#include "sdio_bus.h"

P
Pierre Ossman 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
/* 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);		\
}

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);
}

48
static struct device_attribute sdio_dev_attrs[] = {
P
Pierre Ossman 已提交
49 50 51 52 53 54 55
	__ATTR_RO(class),
	__ATTR_RO(vendor),
	__ATTR_RO(device),
	__ATTR_RO(modalias),
	__ATTR_NULL,
};

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
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 已提交
85 86 87

static int sdio_bus_match(struct device *dev, struct device_driver *drv)
{
88 89 90 91 92 93 94
	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 已提交
95 96 97
}

static int
A
Al Viro 已提交
98
sdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
P
Pierre Ossman 已提交
99
{
P
Pierre Ossman 已提交
100 101
	struct sdio_func *func = dev_to_sdio_func(dev);

A
Al Viro 已提交
102
	if (add_uevent_var(env,
P
Pierre Ossman 已提交
103 104 105
			"SDIO_CLASS=%02X", func->class))
		return -ENOMEM;

A
Al Viro 已提交
106
	if (add_uevent_var(env, 
P
Pierre Ossman 已提交
107 108 109
			"SDIO_ID=%04X:%04X", func->vendor, func->device))
		return -ENOMEM;

A
Al Viro 已提交
110
	if (add_uevent_var(env,
P
Pierre Ossman 已提交
111 112 113 114
			"MODALIAS=sdio:c%02Xv%04Xd%04X",
			func->class, func->vendor, func->device))
		return -ENOMEM;

P
Pierre Ossman 已提交
115 116 117 118 119
	return 0;
}

static int sdio_bus_probe(struct device *dev)
{
120 121 122
	struct sdio_driver *drv = to_sdio_driver(dev->driver);
	struct sdio_func *func = dev_to_sdio_func(dev);
	const struct sdio_device_id *id;
123
	int ret;
124 125 126 127 128

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

129 130 131 132 133 134 135 136 137 138
	/* 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.
	 */
	ret = pm_runtime_get_sync(dev);
	if (ret < 0)
		goto out;

139 140 141 142 143 144
	/* 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)
145 146 147 148 149 150 151
		goto disable_runtimepm;

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

	return 0;
152

153 154 155 156
disable_runtimepm:
	pm_runtime_put_noidle(dev);
out:
	return ret;
P
Pierre Ossman 已提交
157 158 159 160
}

static int sdio_bus_remove(struct device *dev)
{
161 162
	struct sdio_driver *drv = to_sdio_driver(dev->driver);
	struct sdio_func *func = dev_to_sdio_func(dev);
163 164 165 166 167 168
	int ret;

	/* Make sure card is powered before invoking ->remove() */
	ret = pm_runtime_get_sync(dev);
	if (ret < 0)
		goto out;
169 170 171

	drv->remove(func);

172 173 174 175 176 177 178 179
	if (func->irq_handler) {
		printk(KERN_WARNING "WARNING: driver %s did not remove "
			"its interrupt handler!\n", drv->name);
		sdio_claim_host(func);
		sdio_release_irq(func);
		sdio_release_host(func);
	}

180 181 182 183 184 185 186 187
	/* First, undo the increment made directly above */
	pm_runtime_put_noidle(dev);

	/* Then undo the runtime PM settings in sdio_bus_probe() */
	pm_runtime_put_noidle(dev);

out:
	return ret;
P
Pierre Ossman 已提交
188 189
}

190 191
#ifdef CONFIG_PM_RUNTIME

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
static int sdio_bus_pm_prepare(struct device *dev)
{
	/*
	 * Resume an SDIO device which was suspended at run time at this
	 * point, in order to allow standard SDIO suspend/resume paths
	 * to keep working as usual.
	 *
	 * Ultimately, the SDIO driver itself will decide (in its
	 * suspend handler, or lack thereof) whether the card should be
	 * removed or kept, and if kept, at what power state.
	 *
	 * At this point, PM core have increased our use count, so it's
	 * safe to directly resume the device. After system is resumed
	 * again, PM core will drop back its runtime PM use count, and if
	 * needed device will be suspended again.
	 *
	 * The end result is guaranteed to be a power state that is
	 * coherent with the device's runtime PM use count.
	 *
	 * The return value of pm_runtime_resume is deliberately unchecked
	 * since there is little point in failing system suspend if a
	 * device can't be resumed.
	 */
	pm_runtime_resume(dev);

	return 0;
}

220 221 222 223 224 225
static const struct dev_pm_ops sdio_bus_pm_ops = {
	SET_RUNTIME_PM_OPS(
		pm_generic_runtime_suspend,
		pm_generic_runtime_resume,
		pm_generic_runtime_idle
	)
226
	.prepare = sdio_bus_pm_prepare,
227 228 229 230 231 232 233 234 235 236
};

#define SDIO_PM_OPS_PTR	(&sdio_bus_pm_ops)

#else /* !CONFIG_PM_RUNTIME */

#define SDIO_PM_OPS_PTR	NULL

#endif /* !CONFIG_PM_RUNTIME */

P
Pierre Ossman 已提交
237 238
static struct bus_type sdio_bus_type = {
	.name		= "sdio",
P
Pierre Ossman 已提交
239
	.dev_attrs	= sdio_dev_attrs,
P
Pierre Ossman 已提交
240 241 242 243
	.match		= sdio_bus_match,
	.uevent		= sdio_bus_uevent,
	.probe		= sdio_bus_probe,
	.remove		= sdio_bus_remove,
244
	.pm		= SDIO_PM_OPS_PTR,
P
Pierre Ossman 已提交
245 246 247 248 249 250 251 252 253 254 255 256
};

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

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

P
Pierre Ossman 已提交
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
/**
 *	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 已提交
280 281 282
static void sdio_release_func(struct device *dev)
{
	struct sdio_func *func = dev_to_sdio_func(dev);
283

284
	sdio_free_func_cis(func);
P
Pierre Ossman 已提交
285

P
Pierre Ossman 已提交
286 287 288
	if (func->info)
		kfree(func->info);

P
Pierre Ossman 已提交
289 290 291 292 293 294 295 296 297 298
	kfree(func);
}

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

299
	func = kzalloc(sizeof(struct sdio_func), GFP_KERNEL);
P
Pierre Ossman 已提交
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
	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;
}

/*
 * Register a new SDIO function with the driver model.
 */
int sdio_add_func(struct sdio_func *func)
{
	int ret;

321
	dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
P
Pierre Ossman 已提交
322 323 324 325 326 327 328 329 330 331 332

	ret = device_add(&func->dev);
	if (ret == 0)
		sdio_func_set_present(func);

	return ret;
}

/*
 * Unregister a SDIO function with the driver model, and
 * (eventually) free it.
333 334
 * 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 已提交
335 336 337
 */
void sdio_remove_func(struct sdio_func *func)
{
338 339
	if (!sdio_func_present(func))
		return;
P
Pierre Ossman 已提交
340

341
	device_del(&func->dev);
P
Pierre Ossman 已提交
342 343 344
	put_device(&func->dev);
}