Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/pci/ops-vr41xx.c
10817 views
1
/*
2
* ops-vr41xx.c, PCI configuration routines for the PCIU of NEC VR4100 series.
3
*
4
* Copyright (C) 2001-2003 MontaVista Software Inc.
5
* Author: Yoichi Yuasa <[email protected]>
6
* Copyright (C) 2004-2005 Yoichi Yuasa <[email protected]>
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
*/
22
/*
23
* Changes:
24
* MontaVista Software Inc. <[email protected]>
25
* - New creation, NEC VR4122 and VR4131 are supported.
26
*/
27
#include <linux/pci.h>
28
#include <linux/types.h>
29
30
#include <asm/io.h>
31
32
#define PCICONFDREG (void __iomem *)KSEG1ADDR(0x0f000c14)
33
#define PCICONFAREG (void __iomem *)KSEG1ADDR(0x0f000c18)
34
35
static inline int set_pci_configuration_address(unsigned char number,
36
unsigned int devfn, int where)
37
{
38
if (number == 0) {
39
/*
40
* Type 0 configuration
41
*/
42
if (PCI_SLOT(devfn) < 11 || where > 0xff)
43
return -EINVAL;
44
45
writel((1U << PCI_SLOT(devfn)) | (PCI_FUNC(devfn) << 8) |
46
(where & 0xfc), PCICONFAREG);
47
} else {
48
/*
49
* Type 1 configuration
50
*/
51
if (where > 0xff)
52
return -EINVAL;
53
54
writel(((uint32_t)number << 16) | ((devfn & 0xff) << 8) |
55
(where & 0xfc) | 1U, PCICONFAREG);
56
}
57
58
return 0;
59
}
60
61
static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where,
62
int size, uint32_t *val)
63
{
64
uint32_t data;
65
66
*val = 0xffffffffU;
67
if (set_pci_configuration_address(bus->number, devfn, where) < 0)
68
return PCIBIOS_DEVICE_NOT_FOUND;
69
70
data = readl(PCICONFDREG);
71
72
switch (size) {
73
case 1:
74
*val = (data >> ((where & 3) << 3)) & 0xffU;
75
break;
76
case 2:
77
*val = (data >> ((where & 2) << 3)) & 0xffffU;
78
break;
79
case 4:
80
*val = data;
81
break;
82
default:
83
return PCIBIOS_FUNC_NOT_SUPPORTED;
84
}
85
86
return PCIBIOS_SUCCESSFUL;
87
}
88
89
static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where,
90
int size, uint32_t val)
91
{
92
uint32_t data;
93
int shift;
94
95
if (set_pci_configuration_address(bus->number, devfn, where) < 0)
96
return PCIBIOS_DEVICE_NOT_FOUND;
97
98
data = readl(PCICONFDREG);
99
100
switch (size) {
101
case 1:
102
shift = (where & 3) << 3;
103
data &= ~(0xffU << shift);
104
data |= ((val & 0xffU) << shift);
105
break;
106
case 2:
107
shift = (where & 2) << 3;
108
data &= ~(0xffffU << shift);
109
data |= ((val & 0xffffU) << shift);
110
break;
111
case 4:
112
data = val;
113
break;
114
default:
115
return PCIBIOS_FUNC_NOT_SUPPORTED;
116
}
117
118
writel(data, PCICONFDREG);
119
120
return PCIBIOS_SUCCESSFUL;
121
}
122
123
struct pci_ops vr41xx_pci_ops = {
124
.read = pci_config_read,
125
.write = pci_config_write,
126
};
127
128