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