Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6] / arch / mips / pci / ops-nile4.c
1 #include <linux/kernel.h>
2 #include <linux/init.h>
3 #include <linux/pci.h>
4 #include <asm/bootinfo.h>
5
6 #include <asm/lasat/lasat.h>
7 #include <asm/gt64120.h>
8 #include <asm/nile4.h>
9
10 #define PCI_ACCESS_READ  0
11 #define PCI_ACCESS_WRITE 1
12
13 #define LO(reg) (reg / 4)
14 #define HI(reg) (reg / 4 + 1)
15
16 volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE;
17
18 static DEFINE_SPINLOCK(nile4_pci_lock);
19
20 static int nile4_pcibios_config_access(unsigned char access_type,
21         struct pci_bus *bus, unsigned int devfn, int where, u32 *val)
22 {
23         unsigned char busnum = bus->number;
24         u32 adr, mask, err;
25
26         if ((busnum == 0) && (PCI_SLOT(devfn) > 8))
27                 /* The addressing scheme chosen leaves room for just
28                  * 8 devices on the first busnum (besides the PCI
29                  * controller itself) */
30                 return PCIBIOS_DEVICE_NOT_FOUND;
31
32         if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) {
33                 /* Access controller registers directly */
34                 if (access_type == PCI_ACCESS_WRITE) {
35                         vrc_pciregs[(0x200 + where) >> 2] = *val;
36                 } else {
37                         *val = vrc_pciregs[(0x200 + where) >> 2];
38                 }
39                 return PCIBIOS_SUCCESSFUL;
40         }
41
42         /* Temporarily map PCI Window 1 to config space */
43         mask = vrc_pciregs[LO(NILE4_PCIINIT1)];
44         vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0);
45
46         /* Clear PCI Error register. This also clears the Error Type
47          * bits in the Control register */
48         vrc_pciregs[LO(NILE4_PCIERR)] = 0;
49         vrc_pciregs[HI(NILE4_PCIERR)] = 0;
50
51         /* Setup address */
52         if (busnum == 0)
53                 adr =
54                     KSEG1ADDR(PCI_WINDOW1) +
55                     ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8)
56                      | (where & ~3));
57         else
58                 adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) |
59                       (where & ~3);
60
61         if (access_type == PCI_ACCESS_WRITE)
62                 *(u32 *) adr = *val;
63         else
64                 *val = *(u32 *) adr;
65
66         /* Check for master or target abort */
67         err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7;
68
69         /* Restore PCI Window 1 */
70         vrc_pciregs[LO(NILE4_PCIINIT1)] = mask;
71
72         if (err)
73                 return PCIBIOS_DEVICE_NOT_FOUND;
74
75         return PCIBIOS_SUCCESSFUL;
76 }
77
78 static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn,
79         int where, int size, u32 *val)
80 {
81         unsigned long flags;
82         u32 data = 0;
83         int err;
84
85         if ((size == 2) && (where & 1))
86                 return PCIBIOS_BAD_REGISTER_NUMBER;
87         else if ((size == 4) && (where & 3))
88                 return PCIBIOS_BAD_REGISTER_NUMBER;
89
90         spin_lock_irqsave(&nile4_pci_lock, flags);
91         err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
92                                         &data);
93         spin_unlock_irqrestore(&nile4_pci_lock, flags);
94
95         if (err)
96                 return err;
97
98         if (size == 1)
99                 *val = (data >> ((where & 3) << 3)) & 0xff;
100         else if (size == 2)
101                 *val = (data >> ((where & 3) << 3)) & 0xffff;
102         else
103                 *val = data;
104
105         return PCIBIOS_SUCCESSFUL;
106 }
107
108 static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn,
109         int where, int size, u32 val)
110 {
111         unsigned long flags;
112         u32 data = 0;
113         int err;
114
115         if ((size == 2) && (where & 1))
116                 return PCIBIOS_BAD_REGISTER_NUMBER;
117         else if ((size == 4) && (where & 3))
118                 return PCIBIOS_BAD_REGISTER_NUMBER;
119
120         spin_lock_irqsave(&nile4_pci_lock, flags);
121         err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
122                                           &data);
123         spin_unlock_irqrestore(&nile4_pci_lock, flags);
124
125         if (err)
126                 return err;
127
128         if (size == 1)
129                 data = (data & ~(0xff << ((where & 3) << 3))) |
130                     (val << ((where & 3) << 3));
131         else if (size == 2)
132                 data = (data & ~(0xffff << ((where & 3) << 3))) |
133                     (val << ((where & 3) << 3));
134         else
135                 data = val;
136
137         if (nile4_pcibios_config_access
138             (PCI_ACCESS_WRITE, bus, devfn, where, &data))
139                 return -1;
140
141         return PCIBIOS_SUCCESSFUL;
142 }
143
144 struct pci_ops nile4_pci_ops = {
145         .read = nile4_pcibios_read,
146         .write = nile4_pcibios_write,
147 };