Merge tag 'split-asm_system_h-for-linus-20120328' of git://git.kernel.org/pub/scm...
[linux-2.6.git] / arch / arm / mach-ixp2000 / pci.c
1 /*
2  * arch/arm/mach-ixp2000/pci.c
3  *
4  * PCI routines for IXDP2400/IXDP2800 boards
5  *
6  * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
7  * Maintained by: Deepak Saxena <dsaxena@plexity.net>
8  *
9  * Copyright 2002 Intel Corp.
10  * Copyright (C) 2003-2004 MontaVista Software, Inc.
11  *
12  *  This program is free software; you can redistribute  it and/or modify it
13  *  under  the terms of  the GNU General  Public License as published by the
14  *  Free Software Foundation;  either version 2 of the  License, or (at your
15  *  option) any later version.
16  */
17
18 #include <linux/sched.h>
19 #include <linux/kernel.h>
20 #include <linux/pci.h>
21 #include <linux/interrupt.h>
22 #include <linux/mm.h>
23 #include <linux/init.h>
24 #include <linux/ioport.h>
25 #include <linux/delay.h>
26 #include <linux/io.h>
27
28 #include <asm/irq.h>
29 #include <mach/hardware.h>
30
31 #include <asm/mach/pci.h>
32
33 static volatile int pci_master_aborts = 0;
34
35 static int clear_master_aborts(void);
36
37 u32 *
38 ixp2000_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
39 {
40         u32 *paddress;
41
42         if (PCI_SLOT(devfn) > 7)
43                 return 0;
44
45         /* Must be dword aligned */
46         where &= ~3;
47
48         /*
49          * For top bus, generate type 0, else type 1
50          */
51         if (!bus_nr) {
52                 /* only bits[23:16] are used for IDSEL */
53                 paddress = (u32 *) (IXP2000_PCI_CFG0_VIRT_BASE
54                                     | (1 << (PCI_SLOT(devfn) + 16))
55                                     | (PCI_FUNC(devfn) << 8) | where);
56         } else {
57                 paddress = (u32 *) (IXP2000_PCI_CFG1_VIRT_BASE 
58                                     | (bus_nr << 16)
59                                     | (PCI_SLOT(devfn) << 11)
60                                     | (PCI_FUNC(devfn) << 8) | where);
61         }
62
63         return paddress;
64 }
65
66 /*
67  * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes.
68  * 0 and 3 are not valid indexes...
69  */
70 static u32 bytemask[] = {
71         /*0*/   0,
72         /*1*/   0xff,
73         /*2*/   0xffff,
74         /*3*/   0,
75         /*4*/   0xffffffff,
76 };
77
78
79 int ixp2000_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where,
80                                 int size, u32 *value)
81 {
82         u32 n;
83         u32 *addr;
84
85         n = where % 4;
86
87         addr = ixp2000_pci_config_addr(bus->number, devfn, where);
88         if (!addr)
89                 return PCIBIOS_DEVICE_NOT_FOUND;
90
91         pci_master_aborts = 0;
92         *value = (*addr >> (8*n)) & bytemask[size];
93         if (pci_master_aborts) {
94                 pci_master_aborts = 0;
95                 *value = 0xffffffff;
96                 return PCIBIOS_DEVICE_NOT_FOUND;
97         }
98
99         return PCIBIOS_SUCCESSFUL;
100 }
101
102 /*
103  * We don't do error checks by calling clear_master_aborts() b/c the
104  * assumption is that the caller did a read first to make sure a device
105  * exists.
106  */
107 int ixp2000_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where,
108                                 int size, u32 value)
109 {
110         u32 mask;
111         u32 *addr;
112         u32 temp;
113
114         mask = ~(bytemask[size] << ((where % 0x4) * 8));
115         addr = ixp2000_pci_config_addr(bus->number, devfn, where);
116         if (!addr)
117                 return PCIBIOS_DEVICE_NOT_FOUND;
118         temp = (u32) (value) << ((where % 0x4) * 8);
119         *addr = (*addr & mask) | temp;
120
121         clear_master_aborts();
122
123         return PCIBIOS_SUCCESSFUL;
124 }
125
126
127 static struct pci_ops ixp2000_pci_ops = {
128         .read   = ixp2000_pci_read_config,
129         .write  = ixp2000_pci_write_config
130 };
131
132 struct pci_bus *ixp2000_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
133 {
134         return pci_scan_root_bus(NULL, sysdata->busnr, &ixp2000_pci_ops,
135                                  sysdata, &sysdata->resources);
136 }
137
138
139 int ixp2000_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
140 {
141
142         volatile u32 temp;
143         unsigned long flags;
144
145         pci_master_aborts = 1;
146
147         local_irq_save(flags);
148         temp = *(IXP2000_PCI_CONTROL);
149         if (temp & ((1 << 8) | (1 << 5))) {
150                 ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp);
151         }
152
153         temp = *(IXP2000_PCI_CMDSTAT);
154         if (temp & (1 << 29)) {
155                 while (temp & (1 << 29)) {      
156                         ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp);
157                         temp = *(IXP2000_PCI_CMDSTAT);
158                 }
159         }
160         local_irq_restore(flags);
161
162         /*
163          * If it was an imprecise abort, then we need to correct the
164          * return address to be _after_ the instruction.
165          */
166         if (fsr & (1 << 10))
167                 regs->ARM_pc += 4;
168
169         return 0;
170 }
171
172 int
173 clear_master_aborts(void)
174 {
175         volatile u32 temp;
176         unsigned long flags;
177
178         local_irq_save(flags);
179         temp = *(IXP2000_PCI_CONTROL);
180         if (temp & ((1 << 8) | (1 << 5))) {
181                 ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp);
182         }
183
184         temp = *(IXP2000_PCI_CMDSTAT);
185         if (temp & (1 << 29)) {
186                 while (temp & (1 << 29)) {
187                         ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp);
188                         temp = *(IXP2000_PCI_CMDSTAT);
189                 }
190         }
191         local_irq_restore(flags);
192
193         return 0;
194 }
195
196 void __init
197 ixp2000_pci_preinit(void)
198 {
199         pci_set_flags(0);
200
201         pcibios_min_io = 0;
202         pcibios_min_mem = 0;
203
204 #ifndef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO
205         /*
206          * Configure the PCI unit to properly byteswap I/O transactions,
207          * and verify that it worked.
208          */
209         ixp2000_reg_write(IXP2000_PCI_CONTROL,
210                           (*IXP2000_PCI_CONTROL | PCI_CONTROL_IEE));
211
212         if ((*IXP2000_PCI_CONTROL & PCI_CONTROL_IEE) == 0)
213                 panic("IXP2000: PCI I/O is broken on this ixp model, and "
214                         "the needed workaround has not been configured in");
215 #endif
216
217         hook_fault_code(16+6, ixp2000_pci_abort_handler, SIGBUS, 0,
218                                 "PCI config cycle to non-existent device");
219 }
220
221
222 /*
223  * IXP2000 systems often have large resource requirements, so we just
224  * use our own resource space.
225  */
226 static struct resource ixp2000_pci_mem_space = {
227         .start  = 0xe0000000,
228         .end    = 0xffffffff,
229         .flags  = IORESOURCE_MEM,
230         .name   = "PCI Mem Space"
231 };
232
233 static struct resource ixp2000_pci_io_space = {
234         .start  = 0x00010000,
235         .end    = 0x0001ffff,
236         .flags  = IORESOURCE_IO,
237         .name   = "PCI I/O Space"
238 };
239
240 int ixp2000_pci_setup(int nr, struct pci_sys_data *sys)
241 {
242         if (nr >= 1)
243                 return 0;
244
245         pci_add_resource_offset(&sys->resources,
246                                 &ixp2000_pci_io_space, sys->io_offset);
247         pci_add_resource_offset(&sys->resources,
248                                 &ixp2000_pci_mem_space, sys->mem_offset);
249
250         return 1;
251 }
252