• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/powerpc/platforms/cell/
1
2#undef DEBUG
3
4#include <linux/kernel.h>
5
6#include <asm/io.h>
7#include <asm/machdep.h>
8#include <asm/pgtable.h>
9#include <asm/ppc-pci.h>
10
11#include "io-workarounds.h"
12
13#define IOWA_MAX_BUS	8
14
15static struct iowa_bus iowa_busses[IOWA_MAX_BUS];
16static unsigned int iowa_bus_count;
17
18static struct iowa_bus *iowa_pci_find(unsigned long vaddr, unsigned long paddr)
19{
20	int i, j;
21	struct resource *res;
22	unsigned long vstart, vend;
23
24	for (i = 0; i < iowa_bus_count; i++) {
25		struct iowa_bus *bus = &iowa_busses[i];
26		struct pci_controller *phb = bus->phb;
27
28		if (vaddr) {
29			vstart = (unsigned long)phb->io_base_virt;
30			vend = vstart + phb->pci_io_size - 1;
31			if ((vaddr >= vstart) && (vaddr <= vend))
32				return bus;
33		}
34
35		if (paddr)
36			for (j = 0; j < 3; j++) {
37				res = &phb->mem_resources[j];
38				if (paddr >= res->start && paddr <= res->end)
39					return bus;
40			}
41	}
42
43	return NULL;
44}
45
46struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR addr)
47{
48	struct iowa_bus *bus;
49	int token;
50
51	token = PCI_GET_ADDR_TOKEN(addr);
52
53	if (token && token <= iowa_bus_count)
54		bus = &iowa_busses[token - 1];
55	else {
56		unsigned long vaddr, paddr;
57		pte_t *ptep;
58
59		vaddr = (unsigned long)PCI_FIX_ADDR(addr);
60		if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
61			return NULL;
62
63		ptep = find_linux_pte(init_mm.pgd, vaddr);
64		if (ptep == NULL)
65			paddr = 0;
66		else
67			paddr = pte_pfn(*ptep) << PAGE_SHIFT;
68		bus = iowa_pci_find(vaddr, paddr);
69
70		if (bus == NULL)
71			return NULL;
72	}
73
74	return bus;
75}
76
77struct iowa_bus *iowa_pio_find_bus(unsigned long port)
78{
79	unsigned long vaddr = (unsigned long)pci_io_base + port;
80	return iowa_pci_find(vaddr, 0);
81}
82
83
84#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)		\
85static ret iowa_##name at					\
86{								\
87	struct iowa_bus *bus;					\
88	bus = iowa_##space##_find_bus(aa);			\
89	if (bus && bus->ops && bus->ops->name)			\
90		return bus->ops->name al;			\
91	return __do_##name al;					\
92}
93
94#define DEF_PCI_AC_NORET(name, at, al, space, aa)		\
95static void iowa_##name at					\
96{								\
97	struct iowa_bus *bus;					\
98	bus = iowa_##space##_find_bus(aa);			\
99	if (bus && bus->ops && bus->ops->name) {		\
100		bus->ops->name al;				\
101		return;						\
102	}							\
103	__do_##name al;						\
104}
105
106#include <asm/io-defs.h>
107
108#undef DEF_PCI_AC_RET
109#undef DEF_PCI_AC_NORET
110
111static const struct ppc_pci_io __devinitconst iowa_pci_io = {
112
113#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)	.name = iowa_##name,
114#define DEF_PCI_AC_NORET(name, at, al, space, aa)	.name = iowa_##name,
115
116#include <asm/io-defs.h>
117
118#undef DEF_PCI_AC_RET
119#undef DEF_PCI_AC_NORET
120
121};
122
123static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size,
124				  unsigned long flags, void *caller)
125{
126	struct iowa_bus *bus;
127	void __iomem *res = __ioremap_caller(addr, size, flags, caller);
128	int busno;
129
130	bus = iowa_pci_find(0, (unsigned long)addr);
131	if (bus != NULL) {
132		busno = bus - iowa_busses;
133		PCI_SET_ADDR_TOKEN(res, busno + 1);
134	}
135	return res;
136}
137
138void __devinit iowa_register_bus(struct pci_controller *phb,
139			struct ppc_pci_io *ops,
140			int (*initfunc)(struct iowa_bus *, void *), void *data)
141{
142	struct iowa_bus *bus;
143	struct device_node *np = phb->dn;
144
145	if (iowa_bus_count >= IOWA_MAX_BUS) {
146		pr_err("IOWA:Too many pci bridges, "
147		       "workarounds disabled for %s\n", np->full_name);
148		return;
149	}
150
151	bus = &iowa_busses[iowa_bus_count];
152	bus->phb = phb;
153	bus->ops = ops;
154
155	if (initfunc)
156		if ((*initfunc)(bus, data))
157			return;
158
159	iowa_bus_count++;
160
161	pr_debug("IOWA:[%d]Add bus, %s.\n", iowa_bus_count-1, np->full_name);
162}
163
164void __devinit io_workaround_init(void)
165{
166	static int io_workaround_inited;
167
168	if (io_workaround_inited)
169		return;
170	ppc_pci_io = iowa_pci_io;
171	ppc_md.ioremap = iowa_ioremap;
172	io_workaround_inited = 1;
173}
174