1/*- 2 * Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com> 3 * All rights reserved. 4 * 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. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 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. 17 * 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 28 * SUCH DAMAGE. 29 */ 30 31/* 32 * Intel Arria 10 FPGA Manager. 33 * Chapter 4, Arria 10 Hard Processor System Technical Reference Manual. 34 * Chapter A, FPGA Reconfiguration. 35 */ 36 37#include <sys/cdefs.h> 38__FBSDID("$FreeBSD$"); 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/bus.h> 43#include <sys/kernel.h> 44#include <sys/module.h> 45#include <sys/malloc.h> 46#include <sys/rman.h> 47#include <sys/timeet.h> 48#include <sys/timetc.h> 49#include <sys/conf.h> 50#include <sys/uio.h> 51 52#include <dev/ofw/openfirm.h> 53#include <dev/ofw/ofw_bus.h> 54#include <dev/ofw/ofw_bus_subr.h> 55 56#include <machine/bus.h> 57#include <machine/cpu.h> 58#include <machine/intr.h> 59 60#include <arm/altera/socfpga/socfpga_common.h> 61 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) 89#define F2S_MSEL_S 16 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) 98 99struct 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; 104 device_t dev; 105}; 106 107static struct resource_spec fpgamgr_a10_spec[] = { 108 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 109 { SYS_RES_MEMORY, 1, RF_ACTIVE }, 110 { -1, 0 } 111}; 112 113static int 114fpga_wait_dclk_pulses(struct fpgamgr_a10_softc *sc, int npulses) 115{ 116 int tout; 117 118 /* Clear done bit, if any */ 119 if (READ4(sc, FPGAMGR_DCLKSTAT) != 0) 120 WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1); 121 122 /* Request DCLK pulses */ 123 WRITE4(sc, FPGAMGR_DCLKCNT, npulses); 124 125 /* Wait finish */ 126 tout = 1000; 127 while (tout > 0) { 128 if (READ4(sc, FPGAMGR_DCLKSTAT) == 1) { 129 WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1); 130 break; 131 } 132 tout--; 133 DELAY(10); 134 } 135 if (tout == 0) { 136 device_printf(sc->dev, 137 "Error: dclkpulses wait timeout\n"); 138 return (1); 139 } 140 141 return (0); 142} 143 144 145static int 146fpga_open(struct cdev *dev, int flags __unused, 147 int fmt __unused, struct thread *td __unused) 148{ 149 struct fpgamgr_a10_softc *sc; 150 int tout; 151 int msel; 152 int reg; 153 154 sc = dev->si_drv1; 155 156 /* Step 1 */ 157 reg = READ4(sc, IMGCFG_STAT); 158 if ((reg & F2S_USERMODE) == 0) { 159 device_printf(sc->dev, "Error: invalid mode\n"); 160 return (ENXIO); 161 }; 162 163 /* Step 2 */ 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); 170 return (ENXIO); 171 }; 172 173 /* 174 * Step 3. 175 * TODO: add support for compressed, encrypted images. 176 */ 177 reg = READ4(sc, IMGCFG_CTRL_02); 178 reg &= ~(CTRL_02_CDRATIO_M); 179 WRITE4(sc, IMGCFG_CTRL_02, reg); 180 181 reg = READ4(sc, IMGCFG_CTRL_02); 182 reg &= ~CTRL_02_CFGWIDTH_32; 183 WRITE4(sc, IMGCFG_CTRL_02, reg); 184 185 /* Step 4. a */ 186 reg = READ4(sc, IMGCFG_CTRL_01); 187 reg &= ~CTRL_01_S2F_PR_REQUEST; 188 WRITE4(sc, IMGCFG_CTRL_01, reg); 189 190 reg = READ4(sc, IMGCFG_CTRL_00); 191 reg |= CTRL_00_NCONFIG; 192 WRITE4(sc, IMGCFG_CTRL_00, reg); 193 194 /* b */ 195 reg = READ4(sc, IMGCFG_CTRL_01); 196 reg &= ~CTRL_01_S2F_NCE; 197 WRITE4(sc, IMGCFG_CTRL_01, reg); 198 199 /* c */ 200 reg = READ4(sc, IMGCFG_CTRL_02); 201 reg |= CTRL_02_EN_CFG_CTRL; 202 WRITE4(sc, IMGCFG_CTRL_02, reg); 203 204 /* d */ 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); 213 214 /* Step 5 */ 215 reg = READ4(sc, IMGCFG_CTRL_01); 216 reg &= ~CTRL_01_S2F_NENABLE_CONFIG; 217 WRITE4(sc, IMGCFG_CTRL_01, reg); 218 219 /* Step 6 */ 220 fpga_wait_dclk_pulses(sc, 0x100); 221 222 /* Step 7. a */ 223 reg = READ4(sc, IMGCFG_CTRL_01); 224 reg |= CTRL_01_S2F_PR_REQUEST; 225 WRITE4(sc, IMGCFG_CTRL_01, reg); 226 227 /* b, c */ 228 fpga_wait_dclk_pulses(sc, 0x7ff); 229 230 /* Step 8 */ 231 tout = 10; 232 while (tout--) { 233 reg = READ4(sc, IMGCFG_STAT); 234 if (reg & F2S_PR_ERROR) { 235 device_printf(sc->dev, 236 "Error: PR failed on open.\n"); 237 return (ENXIO); 238 } 239 if (reg & F2S_PR_READY) { 240 break; 241 } 242 } 243 if (tout == 0) { 244 device_printf(sc->dev, 245 "Error: Timeout waiting PR ready bit.\n"); 246 return (ENXIO); 247 } 248 249 return (0); 250} 251 252static int 253fpga_close(struct cdev *dev, int flags __unused, 254 int fmt __unused, struct thread *td __unused) 255{ 256 struct fpgamgr_a10_softc *sc; 257 int tout; 258 int reg; 259 260 sc = dev->si_drv1; 261 262 /* Step 10 */ 263 tout = 10; 264 while (tout--) { 265 reg = READ4(sc, IMGCFG_STAT); 266 if (reg & F2S_PR_ERROR) { 267 device_printf(sc->dev, 268 "Error: PR failed.\n"); 269 return (ENXIO); 270 } 271 if (reg & F2S_PR_DONE) { 272 break; 273 } 274 } 275 276 /* Step 11 */ 277 reg = READ4(sc, IMGCFG_CTRL_01); 278 reg &= ~CTRL_01_S2F_PR_REQUEST; 279 WRITE4(sc, IMGCFG_CTRL_01, reg); 280 281 /* Step 12, 13 */ 282 fpga_wait_dclk_pulses(sc, 0x100); 283 284 /* Step 14 */ 285 reg = READ4(sc, IMGCFG_CTRL_02); 286 reg &= ~CTRL_02_EN_CFG_CTRL; 287 WRITE4(sc, IMGCFG_CTRL_02, reg); 288 289 /* Step 15 */ 290 reg = READ4(sc, IMGCFG_CTRL_01); 291 reg |= CTRL_01_S2F_NCE; 292 WRITE4(sc, IMGCFG_CTRL_01, reg); 293 294 /* Step 16 */ 295 reg = READ4(sc, IMGCFG_CTRL_01); 296 reg |= CTRL_01_S2F_NENABLE_CONFIG; 297 WRITE4(sc, IMGCFG_CTRL_01, reg); 298 299 /* Step 17 */ 300 reg = READ4(sc, IMGCFG_STAT); 301 if ((reg & F2S_USERMODE) == 0) { 302 device_printf(sc->dev, 303 "Error: invalid mode\n"); 304 return (ENXIO); 305 }; 306 307 if ((reg & F2S_CONDONE_PIN) == 0) { 308 device_printf(sc->dev, 309 "Error: configuration not done\n"); 310 return (ENXIO); 311 }; 312 313 if ((reg & F2S_NSTATUS_PIN) == 0) { 314 device_printf(sc->dev, 315 "Error: nstatus pin\n"); 316 return (ENXIO); 317 }; 318 319 return (0); 320} 321 322static int 323fpga_write(struct cdev *dev, struct uio *uio, int ioflag) 324{ 325 struct fpgamgr_a10_softc *sc; 326 uint32_t buffer; 327 328 sc = dev->si_drv1; 329 330 /* 331 * Step 9. 332 * Device supports 4-byte writes only. 333 */ 334 335 while (uio->uio_resid >= 4) { 336 uiomove(&buffer, 4, uio); 337 bus_space_write_4(sc->bst_data, sc->bsh_data, 338 0x0, buffer); 339 } 340 341 switch (uio->uio_resid) { 342 case 3: 343 uiomove(&buffer, 3, uio); 344 buffer &= 0xffffff; 345 bus_space_write_4(sc->bst_data, sc->bsh_data, 346 0x0, buffer); 347 break; 348 case 2: 349 uiomove(&buffer, 2, uio); 350 buffer &= 0xffff; 351 bus_space_write_4(sc->bst_data, sc->bsh_data, 352 0x0, buffer); 353 break; 354 case 1: 355 uiomove(&buffer, 1, uio); 356 buffer &= 0xff; 357 bus_space_write_4(sc->bst_data, sc->bsh_data, 358 0x0, buffer); 359 break; 360 default: 361 break; 362 }; 363 364 return (0); 365} 366 367static int 368fpga_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, 369 struct thread *td) 370{ 371 372 return (0); 373} 374 375static struct cdevsw fpga_cdevsw = { 376 .d_version = D_VERSION, 377 .d_open = fpga_open, 378 .d_close = fpga_close, 379 .d_write = fpga_write, 380 .d_ioctl = fpga_ioctl, 381 .d_name = "FPGA Manager", 382}; 383 384static int 385fpgamgr_a10_probe(device_t dev) 386{ 387 388 if (!ofw_bus_status_okay(dev)) 389 return (ENXIO); 390 391 if (!ofw_bus_is_compatible(dev, "altr,socfpga-a10-fpga-mgr")) 392 return (ENXIO); 393 394 device_set_desc(dev, "Arria 10 FPGA Manager"); 395 396 return (BUS_PROBE_DEFAULT); 397} 398 399static int 400fpgamgr_a10_attach(device_t dev) 401{ 402 struct fpgamgr_a10_softc *sc; 403 404 sc = device_get_softc(dev); 405 sc->dev = dev; 406 407 if (bus_alloc_resources(dev, fpgamgr_a10_spec, sc->res)) { 408 device_printf(dev, "Could not allocate resources.\n"); 409 return (ENXIO); 410 } 411 412 /* Memory interface */ 413 sc->bst_data = rman_get_bustag(sc->res[1]); 414 sc->bsh_data = rman_get_bushandle(sc->res[1]); 415 416 sc->mgr_cdev = make_dev(&fpga_cdevsw, 0, UID_ROOT, GID_WHEEL, 417 0600, "fpga%d", device_get_unit(sc->dev)); 418 419 if (sc->mgr_cdev == NULL) { 420 device_printf(dev, "Failed to create character device.\n"); 421 return (ENXIO); 422 } 423 424 sc->mgr_cdev->si_drv1 = sc; 425 426 return (0); 427} 428 429static device_method_t fpgamgr_a10_methods[] = { 430 DEVMETHOD(device_probe, fpgamgr_a10_probe), 431 DEVMETHOD(device_attach, fpgamgr_a10_attach), 432 { 0, 0 } 433}; 434 435static driver_t fpgamgr_a10_driver = { 436 "fpgamgr_a10", 437 fpgamgr_a10_methods, 438 sizeof(struct fpgamgr_a10_softc), 439}; 440 441static devclass_t fpgamgr_a10_devclass; 442 443DRIVER_MODULE(fpgamgr_a10, simplebus, fpgamgr_a10_driver, 444 fpgamgr_a10_devclass, 0, 0); 445