0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
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
0062
0063 #define TARGET_DDR 0
0064
0065
0066
0067
0068 #define WIN_CTRL_OFF 0x0000
0069 #define WIN_CTRL_ENABLE BIT(0)
0070
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
0102 #define MBUS_BRIDGE_CTRL_OFF 0x0
0103 #define MBUS_BRIDGE_BASE_OFF 0x4
0104
0105
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
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
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
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
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
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
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
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
0266
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
0292
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
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
0405
0406
0407
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
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
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
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
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
0605
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, ®_start, ®_end) {
0614
0615
0616
0617
0618 if ((u64)reg_start >= 0x100000000ULL)
0619 continue;
0620
0621
0622
0623
0624
0625 if (reg_end > s)
0626 s = reg_end;
0627 }
0628
0629 *start = s;
0630 *end = 0x100000000ULL;
0631 }
0632
0633
0634
0635
0636
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
0658
0659
0660 if (base >= mbus_bridge_base && end <= mbus_bridge_end)
0661 continue;
0662
0663
0664
0665
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
0674
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
0706
0707
0708
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
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
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;
0768
0769
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
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
0841
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
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
0959 dram = mv_mbus_dram_info();
0960 if (!dram) {
0961 pr_err("missing DRAM information\n");
0962 return -ENODEV;
0963 }
0964
0965
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
1011
1012
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
1176
1177
1178
1179
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
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
1259
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
1287
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
1349
1350
1351
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
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
1378 return mbus_dt_setup(&mbus_state, np);
1379 }
1380 #endif