sdio_bus.c revision e29a7d73f4277eb92aa64e17017dea33460828ef
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>
16e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
17e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/mmc/card.h>
18e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/mmc/sdio_func.h>
19e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
20e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include "sdio_bus.h"
21e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
22e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#define dev_to_sdio_func(d)	container_of(d, struct sdio_func, dev)
23e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
24e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/*
25e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * This currently matches any SDIO function to any driver in order
26e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * to help initial development and testing.
27e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */
28e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_match(struct device *dev, struct device_driver *drv)
29e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
30e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return 1;
31e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
32e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
33e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int
34e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmansdio_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
35e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman		int buf_size)
36e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
37e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	envp[0] = NULL;
38e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
39e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return 0;
40e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
41e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
42e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_probe(struct device *dev)
43e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
44e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return -ENODEV;
45e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
46e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
47e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_remove(struct device *dev)
48e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
49e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return 0;
50e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
51e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
52e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic struct bus_type sdio_bus_type = {
53e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.name		= "sdio",
54e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.match		= sdio_bus_match,
55e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.uevent		= sdio_bus_uevent,
56e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.probe		= sdio_bus_probe,
57e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	.remove		= sdio_bus_remove,
58e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman};
59e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
60e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_register_bus(void)
61e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
62e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return bus_register(&sdio_bus_type);
63e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
64e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
65e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_unregister_bus(void)
66e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
67e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	bus_unregister(&sdio_bus_type);
68e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
69e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
70e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic void sdio_release_func(struct device *dev)
71e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
72e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	struct sdio_func *func = dev_to_sdio_func(dev);
73e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
74e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	kfree(func);
75e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
76e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
77e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/*
78e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Allocate and initialise a new SDIO function structure.
79e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */
80e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstruct sdio_func *sdio_alloc_func(struct mmc_card *card)
81e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
82e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	struct sdio_func *func;
83e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
84e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func = kmalloc(sizeof(struct sdio_func), GFP_KERNEL);
85e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	if (!func)
86e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman		return ERR_PTR(-ENOMEM);
87e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
88e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	memset(func, 0, sizeof(struct sdio_func));
89e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
90e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->card = card;
91e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
92e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	device_initialize(&func->dev);
93e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
94e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->dev.parent = &card->dev;
95e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->dev.bus = &sdio_bus_type;
96e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	func->dev.release = sdio_release_func;
97e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
98e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return func;
99e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
100e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
101e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/*
102e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Register a new SDIO function with the driver model.
103e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */
104e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_add_func(struct sdio_func *func)
105e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
106e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	int ret;
107e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
108e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	snprintf(func->dev.bus_id, sizeof(func->dev.bus_id),
109e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman		 "%s:%d", mmc_card_id(func->card), func->num);
110e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
111e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	ret = device_add(&func->dev);
112e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	if (ret == 0)
113e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman		sdio_func_set_present(func);
114e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
115e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	return ret;
116e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
117e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
118e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/*
119e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Unregister a SDIO function with the driver model, and
120e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * (eventually) free it.
121e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */
122e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_remove_func(struct sdio_func *func)
123e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{
124e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	if (sdio_func_present(func))
125e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman		device_del(&func->dev);
126e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
127e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman	put_device(&func->dev);
128e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}
129e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman
130