aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2014-06-30 05:07:25 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2015-01-19 03:56:26 -0500
commit25185f3f31c924eecc6ff4f55f7acceabf24de11 (patch)
tree240b6d8ac9db0e2688938926f545b43335808d9f /drivers/mmc
parenta31edf1e582111f05fb8315da9dd118c837bede5 (diff)
mmc: Add SDIO function devicetree subnode parsing
This adds SDIO devicetree subnode parsing to the mmc core. While SDIO devices are runtime probable they sometimes need nonprobable additional information on embedded systems, like an additional gpio interrupt or a clock. This patch makes it possible to supply this information from the devicetree. SDIO drivers will find a pointer to the devicenode in their devices of_node pointer. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> [hdegoede@redhat.com: Misc. cleanups] Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/bus.c4
-rw-r--r--drivers/mmc/core/core.c28
-rw-r--r--drivers/mmc/core/core.h3
-rw-r--r--drivers/mmc/core/sdio_bus.c11
4 files changed, 46 insertions, 0 deletions
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 86d271148528..c5ef10065a4a 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -16,6 +16,7 @@
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/stat.h> 18#include <linux/stat.h>
19#include <linux/of.h>
19#include <linux/pm_runtime.h> 20#include <linux/pm_runtime.h>
20 21
21#include <linux/mmc/card.h> 22#include <linux/mmc/card.h>
@@ -321,6 +322,8 @@ int mmc_add_card(struct mmc_card *card)
321#endif 322#endif
322 mmc_init_context_info(card->host); 323 mmc_init_context_info(card->host);
323 324
325 card->dev.of_node = mmc_of_find_child_device(card->host, 0);
326
324 ret = device_add(&card->dev); 327 ret = device_add(&card->dev);
325 if (ret) 328 if (ret)
326 return ret; 329 return ret;
@@ -349,6 +352,7 @@ void mmc_remove_card(struct mmc_card *card)
349 mmc_hostname(card->host), card->rca); 352 mmc_hostname(card->host), card->rca);
350 } 353 }
351 device_del(&card->dev); 354 device_del(&card->dev);
355 of_node_put(card->dev.of_node);
352 } 356 }
353 357
354 put_device(&card->dev); 358 put_device(&card->dev);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9584bffa8b22..d3bfbdfab052 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1232,6 +1232,34 @@ EXPORT_SYMBOL(mmc_of_parse_voltage);
1232 1232
1233#endif /* CONFIG_OF */ 1233#endif /* CONFIG_OF */
1234 1234
1235static int mmc_of_get_func_num(struct device_node *node)
1236{
1237 u32 reg;
1238 int ret;
1239
1240 ret = of_property_read_u32(node, "reg", &reg);
1241 if (ret < 0)
1242 return ret;
1243
1244 return reg;
1245}
1246
1247struct device_node *mmc_of_find_child_device(struct mmc_host *host,
1248 unsigned func_num)
1249{
1250 struct device_node *node;
1251
1252 if (!host->parent || !host->parent->of_node)
1253 return NULL;
1254
1255 for_each_child_of_node(host->parent->of_node, node) {
1256 if (mmc_of_get_func_num(node) == func_num)
1257 return node;
1258 }
1259
1260 return NULL;
1261}
1262
1235#ifdef CONFIG_REGULATOR 1263#ifdef CONFIG_REGULATOR
1236 1264
1237/** 1265/**
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index d76597c65e3a..b528c0e5b264 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -32,6 +32,9 @@ struct mmc_bus_ops {
32void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); 32void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
33void mmc_detach_bus(struct mmc_host *host); 33void mmc_detach_bus(struct mmc_host *host);
34 34
35struct device_node *mmc_of_find_child_device(struct mmc_host *host,
36 unsigned func_num);
37
35void mmc_init_erase(struct mmc_card *card); 38void mmc_init_erase(struct mmc_card *card);
36 39
37void mmc_set_chip_select(struct mmc_host *host, int mode); 40void mmc_set_chip_select(struct mmc_host *host, int mode);
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 60885316afba..bee02e644d62 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -22,7 +22,9 @@
22#include <linux/mmc/card.h> 22#include <linux/mmc/card.h>
23#include <linux/mmc/host.h> 23#include <linux/mmc/host.h>
24#include <linux/mmc/sdio_func.h> 24#include <linux/mmc/sdio_func.h>
25#include <linux/of.h>
25 26
27#include "core.h"
26#include "sdio_cis.h" 28#include "sdio_cis.h"
27#include "sdio_bus.h" 29#include "sdio_bus.h"
28 30
@@ -295,6 +297,13 @@ static void sdio_acpi_set_handle(struct sdio_func *func)
295static inline void sdio_acpi_set_handle(struct sdio_func *func) {} 297static inline void sdio_acpi_set_handle(struct sdio_func *func) {}
296#endif 298#endif
297 299
300static void sdio_set_of_node(struct sdio_func *func)
301{
302 struct mmc_host *host = func->card->host;
303
304 func->dev.of_node = mmc_of_find_child_device(host, func->num);
305}
306
298/* 307/*
299 * Register a new SDIO function with the driver model. 308 * Register a new SDIO function with the driver model.
300 */ 309 */
@@ -304,6 +313,7 @@ int sdio_add_func(struct sdio_func *func)
304 313
305 dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num); 314 dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
306 315
316 sdio_set_of_node(func);
307 sdio_acpi_set_handle(func); 317 sdio_acpi_set_handle(func);
308 ret = device_add(&func->dev); 318 ret = device_add(&func->dev);
309 if (ret == 0) { 319 if (ret == 0) {
@@ -327,6 +337,7 @@ void sdio_remove_func(struct sdio_func *func)
327 337
328 dev_pm_domain_detach(&func->dev, false); 338 dev_pm_domain_detach(&func->dev, false);
329 device_del(&func->dev); 339 device_del(&func->dev);
340 of_node_put(func->dev.of_node);
330 put_device(&func->dev); 341 put_device(&func->dev);
331} 342}
332 343