addr-map.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * arch/arm/mach-orion5x/addr-map.c
  3. *
  4. * Address map functions for Marvell Orion 5x SoCs
  5. *
  6. * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
  7. *
  8. * This file is licensed under the terms of the GNU General Public
  9. * License version 2. This program is licensed "as is" without any
  10. * warranty of any kind, whether express or implied.
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/init.h>
  14. #include <linux/mbus.h>
  15. #include <asm/hardware.h>
  16. #include <asm/io.h>
  17. #include "common.h"
  18. /*
  19. * The Orion has fully programable address map. There's a separate address
  20. * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIE, USB,
  21. * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own
  22. * address decode windows that allow it to access any of the Orion resources.
  23. *
  24. * CPU address decoding --
  25. * Linux assumes that it is the boot loader that already setup the access to
  26. * DDR and internal registers.
  27. * Setup access to PCI and PCI-E IO/MEM space is issued by this file.
  28. * Setup access to various devices located on the device bus interface (e.g.
  29. * flashes, RTC, etc) should be issued by machine-setup.c according to
  30. * specific board population (by using orion5x_setup_*_win()).
  31. *
  32. * Non-CPU Masters address decoding --
  33. * Unlike the CPU, we setup the access from Orion's master interfaces to DDR
  34. * banks only (the typical use case).
  35. * Setup access for each master to DDR is issued by common.c.
  36. *
  37. * Note: although orion_setbits() and orion_clrbits() are not atomic
  38. * no locking is necessary here since code in this file is only called
  39. * at boot time when there is no concurrency issues.
  40. */
  41. /*
  42. * Generic Address Decode Windows bit settings
  43. */
  44. #define TARGET_DDR 0
  45. #define TARGET_DEV_BUS 1
  46. #define TARGET_PCI 3
  47. #define TARGET_PCIE 4
  48. #define ATTR_DDR_CS(n) (((n) ==0) ? 0xe : \
  49. ((n) == 1) ? 0xd : \
  50. ((n) == 2) ? 0xb : \
  51. ((n) == 3) ? 0x7 : 0xf)
  52. #define ATTR_PCIE_MEM 0x59
  53. #define ATTR_PCIE_IO 0x51
  54. #define ATTR_PCIE_WA 0x79
  55. #define ATTR_PCI_MEM 0x59
  56. #define ATTR_PCI_IO 0x51
  57. #define ATTR_DEV_CS0 0x1e
  58. #define ATTR_DEV_CS1 0x1d
  59. #define ATTR_DEV_CS2 0x1b
  60. #define ATTR_DEV_BOOT 0xf
  61. #define WIN_EN 1
  62. /*
  63. * Helpers to get DDR bank info
  64. */
  65. #define DDR_BASE_CS(n) ORION5X_DDR_REG(0x1500 + ((n) * 8))
  66. #define DDR_SIZE_CS(n) ORION5X_DDR_REG(0x1504 + ((n) * 8))
  67. #define DDR_MAX_CS 4
  68. #define DDR_REG_TO_SIZE(reg) (((reg) | 0xffffff) + 1)
  69. #define DDR_REG_TO_BASE(reg) ((reg) & 0xff000000)
  70. #define DDR_BANK_EN 1
  71. /*
  72. * CPU Address Decode Windows registers
  73. */
  74. #define CPU_WIN_CTRL(n) ORION5X_BRIDGE_REG(0x000 | ((n) << 4))
  75. #define CPU_WIN_BASE(n) ORION5X_BRIDGE_REG(0x004 | ((n) << 4))
  76. #define CPU_WIN_REMAP_LO(n) ORION5X_BRIDGE_REG(0x008 | ((n) << 4))
  77. #define CPU_WIN_REMAP_HI(n) ORION5X_BRIDGE_REG(0x00c | ((n) << 4))
  78. /*
  79. * Gigabit Ethernet Address Decode Windows registers
  80. */
  81. #define ETH_WIN_BASE(win) ORION5X_ETH_REG(0x200 + ((win) * 8))
  82. #define ETH_WIN_SIZE(win) ORION5X_ETH_REG(0x204 + ((win) * 8))
  83. #define ETH_WIN_REMAP(win) ORION5X_ETH_REG(0x280 + ((win) * 4))
  84. #define ETH_WIN_EN ORION5X_ETH_REG(0x290)
  85. #define ETH_WIN_PROT ORION5X_ETH_REG(0x294)
  86. #define ETH_MAX_WIN 6
  87. #define ETH_MAX_REMAP_WIN 4
  88. struct mbus_dram_target_info orion5x_mbus_dram_info;
  89. static int __init orion5x_cpu_win_can_remap(int win)
  90. {
  91. u32 dev, rev;
  92. orion5x_pcie_id(&dev, &rev);
  93. if ((dev == MV88F5281_DEV_ID && win < 4)
  94. || (dev == MV88F5182_DEV_ID && win < 2)
  95. || (dev == MV88F5181_DEV_ID && win < 2))
  96. return 1;
  97. return 0;
  98. }
  99. static void __init setup_cpu_win(int win, u32 base, u32 size,
  100. u8 target, u8 attr, int remap)
  101. {
  102. orion5x_write(CPU_WIN_BASE(win), base & 0xffff0000);
  103. orion5x_write(CPU_WIN_CTRL(win),
  104. ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1);
  105. if (orion5x_cpu_win_can_remap(win)) {
  106. if (remap < 0)
  107. remap = base;
  108. orion5x_write(CPU_WIN_REMAP_LO(win), remap & 0xffff0000);
  109. orion5x_write(CPU_WIN_REMAP_HI(win), 0);
  110. }
  111. }
  112. void __init orion5x_setup_cpu_mbus_bridge(void)
  113. {
  114. int i;
  115. int cs;
  116. /*
  117. * First, disable and clear windows.
  118. */
  119. for (i = 0; i < 8; i++) {
  120. orion5x_write(CPU_WIN_BASE(i), 0);
  121. orion5x_write(CPU_WIN_CTRL(i), 0);
  122. if (orion5x_cpu_win_can_remap(i)) {
  123. orion5x_write(CPU_WIN_REMAP_LO(i), 0);
  124. orion5x_write(CPU_WIN_REMAP_HI(i), 0);
  125. }
  126. }
  127. /*
  128. * Setup windows for PCI+PCIe IO+MEM space.
  129. */
  130. setup_cpu_win(0, ORION5X_PCIE_IO_PHYS_BASE, ORION5X_PCIE_IO_SIZE,
  131. TARGET_PCIE, ATTR_PCIE_IO, ORION5X_PCIE_IO_BUS_BASE);
  132. setup_cpu_win(1, ORION5X_PCI_IO_PHYS_BASE, ORION5X_PCI_IO_SIZE,
  133. TARGET_PCI, ATTR_PCI_IO, ORION5X_PCI_IO_BUS_BASE);
  134. setup_cpu_win(2, ORION5X_PCIE_MEM_PHYS_BASE, ORION5X_PCIE_MEM_SIZE,
  135. TARGET_PCIE, ATTR_PCIE_MEM, -1);
  136. setup_cpu_win(3, ORION5X_PCI_MEM_PHYS_BASE, ORION5X_PCI_MEM_SIZE,
  137. TARGET_PCI, ATTR_PCI_MEM, -1);
  138. /*
  139. * Setup MBUS dram target info.
  140. */
  141. orion5x_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
  142. for (i = 0, cs = 0; i < 4; i++) {
  143. u32 base = readl(DDR_BASE_CS(i));
  144. u32 size = readl(DDR_SIZE_CS(i));
  145. /*
  146. * Chip select enabled?
  147. */
  148. if (size & 1) {
  149. struct mbus_dram_window *w;
  150. w = &orion5x_mbus_dram_info.cs[cs++];
  151. w->cs_index = i;
  152. w->mbus_attr = 0xf & ~(1 << i);
  153. w->base = base & 0xff000000;
  154. w->size = (size | 0x00ffffff) + 1;
  155. }
  156. }
  157. orion5x_mbus_dram_info.num_cs = cs;
  158. }
  159. void __init orion5x_setup_dev_boot_win(u32 base, u32 size)
  160. {
  161. setup_cpu_win(4, base, size, TARGET_DEV_BUS, ATTR_DEV_BOOT, -1);
  162. }
  163. void __init orion5x_setup_dev0_win(u32 base, u32 size)
  164. {
  165. setup_cpu_win(5, base, size, TARGET_DEV_BUS, ATTR_DEV_CS0, -1);
  166. }
  167. void __init orion5x_setup_dev1_win(u32 base, u32 size)
  168. {
  169. setup_cpu_win(6, base, size, TARGET_DEV_BUS, ATTR_DEV_CS1, -1);
  170. }
  171. void __init orion5x_setup_dev2_win(u32 base, u32 size)
  172. {
  173. setup_cpu_win(7, base, size, TARGET_DEV_BUS, ATTR_DEV_CS2, -1);
  174. }
  175. void __init orion5x_setup_pcie_wa_win(u32 base, u32 size)
  176. {
  177. setup_cpu_win(7, base, size, TARGET_PCIE, ATTR_PCIE_WA, -1);
  178. }
  179. void __init orion5x_setup_eth_wins(void)
  180. {
  181. int i;
  182. /*
  183. * First, disable and clear windows
  184. */
  185. for (i = 0; i < ETH_MAX_WIN; i++) {
  186. orion5x_write(ETH_WIN_BASE(i), 0);
  187. orion5x_write(ETH_WIN_SIZE(i), 0);
  188. orion5x_setbits(ETH_WIN_EN, 1 << i);
  189. orion5x_clrbits(ETH_WIN_PROT, 0x3 << (i * 2));
  190. if (i < ETH_MAX_REMAP_WIN)
  191. orion5x_write(ETH_WIN_REMAP(i), 0);
  192. }
  193. /*
  194. * Setup windows for DDR banks.
  195. */
  196. for (i = 0; i < DDR_MAX_CS; i++) {
  197. u32 base, size;
  198. size = orion5x_read(DDR_SIZE_CS(i));
  199. base = orion5x_read(DDR_BASE_CS(i));
  200. if (size & DDR_BANK_EN) {
  201. base = DDR_REG_TO_BASE(base);
  202. size = DDR_REG_TO_SIZE(size);
  203. orion5x_write(ETH_WIN_SIZE(i), (size-1) & 0xffff0000);
  204. orion5x_write(ETH_WIN_BASE(i), (base & 0xffff0000) |
  205. (ATTR_DDR_CS(i) << 8) |
  206. TARGET_DDR);
  207. orion5x_clrbits(ETH_WIN_EN, 1 << i);
  208. orion5x_setbits(ETH_WIN_PROT, 0x3 << (i * 2));
  209. }
  210. }
  211. }