1*d0787656SStefan Roese /* 2*d0787656SStefan Roese * Address map functions for Marvell EBU SoCs (Kirkwood, Armada 3*d0787656SStefan Roese * 370/XP, Dove, Orion5x and MV78xx0) 4*d0787656SStefan Roese * 5*d0787656SStefan Roese * Ported from the Barebox version to U-Boot by: 6*d0787656SStefan Roese * Stefan Roese <sr@denx.de> 7*d0787656SStefan Roese * 8*d0787656SStefan Roese * The Barebox version is: 9*d0787656SStefan Roese * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> 10*d0787656SStefan Roese * 11*d0787656SStefan Roese * based on mbus driver from Linux 12*d0787656SStefan Roese * (C) Copyright 2008 Marvell Semiconductor 13*d0787656SStefan Roese * 14*d0787656SStefan Roese * SPDX-License-Identifier: GPL-2.0 15*d0787656SStefan Roese * 16*d0787656SStefan Roese * The Marvell EBU SoCs have a configurable physical address space: 17*d0787656SStefan Roese * the physical address at which certain devices (PCIe, NOR, NAND, 18*d0787656SStefan Roese * etc.) sit can be configured. The configuration takes place through 19*d0787656SStefan Roese * two sets of registers: 20*d0787656SStefan Roese * 21*d0787656SStefan Roese * - One to configure the access of the CPU to the devices. Depending 22*d0787656SStefan Roese * on the families, there are between 8 and 20 configurable windows, 23*d0787656SStefan Roese * each can be use to create a physical memory window that maps to a 24*d0787656SStefan Roese * specific device. Devices are identified by a tuple (target, 25*d0787656SStefan Roese * attribute). 26*d0787656SStefan Roese * 27*d0787656SStefan Roese * - One to configure the access to the CPU to the SDRAM. There are 28*d0787656SStefan Roese * either 2 (for Dove) or 4 (for other families) windows to map the 29*d0787656SStefan Roese * SDRAM into the physical address space. 30*d0787656SStefan Roese * 31*d0787656SStefan Roese * This driver: 32*d0787656SStefan Roese * 33*d0787656SStefan Roese * - Reads out the SDRAM address decoding windows at initialization 34*d0787656SStefan Roese * time, and fills the mbus_dram_info structure with these 35*d0787656SStefan Roese * informations. The exported function mv_mbus_dram_info() allow 36*d0787656SStefan Roese * device drivers to get those informations related to the SDRAM 37*d0787656SStefan Roese * address decoding windows. This is because devices also have their 38*d0787656SStefan Roese * own windows (configured through registers that are part of each 39*d0787656SStefan Roese * device register space), and therefore the drivers for Marvell 40*d0787656SStefan Roese * devices have to configure those device -> SDRAM windows to ensure 41*d0787656SStefan Roese * that DMA works properly. 42*d0787656SStefan Roese * 43*d0787656SStefan Roese * - Provides an API for platform code or device drivers to 44*d0787656SStefan Roese * dynamically add or remove address decoding windows for the CPU -> 45*d0787656SStefan Roese * device accesses. This API is mvebu_mbus_add_window_by_id(), 46*d0787656SStefan Roese * mvebu_mbus_add_window_remap_by_id() and 47*d0787656SStefan Roese * mvebu_mbus_del_window(). 48*d0787656SStefan Roese */ 49*d0787656SStefan Roese 50*d0787656SStefan Roese #include <common.h> 51*d0787656SStefan Roese #include <asm/errno.h> 52*d0787656SStefan Roese #include <asm/io.h> 53*d0787656SStefan Roese #include <asm/arch/cpu.h> 54*d0787656SStefan Roese #include <asm/arch/soc.h> 55*d0787656SStefan Roese #include <linux/mbus.h> 56*d0787656SStefan Roese 57*d0787656SStefan Roese #define BIT(nr) (1UL << (nr)) 58*d0787656SStefan Roese 59*d0787656SStefan Roese /* DDR target is the same on all platforms */ 60*d0787656SStefan Roese #define TARGET_DDR 0 61*d0787656SStefan Roese 62*d0787656SStefan Roese /* CPU Address Decode Windows registers */ 63*d0787656SStefan Roese #define WIN_CTRL_OFF 0x0000 64*d0787656SStefan Roese #define WIN_CTRL_ENABLE BIT(0) 65*d0787656SStefan Roese #define WIN_CTRL_TGT_MASK 0xf0 66*d0787656SStefan Roese #define WIN_CTRL_TGT_SHIFT 4 67*d0787656SStefan Roese #define WIN_CTRL_ATTR_MASK 0xff00 68*d0787656SStefan Roese #define WIN_CTRL_ATTR_SHIFT 8 69*d0787656SStefan Roese #define WIN_CTRL_SIZE_MASK 0xffff0000 70*d0787656SStefan Roese #define WIN_CTRL_SIZE_SHIFT 16 71*d0787656SStefan Roese #define WIN_BASE_OFF 0x0004 72*d0787656SStefan Roese #define WIN_BASE_LOW 0xffff0000 73*d0787656SStefan Roese #define WIN_BASE_HIGH 0xf 74*d0787656SStefan Roese #define WIN_REMAP_LO_OFF 0x0008 75*d0787656SStefan Roese #define WIN_REMAP_LOW 0xffff0000 76*d0787656SStefan Roese #define WIN_REMAP_HI_OFF 0x000c 77*d0787656SStefan Roese 78*d0787656SStefan Roese #define ATTR_HW_COHERENCY (0x1 << 4) 79*d0787656SStefan Roese 80*d0787656SStefan Roese #define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3)) 81*d0787656SStefan Roese #define DDR_BASE_CS_HIGH_MASK 0xf 82*d0787656SStefan Roese #define DDR_BASE_CS_LOW_MASK 0xff000000 83*d0787656SStefan Roese #define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3)) 84*d0787656SStefan Roese #define DDR_SIZE_ENABLED BIT(0) 85*d0787656SStefan Roese #define DDR_SIZE_CS_MASK 0x1c 86*d0787656SStefan Roese #define DDR_SIZE_CS_SHIFT 2 87*d0787656SStefan Roese #define DDR_SIZE_MASK 0xff000000 88*d0787656SStefan Roese 89*d0787656SStefan Roese #define DOVE_DDR_BASE_CS_OFF(n) ((n) << 4) 90*d0787656SStefan Roese 91*d0787656SStefan Roese struct mvebu_mbus_state; 92*d0787656SStefan Roese 93*d0787656SStefan Roese struct mvebu_mbus_soc_data { 94*d0787656SStefan Roese unsigned int num_wins; 95*d0787656SStefan Roese unsigned int num_remappable_wins; 96*d0787656SStefan Roese unsigned int (*win_cfg_offset)(const int win); 97*d0787656SStefan Roese void (*setup_cpu_target)(struct mvebu_mbus_state *s); 98*d0787656SStefan Roese }; 99*d0787656SStefan Roese 100*d0787656SStefan Roese struct mvebu_mbus_state mbus_state 101*d0787656SStefan Roese __attribute__ ((section(".data"))); 102*d0787656SStefan Roese static struct mbus_dram_target_info mbus_dram_info 103*d0787656SStefan Roese __attribute__ ((section(".data"))); 104*d0787656SStefan Roese 105*d0787656SStefan Roese /* 106*d0787656SStefan Roese * Functions to manipulate the address decoding windows 107*d0787656SStefan Roese */ 108*d0787656SStefan Roese 109*d0787656SStefan Roese static void mvebu_mbus_read_window(struct mvebu_mbus_state *mbus, 110*d0787656SStefan Roese int win, int *enabled, u64 *base, 111*d0787656SStefan Roese u32 *size, u8 *target, u8 *attr, 112*d0787656SStefan Roese u64 *remap) 113*d0787656SStefan Roese { 114*d0787656SStefan Roese void __iomem *addr = mbus->mbuswins_base + 115*d0787656SStefan Roese mbus->soc->win_cfg_offset(win); 116*d0787656SStefan Roese u32 basereg = readl(addr + WIN_BASE_OFF); 117*d0787656SStefan Roese u32 ctrlreg = readl(addr + WIN_CTRL_OFF); 118*d0787656SStefan Roese 119*d0787656SStefan Roese if (!(ctrlreg & WIN_CTRL_ENABLE)) { 120*d0787656SStefan Roese *enabled = 0; 121*d0787656SStefan Roese return; 122*d0787656SStefan Roese } 123*d0787656SStefan Roese 124*d0787656SStefan Roese *enabled = 1; 125*d0787656SStefan Roese *base = ((u64)basereg & WIN_BASE_HIGH) << 32; 126*d0787656SStefan Roese *base |= (basereg & WIN_BASE_LOW); 127*d0787656SStefan Roese *size = (ctrlreg | ~WIN_CTRL_SIZE_MASK) + 1; 128*d0787656SStefan Roese 129*d0787656SStefan Roese if (target) 130*d0787656SStefan Roese *target = (ctrlreg & WIN_CTRL_TGT_MASK) >> WIN_CTRL_TGT_SHIFT; 131*d0787656SStefan Roese 132*d0787656SStefan Roese if (attr) 133*d0787656SStefan Roese *attr = (ctrlreg & WIN_CTRL_ATTR_MASK) >> WIN_CTRL_ATTR_SHIFT; 134*d0787656SStefan Roese 135*d0787656SStefan Roese if (remap) { 136*d0787656SStefan Roese if (win < mbus->soc->num_remappable_wins) { 137*d0787656SStefan Roese u32 remap_low = readl(addr + WIN_REMAP_LO_OFF); 138*d0787656SStefan Roese u32 remap_hi = readl(addr + WIN_REMAP_HI_OFF); 139*d0787656SStefan Roese *remap = ((u64)remap_hi << 32) | remap_low; 140*d0787656SStefan Roese } else { 141*d0787656SStefan Roese *remap = 0; 142*d0787656SStefan Roese } 143*d0787656SStefan Roese } 144*d0787656SStefan Roese } 145*d0787656SStefan Roese 146*d0787656SStefan Roese static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus, 147*d0787656SStefan Roese int win) 148*d0787656SStefan Roese { 149*d0787656SStefan Roese void __iomem *addr; 150*d0787656SStefan Roese 151*d0787656SStefan Roese addr = mbus->mbuswins_base + mbus->soc->win_cfg_offset(win); 152*d0787656SStefan Roese 153*d0787656SStefan Roese writel(0, addr + WIN_BASE_OFF); 154*d0787656SStefan Roese writel(0, addr + WIN_CTRL_OFF); 155*d0787656SStefan Roese if (win < mbus->soc->num_remappable_wins) { 156*d0787656SStefan Roese writel(0, addr + WIN_REMAP_LO_OFF); 157*d0787656SStefan Roese writel(0, addr + WIN_REMAP_HI_OFF); 158*d0787656SStefan Roese } 159*d0787656SStefan Roese } 160*d0787656SStefan Roese 161*d0787656SStefan Roese /* Checks whether the given window number is available */ 162*d0787656SStefan Roese static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus, 163*d0787656SStefan Roese const int win) 164*d0787656SStefan Roese { 165*d0787656SStefan Roese void __iomem *addr = mbus->mbuswins_base + 166*d0787656SStefan Roese mbus->soc->win_cfg_offset(win); 167*d0787656SStefan Roese u32 ctrl = readl(addr + WIN_CTRL_OFF); 168*d0787656SStefan Roese return !(ctrl & WIN_CTRL_ENABLE); 169*d0787656SStefan Roese } 170*d0787656SStefan Roese 171*d0787656SStefan Roese /* 172*d0787656SStefan Roese * Checks whether the given (base, base+size) area doesn't overlap an 173*d0787656SStefan Roese * existing region 174*d0787656SStefan Roese */ 175*d0787656SStefan Roese static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus, 176*d0787656SStefan Roese phys_addr_t base, size_t size, 177*d0787656SStefan Roese u8 target, u8 attr) 178*d0787656SStefan Roese { 179*d0787656SStefan Roese u64 end = (u64)base + size; 180*d0787656SStefan Roese int win; 181*d0787656SStefan Roese 182*d0787656SStefan Roese for (win = 0; win < mbus->soc->num_wins; win++) { 183*d0787656SStefan Roese u64 wbase, wend; 184*d0787656SStefan Roese u32 wsize; 185*d0787656SStefan Roese u8 wtarget, wattr; 186*d0787656SStefan Roese int enabled; 187*d0787656SStefan Roese 188*d0787656SStefan Roese mvebu_mbus_read_window(mbus, win, 189*d0787656SStefan Roese &enabled, &wbase, &wsize, 190*d0787656SStefan Roese &wtarget, &wattr, NULL); 191*d0787656SStefan Roese 192*d0787656SStefan Roese if (!enabled) 193*d0787656SStefan Roese continue; 194*d0787656SStefan Roese 195*d0787656SStefan Roese wend = wbase + wsize; 196*d0787656SStefan Roese 197*d0787656SStefan Roese /* 198*d0787656SStefan Roese * Check if the current window overlaps with the 199*d0787656SStefan Roese * proposed physical range 200*d0787656SStefan Roese */ 201*d0787656SStefan Roese if ((u64)base < wend && end > wbase) 202*d0787656SStefan Roese return 0; 203*d0787656SStefan Roese 204*d0787656SStefan Roese /* 205*d0787656SStefan Roese * Check if target/attribute conflicts 206*d0787656SStefan Roese */ 207*d0787656SStefan Roese if (target == wtarget && attr == wattr) 208*d0787656SStefan Roese return 0; 209*d0787656SStefan Roese } 210*d0787656SStefan Roese 211*d0787656SStefan Roese return 1; 212*d0787656SStefan Roese } 213*d0787656SStefan Roese 214*d0787656SStefan Roese static int mvebu_mbus_find_window(struct mvebu_mbus_state *mbus, 215*d0787656SStefan Roese phys_addr_t base, size_t size) 216*d0787656SStefan Roese { 217*d0787656SStefan Roese int win; 218*d0787656SStefan Roese 219*d0787656SStefan Roese for (win = 0; win < mbus->soc->num_wins; win++) { 220*d0787656SStefan Roese u64 wbase; 221*d0787656SStefan Roese u32 wsize; 222*d0787656SStefan Roese int enabled; 223*d0787656SStefan Roese 224*d0787656SStefan Roese mvebu_mbus_read_window(mbus, win, 225*d0787656SStefan Roese &enabled, &wbase, &wsize, 226*d0787656SStefan Roese NULL, NULL, NULL); 227*d0787656SStefan Roese 228*d0787656SStefan Roese if (!enabled) 229*d0787656SStefan Roese continue; 230*d0787656SStefan Roese 231*d0787656SStefan Roese if (base == wbase && size == wsize) 232*d0787656SStefan Roese return win; 233*d0787656SStefan Roese } 234*d0787656SStefan Roese 235*d0787656SStefan Roese return -ENODEV; 236*d0787656SStefan Roese } 237*d0787656SStefan Roese 238*d0787656SStefan Roese static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus, 239*d0787656SStefan Roese int win, phys_addr_t base, size_t size, 240*d0787656SStefan Roese phys_addr_t remap, u8 target, 241*d0787656SStefan Roese u8 attr) 242*d0787656SStefan Roese { 243*d0787656SStefan Roese void __iomem *addr = mbus->mbuswins_base + 244*d0787656SStefan Roese mbus->soc->win_cfg_offset(win); 245*d0787656SStefan Roese u32 ctrl, remap_addr; 246*d0787656SStefan Roese 247*d0787656SStefan Roese ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) | 248*d0787656SStefan Roese (attr << WIN_CTRL_ATTR_SHIFT) | 249*d0787656SStefan Roese (target << WIN_CTRL_TGT_SHIFT) | 250*d0787656SStefan Roese WIN_CTRL_ENABLE; 251*d0787656SStefan Roese 252*d0787656SStefan Roese writel(base & WIN_BASE_LOW, addr + WIN_BASE_OFF); 253*d0787656SStefan Roese writel(ctrl, addr + WIN_CTRL_OFF); 254*d0787656SStefan Roese if (win < mbus->soc->num_remappable_wins) { 255*d0787656SStefan Roese if (remap == MVEBU_MBUS_NO_REMAP) 256*d0787656SStefan Roese remap_addr = base; 257*d0787656SStefan Roese else 258*d0787656SStefan Roese remap_addr = remap; 259*d0787656SStefan Roese writel(remap_addr & WIN_REMAP_LOW, addr + WIN_REMAP_LO_OFF); 260*d0787656SStefan Roese writel(0, addr + WIN_REMAP_HI_OFF); 261*d0787656SStefan Roese } 262*d0787656SStefan Roese 263*d0787656SStefan Roese return 0; 264*d0787656SStefan Roese } 265*d0787656SStefan Roese 266*d0787656SStefan Roese static int mvebu_mbus_alloc_window(struct mvebu_mbus_state *mbus, 267*d0787656SStefan Roese phys_addr_t base, size_t size, 268*d0787656SStefan Roese phys_addr_t remap, u8 target, 269*d0787656SStefan Roese u8 attr) 270*d0787656SStefan Roese { 271*d0787656SStefan Roese int win; 272*d0787656SStefan Roese 273*d0787656SStefan Roese if (remap == MVEBU_MBUS_NO_REMAP) { 274*d0787656SStefan Roese for (win = mbus->soc->num_remappable_wins; 275*d0787656SStefan Roese win < mbus->soc->num_wins; win++) 276*d0787656SStefan Roese if (mvebu_mbus_window_is_free(mbus, win)) 277*d0787656SStefan Roese return mvebu_mbus_setup_window(mbus, win, base, 278*d0787656SStefan Roese size, remap, 279*d0787656SStefan Roese target, attr); 280*d0787656SStefan Roese } 281*d0787656SStefan Roese 282*d0787656SStefan Roese 283*d0787656SStefan Roese for (win = 0; win < mbus->soc->num_wins; win++) 284*d0787656SStefan Roese if (mvebu_mbus_window_is_free(mbus, win)) 285*d0787656SStefan Roese return mvebu_mbus_setup_window(mbus, win, base, size, 286*d0787656SStefan Roese remap, target, attr); 287*d0787656SStefan Roese 288*d0787656SStefan Roese return -ENOMEM; 289*d0787656SStefan Roese } 290*d0787656SStefan Roese 291*d0787656SStefan Roese /* 292*d0787656SStefan Roese * SoC-specific functions and definitions 293*d0787656SStefan Roese */ 294*d0787656SStefan Roese 295*d0787656SStefan Roese static unsigned int armada_370_xp_mbus_win_offset(int win) 296*d0787656SStefan Roese { 297*d0787656SStefan Roese /* The register layout is a bit annoying and the below code 298*d0787656SStefan Roese * tries to cope with it. 299*d0787656SStefan Roese * - At offset 0x0, there are the registers for the first 8 300*d0787656SStefan Roese * windows, with 4 registers of 32 bits per window (ctrl, 301*d0787656SStefan Roese * base, remap low, remap high) 302*d0787656SStefan Roese * - Then at offset 0x80, there is a hole of 0x10 bytes for 303*d0787656SStefan Roese * the internal registers base address and internal units 304*d0787656SStefan Roese * sync barrier register. 305*d0787656SStefan Roese * - Then at offset 0x90, there the registers for 12 306*d0787656SStefan Roese * windows, with only 2 registers of 32 bits per window 307*d0787656SStefan Roese * (ctrl, base). 308*d0787656SStefan Roese */ 309*d0787656SStefan Roese if (win < 8) 310*d0787656SStefan Roese return win << 4; 311*d0787656SStefan Roese else 312*d0787656SStefan Roese return 0x90 + ((win - 8) << 3); 313*d0787656SStefan Roese } 314*d0787656SStefan Roese 315*d0787656SStefan Roese static unsigned int orion5x_mbus_win_offset(int win) 316*d0787656SStefan Roese { 317*d0787656SStefan Roese return win << 4; 318*d0787656SStefan Roese } 319*d0787656SStefan Roese 320*d0787656SStefan Roese static void mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus) 321*d0787656SStefan Roese { 322*d0787656SStefan Roese int i; 323*d0787656SStefan Roese int cs; 324*d0787656SStefan Roese 325*d0787656SStefan Roese mbus_dram_info.mbus_dram_target_id = TARGET_DDR; 326*d0787656SStefan Roese 327*d0787656SStefan Roese for (i = 0, cs = 0; i < 4; i++) { 328*d0787656SStefan Roese u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i)); 329*d0787656SStefan Roese u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i)); 330*d0787656SStefan Roese 331*d0787656SStefan Roese /* 332*d0787656SStefan Roese * We only take care of entries for which the chip 333*d0787656SStefan Roese * select is enabled, and that don't have high base 334*d0787656SStefan Roese * address bits set (devices can only access the first 335*d0787656SStefan Roese * 32 bits of the memory). 336*d0787656SStefan Roese */ 337*d0787656SStefan Roese if ((size & DDR_SIZE_ENABLED) && 338*d0787656SStefan Roese !(base & DDR_BASE_CS_HIGH_MASK)) { 339*d0787656SStefan Roese struct mbus_dram_window *w; 340*d0787656SStefan Roese 341*d0787656SStefan Roese w = &mbus_dram_info.cs[cs++]; 342*d0787656SStefan Roese w->cs_index = i; 343*d0787656SStefan Roese w->mbus_attr = 0xf & ~(1 << i); 344*d0787656SStefan Roese #if defined(CONFIG_ARMADA_XP) 345*d0787656SStefan Roese w->mbus_attr |= ATTR_HW_COHERENCY; 346*d0787656SStefan Roese #endif 347*d0787656SStefan Roese w->base = base & DDR_BASE_CS_LOW_MASK; 348*d0787656SStefan Roese w->size = (size | ~DDR_SIZE_MASK) + 1; 349*d0787656SStefan Roese } 350*d0787656SStefan Roese } 351*d0787656SStefan Roese mbus_dram_info.num_cs = cs; 352*d0787656SStefan Roese } 353*d0787656SStefan Roese 354*d0787656SStefan Roese static const struct mvebu_mbus_soc_data 355*d0787656SStefan Roese armada_370_xp_mbus_data __maybe_unused = { 356*d0787656SStefan Roese .num_wins = 20, 357*d0787656SStefan Roese .num_remappable_wins = 8, 358*d0787656SStefan Roese .win_cfg_offset = armada_370_xp_mbus_win_offset, 359*d0787656SStefan Roese .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, 360*d0787656SStefan Roese }; 361*d0787656SStefan Roese 362*d0787656SStefan Roese static const struct mvebu_mbus_soc_data 363*d0787656SStefan Roese kirkwood_mbus_data __maybe_unused = { 364*d0787656SStefan Roese .num_wins = 8, 365*d0787656SStefan Roese .num_remappable_wins = 4, 366*d0787656SStefan Roese .win_cfg_offset = orion5x_mbus_win_offset, 367*d0787656SStefan Roese .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, 368*d0787656SStefan Roese }; 369*d0787656SStefan Roese 370*d0787656SStefan Roese /* 371*d0787656SStefan Roese * Public API of the driver 372*d0787656SStefan Roese */ 373*d0787656SStefan Roese const struct mbus_dram_target_info *mvebu_mbus_dram_info(void) 374*d0787656SStefan Roese { 375*d0787656SStefan Roese return &mbus_dram_info; 376*d0787656SStefan Roese } 377*d0787656SStefan Roese 378*d0787656SStefan Roese int mvebu_mbus_add_window_remap_by_id(unsigned int target, 379*d0787656SStefan Roese unsigned int attribute, 380*d0787656SStefan Roese phys_addr_t base, size_t size, 381*d0787656SStefan Roese phys_addr_t remap) 382*d0787656SStefan Roese { 383*d0787656SStefan Roese struct mvebu_mbus_state *s = &mbus_state; 384*d0787656SStefan Roese 385*d0787656SStefan Roese if (!mvebu_mbus_window_conflicts(s, base, size, target, attribute)) { 386*d0787656SStefan Roese printf("Cannot add window '%x:%x', conflicts with another window\n", 387*d0787656SStefan Roese target, attribute); 388*d0787656SStefan Roese return -EINVAL; 389*d0787656SStefan Roese } 390*d0787656SStefan Roese 391*d0787656SStefan Roese return mvebu_mbus_alloc_window(s, base, size, remap, target, attribute); 392*d0787656SStefan Roese } 393*d0787656SStefan Roese 394*d0787656SStefan Roese int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute, 395*d0787656SStefan Roese phys_addr_t base, size_t size) 396*d0787656SStefan Roese { 397*d0787656SStefan Roese return mvebu_mbus_add_window_remap_by_id(target, attribute, base, 398*d0787656SStefan Roese size, MVEBU_MBUS_NO_REMAP); 399*d0787656SStefan Roese } 400*d0787656SStefan Roese 401*d0787656SStefan Roese int mvebu_mbus_del_window(phys_addr_t base, size_t size) 402*d0787656SStefan Roese { 403*d0787656SStefan Roese int win; 404*d0787656SStefan Roese 405*d0787656SStefan Roese win = mvebu_mbus_find_window(&mbus_state, base, size); 406*d0787656SStefan Roese if (win < 0) 407*d0787656SStefan Roese return win; 408*d0787656SStefan Roese 409*d0787656SStefan Roese mvebu_mbus_disable_window(&mbus_state, win); 410*d0787656SStefan Roese return 0; 411*d0787656SStefan Roese } 412*d0787656SStefan Roese 413*d0787656SStefan Roese int mbus_dt_setup_win(struct mvebu_mbus_state *mbus, 414*d0787656SStefan Roese u32 base, u32 size, u8 target, u8 attr) 415*d0787656SStefan Roese { 416*d0787656SStefan Roese if (!mvebu_mbus_window_conflicts(mbus, base, size, target, attr)) { 417*d0787656SStefan Roese printf("Cannot add window '%04x:%04x', conflicts with another window\n", 418*d0787656SStefan Roese target, attr); 419*d0787656SStefan Roese return -EBUSY; 420*d0787656SStefan Roese } 421*d0787656SStefan Roese 422*d0787656SStefan Roese /* 423*d0787656SStefan Roese * In U-Boot we first try to add the mbus window to the remap windows. 424*d0787656SStefan Roese * If this fails, lets try to add the windows to the non-remap windows. 425*d0787656SStefan Roese */ 426*d0787656SStefan Roese if (mvebu_mbus_alloc_window(mbus, base, size, base, target, attr)) { 427*d0787656SStefan Roese if (mvebu_mbus_alloc_window(mbus, base, size, 428*d0787656SStefan Roese MVEBU_MBUS_NO_REMAP, target, attr)) 429*d0787656SStefan Roese return -ENOMEM; 430*d0787656SStefan Roese } 431*d0787656SStefan Roese 432*d0787656SStefan Roese return 0; 433*d0787656SStefan Roese } 434*d0787656SStefan Roese 435*d0787656SStefan Roese int mvebu_mbus_probe(struct mbus_win windows[], int count) 436*d0787656SStefan Roese { 437*d0787656SStefan Roese int win; 438*d0787656SStefan Roese int ret; 439*d0787656SStefan Roese int i; 440*d0787656SStefan Roese 441*d0787656SStefan Roese #if defined(CONFIG_KIRKWOOD) 442*d0787656SStefan Roese mbus_state.soc = &kirkwood_mbus_data; 443*d0787656SStefan Roese #endif 444*d0787656SStefan Roese #if defined(CONFIG_ARMADA_XP) 445*d0787656SStefan Roese mbus_state.soc = &armada_370_xp_mbus_data; 446*d0787656SStefan Roese #endif 447*d0787656SStefan Roese 448*d0787656SStefan Roese mbus_state.mbuswins_base = (void __iomem *)MVEBU_CPU_WIN_BASE; 449*d0787656SStefan Roese mbus_state.sdramwins_base = (void __iomem *)MVEBU_SDRAM_BASE; 450*d0787656SStefan Roese 451*d0787656SStefan Roese for (win = 0; win < mbus_state.soc->num_wins; win++) 452*d0787656SStefan Roese mvebu_mbus_disable_window(&mbus_state, win); 453*d0787656SStefan Roese 454*d0787656SStefan Roese mbus_state.soc->setup_cpu_target(&mbus_state); 455*d0787656SStefan Roese 456*d0787656SStefan Roese /* Setup statically declared windows in the DT */ 457*d0787656SStefan Roese for (i = 0; i < count; i++) { 458*d0787656SStefan Roese u32 base, size; 459*d0787656SStefan Roese u8 target, attr; 460*d0787656SStefan Roese 461*d0787656SStefan Roese target = windows[i].target; 462*d0787656SStefan Roese attr = windows[i].attr; 463*d0787656SStefan Roese base = windows[i].base; 464*d0787656SStefan Roese size = windows[i].size; 465*d0787656SStefan Roese ret = mbus_dt_setup_win(&mbus_state, base, size, target, attr); 466*d0787656SStefan Roese if (ret < 0) 467*d0787656SStefan Roese return ret; 468*d0787656SStefan Roese } 469*d0787656SStefan Roese 470*d0787656SStefan Roese return 0; 471*d0787656SStefan Roese } 472