hpzx1_misc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Misc. support for HP zx1 chipset support
  3.  *
  4.  * Copyright (C) 2002 Hewlett-Packard Co
  5.  * Copyright (C) 2002 Alex Williamson <alex_williamson@hp.com>
  6.  * Copyright (C) 2002 Bjorn Helgaas <bjorn_helgaas@hp.com>
  7.  */
  8. #include <linux/config.h>
  9. #include <linux/init.h>
  10. #include <linux/kernel.h>
  11. #include <linux/pci.h>
  12. #include <linux/acpi.h>
  13. #include <linux/efi.h>
  14. #include <asm/dma.h>
  15. #include <asm/iosapic.h>
  16. extern acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, acpi_object_list *, unsigned long *);
  17. #define PFX "hpzx1: "
  18. static int hpzx1_devices;
  19. struct fake_pci_dev {
  20. unsigned long csr_base;
  21. unsigned long csr_size;
  22. unsigned long mapped_csrs; // ioremapped
  23. int sizing; // in middle of BAR sizing operation?
  24. };
  25. #define PCI_FAKE_DEV(dev) ((struct fake_pci_dev *) 
  26. PCI_CONTROLLER(dev)->platform_data)
  27. static struct pci_ops *orig_pci_ops;
  28. #define HP_CFG_RD(sz, bits, name) 
  29. static int hp_cfg_read##sz (struct pci_dev *dev, int where, u##bits *value) 
  30. struct fake_pci_dev *fake_dev; 
  31. if (!(fake_dev = PCI_FAKE_DEV(dev))) 
  32. return orig_pci_ops->name(dev, where, value); 
  33. if (where == PCI_BASE_ADDRESS_0) { 
  34. if (fake_dev->sizing) 
  35. *value = ~(fake_dev->csr_size - 1); 
  36. else 
  37. *value = (fake_dev->csr_base & 
  38.     PCI_BASE_ADDRESS_MEM_MASK) | 
  39. PCI_BASE_ADDRESS_SPACE_MEMORY; 
  40. fake_dev->sizing = 0; 
  41. return PCIBIOS_SUCCESSFUL; 
  42. *value = read##sz(fake_dev->mapped_csrs + where); 
  43. if (where == PCI_COMMAND) 
  44. *value |= PCI_COMMAND_MEMORY; /* SBA omits this */ 
  45. return PCIBIOS_SUCCESSFUL; 
  46. }
  47. #define HP_CFG_WR(sz, bits, name) 
  48. static int hp_cfg_write##sz (struct pci_dev *dev, int where, u##bits value) 
  49. struct fake_pci_dev *fake_dev; 
  50. if (!(fake_dev = PCI_FAKE_DEV(dev))) 
  51. return orig_pci_ops->name(dev, where, value); 
  52. if (where == PCI_BASE_ADDRESS_0) { 
  53. if (value == (u##bits) ~0) 
  54. fake_dev->sizing = 1; 
  55. return PCIBIOS_SUCCESSFUL; 
  56. } else 
  57. write##sz(value, fake_dev->mapped_csrs + where); 
  58. return PCIBIOS_SUCCESSFUL; 
  59. }
  60. HP_CFG_RD(b,  8, read_byte)
  61. HP_CFG_RD(w, 16, read_word)
  62. HP_CFG_RD(l, 32, read_dword)
  63. HP_CFG_WR(b,  8, write_byte)
  64. HP_CFG_WR(w, 16, write_word)
  65. HP_CFG_WR(l, 32, write_dword)
  66. static struct pci_ops hp_pci_conf = {
  67. hp_cfg_readb,
  68. hp_cfg_readw,
  69. hp_cfg_readl,
  70. hp_cfg_writeb,
  71. hp_cfg_writew,
  72. hp_cfg_writel,
  73. };
  74. static void
  75. hpzx1_fake_pci_dev(char *name, unsigned int busnum, unsigned long addr, unsigned int size)
  76. {
  77. struct pci_controller *controller;
  78. struct fake_pci_dev *fake;
  79. int slot;
  80. struct pci_dev *dev;
  81. struct pci_bus *b, *bus = NULL;
  82. u8 hdr;
  83. controller = kmalloc(sizeof(*controller), GFP_KERNEL);
  84. if (!controller) {
  85. printk(KERN_ERR PFX "No memory for %s (0x%p) sysdatan", name,
  86. (void *) addr);
  87. return;
  88. }
  89. memset(controller, 0, sizeof(*controller));
  90.         fake = kmalloc(sizeof(*fake), GFP_KERNEL);
  91. if (!fake) {
  92. printk(KERN_ERR PFX "No memory for %s (0x%p) sysdatan", name,
  93. (void *) addr);
  94. kfree(controller);
  95. return;
  96. }
  97. memset(fake, 0, sizeof(*fake));
  98. fake->csr_base = addr;
  99. fake->csr_size = size;
  100. fake->mapped_csrs = (unsigned long) ioremap(addr, size);
  101. fake->sizing = 0;
  102. controller->platform_data = fake;
  103. pci_for_each_bus(b)
  104. if (busnum == b->number) {
  105. bus = b;
  106. break;
  107. }
  108. if (!bus) {
  109. printk(KERN_ERR PFX "No host bus 0x%02x for %s (0x%p)n",
  110. busnum, name, (void *) addr);
  111. kfree(fake);
  112. kfree(controller);
  113. return;
  114. }
  115. for (slot = 0x1e; slot; slot--)
  116. if (!pci_find_slot(busnum, PCI_DEVFN(slot, 0)))
  117. break;
  118. if (slot < 0) {
  119. printk(KERN_ERR PFX "No space for %s (0x%p) on bus 0x%02xn",
  120. name, (void *) addr, busnum);
  121. kfree(fake);
  122. kfree(controller);
  123. return;
  124. }
  125.         dev = kmalloc(sizeof(*dev), GFP_KERNEL);
  126. if (!dev) {
  127. printk(KERN_ERR PFX "No memory for %s (0x%p)n", name,
  128. (void *) addr);
  129. kfree(fake);
  130. kfree(controller);
  131. return;
  132. }
  133. bus->ops = &hp_pci_conf; // replace pci ops for this bus
  134. memset(dev, 0, sizeof(*dev));
  135. dev->bus = bus;
  136. dev->sysdata = controller;
  137. dev->devfn = PCI_DEVFN(slot, 0);
  138. pci_read_config_word(dev, PCI_VENDOR_ID, &dev->vendor);
  139. pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
  140. pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr);
  141. dev->hdr_type = hdr & 0x7f;
  142. pci_setup_device(dev);
  143. // pci_insert_device() without running /sbin/hotplug
  144. list_add_tail(&dev->bus_list, &bus->devices);
  145. list_add_tail(&dev->global_list, &pci_devices);
  146. printk(KERN_INFO PFX "%s at 0x%lx; pci dev %sn", name, addr,
  147. dev->slot_name);
  148. hpzx1_devices++;
  149. }
  150. static acpi_status
  151. hpzx1_sba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
  152. {
  153. u64 csr_base = 0, csr_length = 0;
  154. acpi_status status;
  155. char *name = context;
  156. char fullname[16];
  157. status = acpi_hp_csr_space(obj, &csr_base, &csr_length);
  158. if (ACPI_FAILURE(status))
  159. return status;
  160. /*
  161.  * Only SBA shows up in ACPI namespace, so its CSR space
  162.  * includes both SBA and IOC.  Make SBA and IOC show up
  163.  * separately in PCI space.
  164.  */
  165. sprintf(fullname, "%s SBA", name);
  166. hpzx1_fake_pci_dev(fullname, 0, csr_base, 0x1000);
  167. sprintf(fullname, "%s IOC", name);
  168. hpzx1_fake_pci_dev(fullname, 0, csr_base + 0x1000, 0x1000);
  169. return AE_OK;
  170. }
  171. static acpi_status
  172. hpzx1_lba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
  173. {
  174. u64 csr_base = 0, csr_length = 0;
  175. acpi_status status;
  176. NATIVE_UINT busnum;
  177. char *name = context;
  178. char fullname[32];
  179. status = acpi_hp_csr_space(obj, &csr_base, &csr_length);
  180. if (ACPI_FAILURE(status))
  181. return status;
  182. status = acpi_evaluate_integer(obj, METHOD_NAME__BBN, NULL, &busnum);
  183. if (ACPI_FAILURE(status)) {
  184. printk(KERN_WARNING PFX "evaluate _BBN fail=0x%xn", status);
  185. busnum = 0; // no _BBN; stick it on bus 0
  186. }
  187. sprintf(fullname, "%s _BBN 0x%02x", name, (unsigned int) busnum);
  188. hpzx1_fake_pci_dev(fullname, busnum, csr_base, csr_length);
  189. return AE_OK;
  190. }
  191. static void
  192. hpzx1_acpi_dev_init(void)
  193. {
  194. extern struct pci_ops *pci_root_ops;
  195. orig_pci_ops = pci_root_ops;
  196. /*
  197.  * Make fake PCI devices for the following hardware in the
  198.  * ACPI namespace.  This makes it more convenient for drivers
  199.  * because they can claim these devices based on PCI
  200.  * information, rather than needing to know about ACPI.  The
  201.  * 64-bit "HPA" space for this hardware is available as BAR
  202.  * 0/1.
  203.  *
  204.  * HWP0001: Single IOC SBA w/o IOC in namespace
  205.  * HWP0002: LBA device
  206.  * HWP0003: AGP LBA device
  207.  */
  208. acpi_get_devices("HWP0001", hpzx1_sba_probe, "HWP0001", NULL);
  209. #ifdef CONFIG_IA64_HP_PROTO
  210. if (hpzx1_devices) {
  211. #endif
  212. acpi_get_devices("HWP0002", hpzx1_lba_probe, "HWP0002 PCI LBA", NULL);
  213. acpi_get_devices("HWP0003", hpzx1_lba_probe, "HWP0003 AGP LBA", NULL);
  214. #ifdef CONFIG_IA64_HP_PROTO
  215. }
  216. #define ZX1_FUNC_ID_VALUE    (PCI_DEVICE_ID_HP_ZX1_SBA << 16) | PCI_VENDOR_ID_HP
  217. /*
  218.  * Early protos don't have bridges in the ACPI namespace, so
  219.  * if we didn't find anything, add the things we know are
  220.  * there.
  221.  */
  222. if (hpzx1_devices == 0) {
  223. u64 hpa, csr_base;
  224. csr_base = 0xfed00000UL;
  225. hpa = (u64) ioremap(csr_base, 0x2000);
  226. if (__raw_readl(hpa) == ZX1_FUNC_ID_VALUE) {
  227. hpzx1_fake_pci_dev("HWP0001 SBA", 0, csr_base, 0x1000);
  228. hpzx1_fake_pci_dev("HWP0001 IOC", 0, csr_base + 0x1000,
  229.     0x1000);
  230. csr_base = 0xfed24000UL;
  231. iounmap(hpa);
  232. hpa = (u64) ioremap(csr_base, 0x1000);
  233. hpzx1_fake_pci_dev("HWP0003 AGP LBA", 0x40, csr_base,
  234.     0x1000);
  235. }
  236. iounmap(hpa);
  237. }
  238. #endif
  239. }
  240. extern void sba_init(void);
  241. void
  242. hpzx1_pci_fixup (int phase)
  243. {
  244. iosapic_pci_fixup(phase);
  245. switch (phase) {
  246.       case 0:
  247. /* zx1 has a hardware I/O TLB which lets us DMA from any device to any address */
  248. MAX_DMA_ADDRESS = ~0UL;
  249. break;
  250.       case 1:
  251. hpzx1_acpi_dev_init();
  252. sba_init();
  253. break;
  254. }
  255. }