diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/bus/mvebu-mbus.c | 105 |
1 files changed, 16 insertions, 89 deletions
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 7fa4510dfbe4..6f047dcb94c2 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c | |||
| @@ -58,7 +58,6 @@ | |||
| 58 | #include <linux/debugfs.h> | 58 | #include <linux/debugfs.h> |
| 59 | #include <linux/log2.h> | 59 | #include <linux/log2.h> |
| 60 | #include <linux/syscore_ops.h> | 60 | #include <linux/syscore_ops.h> |
| 61 | #include <linux/memblock.h> | ||
| 62 | 61 | ||
| 63 | /* | 62 | /* |
| 64 | * DDR target is the same on all platforms. | 63 | * DDR target is the same on all platforms. |
| @@ -103,9 +102,7 @@ | |||
| 103 | 102 | ||
| 104 | /* Relative to mbusbridge_base */ | 103 | /* Relative to mbusbridge_base */ |
| 105 | #define MBUS_BRIDGE_CTRL_OFF 0x0 | 104 | #define MBUS_BRIDGE_CTRL_OFF 0x0 |
| 106 | #define MBUS_BRIDGE_SIZE_MASK 0xffff0000 | ||
| 107 | #define MBUS_BRIDGE_BASE_OFF 0x4 | 105 | #define MBUS_BRIDGE_BASE_OFF 0x4 |
| 108 | #define MBUS_BRIDGE_BASE_MASK 0xffff0000 | ||
| 109 | 106 | ||
| 110 | /* Maximum number of windows, for all known platforms */ | 107 | /* Maximum number of windows, for all known platforms */ |
| 111 | #define MBUS_WINS_MAX 20 | 108 | #define MBUS_WINS_MAX 20 |
| @@ -579,106 +576,36 @@ static unsigned int armada_xp_mbus_win_remap_offset(int win) | |||
| 579 | return MVEBU_MBUS_NO_REMAP; | 576 | return MVEBU_MBUS_NO_REMAP; |
| 580 | } | 577 | } |
| 581 | 578 | ||
| 582 | /* | ||
| 583 | * Use the memblock information to find the MBus bridge hole in the | ||
| 584 | * physical address space. | ||
| 585 | */ | ||
| 586 | static void __init | ||
| 587 | mvebu_mbus_find_bridge_hole(uint64_t *start, uint64_t *end) | ||
| 588 | { | ||
| 589 | struct memblock_region *r; | ||
| 590 | uint64_t s = 0; | ||
| 591 | |||
| 592 | for_each_memblock(memory, r) { | ||
| 593 | /* | ||
| 594 | * This part of the memory is above 4 GB, so we don't | ||
| 595 | * care for the MBus bridge hole. | ||
| 596 | */ | ||
| 597 | if (r->base >= 0x100000000) | ||
| 598 | continue; | ||
| 599 | |||
| 600 | /* | ||
| 601 | * The MBus bridge hole is at the end of the RAM under | ||
| 602 | * the 4 GB limit. | ||
| 603 | */ | ||
| 604 | if (r->base + r->size > s) | ||
| 605 | s = r->base + r->size; | ||
| 606 | } | ||
| 607 | |||
| 608 | *start = s; | ||
| 609 | *end = 0x100000000; | ||
| 610 | } | ||
| 611 | |||
| 612 | static void __init | 579 | static void __init |
| 613 | mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus) | 580 | mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus) |
| 614 | { | 581 | { |
| 615 | int i; | 582 | int i; |
| 616 | int cs; | 583 | int cs; |
| 617 | uint64_t mbus_bridge_base, mbus_bridge_end; | ||
| 618 | 584 | ||
| 619 | mvebu_mbus_dram_info.mbus_dram_target_id = TARGET_DDR; | 585 | mvebu_mbus_dram_info.mbus_dram_target_id = TARGET_DDR; |
| 620 | 586 | ||
| 621 | mvebu_mbus_find_bridge_hole(&mbus_bridge_base, &mbus_bridge_end); | ||
| 622 | |||
| 623 | for (i = 0, cs = 0; i < 4; i++) { | 587 | for (i = 0, cs = 0; i < 4; i++) { |
| 624 | u64 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i)); | 588 | u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i)); |
| 625 | u64 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i)); | 589 | u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i)); |
| 626 | u64 end; | ||
| 627 | struct mbus_dram_window *w; | ||
| 628 | |||
| 629 | /* Ignore entries that are not enabled */ | ||
| 630 | if (!(size & DDR_SIZE_ENABLED)) | ||
| 631 | continue; | ||
| 632 | |||
| 633 | /* | ||
| 634 | * Ignore entries whose base address is above 2^32, | ||
| 635 | * since devices cannot DMA to such high addresses | ||
| 636 | */ | ||
| 637 | if (base & DDR_BASE_CS_HIGH_MASK) | ||
| 638 | continue; | ||
| 639 | |||
| 640 | base = base & DDR_BASE_CS_LOW_MASK; | ||
| 641 | size = (size | ~DDR_SIZE_MASK) + 1; | ||
| 642 | end = base + size; | ||
| 643 | |||
| 644 | /* | ||
| 645 | * Adjust base/size of the current CS to make sure it | ||
| 646 | * doesn't overlap with the MBus bridge hole. This is | ||
| 647 | * particularly important for devices that do DMA from | ||
| 648 | * DRAM to a SRAM mapped in a MBus window, such as the | ||
| 649 | * CESA cryptographic engine. | ||
| 650 | */ | ||
| 651 | 590 | ||
| 652 | /* | 591 | /* |
| 653 | * The CS is fully enclosed inside the MBus bridge | 592 | * We only take care of entries for which the chip |
| 654 | * area, so ignore it. | 593 | * select is enabled, and that don't have high base |
| 594 | * address bits set (devices can only access the first | ||
| 595 | * 32 bits of the memory). | ||
| 655 | */ | 596 | */ |
| 656 | if (base >= mbus_bridge_base && end <= mbus_bridge_end) | 597 | if ((size & DDR_SIZE_ENABLED) && |
| 657 | continue; | 598 | !(base & DDR_BASE_CS_HIGH_MASK)) { |
| 599 | struct mbus_dram_window *w; | ||
| 658 | 600 | ||
| 659 | /* | 601 | w = &mvebu_mbus_dram_info.cs[cs++]; |
| 660 | * Beginning of CS overlaps with end of MBus, raise CS | 602 | w->cs_index = i; |
| 661 | * base address, and shrink its size. | 603 | w->mbus_attr = 0xf & ~(1 << i); |
| 662 | */ | 604 | if (mbus->hw_io_coherency) |
| 663 | if (base >= mbus_bridge_base && end > mbus_bridge_end) { | 605 | w->mbus_attr |= ATTR_HW_COHERENCY; |
| 664 | size -= mbus_bridge_end - base; | 606 | w->base = base & DDR_BASE_CS_LOW_MASK; |
| 665 | base = mbus_bridge_end; | 607 | w->size = (size | ~DDR_SIZE_MASK) + 1; |
| 666 | } | 608 | } |
| 667 | |||
| 668 | /* | ||
| 669 | * End of CS overlaps with beginning of MBus, shrink | ||
| 670 | * CS size. | ||
| 671 | */ | ||
| 672 | if (base < mbus_bridge_base && end > mbus_bridge_base) | ||
| 673 | size -= end - mbus_bridge_base; | ||
| 674 | |||
| 675 | w = &mvebu_mbus_dram_info.cs[cs++]; | ||
| 676 | w->cs_index = i; | ||
| 677 | w->mbus_attr = 0xf & ~(1 << i); | ||
| 678 | if (mbus->hw_io_coherency) | ||
| 679 | w->mbus_attr |= ATTR_HW_COHERENCY; | ||
| 680 | w->base = base; | ||
| 681 | w->size = size; | ||
| 682 | } | 609 | } |
| 683 | mvebu_mbus_dram_info.num_cs = cs; | 610 | mvebu_mbus_dram_info.num_cs = cs; |
| 684 | } | 611 | } |
