ixdp2x00.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /*
  2. * arch/arm/mach-ixp2000/ixdp2x00.c
  3. *
  4. * Code common to IXDP2400 and IXDP2800 platforms.
  5. *
  6. * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
  7. * Maintainer: Deepak Saxena <dsaxena@plexity.net>
  8. *
  9. * Copyright (C) 2002 Intel Corp.
  10. * Copyright (C) 2003-2004 MontaVista Software, Inc.
  11. *
  12. * This program is free software; you can redistribute it and/or modify it
  13. * under the terms of the GNU General Public License as published by the
  14. * Free Software Foundation; either version 2 of the License, or (at your
  15. * option) any later version.
  16. */
  17. #include <linux/gpio.h>
  18. #include <linux/kernel.h>
  19. #include <linux/init.h>
  20. #include <linux/mm.h>
  21. #include <linux/sched.h>
  22. #include <linux/interrupt.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/bitops.h>
  25. #include <linux/pci.h>
  26. #include <linux/ioport.h>
  27. #include <linux/delay.h>
  28. #include <linux/io.h>
  29. #include <asm/irq.h>
  30. #include <asm/pgtable.h>
  31. #include <asm/page.h>
  32. #include <mach/hardware.h>
  33. #include <asm/mach-types.h>
  34. #include <asm/mach/pci.h>
  35. #include <asm/mach/map.h>
  36. #include <asm/mach/irq.h>
  37. #include <asm/mach/time.h>
  38. #include <asm/mach/flash.h>
  39. #include <asm/mach/arch.h>
  40. #include <mach/gpio-ixp2000.h>
  41. /*************************************************************************
  42. * IXDP2x00 IRQ Initialization
  43. *************************************************************************/
  44. static volatile unsigned long *board_irq_mask;
  45. static volatile unsigned long *board_irq_stat;
  46. static unsigned long board_irq_count;
  47. #ifdef CONFIG_ARCH_IXDP2400
  48. /*
  49. * Slowport configuration for accessing CPLD registers on IXDP2x00
  50. */
  51. static struct slowport_cfg slowport_cpld_cfg = {
  52. .CCR = SLOWPORT_CCR_DIV_2,
  53. .WTC = 0x00000070,
  54. .RTC = 0x00000070,
  55. .PCR = SLOWPORT_MODE_FLASH,
  56. .ADC = SLOWPORT_ADDR_WIDTH_24 | SLOWPORT_DATA_WIDTH_8
  57. };
  58. #endif
  59. static void ixdp2x00_irq_mask(struct irq_data *d)
  60. {
  61. unsigned long dummy;
  62. static struct slowport_cfg old_cfg;
  63. /*
  64. * This is ugly in common code but really don't know
  65. * of a better way to handle it. :(
  66. */
  67. #ifdef CONFIG_ARCH_IXDP2400
  68. if (machine_is_ixdp2400())
  69. ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
  70. #endif
  71. dummy = *board_irq_mask;
  72. dummy |= IXP2000_BOARD_IRQ_MASK(d->irq);
  73. ixp2000_reg_wrb(board_irq_mask, dummy);
  74. #ifdef CONFIG_ARCH_IXDP2400
  75. if (machine_is_ixdp2400())
  76. ixp2000_release_slowport(&old_cfg);
  77. #endif
  78. }
  79. static void ixdp2x00_irq_unmask(struct irq_data *d)
  80. {
  81. unsigned long dummy;
  82. static struct slowport_cfg old_cfg;
  83. #ifdef CONFIG_ARCH_IXDP2400
  84. if (machine_is_ixdp2400())
  85. ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
  86. #endif
  87. dummy = *board_irq_mask;
  88. dummy &= ~IXP2000_BOARD_IRQ_MASK(d->irq);
  89. ixp2000_reg_wrb(board_irq_mask, dummy);
  90. if (machine_is_ixdp2400())
  91. ixp2000_release_slowport(&old_cfg);
  92. }
  93. static void ixdp2x00_irq_handler(unsigned int irq, struct irq_desc *desc)
  94. {
  95. volatile u32 ex_interrupt = 0;
  96. static struct slowport_cfg old_cfg;
  97. int i;
  98. desc->irq_data.chip->irq_mask(&desc->irq_data);
  99. #ifdef CONFIG_ARCH_IXDP2400
  100. if (machine_is_ixdp2400())
  101. ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
  102. #endif
  103. ex_interrupt = *board_irq_stat & 0xff;
  104. if (machine_is_ixdp2400())
  105. ixp2000_release_slowport(&old_cfg);
  106. if(!ex_interrupt) {
  107. printk(KERN_ERR "Spurious IXDP2x00 CPLD interrupt!\n");
  108. return;
  109. }
  110. for(i = 0; i < board_irq_count; i++) {
  111. if(ex_interrupt & (1 << i)) {
  112. int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
  113. generic_handle_irq(cpld_irq);
  114. }
  115. }
  116. desc->irq_data.chip->irq_unmask(&desc->irq_data);
  117. }
  118. static struct irq_chip ixdp2x00_cpld_irq_chip = {
  119. .irq_ack = ixdp2x00_irq_mask,
  120. .irq_mask = ixdp2x00_irq_mask,
  121. .irq_unmask = ixdp2x00_irq_unmask
  122. };
  123. void __init ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_of_irqs)
  124. {
  125. unsigned int irq;
  126. ixp2000_init_irq();
  127. if (!ixdp2x00_master_npu())
  128. return;
  129. board_irq_stat = stat_reg;
  130. board_irq_mask = mask_reg;
  131. board_irq_count = nr_of_irqs;
  132. *board_irq_mask = 0xffffffff;
  133. for(irq = IXP2000_BOARD_IRQ(0); irq < IXP2000_BOARD_IRQ(board_irq_count); irq++) {
  134. irq_set_chip_and_handler(irq, &ixdp2x00_cpld_irq_chip,
  135. handle_level_irq);
  136. set_irq_flags(irq, IRQF_VALID);
  137. }
  138. /* Hook into PCI interrupt */
  139. irq_set_chained_handler(IRQ_IXP2000_PCIB, ixdp2x00_irq_handler);
  140. }
  141. /*************************************************************************
  142. * IXDP2x00 memory map
  143. *************************************************************************/
  144. static struct map_desc ixdp2x00_io_desc __initdata = {
  145. .virtual = IXDP2X00_VIRT_CPLD_BASE,
  146. .pfn = __phys_to_pfn(IXDP2X00_PHYS_CPLD_BASE),
  147. .length = IXDP2X00_CPLD_SIZE,
  148. .type = MT_DEVICE
  149. };
  150. void __init ixdp2x00_map_io(void)
  151. {
  152. ixp2000_map_io();
  153. iotable_init(&ixdp2x00_io_desc, 1);
  154. }
  155. /*************************************************************************
  156. * IXDP2x00-common PCI init
  157. *
  158. * The IXDP2[48]00 has a horrid PCI bus layout. Basically the board
  159. * contains two NPUs (ingress and egress) connected over PCI, both running
  160. * instances of the kernel. So far so good. Peers on the PCI bus running
  161. * Linux is a common design in telecom systems. The problem is that instead
  162. * of all the devices being controlled by a single host, different
  163. * devices are controlled by different NPUs on the same bus, leading to
  164. * multiple hosts on the bus. The exact bus layout looks like:
  165. *
  166. * Bus 0
  167. * Master NPU <-------------------+-------------------> Slave NPU
  168. * |
  169. * |
  170. * P2P
  171. * |
  172. *
  173. * Bus 1 |
  174. * <--+------+---------+---------+------+-->
  175. * | | | | |
  176. * | | | | |
  177. * ... Dev PMC Media Eth0 Eth1 ...
  178. *
  179. * The master controls all but Eth1, which is controlled by the
  180. * slave. What this means is that the both the master and the slave
  181. * have to scan the bus, but only one of them can enumerate the bus.
  182. * In addition, after the bus is scanned, each kernel must remove
  183. * the device(s) it does not control from the PCI dev list otherwise
  184. * a driver on each NPU will try to manage it and we will have horrible
  185. * conflicts. Oh..and the slave NPU needs to see the master NPU
  186. * for Intel's drivers to work properly. Closed source drivers...
  187. *
  188. * The way we deal with this is fairly simple but ugly:
  189. *
  190. * 1) Let master scan and enumerate the bus completely.
  191. * 2) Master deletes Eth1 from device list.
  192. * 3) Slave scans bus and then deletes all but Eth1 (Eth0 on slave)
  193. * from device list.
  194. * 4) Find HW designers and LART them.
  195. *
  196. * The boards also do not do normal PCI IRQ routing, or any sort of
  197. * sensical swizzling, so we just need to check where on the bus a
  198. * device sits and figure out to which CPLD pin the interrupt is routed.
  199. * See ixdp2[48]00.c files.
  200. *
  201. *************************************************************************/
  202. void ixdp2x00_slave_pci_postinit(void)
  203. {
  204. struct pci_dev *dev;
  205. /*
  206. * Remove PMC device is there is one
  207. */
  208. if((dev = pci_get_bus_and_slot(1, IXDP2X00_PMC_DEVFN))) {
  209. pci_stop_and_remove_bus_device(dev);
  210. pci_dev_put(dev);
  211. }
  212. dev = pci_get_bus_and_slot(0, IXDP2X00_21555_DEVFN);
  213. pci_stop_and_remove_bus_device(dev);
  214. pci_dev_put(dev);
  215. }
  216. /**************************************************************************
  217. * IXDP2x00 Machine Setup
  218. *************************************************************************/
  219. static struct flash_platform_data ixdp2x00_platform_data = {
  220. .map_name = "cfi_probe",
  221. .width = 1,
  222. };
  223. static struct ixp2000_flash_data ixdp2x00_flash_data = {
  224. .platform_data = &ixdp2x00_platform_data,
  225. .nr_banks = 1
  226. };
  227. static struct resource ixdp2x00_flash_resource = {
  228. .start = 0xc4000000,
  229. .end = 0xc4000000 + 0x00ffffff,
  230. .flags = IORESOURCE_MEM,
  231. };
  232. static struct platform_device ixdp2x00_flash = {
  233. .name = "IXP2000-Flash",
  234. .id = 0,
  235. .dev = {
  236. .platform_data = &ixdp2x00_flash_data,
  237. },
  238. .num_resources = 1,
  239. .resource = &ixdp2x00_flash_resource,
  240. };
  241. static struct ixp2000_i2c_pins ixdp2x00_i2c_gpio_pins = {
  242. .sda_pin = IXDP2X00_GPIO_SDA,
  243. .scl_pin = IXDP2X00_GPIO_SCL,
  244. };
  245. static struct platform_device ixdp2x00_i2c_controller = {
  246. .name = "IXP2000-I2C",
  247. .id = 0,
  248. .dev = {
  249. .platform_data = &ixdp2x00_i2c_gpio_pins,
  250. },
  251. .num_resources = 0
  252. };
  253. static struct platform_device *ixdp2x00_devices[] __initdata = {
  254. &ixdp2x00_flash,
  255. &ixdp2x00_i2c_controller
  256. };
  257. void __init ixdp2x00_init_machine(void)
  258. {
  259. gpio_line_set(IXDP2X00_GPIO_I2C_ENABLE, 1);
  260. gpio_line_config(IXDP2X00_GPIO_I2C_ENABLE, GPIO_OUT);
  261. platform_add_devices(ixdp2x00_devices, ARRAY_SIZE(ixdp2x00_devices));
  262. ixp2000_uart_init();
  263. }