Skip to content

Commit b650352

Browse files
committed
mmc: sdhci-pxa: Add device tree support
Tested on an OLPC XO-1.75. (MMP2, sdhci-pxav3, CONFIG_MACH_MMP2_DT=y) Signed-off-by: Chris Ball <cjb@laptop.org> Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>
1 parent ed3efc1 commit b650352

File tree

3 files changed

+127
-0
lines changed

3 files changed

+127
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
* Marvell sdhci-pxa v2/v3 controller
2+
3+
This file documents differences between the core properties in mmc.txt
4+
and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers.
5+
6+
Required properties:
7+
- compatible: Should be "mrvl,pxav2-mmc" or "mrvl,pxav3-mmc".
8+
9+
Optional properties:
10+
- mrvl,clk-delay-cycles: Specify a number of cycles to delay for tuning.
11+
12+
Example:
13+
14+
sdhci@d4280800 {
15+
compatible = "mrvl,pxav3-mmc";
16+
reg = <0xd4280800 0x800>;
17+
bus-width = <8>;
18+
interrupts = <27>;
19+
non-removable;
20+
mrvl,clk-delay-cycles = <31>;
21+
};

drivers/mmc/host/sdhci-pxav2.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#include <linux/mmc/host.h>
2929
#include <linux/platform_data/pxa_sdhci.h>
3030
#include <linux/slab.h>
31+
#include <linux/of.h>
32+
#include <linux/of_device.h>
33+
3134
#include "sdhci.h"
3235
#include "sdhci-pltfm.h"
3336

@@ -121,13 +124,57 @@ static struct sdhci_ops pxav2_sdhci_ops = {
121124
.platform_8bit_width = pxav2_mmc_set_width,
122125
};
123126

127+
#ifdef CONFIG_OF
128+
static const struct of_device_id sdhci_pxav2_of_match[] = {
129+
{
130+
.compatible = "mrvl,pxav2-mmc",
131+
},
132+
{},
133+
};
134+
MODULE_DEVICE_TABLE(of, sdhci_pxav2_of_match);
135+
136+
static struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev)
137+
{
138+
struct sdhci_pxa_platdata *pdata;
139+
struct device_node *np = dev->of_node;
140+
u32 bus_width;
141+
u32 clk_delay_cycles;
142+
143+
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
144+
if (!pdata)
145+
return NULL;
146+
147+
if (of_find_property(np, "non-removable", NULL))
148+
pdata->flags |= PXA_FLAG_CARD_PERMANENT;
149+
150+
of_property_read_u32(np, "bus-width", &bus_width);
151+
if (bus_width == 8)
152+
pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT;
153+
154+
of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles);
155+
if (clk_delay_cycles > 0) {
156+
pdata->clk_delay_sel = 1;
157+
pdata->clk_delay_cycles = clk_delay_cycles;
158+
}
159+
160+
return pdata;
161+
}
162+
#else
163+
static inline struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev)
164+
{
165+
return NULL;
166+
}
167+
#endif
168+
124169
static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
125170
{
126171
struct sdhci_pltfm_host *pltfm_host;
127172
struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
128173
struct device *dev = &pdev->dev;
129174
struct sdhci_host *host = NULL;
130175
struct sdhci_pxa *pxa = NULL;
176+
const struct of_device_id *match;
177+
131178
int ret;
132179
struct clk *clk;
133180

@@ -156,6 +203,10 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
156203
| SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
157204
| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
158205

206+
match = of_match_device(of_match_ptr(sdhci_pxav2_of_match), &pdev->dev);
207+
if (match) {
208+
pdata = pxav2_get_mmc_pdata(dev);
209+
}
159210
if (pdata) {
160211
if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
161212
/* on-chip device */
@@ -218,6 +269,9 @@ static struct platform_driver sdhci_pxav2_driver = {
218269
.driver = {
219270
.name = "sdhci-pxav2",
220271
.owner = THIS_MODULE,
272+
#ifdef CONFIG_OF
273+
.of_match_table = sdhci_pxav2_of_match,
274+
#endif
221275
.pm = SDHCI_PLTFM_PMOPS,
222276
},
223277
.probe = sdhci_pxav2_probe,

drivers/mmc/host/sdhci-pxav3.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#include <linux/slab.h>
2929
#include <linux/delay.h>
3030
#include <linux/module.h>
31+
#include <linux/of.h>
32+
#include <linux/of_device.h>
33+
3134
#include "sdhci.h"
3235
#include "sdhci-pltfm.h"
3336

@@ -164,13 +167,55 @@ static struct sdhci_ops pxav3_sdhci_ops = {
164167
.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
165168
};
166169

170+
#ifdef CONFIG_OF
171+
static const struct of_device_id sdhci_pxav3_of_match[] = {
172+
{
173+
.compatible = "mrvl,pxav3-mmc",
174+
},
175+
{},
176+
};
177+
MODULE_DEVICE_TABLE(of, sdhci_pxav3_of_match);
178+
179+
static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
180+
{
181+
struct sdhci_pxa_platdata *pdata;
182+
struct device_node *np = dev->of_node;
183+
u32 bus_width;
184+
u32 clk_delay_cycles;
185+
186+
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
187+
if (!pdata)
188+
return NULL;
189+
190+
if (of_find_property(np, "non-removable", NULL))
191+
pdata->flags |= PXA_FLAG_CARD_PERMANENT;
192+
193+
of_property_read_u32(np, "bus-width", &bus_width);
194+
if (bus_width == 8)
195+
pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT;
196+
197+
of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles);
198+
if (clk_delay_cycles > 0)
199+
pdata->clk_delay_cycles = clk_delay_cycles;
200+
201+
return pdata;
202+
}
203+
#else
204+
static inline struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
205+
{
206+
return NULL;
207+
}
208+
#endif
209+
167210
static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
168211
{
169212
struct sdhci_pltfm_host *pltfm_host;
170213
struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
171214
struct device *dev = &pdev->dev;
172215
struct sdhci_host *host = NULL;
173216
struct sdhci_pxa *pxa = NULL;
217+
const struct of_device_id *match;
218+
174219
int ret;
175220
struct clk *clk;
176221

@@ -202,6 +247,10 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
202247
/* enable 1/8V DDR capable */
203248
host->mmc->caps |= MMC_CAP_1_8V_DDR;
204249

250+
match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev);
251+
if (match)
252+
pdata = pxav3_get_mmc_pdata(dev);
253+
205254
if (pdata) {
206255
if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
207256
/* on-chip device */
@@ -263,6 +312,9 @@ static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
263312
static struct platform_driver sdhci_pxav3_driver = {
264313
.driver = {
265314
.name = "sdhci-pxav3",
315+
#ifdef CONFIG_OF
316+
.of_match_table = sdhci_pxav3_of_match,
317+
#endif
266318
.owner = THIS_MODULE,
267319
.pm = SDHCI_PLTFM_PMOPS,
268320
},

0 commit comments

Comments
 (0)