Commit | Line | Data |
---|---|---|
c67de5b3 | 1 | /* |
9dd0b194 | 2 | * arch/arm/mach-orion5x/addr-map.c |
c67de5b3 | 3 | * |
9dd0b194 | 4 | * Address map functions for Marvell Orion 5x SoCs |
c67de5b3 TP |
5 | * |
6 | * Maintainer: Tzachi Perelstein <tzachi@marvell.com> | |
7 | * | |
159ffb3a LB |
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 | |
c67de5b3 TP |
10 | * warranty of any kind, whether express or implied. |
11 | */ | |
12 | ||
13 | #include <linux/kernel.h> | |
14 | #include <linux/init.h> | |
83b6d822 | 15 | #include <linux/mbus.h> |
fced80c7 | 16 | #include <linux/io.h> |
3a8f7441 | 17 | #include <linux/errno.h> |
a09e64fb | 18 | #include <mach/hardware.h> |
c67de5b3 TP |
19 | #include "common.h" |
20 | ||
21 | /* | |
25985edc | 22 | * The Orion has fully programmable address map. There's a separate address |
b46926bb | 23 | * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIe, USB, |
c67de5b3 TP |
24 | * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own |
25 | * address decode windows that allow it to access any of the Orion resources. | |
26 | * | |
27 | * CPU address decoding -- | |
28 | * Linux assumes that it is the boot loader that already setup the access to | |
29 | * DDR and internal registers. | |
b46926bb | 30 | * Setup access to PCI and PCIe IO/MEM space is issued by this file. |
c67de5b3 TP |
31 | * Setup access to various devices located on the device bus interface (e.g. |
32 | * flashes, RTC, etc) should be issued by machine-setup.c according to | |
9dd0b194 | 33 | * specific board population (by using orion5x_setup_*_win()). |
c67de5b3 TP |
34 | * |
35 | * Non-CPU Masters address decoding -- | |
36 | * Unlike the CPU, we setup the access from Orion's master interfaces to DDR | |
37 | * banks only (the typical use case). | |
da109897 | 38 | * Setup access for each master to DDR is issued by platform device setup. |
c67de5b3 TP |
39 | */ |
40 | ||
41 | /* | |
42 | * Generic Address Decode Windows bit settings | |
43 | */ | |
44 | #define TARGET_DDR 0 | |
159ffb3a | 45 | #define TARGET_DEV_BUS 1 |
c67de5b3 TP |
46 | #define TARGET_PCI 3 |
47 | #define TARGET_PCIE 4 | |
3a8f7441 | 48 | #define TARGET_SRAM 9 |
c67de5b3 TP |
49 | #define ATTR_PCIE_MEM 0x59 |
50 | #define ATTR_PCIE_IO 0x51 | |
98f79d1e | 51 | #define ATTR_PCIE_WA 0x79 |
c67de5b3 TP |
52 | #define ATTR_PCI_MEM 0x59 |
53 | #define ATTR_PCI_IO 0x51 | |
54 | #define ATTR_DEV_CS0 0x1e | |
55 | #define ATTR_DEV_CS1 0x1d | |
56 | #define ATTR_DEV_CS2 0x1b | |
57 | #define ATTR_DEV_BOOT 0xf | |
3a8f7441 | 58 | #define ATTR_SRAM 0x0 |
c67de5b3 TP |
59 | |
60 | /* | |
159ffb3a | 61 | * Helpers to get DDR bank info |
c67de5b3 | 62 | */ |
fdd8b079 | 63 | #define ORION5X_DDR_REG(x) (ORION5X_DDR_VIRT_BASE | (x)) |
da109897 LB |
64 | #define DDR_BASE_CS(n) ORION5X_DDR_REG(0x1500 + ((n) << 3)) |
65 | #define DDR_SIZE_CS(n) ORION5X_DDR_REG(0x1504 + ((n) << 3)) | |
c67de5b3 TP |
66 | |
67 | /* | |
68 | * CPU Address Decode Windows registers | |
69 | */ | |
fdd8b079 | 70 | #define ORION5X_BRIDGE_REG(x) (ORION5X_BRIDGE_VIRT_BASE | (x)) |
9dd0b194 LB |
71 | #define CPU_WIN_CTRL(n) ORION5X_BRIDGE_REG(0x000 | ((n) << 4)) |
72 | #define CPU_WIN_BASE(n) ORION5X_BRIDGE_REG(0x004 | ((n) << 4)) | |
73 | #define CPU_WIN_REMAP_LO(n) ORION5X_BRIDGE_REG(0x008 | ((n) << 4)) | |
74 | #define CPU_WIN_REMAP_HI(n) ORION5X_BRIDGE_REG(0x00c | ((n) << 4)) | |
c67de5b3 | 75 | |
83b6d822 | 76 | |
9dd0b194 | 77 | struct mbus_dram_target_info orion5x_mbus_dram_info; |
a18b6584 | 78 | static int __initdata win_alloc_count; |
83b6d822 | 79 | |
9dd0b194 | 80 | static int __init orion5x_cpu_win_can_remap(int win) |
c67de5b3 TP |
81 | { |
82 | u32 dev, rev; | |
83 | ||
9dd0b194 | 84 | orion5x_pcie_id(&dev, &rev); |
c9e3de94 HVR |
85 | if ((dev == MV88F5281_DEV_ID && win < 4) |
86 | || (dev == MV88F5182_DEV_ID && win < 2) | |
7153c360 LB |
87 | || (dev == MV88F5181_DEV_ID && win < 2) |
88 | || (dev == MV88F6183_DEV_ID && win < 4)) | |
c67de5b3 TP |
89 | return 1; |
90 | ||
91 | return 0; | |
92 | } | |
93 | ||
3a8f7441 | 94 | static int __init setup_cpu_win(int win, u32 base, u32 size, |
98f79d1e | 95 | u8 target, u8 attr, int remap) |
c67de5b3 | 96 | { |
a18b6584 LB |
97 | if (win >= 8) { |
98 | printk(KERN_ERR "setup_cpu_win: trying to allocate " | |
99 | "window %d\n", win); | |
3a8f7441 | 100 | return -ENOSPC; |
a18b6584 LB |
101 | } |
102 | ||
79e90dd5 LB |
103 | writel(base & 0xffff0000, CPU_WIN_BASE(win)); |
104 | writel(((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1, | |
105 | CPU_WIN_CTRL(win)); | |
c67de5b3 | 106 | |
9dd0b194 | 107 | if (orion5x_cpu_win_can_remap(win)) { |
98f79d1e LB |
108 | if (remap < 0) |
109 | remap = base; | |
110 | ||
79e90dd5 LB |
111 | writel(remap & 0xffff0000, CPU_WIN_REMAP_LO(win)); |
112 | writel(0, CPU_WIN_REMAP_HI(win)); | |
c67de5b3 | 113 | } |
3a8f7441 | 114 | return 0; |
c67de5b3 TP |
115 | } |
116 | ||
9dd0b194 | 117 | void __init orion5x_setup_cpu_mbus_bridge(void) |
c67de5b3 TP |
118 | { |
119 | int i; | |
83b6d822 | 120 | int cs; |
c67de5b3 TP |
121 | |
122 | /* | |
98f79d1e | 123 | * First, disable and clear windows. |
c67de5b3 | 124 | */ |
98f79d1e | 125 | for (i = 0; i < 8; i++) { |
79e90dd5 LB |
126 | writel(0, CPU_WIN_BASE(i)); |
127 | writel(0, CPU_WIN_CTRL(i)); | |
9dd0b194 | 128 | if (orion5x_cpu_win_can_remap(i)) { |
79e90dd5 LB |
129 | writel(0, CPU_WIN_REMAP_LO(i)); |
130 | writel(0, CPU_WIN_REMAP_HI(i)); | |
c67de5b3 TP |
131 | } |
132 | } | |
133 | ||
134 | /* | |
7f74c2c7 | 135 | * Setup windows for PCI+PCIe IO+MEM space. |
c67de5b3 | 136 | */ |
9dd0b194 LB |
137 | setup_cpu_win(0, ORION5X_PCIE_IO_PHYS_BASE, ORION5X_PCIE_IO_SIZE, |
138 | TARGET_PCIE, ATTR_PCIE_IO, ORION5X_PCIE_IO_BUS_BASE); | |
139 | setup_cpu_win(1, ORION5X_PCI_IO_PHYS_BASE, ORION5X_PCI_IO_SIZE, | |
140 | TARGET_PCI, ATTR_PCI_IO, ORION5X_PCI_IO_BUS_BASE); | |
141 | setup_cpu_win(2, ORION5X_PCIE_MEM_PHYS_BASE, ORION5X_PCIE_MEM_SIZE, | |
98f79d1e | 142 | TARGET_PCIE, ATTR_PCIE_MEM, -1); |
9dd0b194 | 143 | setup_cpu_win(3, ORION5X_PCI_MEM_PHYS_BASE, ORION5X_PCI_MEM_SIZE, |
98f79d1e | 144 | TARGET_PCI, ATTR_PCI_MEM, -1); |
a18b6584 | 145 | win_alloc_count = 4; |
83b6d822 LB |
146 | |
147 | /* | |
148 | * Setup MBUS dram target info. | |
149 | */ | |
9dd0b194 | 150 | orion5x_mbus_dram_info.mbus_dram_target_id = TARGET_DDR; |
83b6d822 LB |
151 | |
152 | for (i = 0, cs = 0; i < 4; i++) { | |
153 | u32 base = readl(DDR_BASE_CS(i)); | |
154 | u32 size = readl(DDR_SIZE_CS(i)); | |
155 | ||
156 | /* | |
157 | * Chip select enabled? | |
158 | */ | |
159 | if (size & 1) { | |
160 | struct mbus_dram_window *w; | |
161 | ||
9dd0b194 | 162 | w = &orion5x_mbus_dram_info.cs[cs++]; |
83b6d822 LB |
163 | w->cs_index = i; |
164 | w->mbus_attr = 0xf & ~(1 << i); | |
4fc338e3 LB |
165 | w->base = base & 0xffff0000; |
166 | w->size = (size | 0x0000ffff) + 1; | |
83b6d822 LB |
167 | } |
168 | } | |
9dd0b194 | 169 | orion5x_mbus_dram_info.num_cs = cs; |
c67de5b3 TP |
170 | } |
171 | ||
9dd0b194 | 172 | void __init orion5x_setup_dev_boot_win(u32 base, u32 size) |
98f79d1e | 173 | { |
a18b6584 LB |
174 | setup_cpu_win(win_alloc_count++, base, size, |
175 | TARGET_DEV_BUS, ATTR_DEV_BOOT, -1); | |
98f79d1e LB |
176 | } |
177 | ||
9dd0b194 | 178 | void __init orion5x_setup_dev0_win(u32 base, u32 size) |
98f79d1e | 179 | { |
a18b6584 LB |
180 | setup_cpu_win(win_alloc_count++, base, size, |
181 | TARGET_DEV_BUS, ATTR_DEV_CS0, -1); | |
98f79d1e LB |
182 | } |
183 | ||
9dd0b194 | 184 | void __init orion5x_setup_dev1_win(u32 base, u32 size) |
98f79d1e | 185 | { |
a18b6584 LB |
186 | setup_cpu_win(win_alloc_count++, base, size, |
187 | TARGET_DEV_BUS, ATTR_DEV_CS1, -1); | |
98f79d1e LB |
188 | } |
189 | ||
9dd0b194 | 190 | void __init orion5x_setup_dev2_win(u32 base, u32 size) |
98f79d1e | 191 | { |
a18b6584 LB |
192 | setup_cpu_win(win_alloc_count++, base, size, |
193 | TARGET_DEV_BUS, ATTR_DEV_CS2, -1); | |
98f79d1e LB |
194 | } |
195 | ||
9dd0b194 | 196 | void __init orion5x_setup_pcie_wa_win(u32 base, u32 size) |
98f79d1e | 197 | { |
a18b6584 LB |
198 | setup_cpu_win(win_alloc_count++, base, size, |
199 | TARGET_PCIE, ATTR_PCIE_WA, -1); | |
98f79d1e | 200 | } |
3a8f7441 SAS |
201 | |
202 | int __init orion5x_setup_sram_win(void) | |
203 | { | |
97f8a27a | 204 | return setup_cpu_win(win_alloc_count++, ORION5X_SRAM_PHYS_BASE, |
3a8f7441 SAS |
205 | ORION5X_SRAM_SIZE, TARGET_SRAM, ATTR_SRAM, -1); |
206 | } |