Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Address map functions for Marvell EBU SoCs (Kirkwood, Armada
0004  * 370/XP, Dove, Orion5x and MV78xx0)
0005  *
0006  * The Marvell EBU SoCs have a configurable physical address space:
0007  * the physical address at which certain devices (PCIe, NOR, NAND,
0008  * etc.) sit can be configured. The configuration takes place through
0009  * two sets of registers:
0010  *
0011  * - One to configure the access of the CPU to the devices. Depending
0012  *   on the families, there are between 8 and 20 configurable windows,
0013  *   each can be use to create a physical memory window that maps to a
0014  *   specific device. Devices are identified by a tuple (target,
0015  *   attribute).
0016  *
0017  * - One to configure the access to the CPU to the SDRAM. There are
0018  *   either 2 (for Dove) or 4 (for other families) windows to map the
0019  *   SDRAM into the physical address space.
0020  *
0021  * This driver:
0022  *
0023  * - Reads out the SDRAM address decoding windows at initialization
0024  *   time, and fills the mvebu_mbus_dram_info structure with these
0025  *   information. The exported function mv_mbus_dram_info() allow
0026  *   device drivers to get those information related to the SDRAM
0027  *   address decoding windows. This is because devices also have their
0028  *   own windows (configured through registers that are part of each
0029  *   device register space), and therefore the drivers for Marvell
0030  *   devices have to configure those device -> SDRAM windows to ensure
0031  *   that DMA works properly.
0032  *
0033  * - Provides an API for platform code or device drivers to
0034  *   dynamically add or remove address decoding windows for the CPU ->
0035  *   device accesses. This API is mvebu_mbus_add_window_by_id(),
0036  *   mvebu_mbus_add_window_remap_by_id() and
0037  *   mvebu_mbus_del_window().
0038  *
0039  * - Provides a debugfs interface in /sys/kernel/debug/mvebu-mbus/ to
0040  *   see the list of CPU -> SDRAM windows and their configuration
0041  *   (file 'sdram') and the list of CPU -> devices windows and their
0042  *   configuration (file 'devices').
0043  */
0044 
0045 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0046 
0047 #include <linux/kernel.h>
0048 #include <linux/module.h>
0049 #include <linux/init.h>
0050 #include <linux/mbus.h>
0051 #include <linux/io.h>
0052 #include <linux/ioport.h>
0053 #include <linux/of.h>
0054 #include <linux/of_address.h>
0055 #include <linux/debugfs.h>
0056 #include <linux/log2.h>
0057 #include <linux/memblock.h>
0058 #include <linux/syscore_ops.h>
0059 
0060 /*
0061  * DDR target is the same on all platforms.
0062  */
0063 #define TARGET_DDR      0
0064 
0065 /*
0066  * CPU Address Decode Windows registers
0067  */
0068 #define WIN_CTRL_OFF        0x0000
0069 #define   WIN_CTRL_ENABLE       BIT(0)
0070 /* Only on HW I/O coherency capable platforms */
0071 #define   WIN_CTRL_SYNCBARRIER  BIT(1)
0072 #define   WIN_CTRL_TGT_MASK     0xf0
0073 #define   WIN_CTRL_TGT_SHIFT    4
0074 #define   WIN_CTRL_ATTR_MASK    0xff00
0075 #define   WIN_CTRL_ATTR_SHIFT   8
0076 #define   WIN_CTRL_SIZE_MASK    0xffff0000
0077 #define   WIN_CTRL_SIZE_SHIFT   16
0078 #define WIN_BASE_OFF        0x0004
0079 #define   WIN_BASE_LOW          0xffff0000
0080 #define   WIN_BASE_HIGH         0xf
0081 #define WIN_REMAP_LO_OFF    0x0008
0082 #define   WIN_REMAP_LOW         0xffff0000
0083 #define WIN_REMAP_HI_OFF    0x000c
0084 
0085 #define UNIT_SYNC_BARRIER_OFF   0x84
0086 #define   UNIT_SYNC_BARRIER_ALL 0xFFFF
0087 
0088 #define ATTR_HW_COHERENCY   (0x1 << 4)
0089 
0090 #define DDR_BASE_CS_OFF(n)  (0x0000 + ((n) << 3))
0091 #define  DDR_BASE_CS_HIGH_MASK  0xf
0092 #define  DDR_BASE_CS_LOW_MASK   0xff000000
0093 #define DDR_SIZE_CS_OFF(n)  (0x0004 + ((n) << 3))
0094 #define  DDR_SIZE_ENABLED       BIT(0)
0095 #define  DDR_SIZE_CS_MASK       0x1c
0096 #define  DDR_SIZE_CS_SHIFT      2
0097 #define  DDR_SIZE_MASK          0xff000000
0098 
0099 #define DOVE_DDR_BASE_CS_OFF(n) ((n) << 4)
0100 
0101 /* Relative to mbusbridge_base */
0102 #define MBUS_BRIDGE_CTRL_OFF    0x0
0103 #define MBUS_BRIDGE_BASE_OFF    0x4
0104 
0105 /* Maximum number of windows, for all known platforms */
0106 #define MBUS_WINS_MAX           20
0107 
0108 struct mvebu_mbus_state;
0109 
0110 struct mvebu_mbus_soc_data {
0111     unsigned int num_wins;
0112     bool has_mbus_bridge;
0113     unsigned int (*win_cfg_offset)(const int win);
0114     unsigned int (*win_remap_offset)(const int win);
0115     void (*setup_cpu_target)(struct mvebu_mbus_state *s);
0116     int (*save_cpu_target)(struct mvebu_mbus_state *s,
0117                    u32 __iomem *store_addr);
0118     int (*show_cpu_target)(struct mvebu_mbus_state *s,
0119                    struct seq_file *seq, void *v);
0120 };
0121 
0122 /*
0123  * Used to store the state of one MBus window across suspend/resume.
0124  */
0125 struct mvebu_mbus_win_data {
0126     u32 ctrl;
0127     u32 base;
0128     u32 remap_lo;
0129     u32 remap_hi;
0130 };
0131 
0132 struct mvebu_mbus_state {
0133     void __iomem *mbuswins_base;
0134     void __iomem *sdramwins_base;
0135     void __iomem *mbusbridge_base;
0136     phys_addr_t sdramwins_phys_base;
0137     struct dentry *debugfs_root;
0138     struct dentry *debugfs_sdram;
0139     struct dentry *debugfs_devs;
0140     struct resource pcie_mem_aperture;
0141     struct resource pcie_io_aperture;
0142     const struct mvebu_mbus_soc_data *soc;
0143     int hw_io_coherency;
0144 
0145     /* Used during suspend/resume */
0146     u32 mbus_bridge_ctrl;
0147     u32 mbus_bridge_base;
0148     struct mvebu_mbus_win_data wins[MBUS_WINS_MAX];
0149 };
0150 
0151 static struct mvebu_mbus_state mbus_state;
0152 
0153 /*
0154  * We provide two variants of the mv_mbus_dram_info() function:
0155  *
0156  * - The normal one, where the described DRAM ranges may overlap with
0157  *   the I/O windows, but for which the DRAM ranges are guaranteed to
0158  *   have a power of two size. Such ranges are suitable for the DMA
0159  *   masters that only DMA between the RAM and the device, which is
0160  *   actually all devices except the crypto engines.
0161  *
0162  * - The 'nooverlap' one, where the described DRAM ranges are
0163  *   guaranteed to not overlap with the I/O windows, but for which the
0164  *   DRAM ranges will not have power of two sizes. They will only be
0165  *   aligned on a 64 KB boundary, and have a size multiple of 64
0166  *   KB. Such ranges are suitable for the DMA masters that DMA between
0167  *   the crypto SRAM (which is mapped through an I/O window) and a
0168  *   device. This is the case for the crypto engines.
0169  */
0170 
0171 static struct mbus_dram_target_info mvebu_mbus_dram_info;
0172 static struct mbus_dram_target_info mvebu_mbus_dram_info_nooverlap;
0173 
0174 const struct mbus_dram_target_info *mv_mbus_dram_info(void)
0175 {
0176     return &mvebu_mbus_dram_info;
0177 }
0178 EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
0179 
0180 const struct mbus_dram_target_info *mv_mbus_dram_info_nooverlap(void)
0181 {
0182     return &mvebu_mbus_dram_info_nooverlap;
0183 }
0184 EXPORT_SYMBOL_GPL(mv_mbus_dram_info_nooverlap);
0185 
0186 /* Checks whether the given window has remap capability */
0187 static bool mvebu_mbus_window_is_remappable(struct mvebu_mbus_state *mbus,
0188                         const int win)
0189 {
0190     return mbus->soc->win_remap_offset(win) != MVEBU_MBUS_NO_REMAP;
0191 }
0192 
0193 /*
0194  * Functions to manipulate the address decoding windows
0195  */
0196 
0197 static void mvebu_mbus_read_window(struct mvebu_mbus_state *mbus,
0198                    int win, int *enabled, u64 *base,
0199                    u32 *size, u8 *target, u8 *attr,
0200                    u64 *remap)
0201 {
0202     void __iomem *addr = mbus->mbuswins_base +
0203         mbus->soc->win_cfg_offset(win);
0204     u32 basereg = readl(addr + WIN_BASE_OFF);
0205     u32 ctrlreg = readl(addr + WIN_CTRL_OFF);
0206 
0207     if (!(ctrlreg & WIN_CTRL_ENABLE)) {
0208         *enabled = 0;
0209         return;
0210     }
0211 
0212     *enabled = 1;
0213     *base = ((u64)basereg & WIN_BASE_HIGH) << 32;
0214     *base |= (basereg & WIN_BASE_LOW);
0215     *size = (ctrlreg | ~WIN_CTRL_SIZE_MASK) + 1;
0216 
0217     if (target)
0218         *target = (ctrlreg & WIN_CTRL_TGT_MASK) >> WIN_CTRL_TGT_SHIFT;
0219 
0220     if (attr)
0221         *attr = (ctrlreg & WIN_CTRL_ATTR_MASK) >> WIN_CTRL_ATTR_SHIFT;
0222 
0223     if (remap) {
0224         if (mvebu_mbus_window_is_remappable(mbus, win)) {
0225             u32 remap_low, remap_hi;
0226             void __iomem *addr_rmp = mbus->mbuswins_base +
0227                 mbus->soc->win_remap_offset(win);
0228             remap_low = readl(addr_rmp + WIN_REMAP_LO_OFF);
0229             remap_hi  = readl(addr_rmp + WIN_REMAP_HI_OFF);
0230             *remap = ((u64)remap_hi << 32) | remap_low;
0231         } else
0232             *remap = 0;
0233     }
0234 }
0235 
0236 static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus,
0237                       int win)
0238 {
0239     void __iomem *addr;
0240 
0241     addr = mbus->mbuswins_base + mbus->soc->win_cfg_offset(win);
0242     writel(0, addr + WIN_BASE_OFF);
0243     writel(0, addr + WIN_CTRL_OFF);
0244 
0245     if (mvebu_mbus_window_is_remappable(mbus, win)) {
0246         addr = mbus->mbuswins_base + mbus->soc->win_remap_offset(win);
0247         writel(0, addr + WIN_REMAP_LO_OFF);
0248         writel(0, addr + WIN_REMAP_HI_OFF);
0249     }
0250 }
0251 
0252 /* Checks whether the given window number is available */
0253 
0254 static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus,
0255                      const int win)
0256 {
0257     void __iomem *addr = mbus->mbuswins_base +
0258         mbus->soc->win_cfg_offset(win);
0259     u32 ctrl = readl(addr + WIN_CTRL_OFF);
0260 
0261     return !(ctrl & WIN_CTRL_ENABLE);
0262 }
0263 
0264 /*
0265  * Checks whether the given (base, base+size) area doesn't overlap an
0266  * existing region
0267  */
0268 static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
0269                        phys_addr_t base, size_t size,
0270                        u8 target, u8 attr)
0271 {
0272     u64 end = (u64)base + size;
0273     int win;
0274 
0275     for (win = 0; win < mbus->soc->num_wins; win++) {
0276         u64 wbase, wend;
0277         u32 wsize;
0278         u8 wtarget, wattr;
0279         int enabled;
0280 
0281         mvebu_mbus_read_window(mbus, win,
0282                        &enabled, &wbase, &wsize,
0283                        &wtarget, &wattr, NULL);
0284 
0285         if (!enabled)
0286             continue;
0287 
0288         wend = wbase + wsize;
0289 
0290         /*
0291          * Check if the current window overlaps with the
0292          * proposed physical range
0293          */
0294         if ((u64)base < wend && end > wbase)
0295             return 0;
0296     }
0297 
0298     return 1;
0299 }
0300 
0301 static int mvebu_mbus_find_window(struct mvebu_mbus_state *mbus,
0302                   phys_addr_t base, size_t size)
0303 {
0304     int win;
0305 
0306     for (win = 0; win < mbus->soc->num_wins; win++) {
0307         u64 wbase;
0308         u32 wsize;
0309         int enabled;
0310 
0311         mvebu_mbus_read_window(mbus, win,
0312                        &enabled, &wbase, &wsize,
0313                        NULL, NULL, NULL);
0314 
0315         if (!enabled)
0316             continue;
0317 
0318         if (base == wbase && size == wsize)
0319             return win;
0320     }
0321 
0322     return -ENODEV;
0323 }
0324 
0325 static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus,
0326                    int win, phys_addr_t base, size_t size,
0327                    phys_addr_t remap, u8 target,
0328                    u8 attr)
0329 {
0330     void __iomem *addr = mbus->mbuswins_base +
0331         mbus->soc->win_cfg_offset(win);
0332     u32 ctrl, remap_addr;
0333 
0334     if (!is_power_of_2(size)) {
0335         WARN(true, "Invalid MBus window size: 0x%zx\n", size);
0336         return -EINVAL;
0337     }
0338 
0339     if ((base & (phys_addr_t)(size - 1)) != 0) {
0340         WARN(true, "Invalid MBus base/size: %pa len 0x%zx\n", &base,
0341              size);
0342         return -EINVAL;
0343     }
0344 
0345     ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) |
0346         (attr << WIN_CTRL_ATTR_SHIFT)    |
0347         (target << WIN_CTRL_TGT_SHIFT)   |
0348         WIN_CTRL_ENABLE;
0349     if (mbus->hw_io_coherency)
0350         ctrl |= WIN_CTRL_SYNCBARRIER;
0351 
0352     writel(base & WIN_BASE_LOW, addr + WIN_BASE_OFF);
0353     writel(ctrl, addr + WIN_CTRL_OFF);
0354 
0355     if (mvebu_mbus_window_is_remappable(mbus, win)) {
0356         void __iomem *addr_rmp = mbus->mbuswins_base +
0357             mbus->soc->win_remap_offset(win);
0358 
0359         if (remap == MVEBU_MBUS_NO_REMAP)
0360             remap_addr = base;
0361         else
0362             remap_addr = remap;
0363         writel(remap_addr & WIN_REMAP_LOW, addr_rmp + WIN_REMAP_LO_OFF);
0364         writel(0, addr_rmp + WIN_REMAP_HI_OFF);
0365     }
0366 
0367     return 0;
0368 }
0369 
0370 static int mvebu_mbus_alloc_window(struct mvebu_mbus_state *mbus,
0371                    phys_addr_t base, size_t size,
0372                    phys_addr_t remap, u8 target,
0373                    u8 attr)
0374 {
0375     int win;
0376 
0377     if (remap == MVEBU_MBUS_NO_REMAP) {
0378         for (win = 0; win < mbus->soc->num_wins; win++) {
0379             if (mvebu_mbus_window_is_remappable(mbus, win))
0380                 continue;
0381 
0382             if (mvebu_mbus_window_is_free(mbus, win))
0383                 return mvebu_mbus_setup_window(mbus, win, base,
0384                                    size, remap,
0385                                    target, attr);
0386         }
0387     }
0388 
0389     for (win = 0; win < mbus->soc->num_wins; win++) {
0390         /* Skip window if need remap but is not supported */
0391         if ((remap != MVEBU_MBUS_NO_REMAP) &&
0392             !mvebu_mbus_window_is_remappable(mbus, win))
0393             continue;
0394 
0395         if (mvebu_mbus_window_is_free(mbus, win))
0396             return mvebu_mbus_setup_window(mbus, win, base, size,
0397                                remap, target, attr);
0398     }
0399 
0400     return -ENOMEM;
0401 }
0402 
0403 /*
0404  * Debugfs debugging
0405  */
0406 
0407 /* Common function used for Dove, Kirkwood, Armada 370/XP and Orion 5x */
0408 static int mvebu_sdram_debug_show_orion(struct mvebu_mbus_state *mbus,
0409                     struct seq_file *seq, void *v)
0410 {
0411     int i;
0412 
0413     for (i = 0; i < 4; i++) {
0414         u32 basereg = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
0415         u32 sizereg = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
0416         u64 base;
0417         u32 size;
0418 
0419         if (!(sizereg & DDR_SIZE_ENABLED)) {
0420             seq_printf(seq, "[%d] disabled\n", i);
0421             continue;
0422         }
0423 
0424         base = ((u64)basereg & DDR_BASE_CS_HIGH_MASK) << 32;
0425         base |= basereg & DDR_BASE_CS_LOW_MASK;
0426         size = (sizereg | ~DDR_SIZE_MASK);
0427 
0428         seq_printf(seq, "[%d] %016llx - %016llx : cs%d\n",
0429                i, (unsigned long long)base,
0430                (unsigned long long)base + size + 1,
0431                (sizereg & DDR_SIZE_CS_MASK) >> DDR_SIZE_CS_SHIFT);
0432     }
0433 
0434     return 0;
0435 }
0436 
0437 /* Special function for Dove */
0438 static int mvebu_sdram_debug_show_dove(struct mvebu_mbus_state *mbus,
0439                        struct seq_file *seq, void *v)
0440 {
0441     int i;
0442 
0443     for (i = 0; i < 2; i++) {
0444         u32 map = readl(mbus->sdramwins_base + DOVE_DDR_BASE_CS_OFF(i));
0445         u64 base;
0446         u32 size;
0447 
0448         if (!(map & 1)) {
0449             seq_printf(seq, "[%d] disabled\n", i);
0450             continue;
0451         }
0452 
0453         base = map & 0xff800000;
0454         size = 0x100000 << (((map & 0x000f0000) >> 16) - 4);
0455 
0456         seq_printf(seq, "[%d] %016llx - %016llx : cs%d\n",
0457                i, (unsigned long long)base,
0458                (unsigned long long)base + size, i);
0459     }
0460 
0461     return 0;
0462 }
0463 
0464 static int mvebu_sdram_debug_show(struct seq_file *seq, void *v)
0465 {
0466     struct mvebu_mbus_state *mbus = &mbus_state;
0467     return mbus->soc->show_cpu_target(mbus, seq, v);
0468 }
0469 
0470 static int mvebu_sdram_debug_open(struct inode *inode, struct file *file)
0471 {
0472     return single_open(file, mvebu_sdram_debug_show, inode->i_private);
0473 }
0474 
0475 static const struct file_operations mvebu_sdram_debug_fops = {
0476     .open = mvebu_sdram_debug_open,
0477     .read = seq_read,
0478     .llseek = seq_lseek,
0479     .release = single_release,
0480 };
0481 
0482 static int mvebu_devs_debug_show(struct seq_file *seq, void *v)
0483 {
0484     struct mvebu_mbus_state *mbus = &mbus_state;
0485     int win;
0486 
0487     for (win = 0; win < mbus->soc->num_wins; win++) {
0488         u64 wbase, wremap;
0489         u32 wsize;
0490         u8 wtarget, wattr;
0491         int enabled;
0492 
0493         mvebu_mbus_read_window(mbus, win,
0494                        &enabled, &wbase, &wsize,
0495                        &wtarget, &wattr, &wremap);
0496 
0497         if (!enabled) {
0498             seq_printf(seq, "[%02d] disabled\n", win);
0499             continue;
0500         }
0501 
0502         seq_printf(seq, "[%02d] %016llx - %016llx : %04x:%04x",
0503                win, (unsigned long long)wbase,
0504                (unsigned long long)(wbase + wsize), wtarget, wattr);
0505 
0506         if (!is_power_of_2(wsize) ||
0507             ((wbase & (u64)(wsize - 1)) != 0))
0508             seq_puts(seq, " (Invalid base/size!!)");
0509 
0510         if (mvebu_mbus_window_is_remappable(mbus, win)) {
0511             seq_printf(seq, " (remap %016llx)\n",
0512                    (unsigned long long)wremap);
0513         } else
0514             seq_printf(seq, "\n");
0515     }
0516 
0517     return 0;
0518 }
0519 
0520 static int mvebu_devs_debug_open(struct inode *inode, struct file *file)
0521 {
0522     return single_open(file, mvebu_devs_debug_show, inode->i_private);
0523 }
0524 
0525 static const struct file_operations mvebu_devs_debug_fops = {
0526     .open = mvebu_devs_debug_open,
0527     .read = seq_read,
0528     .llseek = seq_lseek,
0529     .release = single_release,
0530 };
0531 
0532 /*
0533  * SoC-specific functions and definitions
0534  */
0535 
0536 static unsigned int generic_mbus_win_cfg_offset(int win)
0537 {
0538     return win << 4;
0539 }
0540 
0541 static unsigned int armada_370_xp_mbus_win_cfg_offset(int win)
0542 {
0543     /* The register layout is a bit annoying and the below code
0544      * tries to cope with it.
0545      * - At offset 0x0, there are the registers for the first 8
0546      *   windows, with 4 registers of 32 bits per window (ctrl,
0547      *   base, remap low, remap high)
0548      * - Then at offset 0x80, there is a hole of 0x10 bytes for
0549      *   the internal registers base address and internal units
0550      *   sync barrier register.
0551      * - Then at offset 0x90, there the registers for 12
0552      *   windows, with only 2 registers of 32 bits per window
0553      *   (ctrl, base).
0554      */
0555     if (win < 8)
0556         return win << 4;
0557     else
0558         return 0x90 + ((win - 8) << 3);
0559 }
0560 
0561 static unsigned int mv78xx0_mbus_win_cfg_offset(int win)
0562 {
0563     if (win < 8)
0564         return win << 4;
0565     else
0566         return 0x900 + ((win - 8) << 4);
0567 }
0568 
0569 static unsigned int generic_mbus_win_remap_2_offset(int win)
0570 {
0571     if (win < 2)
0572         return generic_mbus_win_cfg_offset(win);
0573     else
0574         return MVEBU_MBUS_NO_REMAP;
0575 }
0576 
0577 static unsigned int generic_mbus_win_remap_4_offset(int win)
0578 {
0579     if (win < 4)
0580         return generic_mbus_win_cfg_offset(win);
0581     else
0582         return MVEBU_MBUS_NO_REMAP;
0583 }
0584 
0585 static unsigned int generic_mbus_win_remap_8_offset(int win)
0586 {
0587     if (win < 8)
0588         return generic_mbus_win_cfg_offset(win);
0589     else
0590         return MVEBU_MBUS_NO_REMAP;
0591 }
0592 
0593 static unsigned int armada_xp_mbus_win_remap_offset(int win)
0594 {
0595     if (win < 8)
0596         return generic_mbus_win_cfg_offset(win);
0597     else if (win == 13)
0598         return 0xF0 - WIN_REMAP_LO_OFF;
0599     else
0600         return MVEBU_MBUS_NO_REMAP;
0601 }
0602 
0603 /*
0604  * Use the memblock information to find the MBus bridge hole in the
0605  * physical address space.
0606  */
0607 static void __init
0608 mvebu_mbus_find_bridge_hole(uint64_t *start, uint64_t *end)
0609 {
0610     phys_addr_t reg_start, reg_end;
0611     uint64_t i, s = 0;
0612 
0613     for_each_mem_range(i, &reg_start, &reg_end) {
0614         /*
0615          * This part of the memory is above 4 GB, so we don't
0616          * care for the MBus bridge hole.
0617          */
0618         if ((u64)reg_start >= 0x100000000ULL)
0619             continue;
0620 
0621         /*
0622          * The MBus bridge hole is at the end of the RAM under
0623          * the 4 GB limit.
0624          */
0625         if (reg_end > s)
0626             s = reg_end;
0627     }
0628 
0629     *start = s;
0630     *end = 0x100000000ULL;
0631 }
0632 
0633 /*
0634  * This function fills in the mvebu_mbus_dram_info_nooverlap data
0635  * structure, by looking at the mvebu_mbus_dram_info data, and
0636  * removing the parts of it that overlap with I/O windows.
0637  */
0638 static void __init
0639 mvebu_mbus_setup_cpu_target_nooverlap(struct mvebu_mbus_state *mbus)
0640 {
0641     uint64_t mbus_bridge_base, mbus_bridge_end;
0642     int cs_nooverlap = 0;
0643     int i;
0644 
0645     mvebu_mbus_find_bridge_hole(&mbus_bridge_base, &mbus_bridge_end);
0646 
0647     for (i = 0; i < mvebu_mbus_dram_info.num_cs; i++) {
0648         struct mbus_dram_window *w;
0649         u64 base, size, end;
0650 
0651         w = &mvebu_mbus_dram_info.cs[i];
0652         base = w->base;
0653         size = w->size;
0654         end = base + size;
0655 
0656         /*
0657          * The CS is fully enclosed inside the MBus bridge
0658          * area, so ignore it.
0659          */
0660         if (base >= mbus_bridge_base && end <= mbus_bridge_end)
0661             continue;
0662 
0663         /*
0664          * Beginning of CS overlaps with end of MBus, raise CS
0665          * base address, and shrink its size.
0666          */
0667         if (base >= mbus_bridge_base && end > mbus_bridge_end) {
0668             size -= mbus_bridge_end - base;
0669             base = mbus_bridge_end;
0670         }
0671 
0672         /*
0673          * End of CS overlaps with beginning of MBus, shrink
0674          * CS size.
0675          */
0676         if (base < mbus_bridge_base && end > mbus_bridge_base)
0677             size -= end - mbus_bridge_base;
0678 
0679         w = &mvebu_mbus_dram_info_nooverlap.cs[cs_nooverlap++];
0680         w->cs_index = i;
0681         w->mbus_attr = 0xf & ~(1 << i);
0682         if (mbus->hw_io_coherency)
0683             w->mbus_attr |= ATTR_HW_COHERENCY;
0684         w->base = base;
0685         w->size = size;
0686     }
0687 
0688     mvebu_mbus_dram_info_nooverlap.mbus_dram_target_id = TARGET_DDR;
0689     mvebu_mbus_dram_info_nooverlap.num_cs = cs_nooverlap;
0690 }
0691 
0692 static void __init
0693 mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
0694 {
0695     int i;
0696     int cs;
0697 
0698     mvebu_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
0699 
0700     for (i = 0, cs = 0; i < 4; i++) {
0701         u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
0702         u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
0703 
0704         /*
0705          * We only take care of entries for which the chip
0706          * select is enabled, and that don't have high base
0707          * address bits set (devices can only access the first
0708          * 32 bits of the memory).
0709          */
0710         if ((size & DDR_SIZE_ENABLED) &&
0711             !(base & DDR_BASE_CS_HIGH_MASK)) {
0712             struct mbus_dram_window *w;
0713 
0714             w = &mvebu_mbus_dram_info.cs[cs++];
0715             w->cs_index = i;
0716             w->mbus_attr = 0xf & ~(1 << i);
0717             if (mbus->hw_io_coherency)
0718                 w->mbus_attr |= ATTR_HW_COHERENCY;
0719             w->base = base & DDR_BASE_CS_LOW_MASK;
0720             w->size = (u64)(size | ~DDR_SIZE_MASK) + 1;
0721         }
0722     }
0723     mvebu_mbus_dram_info.num_cs = cs;
0724 }
0725 
0726 static int
0727 mvebu_mbus_default_save_cpu_target(struct mvebu_mbus_state *mbus,
0728                    u32 __iomem *store_addr)
0729 {
0730     int i;
0731 
0732     for (i = 0; i < 4; i++) {
0733         u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
0734         u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
0735 
0736         writel(mbus->sdramwins_phys_base + DDR_BASE_CS_OFF(i),
0737                store_addr++);
0738         writel(base, store_addr++);
0739         writel(mbus->sdramwins_phys_base + DDR_SIZE_CS_OFF(i),
0740                store_addr++);
0741         writel(size, store_addr++);
0742     }
0743 
0744     /* We've written 16 words to the store address */
0745     return 16;
0746 }
0747 
0748 static void __init
0749 mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus)
0750 {
0751     int i;
0752     int cs;
0753 
0754     mvebu_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
0755 
0756     for (i = 0, cs = 0; i < 2; i++) {
0757         u32 map = readl(mbus->sdramwins_base + DOVE_DDR_BASE_CS_OFF(i));
0758 
0759         /*
0760          * Chip select enabled?
0761          */
0762         if (map & 1) {
0763             struct mbus_dram_window *w;
0764 
0765             w = &mvebu_mbus_dram_info.cs[cs++];
0766             w->cs_index = i;
0767             w->mbus_attr = 0; /* CS address decoding done inside */
0768                       /* the DDR controller, no need to  */
0769                       /* provide attributes */
0770             w->base = map & 0xff800000;
0771             w->size = 0x100000 << (((map & 0x000f0000) >> 16) - 4);
0772         }
0773     }
0774 
0775     mvebu_mbus_dram_info.num_cs = cs;
0776 }
0777 
0778 static int
0779 mvebu_mbus_dove_save_cpu_target(struct mvebu_mbus_state *mbus,
0780                 u32 __iomem *store_addr)
0781 {
0782     int i;
0783 
0784     for (i = 0; i < 2; i++) {
0785         u32 map = readl(mbus->sdramwins_base + DOVE_DDR_BASE_CS_OFF(i));
0786 
0787         writel(mbus->sdramwins_phys_base + DOVE_DDR_BASE_CS_OFF(i),
0788                store_addr++);
0789         writel(map, store_addr++);
0790     }
0791 
0792     /* We've written 4 words to the store address */
0793     return 4;
0794 }
0795 
0796 int mvebu_mbus_save_cpu_target(u32 __iomem *store_addr)
0797 {
0798     return mbus_state.soc->save_cpu_target(&mbus_state, store_addr);
0799 }
0800 
0801 static const struct mvebu_mbus_soc_data armada_370_mbus_data = {
0802     .num_wins            = 20,
0803     .has_mbus_bridge     = true,
0804     .win_cfg_offset      = armada_370_xp_mbus_win_cfg_offset,
0805     .win_remap_offset    = generic_mbus_win_remap_8_offset,
0806     .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
0807     .show_cpu_target     = mvebu_sdram_debug_show_orion,
0808     .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
0809 };
0810 
0811 static const struct mvebu_mbus_soc_data armada_xp_mbus_data = {
0812     .num_wins            = 20,
0813     .has_mbus_bridge     = true,
0814     .win_cfg_offset      = armada_370_xp_mbus_win_cfg_offset,
0815     .win_remap_offset    = armada_xp_mbus_win_remap_offset,
0816     .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
0817     .show_cpu_target     = mvebu_sdram_debug_show_orion,
0818     .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
0819 };
0820 
0821 static const struct mvebu_mbus_soc_data kirkwood_mbus_data = {
0822     .num_wins            = 8,
0823     .win_cfg_offset      = generic_mbus_win_cfg_offset,
0824     .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
0825     .win_remap_offset    = generic_mbus_win_remap_4_offset,
0826     .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
0827     .show_cpu_target     = mvebu_sdram_debug_show_orion,
0828 };
0829 
0830 static const struct mvebu_mbus_soc_data dove_mbus_data = {
0831     .num_wins            = 8,
0832     .win_cfg_offset      = generic_mbus_win_cfg_offset,
0833     .save_cpu_target     = mvebu_mbus_dove_save_cpu_target,
0834     .win_remap_offset    = generic_mbus_win_remap_4_offset,
0835     .setup_cpu_target    = mvebu_mbus_dove_setup_cpu_target,
0836     .show_cpu_target     = mvebu_sdram_debug_show_dove,
0837 };
0838 
0839 /*
0840  * Some variants of Orion5x have 4 remappable windows, some other have
0841  * only two of them.
0842  */
0843 static const struct mvebu_mbus_soc_data orion5x_4win_mbus_data = {
0844     .num_wins            = 8,
0845     .win_cfg_offset      = generic_mbus_win_cfg_offset,
0846     .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
0847     .win_remap_offset    = generic_mbus_win_remap_4_offset,
0848     .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
0849     .show_cpu_target     = mvebu_sdram_debug_show_orion,
0850 };
0851 
0852 static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = {
0853     .num_wins            = 8,
0854     .win_cfg_offset      = generic_mbus_win_cfg_offset,
0855     .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
0856     .win_remap_offset    = generic_mbus_win_remap_2_offset,
0857     .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
0858     .show_cpu_target     = mvebu_sdram_debug_show_orion,
0859 };
0860 
0861 static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
0862     .num_wins            = 14,
0863     .win_cfg_offset      = mv78xx0_mbus_win_cfg_offset,
0864     .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
0865     .win_remap_offset    = generic_mbus_win_remap_8_offset,
0866     .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
0867     .show_cpu_target     = mvebu_sdram_debug_show_orion,
0868 };
0869 
0870 static const struct of_device_id of_mvebu_mbus_ids[] = {
0871     { .compatible = "marvell,armada370-mbus",
0872       .data = &armada_370_mbus_data, },
0873     { .compatible = "marvell,armada375-mbus",
0874       .data = &armada_xp_mbus_data, },
0875     { .compatible = "marvell,armada380-mbus",
0876       .data = &armada_xp_mbus_data, },
0877     { .compatible = "marvell,armadaxp-mbus",
0878       .data = &armada_xp_mbus_data, },
0879     { .compatible = "marvell,kirkwood-mbus",
0880       .data = &kirkwood_mbus_data, },
0881     { .compatible = "marvell,dove-mbus",
0882       .data = &dove_mbus_data, },
0883     { .compatible = "marvell,orion5x-88f5281-mbus",
0884       .data = &orion5x_4win_mbus_data, },
0885     { .compatible = "marvell,orion5x-88f5182-mbus",
0886       .data = &orion5x_2win_mbus_data, },
0887     { .compatible = "marvell,orion5x-88f5181-mbus",
0888       .data = &orion5x_2win_mbus_data, },
0889     { .compatible = "marvell,orion5x-88f6183-mbus",
0890       .data = &orion5x_4win_mbus_data, },
0891     { .compatible = "marvell,mv78xx0-mbus",
0892       .data = &mv78xx0_mbus_data, },
0893     { },
0894 };
0895 
0896 /*
0897  * Public API of the driver
0898  */
0899 int mvebu_mbus_add_window_remap_by_id(unsigned int target,
0900                       unsigned int attribute,
0901                       phys_addr_t base, size_t size,
0902                       phys_addr_t remap)
0903 {
0904     struct mvebu_mbus_state *s = &mbus_state;
0905 
0906     if (!mvebu_mbus_window_conflicts(s, base, size, target, attribute)) {
0907         pr_err("cannot add window '%x:%x', conflicts with another window\n",
0908                target, attribute);
0909         return -EINVAL;
0910     }
0911 
0912     return mvebu_mbus_alloc_window(s, base, size, remap, target, attribute);
0913 }
0914 EXPORT_SYMBOL_GPL(mvebu_mbus_add_window_remap_by_id);
0915 
0916 int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
0917                 phys_addr_t base, size_t size)
0918 {
0919     return mvebu_mbus_add_window_remap_by_id(target, attribute, base,
0920                          size, MVEBU_MBUS_NO_REMAP);
0921 }
0922 EXPORT_SYMBOL_GPL(mvebu_mbus_add_window_by_id);
0923 
0924 int mvebu_mbus_del_window(phys_addr_t base, size_t size)
0925 {
0926     int win;
0927 
0928     win = mvebu_mbus_find_window(&mbus_state, base, size);
0929     if (win < 0)
0930         return win;
0931 
0932     mvebu_mbus_disable_window(&mbus_state, win);
0933     return 0;
0934 }
0935 EXPORT_SYMBOL_GPL(mvebu_mbus_del_window);
0936 
0937 void mvebu_mbus_get_pcie_mem_aperture(struct resource *res)
0938 {
0939     if (!res)
0940         return;
0941     *res = mbus_state.pcie_mem_aperture;
0942 }
0943 EXPORT_SYMBOL_GPL(mvebu_mbus_get_pcie_mem_aperture);
0944 
0945 void mvebu_mbus_get_pcie_io_aperture(struct resource *res)
0946 {
0947     if (!res)
0948         return;
0949     *res = mbus_state.pcie_io_aperture;
0950 }
0951 EXPORT_SYMBOL_GPL(mvebu_mbus_get_pcie_io_aperture);
0952 
0953 int mvebu_mbus_get_dram_win_info(phys_addr_t phyaddr, u8 *target, u8 *attr)
0954 {
0955     const struct mbus_dram_target_info *dram;
0956     int i;
0957 
0958     /* Get dram info */
0959     dram = mv_mbus_dram_info();
0960     if (!dram) {
0961         pr_err("missing DRAM information\n");
0962         return -ENODEV;
0963     }
0964 
0965     /* Try to find matching DRAM window for phyaddr */
0966     for (i = 0; i < dram->num_cs; i++) {
0967         const struct mbus_dram_window *cs = dram->cs + i;
0968 
0969         if (cs->base <= phyaddr &&
0970             phyaddr <= (cs->base + cs->size - 1)) {
0971             *target = dram->mbus_dram_target_id;
0972             *attr = cs->mbus_attr;
0973             return 0;
0974         }
0975     }
0976 
0977     pr_err("invalid dram address %pa\n", &phyaddr);
0978     return -EINVAL;
0979 }
0980 EXPORT_SYMBOL_GPL(mvebu_mbus_get_dram_win_info);
0981 
0982 int mvebu_mbus_get_io_win_info(phys_addr_t phyaddr, u32 *size, u8 *target,
0983                    u8 *attr)
0984 {
0985     int win;
0986 
0987     for (win = 0; win < mbus_state.soc->num_wins; win++) {
0988         u64 wbase;
0989         int enabled;
0990 
0991         mvebu_mbus_read_window(&mbus_state, win, &enabled, &wbase,
0992                        size, target, attr, NULL);
0993 
0994         if (!enabled)
0995             continue;
0996 
0997         if (wbase <= phyaddr && phyaddr <= wbase + *size)
0998             return win;
0999     }
1000 
1001     return -EINVAL;
1002 }
1003 EXPORT_SYMBOL_GPL(mvebu_mbus_get_io_win_info);
1004 
1005 static __init int mvebu_mbus_debugfs_init(void)
1006 {
1007     struct mvebu_mbus_state *s = &mbus_state;
1008 
1009     /*
1010      * If no base has been initialized, doesn't make sense to
1011      * register the debugfs entries. We may be on a multiplatform
1012      * kernel that isn't running a Marvell EBU SoC.
1013      */
1014     if (!s->mbuswins_base)
1015         return 0;
1016 
1017     s->debugfs_root = debugfs_create_dir("mvebu-mbus", NULL);
1018     if (s->debugfs_root) {
1019         s->debugfs_sdram = debugfs_create_file("sdram", S_IRUGO,
1020                                s->debugfs_root, NULL,
1021                                &mvebu_sdram_debug_fops);
1022         s->debugfs_devs = debugfs_create_file("devices", S_IRUGO,
1023                               s->debugfs_root, NULL,
1024                               &mvebu_devs_debug_fops);
1025     }
1026 
1027     return 0;
1028 }
1029 fs_initcall(mvebu_mbus_debugfs_init);
1030 
1031 static int mvebu_mbus_suspend(void)
1032 {
1033     struct mvebu_mbus_state *s = &mbus_state;
1034     int win;
1035 
1036     if (!s->mbusbridge_base)
1037         return -ENODEV;
1038 
1039     for (win = 0; win < s->soc->num_wins; win++) {
1040         void __iomem *addr = s->mbuswins_base +
1041             s->soc->win_cfg_offset(win);
1042         void __iomem *addr_rmp;
1043 
1044         s->wins[win].base = readl(addr + WIN_BASE_OFF);
1045         s->wins[win].ctrl = readl(addr + WIN_CTRL_OFF);
1046 
1047         if (!mvebu_mbus_window_is_remappable(s, win))
1048             continue;
1049 
1050         addr_rmp = s->mbuswins_base +
1051             s->soc->win_remap_offset(win);
1052 
1053         s->wins[win].remap_lo = readl(addr_rmp + WIN_REMAP_LO_OFF);
1054         s->wins[win].remap_hi = readl(addr_rmp + WIN_REMAP_HI_OFF);
1055     }
1056 
1057     s->mbus_bridge_ctrl = readl(s->mbusbridge_base +
1058                     MBUS_BRIDGE_CTRL_OFF);
1059     s->mbus_bridge_base = readl(s->mbusbridge_base +
1060                     MBUS_BRIDGE_BASE_OFF);
1061 
1062     return 0;
1063 }
1064 
1065 static void mvebu_mbus_resume(void)
1066 {
1067     struct mvebu_mbus_state *s = &mbus_state;
1068     int win;
1069 
1070     writel(s->mbus_bridge_ctrl,
1071            s->mbusbridge_base + MBUS_BRIDGE_CTRL_OFF);
1072     writel(s->mbus_bridge_base,
1073            s->mbusbridge_base + MBUS_BRIDGE_BASE_OFF);
1074 
1075     for (win = 0; win < s->soc->num_wins; win++) {
1076         void __iomem *addr = s->mbuswins_base +
1077             s->soc->win_cfg_offset(win);
1078         void __iomem *addr_rmp;
1079 
1080         writel(s->wins[win].base, addr + WIN_BASE_OFF);
1081         writel(s->wins[win].ctrl, addr + WIN_CTRL_OFF);
1082 
1083         if (!mvebu_mbus_window_is_remappable(s, win))
1084             continue;
1085 
1086         addr_rmp = s->mbuswins_base +
1087             s->soc->win_remap_offset(win);
1088 
1089         writel(s->wins[win].remap_lo, addr_rmp + WIN_REMAP_LO_OFF);
1090         writel(s->wins[win].remap_hi, addr_rmp + WIN_REMAP_HI_OFF);
1091     }
1092 }
1093 
1094 static struct syscore_ops mvebu_mbus_syscore_ops = {
1095     .suspend    = mvebu_mbus_suspend,
1096     .resume     = mvebu_mbus_resume,
1097 };
1098 
1099 static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
1100                      phys_addr_t mbuswins_phys_base,
1101                      size_t mbuswins_size,
1102                      phys_addr_t sdramwins_phys_base,
1103                      size_t sdramwins_size,
1104                      phys_addr_t mbusbridge_phys_base,
1105                      size_t mbusbridge_size,
1106                      bool is_coherent)
1107 {
1108     int win;
1109 
1110     mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size);
1111     if (!mbus->mbuswins_base)
1112         return -ENOMEM;
1113 
1114     mbus->sdramwins_base = ioremap(sdramwins_phys_base, sdramwins_size);
1115     if (!mbus->sdramwins_base) {
1116         iounmap(mbus->mbuswins_base);
1117         return -ENOMEM;
1118     }
1119 
1120     mbus->sdramwins_phys_base = sdramwins_phys_base;
1121 
1122     if (mbusbridge_phys_base) {
1123         mbus->mbusbridge_base = ioremap(mbusbridge_phys_base,
1124                         mbusbridge_size);
1125         if (!mbus->mbusbridge_base) {
1126             iounmap(mbus->sdramwins_base);
1127             iounmap(mbus->mbuswins_base);
1128             return -ENOMEM;
1129         }
1130     } else
1131         mbus->mbusbridge_base = NULL;
1132 
1133     for (win = 0; win < mbus->soc->num_wins; win++)
1134         mvebu_mbus_disable_window(mbus, win);
1135 
1136     mbus->soc->setup_cpu_target(mbus);
1137     mvebu_mbus_setup_cpu_target_nooverlap(mbus);
1138 
1139     if (is_coherent)
1140         writel(UNIT_SYNC_BARRIER_ALL,
1141                mbus->mbuswins_base + UNIT_SYNC_BARRIER_OFF);
1142 
1143     register_syscore_ops(&mvebu_mbus_syscore_ops);
1144 
1145     return 0;
1146 }
1147 
1148 int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
1149                size_t mbuswins_size,
1150                phys_addr_t sdramwins_phys_base,
1151                size_t sdramwins_size)
1152 {
1153     const struct of_device_id *of_id;
1154 
1155     for (of_id = of_mvebu_mbus_ids; of_id->compatible[0]; of_id++)
1156         if (!strcmp(of_id->compatible, soc))
1157             break;
1158 
1159     if (!of_id->compatible[0]) {
1160         pr_err("could not find a matching SoC family\n");
1161         return -ENODEV;
1162     }
1163 
1164     mbus_state.soc = of_id->data;
1165 
1166     return mvebu_mbus_common_init(&mbus_state,
1167             mbuswins_phys_base,
1168             mbuswins_size,
1169             sdramwins_phys_base,
1170             sdramwins_size, 0, 0, false);
1171 }
1172 
1173 #ifdef CONFIG_OF
1174 /*
1175  * The window IDs in the ranges DT property have the following format:
1176  *  - bits 28 to 31: MBus custom field
1177  *  - bits 24 to 27: window target ID
1178  *  - bits 16 to 23: window attribute ID
1179  *  - bits  0 to 15: unused
1180  */
1181 #define CUSTOM(id) (((id) & 0xF0000000) >> 24)
1182 #define TARGET(id) (((id) & 0x0F000000) >> 24)
1183 #define ATTR(id)   (((id) & 0x00FF0000) >> 16)
1184 
1185 static int __init mbus_dt_setup_win(struct mvebu_mbus_state *mbus,
1186                     u32 base, u32 size,
1187                     u8 target, u8 attr)
1188 {
1189     if (!mvebu_mbus_window_conflicts(mbus, base, size, target, attr)) {
1190         pr_err("cannot add window '%04x:%04x', conflicts with another window\n",
1191                target, attr);
1192         return -EBUSY;
1193     }
1194 
1195     if (mvebu_mbus_alloc_window(mbus, base, size, MVEBU_MBUS_NO_REMAP,
1196                     target, attr)) {
1197         pr_err("cannot add window '%04x:%04x', too many windows\n",
1198                target, attr);
1199         return -ENOMEM;
1200     }
1201     return 0;
1202 }
1203 
1204 static int __init
1205 mbus_parse_ranges(struct device_node *node,
1206           int *addr_cells, int *c_addr_cells, int *c_size_cells,
1207           int *cell_count, const __be32 **ranges_start,
1208           const __be32 **ranges_end)
1209 {
1210     const __be32 *prop;
1211     int ranges_len, tuple_len;
1212 
1213     /* Allow a node with no 'ranges' property */
1214     *ranges_start = of_get_property(node, "ranges", &ranges_len);
1215     if (*ranges_start == NULL) {
1216         *addr_cells = *c_addr_cells = *c_size_cells = *cell_count = 0;
1217         *ranges_start = *ranges_end = NULL;
1218         return 0;
1219     }
1220     *ranges_end = *ranges_start + ranges_len / sizeof(__be32);
1221 
1222     *addr_cells = of_n_addr_cells(node);
1223 
1224     prop = of_get_property(node, "#address-cells", NULL);
1225     *c_addr_cells = be32_to_cpup(prop);
1226 
1227     prop = of_get_property(node, "#size-cells", NULL);
1228     *c_size_cells = be32_to_cpup(prop);
1229 
1230     *cell_count = *addr_cells + *c_addr_cells + *c_size_cells;
1231     tuple_len = (*cell_count) * sizeof(__be32);
1232 
1233     if (ranges_len % tuple_len) {
1234         pr_warn("malformed ranges entry '%pOFn'\n", node);
1235         return -EINVAL;
1236     }
1237     return 0;
1238 }
1239 
1240 static int __init mbus_dt_setup(struct mvebu_mbus_state *mbus,
1241                 struct device_node *np)
1242 {
1243     int addr_cells, c_addr_cells, c_size_cells;
1244     int i, ret, cell_count;
1245     const __be32 *r, *ranges_start, *ranges_end;
1246 
1247     ret = mbus_parse_ranges(np, &addr_cells, &c_addr_cells,
1248                 &c_size_cells, &cell_count,
1249                 &ranges_start, &ranges_end);
1250     if (ret < 0)
1251         return ret;
1252 
1253     for (i = 0, r = ranges_start; r < ranges_end; r += cell_count, i++) {
1254         u32 windowid, base, size;
1255         u8 target, attr;
1256 
1257         /*
1258          * An entry with a non-zero custom field do not
1259          * correspond to a static window, so skip it.
1260          */
1261         windowid = of_read_number(r, 1);
1262         if (CUSTOM(windowid))
1263             continue;
1264 
1265         target = TARGET(windowid);
1266         attr = ATTR(windowid);
1267 
1268         base = of_read_number(r + c_addr_cells, addr_cells);
1269         size = of_read_number(r + c_addr_cells + addr_cells,
1270                       c_size_cells);
1271         ret = mbus_dt_setup_win(mbus, base, size, target, attr);
1272         if (ret < 0)
1273             return ret;
1274     }
1275     return 0;
1276 }
1277 
1278 static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
1279                          struct resource *mem,
1280                          struct resource *io)
1281 {
1282     u32 reg[2];
1283     int ret;
1284 
1285     /*
1286      * These are optional, so we make sure that resource_size(x) will
1287      * return 0.
1288      */
1289     memset(mem, 0, sizeof(struct resource));
1290     mem->end = -1;
1291     memset(io, 0, sizeof(struct resource));
1292     io->end = -1;
1293 
1294     ret = of_property_read_u32_array(np, "pcie-mem-aperture", reg, ARRAY_SIZE(reg));
1295     if (!ret) {
1296         mem->start = reg[0];
1297         mem->end = mem->start + reg[1] - 1;
1298         mem->flags = IORESOURCE_MEM;
1299     }
1300 
1301     ret = of_property_read_u32_array(np, "pcie-io-aperture", reg, ARRAY_SIZE(reg));
1302     if (!ret) {
1303         io->start = reg[0];
1304         io->end = io->start + reg[1] - 1;
1305         io->flags = IORESOURCE_IO;
1306     }
1307 }
1308 
1309 int __init mvebu_mbus_dt_init(bool is_coherent)
1310 {
1311     struct resource mbuswins_res, sdramwins_res, mbusbridge_res;
1312     struct device_node *np, *controller;
1313     const struct of_device_id *of_id;
1314     const __be32 *prop;
1315     int ret;
1316 
1317     np = of_find_matching_node_and_match(NULL, of_mvebu_mbus_ids, &of_id);
1318     if (!np) {
1319         pr_err("could not find a matching SoC family\n");
1320         return -ENODEV;
1321     }
1322 
1323     mbus_state.soc = of_id->data;
1324 
1325     prop = of_get_property(np, "controller", NULL);
1326     if (!prop) {
1327         pr_err("required 'controller' property missing\n");
1328         return -EINVAL;
1329     }
1330 
1331     controller = of_find_node_by_phandle(be32_to_cpup(prop));
1332     if (!controller) {
1333         pr_err("could not find an 'mbus-controller' node\n");
1334         return -ENODEV;
1335     }
1336 
1337     if (of_address_to_resource(controller, 0, &mbuswins_res)) {
1338         pr_err("cannot get MBUS register address\n");
1339         return -EINVAL;
1340     }
1341 
1342     if (of_address_to_resource(controller, 1, &sdramwins_res)) {
1343         pr_err("cannot get SDRAM register address\n");
1344         return -EINVAL;
1345     }
1346 
1347     /*
1348      * Set the resource to 0 so that it can be left unmapped by
1349      * mvebu_mbus_common_init() if the DT doesn't carry the
1350      * necessary information. This is needed to preserve backward
1351      * compatibility.
1352      */
1353     memset(&mbusbridge_res, 0, sizeof(mbusbridge_res));
1354 
1355     if (mbus_state.soc->has_mbus_bridge) {
1356         if (of_address_to_resource(controller, 2, &mbusbridge_res))
1357             pr_warn(FW_WARN "deprecated mbus-mvebu Device Tree, suspend/resume will not work\n");
1358     }
1359 
1360     mbus_state.hw_io_coherency = is_coherent;
1361 
1362     /* Get optional pcie-{mem,io}-aperture properties */
1363     mvebu_mbus_get_pcie_resources(np, &mbus_state.pcie_mem_aperture,
1364                       &mbus_state.pcie_io_aperture);
1365 
1366     ret = mvebu_mbus_common_init(&mbus_state,
1367                      mbuswins_res.start,
1368                      resource_size(&mbuswins_res),
1369                      sdramwins_res.start,
1370                      resource_size(&sdramwins_res),
1371                      mbusbridge_res.start,
1372                      resource_size(&mbusbridge_res),
1373                      is_coherent);
1374     if (ret)
1375         return ret;
1376 
1377     /* Setup statically declared windows in the DT */
1378     return mbus_dt_setup(&mbus_state, np);
1379 }
1380 #endif