diff options
author | Chris Ball <cjb@laptop.org> | 2012-04-10 22:34:33 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-07-21 00:01:47 -0400 |
commit | b650352dd3df36164e3427bff3f33bc06ac47642 (patch) | |
tree | 883219dd446358996e8860027bb712e258f2554c /drivers/mmc | |
parent | ed3efc1ccc4421865b64d902cd410f6733c85a49 (diff) |
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>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/sdhci-pxav2.c | 54 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pxav3.c | 52 |
2 files changed, 106 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index dbb75bfbcffb..b6ee8857e226 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #include <linux/mmc/host.h> | 28 | #include <linux/mmc/host.h> |
29 | #include <linux/platform_data/pxa_sdhci.h> | 29 | #include <linux/platform_data/pxa_sdhci.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/of.h> | ||
32 | #include <linux/of_device.h> | ||
33 | |||
31 | #include "sdhci.h" | 34 | #include "sdhci.h" |
32 | #include "sdhci-pltfm.h" | 35 | #include "sdhci-pltfm.h" |
33 | 36 | ||
@@ -121,6 +124,48 @@ static struct sdhci_ops pxav2_sdhci_ops = { | |||
121 | .platform_8bit_width = pxav2_mmc_set_width, | 124 | .platform_8bit_width = pxav2_mmc_set_width, |
122 | }; | 125 | }; |
123 | 126 | ||
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 | |||
124 | static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) | 169 | static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) |
125 | { | 170 | { |
126 | struct sdhci_pltfm_host *pltfm_host; | 171 | struct sdhci_pltfm_host *pltfm_host; |
@@ -128,6 +173,8 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) | |||
128 | struct device *dev = &pdev->dev; | 173 | struct device *dev = &pdev->dev; |
129 | struct sdhci_host *host = NULL; | 174 | struct sdhci_host *host = NULL; |
130 | struct sdhci_pxa *pxa = NULL; | 175 | struct sdhci_pxa *pxa = NULL; |
176 | const struct of_device_id *match; | ||
177 | |||
131 | int ret; | 178 | int ret; |
132 | struct clk *clk; | 179 | struct clk *clk; |
133 | 180 | ||
@@ -156,6 +203,10 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) | |||
156 | | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 203 | | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
157 | | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN; | 204 | | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN; |
158 | 205 | ||
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 | } | ||
159 | if (pdata) { | 210 | if (pdata) { |
160 | if (pdata->flags & PXA_FLAG_CARD_PERMANENT) { | 211 | if (pdata->flags & PXA_FLAG_CARD_PERMANENT) { |
161 | /* on-chip device */ | 212 | /* on-chip device */ |
@@ -218,6 +269,9 @@ static struct platform_driver sdhci_pxav2_driver = { | |||
218 | .driver = { | 269 | .driver = { |
219 | .name = "sdhci-pxav2", | 270 | .name = "sdhci-pxav2", |
220 | .owner = THIS_MODULE, | 271 | .owner = THIS_MODULE, |
272 | #ifdef CONFIG_OF | ||
273 | .of_match_table = sdhci_pxav2_of_match, | ||
274 | #endif | ||
221 | .pm = SDHCI_PLTFM_PMOPS, | 275 | .pm = SDHCI_PLTFM_PMOPS, |
222 | }, | 276 | }, |
223 | .probe = sdhci_pxav2_probe, | 277 | .probe = sdhci_pxav2_probe, |
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index f29695683556..07fe3834fe0b 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/of.h> | ||
32 | #include <linux/of_device.h> | ||
33 | |||
31 | #include "sdhci.h" | 34 | #include "sdhci.h" |
32 | #include "sdhci-pltfm.h" | 35 | #include "sdhci-pltfm.h" |
33 | 36 | ||
@@ -164,6 +167,46 @@ static struct sdhci_ops pxav3_sdhci_ops = { | |||
164 | .platform_send_init_74_clocks = pxav3_gen_init_74_clocks, | 167 | .platform_send_init_74_clocks = pxav3_gen_init_74_clocks, |
165 | }; | 168 | }; |
166 | 169 | ||
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 | |||
167 | static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | 210 | static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) |
168 | { | 211 | { |
169 | struct sdhci_pltfm_host *pltfm_host; | 212 | struct sdhci_pltfm_host *pltfm_host; |
@@ -171,6 +214,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | |||
171 | struct device *dev = &pdev->dev; | 214 | struct device *dev = &pdev->dev; |
172 | struct sdhci_host *host = NULL; | 215 | struct sdhci_host *host = NULL; |
173 | struct sdhci_pxa *pxa = NULL; | 216 | struct sdhci_pxa *pxa = NULL; |
217 | const struct of_device_id *match; | ||
218 | |||
174 | int ret; | 219 | int ret; |
175 | struct clk *clk; | 220 | struct clk *clk; |
176 | 221 | ||
@@ -202,6 +247,10 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | |||
202 | /* enable 1/8V DDR capable */ | 247 | /* enable 1/8V DDR capable */ |
203 | host->mmc->caps |= MMC_CAP_1_8V_DDR; | 248 | host->mmc->caps |= MMC_CAP_1_8V_DDR; |
204 | 249 | ||
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 | |||
205 | if (pdata) { | 254 | if (pdata) { |
206 | if (pdata->flags & PXA_FLAG_CARD_PERMANENT) { | 255 | if (pdata->flags & PXA_FLAG_CARD_PERMANENT) { |
207 | /* on-chip device */ | 256 | /* on-chip device */ |
@@ -263,6 +312,9 @@ static int __devexit sdhci_pxav3_remove(struct platform_device *pdev) | |||
263 | static struct platform_driver sdhci_pxav3_driver = { | 312 | static struct platform_driver sdhci_pxav3_driver = { |
264 | .driver = { | 313 | .driver = { |
265 | .name = "sdhci-pxav3", | 314 | .name = "sdhci-pxav3", |
315 | #ifdef CONFIG_OF | ||
316 | .of_match_table = sdhci_pxav3_of_match, | ||
317 | #endif | ||
266 | .owner = THIS_MODULE, | 318 | .owner = THIS_MODULE, |
267 | .pm = SDHCI_PLTFM_PMOPS, | 319 | .pm = SDHCI_PLTFM_PMOPS, |
268 | }, | 320 | }, |