Skip to content

Commit 275173b

Browse files
glikelycjb
authored andcommitted
mmc: sdhci-tegra: Add Device Tree probing support
Add hooks to read gpio configuration out of the device tree node. [grant.likely: Rewrite of original patch from John Bonesio] Signed-off-by: Grant Likely <grant.likely@secretlab.ca> [swarren: Fixed tegra_sdhci_get_ro() to retrieve pdata correctly] [swarren: Reworked to avoid #ifdef CONFIG_OF] [swarren: Reworked binding based on fsl-imx-esdhc.txt] [swarren: Documented binding] Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Chris Ball <cjb@laptop.org>
1 parent 08da834 commit 275173b

File tree

2 files changed

+65
-11
lines changed

2 files changed

+65
-11
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
* NVIDIA Tegra Secure Digital Host Controller
2+
3+
This controller on Tegra family SoCs provides an interface for MMC, SD,
4+
and SDIO types of memory cards.
5+
6+
Required properties:
7+
- compatible : Should be "nvidia,<chip>-sdhci"
8+
- reg : Should contain eSDHC registers location and length
9+
- interrupts : Should contain eSDHC interrupt
10+
11+
Optional properties:
12+
- cd-gpios : Specify GPIOs for card detection
13+
- wp-gpios : Specify GPIOs for write protection
14+
- power-gpios : Specify GPIOs for power control
15+
16+
Example:
17+
18+
sdhci@c8000200 {
19+
compatible = "nvidia,tegra20-sdhci";
20+
reg = <0xc8000200 0x200>;
21+
interrupts = <47>;
22+
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
23+
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
24+
power-gpios = <&gpio 155 0>; /* gpio PT3 */
25+
};

drivers/mmc/host/sdhci-tegra.c

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/platform_device.h>
1818
#include <linux/clk.h>
1919
#include <linux/io.h>
20+
#include <linux/of_gpio.h>
2021
#include <linux/gpio.h>
2122
#include <linux/mmc/card.h>
2223
#include <linux/mmc/host.h>
@@ -73,10 +74,8 @@ static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
7374

7475
static unsigned int tegra_sdhci_get_ro(struct sdhci_host *sdhci)
7576
{
76-
struct platform_device *pdev = to_platform_device(mmc_dev(sdhci->mmc));
77-
struct tegra_sdhci_platform_data *plat;
78-
79-
plat = pdev->dev.platform_data;
77+
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
78+
struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
8079

8180
if (!gpio_is_valid(plat->wp_gpio))
8281
return -1;
@@ -94,12 +93,10 @@ static irqreturn_t carddetect_irq(int irq, void *data)
9493

9594
static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width)
9695
{
97-
struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
98-
struct tegra_sdhci_platform_data *plat;
96+
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
97+
struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
9998
u32 ctrl;
10099

101-
plat = pdev->dev.platform_data;
102-
103100
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
104101
if (plat->is_8bit && bus_width == MMC_BUS_WIDTH_8) {
105102
ctrl &= ~SDHCI_CTRL_4BITBUS;
@@ -131,6 +128,34 @@ static struct sdhci_pltfm_data sdhci_tegra_pdata = {
131128
.ops = &tegra_sdhci_ops,
132129
};
133130

131+
static const struct of_device_id sdhci_tegra_dt_match[] __devinitdata = {
132+
{ .compatible = "nvidia,tegra20-sdhci", },
133+
{}
134+
};
135+
MODULE_DEVICE_TABLE(of, sdhci_dt_ids);
136+
137+
static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
138+
struct platform_device *pdev)
139+
{
140+
struct tegra_sdhci_platform_data *plat;
141+
struct device_node *np = pdev->dev.of_node;
142+
143+
if (!np)
144+
return NULL;
145+
146+
plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
147+
if (!plat) {
148+
dev_err(&pdev->dev, "Can't allocate platform data\n");
149+
return NULL;
150+
}
151+
152+
plat->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
153+
plat->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
154+
plat->power_gpio = of_get_named_gpio(np, "power-gpios", 0);
155+
156+
return plat;
157+
}
158+
134159
static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
135160
{
136161
struct sdhci_pltfm_host *pltfm_host;
@@ -147,12 +172,17 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
147172

148173
plat = pdev->dev.platform_data;
149174

175+
if (plat == NULL)
176+
plat = sdhci_tegra_dt_parse_pdata(pdev);
177+
150178
if (plat == NULL) {
151179
dev_err(mmc_dev(host->mmc), "missing platform data\n");
152180
rc = -ENXIO;
153181
goto err_no_plat;
154182
}
155183

184+
pltfm_host->priv = plat;
185+
156186
if (gpio_is_valid(plat->power_gpio)) {
157187
rc = gpio_request(plat->power_gpio, "sdhci_power");
158188
if (rc) {
@@ -247,13 +277,11 @@ static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
247277
{
248278
struct sdhci_host *host = platform_get_drvdata(pdev);
249279
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
250-
struct tegra_sdhci_platform_data *plat;
280+
struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
251281
int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
252282

253283
sdhci_remove_host(host, dead);
254284

255-
plat = pdev->dev.platform_data;
256-
257285
if (gpio_is_valid(plat->wp_gpio)) {
258286
tegra_gpio_disable(plat->wp_gpio);
259287
gpio_free(plat->wp_gpio);
@@ -282,6 +310,7 @@ static struct platform_driver sdhci_tegra_driver = {
282310
.driver = {
283311
.name = "sdhci-tegra",
284312
.owner = THIS_MODULE,
313+
.of_match_table = sdhci_tegra_dt_match,
285314
},
286315
.probe = sdhci_tegra_probe,
287316
.remove = __devexit_p(sdhci_tegra_remove),

0 commit comments

Comments
 (0)