aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 4646cc7aa93a..cd37e49e7034 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -1,6 +1,10 @@
1/* 1/*
2 * Freescale MPC85xx/MPC86xx RapidIO support 2 * Freescale MPC85xx/MPC86xx RapidIO support
3 * 3 *
4 * Copyright 2009 Sysgo AG
5 * Thomas Moll <thomas.moll@sysgo.com>
6 * - fixed maintenance access routines, check for aligned access
7 *
4 * Copyright 2009 Integrated Device Technology, Inc. 8 * Copyright 2009 Integrated Device Technology, Inc.
5 * Alex Bounine <alexandre.bounine@idt.com> 9 * Alex Bounine <alexandre.bounine@idt.com>
6 * - Added Port-Write message handling 10 * - Added Port-Write message handling
@@ -371,10 +375,17 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
371 pr_debug 375 pr_debug
372 ("fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n", 376 ("fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
373 index, destid, hopcount, offset, len); 377 index, destid, hopcount, offset, len);
378
379 /* 16MB maintenance window possible */
380 /* allow only aligned access to maintenance registers */
381 if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
382 return -EINVAL;
383
374 out_be32(&priv->maint_atmu_regs->rowtar, 384 out_be32(&priv->maint_atmu_regs->rowtar,
375 (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9)); 385 (destid << 22) | (hopcount << 12) | (offset >> 12));
386 out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
376 387
377 data = (u8 *) priv->maint_win + offset; 388 data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1));
378 switch (len) { 389 switch (len) {
379 case 1: 390 case 1:
380 __fsl_read_rio_config(rval, data, err, "lbz"); 391 __fsl_read_rio_config(rval, data, err, "lbz");
@@ -382,9 +393,11 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
382 case 2: 393 case 2:
383 __fsl_read_rio_config(rval, data, err, "lhz"); 394 __fsl_read_rio_config(rval, data, err, "lhz");
384 break; 395 break;
385 default: 396 case 4:
386 __fsl_read_rio_config(rval, data, err, "lwz"); 397 __fsl_read_rio_config(rval, data, err, "lwz");
387 break; 398 break;
399 default:
400 return -EINVAL;
388 } 401 }
389 402
390 if (err) { 403 if (err) {
@@ -419,10 +432,17 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
419 pr_debug 432 pr_debug
420 ("fsl_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n", 433 ("fsl_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
421 index, destid, hopcount, offset, len, val); 434 index, destid, hopcount, offset, len, val);
435
436 /* 16MB maintenance windows possible */
437 /* allow only aligned access to maintenance registers */
438 if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
439 return -EINVAL;
440
422 out_be32(&priv->maint_atmu_regs->rowtar, 441 out_be32(&priv->maint_atmu_regs->rowtar,
423 (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9)); 442 (destid << 22) | (hopcount << 12) | (offset >> 12));
443 out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
424 444
425 data = (u8 *) priv->maint_win + offset; 445 data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1));
426 switch (len) { 446 switch (len) {
427 case 1: 447 case 1:
428 out_8((u8 *) data, val); 448 out_8((u8 *) data, val);
@@ -430,9 +450,11 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
430 case 2: 450 case 2:
431 out_be16((u16 *) data, val); 451 out_be16((u16 *) data, val);
432 break; 452 break;
433 default: 453 case 4:
434 out_be32((u32 *) data, val); 454 out_be32((u32 *) data, val);
435 break; 455 break;
456 default:
457 return -EINVAL;
436 } 458 }
437 459
438 return 0; 460 return 0;
@@ -1483,7 +1505,8 @@ int fsl_rio_setup(struct of_device *dev)
1483 1505
1484 /* Configure maintenance transaction window */ 1506 /* Configure maintenance transaction window */
1485 out_be32(&priv->maint_atmu_regs->rowbar, law_start >> 12); 1507 out_be32(&priv->maint_atmu_regs->rowbar, law_start >> 12);
1486 out_be32(&priv->maint_atmu_regs->rowar, 0x80077015); /* 4M */ 1508 out_be32(&priv->maint_atmu_regs->rowar,
1509 0x80077000 | (ilog2(RIO_MAINT_WIN_SIZE) - 1));
1487 1510
1488 priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE); 1511 priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE);
1489 1512