1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2019 Ramon Fried <ramon.fried@gmail.com>
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <pci.h>
#include <pci_ep.h>
#include <asm/test.h>
/**
* struct sandbox_pci_ep_priv - private data for driver
* @hdr: Stores the EP device header
* @msix: required MSIx count;
* @msi: required MSI count;
*/
struct sandbox_pci_ep_priv {
struct pci_ep_header hdr;
struct pci_bar bars[6];
int msix;
int msi;
int irq_count;
};
/* Method exported for testing purposes */
int sandbox_get_pci_ep_irq_count(struct udevice *dev)
{
struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
return priv->irq_count;
}
static const struct udevice_id sandbox_pci_ep_ids[] = {
{ .compatible = "sandbox,pci_ep" },
{ }
};
static int sandbox_write_header(struct udevice *dev, uint fn,
struct pci_ep_header *hdr)
{
struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
if (fn > 0)
return -ENODEV;
memcpy(&priv->hdr, hdr, sizeof(*hdr));
return 0;
}
static int sandbox_read_header(struct udevice *dev, uint fn,
struct pci_ep_header *hdr)
{
struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
if (fn > 0)
return -ENODEV;
memcpy(hdr, &priv->hdr, sizeof(*hdr));
return 0;
}
static int sandbox_set_bar(struct udevice *dev, uint fn,
struct pci_bar *ep_bar)
{
struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
int bar_idx;
if (fn > 0)
return -ENODEV;
bar_idx = ep_bar->barno;
memcpy(&priv->bars[bar_idx], ep_bar, sizeof(*ep_bar));
return 0;
}
static int sandbox_read_bar(struct udevice *dev, uint fn,
struct pci_bar *ep_bar, enum pci_barno barno)
{
struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
if (fn > 0)
return -ENODEV;
memcpy(ep_bar, &priv->bars[barno], sizeof(*ep_bar));
return 0;
}
static int sandbox_set_msi(struct udevice *dev, uint fn, uint interrupts)
{
struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
if (fn > 0)
return -ENODEV;
priv->msi = interrupts;
return 0;
}
static int sandbox_get_msi(struct udevice *dev, uint fn)
{
struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
if (fn > 0)
return -ENODEV;
return priv->msi;
}
static int sandbox_set_msix(struct udevice *dev, uint fn, uint interrupts)
{
struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
if (fn > 0)
return -ENODEV;
priv->msix = interrupts;
return 0;
}
static int sandbox_get_msix(struct udevice *dev, uint fn)
{
struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
if (fn > 0)
return -ENODEV;
return priv->msix;
}
static int sandbox_raise_irq(struct udevice *dev, uint fn,
enum pci_ep_irq_type type, uint interrupt_num)
{
struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
if (fn > 0)
return -ENODEV;
priv->irq_count++;
return 0;
}
static int sandbox_pci_ep_probe(struct udevice *dev)
{
struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
memset(priv, 0, sizeof(*priv));
return 0;
}
static struct pci_ep_ops sandbox_pci_ep_ops = {
.write_header = sandbox_write_header,
.read_header = sandbox_read_header,
.set_bar = sandbox_set_bar,
.read_bar = sandbox_read_bar,
.set_msi = sandbox_set_msi,
.get_msi = sandbox_get_msi,
.set_msix = sandbox_set_msix,
.get_msix = sandbox_get_msix,
.raise_irq = sandbox_raise_irq,
};
U_BOOT_DRIVER(pci_ep_sandbox) = {
.name = "pci_ep_sandbox",
.id = UCLASS_PCI_EP,
.of_match = sandbox_pci_ep_ids,
.probe = sandbox_pci_ep_probe,
.ops = &sandbox_pci_ep_ops,
.priv_auto_alloc_size = sizeof(struct sandbox_pci_ep_priv),
};
|