• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/mn10300/unit-asb2305/
1/* ASB2305 PCI support
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 * Derived from arch/i386/kernel/pci-pc.c
6 *	(c) 1999--2000 Martin Mares <mj@suse.cz>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public Licence
10 * as published by the Free Software Foundation; either version
11 * 2 of the Licence, or (at your option) any later version.
12 */
13#include <linux/types.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/pci.h>
17#include <linux/init.h>
18#include <linux/ioport.h>
19#include <linux/delay.h>
20#include <asm/io.h>
21#include "pci-asb2305.h"
22
23unsigned int pci_probe = 1;
24
25int pcibios_last_bus = -1;
26struct pci_bus *pci_root_bus;
27struct pci_ops *pci_root_ops;
28
29/*
30 * The accessible PCI window does not cover the entire CPU address space, but
31 * there are devices we want to access outside of that window, so we need to
32 * insert specific PCI bus resources instead of using the platform-level bus
33 * resources directly for the PCI root bus.
34 *
35 * These are configured and inserted by pcibios_init() and are attached to the
36 * root bus by pcibios_fixup_bus().
37 */
38static struct resource pci_ioport_resource = {
39	.name	= "PCI IO",
40	.start	= 0xbe000000,
41	.end	= 0xbe03ffff,
42	.flags	= IORESOURCE_IO,
43};
44
45static struct resource pci_iomem_resource = {
46	.name	= "PCI mem",
47	.start	= 0xb8000000,
48	.end	= 0xbbffffff,
49	.flags	= IORESOURCE_MEM,
50};
51
52/*
53 * Functions for accessing PCI configuration space
54 */
55
56#define CONFIG_CMD(bus, devfn, where) \
57	(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
58
59#define MEM_PAGING_REG	(*(volatile __u32 *) 0xBFFFFFF4)
60#define CONFIG_ADDRESS	(*(volatile __u32 *) 0xBFFFFFF8)
61#define CONFIG_DATAL(X)	(*(volatile __u32 *) 0xBFFFFFFC)
62#define CONFIG_DATAW(X)	(*(volatile __u16 *) (0xBFFFFFFC + ((X) & 2)))
63#define CONFIG_DATAB(X)	(*(volatile __u8  *) (0xBFFFFFFC + ((X) & 3)))
64
65#define BRIDGEREGB(X)	(*(volatile __u8  *) (0xBE040000 + (X)))
66#define BRIDGEREGW(X)	(*(volatile __u16 *) (0xBE040000 + (X)))
67#define BRIDGEREGL(X)	(*(volatile __u32 *) (0xBE040000 + (X)))
68
69static inline int __query(const struct pci_bus *bus, unsigned int devfn)
70{
71	return 1;
72}
73
74/*
75 * translate Linuxcentric addresses to PCI bus addresses
76 */
77void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
78			     struct resource *res)
79{
80	if (res->flags & IORESOURCE_IO) {
81		region->start = (res->start & 0x00ffffff);
82		region->end   = (res->end   & 0x00ffffff);
83	}
84
85	if (res->flags & IORESOURCE_MEM) {
86		region->start = (res->start & 0x03ffffff) | MEM_PAGING_REG;
87		region->end   = (res->end   & 0x03ffffff) | MEM_PAGING_REG;
88	}
89
90}
91EXPORT_SYMBOL(pcibios_resource_to_bus);
92
93/*
94 * translate PCI bus addresses to Linuxcentric addresses
95 */
96void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
97			     struct pci_bus_region *region)
98{
99	if (res->flags & IORESOURCE_IO) {
100		res->start = (region->start & 0x00ffffff) | 0xbe000000;
101		res->end   = (region->end   & 0x00ffffff) | 0xbe000000;
102	}
103
104	if (res->flags & IORESOURCE_MEM) {
105		res->start = (region->start & 0x03ffffff) | 0xb8000000;
106		res->end   = (region->end   & 0x03ffffff) | 0xb8000000;
107	}
108
109}
110EXPORT_SYMBOL(pcibios_bus_to_resource);
111
112/*
113 *
114 */
115static int pci_ampci_read_config_byte(struct pci_bus *bus, unsigned int devfn,
116				      int where, u32 *_value)
117{
118	u32 rawval, value;
119
120	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
121		value = BRIDGEREGB(where);
122		__pcbdebug("=> %02hx", &BRIDGEREGL(where), value);
123	} else {
124		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
125		rawval = CONFIG_ADDRESS;
126		value = CONFIG_DATAB(where);
127		if (__query(bus, devfn))
128			__pcidebug("=> %02hx", bus, devfn, where, value);
129	}
130
131	*_value = value;
132	return PCIBIOS_SUCCESSFUL;
133}
134
135static int pci_ampci_read_config_word(struct pci_bus *bus, unsigned int devfn,
136				      int where, u32 *_value)
137{
138	u32 rawval, value;
139
140	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
141		value = BRIDGEREGW(where);
142		__pcbdebug("=> %04hx", &BRIDGEREGL(where), value);
143	} else {
144		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
145		rawval = CONFIG_ADDRESS;
146		value = CONFIG_DATAW(where);
147		if (__query(bus, devfn))
148			__pcidebug("=> %04hx", bus, devfn, where, value);
149	}
150
151	*_value = value;
152	return PCIBIOS_SUCCESSFUL;
153}
154
155static int pci_ampci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
156				       int where, u32 *_value)
157{
158	u32 rawval, value;
159
160	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
161		value = BRIDGEREGL(where);
162		__pcbdebug("=> %08x", &BRIDGEREGL(where), value);
163	} else {
164		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
165		rawval = CONFIG_ADDRESS;
166		value = CONFIG_DATAL(where);
167		if (__query(bus, devfn))
168			__pcidebug("=> %08x", bus, devfn, where, value);
169	}
170
171	*_value = value;
172	return PCIBIOS_SUCCESSFUL;
173}
174
175static int pci_ampci_write_config_byte(struct pci_bus *bus, unsigned int devfn,
176				       int where, u8 value)
177{
178	u32 rawval;
179
180	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
181		__pcbdebug("<= %02x", &BRIDGEREGB(where), value);
182		BRIDGEREGB(where) = value;
183	} else {
184		if (bus->number == 0 &&
185		    (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(3, 0))
186		    )
187			__pcidebug("<= %02x", bus, devfn, where, value);
188		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
189		rawval = CONFIG_ADDRESS;
190		CONFIG_DATAB(where) = value;
191	}
192	return PCIBIOS_SUCCESSFUL;
193}
194
195static int pci_ampci_write_config_word(struct pci_bus *bus, unsigned int devfn,
196				       int where, u16 value)
197{
198	u32 rawval;
199
200	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
201		__pcbdebug("<= %04hx", &BRIDGEREGW(where), value);
202		BRIDGEREGW(where) = value;
203	} else {
204		if (__query(bus, devfn))
205			__pcidebug("<= %04hx", bus, devfn, where, value);
206		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
207		rawval = CONFIG_ADDRESS;
208		CONFIG_DATAW(where) = value;
209	}
210	return PCIBIOS_SUCCESSFUL;
211}
212
213static int pci_ampci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
214					int where, u32 value)
215{
216	u32 rawval;
217
218	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
219		__pcbdebug("<= %08x", &BRIDGEREGL(where), value);
220		BRIDGEREGL(where) = value;
221	} else {
222		if (__query(bus, devfn))
223			__pcidebug("<= %08x", bus, devfn, where, value);
224		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
225		rawval = CONFIG_ADDRESS;
226		CONFIG_DATAL(where) = value;
227	}
228	return PCIBIOS_SUCCESSFUL;
229}
230
231static int pci_ampci_read_config(struct pci_bus *bus, unsigned int devfn,
232				 int where, int size, u32 *val)
233{
234	switch (size) {
235	case 1:
236		return pci_ampci_read_config_byte(bus, devfn, where, val);
237	case 2:
238		return pci_ampci_read_config_word(bus, devfn, where, val);
239	case 4:
240		return pci_ampci_read_config_dword(bus, devfn, where, val);
241	default:
242		BUG();
243		return -EOPNOTSUPP;
244	}
245}
246
247static int pci_ampci_write_config(struct pci_bus *bus, unsigned int devfn,
248				  int where, int size, u32 val)
249{
250	switch (size) {
251	case 1:
252		return pci_ampci_write_config_byte(bus, devfn, where, val);
253	case 2:
254		return pci_ampci_write_config_word(bus, devfn, where, val);
255	case 4:
256		return pci_ampci_write_config_dword(bus, devfn, where, val);
257	default:
258		BUG();
259		return -EOPNOTSUPP;
260	}
261}
262
263static struct pci_ops pci_direct_ampci = {
264	pci_ampci_read_config,
265	pci_ampci_write_config,
266};
267
268/*
269 * Before we decide to use direct hardware access mechanisms, we try to do some
270 * trivial checks to ensure it at least _seems_ to be working -- we just test
271 * whether bus 00 contains a host bridge (this is similar to checking
272 * techniques used in XFree86, but ours should be more reliable since we
273 * attempt to make use of direct access hints provided by the PCI BIOS).
274 *
275 * This should be close to trivial, but it isn't, because there are buggy
276 * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
277 */
278static int __init pci_sanity_check(struct pci_ops *o)
279{
280	struct pci_bus bus;		/* Fake bus and device */
281	u32 x;
282
283	bus.number = 0;
284
285	if ((!o->read(&bus, 0, PCI_CLASS_DEVICE, 2, &x) &&
286	     (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) ||
287	    (!o->read(&bus, 0, PCI_VENDOR_ID, 2, &x) &&
288	     (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)))
289		return 1;
290
291	printk(KERN_ERR "PCI: Sanity check failed\n");
292	return 0;
293}
294
295static int __init pci_check_direct(void)
296{
297	unsigned long flags;
298
299	local_irq_save(flags);
300
301	/*
302	 * Check if access works.
303	 */
304	if (pci_sanity_check(&pci_direct_ampci)) {
305		local_irq_restore(flags);
306		printk(KERN_INFO "PCI: Using configuration ampci\n");
307		request_mem_region(0xBE040000, 256, "AMPCI bridge");
308		request_mem_region(0xBFFFFFF4, 12, "PCI ampci");
309		request_mem_region(0xBC000000, 32 * 1024 * 1024, "PCI SRAM");
310		return 0;
311	}
312
313	local_irq_restore(flags);
314	return -ENODEV;
315}
316
317static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
318{
319	unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM;
320	struct resource *devr = &dev->resource[idx], *busr;
321
322	if (dev->bus) {
323		pci_bus_for_each_resource(dev->bus, busr, i) {
324			if (!busr || (busr->flags ^ devr->flags) & type_mask)
325				continue;
326
327			if (devr->start &&
328			    devr->start >= busr->start &&
329			    devr->end <= busr->end)
330				return 1;
331		}
332	}
333
334	return 0;
335}
336
337static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
338{
339	struct pci_bus_region region;
340	int i;
341	int limit;
342
343	if (dev->bus->number != 0)
344		return;
345
346	limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ?
347		PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES;
348
349	for (i = 0; i < limit; i++) {
350		if (!dev->resource[i].flags)
351			continue;
352
353		region.start = dev->resource[i].start;
354		region.end = dev->resource[i].end;
355		pcibios_bus_to_resource(dev, &dev->resource[i], &region);
356		if (is_valid_resource(dev, i))
357			pci_claim_resource(dev, i);
358	}
359}
360
361/*
362 *  Called after each bus is probed, but before its children
363 *  are examined.
364 */
365void __devinit pcibios_fixup_bus(struct pci_bus *bus)
366{
367	struct pci_dev *dev;
368
369	if (bus->number == 0) {
370		bus->resource[0] = &pci_ioport_resource;
371		bus->resource[1] = &pci_iomem_resource;
372	}
373
374	if (bus->self) {
375		pci_read_bridge_bases(bus);
376		pcibios_fixup_device_resources(bus->self);
377	}
378
379	list_for_each_entry(dev, &bus->devices, bus_list)
380		pcibios_fixup_device_resources(dev);
381}
382
383/*
384 * Initialization. Try all known PCI access methods. Note that we support
385 * using both PCI BIOS and direct access: in such cases, we use I/O ports
386 * to access config space, but we still keep BIOS order of cards to be
387 * compatible with 2.0.X. This should go away some day.
388 */
389static int __init pcibios_init(void)
390{
391	ioport_resource.start	= 0xA0000000;
392	ioport_resource.end	= 0xDFFFFFFF;
393	iomem_resource.start	= 0xA0000000;
394	iomem_resource.end	= 0xDFFFFFFF;
395
396	if (insert_resource(&iomem_resource, &pci_iomem_resource) < 0)
397		panic("Unable to insert PCI IOMEM resource\n");
398	if (insert_resource(&ioport_resource, &pci_ioport_resource) < 0)
399		panic("Unable to insert PCI IOPORT resource\n");
400
401	if (!pci_probe)
402		return 0;
403
404	if (pci_check_direct() < 0) {
405		printk(KERN_WARNING "PCI: No PCI bus detected\n");
406		return 0;
407	}
408
409	printk(KERN_INFO "PCI: Probing PCI hardware [mempage %08x]\n",
410	       MEM_PAGING_REG);
411
412	pci_root_bus = pci_scan_bus(0, &pci_direct_ampci, NULL);
413
414	pcibios_irq_init();
415	pcibios_fixup_irqs();
416	pcibios_resource_survey();
417	return 0;
418}
419
420arch_initcall(pcibios_init);
421
422char *__init pcibios_setup(char *str)
423{
424	if (!strcmp(str, "off")) {
425		pci_probe = 0;
426		return NULL;
427
428	} else if (!strncmp(str, "lastbus=", 8)) {
429		pcibios_last_bus = simple_strtol(str+8, NULL, 0);
430		return NULL;
431	}
432
433	return str;
434}
435
436int pcibios_enable_device(struct pci_dev *dev, int mask)
437{
438	int err;
439
440	err = pci_enable_resources(dev, mask);
441	if (err == 0)
442		pcibios_enable_irq(dev);
443	return err;
444}
445
446/*
447 * disable the ethernet chipset
448 */
449static void __init unit_disable_pcnet(struct pci_bus *bus, struct pci_ops *o)
450{
451	u32 x;
452
453	bus->number = 0;
454
455	o->read (bus, PCI_DEVFN(2, 0), PCI_VENDOR_ID,		4, &x);
456	o->read (bus, PCI_DEVFN(2, 0), PCI_COMMAND,		2, &x);
457	x |= PCI_COMMAND_MASTER |
458		PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
459		PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
460	o->write(bus, PCI_DEVFN(2, 0), PCI_COMMAND,		2, x);
461	o->read (bus, PCI_DEVFN(2, 0), PCI_COMMAND,		2, &x);
462	o->write(bus, PCI_DEVFN(2, 0), PCI_BASE_ADDRESS_0,	4, 0x00030001);
463	o->read (bus, PCI_DEVFN(2, 0), PCI_BASE_ADDRESS_0,	4, &x);
464
465#define RDP (*(volatile u32 *) 0xBE030010)
466#define RAP (*(volatile u32 *) 0xBE030014)
467#define __set_RAP(X) do { RAP = (X); x = RAP; } while (0)
468#define __set_RDP(X) do { RDP = (X); x = RDP; } while (0)
469#define __get_RDP() ({ RDP & 0xffff; })
470
471	__set_RAP(0);
472	__set_RDP(0x0004);	/* CSR0 = STOP */
473
474	__set_RAP(88);		/* check CSR88 indicates an Am79C973 */
475	BUG_ON(__get_RDP() != 0x5003);
476
477	for (x = 0; x < 100; x++)
478		asm volatile("nop");
479
480	__set_RDP(0x0004);	/* CSR0 = STOP */
481}
482
483/*
484 * initialise the unit hardware
485 */
486asmlinkage void __init unit_pci_init(void)
487{
488	struct pci_bus bus;		/* Fake bus and device */
489	struct pci_ops *o = &pci_direct_ampci;
490	u32 x;
491
492	set_intr_level(XIRQ1, GxICR_LEVEL_3);
493
494	memset(&bus, 0, sizeof(bus));
495
496	MEM_PAGING_REG = 0xE8000000;
497
498	/* we need to set up the bridge _now_ or we won't be able to access the
499	 * PCI config registers
500	 */
501	BRIDGEREGW(PCI_COMMAND) |=
502		PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
503		PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER;
504	BRIDGEREGW(PCI_STATUS)		= 0xF800;
505	BRIDGEREGB(PCI_LATENCY_TIMER)	= 0x10;
506	BRIDGEREGL(PCI_BASE_ADDRESS_0)	= 0x80000000;
507	BRIDGEREGB(PCI_INTERRUPT_LINE)	= 1;
508	BRIDGEREGL(0x48)		= 0x98000000;	/* AMPCI base addr */
509	BRIDGEREGB(0x41)		= 0x00;		/* secondary bus
510							 * number */
511	BRIDGEREGB(0x42)		= 0x01;		/* subordinate bus
512							 * number */
513	BRIDGEREGB(0x44)		= 0x01;
514	BRIDGEREGL(0x50)		= 0x00000001;
515	BRIDGEREGL(0x58)		= 0x00001002;
516	BRIDGEREGL(0x5C)		= 0x00000011;
517
518	/* we also need to set up the PCI-PCI bridge */
519	bus.number = 0;
520
521	/* IO: 0x00000000-0x00020000 */
522	o->read (&bus, PCI_DEVFN(3, 0), PCI_COMMAND,		2, &x);
523	x |= PCI_COMMAND_MASTER |
524		PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
525		PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
526	o->write(&bus, PCI_DEVFN(3, 0), PCI_COMMAND,		2, x);
527
528	o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE,		1, &x);
529	o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16,	4, &x);
530	o->read (&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE,	4, &x);
531	o->read (&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE,	4, &x);
532
533	o->write(&bus, PCI_DEVFN(3, 0), PCI_IO_BASE,		1, 0x01);
534	o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE,		1, &x);
535	o->write(&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16,	4, 0x00020000);
536	o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16,	4, &x);
537	o->write(&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE,	4, 0xEBB0EA00);
538	o->read (&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE,	4, &x);
539	o->write(&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE,	4, 0xE9F0E800);
540	o->read (&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE,	4, &x);
541
542	unit_disable_pcnet(&bus, o);
543}
544