mv64x60.c 17 KB

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