OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [mips/] [vr41xx/] [common/] [pciu.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * FILE NAME
3
 *      arch/mips/vr41xx/common/pciu.c
4
 *
5
 * BRIEF MODULE DESCRIPTION
6
 *      PCI Control Unit routines for the NEC VR4100 series.
7
 *
8
 * Author: Yoichi Yuasa
9
 *         yyuasa@mvista.com or source@mvista.com
10
 *
11
 * Copyright 2001,2002 MontaVista Software Inc.
12
 *
13
 *  This program is free software; you can redistribute it and/or modify it
14
 *  under the terms of the GNU General Public License as published by the
15
 *  Free Software Foundation; either version 2 of the License, or (at your
16
 *  option) any later version.
17
 *
18
 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19
 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20
 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24
 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26
 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27
 *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 *  You should have received a copy of the GNU General Public License along
30
 *  with this program; if not, write to the Free Software Foundation, Inc.,
31
 *  675 Mass Ave, Cambridge, MA 02139, USA.
32
 */
33
/*
34
 * Changes:
35
 *  Paul Mundt <lethal@chaoticdreams.org>
36
 *  - Fix deadlock-causing PCIU access race for VR4131.
37
 *
38
 *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
39
 *  - New creation, NEC VR4122 and VR4131 are supported.
40
 */
41
#include <linux/config.h>
42
#include <linux/init.h>
43
#include <linux/pci.h>
44
#include <linux/types.h>
45
#include <linux/delay.h>
46
 
47
#include <asm/cpu.h>
48
#include <asm/io.h>
49
#include <asm/pci_channel.h>
50
#include <asm/vr41xx/vr41xx.h>
51
 
52
#include "pciu.h"
53
 
54
static inline int vr41xx_pci_config_access(struct pci_dev *dev, int where)
55
{
56
        unsigned char bus = dev->bus->number;
57
        unsigned int dev_fn = dev->devfn;
58
 
59
        if (bus == 0) {
60
                /*
61
                 * Type 0 configuration
62
                 */
63
                if (PCI_SLOT(dev_fn) < 11 || PCI_SLOT(dev_fn) > 31 || where > 255)
64
                        return -1;
65
 
66
                writel((1UL << PCI_SLOT(dev_fn))|
67
                       (PCI_FUNC(dev_fn) << 8)  |
68
                       (where & 0xfc),
69
                       PCICONFAREG);
70
        }
71
        else {
72
                /*
73
                 * Type 1 configuration
74
                 */
75
                if (PCI_SLOT(dev_fn) > 31 || where > 255)
76
                        return -1;
77
 
78
                writel((bus << 16)      |
79
                       (dev_fn << 8)    |
80
                       (where & 0xfc)   |
81
                       1UL,
82
                       PCICONFAREG);
83
        }
84
 
85
        return 0;
86
}
87
 
88
static int vr41xx_pci_read_config_byte(struct pci_dev *dev, int where, u8 *val)
89
{
90
        u32 data;
91
 
92
        *val = 0xff;
93
        if (vr41xx_pci_config_access(dev, where) < 0)
94
                return PCIBIOS_DEVICE_NOT_FOUND;
95
 
96
        data = readl(PCICONFDREG);
97
        *val = (u8)(data >> ((where & 3) << 3));
98
 
99
        return PCIBIOS_SUCCESSFUL;
100
 
101
}
102
 
103
static int vr41xx_pci_read_config_word(struct pci_dev *dev, int where, u16 *val)
104
{
105
        u32 data;
106
 
107
        *val = 0xffff;
108
        if (where & 1)
109
                return PCIBIOS_BAD_REGISTER_NUMBER;
110
 
111
        if (vr41xx_pci_config_access(dev, where) < 0)
112
                return PCIBIOS_DEVICE_NOT_FOUND;
113
 
114
        data = readl(PCICONFDREG);
115
        *val = (u16)(data >> ((where & 2) << 3));
116
 
117
        return PCIBIOS_SUCCESSFUL;
118
}
119
 
120
static int vr41xx_pci_read_config_dword(struct pci_dev *dev, int where, u32 *val)
121
{
122
        *val = 0xffffffff;
123
        if (where & 3)
124
                return PCIBIOS_BAD_REGISTER_NUMBER;
125
 
126
        if (vr41xx_pci_config_access(dev, where) < 0)
127
                return PCIBIOS_DEVICE_NOT_FOUND;
128
 
129
        *val = readl(PCICONFDREG);
130
 
131
        return PCIBIOS_SUCCESSFUL;
132
}
133
 
134
static int vr41xx_pci_write_config_byte(struct pci_dev *dev, int where, u8 val)
135
{
136
        u32 data;
137
        int shift;
138
 
139
        if (vr41xx_pci_config_access(dev, where) < 0)
140
                return PCIBIOS_DEVICE_NOT_FOUND;
141
 
142
        data = readl(PCICONFDREG);
143
        shift = (where & 3) << 3;
144
        data &= ~(0xff << shift);
145
        data |= (((u32)val) << shift);
146
 
147
        writel(data, PCICONFDREG);
148
 
149
        return PCIBIOS_SUCCESSFUL;
150
}
151
 
152
static int vr41xx_pci_write_config_word(struct pci_dev *dev, int where, u16 val)
153
{
154
        u32 data;
155
        int shift;
156
 
157
        if (where & 1)
158
                return PCIBIOS_BAD_REGISTER_NUMBER;
159
 
160
        if (vr41xx_pci_config_access(dev, where) < 0)
161
                return PCIBIOS_DEVICE_NOT_FOUND;
162
 
163
        data = readl(PCICONFDREG);
164
        shift = (where & 2) << 3;
165
        data &= ~(0xffff << shift);
166
        data |= (((u32)val) << shift);
167
        writel(data, PCICONFDREG);
168
 
169
        return PCIBIOS_SUCCESSFUL;
170
}
171
 
172
static int vr41xx_pci_write_config_dword(struct pci_dev *dev, int where, u32 val)
173
{
174
        if (where & 3)
175
                return PCIBIOS_BAD_REGISTER_NUMBER;
176
 
177
        if (vr41xx_pci_config_access(dev, where) < 0)
178
                return PCIBIOS_DEVICE_NOT_FOUND;
179
 
180
        writel(val, PCICONFDREG);
181
 
182
        return PCIBIOS_SUCCESSFUL;
183
}
184
 
185
struct pci_ops vr41xx_pci_ops = {
186
        vr41xx_pci_read_config_byte,
187
        vr41xx_pci_read_config_word,
188
        vr41xx_pci_read_config_dword,
189
        vr41xx_pci_write_config_byte,
190
        vr41xx_pci_write_config_word,
191
        vr41xx_pci_write_config_dword
192
};
193
 
194
void __init vr41xx_pciu_init(struct vr41xx_pci_address_map *map)
195
{
196
        struct vr41xx_pci_address_space *s;
197
        unsigned long vtclock;
198
        u32 config;
199
        int n;
200
 
201
        if (!map)
202
                return;
203
 
204
        /* Disable PCI interrupt */
205
        writew(0, MPCIINTREG);
206
 
207
        /* Supply VTClock to PCIU */
208
        vr41xx_clock_supply(PCIU_CLOCK);
209
 
210
        /*
211
         * Sleep for 1us after setting MSKPPCIU bit in CMUCLKMSK
212
         * before doing any PCIU access to avoid deadlock on VR4131.
213
         */
214
        udelay(1);
215
 
216
        /* Select PCI clock */
217
        vtclock = vr41xx_get_vtclock_frequency();
218
        if (vtclock < MAX_PCI_CLOCK)
219
                writel(EQUAL_VTCLOCK, PCICLKSELREG);
220
        else if ((vtclock / 2) < MAX_PCI_CLOCK)
221
                writel(HALF_VTCLOCK, PCICLKSELREG);
222
        else if ((vtclock / 4) < MAX_PCI_CLOCK)
223
                writel(QUARTER_VTCLOCK, PCICLKSELREG);
224
        else
225
                printk(KERN_INFO "Warning: PCI Clock is over 33MHz.\n");
226
 
227
        /* Supply PCI clock by PCI bus */
228
        vr41xx_clock_supply(PCI_CLOCK);
229
 
230
        /*
231
         * Set PCI memory & I/O space address conversion registers
232
         * for master transaction.
233
         */
234
        if (map->mem1 != NULL) {
235
                s = map->mem1;
236
                config = (s->internal_base & 0xff000000) |
237
                         ((s->address_mask & 0x7f000000) >> 11) | (1UL << 12) |
238
                         ((s->pci_base & 0xff000000) >> 24);
239
                writel(config, PCIMMAW1REG);
240
        }
241
        if (map->mem2 != NULL) {
242
                s = map->mem2;
243
                config = (s->internal_base & 0xff000000) |
244
                         ((s->address_mask & 0x7f000000) >> 11) | (1UL << 12) |
245
                         ((s->pci_base & 0xff000000) >> 24);
246
                writel(config, PCIMMAW2REG);
247
        }
248
        if (map->io != NULL) {
249
                s = map->io;
250
                config = (s->internal_base & 0xff000000) |
251
                         ((s->address_mask & 0x7f000000) >> 11) | (1UL << 12) |
252
                         ((s->pci_base & 0xff000000) >> 24);
253
                writel(config, PCIMIOAWREG);
254
        }
255
 
256
        /* Set target memory windows */
257
        writel(0x00081000, PCITAW1REG);
258
        writel(0UL, PCITAW2REG);
259
        pciu_write_config_dword(PCI_BASE_ADDRESS_0, 0UL);
260
        pciu_write_config_dword(PCI_BASE_ADDRESS_1, 0UL);
261
 
262
        /* Clear bus error */
263
        n = readl(BUSERRADREG);
264
 
265
        if (current_cpu_data.cputype == CPU_VR4122) {
266
                writel(0UL, PCITRDYVREG);
267
                pciu_write_config_dword(PCI_CACHE_LINE_SIZE, 0x0000f804);
268
        } else {
269
                writel(100UL, PCITRDYVREG);
270
                pciu_write_config_dword(PCI_CACHE_LINE_SIZE, 0x00008004);
271
        }
272
 
273
        writel(CONFIG_DONE, PCIENREG);
274
        pciu_write_config_dword(PCI_COMMAND,
275
                                PCI_COMMAND_IO |
276
                                PCI_COMMAND_MEMORY |
277
                                PCI_COMMAND_MASTER |
278
                                PCI_COMMAND_PARITY |
279
                                PCI_COMMAND_SERR);
280
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.