diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2013-02-16 10:21:16 -0500 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2013-02-24 14:37:19 -0500 |
commit | 6c56e7a0fff166904ce2715f7ab1746460c1f11b (patch) | |
tree | b1c71673f7473cd7a2ec8995214d15ba7df9f6fe /drivers/mmc | |
parent | 6da15e96fb14e7428ecdc69306d8a3287296a968 (diff) |
mmc: provide a standard MMC device-tree binding parser centrally
MMC defines a number of standard DT bindings. Having each driver parse
them individually adds code redundancy and is error prone. Provide a
standard function to unify the parsing. After all drivers are converted
to using it instead of their own parsers, this function can be integrated
into mmc_alloc_host().
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/host.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index ee2e16b17017..9c53452e73e1 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/idr.h> | 17 | #include <linux/idr.h> |
18 | #include <linux/of.h> | ||
19 | #include <linux/of_gpio.h> | ||
18 | #include <linux/pagemap.h> | 20 | #include <linux/pagemap.h> |
19 | #include <linux/export.h> | 21 | #include <linux/export.h> |
20 | #include <linux/leds.h> | 22 | #include <linux/leds.h> |
@@ -23,6 +25,7 @@ | |||
23 | 25 | ||
24 | #include <linux/mmc/host.h> | 26 | #include <linux/mmc/host.h> |
25 | #include <linux/mmc/card.h> | 27 | #include <linux/mmc/card.h> |
28 | #include <linux/mmc/slot-gpio.h> | ||
26 | 29 | ||
27 | #include "core.h" | 30 | #include "core.h" |
28 | #include "host.h" | 31 | #include "host.h" |
@@ -295,6 +298,113 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) | |||
295 | #endif | 298 | #endif |
296 | 299 | ||
297 | /** | 300 | /** |
301 | * mmc_of_parse() - parse host's device-tree node | ||
302 | * @host: host whose node should be parsed. | ||
303 | * | ||
304 | * To keep the rest of the MMC subsystem unaware of whether DT has been | ||
305 | * used to to instantiate and configure this host instance or not, we | ||
306 | * parse the properties and set respective generic mmc-host flags and | ||
307 | * parameters. | ||
308 | */ | ||
309 | void mmc_of_parse(struct mmc_host *host) | ||
310 | { | ||
311 | struct device_node *np; | ||
312 | u32 bus_width; | ||
313 | bool explicit_inv_wp, gpio_inv_wp = false; | ||
314 | enum of_gpio_flags flags; | ||
315 | int len, ret, gpio; | ||
316 | |||
317 | if (!host->parent || !host->parent->of_node) | ||
318 | return; | ||
319 | |||
320 | np = host->parent->of_node; | ||
321 | |||
322 | /* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */ | ||
323 | if (of_property_read_u32(np, "bus-width", &bus_width) < 0) { | ||
324 | dev_dbg(host->parent, | ||
325 | "\"bus-width\" property is missing, assuming 1 bit.\n"); | ||
326 | bus_width = 1; | ||
327 | } | ||
328 | |||
329 | switch (bus_width) { | ||
330 | case 8: | ||
331 | host->caps |= MMC_CAP_8_BIT_DATA; | ||
332 | /* Hosts capable of 8-bit transfers can also do 4 bits */ | ||
333 | case 4: | ||
334 | host->caps |= MMC_CAP_4_BIT_DATA; | ||
335 | break; | ||
336 | case 1: | ||
337 | break; | ||
338 | default: | ||
339 | dev_err(host->parent, | ||
340 | "Invalid \"bus-width\" value %ud!\n", bus_width); | ||
341 | } | ||
342 | |||
343 | /* f_max is obtained from the optional "max-frequency" property */ | ||
344 | of_property_read_u32(np, "max-frequency", &host->f_max); | ||
345 | |||
346 | /* | ||
347 | * Configure CD and WP pins. They are both by default active low to | ||
348 | * match the SDHCI spec. If GPIOs are provided for CD and / or WP, the | ||
349 | * mmc-gpio helpers are used to attach, configure and use them. If | ||
350 | * polarity inversion is specified in DT, one of MMC_CAP2_CD_ACTIVE_HIGH | ||
351 | * and MMC_CAP2_RO_ACTIVE_HIGH capability-2 flags is set. If the | ||
352 | * "broken-cd" property is provided, the MMC_CAP_NEEDS_POLL capability | ||
353 | * is set. If the "non-removable" property is found, the | ||
354 | * MMC_CAP_NONREMOVABLE capability is set and no card-detection | ||
355 | * configuration is performed. | ||
356 | */ | ||
357 | |||
358 | /* Parse Card Detection */ | ||
359 | if (of_find_property(np, "non-removable", &len)) { | ||
360 | host->caps |= MMC_CAP_NONREMOVABLE; | ||
361 | } else { | ||
362 | bool explicit_inv_cd, gpio_inv_cd = false; | ||
363 | |||
364 | explicit_inv_cd = of_property_read_bool(np, "cd-inverted"); | ||
365 | |||
366 | if (of_find_property(np, "broken-cd", &len)) | ||
367 | host->caps |= MMC_CAP_NEEDS_POLL; | ||
368 | |||
369 | gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &flags); | ||
370 | if (gpio_is_valid(gpio)) { | ||
371 | if (!(flags & OF_GPIO_ACTIVE_LOW)) | ||
372 | gpio_inv_cd = true; | ||
373 | |||
374 | ret = mmc_gpio_request_cd(host, gpio); | ||
375 | if (ret < 0) | ||
376 | dev_err(host->parent, | ||
377 | "Failed to request CD GPIO #%d: %d!\n", | ||
378 | gpio, ret); | ||
379 | else | ||
380 | dev_info(host->parent, "Got CD GPIO #%d.\n", | ||
381 | gpio); | ||
382 | } | ||
383 | |||
384 | if (explicit_inv_cd ^ gpio_inv_cd) | ||
385 | host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; | ||
386 | } | ||
387 | |||
388 | /* Parse Write Protection */ | ||
389 | explicit_inv_wp = of_property_read_bool(np, "wp-inverted"); | ||
390 | |||
391 | gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags); | ||
392 | if (gpio_is_valid(gpio)) { | ||
393 | if (!(flags & OF_GPIO_ACTIVE_LOW)) | ||
394 | gpio_inv_wp = true; | ||
395 | |||
396 | ret = mmc_gpio_request_ro(host, gpio); | ||
397 | if (ret < 0) | ||
398 | dev_err(host->parent, | ||
399 | "Failed to request WP GPIO: %d!\n", ret); | ||
400 | } | ||
401 | if (explicit_inv_wp ^ gpio_inv_wp) | ||
402 | host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; | ||
403 | } | ||
404 | |||
405 | EXPORT_SYMBOL(mmc_of_parse); | ||
406 | |||
407 | /** | ||
298 | * mmc_alloc_host - initialise the per-host structure. | 408 | * mmc_alloc_host - initialise the per-host structure. |
299 | * @extra: sizeof private data structure | 409 | * @extra: sizeof private data structure |
300 | * @dev: pointer to host device model structure | 410 | * @dev: pointer to host device model structure |