diff options
Diffstat (limited to 'arch/arm/mach-mvebu/addr-map.c')
| -rw-r--r-- | arch/arm/mach-mvebu/addr-map.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/arch/arm/mach-mvebu/addr-map.c b/arch/arm/mach-mvebu/addr-map.c new file mode 100644 index 000000000000..fe454a4430be --- /dev/null +++ b/arch/arm/mach-mvebu/addr-map.c | |||
| @@ -0,0 +1,134 @@ | |||
| 1 | /* | ||
| 2 | * Address map functions for Marvell 370 / XP SoCs | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Marvell | ||
| 5 | * | ||
| 6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
| 7 | * | ||
| 8 | * This file is licensed under the terms of the GNU General Public | ||
| 9 | * License version 2. This program is licensed "as is" without any | ||
| 10 | * warranty of any kind, whether express or implied. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/mbus.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/of.h> | ||
| 18 | #include <linux/of_address.h> | ||
| 19 | #include <plat/addr-map.h> | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Generic Address Decode Windows bit settings | ||
| 23 | */ | ||
| 24 | #define ARMADA_XP_TARGET_DEV_BUS 1 | ||
| 25 | #define ARMADA_XP_ATTR_DEV_BOOTROM 0x1D | ||
| 26 | #define ARMADA_XP_TARGET_ETH1 3 | ||
| 27 | #define ARMADA_XP_TARGET_PCIE_0_2 4 | ||
| 28 | #define ARMADA_XP_TARGET_ETH0 7 | ||
| 29 | #define ARMADA_XP_TARGET_PCIE_1_3 8 | ||
| 30 | |||
| 31 | #define ARMADA_370_TARGET_DEV_BUS 1 | ||
| 32 | #define ARMADA_370_ATTR_DEV_BOOTROM 0x1D | ||
| 33 | #define ARMADA_370_TARGET_PCIE_0 4 | ||
| 34 | #define ARMADA_370_TARGET_PCIE_1 8 | ||
| 35 | |||
| 36 | #define ARMADA_WINDOW_8_PLUS_OFFSET 0x90 | ||
| 37 | #define ARMADA_SDRAM_ADDR_DECODING_OFFSET 0x180 | ||
| 38 | |||
| 39 | static const struct __initdata orion_addr_map_info | ||
| 40 | armada_xp_addr_map_info[] = { | ||
| 41 | /* | ||
| 42 | * Window for the BootROM, needed for SMP on Armada XP | ||
| 43 | */ | ||
| 44 | { 0, 0xfff00000, SZ_1M, ARMADA_XP_TARGET_DEV_BUS, | ||
| 45 | ARMADA_XP_ATTR_DEV_BOOTROM, -1 }, | ||
| 46 | /* End marker */ | ||
| 47 | { -1, 0, 0, 0, 0, 0 }, | ||
| 48 | }; | ||
| 49 | |||
| 50 | static const struct __initdata orion_addr_map_info | ||
| 51 | armada_370_addr_map_info[] = { | ||
| 52 | /* End marker */ | ||
| 53 | { -1, 0, 0, 0, 0, 0 }, | ||
| 54 | }; | ||
| 55 | |||
| 56 | static struct of_device_id of_addr_decoding_controller_table[] = { | ||
| 57 | { .compatible = "marvell,armada-addr-decoding-controller" }, | ||
| 58 | { /* end of list */ }, | ||
| 59 | }; | ||
| 60 | |||
| 61 | static void __iomem * | ||
| 62 | armada_cfg_base(const struct orion_addr_map_cfg *cfg, int win) | ||
| 63 | { | ||
| 64 | unsigned int offset; | ||
| 65 | |||
| 66 | /* The register layout is a bit annoying and the below code | ||
| 67 | * tries to cope with it. | ||
| 68 | * - At offset 0x0, there are the registers for the first 8 | ||
| 69 | * windows, with 4 registers of 32 bits per window (ctrl, | ||
| 70 | * base, remap low, remap high) | ||
| 71 | * - Then at offset 0x80, there is a hole of 0x10 bytes for | ||
| 72 | * the internal registers base address and internal units | ||
| 73 | * sync barrier register. | ||
| 74 | * - Then at offset 0x90, there the registers for 12 | ||
| 75 | * windows, with only 2 registers of 32 bits per window | ||
| 76 | * (ctrl, base). | ||
| 77 | */ | ||
| 78 | if (win < 8) | ||
| 79 | offset = (win << 4); | ||
| 80 | else | ||
| 81 | offset = ARMADA_WINDOW_8_PLUS_OFFSET + (win << 3); | ||
| 82 | |||
| 83 | return cfg->bridge_virt_base + offset; | ||
| 84 | } | ||
| 85 | |||
| 86 | static struct __initdata orion_addr_map_cfg addr_map_cfg = { | ||
| 87 | .num_wins = 20, | ||
| 88 | .remappable_wins = 8, | ||
| 89 | .win_cfg_base = armada_cfg_base, | ||
| 90 | }; | ||
| 91 | |||
| 92 | static int __init armada_setup_cpu_mbus(void) | ||
| 93 | { | ||
| 94 | struct device_node *np; | ||
| 95 | void __iomem *mbus_unit_addr_decoding_base; | ||
| 96 | void __iomem *sdram_addr_decoding_base; | ||
| 97 | |||
| 98 | np = of_find_matching_node(NULL, of_addr_decoding_controller_table); | ||
| 99 | if (!np) | ||
| 100 | return -ENODEV; | ||
| 101 | |||
| 102 | mbus_unit_addr_decoding_base = of_iomap(np, 0); | ||
| 103 | BUG_ON(!mbus_unit_addr_decoding_base); | ||
| 104 | |||
| 105 | sdram_addr_decoding_base = | ||
| 106 | mbus_unit_addr_decoding_base + | ||
| 107 | ARMADA_SDRAM_ADDR_DECODING_OFFSET; | ||
| 108 | |||
| 109 | addr_map_cfg.bridge_virt_base = mbus_unit_addr_decoding_base; | ||
| 110 | |||
| 111 | /* | ||
| 112 | * Disable, clear and configure windows. | ||
| 113 | */ | ||
| 114 | if (of_machine_is_compatible("marvell,armadaxp")) | ||
| 115 | orion_config_wins(&addr_map_cfg, armada_xp_addr_map_info); | ||
| 116 | else if (of_machine_is_compatible("marvell,armada370")) | ||
| 117 | orion_config_wins(&addr_map_cfg, armada_370_addr_map_info); | ||
| 118 | else { | ||
| 119 | pr_err("Unsupported SoC\n"); | ||
| 120 | return -EINVAL; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* | ||
| 124 | * Setup MBUS dram target info. | ||
| 125 | */ | ||
| 126 | orion_setup_cpu_mbus_target(&addr_map_cfg, | ||
| 127 | sdram_addr_decoding_base); | ||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | /* Using a early_initcall is needed so that this initialization gets | ||
| 132 | * done before the SMP initialization, which requires the BootROM to | ||
| 133 | * be remapped. */ | ||
| 134 | early_initcall(armada_setup_cpu_mbus); | ||
