Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm64/qoriq/qoriq_dw_pci.c
39478 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright 2020 Michal Meloun <[email protected]>
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*
27
*/
28
29
/* Layerscape DesignWare PCIe driver */
30
31
#include <sys/param.h>
32
#include <sys/systm.h>
33
#include <sys/bus.h>
34
#include <sys/proc.h>
35
#include <sys/kernel.h>
36
#include <sys/malloc.h>
37
#include <sys/module.h>
38
#include <sys/mutex.h>
39
#include <sys/rman.h>
40
#include <sys/sysctl.h>
41
42
#include <machine/bus.h>
43
#include <machine/intr.h>
44
#include <machine/resource.h>
45
46
#include <dev/ofw/ofw_bus.h>
47
#include <dev/ofw/ofw_bus_subr.h>
48
#include <dev/ofw/ofw_pci.h>
49
#include <dev/ofw/ofwpci.h>
50
#include <dev/pci/pcivar.h>
51
#include <dev/pci/pcireg.h>
52
#include <dev/pci/pcib_private.h>
53
#include <dev/pci/pci_dw.h>
54
55
#include "pcib_if.h"
56
#include "pci_dw_if.h"
57
58
#define PCIE_ABSERR 0x8D0
59
60
struct qoriq_dw_pci_cfg {
61
uint32_t pex_pf0_dgb; /* offset of PEX_PF0_DBG register */
62
uint32_t ltssm_bit; /* LSB bit of LTSSM state field */
63
};
64
65
struct qorif_dw_pci_softc {
66
struct pci_dw_softc dw_sc;
67
device_t dev;
68
phandle_t node;
69
struct resource *irq_res;
70
void *intr_cookie;
71
struct qoriq_dw_pci_cfg *soc_cfg;
72
73
};
74
75
static struct qoriq_dw_pci_cfg ls1043_cfg = {
76
.pex_pf0_dgb = 0x10000 + 0x7FC,
77
.ltssm_bit = 24,
78
};
79
80
static struct qoriq_dw_pci_cfg ls1012_cfg = {
81
.pex_pf0_dgb = 0x80000 + 0x407FC,
82
.ltssm_bit = 24,
83
};
84
85
static struct qoriq_dw_pci_cfg ls2080_cfg = {
86
.pex_pf0_dgb = 0x80000 + 0x7FC,
87
.ltssm_bit = 0,
88
};
89
90
static struct qoriq_dw_pci_cfg ls2028_cfg = {
91
.pex_pf0_dgb = 0x80000 + 0x407FC,
92
.ltssm_bit = 0,
93
};
94
95
96
/* Compatible devices. */
97
static struct ofw_compat_data compat_data[] = {
98
{"fsl,ls1012a-pcie", (uintptr_t)&ls1012_cfg},
99
{"fsl,ls1028a-pcie", (uintptr_t)&ls2028_cfg},
100
{"fsl,ls1043a-pcie", (uintptr_t)&ls1043_cfg},
101
{"fsl,ls1046a-pcie", (uintptr_t)&ls1012_cfg},
102
{"fsl,ls2080a-pcie", (uintptr_t)&ls2080_cfg},
103
{"fsl,ls2085a-pcie", (uintptr_t)&ls2080_cfg},
104
{"fsl,ls2088a-pcie", (uintptr_t)&ls2028_cfg},
105
{"fsl,ls1088a-pcie", (uintptr_t)&ls2028_cfg},
106
{NULL, 0},
107
};
108
109
static void
110
qorif_dw_pci_dbi_protect(struct qorif_dw_pci_softc *sc, bool protect)
111
{
112
uint32_t reg;
113
114
reg = pci_dw_dbi_rd4(sc->dev, DW_MISC_CONTROL_1);
115
if (protect)
116
reg &= ~DBI_RO_WR_EN;
117
else
118
reg |= DBI_RO_WR_EN;
119
pci_dw_dbi_wr4(sc->dev, DW_MISC_CONTROL_1, reg);
120
}
121
122
static int qorif_dw_pci_intr(void *arg)
123
{
124
#if 0
125
struct qorif_dw_pci_softc *sc = arg;
126
uint32_t cause1, cause2;
127
128
/* Ack all interrups */
129
cause1 = pci_dw_dbi_rd4(sc->dev, MV_INT_CAUSE1);
130
cause2 = pci_dw_dbi_rd4(sc->dev, MV_INT_CAUSE2);
131
132
pci_dw_dbi_wr4(sc->dev, MV_INT_CAUSE1, cause1);
133
pci_dw_dbi_wr4(sc->dev, MV_INT_CAUSE2, cause2);
134
#endif
135
return (FILTER_HANDLED);
136
}
137
138
static int
139
qorif_dw_pci_get_link(device_t dev, bool *status)
140
{
141
struct qorif_dw_pci_softc *sc;
142
uint32_t reg;
143
144
sc = device_get_softc(dev);
145
reg = pci_dw_dbi_rd4(sc->dev, sc->soc_cfg->pex_pf0_dgb);
146
reg >>= sc->soc_cfg->ltssm_bit;
147
reg &= 0x3F;
148
*status = (reg == 0x11) ? true : false;
149
return (0);
150
}
151
152
static void
153
qorif_dw_pci_init(struct qorif_dw_pci_softc *sc)
154
{
155
156
// ls_pcie_disable_outbound_atus(pcie);
157
158
/* Forward error response */
159
pci_dw_dbi_wr4(sc->dev, PCIE_ABSERR, 0x9401);
160
161
qorif_dw_pci_dbi_protect(sc, true);
162
pci_dw_dbi_wr1(sc->dev, PCIR_HDRTYPE, 1);
163
qorif_dw_pci_dbi_protect(sc, false);
164
165
// ls_pcie_drop_msg_tlp(pcie);
166
167
}
168
169
static int
170
qorif_dw_pci_probe(device_t dev)
171
{
172
173
if (!ofw_bus_status_okay(dev))
174
return (ENXIO);
175
176
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
177
return (ENXIO);
178
179
device_set_desc(dev, "NPX Layaerscape PCI-E Controller");
180
return (BUS_PROBE_DEFAULT);
181
}
182
183
static int
184
qorif_dw_pci_attach(device_t dev)
185
{
186
struct resource_map_request req;
187
struct resource_map map;
188
struct qorif_dw_pci_softc *sc;
189
phandle_t node;
190
int rv;
191
int rid;
192
193
sc = device_get_softc(dev);
194
node = ofw_bus_get_node(dev);
195
sc->dev = dev;
196
sc->node = node;
197
sc->soc_cfg = (struct qoriq_dw_pci_cfg *)
198
ofw_bus_search_compatible(dev, compat_data)->ocd_data;
199
200
rid = 0;
201
sc->dw_sc.dbi_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
202
RF_ACTIVE | RF_UNMAPPED);
203
if (sc->dw_sc.dbi_res == NULL) {
204
device_printf(dev, "Cannot allocate DBI memory\n");
205
rv = ENXIO;
206
goto out;
207
}
208
209
resource_init_map_request(&req);
210
req.memattr = VM_MEMATTR_DEVICE_NP;
211
rv = bus_map_resource(dev, SYS_RES_MEMORY, sc->dw_sc.dbi_res, &req,
212
&map);
213
if (rv != 0) {
214
device_printf(dev, "could not map memory.\n");
215
return (rv);
216
}
217
rman_set_mapping(sc->dw_sc.dbi_res, &map);
218
219
/* PCI interrupt */
220
rid = 0;
221
sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
222
RF_ACTIVE | RF_SHAREABLE);
223
if (sc->irq_res == NULL) {
224
device_printf(dev, "Cannot allocate IRQ resources\n");
225
rv = ENXIO;
226
goto out;
227
}
228
229
rv = pci_dw_init(dev);
230
if (rv != 0)
231
goto out;
232
233
qorif_dw_pci_init(sc);
234
235
/* Setup interrupt */
236
if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
237
qorif_dw_pci_intr, NULL, sc, &sc->intr_cookie)) {
238
device_printf(dev, "cannot setup interrupt handler\n");
239
rv = ENXIO;
240
goto out;
241
}
242
243
bus_attach_children(dev);
244
return (0);
245
out:
246
/* XXX Cleanup */
247
return (rv);
248
}
249
250
static device_method_t qorif_dw_pci_methods[] = {
251
/* Device interface */
252
DEVMETHOD(device_probe, qorif_dw_pci_probe),
253
DEVMETHOD(device_attach, qorif_dw_pci_attach),
254
255
DEVMETHOD(pci_dw_get_link, qorif_dw_pci_get_link),
256
257
DEVMETHOD_END
258
};
259
260
DEFINE_CLASS_1(pcib, qorif_dw_pci_driver, qorif_dw_pci_methods,
261
sizeof(struct qorif_dw_pci_softc), pci_dw_driver);
262
DRIVER_MODULE( qorif_dw_pci, simplebus, qorif_dw_pci_driver, NULL, NULL);
263
264