mpc10x_common.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. /*
  2. * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge,
  3. * Mem ctlr, EPIC, etc.
  4. *
  5. * Author: Mark A. Greer
  6. * mgreer@mvista.com
  7. *
  8. * 2001 (c) MontaVista, Software, Inc. This file is licensed under
  9. * the terms of the GNU General Public License version 2. This program
  10. * is licensed "as is" without any warranty of any kind, whether express
  11. * or implied.
  12. */
  13. /*
  14. * *** WARNING - A BAT MUST be set to access the PCI config addr/data regs ***
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/init.h>
  18. #include <linux/pci.h>
  19. #include <linux/slab.h>
  20. #include <linux/serial_8250.h>
  21. #include <linux/fsl_devices.h>
  22. #include <linux/device.h>
  23. #include <asm/byteorder.h>
  24. #include <asm/io.h>
  25. #include <asm/irq.h>
  26. #include <asm/uaccess.h>
  27. #include <asm/machdep.h>
  28. #include <asm/pci-bridge.h>
  29. #include <asm/open_pic.h>
  30. #include <asm/mpc10x.h>
  31. #include <asm/ppc_sys.h>
  32. #ifdef CONFIG_MPC10X_OPENPIC
  33. #ifdef CONFIG_EPIC_SERIAL_MODE
  34. #define EPIC_IRQ_BASE (epic_serial_mode ? 16 : 5)
  35. #else
  36. #define EPIC_IRQ_BASE 5
  37. #endif
  38. #define MPC10X_I2C_IRQ (EPIC_IRQ_BASE + NUM_8259_INTERRUPTS)
  39. #define MPC10X_DMA0_IRQ (EPIC_IRQ_BASE + 1 + NUM_8259_INTERRUPTS)
  40. #define MPC10X_DMA1_IRQ (EPIC_IRQ_BASE + 2 + NUM_8259_INTERRUPTS)
  41. #define MPC10X_UART0_IRQ (EPIC_IRQ_BASE + 4 + NUM_8259_INTERRUPTS)
  42. #define MPC10X_UART1_IRQ (EPIC_IRQ_BASE + 5 + NUM_8259_INTERRUPTS)
  43. #else
  44. #define MPC10X_I2C_IRQ -1
  45. #define MPC10X_DMA0_IRQ -1
  46. #define MPC10X_DMA1_IRQ -1
  47. #define MPC10X_UART0_IRQ -1
  48. #define MPC10X_UART1_IRQ -1
  49. #endif
  50. static struct fsl_i2c_platform_data mpc10x_i2c_pdata = {
  51. .device_flags = 0,
  52. };
  53. static struct plat_serial8250_port serial_plat_uart0[] = {
  54. [0] = {
  55. .mapbase = 0x4500,
  56. .iotype = UPIO_MEM,
  57. .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
  58. },
  59. { },
  60. };
  61. static struct plat_serial8250_port serial_plat_uart1[] = {
  62. [0] = {
  63. .mapbase = 0x4600,
  64. .iotype = UPIO_MEM,
  65. .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
  66. },
  67. { },
  68. };
  69. struct platform_device ppc_sys_platform_devices[] = {
  70. [MPC10X_IIC1] = {
  71. .name = "fsl-i2c",
  72. .id = 1,
  73. .dev.platform_data = &mpc10x_i2c_pdata,
  74. .num_resources = 2,
  75. .resource = (struct resource[]) {
  76. {
  77. .start = MPC10X_EUMB_I2C_OFFSET,
  78. .end = MPC10X_EUMB_I2C_OFFSET +
  79. MPC10X_EUMB_I2C_SIZE - 1,
  80. .flags = IORESOURCE_MEM,
  81. },
  82. {
  83. .flags = IORESOURCE_IRQ
  84. },
  85. },
  86. },
  87. [MPC10X_DMA0] = {
  88. .name = "fsl-dma",
  89. .id = 0,
  90. .num_resources = 2,
  91. .resource = (struct resource[]) {
  92. {
  93. .start = MPC10X_EUMB_DMA_OFFSET + 0x10,
  94. .end = MPC10X_EUMB_DMA_OFFSET + 0x1f,
  95. .flags = IORESOURCE_MEM,
  96. },
  97. {
  98. .flags = IORESOURCE_IRQ,
  99. },
  100. },
  101. },
  102. [MPC10X_DMA1] = {
  103. .name = "fsl-dma",
  104. .id = 1,
  105. .num_resources = 2,
  106. .resource = (struct resource[]) {
  107. {
  108. .start = MPC10X_EUMB_DMA_OFFSET + 0x20,
  109. .end = MPC10X_EUMB_DMA_OFFSET + 0x2f,
  110. .flags = IORESOURCE_MEM,
  111. },
  112. {
  113. .flags = IORESOURCE_IRQ,
  114. },
  115. },
  116. },
  117. [MPC10X_DMA1] = {
  118. .name = "fsl-dma",
  119. .id = 1,
  120. .num_resources = 2,
  121. .resource = (struct resource[]) {
  122. {
  123. .start = MPC10X_EUMB_DMA_OFFSET + 0x20,
  124. .end = MPC10X_EUMB_DMA_OFFSET + 0x2f,
  125. .flags = IORESOURCE_MEM,
  126. },
  127. {
  128. .flags = IORESOURCE_IRQ,
  129. },
  130. },
  131. },
  132. [MPC10X_UART0] = {
  133. .name = "serial8250",
  134. .id = PLAT8250_DEV_PLATFORM,
  135. .dev.platform_data = serial_plat_uart0,
  136. },
  137. [MPC10X_UART1] = {
  138. .name = "serial8250",
  139. .id = PLAT8250_DEV_PLATFORM1,
  140. .dev.platform_data = serial_plat_uart1,
  141. },
  142. };
  143. /* We use the PCI ID to match on */
  144. struct ppc_sys_spec *cur_ppc_sys_spec;
  145. struct ppc_sys_spec ppc_sys_specs[] = {
  146. {
  147. .ppc_sys_name = "8245",
  148. .mask = 0xFFFFFFFF,
  149. .value = MPC10X_BRIDGE_8245,
  150. .num_devices = 5,
  151. .device_list = (enum ppc_sys_devices[])
  152. {
  153. MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1, MPC10X_UART0, MPC10X_UART1,
  154. },
  155. },
  156. {
  157. .ppc_sys_name = "8240",
  158. .mask = 0xFFFFFFFF,
  159. .value = MPC10X_BRIDGE_8240,
  160. .num_devices = 3,
  161. .device_list = (enum ppc_sys_devices[])
  162. {
  163. MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1,
  164. },
  165. },
  166. {
  167. .ppc_sys_name = "107",
  168. .mask = 0xFFFFFFFF,
  169. .value = MPC10X_BRIDGE_107,
  170. .num_devices = 3,
  171. .device_list = (enum ppc_sys_devices[])
  172. {
  173. MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1,
  174. },
  175. },
  176. { /* default match */
  177. .ppc_sys_name = "",
  178. .mask = 0x00000000,
  179. .value = 0x00000000,
  180. },
  181. };
  182. /*
  183. * mach_mpc10x_fixup: This function enables DUART mode if it detects
  184. * if it detects two UARTS in the platform device entries.
  185. */
  186. static int __init mach_mpc10x_fixup(struct platform_device *pdev)
  187. {
  188. if (strncmp (pdev->name, "serial8250", 10) == 0 && pdev->id == 1)
  189. writeb(readb(serial_plat_uart1[0].membase + 0x11) | 0x1,
  190. serial_plat_uart1[0].membase + 0x11);
  191. return 0;
  192. }
  193. static int __init mach_mpc10x_init(void)
  194. {
  195. ppc_sys_device_fixup = mach_mpc10x_fixup;
  196. return 0;
  197. }
  198. postcore_initcall(mach_mpc10x_init);
  199. /* Set resources to match bridge memory map */
  200. void __init
  201. mpc10x_bridge_set_resources(int map, struct pci_controller *hose)
  202. {
  203. switch (map) {
  204. case MPC10X_MEM_MAP_A:
  205. pci_init_resource(&hose->io_resource,
  206. 0x00000000,
  207. 0x3f7fffff,
  208. IORESOURCE_IO,
  209. "PCI host bridge");
  210. pci_init_resource (&hose->mem_resources[0],
  211. 0xc0000000,
  212. 0xfeffffff,
  213. IORESOURCE_MEM,
  214. "PCI host bridge");
  215. break;
  216. case MPC10X_MEM_MAP_B:
  217. pci_init_resource(&hose->io_resource,
  218. 0x00000000,
  219. 0x00bfffff,
  220. IORESOURCE_IO,
  221. "PCI host bridge");
  222. pci_init_resource (&hose->mem_resources[0],
  223. 0x80000000,
  224. 0xfcffffff,
  225. IORESOURCE_MEM,
  226. "PCI host bridge");
  227. break;
  228. default:
  229. printk("mpc10x_bridge_set_resources: "
  230. "Invalid map specified\n");
  231. if (ppc_md.progress)
  232. ppc_md.progress("mpc10x:exit1", 0x100);
  233. }
  234. }
  235. /*
  236. * Do some initialization and put the EUMB registers at the specified address
  237. * (also map the EPIC registers into virtual space--OpenPIC_Addr will be set).
  238. *
  239. * The EPIC is not on the 106, only the 8240 and 107.
  240. */
  241. int __init
  242. mpc10x_bridge_init(struct pci_controller *hose,
  243. uint current_map,
  244. uint new_map,
  245. uint phys_eumb_base)
  246. {
  247. int host_bridge, picr1, picr1_bit, i;
  248. ulong pci_config_addr, pci_config_data;
  249. u_char pir, byte;
  250. if (ppc_md.progress) ppc_md.progress("mpc10x:enter", 0x100);
  251. /* Set up for current map so we can get at config regs */
  252. switch (current_map) {
  253. case MPC10X_MEM_MAP_A:
  254. setup_indirect_pci(hose,
  255. MPC10X_MAPA_CNFG_ADDR,
  256. MPC10X_MAPA_CNFG_DATA);
  257. break;
  258. case MPC10X_MEM_MAP_B:
  259. setup_indirect_pci(hose,
  260. MPC10X_MAPB_CNFG_ADDR,
  261. MPC10X_MAPB_CNFG_DATA);
  262. break;
  263. default:
  264. printk("mpc10x_bridge_init: %s\n",
  265. "Invalid current map specified");
  266. if (ppc_md.progress)
  267. ppc_md.progress("mpc10x:exit1", 0x100);
  268. return -1;
  269. }
  270. /* Make sure it's a supported bridge */
  271. early_read_config_dword(hose,
  272. 0,
  273. PCI_DEVFN(0,0),
  274. PCI_VENDOR_ID,
  275. &host_bridge);
  276. switch (host_bridge) {
  277. case MPC10X_BRIDGE_106:
  278. case MPC10X_BRIDGE_8240:
  279. case MPC10X_BRIDGE_107:
  280. case MPC10X_BRIDGE_8245:
  281. break;
  282. default:
  283. if (ppc_md.progress)
  284. ppc_md.progress("mpc10x:exit2", 0x100);
  285. return -1;
  286. }
  287. switch (new_map) {
  288. case MPC10X_MEM_MAP_A:
  289. MPC10X_SETUP_HOSE(hose, A);
  290. pci_config_addr = MPC10X_MAPA_CNFG_ADDR;
  291. pci_config_data = MPC10X_MAPA_CNFG_DATA;
  292. picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_A;
  293. break;
  294. case MPC10X_MEM_MAP_B:
  295. MPC10X_SETUP_HOSE(hose, B);
  296. pci_config_addr = MPC10X_MAPB_CNFG_ADDR;
  297. pci_config_data = MPC10X_MAPB_CNFG_DATA;
  298. picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_B;
  299. break;
  300. default:
  301. printk("mpc10x_bridge_init: %s\n",
  302. "Invalid new map specified");
  303. if (ppc_md.progress)
  304. ppc_md.progress("mpc10x:exit3", 0x100);
  305. return -1;
  306. }
  307. /* Make bridge use the 'new_map', if not already usng it */
  308. if (current_map != new_map) {
  309. early_read_config_dword(hose,
  310. 0,
  311. PCI_DEVFN(0,0),
  312. MPC10X_CFG_PICR1_REG,
  313. &picr1);
  314. picr1 = (picr1 & ~MPC10X_CFG_PICR1_ADDR_MAP_MASK) |
  315. picr1_bit;
  316. early_write_config_dword(hose,
  317. 0,
  318. PCI_DEVFN(0,0),
  319. MPC10X_CFG_PICR1_REG,
  320. picr1);
  321. asm volatile("sync");
  322. /* Undo old mappings & map in new cfg data/addr regs */
  323. iounmap((void *)hose->cfg_addr);
  324. iounmap((void *)hose->cfg_data);
  325. setup_indirect_pci(hose,
  326. pci_config_addr,
  327. pci_config_data);
  328. }
  329. /* Setup resources to match map */
  330. mpc10x_bridge_set_resources(new_map, hose);
  331. /*
  332. * Want processor accesses of 0xFDxxxxxx to be mapped
  333. * to PCI memory space at 0x00000000. Do not want
  334. * host bridge to respond to PCI memory accesses of
  335. * 0xFDxxxxxx. Do not want host bridge to respond
  336. * to PCI memory addresses 0xFD000000-0xFDFFFFFF;
  337. * want processor accesses from 0x000A0000-0x000BFFFF
  338. * to be forwarded to system memory.
  339. *
  340. * Only valid if not in agent mode and using MAP B.
  341. */
  342. if (new_map == MPC10X_MEM_MAP_B) {
  343. early_read_config_byte(hose,
  344. 0,
  345. PCI_DEVFN(0,0),
  346. MPC10X_CFG_MAPB_OPTIONS_REG,
  347. &byte);
  348. byte &= ~(MPC10X_CFG_MAPB_OPTIONS_PFAE |
  349. MPC10X_CFG_MAPB_OPTIONS_PCICH |
  350. MPC10X_CFG_MAPB_OPTIONS_PROCCH);
  351. if (host_bridge != MPC10X_BRIDGE_106) {
  352. byte |= MPC10X_CFG_MAPB_OPTIONS_CFAE;
  353. }
  354. early_write_config_byte(hose,
  355. 0,
  356. PCI_DEVFN(0,0),
  357. MPC10X_CFG_MAPB_OPTIONS_REG,
  358. byte);
  359. }
  360. if (host_bridge != MPC10X_BRIDGE_106) {
  361. early_read_config_byte(hose,
  362. 0,
  363. PCI_DEVFN(0,0),
  364. MPC10X_CFG_PIR_REG,
  365. &pir);
  366. if (pir != MPC10X_CFG_PIR_HOST_BRIDGE) {
  367. printk("Host bridge in Agent mode\n");
  368. /* Read or Set LMBAR & PCSRBAR? */
  369. }
  370. /* Set base addr of the 8240/107 EUMB. */
  371. early_write_config_dword(hose,
  372. 0,
  373. PCI_DEVFN(0,0),
  374. MPC10X_CFG_EUMBBAR,
  375. phys_eumb_base);
  376. #ifdef CONFIG_MPC10X_OPENPIC
  377. /* Map EPIC register part of EUMB into vitual memory - PCORE
  378. uses an i8259 instead of EPIC. */
  379. OpenPIC_Addr =
  380. ioremap(phys_eumb_base + MPC10X_EUMB_EPIC_OFFSET,
  381. MPC10X_EUMB_EPIC_SIZE);
  382. #endif
  383. }
  384. #ifdef CONFIG_MPC10X_STORE_GATHERING
  385. mpc10x_enable_store_gathering(hose);
  386. #else
  387. mpc10x_disable_store_gathering(hose);
  388. #endif
  389. /* setup platform devices for MPC10x bridges */
  390. identify_ppc_sys_by_id (host_bridge);
  391. for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
  392. unsigned int dev_id = cur_ppc_sys_spec->device_list[i];
  393. ppc_sys_fixup_mem_resource(&ppc_sys_platform_devices[dev_id],
  394. phys_eumb_base);
  395. }
  396. /* IRQ's are determined at runtime */
  397. ppc_sys_platform_devices[MPC10X_IIC1].resource[1].start = MPC10X_I2C_IRQ;
  398. ppc_sys_platform_devices[MPC10X_IIC1].resource[1].end = MPC10X_I2C_IRQ;
  399. ppc_sys_platform_devices[MPC10X_DMA0].resource[1].start = MPC10X_DMA0_IRQ;
  400. ppc_sys_platform_devices[MPC10X_DMA0].resource[1].end = MPC10X_DMA0_IRQ;
  401. ppc_sys_platform_devices[MPC10X_DMA1].resource[1].start = MPC10X_DMA1_IRQ;
  402. ppc_sys_platform_devices[MPC10X_DMA1].resource[1].end = MPC10X_DMA1_IRQ;
  403. serial_plat_uart0[0].mapbase += phys_eumb_base;
  404. serial_plat_uart0[0].irq = MPC10X_UART0_IRQ;
  405. serial_plat_uart0[0].membase = ioremap(serial_plat_uart0[0].mapbase, 0x100);
  406. serial_plat_uart1[0].mapbase += phys_eumb_base;
  407. serial_plat_uart1[0].irq = MPC10X_UART1_IRQ;
  408. serial_plat_uart1[0].membase = ioremap(serial_plat_uart1[0].mapbase, 0x100);
  409. /*
  410. * 8240 erratum 26, 8241/8245 erratum 29, 107 erratum 23: speculative
  411. * PCI reads may return stale data so turn off.
  412. */
  413. if ((host_bridge == MPC10X_BRIDGE_8240)
  414. || (host_bridge == MPC10X_BRIDGE_8245)
  415. || (host_bridge == MPC10X_BRIDGE_107)) {
  416. early_read_config_dword(hose, 0, PCI_DEVFN(0,0),
  417. MPC10X_CFG_PICR1_REG, &picr1);
  418. picr1 &= ~MPC10X_CFG_PICR1_SPEC_PCI_RD;
  419. early_write_config_dword(hose, 0, PCI_DEVFN(0,0),
  420. MPC10X_CFG_PICR1_REG, picr1);
  421. }
  422. /*
  423. * 8241/8245 erratum 28: PCI reads from local memory may return
  424. * stale data. Workaround by setting PICR2[0] to disable copyback
  425. * optimization. Oddly, the latest available user manual for the
  426. * 8245 (Rev 2., dated 10/2003) says PICR2[0] is reserverd.
  427. */
  428. if (host_bridge == MPC10X_BRIDGE_8245) {
  429. u32 picr2;
  430. early_read_config_dword(hose, 0, PCI_DEVFN(0,0),
  431. MPC10X_CFG_PICR2_REG, &picr2);
  432. picr2 |= MPC10X_CFG_PICR2_COPYBACK_OPT;
  433. early_write_config_dword(hose, 0, PCI_DEVFN(0,0),
  434. MPC10X_CFG_PICR2_REG, picr2);
  435. }
  436. if (ppc_md.progress) ppc_md.progress("mpc10x:exit", 0x100);
  437. return 0;
  438. }
  439. /*
  440. * Need to make our own PCI config space access macros because
  441. * mpc10x_get_mem_size() is called before the data structures are set up for
  442. * the 'early_xxx' and 'indirect_xxx' routines to work.
  443. * Assumes bus 0.
  444. */
  445. #define MPC10X_CFG_read(val, addr, type, op) *val = op((type)(addr))
  446. #define MPC10X_CFG_write(val, addr, type, op) op((type *)(addr), (val))
  447. #define MPC10X_PCI_OP(rw, size, type, op, mask) \
  448. static void \
  449. mpc10x_##rw##_config_##size(uint *cfg_addr, uint *cfg_data, int devfn, int offset, type val) \
  450. { \
  451. out_be32(cfg_addr, \
  452. ((offset & 0xfc) << 24) | (devfn << 16) \
  453. | (0 << 8) | 0x80); \
  454. MPC10X_CFG_##rw(val, cfg_data + (offset & mask), type, op); \
  455. return; \
  456. }
  457. MPC10X_PCI_OP(read, byte, u8 *, in_8, 3)
  458. MPC10X_PCI_OP(read, dword, u32 *, in_le32, 0)
  459. #if 0 /* Not used */
  460. MPC10X_PCI_OP(write, byte, u8, out_8, 3)
  461. MPC10X_PCI_OP(read, word, u16 *, in_le16, 2)
  462. MPC10X_PCI_OP(write, word, u16, out_le16, 2)
  463. MPC10X_PCI_OP(write, dword, u32, out_le32, 0)
  464. #endif
  465. /*
  466. * Read the memory controller registers to determine the amount of memory in
  467. * the system. This assumes that the firmware has correctly set up the memory
  468. * controller registers.
  469. */
  470. unsigned long __init
  471. mpc10x_get_mem_size(uint mem_map)
  472. {
  473. uint *config_addr, *config_data, val;
  474. ulong start, end, total, offset;
  475. int i;
  476. u_char bank_enables;
  477. switch (mem_map) {
  478. case MPC10X_MEM_MAP_A:
  479. config_addr = (uint *)MPC10X_MAPA_CNFG_ADDR;
  480. config_data = (uint *)MPC10X_MAPA_CNFG_DATA;
  481. break;
  482. case MPC10X_MEM_MAP_B:
  483. config_addr = (uint *)MPC10X_MAPB_CNFG_ADDR;
  484. config_data = (uint *)MPC10X_MAPB_CNFG_DATA;
  485. break;
  486. default:
  487. return 0;
  488. }
  489. mpc10x_read_config_byte(config_addr,
  490. config_data,
  491. PCI_DEVFN(0,0),
  492. MPC10X_MCTLR_MEM_BANK_ENABLES,
  493. &bank_enables);
  494. total = 0;
  495. for (i=0; i<8; i++) {
  496. if (bank_enables & (1 << i)) {
  497. offset = MPC10X_MCTLR_MEM_START_1 + ((i > 3) ? 4 : 0);
  498. mpc10x_read_config_dword(config_addr,
  499. config_data,
  500. PCI_DEVFN(0,0),
  501. offset,
  502. &val);
  503. start = (val >> ((i & 3) << 3)) & 0xff;
  504. offset = MPC10X_MCTLR_EXT_MEM_START_1 + ((i>3) ? 4 : 0);
  505. mpc10x_read_config_dword(config_addr,
  506. config_data,
  507. PCI_DEVFN(0,0),
  508. offset,
  509. &val);
  510. val = (val >> ((i & 3) << 3)) & 0x03;
  511. start = (val << 28) | (start << 20);
  512. offset = MPC10X_MCTLR_MEM_END_1 + ((i > 3) ? 4 : 0);
  513. mpc10x_read_config_dword(config_addr,
  514. config_data,
  515. PCI_DEVFN(0,0),
  516. offset,
  517. &val);
  518. end = (val >> ((i & 3) << 3)) & 0xff;
  519. offset = MPC10X_MCTLR_EXT_MEM_END_1 + ((i > 3) ? 4 : 0);
  520. mpc10x_read_config_dword(config_addr,
  521. config_data,
  522. PCI_DEVFN(0,0),
  523. offset,
  524. &val);
  525. val = (val >> ((i & 3) << 3)) & 0x03;
  526. end = (val << 28) | (end << 20) | 0xfffff;
  527. total += (end - start + 1);
  528. }
  529. }
  530. return total;
  531. }
  532. int __init
  533. mpc10x_enable_store_gathering(struct pci_controller *hose)
  534. {
  535. uint picr1;
  536. early_read_config_dword(hose,
  537. 0,
  538. PCI_DEVFN(0,0),
  539. MPC10X_CFG_PICR1_REG,
  540. &picr1);
  541. picr1 |= MPC10X_CFG_PICR1_ST_GATH_EN;
  542. early_write_config_dword(hose,
  543. 0,
  544. PCI_DEVFN(0,0),
  545. MPC10X_CFG_PICR1_REG,
  546. picr1);
  547. return 0;
  548. }
  549. int __init
  550. mpc10x_disable_store_gathering(struct pci_controller *hose)
  551. {
  552. uint picr1;
  553. early_read_config_dword(hose,
  554. 0,
  555. PCI_DEVFN(0,0),
  556. MPC10X_CFG_PICR1_REG,
  557. &picr1);
  558. picr1 &= ~MPC10X_CFG_PICR1_ST_GATH_EN;
  559. early_write_config_dword(hose,
  560. 0,
  561. PCI_DEVFN(0,0),
  562. MPC10X_CFG_PICR1_REG,
  563. picr1);
  564. return 0;
  565. }
  566. #ifdef CONFIG_MPC10X_OPENPIC
  567. void __init mpc10x_set_openpic(void)
  568. {
  569. /* Map external IRQs */
  570. openpic_set_sources(0, EPIC_IRQ_BASE, OpenPIC_Addr + 0x10200);
  571. /* Skip reserved space and map i2c and DMA Ch[01] */
  572. openpic_set_sources(EPIC_IRQ_BASE, 3, OpenPIC_Addr + 0x11020);
  573. /* Skip reserved space and map Message Unit Interrupt (I2O) */
  574. openpic_set_sources(EPIC_IRQ_BASE + 3, 1, OpenPIC_Addr + 0x110C0);
  575. /* Skip reserved space and map Serial Interupts */
  576. openpic_set_sources(EPIC_IRQ_BASE + 4, 2, OpenPIC_Addr + 0x11120);
  577. openpic_init(NUM_8259_INTERRUPTS);
  578. }
  579. #endif