diff options
author | Simon Horman <horms@verge.net.au> | 2011-06-20 19:00:10 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2011-07-20 17:20:57 -0400 |
commit | 973ed3af1a570612771ed10dec6506c757767668 (patch) | |
tree | db993034cacfcc3f3388c43d96459a123adc32a2 /drivers/mmc/host/sh_mobile_sdhi.c | |
parent | a11862d3389d4304211eed0758f510d5e573f93c (diff) |
mmc: sdhi: Add write16_hook
Some controllers require waiting for the bus to become idle
before writing to some registers. I have implemented this
by adding a hook to sd_ctrl_write16() and implementing
a hook for SDHI which waits for the bus to become idle.
Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Cc: Magnus Damm <magnus.damm@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/sh_mobile_sdhi.c')
-rw-r--r-- | drivers/mmc/host/sh_mobile_sdhi.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index ce500f03df85..774f6439d7ce 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/mmc/sh_mobile_sdhi.h> | 26 | #include <linux/mmc/sh_mobile_sdhi.h> |
27 | #include <linux/mfd/tmio.h> | 27 | #include <linux/mfd/tmio.h> |
28 | #include <linux/sh_dma.h> | 28 | #include <linux/sh_dma.h> |
29 | #include <linux/delay.h> | ||
29 | 30 | ||
30 | #include "tmio_mmc.h" | 31 | #include "tmio_mmc.h" |
31 | 32 | ||
@@ -55,6 +56,39 @@ static int sh_mobile_sdhi_get_cd(struct platform_device *pdev) | |||
55 | return -ENOSYS; | 56 | return -ENOSYS; |
56 | } | 57 | } |
57 | 58 | ||
59 | static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) | ||
60 | { | ||
61 | int timeout = 1000; | ||
62 | |||
63 | while (--timeout && !(sd_ctrl_read16(host, CTL_STATUS2) & (1 << 13))) | ||
64 | udelay(1); | ||
65 | |||
66 | if (!timeout) { | ||
67 | dev_warn(host->pdata->dev, "timeout waiting for SD bus idle\n"); | ||
68 | return -EBUSY; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) | ||
75 | { | ||
76 | switch (addr) | ||
77 | { | ||
78 | case CTL_SD_CMD: | ||
79 | case CTL_STOP_INTERNAL_ACTION: | ||
80 | case CTL_XFER_BLK_COUNT: | ||
81 | case CTL_SD_CARD_CLK_CTL: | ||
82 | case CTL_SD_XFER_LEN: | ||
83 | case CTL_SD_MEM_CARD_OPT: | ||
84 | case CTL_TRANSACTION_CTL: | ||
85 | case CTL_DMA_ENABLE: | ||
86 | return sh_mobile_sdhi_wait_idle(host); | ||
87 | } | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
58 | static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) | 92 | static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) |
59 | { | 93 | { |
60 | struct sh_mobile_sdhi *priv; | 94 | struct sh_mobile_sdhi *priv; |
@@ -86,6 +120,8 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
86 | mmc_data->hclk = clk_get_rate(priv->clk); | 120 | mmc_data->hclk = clk_get_rate(priv->clk); |
87 | mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; | 121 | mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; |
88 | mmc_data->get_cd = sh_mobile_sdhi_get_cd; | 122 | mmc_data->get_cd = sh_mobile_sdhi_get_cd; |
123 | if (mmc_data->flags & TMIO_MMC_HAS_IDLE_WAIT) | ||
124 | mmc_data->write16_hook = sh_mobile_sdhi_write16_hook; | ||
89 | mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; | 125 | mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; |
90 | if (p) { | 126 | if (p) { |
91 | mmc_data->flags = p->tmio_flags; | 127 | mmc_data->flags = p->tmio_flags; |