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