aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vme/bridges/vme_tsi148.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vme/bridges/vme_tsi148.c')
-rw-r--r--drivers/vme/bridges/vme_tsi148.c85
1 files changed, 83 insertions, 2 deletions
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c
index f6385f7a66d9..880d9242e349 100644
--- a/drivers/vme/bridges/vme_tsi148.c
+++ b/drivers/vme/bridges/vme_tsi148.c
@@ -1263,12 +1263,55 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
1263 u32 aspace, cycle, dwidth; 1263 u32 aspace, cycle, dwidth;
1264 struct vme_bus_error *vme_err = NULL; 1264 struct vme_bus_error *vme_err = NULL;
1265 struct vme_bridge *tsi148_bridge; 1265 struct vme_bridge *tsi148_bridge;
1266 void *addr = image->kern_base + offset;
1267 unsigned int done = 0;
1268 unsigned int count32;
1266 1269
1267 tsi148_bridge = image->parent; 1270 tsi148_bridge = image->parent;
1268 1271
1269 spin_lock(&image->lock); 1272 spin_lock(&image->lock);
1270 1273
1271 memcpy_fromio(buf, image->kern_base + offset, (unsigned int)count); 1274 /* The following code handles VME address alignment. We cannot use
1275 * memcpy_xxx directly here because it may cut small data transfers in
1276 * to 8-bit cycles, thus making D16 cycle impossible.
1277 * On the other hand, the bridge itself assures that the maximum data
1278 * cycle configured for the transfer is used and splits it
1279 * automatically for non-aligned addresses, so we don't want the
1280 * overhead of needlessly forcing small transfers for the entire cycle.
1281 */
1282 if ((uintptr_t)addr & 0x1) {
1283 *(u8 *)buf = ioread8(addr);
1284 done += 1;
1285 if (done == count)
1286 goto out;
1287 }
1288 if ((uintptr_t)addr & 0x2) {
1289 if ((count - done) < 2) {
1290 *(u8 *)(buf + done) = ioread8(addr + done);
1291 done += 1;
1292 goto out;
1293 } else {
1294 *(u16 *)(buf + done) = ioread16(addr + done);
1295 done += 2;
1296 }
1297 }
1298
1299 count32 = (count - done) & ~0x3;
1300 if (count32 > 0) {
1301 memcpy_fromio(buf + done, addr + done, count32);
1302 done += count32;
1303 }
1304
1305 if ((count - done) & 0x2) {
1306 *(u16 *)(buf + done) = ioread16(addr + done);
1307 done += 2;
1308 }
1309 if ((count - done) & 0x1) {
1310 *(u8 *)(buf + done) = ioread8(addr + done);
1311 done += 1;
1312 }
1313
1314out:
1272 retval = count; 1315 retval = count;
1273 1316
1274 if (!err_chk) 1317 if (!err_chk)
@@ -1301,6 +1344,9 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
1301 int retval = 0, enabled; 1344 int retval = 0, enabled;
1302 unsigned long long vme_base, size; 1345 unsigned long long vme_base, size;
1303 u32 aspace, cycle, dwidth; 1346 u32 aspace, cycle, dwidth;
1347 void *addr = image->kern_base + offset;
1348 unsigned int done = 0;
1349 unsigned int count32;
1304 1350
1305 struct vme_bus_error *vme_err = NULL; 1351 struct vme_bus_error *vme_err = NULL;
1306 struct vme_bridge *tsi148_bridge; 1352 struct vme_bridge *tsi148_bridge;
@@ -1312,7 +1358,42 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
1312 1358
1313 spin_lock(&image->lock); 1359 spin_lock(&image->lock);
1314 1360
1315 memcpy_toio(image->kern_base + offset, buf, (unsigned int)count); 1361 /* Here we apply for the same strategy we do in master_read
1362 * function in order to assure D16 cycle when required.
1363 */
1364 if ((uintptr_t)addr & 0x1) {
1365 iowrite8(*(u8 *)buf, addr);
1366 done += 1;
1367 if (done == count)
1368 goto out;
1369 }
1370 if ((uintptr_t)addr & 0x2) {
1371 if ((count - done) < 2) {
1372 iowrite8(*(u8 *)(buf + done), addr + done);
1373 done += 1;
1374 goto out;
1375 } else {
1376 iowrite16(*(u16 *)(buf + done), addr + done);
1377 done += 2;
1378 }
1379 }
1380
1381 count32 = (count - done) & ~0x3;
1382 if (count32 > 0) {
1383 memcpy_toio(addr + done, buf + done, count32);
1384 done += count32;
1385 }
1386
1387 if ((count - done) & 0x2) {
1388 iowrite16(*(u16 *)(buf + done), addr + done);
1389 done += 2;
1390 }
1391 if ((count - done) & 0x1) {
1392 iowrite8(*(u8 *)(buf + done), addr + done);
1393 done += 1;
1394 }
1395
1396out:
1316 retval = count; 1397 retval = count;
1317 1398
1318 /* 1399 /*