import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / ia64 / hp / zx1 / hpzx1_misc.c
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
9
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>
16
17 #include <asm/dma.h>
18 #include <asm/iosapic.h>
19
20 #define PFX
21
22 static int hpzx1_devices;
23
24 struct fake_pci_dev {
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?
29 };
30
31 #define PCI_FAKE_DEV(dev)       ((struct fake_pci_dev *) \
32                                         PCI_CONTROLLER(dev)->platform_data)
33
34 static struct pci_ops *orig_pci_ops;
35
36 #define HP_CFG_RD(sz, bits, name) \
37 static int hp_cfg_read##sz (struct pci_dev *dev, int where, u##bits *value) \
38 { \
39         struct fake_pci_dev *fake_dev; \
40         if (!(fake_dev = PCI_FAKE_DEV(dev))) \
41                 return orig_pci_ops->name(dev, where, value); \
42         \
43         if (where == PCI_BASE_ADDRESS_0) { \
44                 if (fake_dev->sizing) \
45                         *value = ~(fake_dev->csr_size - 1); \
46                 else \
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; \
52         } \
53         switch (where & ~0x7) { \
54                 case 0x48: /* initiates config cycles */ \
55                 case 0x78: /* elroy suspend mode register */ \
56                         *value = 0; \
57                         break; \
58                 default: \
59                         *value = read##sz(fake_dev->mapped_csrs + where); \
60         } \
61         if (where == PCI_COMMAND) \
62                 *value |= PCI_COMMAND_MEMORY; /* SBA omits this */ \
63         return PCIBIOS_SUCCESSFUL; \
64 }
65
66 #define HP_CFG_WR(sz, bits, name) \
67 static int hp_cfg_write##sz (struct pci_dev *dev, int where, u##bits value) \
68 { \
69         struct fake_pci_dev *fake_dev; \
70         \
71         if (!(fake_dev = PCI_FAKE_DEV(dev))) \
72                 return orig_pci_ops->name(dev, where, value); \
73         \
74         if (where == PCI_BASE_ADDRESS_0) { \
75                 if (value == (u##bits) ~0) \
76                         fake_dev->sizing = 1; \
77                 return PCIBIOS_SUCCESSFUL; \
78         } \
79         switch (where & ~0x7) { \
80                 case 0x48: /* initiates config cycles */ \
81                 case 0x78: /* elroy suspend mode register */ \
82                         break; \
83                 default: \
84                         write##sz(value, fake_dev->mapped_csrs + where); \
85         } \
86         return PCIBIOS_SUCCESSFUL; \
87 }
88
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)
95
96 static struct pci_ops hp_pci_conf = {
97         hp_cfg_readb,
98         hp_cfg_readw,
99         hp_cfg_readl,
100         hp_cfg_writeb,
101         hp_cfg_writew,
102         hp_cfg_writel,
103 };
104
105 static void
106 hpzx1_fake_pci_dev(char *name, unsigned int busnum, unsigned long addr, unsigned int size)
107 {
108         struct pci_controller *controller;
109         struct fake_pci_dev *fake;
110         int slot;
111         struct pci_dev *dev;
112         struct pci_bus *b, *bus = NULL;
113         u8 hdr;
114
115         controller = kmalloc(sizeof(*controller), GFP_KERNEL);
116         if (!controller) {
117                 printk(KERN_ERR PFX "No memory for %s (0x%p) sysdata\n", name,
118                         (void *) addr);
119                 return;
120         }
121         memset(controller, 0, sizeof(*controller));
122
123         fake = kmalloc(sizeof(*fake), GFP_KERNEL);
124         if (!fake) {
125                 printk(KERN_ERR PFX "No memory for %s (0x%p) sysdata\n", name,
126                         (void *) addr);
127                 kfree(controller);
128                 return;
129         }
130
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);
135         fake->sizing = 0;
136         controller->platform_data = fake;
137
138         pci_for_each_bus(b)
139                 if (busnum == b->number) {
140                         bus = b;
141                         break;
142                 }
143
144         if (!bus) {
145                 printk(KERN_ERR PFX "No host bus 0x%02x for %s (0x%p)\n",
146                         busnum, name, (void *) addr);
147                 kfree(fake);
148                 kfree(controller);
149                 return;
150         }
151
152         for (slot = 0x1e; slot; slot--)
153                 if (!pci_find_slot(busnum, PCI_DEVFN(slot, 0)))
154                         break;
155
156         if (slot < 0) {
157                 printk(KERN_ERR PFX "No space for %s (0x%p) on bus 0x%02x\n",
158                         name, (void *) addr, busnum);
159                 kfree(fake);
160                 kfree(controller);
161                 return;
162         }
163
164         dev = kmalloc(sizeof(*dev), GFP_KERNEL);
165         if (!dev) {
166                 printk(KERN_ERR PFX "No memory for %s (0x%p)\n", name,
167                         (void *) addr);
168                 kfree(fake);
169                 kfree(controller);
170                 return;
171         }
172
173         bus->ops = &hp_pci_conf;        // replace pci ops for this bus
174
175         memset(dev, 0, sizeof(*dev));
176         dev->bus = bus;
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;
183
184         pci_setup_device(dev);
185
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);
189
190         printk(KERN_INFO PFX "%s at 0x%lx; pci dev %s\n", name, addr,
191                 dev->slot_name);
192
193         hpzx1_devices++;
194 }
195
196 static acpi_status
197 hpzx1_sba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
198 {
199         u64 csr_base = 0, csr_length = 0;
200         acpi_status status;
201         char *name = context;
202         char fullname[16];
203
204         status = acpi_hp_csr_space(obj, &csr_base, &csr_length);
205         if (ACPI_FAILURE(status))
206                 return status;
207
208         /*
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.
212          */
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);
217
218         return AE_OK;
219 }
220
221 static acpi_status
222 hpzx1_lba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
223 {
224         u64 csr_base = 0, csr_length = 0;
225         acpi_status status;
226         acpi_native_uint busnum;
227         char *name = context;
228         char fullname[32];
229
230         status = acpi_hp_csr_space(obj, &csr_base, &csr_length);
231         if (ACPI_FAILURE(status))
232                 return status;
233
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
238         }
239
240         sprintf(fullname, "%s _BBN 0x%02x", name, (unsigned int) busnum);
241         hpzx1_fake_pci_dev(fullname, busnum, csr_base, csr_length);
242
243         return AE_OK;
244 }
245
246 static void
247 hpzx1_acpi_dev_init(void)
248 {
249         extern struct pci_ops *pci_root_ops;
250
251         orig_pci_ops = pci_root_ops;
252
253         /*
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
259          * 0/1.
260          *
261          * HWP0001: Single IOC SBA w/o IOC in namespace
262          * HWP0002: LBA device
263          * HWP0003: AGP LBA device
264          */
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);
268 }
269
270 extern void sba_init(void);
271
272 void
273 hpzx1_pci_fixup (int phase)
274 {
275         iosapic_pci_fixup(phase);
276         switch (phase) {
277               case 0:
278                 /* zx1 has a hardware I/O TLB which lets us DMA from any device to any address */
279                 MAX_DMA_ADDRESS = ~0UL;
280                 break;
281
282               case 1:
283                 hpzx1_acpi_dev_init();
284                 sba_init();
285                 break;
286         }
287 }