aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/omap_hsmmc.c
diff options
context:
space:
mode:
authorBalaji T K <balajitk@ti.com>2014-01-21 09:24:42 -0500
committerChris Ball <chris@printf.net>2014-03-04 11:46:49 -0500
commita2e771522c2a60459a79844004722f109cb4e13d (patch)
tree1c51cac9288636b69191adf8dbaf7afd130784b2 /drivers/mmc/host/omap_hsmmc.c
parentbf129e1ca19f973731d56478297be3de3181efcb (diff)
mmc: omap_hsmmc: add autocmd23 support
Add support for autocmd23 support Signed-off-by: Balaji T K <balajitk@ti.com> Signed-off-by: Chris Ball <chris@printf.net>
Diffstat (limited to 'drivers/mmc/host/omap_hsmmc.c')
-rw-r--r--drivers/mmc/host/omap_hsmmc.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 476c6a632bfc..e91ee21549d0 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -45,6 +45,7 @@
45/* OMAP HSMMC Host Controller Registers */ 45/* OMAP HSMMC Host Controller Registers */
46#define OMAP_HSMMC_SYSSTATUS 0x0014 46#define OMAP_HSMMC_SYSSTATUS 0x0014
47#define OMAP_HSMMC_CON 0x002C 47#define OMAP_HSMMC_CON 0x002C
48#define OMAP_HSMMC_SDMASA 0x0100
48#define OMAP_HSMMC_BLK 0x0104 49#define OMAP_HSMMC_BLK 0x0104
49#define OMAP_HSMMC_ARG 0x0108 50#define OMAP_HSMMC_ARG 0x0108
50#define OMAP_HSMMC_CMD 0x010C 51#define OMAP_HSMMC_CMD 0x010C
@@ -58,6 +59,7 @@
58#define OMAP_HSMMC_STAT 0x0130 59#define OMAP_HSMMC_STAT 0x0130
59#define OMAP_HSMMC_IE 0x0134 60#define OMAP_HSMMC_IE 0x0134
60#define OMAP_HSMMC_ISE 0x0138 61#define OMAP_HSMMC_ISE 0x0138
62#define OMAP_HSMMC_AC12 0x013C
61#define OMAP_HSMMC_CAPA 0x0140 63#define OMAP_HSMMC_CAPA 0x0140
62 64
63#define VS18 (1 << 26) 65#define VS18 (1 << 26)
@@ -81,6 +83,7 @@
81#define DTO_MASK 0x000F0000 83#define DTO_MASK 0x000F0000
82#define DTO_SHIFT 16 84#define DTO_SHIFT 16
83#define INIT_STREAM (1 << 1) 85#define INIT_STREAM (1 << 1)
86#define ACEN_ACMD23 (2 << 2)
84#define DP_SELECT (1 << 21) 87#define DP_SELECT (1 << 21)
85#define DDIR (1 << 4) 88#define DDIR (1 << 4)
86#define DMAE 0x1 89#define DMAE 0x1
@@ -111,13 +114,21 @@
111#define DTO_EN (1 << 20) 114#define DTO_EN (1 << 20)
112#define DCRC_EN (1 << 21) 115#define DCRC_EN (1 << 21)
113#define DEB_EN (1 << 22) 116#define DEB_EN (1 << 22)
117#define ACE_EN (1 << 24)
114#define CERR_EN (1 << 28) 118#define CERR_EN (1 << 28)
115#define BADA_EN (1 << 29) 119#define BADA_EN (1 << 29)
116 120
117#define INT_EN_MASK (BADA_EN | CERR_EN | DEB_EN | DCRC_EN |\ 121#define INT_EN_MASK (BADA_EN | CERR_EN | ACE_EN | DEB_EN | DCRC_EN |\
118 DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \ 122 DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \
119 BRR_EN | BWR_EN | TC_EN | CC_EN) 123 BRR_EN | BWR_EN | TC_EN | CC_EN)
120 124
125#define CNI (1 << 7)
126#define ACIE (1 << 4)
127#define ACEB (1 << 3)
128#define ACCE (1 << 2)
129#define ACTO (1 << 1)
130#define ACNE (1 << 0)
131
121#define MMC_AUTOSUSPEND_DELAY 100 132#define MMC_AUTOSUSPEND_DELAY 100
122#define MMC_TIMEOUT_MS 20 /* 20 mSec */ 133#define MMC_TIMEOUT_MS 20 /* 20 mSec */
123#define MMC_TIMEOUT_US 20000 /* 20000 micro Sec */ 134#define MMC_TIMEOUT_US 20000 /* 20000 micro Sec */
@@ -129,6 +140,7 @@
129#define VDD_3V0 3000000 /* 300000 uV */ 140#define VDD_3V0 3000000 /* 300000 uV */
130#define VDD_165_195 (ffs(MMC_VDD_165_195) - 1) 141#define VDD_165_195 (ffs(MMC_VDD_165_195) - 1)
131 142
143#define AUTO_CMD23 (1 << 1) /* Auto CMD23 support */
132/* 144/*
133 * One controller can have multiple slots, like on some omap boards using 145 * One controller can have multiple slots, like on some omap boards using
134 * omap.c controller driver. Luckily this is not currently done on any known 146 * omap.c controller driver. Luckily this is not currently done on any known
@@ -193,6 +205,7 @@ struct omap_hsmmc_host {
193 int use_reg; 205 int use_reg;
194 int req_in_progress; 206 int req_in_progress;
195 unsigned long clk_rate; 207 unsigned long clk_rate;
208 unsigned int flags;
196 struct omap_hsmmc_next next_data; 209 struct omap_hsmmc_next next_data;
197 struct omap_mmc_platform_data *pdata; 210 struct omap_mmc_platform_data *pdata;
198}; 211};
@@ -813,6 +826,11 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
813 826
814 cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22); 827 cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
815 828
829 if ((host->flags & AUTO_CMD23) && mmc_op_multi(cmd->opcode) &&
830 host->mrq->sbc) {
831 cmdreg |= ACEN_ACMD23;
832 OMAP_HSMMC_WRITE(host->base, SDMASA, host->mrq->sbc->arg);
833 }
816 if (data) { 834 if (data) {
817 cmdreg |= DP_SELECT | MSBS | BCE; 835 cmdreg |= DP_SELECT | MSBS | BCE;
818 if (data->flags & MMC_DATA_READ) 836 if (data->flags & MMC_DATA_READ)
@@ -905,7 +923,7 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd)
905 host->cmd = NULL; 923 host->cmd = NULL;
906 924
907 if (host->mrq->sbc && (host->cmd == host->mrq->sbc) && 925 if (host->mrq->sbc && (host->cmd == host->mrq->sbc) &&
908 !host->mrq->sbc->error) { 926 !host->mrq->sbc->error && !(host->flags & AUTO_CMD23)) {
909 omap_hsmmc_start_dma_transfer(host); 927 omap_hsmmc_start_dma_transfer(host);
910 omap_hsmmc_start_command(host, host->mrq->cmd, 928 omap_hsmmc_start_command(host, host->mrq->cmd,
911 host->mrq->data); 929 host->mrq->data);
@@ -1048,6 +1066,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
1048{ 1066{
1049 struct mmc_data *data; 1067 struct mmc_data *data;
1050 int end_cmd = 0, end_trans = 0; 1068 int end_cmd = 0, end_trans = 0;
1069 int error = 0;
1051 1070
1052 data = host->data; 1071 data = host->data;
1053 dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); 1072 dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
@@ -1062,6 +1081,20 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
1062 else if (status & (CCRC_EN | DCRC_EN)) 1081 else if (status & (CCRC_EN | DCRC_EN))
1063 hsmmc_command_incomplete(host, -EILSEQ, end_cmd); 1082 hsmmc_command_incomplete(host, -EILSEQ, end_cmd);
1064 1083
1084 if (status & ACE_EN) {
1085 u32 ac12;
1086 ac12 = OMAP_HSMMC_READ(host->base, AC12);
1087 if (!(ac12 & ACNE) && host->mrq->sbc) {
1088 end_cmd = 1;
1089 if (ac12 & ACTO)
1090 error = -ETIMEDOUT;
1091 else if (ac12 & (ACCE | ACEB | ACIE))
1092 error = -EILSEQ;
1093 host->mrq->sbc->error = error;
1094 hsmmc_command_incomplete(host, error, end_cmd);
1095 }
1096 dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12);
1097 }
1065 if (host->data || host->response_busy) { 1098 if (host->data || host->response_busy) {
1066 end_trans = !end_cmd; 1099 end_trans = !end_cmd;
1067 host->response_busy = 0; 1100 host->response_busy = 0;
@@ -1513,7 +1546,7 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
1513 mmc_request_done(mmc, req); 1546 mmc_request_done(mmc, req);
1514 return; 1547 return;
1515 } 1548 }
1516 if (req->sbc) { 1549 if (req->sbc && !(host->flags & AUTO_CMD23)) {
1517 omap_hsmmc_start_command(host, req->sbc, NULL); 1550 omap_hsmmc_start_command(host, req->sbc, NULL);
1518 return; 1551 return;
1519 } 1552 }