mpc10x_common.c 16 KB

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