blob: 461fe4837a9fe6fef8dff153ccdd226341ba63e2 [file] [log] [blame]
Pierre Ossmane29a7d72007-05-26 13:48:18 +02001/*
2 * linux/drivers/mmc/core/sdio_bus.c
3 *
4 * Copyright 2007 Pierre Ossman
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
10 *
11 * SDIO function driver model
12 */
13
14#include <linux/device.h>
15#include <linux/err.h>
16
17#include <linux/mmc/card.h>
18#include <linux/mmc/sdio_func.h>
19
Nicolas Pitreb1538bc2007-06-16 02:06:47 -040020#include "sdio_cis.h"
Pierre Ossmane29a7d72007-05-26 13:48:18 +020021#include "sdio_bus.h"
22
23#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev)
24
25/*
26 * This currently matches any SDIO function to any driver in order
27 * to help initial development and testing.
28 */
29static int sdio_bus_match(struct device *dev, struct device_driver *drv)
30{
31 return 1;
32}
33
34static int
35sdio_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
36 int buf_size)
37{
38 envp[0] = NULL;
39
40 return 0;
41}
42
43static int sdio_bus_probe(struct device *dev)
44{
45 return -ENODEV;
46}
47
48static int sdio_bus_remove(struct device *dev)
49{
50 return 0;
51}
52
53static struct bus_type sdio_bus_type = {
54 .name = "sdio",
55 .match = sdio_bus_match,
56 .uevent = sdio_bus_uevent,
57 .probe = sdio_bus_probe,
58 .remove = sdio_bus_remove,
59};
60
61int sdio_register_bus(void)
62{
63 return bus_register(&sdio_bus_type);
64}
65
66void sdio_unregister_bus(void)
67{
68 bus_unregister(&sdio_bus_type);
69}
70
Pierre Ossmanf76c8512007-05-27 12:00:02 +020071/**
72 * sdio_register_driver - register a function driver
73 * @drv: SDIO function driver
74 */
75int sdio_register_driver(struct sdio_driver *drv)
76{
77 drv->drv.name = drv->name;
78 drv->drv.bus = &sdio_bus_type;
79 return driver_register(&drv->drv);
80}
81EXPORT_SYMBOL_GPL(sdio_register_driver);
82
83/**
84 * sdio_unregister_driver - unregister a function driver
85 * @drv: SDIO function driver
86 */
87void sdio_unregister_driver(struct sdio_driver *drv)
88{
89 drv->drv.bus = &sdio_bus_type;
90 driver_unregister(&drv->drv);
91}
92EXPORT_SYMBOL_GPL(sdio_unregister_driver);
93
Pierre Ossmane29a7d72007-05-26 13:48:18 +020094static void sdio_release_func(struct device *dev)
95{
96 struct sdio_func *func = dev_to_sdio_func(dev);
97
Pierre Ossman1a632f82007-07-30 15:15:30 +020098 sdio_free_func_cis(func);
Nicolas Pitreb1538bc2007-06-16 02:06:47 -040099
Pierre Ossmane29a7d72007-05-26 13:48:18 +0200100 kfree(func);
101}
102
103/*
104 * Allocate and initialise a new SDIO function structure.
105 */
106struct sdio_func *sdio_alloc_func(struct mmc_card *card)
107{
108 struct sdio_func *func;
109
110 func = kmalloc(sizeof(struct sdio_func), GFP_KERNEL);
111 if (!func)
112 return ERR_PTR(-ENOMEM);
113
114 memset(func, 0, sizeof(struct sdio_func));
115
116 func->card = card;
117
118 device_initialize(&func->dev);
119
120 func->dev.parent = &card->dev;
121 func->dev.bus = &sdio_bus_type;
122 func->dev.release = sdio_release_func;
123
124 return func;
125}
126
127/*
128 * Register a new SDIO function with the driver model.
129 */
130int sdio_add_func(struct sdio_func *func)
131{
132 int ret;
133
134 snprintf(func->dev.bus_id, sizeof(func->dev.bus_id),
135 "%s:%d", mmc_card_id(func->card), func->num);
136
137 ret = device_add(&func->dev);
138 if (ret == 0)
139 sdio_func_set_present(func);
140
141 return ret;
142}
143
144/*
145 * Unregister a SDIO function with the driver model, and
146 * (eventually) free it.
147 */
148void sdio_remove_func(struct sdio_func *func)
149{
150 if (sdio_func_present(func))
151 device_del(&func->dev);
152
153 put_device(&func->dev);
154}
155