1 /*
2 * arch/mips/vr41xx/common/pciu.c
3 *
4 * PCI Control Unit routines for the NEC VR4100 series.
5 *
6 * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
7 *
8 * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under
9 * the terms of the GNU General Public License version 2. This program
10 * is licensed "as is" without any warranty of any kind, whether express
11 * or implied.
12 */
13 /*
14 * Changes:
15 * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
16 * - New creation, NEC VR4122 and VR4131 are supported.
17 */
18 #include <linux/config.h>
19 #include <linux/init.h>
20 #include <linux/pci.h>
21 #include <linux/types.h>
22
23 #include <asm/cpu.h>
24 #include <asm/io.h>
25 #include <asm/pci_channel.h>
26 #include <asm/vr41xx/vr41xx.h>
27
28 #include "pciu.h"
29
vr41xx_pci_config_access(struct pci_dev * dev,int where)30 static inline int vr41xx_pci_config_access(struct pci_dev *dev, int where)
31 {
32 unsigned char bus = dev->bus->number;
33 unsigned int dev_fn = dev->devfn;
34
35 if (bus == 0) {
36 /*
37 * Type 0 configuration
38 */
39 if (PCI_SLOT(dev_fn) < 11 || PCI_SLOT(dev_fn) > 31 || where > 0xff)
40 return -EINVAL;
41
42 writel((1U << PCI_SLOT(dev_fn)) |
43 (PCI_FUNC(dev_fn) << 8) |
44 (where & 0xfc),
45 PCICONFAREG);
46 } else {
47 /*
48 * Type 1 configuration
49 */
50 if (PCI_SLOT(dev_fn) > 31 || where > 0xff)
51 return -EINVAL;
52
53 writel((bus << 16) |
54 (dev_fn << 8) |
55 (where & 0xfc) |
56 1U,
57 PCICONFAREG);
58 }
59
60 return 0;
61 }
62
vr41xx_pci_config_read_byte(struct pci_dev * dev,int where,uint8_t * val)63 static int vr41xx_pci_config_read_byte(struct pci_dev *dev, int where, uint8_t *val)
64 {
65 uint32_t data;
66
67 *val = 0xff;
68 if (vr41xx_pci_config_access(dev, where) < 0)
69 return PCIBIOS_DEVICE_NOT_FOUND;
70
71 data = readl(PCICONFDREG);
72 *val = (uint8_t)(data >> ((where & 3) << 3));
73
74 return PCIBIOS_SUCCESSFUL;
75
76 }
77
vr41xx_pci_config_read_word(struct pci_dev * dev,int where,uint16_t * val)78 static int vr41xx_pci_config_read_word(struct pci_dev *dev, int where, uint16_t *val)
79 {
80 uint32_t data;
81
82 *val = 0xffff;
83 if (where & 1)
84 return PCIBIOS_BAD_REGISTER_NUMBER;
85
86 if (vr41xx_pci_config_access(dev, where) < 0)
87 return PCIBIOS_DEVICE_NOT_FOUND;
88
89 data = readl(PCICONFDREG);
90 *val = (uint16_t)(data >> ((where & 2) << 3));
91
92 return PCIBIOS_SUCCESSFUL;
93 }
94
vr41xx_pci_config_read_dword(struct pci_dev * dev,int where,uint32_t * val)95 static int vr41xx_pci_config_read_dword(struct pci_dev *dev, int where, uint32_t *val)
96 {
97 *val = 0xffffffff;
98 if (where & 3)
99 return PCIBIOS_BAD_REGISTER_NUMBER;
100
101 if (vr41xx_pci_config_access(dev, where) < 0)
102 return PCIBIOS_DEVICE_NOT_FOUND;
103
104 *val = readl(PCICONFDREG);
105
106 return PCIBIOS_SUCCESSFUL;
107 }
108
vr41xx_pci_config_write_byte(struct pci_dev * dev,int where,uint8_t val)109 static int vr41xx_pci_config_write_byte(struct pci_dev *dev, int where, uint8_t val)
110 {
111 uint32_t data;
112 int shift;
113
114 if (vr41xx_pci_config_access(dev, where) < 0)
115 return PCIBIOS_DEVICE_NOT_FOUND;
116
117 data = readl(PCICONFDREG);
118 shift = (where & 3) << 3;
119 data &= ~(0xffU << shift);
120 data |= (uint32_t)val << shift;
121 writel(data, PCICONFDREG);
122
123 return PCIBIOS_SUCCESSFUL;
124 }
125
vr41xx_pci_config_write_word(struct pci_dev * dev,int where,uint16_t val)126 static int vr41xx_pci_config_write_word(struct pci_dev *dev, int where, uint16_t val)
127 {
128 uint32_t data;
129 int shift;
130
131 if (where & 1)
132 return PCIBIOS_BAD_REGISTER_NUMBER;
133
134 if (vr41xx_pci_config_access(dev, where) < 0)
135 return PCIBIOS_DEVICE_NOT_FOUND;
136
137 data = readl(PCICONFDREG);
138 shift = (where & 2) << 3;
139 data &= ~(0xffffU << shift);
140 data |= (uint32_t)val << shift;
141 writel(data, PCICONFDREG);
142
143 return PCIBIOS_SUCCESSFUL;
144 }
145
vr41xx_pci_config_write_dword(struct pci_dev * dev,int where,uint32_t val)146 static int vr41xx_pci_config_write_dword(struct pci_dev *dev, int where, uint32_t val)
147 {
148 if (where & 3)
149 return PCIBIOS_BAD_REGISTER_NUMBER;
150
151 if (vr41xx_pci_config_access(dev, where) < 0)
152 return PCIBIOS_DEVICE_NOT_FOUND;
153
154 writel(val, PCICONFDREG);
155
156 return PCIBIOS_SUCCESSFUL;
157 }
158
159 struct pci_ops vr41xx_pci_ops = {
160 .read_byte = vr41xx_pci_config_read_byte,
161 .read_word = vr41xx_pci_config_read_word,
162 .read_dword = vr41xx_pci_config_read_dword,
163 .write_byte = vr41xx_pci_config_write_byte,
164 .write_word = vr41xx_pci_config_write_word,
165 .write_dword = vr41xx_pci_config_write_dword,
166 };
167
vr41xx_pciu_init(struct vr41xx_pci_address_map * map)168 void __init vr41xx_pciu_init(struct vr41xx_pci_address_map *map)
169 {
170 struct vr41xx_pci_address_space *s;
171 unsigned long vtclock;
172 uint32_t config;
173
174 if (map == NULL)
175 return;
176
177 /* Disable PCI interrupt */
178 writew(0, MPCIINTREG);
179
180 /* Supply VTClock to PCIU */
181 vr41xx_supply_clock(PCIU_CLOCK);
182
183 /* Dummy read/write, waiting for supply of VTClock. */
184 readw(MPCIINTREG);
185 writew(0, MPCIINTREG);
186
187 /* Select PCI clock */
188 vtclock = vr41xx_get_vtclock_frequency();
189 if (vtclock < MAX_PCI_CLOCK)
190 writel(EQUAL_VTCLOCK, PCICLKSELREG);
191 else if ((vtclock / 2) < MAX_PCI_CLOCK)
192 writel(HALF_VTCLOCK, PCICLKSELREG);
193 else if ((vtclock / 4) < MAX_PCI_CLOCK)
194 writel(QUARTER_VTCLOCK, PCICLKSELREG);
195 else
196 printk(KERN_INFO "Warning: PCI Clock is over 33MHz.\n");
197
198 /* Supply PCI clock by PCI bus */
199 vr41xx_supply_clock(PCI_CLOCK);
200
201 /*
202 * Set PCI memory & I/O space address conversion registers
203 * for master transaction.
204 */
205 if (map->mem1 != NULL) {
206 s = map->mem1;
207 config = (s->internal_base & INTERNAL_BUS_BASE_ADDRESS) |
208 ((s->address_mask >> 11) & ADDRESS_MASK) |
209 PCI_ACCESS_ENABLE |
210 ((s->pci_base >> 24) & PCI_ADDRESS_SETTING);
211 writel(config, PCIMMAW1REG);
212 }
213 if (map->mem2 != NULL) {
214 s = map->mem2;
215 config = (s->internal_base & INTERNAL_BUS_BASE_ADDRESS) |
216 ((s->address_mask >> 11) & ADDRESS_MASK) |
217 PCI_ACCESS_ENABLE |
218 ((s->pci_base >> 24) & PCI_ADDRESS_SETTING);
219 writel(config, PCIMMAW2REG);
220 }
221 if (map->io != NULL) {
222 s = map->io;
223 config = (s->internal_base & INTERNAL_BUS_BASE_ADDRESS) |
224 ((s->address_mask >> 11) & ADDRESS_MASK) |
225 PCI_ACCESS_ENABLE |
226 ((s->pci_base >> 24) & PCI_ADDRESS_SETTING);
227 writel(config, PCIMIOAWREG);
228 }
229
230 /* Set target memory windows */
231 writel(0x00081000U, PCITAW1REG);
232 writel(0U, PCITAW2REG);
233
234 pciu_write_config_dword(PCI_BASE_ADDRESS_0, 0U);
235 pciu_write_config_dword(PCI_BASE_ADDRESS_1, 0U);
236
237 /* Clear bus error */
238 readl(BUSERRADREG);
239
240 if (current_cpu_data.cputype == CPU_VR4122) {
241 writel(0U, PCITRDYVREG);
242 pciu_write_config_byte(PCI_LATENCY_TIMER, 0xf8);
243 } else {
244 writel(100U, PCITRDYVREG);
245 pciu_write_config_byte(PCI_LATENCY_TIMER, 0x80);
246 }
247
248 writel(CONFIG_DONE, PCIENREG);
249 pciu_write_config_word(PCI_COMMAND,
250 PCI_COMMAND_IO |
251 PCI_COMMAND_MEMORY |
252 PCI_COMMAND_MASTER |
253 PCI_COMMAND_PARITY |
254 PCI_COMMAND_SERR);
255 }
256