1 /*- 2 * Copyright (c) 2014 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 * Altera FPGA Manager. 33 * Chapter 4, Cyclone V Device Handbook (CV-5V2 2014.07.22) 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/bus.h> 39 #include <sys/kernel.h> 40 #include <sys/module.h> 41 #include <sys/malloc.h> 42 #include <sys/rman.h> 43 #include <sys/timeet.h> 44 #include <sys/timetc.h> 45 #include <sys/conf.h> 46 #include <sys/uio.h> 47 48 #include <dev/ofw/openfirm.h> 49 #include <dev/ofw/ofw_bus.h> 50 #include <dev/ofw/ofw_bus_subr.h> 51 52 #include <machine/bus.h> 53 #include <machine/cpu.h> 54 #include <machine/intr.h> 55 56 #include <arm/altera/socfpga/socfpga_common.h> 57 58 /* FPGA Manager Module Registers */ 59 #define FPGAMGR_STAT 0x0 /* Status Register */ 60 #define STAT_MSEL_MASK 0x1f 61 #define STAT_MSEL_SHIFT 3 62 #define STAT_MODE_SHIFT 0 63 #define STAT_MODE_MASK 0x7 64 #define FPGAMGR_CTRL 0x4 /* Control Register */ 65 #define CTRL_AXICFGEN (1 << 8) 66 #define CTRL_CDRATIO_MASK 0x3 67 #define CTRL_CDRATIO_SHIFT 6 68 #define CTRL_CFGWDTH_MASK 1 69 #define CTRL_CFGWDTH_SHIFT 9 70 #define CTRL_NCONFIGPULL (1 << 2) 71 #define CTRL_NCE (1 << 1) 72 #define CTRL_EN (1 << 0) 73 #define FPGAMGR_DCLKCNT 0x8 /* DCLK Count Register */ 74 #define FPGAMGR_DCLKSTAT 0xC /* DCLK Status Register */ 75 #define FPGAMGR_GPO 0x10 /* General-Purpose Output Register */ 76 #define FPGAMGR_GPI 0x14 /* General-Purpose Input Register */ 77 #define FPGAMGR_MISCI 0x18 /* Miscellaneous Input Register */ 78 79 /* Configuration Monitor (MON) Registers */ 80 #define GPIO_INTEN 0x830 /* Interrupt Enable Register */ 81 #define GPIO_INTMASK 0x834 /* Interrupt Mask Register */ 82 #define GPIO_INTTYPE_LEVEL 0x838 /* Interrupt Level Register */ 83 #define GPIO_INT_POLARITY 0x83C /* Interrupt Polarity Register */ 84 #define GPIO_INTSTATUS 0x840 /* Interrupt Status Register */ 85 #define GPIO_RAW_INTSTATUS 0x844 /* Raw Interrupt Status Register */ 86 #define GPIO_PORTA_EOI 0x84C /* Clear Interrupt Register */ 87 #define PORTA_EOI_NS (1 << 0) 88 #define GPIO_EXT_PORTA 0x850 /* External Port A Register */ 89 #define EXT_PORTA_CDP (1 << 10) /* Configuration done */ 90 #define GPIO_LS_SYNC 0x860 /* Synchronization Level Register */ 91 #define GPIO_VER_ID_CODE 0x86C /* GPIO Version Register */ 92 #define GPIO_CONFIG_REG2 0x870 /* Configuration Register 2 */ 93 #define GPIO_CONFIG_REG1 0x874 /* Configuration Register 1 */ 94 95 #define MSEL_PP16_FAST_NOAES_NODC 0x0 96 #define MSEL_PP16_FAST_AES_NODC 0x1 97 #define MSEL_PP16_FAST_AESOPT_DC 0x2 98 #define MSEL_PP16_SLOW_NOAES_NODC 0x4 99 #define MSEL_PP16_SLOW_AES_NODC 0x5 100 #define MSEL_PP16_SLOW_AESOPT_DC 0x6 101 #define MSEL_PP32_FAST_NOAES_NODC 0x8 102 #define MSEL_PP32_FAST_AES_NODC 0x9 103 #define MSEL_PP32_FAST_AESOPT_DC 0xa 104 #define MSEL_PP32_SLOW_NOAES_NODC 0xc 105 #define MSEL_PP32_SLOW_AES_NODC 0xd 106 #define MSEL_PP32_SLOW_AESOPT_DC 0xe 107 108 #define CFGWDTH_16 0 109 #define CFGWDTH_32 1 110 111 #define CDRATIO_1 0 112 #define CDRATIO_2 1 113 #define CDRATIO_4 2 114 #define CDRATIO_8 3 115 116 #define FPGAMGR_MODE_POWEROFF 0x0 117 #define FPGAMGR_MODE_RESET 0x1 118 #define FPGAMGR_MODE_CONFIG 0x2 119 #define FPGAMGR_MODE_INIT 0x3 120 #define FPGAMGR_MODE_USER 0x4 121 122 struct cfgmgr_mode { 123 int msel; 124 int cfgwdth; 125 int cdratio; 126 }; 127 128 static struct cfgmgr_mode cfgmgr_modes[] = { 129 { MSEL_PP16_FAST_NOAES_NODC, CFGWDTH_16, CDRATIO_1 }, 130 { MSEL_PP16_FAST_AES_NODC, CFGWDTH_16, CDRATIO_2 }, 131 { MSEL_PP16_FAST_AESOPT_DC, CFGWDTH_16, CDRATIO_4 }, 132 { MSEL_PP16_SLOW_NOAES_NODC, CFGWDTH_16, CDRATIO_1 }, 133 { MSEL_PP16_SLOW_AES_NODC, CFGWDTH_16, CDRATIO_2 }, 134 { MSEL_PP16_SLOW_AESOPT_DC, CFGWDTH_16, CDRATIO_4 }, 135 { MSEL_PP32_FAST_NOAES_NODC, CFGWDTH_32, CDRATIO_1 }, 136 { MSEL_PP32_FAST_AES_NODC, CFGWDTH_32, CDRATIO_4 }, 137 { MSEL_PP32_FAST_AESOPT_DC, CFGWDTH_32, CDRATIO_8 }, 138 { MSEL_PP32_SLOW_NOAES_NODC, CFGWDTH_32, CDRATIO_1 }, 139 { MSEL_PP32_SLOW_AES_NODC, CFGWDTH_32, CDRATIO_4 }, 140 { MSEL_PP32_SLOW_AESOPT_DC, CFGWDTH_32, CDRATIO_8 }, 141 { -1, -1, -1 }, 142 }; 143 144 struct fpgamgr_softc { 145 struct resource *res[3]; 146 bus_space_tag_t bst_data; 147 bus_space_handle_t bsh_data; 148 struct cdev *mgr_cdev; 149 device_t dev; 150 }; 151 152 static struct resource_spec fpgamgr_spec[] = { 153 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 154 { SYS_RES_MEMORY, 1, RF_ACTIVE }, 155 { SYS_RES_IRQ, 0, RF_ACTIVE }, 156 { -1, 0 } 157 }; 158 159 static int 160 fpgamgr_state_get(struct fpgamgr_softc *sc) 161 { 162 int reg; 163 164 reg = READ4(sc, FPGAMGR_STAT); 165 reg >>= STAT_MODE_SHIFT; 166 reg &= STAT_MODE_MASK; 167 168 return reg; 169 } 170 171 static int 172 fpgamgr_state_wait(struct fpgamgr_softc *sc, int state) 173 { 174 int tout; 175 176 tout = 1000; 177 while (tout > 0) { 178 if (fpgamgr_state_get(sc) == state) 179 break; 180 tout--; 181 DELAY(10); 182 } 183 if (tout == 0) { 184 return (1); 185 } 186 187 return (0); 188 } 189 190 static int 191 fpga_open(struct cdev *dev, int flags __unused, 192 int fmt __unused, struct thread *td __unused) 193 { 194 struct fpgamgr_softc *sc; 195 struct cfgmgr_mode *mode; 196 int msel; 197 int reg; 198 int i; 199 200 sc = dev->si_drv1; 201 202 msel = READ4(sc, FPGAMGR_STAT); 203 msel >>= STAT_MSEL_SHIFT; 204 msel &= STAT_MSEL_MASK; 205 206 mode = NULL; 207 for (i = 0; cfgmgr_modes[i].msel != -1; i++) { 208 if (msel == cfgmgr_modes[i].msel) { 209 mode = &cfgmgr_modes[i]; 210 break; 211 } 212 } 213 if (mode == NULL) { 214 device_printf(sc->dev, "Can't configure: unknown mode\n"); 215 return (ENXIO); 216 } 217 218 reg = READ4(sc, FPGAMGR_CTRL); 219 reg &= ~(CTRL_CDRATIO_MASK << CTRL_CDRATIO_SHIFT); 220 reg |= (mode->cdratio << CTRL_CDRATIO_SHIFT); 221 reg &= ~(CTRL_CFGWDTH_MASK << CTRL_CFGWDTH_SHIFT); 222 reg |= (mode->cfgwdth << CTRL_CFGWDTH_SHIFT); 223 reg &= ~(CTRL_NCE); 224 WRITE4(sc, FPGAMGR_CTRL, reg); 225 226 /* Enable configuration */ 227 reg = READ4(sc, FPGAMGR_CTRL); 228 reg |= (CTRL_EN); 229 WRITE4(sc, FPGAMGR_CTRL, reg); 230 231 /* Reset FPGA */ 232 reg = READ4(sc, FPGAMGR_CTRL); 233 reg |= (CTRL_NCONFIGPULL); 234 WRITE4(sc, FPGAMGR_CTRL, reg); 235 236 /* Wait reset state */ 237 if (fpgamgr_state_wait(sc, FPGAMGR_MODE_RESET)) { 238 device_printf(sc->dev, "Can't get RESET state\n"); 239 return (ENXIO); 240 } 241 242 /* Release from reset */ 243 reg = READ4(sc, FPGAMGR_CTRL); 244 reg &= ~(CTRL_NCONFIGPULL); 245 WRITE4(sc, FPGAMGR_CTRL, reg); 246 247 if (fpgamgr_state_wait(sc, FPGAMGR_MODE_CONFIG)) { 248 device_printf(sc->dev, "Can't get CONFIG state\n"); 249 return (ENXIO); 250 } 251 252 /* Clear nSTATUS edge interrupt */ 253 WRITE4(sc, GPIO_PORTA_EOI, PORTA_EOI_NS); 254 255 /* Enter configuration state */ 256 reg = READ4(sc, FPGAMGR_CTRL); 257 reg |= (CTRL_AXICFGEN); 258 WRITE4(sc, FPGAMGR_CTRL, reg); 259 260 return (0); 261 } 262 263 static int 264 fpga_wait_dclk_pulses(struct fpgamgr_softc *sc, int npulses) 265 { 266 int tout; 267 268 /* Clear done bit, if any */ 269 if (READ4(sc, FPGAMGR_DCLKSTAT) != 0) 270 WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1); 271 272 /* Request DCLK pulses */ 273 WRITE4(sc, FPGAMGR_DCLKCNT, npulses); 274 275 /* Wait finish */ 276 tout = 1000; 277 while (tout > 0) { 278 if (READ4(sc, FPGAMGR_DCLKSTAT) == 1) { 279 WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1); 280 break; 281 } 282 tout--; 283 DELAY(10); 284 } 285 if (tout == 0) { 286 return (1); 287 } 288 289 return (0); 290 } 291 292 static int 293 fpga_close(struct cdev *dev, int flags __unused, 294 int fmt __unused, struct thread *td __unused) 295 { 296 struct fpgamgr_softc *sc; 297 int reg; 298 299 sc = dev->si_drv1; 300 301 reg = READ4(sc, GPIO_EXT_PORTA); 302 if ((reg & EXT_PORTA_CDP) == 0) { 303 device_printf(sc->dev, "Err: configuration failed\n"); 304 return (ENXIO); 305 } 306 307 /* Exit configuration state */ 308 reg = READ4(sc, FPGAMGR_CTRL); 309 reg &= ~(CTRL_AXICFGEN); 310 WRITE4(sc, FPGAMGR_CTRL, reg); 311 312 /* Wait dclk pulses */ 313 if (fpga_wait_dclk_pulses(sc, 4)) { 314 device_printf(sc->dev, "Can't proceed 4 dclk pulses\n"); 315 return (ENXIO); 316 } 317 318 if (fpgamgr_state_wait(sc, FPGAMGR_MODE_USER)) { 319 device_printf(sc->dev, "Can't get USER mode\n"); 320 return (ENXIO); 321 } 322 323 /* Disable configuration */ 324 reg = READ4(sc, FPGAMGR_CTRL); 325 reg &= ~(CTRL_EN); 326 WRITE4(sc, FPGAMGR_CTRL, reg); 327 328 return (0); 329 } 330 331 static int 332 fpga_write(struct cdev *dev, struct uio *uio, int ioflag) 333 { 334 struct fpgamgr_softc *sc; 335 int buffer; 336 337 sc = dev->si_drv1; 338 339 /* 340 * Device supports 4-byte copy only. 341 * TODO: add padding for <4 bytes. 342 */ 343 344 while (uio->uio_resid > 0) { 345 uiomove(&buffer, 4, uio); 346 bus_space_write_4(sc->bst_data, sc->bsh_data, 347 0x0, buffer); 348 } 349 350 return (0); 351 } 352 353 static int 354 fpga_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, 355 struct thread *td) 356 { 357 358 return (0); 359 } 360 361 static struct cdevsw fpga_cdevsw = { 362 .d_version = D_VERSION, 363 .d_open = fpga_open, 364 .d_close = fpga_close, 365 .d_write = fpga_write, 366 .d_ioctl = fpga_ioctl, 367 .d_name = "FPGA Manager", 368 }; 369 370 static int 371 fpgamgr_probe(device_t dev) 372 { 373 374 if (!ofw_bus_status_okay(dev)) 375 return (ENXIO); 376 377 if (!ofw_bus_is_compatible(dev, "altr,socfpga-fpga-mgr")) 378 return (ENXIO); 379 380 device_set_desc(dev, "FPGA Manager"); 381 return (BUS_PROBE_DEFAULT); 382 } 383 384 static int 385 fpgamgr_attach(device_t dev) 386 { 387 struct fpgamgr_softc *sc; 388 389 sc = device_get_softc(dev); 390 sc->dev = dev; 391 392 if (bus_alloc_resources(dev, fpgamgr_spec, sc->res)) { 393 device_printf(dev, "could not allocate resources\n"); 394 return (ENXIO); 395 } 396 397 /* Memory interface */ 398 sc->bst_data = rman_get_bustag(sc->res[1]); 399 sc->bsh_data = rman_get_bushandle(sc->res[1]); 400 401 sc->mgr_cdev = make_dev(&fpga_cdevsw, 0, UID_ROOT, GID_WHEEL, 402 0600, "fpga%d", device_get_unit(sc->dev)); 403 404 if (sc->mgr_cdev == NULL) { 405 device_printf(dev, "Failed to create character device.\n"); 406 return (ENXIO); 407 } 408 409 sc->mgr_cdev->si_drv1 = sc; 410 411 return (0); 412 } 413 414 static device_method_t fpgamgr_methods[] = { 415 DEVMETHOD(device_probe, fpgamgr_probe), 416 DEVMETHOD(device_attach, fpgamgr_attach), 417 { 0, 0 } 418 }; 419 420 static driver_t fpgamgr_driver = { 421 "fpgamgr", 422 fpgamgr_methods, 423 sizeof(struct fpgamgr_softc), 424 }; 425 426 DRIVER_MODULE(fpgamgr, simplebus, fpgamgr_driver, 0, 0); 427