Commit | Line | Data |
---|---|---|
74dd80a7 TP |
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 | |
9f3410ff | 81 | offset = ARMADA_WINDOW_8_PLUS_OFFSET + ((win - 8) << 3); |
74dd80a7 TP |
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 | ||
e60304f8 GC |
111 | if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric")) |
112 | addr_map_cfg.hw_io_coherency = 1; | |
113 | ||
74dd80a7 TP |
114 | /* |
115 | * Disable, clear and configure windows. | |
116 | */ | |
117 | if (of_machine_is_compatible("marvell,armadaxp")) | |
118 | orion_config_wins(&addr_map_cfg, armada_xp_addr_map_info); | |
119 | else if (of_machine_is_compatible("marvell,armada370")) | |
120 | orion_config_wins(&addr_map_cfg, armada_370_addr_map_info); | |
121 | else { | |
122 | pr_err("Unsupported SoC\n"); | |
123 | return -EINVAL; | |
124 | } | |
125 | ||
126 | /* | |
127 | * Setup MBUS dram target info. | |
128 | */ | |
129 | orion_setup_cpu_mbus_target(&addr_map_cfg, | |
130 | sdram_addr_decoding_base); | |
131 | return 0; | |
132 | } | |
133 | ||
134 | /* Using a early_initcall is needed so that this initialization gets | |
135 | * done before the SMP initialization, which requires the BootROM to | |
136 | * be remapped. */ | |
137 | early_initcall(armada_setup_cpu_mbus); |