diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-tegra.c')
-rw-r--r-- | drivers/mmc/host/sdhci-tegra.c | 119 |
1 files changed, 45 insertions, 74 deletions
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 5a600a53b876..08b06e9a3a21 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
@@ -27,8 +27,6 @@ | |||
27 | 27 | ||
28 | #include <asm/gpio.h> | 28 | #include <asm/gpio.h> |
29 | 29 | ||
30 | #include <linux/platform_data/mmc-sdhci-tegra.h> | ||
31 | |||
32 | #include "sdhci-pltfm.h" | 30 | #include "sdhci-pltfm.h" |
33 | 31 | ||
34 | /* Tegra SDHOST controller vendor register definitions */ | 32 | /* Tegra SDHOST controller vendor register definitions */ |
@@ -45,8 +43,11 @@ struct sdhci_tegra_soc_data { | |||
45 | }; | 43 | }; |
46 | 44 | ||
47 | struct sdhci_tegra { | 45 | struct sdhci_tegra { |
48 | const struct tegra_sdhci_platform_data *plat; | ||
49 | const struct sdhci_tegra_soc_data *soc_data; | 46 | const struct sdhci_tegra_soc_data *soc_data; |
47 | int cd_gpio; | ||
48 | int wp_gpio; | ||
49 | int power_gpio; | ||
50 | int is_8bit; | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg) | 53 | static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg) |
@@ -108,12 +109,11 @@ static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host) | |||
108 | { | 109 | { |
109 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 110 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
110 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | 111 | struct sdhci_tegra *tegra_host = pltfm_host->priv; |
111 | const struct tegra_sdhci_platform_data *plat = tegra_host->plat; | ||
112 | 112 | ||
113 | if (!gpio_is_valid(plat->wp_gpio)) | 113 | if (!gpio_is_valid(tegra_host->wp_gpio)) |
114 | return -1; | 114 | return -1; |
115 | 115 | ||
116 | return gpio_get_value(plat->wp_gpio); | 116 | return gpio_get_value(tegra_host->wp_gpio); |
117 | } | 117 | } |
118 | 118 | ||
119 | static irqreturn_t carddetect_irq(int irq, void *data) | 119 | static irqreturn_t carddetect_irq(int irq, void *data) |
@@ -147,11 +147,10 @@ static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width) | |||
147 | { | 147 | { |
148 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 148 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
149 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | 149 | struct sdhci_tegra *tegra_host = pltfm_host->priv; |
150 | const struct tegra_sdhci_platform_data *plat = tegra_host->plat; | ||
151 | u32 ctrl; | 150 | u32 ctrl; |
152 | 151 | ||
153 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); | 152 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
154 | if (plat->is_8bit && bus_width == MMC_BUS_WIDTH_8) { | 153 | if (tegra_host->is_8bit && bus_width == MMC_BUS_WIDTH_8) { |
155 | ctrl &= ~SDHCI_CTRL_4BITBUS; | 154 | ctrl &= ~SDHCI_CTRL_4BITBUS; |
156 | ctrl |= SDHCI_CTRL_8BITBUS; | 155 | ctrl |= SDHCI_CTRL_8BITBUS; |
157 | } else { | 156 | } else { |
@@ -217,31 +216,19 @@ static const struct of_device_id sdhci_tegra_dt_match[] = { | |||
217 | }; | 216 | }; |
218 | MODULE_DEVICE_TABLE(of, sdhci_dt_ids); | 217 | MODULE_DEVICE_TABLE(of, sdhci_dt_ids); |
219 | 218 | ||
220 | static struct tegra_sdhci_platform_data *sdhci_tegra_dt_parse_pdata( | 219 | static void sdhci_tegra_parse_dt(struct device *dev, |
221 | struct platform_device *pdev) | 220 | struct sdhci_tegra *tegra_host) |
222 | { | 221 | { |
223 | struct tegra_sdhci_platform_data *plat; | 222 | struct device_node *np = dev->of_node; |
224 | struct device_node *np = pdev->dev.of_node; | ||
225 | u32 bus_width; | 223 | u32 bus_width; |
226 | 224 | ||
227 | if (!np) | 225 | tegra_host->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); |
228 | return NULL; | 226 | tegra_host->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); |
229 | 227 | tegra_host->power_gpio = of_get_named_gpio(np, "power-gpios", 0); | |
230 | plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); | ||
231 | if (!plat) { | ||
232 | dev_err(&pdev->dev, "Can't allocate platform data\n"); | ||
233 | return NULL; | ||
234 | } | ||
235 | |||
236 | plat->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); | ||
237 | plat->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); | ||
238 | plat->power_gpio = of_get_named_gpio(np, "power-gpios", 0); | ||
239 | 228 | ||
240 | if (of_property_read_u32(np, "bus-width", &bus_width) == 0 && | 229 | if (of_property_read_u32(np, "bus-width", &bus_width) == 0 && |
241 | bus_width == 8) | 230 | bus_width == 8) |
242 | plat->is_8bit = 1; | 231 | tegra_host->is_8bit = 1; |
243 | |||
244 | return plat; | ||
245 | } | 232 | } |
246 | 233 | ||
247 | static int sdhci_tegra_probe(struct platform_device *pdev) | 234 | static int sdhci_tegra_probe(struct platform_device *pdev) |
@@ -250,7 +237,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev) | |||
250 | const struct sdhci_tegra_soc_data *soc_data; | 237 | const struct sdhci_tegra_soc_data *soc_data; |
251 | struct sdhci_host *host; | 238 | struct sdhci_host *host; |
252 | struct sdhci_pltfm_host *pltfm_host; | 239 | struct sdhci_pltfm_host *pltfm_host; |
253 | struct tegra_sdhci_platform_data *plat; | ||
254 | struct sdhci_tegra *tegra_host; | 240 | struct sdhci_tegra *tegra_host; |
255 | struct clk *clk; | 241 | struct clk *clk; |
256 | int rc; | 242 | int rc; |
@@ -263,52 +249,40 @@ static int sdhci_tegra_probe(struct platform_device *pdev) | |||
263 | host = sdhci_pltfm_init(pdev, soc_data->pdata); | 249 | host = sdhci_pltfm_init(pdev, soc_data->pdata); |
264 | if (IS_ERR(host)) | 250 | if (IS_ERR(host)) |
265 | return PTR_ERR(host); | 251 | return PTR_ERR(host); |
266 | |||
267 | pltfm_host = sdhci_priv(host); | 252 | pltfm_host = sdhci_priv(host); |
268 | 253 | ||
269 | plat = pdev->dev.platform_data; | ||
270 | |||
271 | if (plat == NULL) | ||
272 | plat = sdhci_tegra_dt_parse_pdata(pdev); | ||
273 | |||
274 | if (plat == NULL) { | ||
275 | dev_err(mmc_dev(host->mmc), "missing platform data\n"); | ||
276 | rc = -ENXIO; | ||
277 | goto err_no_plat; | ||
278 | } | ||
279 | |||
280 | tegra_host = devm_kzalloc(&pdev->dev, sizeof(*tegra_host), GFP_KERNEL); | 254 | tegra_host = devm_kzalloc(&pdev->dev, sizeof(*tegra_host), GFP_KERNEL); |
281 | if (!tegra_host) { | 255 | if (!tegra_host) { |
282 | dev_err(mmc_dev(host->mmc), "failed to allocate tegra_host\n"); | 256 | dev_err(mmc_dev(host->mmc), "failed to allocate tegra_host\n"); |
283 | rc = -ENOMEM; | 257 | rc = -ENOMEM; |
284 | goto err_no_plat; | 258 | goto err_alloc_tegra_host; |
285 | } | 259 | } |
286 | |||
287 | tegra_host->plat = plat; | ||
288 | tegra_host->soc_data = soc_data; | 260 | tegra_host->soc_data = soc_data; |
289 | |||
290 | pltfm_host->priv = tegra_host; | 261 | pltfm_host->priv = tegra_host; |
291 | 262 | ||
292 | if (gpio_is_valid(plat->power_gpio)) { | 263 | sdhci_tegra_parse_dt(&pdev->dev, tegra_host); |
293 | rc = gpio_request(plat->power_gpio, "sdhci_power"); | 264 | |
265 | if (gpio_is_valid(tegra_host->power_gpio)) { | ||
266 | rc = gpio_request(tegra_host->power_gpio, "sdhci_power"); | ||
294 | if (rc) { | 267 | if (rc) { |
295 | dev_err(mmc_dev(host->mmc), | 268 | dev_err(mmc_dev(host->mmc), |
296 | "failed to allocate power gpio\n"); | 269 | "failed to allocate power gpio\n"); |
297 | goto err_power_req; | 270 | goto err_power_req; |
298 | } | 271 | } |
299 | gpio_direction_output(plat->power_gpio, 1); | 272 | gpio_direction_output(tegra_host->power_gpio, 1); |
300 | } | 273 | } |
301 | 274 | ||
302 | if (gpio_is_valid(plat->cd_gpio)) { | 275 | if (gpio_is_valid(tegra_host->cd_gpio)) { |
303 | rc = gpio_request(plat->cd_gpio, "sdhci_cd"); | 276 | rc = gpio_request(tegra_host->cd_gpio, "sdhci_cd"); |
304 | if (rc) { | 277 | if (rc) { |
305 | dev_err(mmc_dev(host->mmc), | 278 | dev_err(mmc_dev(host->mmc), |
306 | "failed to allocate cd gpio\n"); | 279 | "failed to allocate cd gpio\n"); |
307 | goto err_cd_req; | 280 | goto err_cd_req; |
308 | } | 281 | } |
309 | gpio_direction_input(plat->cd_gpio); | 282 | gpio_direction_input(tegra_host->cd_gpio); |
310 | 283 | ||
311 | rc = request_irq(gpio_to_irq(plat->cd_gpio), carddetect_irq, | 284 | rc = request_irq(gpio_to_irq(tegra_host->cd_gpio), |
285 | carddetect_irq, | ||
312 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 286 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, |
313 | mmc_hostname(host->mmc), host); | 287 | mmc_hostname(host->mmc), host); |
314 | 288 | ||
@@ -319,14 +293,14 @@ static int sdhci_tegra_probe(struct platform_device *pdev) | |||
319 | 293 | ||
320 | } | 294 | } |
321 | 295 | ||
322 | if (gpio_is_valid(plat->wp_gpio)) { | 296 | if (gpio_is_valid(tegra_host->wp_gpio)) { |
323 | rc = gpio_request(plat->wp_gpio, "sdhci_wp"); | 297 | rc = gpio_request(tegra_host->wp_gpio, "sdhci_wp"); |
324 | if (rc) { | 298 | if (rc) { |
325 | dev_err(mmc_dev(host->mmc), | 299 | dev_err(mmc_dev(host->mmc), |
326 | "failed to allocate wp gpio\n"); | 300 | "failed to allocate wp gpio\n"); |
327 | goto err_wp_req; | 301 | goto err_wp_req; |
328 | } | 302 | } |
329 | gpio_direction_input(plat->wp_gpio); | 303 | gpio_direction_input(tegra_host->wp_gpio); |
330 | } | 304 | } |
331 | 305 | ||
332 | clk = clk_get(mmc_dev(host->mmc), NULL); | 306 | clk = clk_get(mmc_dev(host->mmc), NULL); |
@@ -338,9 +312,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) | |||
338 | clk_prepare_enable(clk); | 312 | clk_prepare_enable(clk); |
339 | pltfm_host->clk = clk; | 313 | pltfm_host->clk = clk; |
340 | 314 | ||
341 | host->mmc->pm_caps = plat->pm_flags; | 315 | if (tegra_host->is_8bit) |
342 | |||
343 | if (plat->is_8bit) | ||
344 | host->mmc->caps |= MMC_CAP_8_BIT_DATA; | 316 | host->mmc->caps |= MMC_CAP_8_BIT_DATA; |
345 | 317 | ||
346 | rc = sdhci_add_host(host); | 318 | rc = sdhci_add_host(host); |
@@ -353,19 +325,19 @@ err_add_host: | |||
353 | clk_disable_unprepare(pltfm_host->clk); | 325 | clk_disable_unprepare(pltfm_host->clk); |
354 | clk_put(pltfm_host->clk); | 326 | clk_put(pltfm_host->clk); |
355 | err_clk_get: | 327 | err_clk_get: |
356 | if (gpio_is_valid(plat->wp_gpio)) | 328 | if (gpio_is_valid(tegra_host->wp_gpio)) |
357 | gpio_free(plat->wp_gpio); | 329 | gpio_free(tegra_host->wp_gpio); |
358 | err_wp_req: | 330 | err_wp_req: |
359 | if (gpio_is_valid(plat->cd_gpio)) | 331 | if (gpio_is_valid(tegra_host->cd_gpio)) |
360 | free_irq(gpio_to_irq(plat->cd_gpio), host); | 332 | free_irq(gpio_to_irq(tegra_host->cd_gpio), host); |
361 | err_cd_irq_req: | 333 | err_cd_irq_req: |
362 | if (gpio_is_valid(plat->cd_gpio)) | 334 | if (gpio_is_valid(tegra_host->cd_gpio)) |
363 | gpio_free(plat->cd_gpio); | 335 | gpio_free(tegra_host->cd_gpio); |
364 | err_cd_req: | 336 | err_cd_req: |
365 | if (gpio_is_valid(plat->power_gpio)) | 337 | if (gpio_is_valid(tegra_host->power_gpio)) |
366 | gpio_free(plat->power_gpio); | 338 | gpio_free(tegra_host->power_gpio); |
367 | err_power_req: | 339 | err_power_req: |
368 | err_no_plat: | 340 | err_alloc_tegra_host: |
369 | sdhci_pltfm_free(pdev); | 341 | sdhci_pltfm_free(pdev); |
370 | return rc; | 342 | return rc; |
371 | } | 343 | } |
@@ -375,21 +347,20 @@ static int sdhci_tegra_remove(struct platform_device *pdev) | |||
375 | struct sdhci_host *host = platform_get_drvdata(pdev); | 347 | struct sdhci_host *host = platform_get_drvdata(pdev); |
376 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 348 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
377 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | 349 | struct sdhci_tegra *tegra_host = pltfm_host->priv; |
378 | const struct tegra_sdhci_platform_data *plat = tegra_host->plat; | ||
379 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); | 350 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); |
380 | 351 | ||
381 | sdhci_remove_host(host, dead); | 352 | sdhci_remove_host(host, dead); |
382 | 353 | ||
383 | if (gpio_is_valid(plat->wp_gpio)) | 354 | if (gpio_is_valid(tegra_host->wp_gpio)) |
384 | gpio_free(plat->wp_gpio); | 355 | gpio_free(tegra_host->wp_gpio); |
385 | 356 | ||
386 | if (gpio_is_valid(plat->cd_gpio)) { | 357 | if (gpio_is_valid(tegra_host->cd_gpio)) { |
387 | free_irq(gpio_to_irq(plat->cd_gpio), host); | 358 | free_irq(gpio_to_irq(tegra_host->cd_gpio), host); |
388 | gpio_free(plat->cd_gpio); | 359 | gpio_free(tegra_host->cd_gpio); |
389 | } | 360 | } |
390 | 361 | ||
391 | if (gpio_is_valid(plat->power_gpio)) | 362 | if (gpio_is_valid(tegra_host->power_gpio)) |
392 | gpio_free(plat->power_gpio); | 363 | gpio_free(tegra_host->power_gpio); |
393 | 364 | ||
394 | clk_disable_unprepare(pltfm_host->clk); | 365 | clk_disable_unprepare(pltfm_host->clk); |
395 | clk_put(pltfm_host->clk); | 366 | clk_put(pltfm_host->clk); |