diff options
author | Jaehoon Chung <jh80.chung@samsung.com> | 2011-10-17 06:36:23 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2011-10-26 16:32:25 -0400 |
commit | 4e0a5adf46ee7810af2e1b7e4e8c2a298652618e (patch) | |
tree | 64b60adcedd341a02a8f150ce7257e2b0eb40e0c /drivers/mmc/host/dw_mmc.c | |
parent | c43fd7746698a10aa6435d62ec28f977dd6246cc (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.c | 66 |
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 | */ |