add the 'goldfish' target, useful for experimenting with virtual phone hardware ...
[openwrt.git] / target / linux / goldfish / patches-2.6.30 / 0095-mmc-Add-concept-of-an-embedded-SDIO-device.patch
1 From 62d51f0d0d0b3c758b4505c3855b61288b8e90aa Mon Sep 17 00:00:00 2001
2 From: San Mehat <san@android.com>
3 Date: Mon, 14 Apr 2008 15:22:49 -0700
4 Subject: [PATCH 095/134] mmc: Add concept of an 'embedded' SDIO device.
5
6 This is required to support chips which use SDIO for signaling/
7 communication but do not implement the various card enumeration registers
8 as required for full SD / SDIO cards.
9
10 mmc: sdio: Fix bug where we're freeing the CIS tables we never allocated when using EMBEDDED_SDIO
11 mmc: Add max_blksize to embedded SDIO data
12
13 Signed-off-by: San Mehat <san@google.com>
14 ---
15  arch/arm/include/asm/mach/mmc.h |   10 ++++++
16  drivers/mmc/core/Kconfig        |   10 +++++-
17  drivers/mmc/core/core.c         |   16 +++++++++
18  drivers/mmc/core/sdio.c         |   67 ++++++++++++++++++++++++++++++++-------
19  drivers/mmc/core/sdio_bus.c     |   13 +++++++-
20  include/linux/mmc/host.h        |   17 ++++++++++
21  include/linux/mmc/sdio_func.h   |    8 +++++
22  7 files changed, 127 insertions(+), 14 deletions(-)
23
24 --- a/arch/arm/include/asm/mach/mmc.h
25 +++ b/arch/arm/include/asm/mach/mmc.h
26 @@ -5,12 +5,22 @@
27  #define ASMARM_MACH_MMC_H
28  
29  #include <linux/mmc/host.h>
30 +#include <linux/mmc/card.h>
31 +#include <linux/mmc/sdio_func.h>
32 +
33 +struct embedded_sdio_data {
34 +        struct sdio_cis cis;
35 +        struct sdio_cccr cccr;
36 +        struct sdio_embedded_func *funcs;
37 +        int num_funcs;
38 +};
39  
40  struct mmc_platform_data {
41         unsigned int ocr_mask;                  /* available voltages */
42         u32 (*translate_vdd)(struct device *, unsigned int);
43         unsigned int (*status)(struct device *);
44         unsigned int status_irq;
45 +       struct embedded_sdio_data *embedded_sdio;
46         int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
47  };
48  
49 --- a/drivers/mmc/core/Kconfig
50 +++ b/drivers/mmc/core/Kconfig
51 @@ -14,11 +14,19 @@ config MMC_UNSAFE_RESUME
52           This option is usually just for embedded systems which use
53           a MMC/SD card for rootfs. Most people should say N here.
54  
55 +config MMC_EMBEDDED_SDIO
56 +       boolean "MMC embedded SDIO device support (EXPERIMENTAL)"
57 +       depends on EXPERIMENTAL
58 +       help
59 +         If you say Y here, support will be added for embedded SDIO
60 +         devices which do not contain the necessary enumeration
61 +         support in hardware to be properly detected.
62 +
63  config MMC_PARANOID_SD_INIT
64         bool "Enable paranoid SD card initialization (EXPERIMENTAL)"
65 +       depends on EXPERIMENTAL
66         help
67           If you say Y here, the MMC layer will be extra paranoid
68           about re-trying SD init requests. This can be a useful
69           work-around for buggy controllers and hardware. Enable
70           if you are experiencing issues with SD detection.
71 -
72 --- a/drivers/mmc/core/core.c
73 +++ b/drivers/mmc/core/core.c
74 @@ -1011,6 +1011,22 @@ EXPORT_SYMBOL(mmc_resume_host);
75  
76  #endif
77  
78 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
79 +void mmc_set_embedded_sdio_data(struct mmc_host *host,
80 +                               struct sdio_cis *cis,
81 +                               struct sdio_cccr *cccr,
82 +                               struct sdio_embedded_func *funcs,
83 +                               int num_funcs)
84 +{
85 +       host->embedded_sdio_data.cis = cis;
86 +       host->embedded_sdio_data.cccr = cccr;
87 +       host->embedded_sdio_data.funcs = funcs;
88 +       host->embedded_sdio_data.num_funcs = num_funcs;
89 +}
90 +
91 +EXPORT_SYMBOL(mmc_set_embedded_sdio_data);
92 +#endif
93 +
94  static int __init mmc_init(void)
95  {
96         int ret;
97 --- a/drivers/mmc/core/sdio.c
98 +++ b/drivers/mmc/core/sdio.c
99 @@ -24,6 +24,10 @@
100  #include "sdio_ops.h"
101  #include "sdio_cis.h"
102  
103 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
104 +#include <linux/mmc/sdio_ids.h>
105 +#endif
106 +
107  static int sdio_read_fbr(struct sdio_func *func)
108  {
109         int ret;
110 @@ -314,6 +318,11 @@ int mmc_attach_sdio(struct mmc_host *hos
111          */
112         funcs = (ocr & 0x70000000) >> 28;
113  
114 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
115 +       if (host->embedded_sdio_data.funcs)
116 +               funcs = host->embedded_sdio_data.num_funcs;
117 +#endif
118 +
119         /*
120          * Allocate card structure.
121          */
122 @@ -351,17 +360,33 @@ int mmc_attach_sdio(struct mmc_host *hos
123         /*
124          * Read the common registers.
125          */
126 -       err = sdio_read_cccr(card);
127 -       if (err)
128 -               goto remove;
129  
130 -       /*
131 -        * Read the common CIS tuples.
132 -        */
133 -       err = sdio_read_common_cis(card);
134 -       if (err)
135 -               goto remove;
136 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
137 +       if (host->embedded_sdio_data.cccr)
138 +               memcpy(&card->cccr, host->embedded_sdio_data.cccr, sizeof(struct sdio_cccr));
139 +       else {
140 +#endif
141 +               err = sdio_read_cccr(card);
142 +               if (err)
143 +                       goto remove;
144 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
145 +       }
146 +#endif
147  
148 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
149 +       if (host->embedded_sdio_data.cis)
150 +               memcpy(&card->cis, host->embedded_sdio_data.cis, sizeof(struct sdio_cis));
151 +       else {
152 +#endif
153 +               /*
154 +                * Read the common CIS tuples.
155 +                */
156 +               err = sdio_read_common_cis(card);
157 +               if (err)
158 +                       goto remove;
159 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
160 +       }
161 +#endif
162         /*
163          * Switch to high-speed (if supported).
164          */
165 @@ -395,9 +420,27 @@ int mmc_attach_sdio(struct mmc_host *hos
166          * Initialize (but don't add) all present functions.
167          */
168         for (i = 0;i < funcs;i++) {
169 -               err = sdio_init_func(host->card, i + 1);
170 -               if (err)
171 -                       goto remove;
172 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
173 +               if (host->embedded_sdio_data.funcs) {
174 +                       struct sdio_func *tmp;
175 +
176 +                       tmp = sdio_alloc_func(host->card);
177 +                       if (IS_ERR(tmp))
178 +                               goto remove;
179 +                       tmp->num = (i + 1);
180 +                       card->sdio_func[i] = tmp;
181 +                       tmp->class = host->embedded_sdio_data.funcs[i].f_class;
182 +                       tmp->max_blksize = host->embedded_sdio_data.funcs[i].f_maxblksize;
183 +                       tmp->vendor = card->cis.vendor;
184 +                       tmp->device = card->cis.device;
185 +               } else {
186 +#endif
187 +                       err = sdio_init_func(host->card, i + 1);
188 +                       if (err)
189 +                               goto remove;
190 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
191 +               }
192 +#endif
193         }
194  
195         mmc_release_host(host);
196 --- a/drivers/mmc/core/sdio_bus.c
197 +++ b/drivers/mmc/core/sdio_bus.c
198 @@ -20,6 +20,10 @@
199  #include "sdio_cis.h"
200  #include "sdio_bus.h"
201  
202 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
203 +#include <linux/mmc/host.h>
204 +#endif
205 +
206  #define dev_to_sdio_func(d)    container_of(d, struct sdio_func, dev)
207  #define to_sdio_driver(d)      container_of(d, struct sdio_driver, drv)
208  
209 @@ -202,7 +206,14 @@ static void sdio_release_func(struct dev
210  {
211         struct sdio_func *func = dev_to_sdio_func(dev);
212  
213 -       sdio_free_func_cis(func);
214 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
215 +       /*
216 +        * If this device is embedded then we never allocated
217 +        * cis tables for this func
218 +        */
219 +       if (!func->card->host->embedded_sdio_data.funcs)
220 +#endif
221 +               sdio_free_func_cis(func);
222  
223         if (func->info)
224                 kfree(func->info);
225 --- a/include/linux/mmc/host.h
226 +++ b/include/linux/mmc/host.h
227 @@ -161,6 +161,15 @@ struct mmc_host {
228  
229         struct dentry           *debugfs_root;
230  
231 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
232 +       struct {
233 +               struct sdio_cis                 *cis;
234 +               struct sdio_cccr                *cccr;
235 +               struct sdio_embedded_func       *funcs;
236 +               int                             num_funcs;
237 +       } embedded_sdio_data;
238 +#endif
239 +
240         unsigned long           private[0] ____cacheline_aligned;
241  };
242  
243 @@ -169,6 +178,14 @@ extern int mmc_add_host(struct mmc_host 
244  extern void mmc_remove_host(struct mmc_host *);
245  extern void mmc_free_host(struct mmc_host *);
246  
247 +#ifdef CONFIG_MMC_EMBEDDED_SDIO
248 +extern void mmc_set_embedded_sdio_data(struct mmc_host *host,
249 +                                      struct sdio_cis *cis,
250 +                                      struct sdio_cccr *cccr,
251 +                                      struct sdio_embedded_func *funcs,
252 +                                      int num_funcs);
253 +#endif
254 +
255  static inline void *mmc_priv(struct mmc_host *host)
256  {
257         return (void *)host->private;
258 --- a/include/linux/mmc/sdio_func.h
259 +++ b/include/linux/mmc/sdio_func.h
260 @@ -21,6 +21,14 @@ struct sdio_func;
261  typedef void (sdio_irq_handler_t)(struct sdio_func *);
262  
263  /*
264 + * Structure used to hold embedded SDIO device data from platform layer
265 + */
266 +struct sdio_embedded_func {
267 +       uint8_t f_class;
268 +       uint32_t f_maxblksize;
269 +};
270 +
271 +/*
272   * SDIO function CIS tuple (unknown to the core)
273   */
274  struct sdio_func_tuple {