1 This commit adds two functions armada_370_xp_alloc_pcie_window() and
2 armada_370_xp_free_pcie_window() that respectively allocate and free
3 an address decoding window pointing to either a memory or I/O region
6 Those functions will be used by the PCIe driver to create and remove
7 those regions depending on the PCIe devices that are detected.
9 Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
11 arch/arm/mach-mvebu/addr-map.c | 156 ++++++++++++++++++++++++++++++++++++++--
12 arch/arm/mach-mvebu/common.h | 4 ++
13 2 files changed, 156 insertions(+), 4 deletions(-)
15 --- a/arch/arm/mach-mvebu/addr-map.c
16 +++ b/arch/arm/mach-mvebu/addr-map.c
18 #define ARMADA_XP_TARGET_DEV_BUS 1
19 #define ARMADA_XP_ATTR_DEV_BOOTROM 0x1D
20 #define ARMADA_XP_TARGET_ETH1 3
21 -#define ARMADA_XP_TARGET_PCIE_0_2 4
22 #define ARMADA_XP_TARGET_ETH0 7
23 -#define ARMADA_XP_TARGET_PCIE_1_3 8
25 #define ARMADA_370_TARGET_DEV_BUS 1
26 #define ARMADA_370_ATTR_DEV_BOOTROM 0x1D
27 -#define ARMADA_370_TARGET_PCIE_0 4
28 -#define ARMADA_370_TARGET_PCIE_1 8
30 #define ARMADA_WINDOW_8_PLUS_OFFSET 0x90
31 #define ARMADA_SDRAM_ADDR_DECODING_OFFSET 0x180
32 @@ -89,6 +85,158 @@ static struct __initdata orion_addr_map_
33 .win_cfg_base = armada_cfg_base,
38 + * PCIe windows allocation code.
40 +#define ARMADA_370_XP_PCIE_MEM_START 0xC0000000
41 +#define ARMADA_370_XP_PCIE_MEM_END (ARMADA_370_XP_PCIE_MEM_START + SZ_256M)
42 +#define ARMADA_370_XP_PCIE_IO_START 0xF2000000
43 +#define ARMADA_370_XP_PCIE_IO_END (ARMADA_370_XP_PCIE_IO_START + SZ_1M)
45 +static unsigned long armada_370_xp_pcie_memaddr = ARMADA_370_XP_PCIE_MEM_START;
46 +static unsigned long armada_370_xp_pcie_ioaddr = ARMADA_370_XP_PCIE_IO_START;
49 + * This structure and the following arrays allow to map a PCIe (port,
50 + * lane) tuple to the corresponding (target, attribute) tuple needed
51 + * to configure an address decoding window for the given PCIe (port,
54 +struct pcie_mapping {
61 +struct pcie_mapping armada_xp_pcie_mappings[] = {
62 + { .port = 0, .lane = 0, .target = 4, .attr = 0xE0 },
63 + { .port = 0, .lane = 1, .target = 4, .attr = 0xD0 },
64 + { .port = 0, .lane = 2, .target = 4, .attr = 0xB0 },
65 + { .port = 0, .lane = 3, .target = 4, .attr = 0x70 },
66 + { .port = 1, .lane = 0, .target = 8, .attr = 0xE0 },
67 + { .port = 1, .lane = 1, .target = 8, .attr = 0xD0 },
68 + { .port = 1, .lane = 2, .target = 8, .attr = 0xB0 },
69 + { .port = 1, .lane = 3, .target = 8, .attr = 0x70 },
70 + { .port = 2, .lane = 0, .target = 4, .attr = 0xF0 },
71 + { .port = 3, .lane = 0, .target = 8, .attr = 0xF0 },
75 +struct pcie_mapping armada_370_pcie_mappings[] = {
76 + { .port = 0, .lane = 0, .target = 4, .attr = 0xE0 },
77 + { .port = 1, .lane = 0, .target = 8, .attr = 0xE0 },
82 + * This function finds an available physical address range between
83 + * ARMADA_370_XP_PCIE_MEM_START and ARMADA_370_XP_PCIE_MEM_END (for
84 + * PCIe memory regions) or between ARMADA_370_XP_PCIE_IO_START and
85 + * ARMADA_370_XP_PCIE_IO_END (for PCIe I/O regions) and creates an
86 + * address decoding window from this allocated address pointing to the
87 + * right PCIe device.
89 + * An error code is returned, the allocated base address is returned
90 + * through the 'outbase' argument.
92 +int __init armada_370_xp_alloc_pcie_window(int pcie_port, int pcie_lane,
94 + unsigned long *outbase)
96 + struct pcie_mapping *mapping, *mappings;
101 + if (of_machine_is_compatible("marvell,armadaxp"))
102 + mappings = armada_xp_pcie_mappings;
103 + else if (of_machine_is_compatible("marvell,armada370"))
104 + mappings = armada_370_pcie_mappings;
108 + for (mapping = mappings; mapping->port != -1; mapping++)
109 + if (mapping->port == pcie_port && mapping->lane == pcie_lane)
112 + if (mapping->port == -1)
115 + target = mapping->target;
116 + attr = mapping->attr;
118 + if (type == IORESOURCE_MEM) {
120 + * Bit 3 of the attributes indicates that it is a
121 + * memory region, as opposed to an I/O region
125 + if (armada_370_xp_pcie_memaddr + size >
126 + ARMADA_370_XP_PCIE_MEM_END)
129 + base = armada_370_xp_pcie_memaddr;
130 + armada_370_xp_pcie_memaddr += size;
132 + ret = orion_alloc_cpu_win(&addr_map_cfg, base, size, target,
135 + armada_370_xp_pcie_memaddr -= size;
138 + } else if (type == IORESOURCE_IO) {
139 + if (armada_370_xp_pcie_ioaddr + size >
140 + ARMADA_370_XP_PCIE_IO_END)
143 + base = armada_370_xp_pcie_ioaddr;
144 + armada_370_xp_pcie_ioaddr += size;
146 + ret = orion_alloc_cpu_win(&addr_map_cfg, base, size, target,
149 + armada_370_xp_pcie_ioaddr -= size;
160 + * Frees an address decoding window previously allocated by
161 + * armada_370_xp_alloc_pcie_window(). Note that only the last window
162 + * allocated for a given type (MEM or IO) can be freed, due to the
163 + * simplicity of the allocator. This is however sufficient to handle
164 + * the error cases when initializing one PCIe device.
166 +int __init armada_370_xp_free_pcie_window(int type, unsigned long base,
169 + if (type == IORESOURCE_MEM) {
170 + /* We can only free the last allocated window */
171 + if (base + size != armada_370_xp_pcie_memaddr)
173 + orion_free_cpu_win(&addr_map_cfg, base);
174 + armada_370_xp_pcie_memaddr -= size;
175 + } else if (type == IORESOURCE_IO) {
176 + /* We can only free the last allocated window */
177 + if (base + size != armada_370_xp_pcie_ioaddr)
179 + orion_free_cpu_win(&addr_map_cfg, base);
180 + armada_370_xp_pcie_ioaddr -= size;
188 static int __init armada_setup_cpu_mbus(void)
190 struct device_node *np;
191 --- a/arch/arm/mach-mvebu/common.h
192 +++ b/arch/arm/mach-mvebu/common.h
193 @@ -25,4 +25,8 @@ int armada_370_xp_coherency_init(void);
194 int armada_370_xp_pmsu_init(void);
195 void armada_xp_secondary_startup(void);
196 extern struct smp_operations armada_xp_smp_ops;
198 +int armada_370_xp_alloc_pcie_window(int pcie_port, int pcie_lane,
199 + int type, u32 size, unsigned long *outbase);
200 +int armada_370_xp_free_pcie_window(int type, unsigned long base, u32 size);