aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2013-02-16 10:21:16 -0500
committerChris Ball <cjb@laptop.org>2013-02-24 14:37:19 -0500
commit6c56e7a0fff166904ce2715f7ab1746460c1f11b (patch)
treeb1c71673f7473cd7a2ec8995214d15ba7df9f6fe /drivers/mmc
parent6da15e96fb14e7428ecdc69306d8a3287296a968 (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.c110
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 */
309void 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
405EXPORT_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