diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/sysdev/fsl_rio.c | 37 |
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 | ||