aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/dw_mmc.c
diff options
context:
space:
mode:
authorJaehoon Chung <jh80.chung@samsung.com>2011-10-17 06:36:23 -0400
committerChris Ball <cjb@laptop.org>2011-10-26 16:32:25 -0400
commit4e0a5adf46ee7810af2e1b7e4e8c2a298652618e (patch)
tree64b60adcedd341a02a8f150ce7257e2b0eb40e0c /drivers/mmc/host/dw_mmc.c
parentc43fd7746698a10aa6435d62ec28f977dd6246cc (diff)
mmc: dw_mmc: modify DATA register offset
In dw_mmc 2.40a spec, Data register's offset is changed. Before we used Data register offset 0x100. but if somebody uses a 2.40a controller, we must use 0x200 for Data register. This patch adds a version-id checking point and uses SDMMC_DATA(x) instead of SDMMC_DATA. It assumes 2.40a is the latest version. Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Acked-by: James Hogan <james.hogan@imgtec.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/dw_mmc.c')
-rw-r--r--drivers/mmc/host/dw_mmc.c66
1 files changed, 45 insertions, 21 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 701f14e8b54b..3aaeb0841914 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1043,7 +1043,8 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
1043 buf += len; 1043 buf += len;
1044 cnt -= len; 1044 cnt -= len;
1045 if (!sg_next(host->sg) || host->part_buf_count == 2) { 1045 if (!sg_next(host->sg) || host->part_buf_count == 2) {
1046 mci_writew(host, DATA, host->part_buf16); 1046 mci_writew(host, DATA(host->data_offset),
1047 host->part_buf16);
1047 host->part_buf_count = 0; 1048 host->part_buf_count = 0;
1048 } 1049 }
1049 } 1050 }
@@ -1060,21 +1061,23 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
1060 cnt -= len; 1061 cnt -= len;
1061 /* push data from aligned buffer into fifo */ 1062 /* push data from aligned buffer into fifo */
1062 for (i = 0; i < items; ++i) 1063 for (i = 0; i < items; ++i)
1063 mci_writew(host, DATA, aligned_buf[i]); 1064 mci_writew(host, DATA(host->data_offset),
1065 aligned_buf[i]);
1064 } 1066 }
1065 } else 1067 } else
1066#endif 1068#endif
1067 { 1069 {
1068 u16 *pdata = buf; 1070 u16 *pdata = buf;
1069 for (; cnt >= 2; cnt -= 2) 1071 for (; cnt >= 2; cnt -= 2)
1070 mci_writew(host, DATA, *pdata++); 1072 mci_writew(host, DATA(host->data_offset), *pdata++);
1071 buf = pdata; 1073 buf = pdata;
1072 } 1074 }
1073 /* put anything remaining in the part_buf */ 1075 /* put anything remaining in the part_buf */
1074 if (cnt) { 1076 if (cnt) {
1075 dw_mci_set_part_bytes(host, buf, cnt); 1077 dw_mci_set_part_bytes(host, buf, cnt);
1076 if (!sg_next(host->sg)) 1078 if (!sg_next(host->sg))
1077 mci_writew(host, DATA, host->part_buf16); 1079 mci_writew(host, DATA(host->data_offset),
1080 host->part_buf16);
1078 } 1081 }
1079} 1082}
1080 1083
@@ -1089,7 +1092,8 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
1089 int items = len >> 1; 1092 int items = len >> 1;
1090 int i; 1093 int i;
1091 for (i = 0; i < items; ++i) 1094 for (i = 0; i < items; ++i)
1092 aligned_buf[i] = mci_readw(host, DATA); 1095 aligned_buf[i] = mci_readw(host,
1096 DATA(host->data_offset));
1093 /* memcpy from aligned buffer into output buffer */ 1097 /* memcpy from aligned buffer into output buffer */
1094 memcpy(buf, aligned_buf, len); 1098 memcpy(buf, aligned_buf, len);
1095 buf += len; 1099 buf += len;
@@ -1100,11 +1104,11 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
1100 { 1104 {
1101 u16 *pdata = buf; 1105 u16 *pdata = buf;
1102 for (; cnt >= 2; cnt -= 2) 1106 for (; cnt >= 2; cnt -= 2)
1103 *pdata++ = mci_readw(host, DATA); 1107 *pdata++ = mci_readw(host, DATA(host->data_offset));
1104 buf = pdata; 1108 buf = pdata;
1105 } 1109 }
1106 if (cnt) { 1110 if (cnt) {
1107 host->part_buf16 = mci_readw(host, DATA); 1111 host->part_buf16 = mci_readw(host, DATA(host->data_offset));
1108 dw_mci_pull_final_bytes(host, buf, cnt); 1112 dw_mci_pull_final_bytes(host, buf, cnt);
1109 } 1113 }
1110} 1114}
@@ -1117,7 +1121,8 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
1117 buf += len; 1121 buf += len;
1118 cnt -= len; 1122 cnt -= len;
1119 if (!sg_next(host->sg) || host->part_buf_count == 4) { 1123 if (!sg_next(host->sg) || host->part_buf_count == 4) {
1120 mci_writel(host, DATA, host->part_buf32); 1124 mci_writel(host, DATA(host->data_offset),
1125 host->part_buf32);
1121 host->part_buf_count = 0; 1126 host->part_buf_count = 0;
1122 } 1127 }
1123 } 1128 }
@@ -1134,21 +1139,23 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
1134 cnt -= len; 1139 cnt -= len;
1135 /* push data from aligned buffer into fifo */ 1140 /* push data from aligned buffer into fifo */
1136 for (i = 0; i < items; ++i) 1141 for (i = 0; i < items; ++i)
1137 mci_writel(host, DATA, aligned_buf[i]); 1142 mci_writel(host, DATA(host->data_offset),
1143 aligned_buf[i]);
1138 } 1144 }
1139 } else 1145 } else
1140#endif 1146#endif
1141 { 1147 {
1142 u32 *pdata = buf; 1148 u32 *pdata = buf;
1143 for (; cnt >= 4; cnt -= 4) 1149 for (; cnt >= 4; cnt -= 4)
1144 mci_writel(host, DATA, *pdata++); 1150 mci_writel(host, DATA(host->data_offset), *pdata++);
1145 buf = pdata; 1151 buf = pdata;
1146 } 1152 }
1147 /* put anything remaining in the part_buf */ 1153 /* put anything remaining in the part_buf */
1148 if (cnt) { 1154 if (cnt) {
1149 dw_mci_set_part_bytes(host, buf, cnt); 1155 dw_mci_set_part_bytes(host, buf, cnt);
1150 if (!sg_next(host->sg)) 1156 if (!sg_next(host->sg))
1151 mci_writel(host, DATA, host->part_buf32); 1157 mci_writel(host, DATA(host->data_offset),
1158 host->part_buf32);
1152 } 1159 }
1153} 1160}
1154 1161
@@ -1163,7 +1170,8 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
1163 int items = len >> 2; 1170 int items = len >> 2;
1164 int i; 1171 int i;
1165 for (i = 0; i < items; ++i) 1172 for (i = 0; i < items; ++i)
1166 aligned_buf[i] = mci_readl(host, DATA); 1173 aligned_buf[i] = mci_readl(host,
1174 DATA(host->data_offset));
1167 /* memcpy from aligned buffer into output buffer */ 1175 /* memcpy from aligned buffer into output buffer */
1168 memcpy(buf, aligned_buf, len); 1176 memcpy(buf, aligned_buf, len);
1169 buf += len; 1177 buf += len;
@@ -1174,11 +1182,11 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
1174 { 1182 {
1175 u32 *pdata = buf; 1183 u32 *pdata = buf;
1176 for (; cnt >= 4; cnt -= 4) 1184 for (; cnt >= 4; cnt -= 4)
1177 *pdata++ = mci_readl(host, DATA); 1185 *pdata++ = mci_readl(host, DATA(host->data_offset));
1178 buf = pdata; 1186 buf = pdata;
1179 } 1187 }
1180 if (cnt) { 1188 if (cnt) {
1181 host->part_buf32 = mci_readl(host, DATA); 1189 host->part_buf32 = mci_readl(host, DATA(host->data_offset));
1182 dw_mci_pull_final_bytes(host, buf, cnt); 1190 dw_mci_pull_final_bytes(host, buf, cnt);
1183 } 1191 }
1184} 1192}
@@ -1191,7 +1199,8 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
1191 buf += len; 1199 buf += len;
1192 cnt -= len; 1200 cnt -= len;
1193 if (!sg_next(host->sg) || host->part_buf_count == 8) { 1201 if (!sg_next(host->sg) || host->part_buf_count == 8) {
1194 mci_writew(host, DATA, host->part_buf); 1202 mci_writew(host, DATA(host->data_offset),
1203 host->part_buf);
1195 host->part_buf_count = 0; 1204 host->part_buf_count = 0;
1196 } 1205 }
1197 } 1206 }
@@ -1208,21 +1217,23 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
1208 cnt -= len; 1217 cnt -= len;
1209 /* push data from aligned buffer into fifo */ 1218 /* push data from aligned buffer into fifo */
1210 for (i = 0; i < items; ++i) 1219 for (i = 0; i < items; ++i)
1211 mci_writeq(host, DATA, aligned_buf[i]); 1220 mci_writeq(host, DATA(host->data_offset),
1221 aligned_buf[i]);
1212 } 1222 }
1213 } else 1223 } else
1214#endif 1224#endif
1215 { 1225 {
1216 u64 *pdata = buf; 1226 u64 *pdata = buf;
1217 for (; cnt >= 8; cnt -= 8) 1227 for (; cnt >= 8; cnt -= 8)
1218 mci_writeq(host, DATA, *pdata++); 1228 mci_writeq(host, DATA(host->data_offset), *pdata++);
1219 buf = pdata; 1229 buf = pdata;
1220 } 1230 }
1221 /* put anything remaining in the part_buf */ 1231 /* put anything remaining in the part_buf */
1222 if (cnt) { 1232 if (cnt) {
1223 dw_mci_set_part_bytes(host, buf, cnt); 1233 dw_mci_set_part_bytes(host, buf, cnt);
1224 if (!sg_next(host->sg)) 1234 if (!sg_next(host->sg))
1225 mci_writeq(host, DATA, host->part_buf); 1235 mci_writeq(host, DATA(host->data_offset),
1236 host->part_buf);
1226 } 1237 }
1227} 1238}
1228 1239
@@ -1237,7 +1248,8 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
1237 int items = len >> 3; 1248 int items = len >> 3;
1238 int i; 1249 int i;
1239 for (i = 0; i < items; ++i) 1250 for (i = 0; i < items; ++i)
1240 aligned_buf[i] = mci_readq(host, DATA); 1251 aligned_buf[i] = mci_readq(host,
1252 DATA(host->data_offset));
1241 /* memcpy from aligned buffer into output buffer */ 1253 /* memcpy from aligned buffer into output buffer */
1242 memcpy(buf, aligned_buf, len); 1254 memcpy(buf, aligned_buf, len);
1243 buf += len; 1255 buf += len;
@@ -1248,11 +1260,11 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
1248 { 1260 {
1249 u64 *pdata = buf; 1261 u64 *pdata = buf;
1250 for (; cnt >= 8; cnt -= 8) 1262 for (; cnt >= 8; cnt -= 8)
1251 *pdata++ = mci_readq(host, DATA); 1263 *pdata++ = mci_readq(host, DATA(host->data_offset));
1252 buf = pdata; 1264 buf = pdata;
1253 } 1265 }
1254 if (cnt) { 1266 if (cnt) {
1255 host->part_buf = mci_readq(host, DATA); 1267 host->part_buf = mci_readq(host, DATA(host->data_offset));
1256 dw_mci_pull_final_bytes(host, buf, cnt); 1268 dw_mci_pull_final_bytes(host, buf, cnt);
1257 } 1269 }
1258} 1270}
@@ -1952,6 +1964,18 @@ static int dw_mci_probe(struct platform_device *pdev)
1952 } 1964 }
1953 1965
1954 /* 1966 /*
1967 * In 2.40a spec, Data offset is changed.
1968 * Need to check the version-id and set data-offset for DATA register.
1969 */
1970 host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
1971 dev_info(&pdev->dev, "Version ID is %04x\n", host->verid);
1972
1973 if (host->verid < DW_MMC_240A)
1974 host->data_offset = DATA_OFFSET;
1975 else
1976 host->data_offset = DATA_240A_OFFSET;
1977
1978 /*
1955 * Enable interrupts for command done, data over, data empty, card det, 1979 * Enable interrupts for command done, data over, data empty, card det,
1956 * receive ready and error such as transmit, receive timeout, crc error 1980 * receive ready and error such as transmit, receive timeout, crc error
1957 */ 1981 */