2 * Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
5 * This software was developed by SRI International and the University of
6 * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
7 * ("CTSRD"), as part of the DARPA CRASH research programme.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * Intel Arria 10 FPGA Manager.
33 * Chapter 4, Arria 10 Hard Processor System Technical Reference Manual.
34 * Chapter A, FPGA Reconfiguration.
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
40 #include <sys/param.h>
41 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/module.h>
45 #include <sys/malloc.h>
47 #include <sys/timeet.h>
48 #include <sys/timetc.h>
52 #include <dev/ofw/openfirm.h>
53 #include <dev/ofw/ofw_bus.h>
54 #include <dev/ofw/ofw_bus_subr.h>
56 #include <machine/bus.h>
57 #include <machine/cpu.h>
58 #include <machine/intr.h>
60 #include <arm/altera/socfpga/socfpga_common.h>
62 #define FPGAMGR_DCLKCNT 0x8 /* DCLK Count Register */
63 #define FPGAMGR_DCLKSTAT 0xC /* DCLK Status Register */
64 #define FPGAMGR_GPO 0x10 /* General-Purpose Output Register */
65 #define FPGAMGR_GPI 0x14 /* General-Purpose Input Register */
66 #define FPGAMGR_MISCI 0x18 /* Miscellaneous Input Register */
67 #define IMGCFG_CTRL_00 0x70
68 #define S2F_CONDONE_OE (1 << 24)
69 #define S2F_NSTATUS_OE (1 << 16)
70 #define CTRL_00_NCONFIG (1 << 8)
71 #define CTRL_00_NENABLE_CONDONE (1 << 2)
72 #define CTRL_00_NENABLE_NSTATUS (1 << 1)
73 #define CTRL_00_NENABLE_NCONFIG (1 << 0)
74 #define IMGCFG_CTRL_01 0x74
75 #define CTRL_01_S2F_NCE (1 << 24)
76 #define CTRL_01_S2F_PR_REQUEST (1 << 16)
77 #define CTRL_01_S2F_NENABLE_CONFIG (1 << 0)
78 #define IMGCFG_CTRL_02 0x78
79 #define CTRL_02_CDRATIO_S 16
80 #define CTRL_02_CDRATIO_M (0x3 << CTRL_02_CDRATIO_S)
81 #define CTRL_02_CFGWIDTH_16 (0 << 24)
82 #define CTRL_02_CFGWIDTH_32 (1 << 24)
83 #define CTRL_02_EN_CFG_DATA (1 << 8)
84 #define CTRL_02_EN_CFG_CTRL (1 << 0)
85 #define IMGCFG_STAT 0x80
86 #define F2S_PR_ERROR (1 << 11)
87 #define F2S_PR_DONE (1 << 10)
88 #define F2S_PR_READY (1 << 9)
90 #define F2S_MSEL_M (0x7 << F2S_MSEL_S)
91 #define MSEL_PASSIVE_FAST 0
92 #define MSEL_PASSIVE_SLOW 1
93 #define F2S_NCONFIG_PIN (1 << 12)
94 #define F2S_CONDONE_OE (1 << 7)
95 #define F2S_NSTATUS_PIN (1 << 4)
96 #define F2S_CONDONE_PIN (1 << 6)
97 #define F2S_USERMODE (1 << 2)
99 struct fpgamgr_a10_softc {
100 struct resource *res[2];
101 bus_space_tag_t bst_data;
102 bus_space_handle_t bsh_data;
103 struct cdev *mgr_cdev;
107 static struct resource_spec fpgamgr_a10_spec[] = {
108 { SYS_RES_MEMORY, 0, RF_ACTIVE },
109 { SYS_RES_MEMORY, 1, RF_ACTIVE },
114 fpga_wait_dclk_pulses(struct fpgamgr_a10_softc *sc, int npulses)
118 /* Clear done bit, if any */
119 if (READ4(sc, FPGAMGR_DCLKSTAT) != 0)
120 WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
122 /* Request DCLK pulses */
123 WRITE4(sc, FPGAMGR_DCLKCNT, npulses);
128 if (READ4(sc, FPGAMGR_DCLKSTAT) == 1) {
129 WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
136 device_printf(sc->dev,
137 "Error: dclkpulses wait timeout\n");
146 fpga_open(struct cdev *dev, int flags __unused,
147 int fmt __unused, struct thread *td __unused)
149 struct fpgamgr_a10_softc *sc;
157 reg = READ4(sc, IMGCFG_STAT);
158 if ((reg & F2S_USERMODE) == 0) {
159 device_printf(sc->dev, "Error: invalid mode\n");
164 reg = READ4(sc, IMGCFG_STAT);
165 msel = (reg & F2S_MSEL_M) >> F2S_MSEL_S;
166 if ((msel != MSEL_PASSIVE_FAST) && \
167 (msel != MSEL_PASSIVE_SLOW)) {
168 device_printf(sc->dev,
169 "Error: invalid msel %d\n", msel);
175 * TODO: add support for compressed, encrypted images.
177 reg = READ4(sc, IMGCFG_CTRL_02);
178 reg &= ~(CTRL_02_CDRATIO_M);
179 WRITE4(sc, IMGCFG_CTRL_02, reg);
181 reg = READ4(sc, IMGCFG_CTRL_02);
182 reg &= ~CTRL_02_CFGWIDTH_32;
183 WRITE4(sc, IMGCFG_CTRL_02, reg);
186 reg = READ4(sc, IMGCFG_CTRL_01);
187 reg &= ~CTRL_01_S2F_PR_REQUEST;
188 WRITE4(sc, IMGCFG_CTRL_01, reg);
190 reg = READ4(sc, IMGCFG_CTRL_00);
191 reg |= CTRL_00_NCONFIG;
192 WRITE4(sc, IMGCFG_CTRL_00, reg);
195 reg = READ4(sc, IMGCFG_CTRL_01);
196 reg &= ~CTRL_01_S2F_NCE;
197 WRITE4(sc, IMGCFG_CTRL_01, reg);
200 reg = READ4(sc, IMGCFG_CTRL_02);
201 reg |= CTRL_02_EN_CFG_CTRL;
202 WRITE4(sc, IMGCFG_CTRL_02, reg);
205 reg = READ4(sc, IMGCFG_CTRL_00);
206 reg &= ~S2F_CONDONE_OE;
207 reg &= ~S2F_NSTATUS_OE;
208 reg |= CTRL_00_NCONFIG;
209 reg |= CTRL_00_NENABLE_NSTATUS;
210 reg |= CTRL_00_NENABLE_CONDONE;
211 reg &= ~CTRL_00_NENABLE_NCONFIG;
212 WRITE4(sc, IMGCFG_CTRL_00, reg);
215 reg = READ4(sc, IMGCFG_CTRL_01);
216 reg &= ~CTRL_01_S2F_NENABLE_CONFIG;
217 WRITE4(sc, IMGCFG_CTRL_01, reg);
220 fpga_wait_dclk_pulses(sc, 0x100);
223 reg = READ4(sc, IMGCFG_CTRL_01);
224 reg |= CTRL_01_S2F_PR_REQUEST;
225 WRITE4(sc, IMGCFG_CTRL_01, reg);
228 fpga_wait_dclk_pulses(sc, 0x7ff);
233 reg = READ4(sc, IMGCFG_STAT);
234 if (reg & F2S_PR_ERROR) {
235 device_printf(sc->dev,
236 "Error: PR failed on open.\n");
239 if (reg & F2S_PR_READY) {
244 device_printf(sc->dev,
245 "Error: Timeout waiting PR ready bit.\n");
253 fpga_close(struct cdev *dev, int flags __unused,
254 int fmt __unused, struct thread *td __unused)
256 struct fpgamgr_a10_softc *sc;
265 reg = READ4(sc, IMGCFG_STAT);
266 if (reg & F2S_PR_ERROR) {
267 device_printf(sc->dev,
268 "Error: PR failed.\n");
271 if (reg & F2S_PR_DONE) {
277 reg = READ4(sc, IMGCFG_CTRL_01);
278 reg &= ~CTRL_01_S2F_PR_REQUEST;
279 WRITE4(sc, IMGCFG_CTRL_01, reg);
282 fpga_wait_dclk_pulses(sc, 0x100);
285 reg = READ4(sc, IMGCFG_CTRL_02);
286 reg &= ~CTRL_02_EN_CFG_CTRL;
287 WRITE4(sc, IMGCFG_CTRL_02, reg);
290 reg = READ4(sc, IMGCFG_CTRL_01);
291 reg |= CTRL_01_S2F_NCE;
292 WRITE4(sc, IMGCFG_CTRL_01, reg);
295 reg = READ4(sc, IMGCFG_CTRL_01);
296 reg |= CTRL_01_S2F_NENABLE_CONFIG;
297 WRITE4(sc, IMGCFG_CTRL_01, reg);
300 reg = READ4(sc, IMGCFG_STAT);
301 if ((reg & F2S_USERMODE) == 0) {
302 device_printf(sc->dev,
303 "Error: invalid mode\n");
307 if ((reg & F2S_CONDONE_PIN) == 0) {
308 device_printf(sc->dev,
309 "Error: configuration not done\n");
313 if ((reg & F2S_NSTATUS_PIN) == 0) {
314 device_printf(sc->dev,
315 "Error: nstatus pin\n");
323 fpga_write(struct cdev *dev, struct uio *uio, int ioflag)
325 struct fpgamgr_a10_softc *sc;
332 * Device supports 4-byte writes only.
335 while (uio->uio_resid >= 4) {
336 uiomove(&buffer, 4, uio);
337 bus_space_write_4(sc->bst_data, sc->bsh_data,
341 switch (uio->uio_resid) {
343 uiomove(&buffer, 3, uio);
345 bus_space_write_4(sc->bst_data, sc->bsh_data,
349 uiomove(&buffer, 2, uio);
351 bus_space_write_4(sc->bst_data, sc->bsh_data,
355 uiomove(&buffer, 1, uio);
357 bus_space_write_4(sc->bst_data, sc->bsh_data,
368 fpga_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
375 static struct cdevsw fpga_cdevsw = {
376 .d_version = D_VERSION,
378 .d_close = fpga_close,
379 .d_write = fpga_write,
380 .d_ioctl = fpga_ioctl,
381 .d_name = "FPGA Manager",
385 fpgamgr_a10_probe(device_t dev)
388 if (!ofw_bus_status_okay(dev))
391 if (!ofw_bus_is_compatible(dev, "altr,socfpga-a10-fpga-mgr"))
394 device_set_desc(dev, "Arria 10 FPGA Manager");
396 return (BUS_PROBE_DEFAULT);
400 fpgamgr_a10_attach(device_t dev)
402 struct fpgamgr_a10_softc *sc;
404 sc = device_get_softc(dev);
407 if (bus_alloc_resources(dev, fpgamgr_a10_spec, sc->res)) {
408 device_printf(dev, "Could not allocate resources.\n");
412 /* Memory interface */
413 sc->bst_data = rman_get_bustag(sc->res[1]);
414 sc->bsh_data = rman_get_bushandle(sc->res[1]);
416 sc->mgr_cdev = make_dev(&fpga_cdevsw, 0, UID_ROOT, GID_WHEEL,
417 0600, "fpga%d", device_get_unit(sc->dev));
419 if (sc->mgr_cdev == NULL) {
420 device_printf(dev, "Failed to create character device.\n");
424 sc->mgr_cdev->si_drv1 = sc;
429 static device_method_t fpgamgr_a10_methods[] = {
430 DEVMETHOD(device_probe, fpgamgr_a10_probe),
431 DEVMETHOD(device_attach, fpgamgr_a10_attach),
435 static driver_t fpgamgr_a10_driver = {
438 sizeof(struct fpgamgr_a10_softc),
441 static devclass_t fpgamgr_a10_devclass;
443 DRIVER_MODULE(fpgamgr_a10, simplebus, fpgamgr_a10_driver,
444 fpgamgr_a10_devclass, 0, 0);