1/* 2 * Marvell hostbridge routines 3 * 4 * Author: Mark A. Greer <source@mvista.com> 5 * 6 * 2004, 2005, 2007 (c) MontaVista Software, Inc. This file is licensed under 7 * the terms of the GNU General Public License version 2. This program 8 * is licensed "as is" without any warranty of any kind, whether express 9 * or implied. 10 */ 11 12#include <stdarg.h> 13#include <stddef.h> 14#include "types.h" 15#include "elf.h" 16#include "page.h" 17#include "string.h" 18#include "stdio.h" 19#include "io.h" 20#include "ops.h" 21#include "mv64x60.h" 22 23#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) 24 25#define MV64x60_CPU2MEM_WINDOWS 4 26#define MV64x60_CPU2MEM_0_BASE 0x0008 27#define MV64x60_CPU2MEM_0_SIZE 0x0010 28#define MV64x60_CPU2MEM_1_BASE 0x0208 29#define MV64x60_CPU2MEM_1_SIZE 0x0210 30#define MV64x60_CPU2MEM_2_BASE 0x0018 31#define MV64x60_CPU2MEM_2_SIZE 0x0020 32#define MV64x60_CPU2MEM_3_BASE 0x0218 33#define MV64x60_CPU2MEM_3_SIZE 0x0220 34 35#define MV64x60_ENET2MEM_BAR_ENABLE 0x2290 36#define MV64x60_ENET2MEM_0_BASE 0x2200 37#define MV64x60_ENET2MEM_0_SIZE 0x2204 38#define MV64x60_ENET2MEM_1_BASE 0x2208 39#define MV64x60_ENET2MEM_1_SIZE 0x220c 40#define MV64x60_ENET2MEM_2_BASE 0x2210 41#define MV64x60_ENET2MEM_2_SIZE 0x2214 42#define MV64x60_ENET2MEM_3_BASE 0x2218 43#define MV64x60_ENET2MEM_3_SIZE 0x221c 44#define MV64x60_ENET2MEM_4_BASE 0x2220 45#define MV64x60_ENET2MEM_4_SIZE 0x2224 46#define MV64x60_ENET2MEM_5_BASE 0x2228 47#define MV64x60_ENET2MEM_5_SIZE 0x222c 48#define MV64x60_ENET2MEM_ACC_PROT_0 0x2294 49#define MV64x60_ENET2MEM_ACC_PROT_1 0x2298 50#define MV64x60_ENET2MEM_ACC_PROT_2 0x229c 51 52#define MV64x60_MPSC2MEM_BAR_ENABLE 0xf250 53#define MV64x60_MPSC2MEM_0_BASE 0xf200 54#define MV64x60_MPSC2MEM_0_SIZE 0xf204 55#define MV64x60_MPSC2MEM_1_BASE 0xf208 56#define MV64x60_MPSC2MEM_1_SIZE 0xf20c 57#define MV64x60_MPSC2MEM_2_BASE 0xf210 58#define MV64x60_MPSC2MEM_2_SIZE 0xf214 59#define MV64x60_MPSC2MEM_3_BASE 0xf218 60#define MV64x60_MPSC2MEM_3_SIZE 0xf21c 61#define MV64x60_MPSC_0_REMAP 0xf240 62#define MV64x60_MPSC_1_REMAP 0xf244 63#define MV64x60_MPSC2MEM_ACC_PROT_0 0xf254 64#define MV64x60_MPSC2MEM_ACC_PROT_1 0xf258 65#define MV64x60_MPSC2REGS_BASE 0xf25c 66 67#define MV64x60_IDMA2MEM_BAR_ENABLE 0x0a80 68#define MV64x60_IDMA2MEM_0_BASE 0x0a00 69#define MV64x60_IDMA2MEM_0_SIZE 0x0a04 70#define MV64x60_IDMA2MEM_1_BASE 0x0a08 71#define MV64x60_IDMA2MEM_1_SIZE 0x0a0c 72#define MV64x60_IDMA2MEM_2_BASE 0x0a10 73#define MV64x60_IDMA2MEM_2_SIZE 0x0a14 74#define MV64x60_IDMA2MEM_3_BASE 0x0a18 75#define MV64x60_IDMA2MEM_3_SIZE 0x0a1c 76#define MV64x60_IDMA2MEM_4_BASE 0x0a20 77#define MV64x60_IDMA2MEM_4_SIZE 0x0a24 78#define MV64x60_IDMA2MEM_5_BASE 0x0a28 79#define MV64x60_IDMA2MEM_5_SIZE 0x0a2c 80#define MV64x60_IDMA2MEM_6_BASE 0x0a30 81#define MV64x60_IDMA2MEM_6_SIZE 0x0a34 82#define MV64x60_IDMA2MEM_7_BASE 0x0a38 83#define MV64x60_IDMA2MEM_7_SIZE 0x0a3c 84#define MV64x60_IDMA2MEM_ACC_PROT_0 0x0a70 85#define MV64x60_IDMA2MEM_ACC_PROT_1 0x0a74 86#define MV64x60_IDMA2MEM_ACC_PROT_2 0x0a78 87#define MV64x60_IDMA2MEM_ACC_PROT_3 0x0a7c 88 89#define MV64x60_PCI_ACC_CNTL_WINDOWS 6 90#define MV64x60_PCI0_PCI_DECODE_CNTL 0x0d3c 91#define MV64x60_PCI1_PCI_DECODE_CNTL 0x0dbc 92 93#define MV64x60_PCI0_BAR_ENABLE 0x0c3c 94#define MV64x60_PCI02MEM_0_SIZE 0x0c08 95#define MV64x60_PCI0_ACC_CNTL_0_BASE_LO 0x1e00 96#define MV64x60_PCI0_ACC_CNTL_0_BASE_HI 0x1e04 97#define MV64x60_PCI0_ACC_CNTL_0_SIZE 0x1e08 98#define MV64x60_PCI0_ACC_CNTL_1_BASE_LO 0x1e10 99#define MV64x60_PCI0_ACC_CNTL_1_BASE_HI 0x1e14 100#define MV64x60_PCI0_ACC_CNTL_1_SIZE 0x1e18 101#define MV64x60_PCI0_ACC_CNTL_2_BASE_LO 0x1e20 102#define MV64x60_PCI0_ACC_CNTL_2_BASE_HI 0x1e24 103#define MV64x60_PCI0_ACC_CNTL_2_SIZE 0x1e28 104#define MV64x60_PCI0_ACC_CNTL_3_BASE_LO 0x1e30 105#define MV64x60_PCI0_ACC_CNTL_3_BASE_HI 0x1e34 106#define MV64x60_PCI0_ACC_CNTL_3_SIZE 0x1e38 107#define MV64x60_PCI0_ACC_CNTL_4_BASE_LO 0x1e40 108#define MV64x60_PCI0_ACC_CNTL_4_BASE_HI 0x1e44 109#define MV64x60_PCI0_ACC_CNTL_4_SIZE 0x1e48 110#define MV64x60_PCI0_ACC_CNTL_5_BASE_LO 0x1e50 111#define MV64x60_PCI0_ACC_CNTL_5_BASE_HI 0x1e54 112#define MV64x60_PCI0_ACC_CNTL_5_SIZE 0x1e58 113 114#define MV64x60_PCI1_BAR_ENABLE 0x0cbc 115#define MV64x60_PCI12MEM_0_SIZE 0x0c88 116#define MV64x60_PCI1_ACC_CNTL_0_BASE_LO 0x1e80 117#define MV64x60_PCI1_ACC_CNTL_0_BASE_HI 0x1e84 118#define MV64x60_PCI1_ACC_CNTL_0_SIZE 0x1e88 119#define MV64x60_PCI1_ACC_CNTL_1_BASE_LO 0x1e90 120#define MV64x60_PCI1_ACC_CNTL_1_BASE_HI 0x1e94 121#define MV64x60_PCI1_ACC_CNTL_1_SIZE 0x1e98 122#define MV64x60_PCI1_ACC_CNTL_2_BASE_LO 0x1ea0 123#define MV64x60_PCI1_ACC_CNTL_2_BASE_HI 0x1ea4 124#define MV64x60_PCI1_ACC_CNTL_2_SIZE 0x1ea8 125#define MV64x60_PCI1_ACC_CNTL_3_BASE_LO 0x1eb0 126#define MV64x60_PCI1_ACC_CNTL_3_BASE_HI 0x1eb4 127#define MV64x60_PCI1_ACC_CNTL_3_SIZE 0x1eb8 128#define MV64x60_PCI1_ACC_CNTL_4_BASE_LO 0x1ec0 129#define MV64x60_PCI1_ACC_CNTL_4_BASE_HI 0x1ec4 130#define MV64x60_PCI1_ACC_CNTL_4_SIZE 0x1ec8 131#define MV64x60_PCI1_ACC_CNTL_5_BASE_LO 0x1ed0 132#define MV64x60_PCI1_ACC_CNTL_5_BASE_HI 0x1ed4 133#define MV64x60_PCI1_ACC_CNTL_5_SIZE 0x1ed8 134 135#define MV64x60_CPU2PCI_SWAP_NONE 0x01000000 136 137#define MV64x60_CPU2PCI0_IO_BASE 0x0048 138#define MV64x60_CPU2PCI0_IO_SIZE 0x0050 139#define MV64x60_CPU2PCI0_IO_REMAP 0x00f0 140#define MV64x60_CPU2PCI0_MEM_0_BASE 0x0058 141#define MV64x60_CPU2PCI0_MEM_0_SIZE 0x0060 142#define MV64x60_CPU2PCI0_MEM_0_REMAP_LO 0x00f8 143#define MV64x60_CPU2PCI0_MEM_0_REMAP_HI 0x0320 144 145#define MV64x60_CPU2PCI1_IO_BASE 0x0090 146#define MV64x60_CPU2PCI1_IO_SIZE 0x0098 147#define MV64x60_CPU2PCI1_IO_REMAP 0x0108 148#define MV64x60_CPU2PCI1_MEM_0_BASE 0x00a0 149#define MV64x60_CPU2PCI1_MEM_0_SIZE 0x00a8 150#define MV64x60_CPU2PCI1_MEM_0_REMAP_LO 0x0110 151#define MV64x60_CPU2PCI1_MEM_0_REMAP_HI 0x0340 152 153struct mv64x60_mem_win { 154 u32 hi; 155 u32 lo; 156 u32 size; 157}; 158 159struct mv64x60_pci_win { 160 u32 fcn; 161 u32 hi; 162 u32 lo; 163 u32 size; 164}; 165 166/* PCI config access routines */ 167struct { 168 u32 addr; 169 u32 data; 170} static mv64x60_pci_cfgio[2] = { 171 { /* hose 0 */ 172 .addr = 0xcf8, 173 .data = 0xcfc, 174 }, 175 { /* hose 1 */ 176 .addr = 0xc78, 177 .data = 0xc7c, 178 } 179}; 180 181u32 mv64x60_cfg_read(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, u8 offset) 182{ 183 out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].addr), 184 (1 << 31) | (bus << 16) | (devfn << 8) | offset); 185 return in_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].data)); 186} 187 188void mv64x60_cfg_write(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, u8 offset, 189 u32 val) 190{ 191 out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].addr), 192 (1 << 31) | (bus << 16) | (devfn << 8) | offset); 193 out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].data), val); 194} 195 196/* I/O ctlr -> system memory setup */ 197static struct mv64x60_mem_win mv64x60_cpu2mem[MV64x60_CPU2MEM_WINDOWS] = { 198 { 199 .lo = MV64x60_CPU2MEM_0_BASE, 200 .size = MV64x60_CPU2MEM_0_SIZE, 201 }, 202 { 203 .lo = MV64x60_CPU2MEM_1_BASE, 204 .size = MV64x60_CPU2MEM_1_SIZE, 205 }, 206 { 207 .lo = MV64x60_CPU2MEM_2_BASE, 208 .size = MV64x60_CPU2MEM_2_SIZE, 209 }, 210 { 211 .lo = MV64x60_CPU2MEM_3_BASE, 212 .size = MV64x60_CPU2MEM_3_SIZE, 213 }, 214}; 215 216static struct mv64x60_mem_win mv64x60_enet2mem[MV64x60_CPU2MEM_WINDOWS] = { 217 { 218 .lo = MV64x60_ENET2MEM_0_BASE, 219 .size = MV64x60_ENET2MEM_0_SIZE, 220 }, 221 { 222 .lo = MV64x60_ENET2MEM_1_BASE, 223 .size = MV64x60_ENET2MEM_1_SIZE, 224 }, 225 { 226 .lo = MV64x60_ENET2MEM_2_BASE, 227 .size = MV64x60_ENET2MEM_2_SIZE, 228 }, 229 { 230 .lo = MV64x60_ENET2MEM_3_BASE, 231 .size = MV64x60_ENET2MEM_3_SIZE, 232 }, 233}; 234 235static struct mv64x60_mem_win mv64x60_mpsc2mem[MV64x60_CPU2MEM_WINDOWS] = { 236 { 237 .lo = MV64x60_MPSC2MEM_0_BASE, 238 .size = MV64x60_MPSC2MEM_0_SIZE, 239 }, 240 { 241 .lo = MV64x60_MPSC2MEM_1_BASE, 242 .size = MV64x60_MPSC2MEM_1_SIZE, 243 }, 244 { 245 .lo = MV64x60_MPSC2MEM_2_BASE, 246 .size = MV64x60_MPSC2MEM_2_SIZE, 247 }, 248 { 249 .lo = MV64x60_MPSC2MEM_3_BASE, 250 .size = MV64x60_MPSC2MEM_3_SIZE, 251 }, 252}; 253 254static struct mv64x60_mem_win mv64x60_idma2mem[MV64x60_CPU2MEM_WINDOWS] = { 255 { 256 .lo = MV64x60_IDMA2MEM_0_BASE, 257 .size = MV64x60_IDMA2MEM_0_SIZE, 258 }, 259 { 260 .lo = MV64x60_IDMA2MEM_1_BASE, 261 .size = MV64x60_IDMA2MEM_1_SIZE, 262 }, 263 { 264 .lo = MV64x60_IDMA2MEM_2_BASE, 265 .size = MV64x60_IDMA2MEM_2_SIZE, 266 }, 267 { 268 .lo = MV64x60_IDMA2MEM_3_BASE, 269 .size = MV64x60_IDMA2MEM_3_SIZE, 270 }, 271}; 272 273static u32 mv64x60_dram_selects[MV64x60_CPU2MEM_WINDOWS] = {0xe,0xd,0xb,0x7}; 274 275/* 276 * ENET, MPSC, and IDMA ctlrs on the MV64x60 have separate windows that 277 * must be set up so that the respective ctlr can access system memory. 278 * Configure them to be same as cpu->memory windows. 279 */ 280void mv64x60_config_ctlr_windows(u8 *bridge_base, u8 *bridge_pbase, 281 u8 is_coherent) 282{ 283 u32 i, base, size, enables, prot = 0, snoop_bits = 0; 284 285 /* Disable ctlr->mem windows */ 286 out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), 0x3f); 287 out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_BAR_ENABLE), 0xf); 288 out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), 0xff); 289 290 if (is_coherent) 291 snoop_bits = 0x2 << 12; /* Writeback */ 292 293 enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)) & 0xf; 294 295 for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) { 296 if (enables & (1 << i)) /* Set means disabled */ 297 continue; 298 299 base = in_le32((u32 *)(bridge_base + mv64x60_cpu2mem[i].lo)) 300 << 16; 301 base |= snoop_bits | (mv64x60_dram_selects[i] << 8); 302 size = in_le32((u32 *)(bridge_base + mv64x60_cpu2mem[i].size)) 303 << 16; 304 prot |= (0x3 << (i << 1)); /* RW access */ 305 306 out_le32((u32 *)(bridge_base + mv64x60_enet2mem[i].lo), base); 307 out_le32((u32 *)(bridge_base + mv64x60_enet2mem[i].size), size); 308 out_le32((u32 *)(bridge_base + mv64x60_mpsc2mem[i].lo), base); 309 out_le32((u32 *)(bridge_base + mv64x60_mpsc2mem[i].size), size); 310 out_le32((u32 *)(bridge_base + mv64x60_idma2mem[i].lo), base); 311 out_le32((u32 *)(bridge_base + mv64x60_idma2mem[i].size), size); 312 } 313 314 out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_0), prot); 315 out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_1), prot); 316 out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_2), prot); 317 out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_ACC_PROT_0), prot); 318 out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_ACC_PROT_1), prot); 319 out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_0), prot); 320 out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_1), prot); 321 out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_2), prot); 322 out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_3), prot); 323 324 /* Set mpsc->bridge's reg window to the bridge's internal registers. */ 325 out_le32((u32 *)(bridge_base + MV64x60_MPSC2REGS_BASE), 326 (u32)bridge_pbase); 327 328 out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), enables); 329 out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_BAR_ENABLE), enables); 330 out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_BAR_ENABLE), enables); 331} 332 333/* PCI MEM -> system memory, et. al. setup */ 334static struct mv64x60_pci_win mv64x60_pci2mem[2] = { 335 { /* hose 0 */ 336 .fcn = 0, 337 .hi = 0x14, 338 .lo = 0x10, 339 .size = MV64x60_PCI02MEM_0_SIZE, 340 }, 341 { /* hose 1 */ 342 .fcn = 0, 343 .hi = 0x94, 344 .lo = 0x90, 345 .size = MV64x60_PCI12MEM_0_SIZE, 346 }, 347}; 348 349static struct 350mv64x60_mem_win mv64x60_pci_acc[2][MV64x60_PCI_ACC_CNTL_WINDOWS] = { 351 { /* hose 0 */ 352 { 353 .hi = MV64x60_PCI0_ACC_CNTL_0_BASE_HI, 354 .lo = MV64x60_PCI0_ACC_CNTL_0_BASE_LO, 355 .size = MV64x60_PCI0_ACC_CNTL_0_SIZE, 356 }, 357 { 358 .hi = MV64x60_PCI0_ACC_CNTL_1_BASE_HI, 359 .lo = MV64x60_PCI0_ACC_CNTL_1_BASE_LO, 360 .size = MV64x60_PCI0_ACC_CNTL_1_SIZE, 361 }, 362 { 363 .hi = MV64x60_PCI0_ACC_CNTL_2_BASE_HI, 364 .lo = MV64x60_PCI0_ACC_CNTL_2_BASE_LO, 365 .size = MV64x60_PCI0_ACC_CNTL_2_SIZE, 366 }, 367 { 368 .hi = MV64x60_PCI0_ACC_CNTL_3_BASE_HI, 369 .lo = MV64x60_PCI0_ACC_CNTL_3_BASE_LO, 370 .size = MV64x60_PCI0_ACC_CNTL_3_SIZE, 371 }, 372 }, 373 { /* hose 1 */ 374 { 375 .hi = MV64x60_PCI1_ACC_CNTL_0_BASE_HI, 376 .lo = MV64x60_PCI1_ACC_CNTL_0_BASE_LO, 377 .size = MV64x60_PCI1_ACC_CNTL_0_SIZE, 378 }, 379 { 380 .hi = MV64x60_PCI1_ACC_CNTL_1_BASE_HI, 381 .lo = MV64x60_PCI1_ACC_CNTL_1_BASE_LO, 382 .size = MV64x60_PCI1_ACC_CNTL_1_SIZE, 383 }, 384 { 385 .hi = MV64x60_PCI1_ACC_CNTL_2_BASE_HI, 386 .lo = MV64x60_PCI1_ACC_CNTL_2_BASE_LO, 387 .size = MV64x60_PCI1_ACC_CNTL_2_SIZE, 388 }, 389 { 390 .hi = MV64x60_PCI1_ACC_CNTL_3_BASE_HI, 391 .lo = MV64x60_PCI1_ACC_CNTL_3_BASE_LO, 392 .size = MV64x60_PCI1_ACC_CNTL_3_SIZE, 393 }, 394 }, 395}; 396 397static struct mv64x60_mem_win mv64x60_pci2reg[2] = { 398 { 399 .hi = 0x24, 400 .lo = 0x20, 401 .size = 0, 402 }, 403 { 404 .hi = 0xa4, 405 .lo = 0xa0, 406 .size = 0, 407 }, 408}; 409 410/* Only need to use 1 window (per hose) to get access to all of system memory */ 411void mv64x60_config_pci_windows(u8 *bridge_base, u8 *bridge_pbase, u8 hose, 412 u8 bus, u32 mem_size, u32 acc_bits) 413{ 414 u32 i, offset, bar_enable, enables; 415 416 /* Disable all windows but PCI MEM -> Bridge's regs window */ 417 enables = ~(1 << 9); 418 bar_enable = hose ? MV64x60_PCI1_BAR_ENABLE : MV64x60_PCI0_BAR_ENABLE; 419 out_le32((u32 *)(bridge_base + bar_enable), enables); 420 421 for (i=0; i<MV64x60_PCI_ACC_CNTL_WINDOWS; i++) 422 out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][i].lo), 0); 423 424 /* If mem_size is 0, leave windows disabled */ 425 if (mem_size == 0) 426 return; 427 428 /* Cause automatic updates of PCI remap regs */ 429 offset = hose ? 430 MV64x60_PCI1_PCI_DECODE_CNTL : MV64x60_PCI0_PCI_DECODE_CNTL; 431 i = in_le32((u32 *)(bridge_base + offset)); 432 out_le32((u32 *)(bridge_base + offset), i & ~0x1); 433 434 mem_size = (mem_size - 1) & 0xfffff000; 435 436 /* Map PCI MEM addr 0 -> System Mem addr 0 */ 437 mv64x60_cfg_write(bridge_base, hose, bus, 438 PCI_DEVFN(0, mv64x60_pci2mem[hose].fcn), 439 mv64x60_pci2mem[hose].hi, 0); 440 mv64x60_cfg_write(bridge_base, hose, bus, 441 PCI_DEVFN(0, mv64x60_pci2mem[hose].fcn), 442 mv64x60_pci2mem[hose].lo, 0); 443 out_le32((u32 *)(bridge_base + mv64x60_pci2mem[hose].size),mem_size); 444 445 acc_bits |= MV64x60_PCI_ACC_CNTL_ENABLE; 446 out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].hi), 0); 447 out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].lo), acc_bits); 448 out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].size),mem_size); 449 450 /* Set PCI MEM->bridge's reg window to where they are in CPU mem map */ 451 i = (u32)bridge_base; 452 i &= 0xffff0000; 453 i |= (0x2 << 1); 454 mv64x60_cfg_write(bridge_base, hose, bus, PCI_DEVFN(0,0), 455 mv64x60_pci2reg[hose].hi, 0); 456 mv64x60_cfg_write(bridge_base, hose, bus, PCI_DEVFN(0,0), 457 mv64x60_pci2reg[hose].lo, i); 458 459 enables &= ~0x1; /* Enable PCI MEM -> System Mem window 0 */ 460 out_le32((u32 *)(bridge_base + bar_enable), enables); 461} 462 463/* CPU -> PCI I/O & MEM setup */ 464struct mv64x60_cpu2pci_win mv64x60_cpu2pci_io[2] = { 465 { /* hose 0 */ 466 .lo = MV64x60_CPU2PCI0_IO_BASE, 467 .size = MV64x60_CPU2PCI0_IO_SIZE, 468 .remap_hi = 0, 469 .remap_lo = MV64x60_CPU2PCI0_IO_REMAP, 470 }, 471 { /* hose 1 */ 472 .lo = MV64x60_CPU2PCI1_IO_BASE, 473 .size = MV64x60_CPU2PCI1_IO_SIZE, 474 .remap_hi = 0, 475 .remap_lo = MV64x60_CPU2PCI1_IO_REMAP, 476 }, 477}; 478 479struct mv64x60_cpu2pci_win mv64x60_cpu2pci_mem[2] = { 480 { /* hose 0 */ 481 .lo = MV64x60_CPU2PCI0_MEM_0_BASE, 482 .size = MV64x60_CPU2PCI0_MEM_0_SIZE, 483 .remap_hi = MV64x60_CPU2PCI0_MEM_0_REMAP_HI, 484 .remap_lo = MV64x60_CPU2PCI0_MEM_0_REMAP_LO, 485 }, 486 { /* hose 1 */ 487 .lo = MV64x60_CPU2PCI1_MEM_0_BASE, 488 .size = MV64x60_CPU2PCI1_MEM_0_SIZE, 489 .remap_hi = MV64x60_CPU2PCI1_MEM_0_REMAP_HI, 490 .remap_lo = MV64x60_CPU2PCI1_MEM_0_REMAP_LO, 491 }, 492}; 493 494/* Only need to set up 1 window to pci mem space */ 495void mv64x60_config_cpu2pci_window(u8 *bridge_base, u8 hose, u32 pci_base_hi, 496 u32 pci_base_lo, u32 cpu_base, u32 size, 497 struct mv64x60_cpu2pci_win *offset_tbl) 498{ 499 cpu_base >>= 16; 500 cpu_base |= MV64x60_CPU2PCI_SWAP_NONE; 501 out_le32((u32 *)(bridge_base + offset_tbl[hose].lo), cpu_base); 502 503 if (offset_tbl[hose].remap_hi != 0) 504 out_le32((u32 *)(bridge_base + offset_tbl[hose].remap_hi), 505 pci_base_hi); 506 out_le32((u32 *)(bridge_base + offset_tbl[hose].remap_lo), 507 pci_base_lo >> 16); 508 509 size = (size - 1) >> 16; 510 out_le32((u32 *)(bridge_base + offset_tbl[hose].size), size); 511} 512 513/* Read mem ctlr to get the amount of mem in system */ 514u32 mv64x60_get_mem_size(u8 *bridge_base) 515{ 516 u32 enables, i, v; 517 u32 mem = 0; 518 519 enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)) & 0xf; 520 521 for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) 522 if (!(enables & (1<<i))) { 523 v = in_le32((u32*)(bridge_base 524 + mv64x60_cpu2mem[i].size)); 525 v = ((v & 0xffff) + 1) << 16; 526 mem += v; 527 } 528 529 return mem; 530} 531 532/* Get physical address of bridge's registers */ 533u8 *mv64x60_get_bridge_pbase(void) 534{ 535 u32 v[2]; 536 void *devp; 537 538 devp = finddevice("/mv64x60"); 539 if (devp == NULL) 540 goto err_out; 541 if (getprop(devp, "reg", v, sizeof(v)) != sizeof(v)) 542 goto err_out; 543 544 return (u8 *)v[0]; 545 546err_out: 547 return 0; 548} 549 550/* Get virtual address of bridge's registers */ 551u8 *mv64x60_get_bridge_base(void) 552{ 553 u32 v; 554 void *devp; 555 556 devp = finddevice("/mv64x60"); 557 if (devp == NULL) 558 goto err_out; 559 if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v)) 560 goto err_out; 561 562 return (u8 *)v; 563 564err_out: 565 return 0; 566} 567 568u8 mv64x60_is_coherent(void) 569{ 570 u32 v; 571 void *devp; 572 573 devp = finddevice("/"); 574 if (devp == NULL) 575 return 1; /* Assume coherency on */ 576 577 if (getprop(devp, "coherency-off", &v, sizeof(v)) < 0) 578 return 1; /* Coherency on */ 579 else 580 return 0; 581} 582