• 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/arch/mips/pci/
1/*
2 * BRIEF MODULE DESCRIPTION
3 *	Alchemy/AMD Au1xx0 PCI support.
4 *
5 * Copyright 2001-2003, 2007-2008 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc. <source@mvista.com>
7 *
8 *  Support for all devices (greater than 16) added by David Gathright.
9 *
10 *  This program is free software; you can redistribute  it and/or modify it
11 *  under  the terms of  the GNU General  Public License as published by the
12 *  Free Software Foundation;  either version 2 of the  License, or (at your
13 *  option) any later version.
14 *
15 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
16 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
17 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
18 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
19 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
21 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
23 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 *  You should have received a copy of the  GNU General Public License along
27 *  with this program; if not, write  to the Free Software Foundation, Inc.,
28 *  675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30
31#include <linux/types.h>
32#include <linux/pci.h>
33#include <linux/kernel.h>
34#include <linux/init.h>
35#include <linux/vmalloc.h>
36
37#include <asm/mach-au1x00/au1000.h>
38
39#undef	DEBUG
40#ifdef	DEBUG
41#define DBG(x...) printk(KERN_DEBUG x)
42#else
43#define DBG(x...)
44#endif
45
46#define PCI_ACCESS_READ  0
47#define PCI_ACCESS_WRITE 1
48
49int (*board_pci_idsel)(unsigned int devsel, int assert);
50
51void mod_wired_entry(int entry, unsigned long entrylo0,
52		unsigned long entrylo1, unsigned long entryhi,
53		unsigned long pagemask)
54{
55	unsigned long old_pagemask;
56	unsigned long old_ctx;
57
58	/* Save old context and create impossible VPN2 value */
59	old_ctx = read_c0_entryhi() & 0xff;
60	old_pagemask = read_c0_pagemask();
61	write_c0_index(entry);
62	write_c0_pagemask(pagemask);
63	write_c0_entryhi(entryhi);
64	write_c0_entrylo0(entrylo0);
65	write_c0_entrylo1(entrylo1);
66	tlb_write_indexed();
67	write_c0_entryhi(old_ctx);
68	write_c0_pagemask(old_pagemask);
69}
70
71static struct vm_struct *pci_cfg_vm;
72static int pci_cfg_wired_entry;
73static unsigned long last_entryLo0, last_entryLo1;
74
75/*
76 * We can't ioremap the entire pci config space because it's too large.
77 * Nor can we call ioremap dynamically because some device drivers use
78 * the PCI config routines from within interrupt handlers and that
79 * becomes a problem in get_vm_area().  We use one wired TLB to handle
80 * all config accesses for all busses.
81 */
82void __init au1x_pci_cfg_init(void)
83{
84	/* Reserve a wired entry for PCI config accesses */
85	pci_cfg_vm = get_vm_area(0x2000, VM_IOREMAP);
86	if (!pci_cfg_vm)
87		panic(KERN_ERR "PCI unable to get vm area\n");
88	pci_cfg_wired_entry = read_c0_wired();
89	add_wired_entry(0, 0, (unsigned long)pci_cfg_vm->addr, PM_4K);
90	last_entryLo0 = last_entryLo1 = 0xffffffff;
91}
92
93static int config_access(unsigned char access_type, struct pci_bus *bus,
94			 unsigned int dev_fn, unsigned char where, u32 *data)
95{
96#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
97	unsigned int device = PCI_SLOT(dev_fn);
98	unsigned int function = PCI_FUNC(dev_fn);
99	unsigned long offset, status;
100	unsigned long cfg_base;
101	unsigned long flags;
102	int error = PCIBIOS_SUCCESSFUL;
103	unsigned long entryLo0, entryLo1;
104
105	if (device > 19) {
106		*data = 0xffffffff;
107		return -1;
108	}
109
110	local_irq_save(flags);
111	au_writel(((0x2000 << 16) | (au_readl(Au1500_PCI_STATCMD) & 0xffff)),
112			Au1500_PCI_STATCMD);
113	au_sync_udelay(1);
114
115	/*
116	 * Allow board vendors to implement their own off-chip IDSEL.
117	 * If it doesn't succeed, may as well bail out at this point.
118	 */
119	if (board_pci_idsel && board_pci_idsel(device, 1) == 0) {
120		*data = 0xffffffff;
121		local_irq_restore(flags);
122		return -1;
123	}
124
125	/* Setup the config window */
126	if (bus->number == 0)
127		cfg_base = (1 << device) << 11;
128	else
129		cfg_base = 0x80000000 | (bus->number << 16) | (device << 11);
130
131	/* Setup the lower bits of the 36-bit address */
132	offset = (function << 8) | (where & ~0x3);
133	/* Pick up any address that falls below the page mask */
134	offset |= cfg_base & ~PAGE_MASK;
135
136	/* Page boundary */
137	cfg_base = cfg_base & PAGE_MASK;
138
139	/*
140	 * To improve performance, if the current device is the same as
141	 * the last device accessed, we don't touch the TLB.
142	 */
143	entryLo0 = (6 << 26) | (cfg_base >> 6) | (2 << 3) | 7;
144	entryLo1 = (6 << 26) | (cfg_base >> 6) | (0x1000 >> 6) | (2 << 3) | 7;
145	if ((entryLo0 != last_entryLo0) || (entryLo1 != last_entryLo1)) {
146		mod_wired_entry(pci_cfg_wired_entry, entryLo0, entryLo1,
147				(unsigned long)pci_cfg_vm->addr, PM_4K);
148		last_entryLo0 = entryLo0;
149		last_entryLo1 = entryLo1;
150	}
151
152	if (access_type == PCI_ACCESS_WRITE)
153		au_writel(*data, (int)(pci_cfg_vm->addr + offset));
154	else
155		*data = au_readl((int)(pci_cfg_vm->addr + offset));
156
157	au_sync_udelay(2);
158
159	DBG("cfg_access %d bus->number %u dev %u at %x *data %x conf %lx\n",
160	    access_type, bus->number, device, where, *data, offset);
161
162	/* Check master abort */
163	status = au_readl(Au1500_PCI_STATCMD);
164
165	if (status & (1 << 29)) {
166		*data = 0xffffffff;
167		error = -1;
168		DBG("Au1x Master Abort\n");
169	} else if ((status >> 28) & 0xf) {
170		DBG("PCI ERR detected: device %u, status %lx\n",
171		    device, (status >> 28) & 0xf);
172
173		/* Clear errors */
174		au_writel(status & 0xf000ffff, Au1500_PCI_STATCMD);
175
176		*data = 0xffffffff;
177		error = -1;
178	}
179
180	/* Take away the IDSEL. */
181	if (board_pci_idsel)
182		(void)board_pci_idsel(device, 0);
183
184	local_irq_restore(flags);
185	return error;
186#endif
187}
188
189static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
190			    int where,	u8 *val)
191{
192	u32 data;
193	int ret;
194
195	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
196	if (where & 1)
197		data >>= 8;
198	if (where & 2)
199		data >>= 16;
200	*val = data & 0xff;
201	return ret;
202}
203
204static int read_config_word(struct pci_bus *bus, unsigned int devfn,
205			    int where, u16 *val)
206{
207	u32 data;
208	int ret;
209
210	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
211	if (where & 2)
212		data >>= 16;
213	*val = data & 0xffff;
214	return ret;
215}
216
217static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
218			     int where, u32 *val)
219{
220	int ret;
221
222	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
223	return ret;
224}
225
226static int write_config_byte(struct pci_bus *bus, unsigned int devfn,
227			     int where, u8 val)
228{
229	u32 data = 0;
230
231	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
232		return -1;
233
234	data = (data & ~(0xff << ((where & 3) << 3))) |
235	       (val << ((where & 3) << 3));
236
237	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
238		return -1;
239
240	return PCIBIOS_SUCCESSFUL;
241}
242
243static int write_config_word(struct pci_bus *bus, unsigned int devfn,
244			     int where, u16 val)
245{
246	u32 data = 0;
247
248	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
249		return -1;
250
251	data = (data & ~(0xffff << ((where & 3) << 3))) |
252	       (val << ((where & 3) << 3));
253
254	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
255		return -1;
256
257	return PCIBIOS_SUCCESSFUL;
258}
259
260static int write_config_dword(struct pci_bus *bus, unsigned int devfn,
261			      int where, u32 val)
262{
263	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
264		return -1;
265
266	return PCIBIOS_SUCCESSFUL;
267}
268
269static int config_read(struct pci_bus *bus, unsigned int devfn,
270		       int where, int size, u32 *val)
271{
272	switch (size) {
273	case 1: {
274			u8 _val;
275			int rc = read_config_byte(bus, devfn, where, &_val);
276
277			*val = _val;
278			return rc;
279		}
280	case 2: {
281			u16 _val;
282			int rc = read_config_word(bus, devfn, where, &_val);
283
284			*val = _val;
285			return rc;
286		}
287	default:
288		return read_config_dword(bus, devfn, where, val);
289	}
290}
291
292static int config_write(struct pci_bus *bus, unsigned int devfn,
293			int where, int size, u32 val)
294{
295	switch (size) {
296	case 1:
297		return write_config_byte(bus, devfn, where, (u8) val);
298	case 2:
299		return write_config_word(bus, devfn, where, (u16) val);
300	default:
301		return write_config_dword(bus, devfn, where, val);
302	}
303}
304
305struct pci_ops au1x_pci_ops = {
306	config_read,
307	config_write
308};
309