2 * Misc. support for HP zx1 chipset support
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>
10 #include <linux/config.h>
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/pci.h>
14 #include <linux/acpi.h>
15 #include <linux/efi.h>
18 #include <asm/iosapic.h>
22 static int hpzx1_devices;
25 unsigned long csr_base;
26 unsigned long csr_size;
27 unsigned long mapped_csrs; // ioremapped
28 int sizing; // in middle of BAR sizing operation?
31 #define PCI_FAKE_DEV(dev) ((struct fake_pci_dev *) \
32 PCI_CONTROLLER(dev)->platform_data)
34 static struct pci_ops *orig_pci_ops;
36 #define HP_CFG_RD(sz, bits, name) \
37 static int hp_cfg_read##sz (struct pci_dev *dev, int where, u##bits *value) \
39 struct fake_pci_dev *fake_dev; \
40 if (!(fake_dev = PCI_FAKE_DEV(dev))) \
41 return orig_pci_ops->name(dev, where, value); \
43 if (where == PCI_BASE_ADDRESS_0) { \
44 if (fake_dev->sizing) \
45 *value = ~(fake_dev->csr_size - 1); \
47 *value = (fake_dev->csr_base & \
48 PCI_BASE_ADDRESS_MEM_MASK) | \
49 PCI_BASE_ADDRESS_SPACE_MEMORY; \
50 fake_dev->sizing = 0; \
51 return PCIBIOS_SUCCESSFUL; \
53 switch (where & ~0x7) { \
54 case 0x48: /* initiates config cycles */ \
55 case 0x78: /* elroy suspend mode register */ \
59 *value = read##sz(fake_dev->mapped_csrs + where); \
61 if (where == PCI_COMMAND) \
62 *value |= PCI_COMMAND_MEMORY; /* SBA omits this */ \
63 return PCIBIOS_SUCCESSFUL; \
66 #define HP_CFG_WR(sz, bits, name) \
67 static int hp_cfg_write##sz (struct pci_dev *dev, int where, u##bits value) \
69 struct fake_pci_dev *fake_dev; \
71 if (!(fake_dev = PCI_FAKE_DEV(dev))) \
72 return orig_pci_ops->name(dev, where, value); \
74 if (where == PCI_BASE_ADDRESS_0) { \
75 if (value == (u##bits) ~0) \
76 fake_dev->sizing = 1; \
77 return PCIBIOS_SUCCESSFUL; \
79 switch (where & ~0x7) { \
80 case 0x48: /* initiates config cycles */ \
81 case 0x78: /* elroy suspend mode register */ \
84 write##sz(value, fake_dev->mapped_csrs + where); \
86 return PCIBIOS_SUCCESSFUL; \
89 HP_CFG_RD(b, 8, read_byte)
90 HP_CFG_RD(w, 16, read_word)
91 HP_CFG_RD(l, 32, read_dword)
92 HP_CFG_WR(b, 8, write_byte)
93 HP_CFG_WR(w, 16, write_word)
94 HP_CFG_WR(l, 32, write_dword)
96 static struct pci_ops hp_pci_conf = {
106 hpzx1_fake_pci_dev(char *name, unsigned int busnum, unsigned long addr, unsigned int size)
108 struct pci_controller *controller;
109 struct fake_pci_dev *fake;
112 struct pci_bus *b, *bus = NULL;
115 controller = kmalloc(sizeof(*controller), GFP_KERNEL);
117 printk(KERN_ERR PFX "No memory for %s (0x%p) sysdata\n", name,
121 memset(controller, 0, sizeof(*controller));
123 fake = kmalloc(sizeof(*fake), GFP_KERNEL);
125 printk(KERN_ERR PFX "No memory for %s (0x%p) sysdata\n", name,
131 memset(fake, 0, sizeof(*fake));
132 fake->csr_base = addr;
133 fake->csr_size = size;
134 fake->mapped_csrs = (unsigned long) ioremap(addr, size);
136 controller->platform_data = fake;
139 if (busnum == b->number) {
145 printk(KERN_ERR PFX "No host bus 0x%02x for %s (0x%p)\n",
146 busnum, name, (void *) addr);
152 for (slot = 0x1e; slot; slot--)
153 if (!pci_find_slot(busnum, PCI_DEVFN(slot, 0)))
157 printk(KERN_ERR PFX "No space for %s (0x%p) on bus 0x%02x\n",
158 name, (void *) addr, busnum);
164 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
166 printk(KERN_ERR PFX "No memory for %s (0x%p)\n", name,
173 bus->ops = &hp_pci_conf; // replace pci ops for this bus
175 memset(dev, 0, sizeof(*dev));
177 dev->sysdata = controller;
178 dev->devfn = PCI_DEVFN(slot, 0);
179 pci_read_config_word(dev, PCI_VENDOR_ID, &dev->vendor);
180 pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
181 pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr);
182 dev->hdr_type = hdr & 0x7f;
184 pci_setup_device(dev);
186 // pci_insert_device() without running /sbin/hotplug
187 list_add_tail(&dev->bus_list, &bus->devices);
188 list_add_tail(&dev->global_list, &pci_devices);
190 printk(KERN_INFO PFX "%s at 0x%lx; pci dev %s\n", name, addr,
197 hpzx1_sba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
199 u64 csr_base = 0, csr_length = 0;
201 char *name = context;
204 status = acpi_hp_csr_space(obj, &csr_base, &csr_length);
205 if (ACPI_FAILURE(status))
209 * Only SBA shows up in ACPI namespace, so its CSR space
210 * includes both SBA and IOC. Make SBA and IOC show up
211 * separately in PCI space.
213 sprintf(fullname, "%s SBA", name);
214 hpzx1_fake_pci_dev(fullname, 0, csr_base, 0x1000);
215 sprintf(fullname, "%s IOC", name);
216 hpzx1_fake_pci_dev(fullname, 0, csr_base + 0x1000, 0x1000);
222 hpzx1_lba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
224 u64 csr_base = 0, csr_length = 0;
226 acpi_native_uint busnum;
227 char *name = context;
230 status = acpi_hp_csr_space(obj, &csr_base, &csr_length);
231 if (ACPI_FAILURE(status))
234 status = acpi_evaluate_integer(obj, METHOD_NAME__BBN, NULL, &busnum);
235 if (ACPI_FAILURE(status)) {
236 printk(KERN_WARNING PFX "evaluate _BBN fail=0x%x\n", status);
237 busnum = 0; // no _BBN; stick it on bus 0
240 sprintf(fullname, "%s _BBN 0x%02x", name, (unsigned int) busnum);
241 hpzx1_fake_pci_dev(fullname, busnum, csr_base, csr_length);
247 hpzx1_acpi_dev_init(void)
249 extern struct pci_ops *pci_root_ops;
251 orig_pci_ops = pci_root_ops;
254 * Make fake PCI devices for the following hardware in the
255 * ACPI namespace. This makes it more convenient for drivers
256 * because they can claim these devices based on PCI
257 * information, rather than needing to know about ACPI. The
258 * 64-bit "HPA" space for this hardware is available as BAR
261 * HWP0001: Single IOC SBA w/o IOC in namespace
262 * HWP0002: LBA device
263 * HWP0003: AGP LBA device
265 acpi_get_devices("HWP0001", hpzx1_sba_probe, "HWP0001", NULL);
266 acpi_get_devices("HWP0002", hpzx1_lba_probe, "HWP0002 PCI LBA", NULL);
267 acpi_get_devices("HWP0003", hpzx1_lba_probe, "HWP0003 AGP LBA", NULL);
270 extern void sba_init(void);
273 hpzx1_pci_fixup (int phase)
275 iosapic_pci_fixup(phase);
278 /* zx1 has a hardware I/O TLB which lets us DMA from any device to any address */
279 MAX_DMA_ADDRESS = ~0UL;
283 hpzx1_acpi_dev_init();