1 /*- 2 * Copyright (c) 2013 Thomas Skibo 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 /* 30 * Zynq-7000 Devcfg driver. This allows programming the PL (FPGA) section 31 * of Zynq. 32 * 33 * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual. 34 * (v1.4) November 16, 2012. Xilinx doc UG585. PL Configuration is 35 * covered in section 6.4.5. 36 */ 37 38 #include <sys/cdefs.h> 39 __FBSDID("$FreeBSD$"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/conf.h> 44 #include <sys/kernel.h> 45 #include <sys/module.h> 46 #include <sys/sysctl.h> 47 #include <sys/lock.h> 48 #include <sys/mutex.h> 49 #include <sys/resource.h> 50 #include <sys/rman.h> 51 #include <sys/uio.h> 52 53 #include <machine/bus.h> 54 #include <machine/resource.h> 55 #include <machine/stdarg.h> 56 57 #include <dev/fdt/fdt_common.h> 58 #include <dev/ofw/ofw_bus.h> 59 #include <dev/ofw/ofw_bus_subr.h> 60 61 #include <arm/xilinx/zy7_slcr.h> 62 63 struct zy7_devcfg_softc { 64 device_t dev; 65 struct mtx sc_mtx; 66 struct resource *mem_res; 67 struct resource *irq_res; 68 struct cdev *sc_ctl_dev; 69 void *intrhandle; 70 71 bus_dma_tag_t dma_tag; 72 bus_dmamap_t dma_map; 73 74 int is_open; 75 76 struct sysctl_ctx_list sysctl_tree; 77 struct sysctl_oid *sysctl_tree_top; 78 }; 79 80 static struct zy7_devcfg_softc *zy7_devcfg_softc_p; 81 82 #define FCLK_NUM 4 83 84 struct zy7_fclk_config { 85 int source; 86 int frequency; 87 int actual_frequency; 88 }; 89 90 static struct zy7_fclk_config fclk_configs[FCLK_NUM]; 91 92 #define DEVCFG_SC_LOCK(sc) mtx_lock(&(sc)->sc_mtx) 93 #define DEVCFG_SC_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) 94 #define DEVCFG_SC_LOCK_INIT(sc) \ 95 mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), \ 96 "zy7_devcfg", MTX_DEF) 97 #define DEVCFG_SC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx); 98 #define DEVCFG_SC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED); 99 100 #define RD4(sc, off) (bus_read_4((sc)->mem_res, (off))) 101 #define WR4(sc, off, val) (bus_write_4((sc)->mem_res, (off), (val))) 102 103 SYSCTL_NODE(_hw, OID_AUTO, fpga, CTLFLAG_RD, 0, \ 104 "Xilinx Zynq-7000 PL (FPGA) section"); 105 106 static int zy7_devcfg_sysctl_pl_done(SYSCTL_HANDLER_ARGS); 107 SYSCTL_PROC(_hw_fpga, OID_AUTO, pl_done, CTLTYPE_INT | CTLFLAG_RD, NULL, 0, 108 zy7_devcfg_sysctl_pl_done, "I", "PL section config DONE signal"); 109 110 static int zy7_en_level_shifters = 1; 111 SYSCTL_INT(_hw_fpga, OID_AUTO, en_level_shifters, CTLFLAG_RW, 112 &zy7_en_level_shifters, 0, 113 "Enable PS-PL level shifters after device config"); 114 115 static int zy7_ps_vers = 0; 116 SYSCTL_INT(_hw, OID_AUTO, ps_vers, CTLFLAG_RD, &zy7_ps_vers, 0, 117 "Zynq-7000 PS version"); 118 119 static int zy7_devcfg_fclk_sysctl_level_shifters(SYSCTL_HANDLER_ARGS); 120 SYSCTL_PROC(_hw_fpga, OID_AUTO, level_shifters, 121 CTLFLAG_RW | CTLTYPE_INT, 122 NULL, 0, zy7_devcfg_fclk_sysctl_level_shifters, 123 "I", "Enable/disable level shifters"); 124 125 /* cdev entry points. */ 126 static int zy7_devcfg_open(struct cdev *, int, int, struct thread *); 127 static int zy7_devcfg_write(struct cdev *, struct uio *, int); 128 static int zy7_devcfg_close(struct cdev *, int, int, struct thread *); 129 130 struct cdevsw zy7_devcfg_cdevsw = { 131 .d_version = D_VERSION, 132 .d_open = zy7_devcfg_open, 133 .d_write = zy7_devcfg_write, 134 .d_close = zy7_devcfg_close, 135 .d_name = "devcfg", 136 }; 137 138 /* Devcfg block registers. */ 139 #define ZY7_DEVCFG_CTRL 0x0000 140 #define ZY7_DEVCFG_CTRL_FORCE_RST (1<<31) 141 #define ZY7_DEVCFG_CTRL_PCFG_PROG_B (1<<30) 142 #define ZY7_DEVCFG_CTRL_PCFG_POR_CNT_4K (1<<29) 143 #define ZY7_DEVCFG_CTRL_PCAP_PR (1<<27) 144 #define ZY7_DEVCFG_CTRL_PCAP_MODE (1<<26) 145 #define ZY7_DEVCFG_CTRL_QTR_PCAP_RATE_EN (1<<25) 146 #define ZY7_DEVCFG_CTRL_MULTIBOOT_EN (1<<24) 147 #define ZY7_DEVCFG_CTRL_JTAG_CHAIN_DIS (1<<23) 148 #define ZY7_DEVCFG_CTRL_USER_MODE (1<<15) 149 #define ZY7_DEVCFG_CTRL_RESVD_WR11 (3<<13) /* always write 11 */ 150 #define ZY7_DEVCFG_CTRL_PCFG_AES_FUSE (1<<12) 151 #define ZY7_DEVCFG_CTRL_PCFG_AES_EN_MASK (7<<9) /* all 1's or 0's */ 152 #define ZY7_DEVCFG_CTRL_SEU_EN (1<<8) 153 #define ZY7_DEVCFG_CTRL_SEC_EN (1<<7) 154 #define ZY7_DEVCFG_CTRL_SPNIDEN (1<<6) 155 #define ZY7_DEVCFG_CTRL_SPIDEN (1<<5) 156 #define ZY7_DEVCFG_CTRL_NIDEN (1<<4) 157 #define ZY7_DEVCFG_CTRL_DBGEN (1<<3) 158 #define ZY7_DEVCFG_CTRL_DAP_EN_MASK (7<<0) /* all 1's to enable */ 159 160 #define ZY7_DEVCFG_LOCK 0x004 161 #define ZY7_DEVCFG_LOCK_AES_FUSE_LOCK (1<<4) 162 #define ZY7_DEVCFG_LOCK_AES_EN (1<<3) 163 #define ZY7_DEVCFG_LOCK_SEU_LOCK (1<<2) 164 #define ZY7_DEVCFG_LOCK_SEC_LOCK (1<<1) 165 #define ZY7_DEVCFG_LOCK_DBG_LOCK (1<<0) 166 167 #define ZY7_DEVCFG_CFG 0x008 168 #define ZY7_DEVCFG_CFG_RFIFO_TH_MASK (3<<10) 169 #define ZY7_DEVCFG_CFG_WFIFO_TH_MASK (3<<8) 170 #define ZY7_DEVCFG_CFG_RCLK_EDGE (1<<7) 171 #define ZY7_DEVCFG_CFG_WCLK_EDGE (1<<6) 172 #define ZY7_DEVCFG_CFG_DIS_SRC_INC (1<<5) 173 #define ZY7_DEVCFG_CFG_DIS_DST_INC (1<<4) 174 175 #define ZY7_DEVCFG_INT_STATUS 0x00C 176 #define ZY7_DEVCFG_INT_MASK 0x010 177 #define ZY7_DEVCFG_INT_PSS_GTS_USR_B (1<<31) 178 #define ZY7_DEVCFG_INT_PSS_FST_CFG_B (1<<30) 179 #define ZY7_DEVCFG_INT_PSS_GPWRDWN_B (1<<29) 180 #define ZY7_DEVCFG_INT_PSS_GTS_CFG_B (1<<28) 181 #define ZY7_DEVCFG_INT_CFG_RESET_B (1<<27) 182 #define ZY7_DEVCFG_INT_AXI_WTO (1<<23) /* axi write timeout */ 183 #define ZY7_DEVCFG_INT_AXI_WERR (1<<22) /* axi write err */ 184 #define ZY7_DEVCFG_INT_AXI_RTO (1<<21) /* axi read timeout */ 185 #define ZY7_DEVCFG_INT_AXI_RERR (1<<20) /* axi read err */ 186 #define ZY7_DEVCFG_INT_RX_FIFO_OV (1<<18) /* rx fifo overflow */ 187 #define ZY7_DEVCFG_INT_WR_FIFO_LVL (1<<17) /* wr fifo < level */ 188 #define ZY7_DEVCFG_INT_RD_FIFO_LVL (1<<16) /* rd fifo >= level */ 189 #define ZY7_DEVCFG_INT_DMA_CMD_ERR (1<<15) 190 #define ZY7_DEVCFG_INT_DMA_Q_OV (1<<14) 191 #define ZY7_DEVCFG_INT_DMA_DONE (1<<13) 192 #define ZY7_DEVCFG_INT_DMA_PCAP_DONE (1<<12) 193 #define ZY7_DEVCFG_INT_P2D_LEN_ERR (1<<11) 194 #define ZY7_DEVCFG_INT_PCFG_HMAC_ERR (1<<6) 195 #define ZY7_DEVCFG_INT_PCFG_SEU_ERR (1<<5) 196 #define ZY7_DEVCFG_INT_PCFG_POR_B (1<<4) 197 #define ZY7_DEVCFG_INT_PCFG_CFG_RST (1<<3) 198 #define ZY7_DEVCFG_INT_PCFG_DONE (1<<2) 199 #define ZY7_DEVCFG_INT_PCFG_INIT_PE (1<<1) 200 #define ZY7_DEVCFG_INT_PCFG_INIT_NE (1<<0) 201 #define ZY7_DEVCFG_INT_ERRORS 0x00f0f860 202 #define ZY7_DEVCFG_INT_ALL 0xf8f7f87f 203 204 #define ZY7_DEVCFG_STATUS 0x014 205 #define ZY7_DEVCFG_STATUS_DMA_CMD_Q_F (1<<31) /* cmd queue full */ 206 #define ZY7_DEVCFG_STATUS_DMA_CMD_Q_E (1<<30) /* cmd queue empty */ 207 #define ZY7_DEVCFG_STATUS_DONE_COUNT_MASK (3<<28) 208 #define ZY7_DEVCFG_STATUS_DONE_COUNT_SHIFT 28 209 #define ZY7_DEVCFG_STATUS_RX_FIFO_LVL_MASK (0x1f<<20) 210 #define ZY7_DEVCFG_STATUS_RX_FIFO_LVL_SHIFT 20 211 #define ZY7_DEVCFG_STATUS_TX_FIFO_LVL_MASK (0x7f<<12) 212 #define ZY7_DEVCFG_STATUS_TX_FIFO_LVL_SHIFT 12 213 #define ZY7_DEVCFG_STATUS_PSS_GTS_USR_B (1<<11) 214 #define ZY7_DEVCFG_STATUS_PSS_FST_CFG_B (1<<10) 215 #define ZY7_DEVCFG_STATUS_PSS_GPWRDWN_B (1<<9) 216 #define ZY7_DEVCFG_STATUS_PSS_GTS_CFG_B (1<<8) 217 #define ZY7_DEVCFG_STATUS_ILL_APB_ACCE (1<<6) 218 #define ZY7_DEVCFG_STATUS_PSS_CFG_RESET_B (1<<5) 219 #define ZY7_DEVCFG_STATUS_PCFG_INIT (1<<4) 220 #define ZY7_DEVCFG_STATUS_EFUSE_BBRAM_KEY_DIS (1<<3) 221 #define ZY7_DEVCFG_STATUS_EFUSE_SEC_EN (1<<2) 222 #define ZY7_DEVCFG_STATUS_EFUSE_JTAG_DIS (1<<1) 223 224 #define ZY7_DEVCFG_DMA_SRC_ADDR 0x018 225 #define ZY7_DEVCFG_DMA_DST_ADDR 0x01c 226 #define ZY7_DEVCFG_DMA_ADDR_WAIT_PCAP 1 227 #define ZY7_DEVCFG_DMA_ADDR_ILLEGAL 0xffffffff 228 229 #define ZY7_DEVCFG_DMA_SRC_LEN 0x020 /* in 4-byte words. */ 230 #define ZY7_DEVCFG_DMA_SRC_LEN_MAX 0x7ffffff 231 #define ZY7_DEVCFG_DMA_DST_LEN 0x024 232 #define ZY7_DEVCFG_ROM_SHADOW 0x028 233 #define ZY7_DEVCFG_MULTIBOOT_ADDR 0x02c 234 #define ZY7_DEVCFG_SW_ID 0x030 235 #define ZY7_DEVCFG_UNLOCK 0x034 236 #define ZY7_DEVCFG_UNLOCK_MAGIC 0x757bdf0d 237 #define ZY7_DEVCFG_MCTRL 0x080 238 #define ZY7_DEVCFG_MCTRL_PS_VERS_MASK (0xf<<28) 239 #define ZY7_DEVCFG_MCTRL_PS_VERS_SHIFT 28 240 #define ZY7_DEVCFG_MCTRL_PCFG_POR_B (1<<8) 241 #define ZY7_DEVCFG_MCTRL_INT_PCAP_LPBK (1<<4) 242 #define ZY7_DEVCFG_XADCIF_CFG 0x100 243 #define ZY7_DEVCFG_XADCIF_INT_STAT 0x104 244 #define ZY7_DEVCFG_XADCIF_INT_MASK 0x108 245 #define ZY7_DEVCFG_XADCIF_MSTS 0x10c 246 #define ZY7_DEVCFG_XADCIF_CMD_FIFO 0x110 247 #define ZY7_DEVCFG_XADCIF_RD_FIFO 0x114 248 #define ZY7_DEVCFG_XADCIF_MCTL 0x118 249 250 static int 251 zy7_devcfg_fclk_sysctl_source(SYSCTL_HANDLER_ARGS) 252 { 253 char buf[4]; 254 struct zy7_fclk_config *cfg; 255 int unit; 256 int error; 257 258 cfg = arg1; 259 unit = arg2; 260 261 switch (cfg->source) { 262 case ZY7_PL_FCLK_SRC_IO: 263 case ZY7_PL_FCLK_SRC_IO_ALT: 264 strncpy(buf, "IO", sizeof(buf)); 265 break; 266 case ZY7_PL_FCLK_SRC_DDR: 267 strncpy(buf, "DDR", sizeof(buf)); 268 break; 269 case ZY7_PL_FCLK_SRC_ARM: 270 strncpy(buf, "ARM", sizeof(buf)); 271 break; 272 default: 273 strncpy(buf, "???", sizeof(buf)); 274 break; 275 } 276 277 error = sysctl_handle_string(oidp, buf, sizeof(buf), req); 278 if (error != 0 || req->newptr == NULL) 279 return (error); 280 281 if (strcasecmp(buf, "io") == 0) 282 cfg->source = ZY7_PL_FCLK_SRC_IO; 283 else if (strcasecmp(buf, "ddr") == 0) 284 cfg->source = ZY7_PL_FCLK_SRC_DDR; 285 else if (strcasecmp(buf, "arm") == 0) 286 cfg->source = ZY7_PL_FCLK_SRC_ARM; 287 else 288 return (EINVAL); 289 290 zy7_pl_fclk_set_source(unit, cfg->source); 291 if (cfg->frequency > 0) 292 cfg->actual_frequency = zy7_pl_fclk_get_freq(unit); 293 294 return (0); 295 } 296 297 static int 298 zy7_devcfg_fclk_sysctl_freq(SYSCTL_HANDLER_ARGS) 299 { 300 struct zy7_fclk_config *cfg; 301 int unit; 302 int error; 303 int freq; 304 int new_actual_freq; 305 306 cfg = arg1; 307 unit = arg2; 308 309 freq = cfg->frequency; 310 311 error = sysctl_handle_int(oidp, &freq, 0, req); 312 if (error != 0 || req->newptr == NULL) 313 return (error); 314 315 if (freq > 0) { 316 new_actual_freq = zy7_pl_fclk_set_freq(unit, freq); 317 if (new_actual_freq < 0) 318 return (EINVAL); 319 if (!zy7_pl_fclk_enabled(unit)) 320 zy7_pl_fclk_enable(unit); 321 } 322 else { 323 zy7_pl_fclk_disable(unit); 324 new_actual_freq = 0; 325 } 326 327 cfg->frequency = freq; 328 cfg->actual_frequency = new_actual_freq; 329 330 return (0); 331 } 332 333 static int 334 zy7_devcfg_fclk_sysctl_level_shifters(SYSCTL_HANDLER_ARGS) 335 { 336 int error, enabled; 337 338 enabled = zy7_pl_level_shifters_enabled(); 339 340 error = sysctl_handle_int(oidp, &enabled, 0, req); 341 if (error != 0 || req->newptr == NULL) 342 return (error); 343 344 if (enabled) 345 zy7_pl_level_shifters_enable(); 346 else 347 zy7_pl_level_shifters_disable(); 348 349 return (0); 350 } 351 352 static int 353 zy7_devcfg_init_fclk_sysctl(struct zy7_devcfg_softc *sc) 354 { 355 struct sysctl_oid *fclk_node; 356 char fclk_num[4]; 357 int i; 358 359 sysctl_ctx_init(&sc->sysctl_tree); 360 sc->sysctl_tree_top = SYSCTL_ADD_NODE(&sc->sysctl_tree, 361 SYSCTL_STATIC_CHILDREN(_hw_fpga), OID_AUTO, "fclk", 362 CTLFLAG_RD, 0, ""); 363 if (sc->sysctl_tree_top == NULL) { 364 sysctl_ctx_free(&sc->sysctl_tree); 365 return (-1); 366 } 367 368 for (i = 0; i < FCLK_NUM; i++) { 369 snprintf(fclk_num, sizeof(fclk_num), "%d", i); 370 fclk_node = SYSCTL_ADD_NODE(&sc->sysctl_tree, 371 SYSCTL_CHILDREN(sc->sysctl_tree_top), OID_AUTO, fclk_num, 372 CTLFLAG_RD, 0, ""); 373 374 SYSCTL_ADD_INT(&sc->sysctl_tree, 375 SYSCTL_CHILDREN(fclk_node), OID_AUTO, 376 "actual_freq", CTLFLAG_RD, 377 &fclk_configs[i].actual_frequency, i, 378 "Actual frequency"); 379 SYSCTL_ADD_PROC(&sc->sysctl_tree, 380 SYSCTL_CHILDREN(fclk_node), OID_AUTO, 381 "freq", CTLFLAG_RW | CTLTYPE_INT, 382 &fclk_configs[i], i, 383 zy7_devcfg_fclk_sysctl_freq, 384 "I", "Configured frequency"); 385 SYSCTL_ADD_PROC(&sc->sysctl_tree, 386 SYSCTL_CHILDREN(fclk_node), OID_AUTO, 387 "source", CTLFLAG_RW | CTLTYPE_STRING, 388 &fclk_configs[i], i, 389 zy7_devcfg_fclk_sysctl_source, 390 "A", "Clock source"); 391 } 392 393 return (0); 394 } 395 396 /* Enable programming the PL through PCAP. */ 397 static void 398 zy7_devcfg_init_hw(struct zy7_devcfg_softc *sc) 399 { 400 401 DEVCFG_SC_ASSERT_LOCKED(sc); 402 403 /* Set devcfg control register. */ 404 WR4(sc, ZY7_DEVCFG_CTRL, 405 ZY7_DEVCFG_CTRL_PCFG_PROG_B | 406 ZY7_DEVCFG_CTRL_PCAP_PR | 407 ZY7_DEVCFG_CTRL_PCAP_MODE | 408 ZY7_DEVCFG_CTRL_USER_MODE | 409 ZY7_DEVCFG_CTRL_RESVD_WR11 | 410 ZY7_DEVCFG_CTRL_SPNIDEN | 411 ZY7_DEVCFG_CTRL_SPIDEN | 412 ZY7_DEVCFG_CTRL_NIDEN | 413 ZY7_DEVCFG_CTRL_DBGEN | 414 ZY7_DEVCFG_CTRL_DAP_EN_MASK); 415 416 /* Turn off internal PCAP loopback. */ 417 WR4(sc, ZY7_DEVCFG_MCTRL, RD4(sc, ZY7_DEVCFG_MCTRL) & 418 ~ZY7_DEVCFG_MCTRL_INT_PCAP_LPBK); 419 } 420 421 /* Clear previous configuration of the PL by asserting PROG_B. */ 422 static int 423 zy7_devcfg_reset_pl(struct zy7_devcfg_softc *sc) 424 { 425 uint32_t devcfg_ctl; 426 int tries, err; 427 428 DEVCFG_SC_ASSERT_LOCKED(sc); 429 430 devcfg_ctl = RD4(sc, ZY7_DEVCFG_CTRL); 431 432 /* Clear sticky bits and set up INIT signal positive edge interrupt. */ 433 WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL); 434 WR4(sc, ZY7_DEVCFG_INT_MASK, ~ZY7_DEVCFG_INT_PCFG_INIT_PE); 435 436 /* Deassert PROG_B (active low). */ 437 devcfg_ctl |= ZY7_DEVCFG_CTRL_PCFG_PROG_B; 438 WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl); 439 440 /* 441 * Wait for INIT to assert. If it is already asserted, we may not get 442 * an edge interrupt so cancel it and continue. 443 */ 444 if ((RD4(sc, ZY7_DEVCFG_STATUS) & 445 ZY7_DEVCFG_STATUS_PCFG_INIT) != 0) { 446 /* Already asserted. Cancel interrupt. */ 447 WR4(sc, ZY7_DEVCFG_INT_MASK, ~0); 448 } 449 else { 450 /* Wait for positive edge interrupt. */ 451 err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7i1", hz); 452 if (err != 0) 453 return (err); 454 } 455 456 /* Reassert PROG_B (active low). */ 457 devcfg_ctl &= ~ZY7_DEVCFG_CTRL_PCFG_PROG_B; 458 WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl); 459 460 /* Wait for INIT deasserted. This happens almost instantly. */ 461 tries = 0; 462 while ((RD4(sc, ZY7_DEVCFG_STATUS) & 463 ZY7_DEVCFG_STATUS_PCFG_INIT) != 0) { 464 if (++tries >= 100) 465 return (EIO); 466 DELAY(5); 467 } 468 469 /* Clear sticky bits and set up INIT positive edge interrupt. */ 470 WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL); 471 WR4(sc, ZY7_DEVCFG_INT_MASK, ~ZY7_DEVCFG_INT_PCFG_INIT_PE); 472 473 /* Deassert PROG_B again. */ 474 devcfg_ctl |= ZY7_DEVCFG_CTRL_PCFG_PROG_B; 475 WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl); 476 477 /* 478 * Wait for INIT asserted indicating FPGA internal initialization 479 * is complete. 480 */ 481 err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7i2", hz); 482 if (err != 0) 483 return (err); 484 485 /* Clear sticky DONE bit in interrupt status. */ 486 WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL); 487 488 return (0); 489 } 490 491 /* Callback function for bus_dmamap_load(). */ 492 static void 493 zy7_dma_cb2(void *arg, bus_dma_segment_t *seg, int nsegs, int error) 494 { 495 if (!error && nsegs == 1) 496 *(bus_addr_t *)arg = seg[0].ds_addr; 497 } 498 499 static int 500 zy7_devcfg_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 501 { 502 struct zy7_devcfg_softc *sc = dev->si_drv1; 503 int err; 504 505 DEVCFG_SC_LOCK(sc); 506 if (sc->is_open) { 507 DEVCFG_SC_UNLOCK(sc); 508 return (EBUSY); 509 } 510 511 sc->dma_map = NULL; 512 err = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 4, 0, 513 BUS_SPACE_MAXADDR_32BIT, 514 BUS_SPACE_MAXADDR, 515 NULL, NULL, 516 PAGE_SIZE, 517 1, 518 PAGE_SIZE, 519 0, 520 busdma_lock_mutex, 521 &sc->sc_mtx, 522 &sc->dma_tag); 523 if (err) { 524 DEVCFG_SC_UNLOCK(sc); 525 return (err); 526 } 527 528 sc->is_open = 1; 529 DEVCFG_SC_UNLOCK(sc); 530 return (0); 531 } 532 533 static int 534 zy7_devcfg_write(struct cdev *dev, struct uio *uio, int ioflag) 535 { 536 struct zy7_devcfg_softc *sc = dev->si_drv1; 537 void *dma_mem; 538 bus_addr_t dma_physaddr; 539 int segsz, err; 540 541 DEVCFG_SC_LOCK(sc); 542 543 /* First write? Reset PL. */ 544 if (uio->uio_offset == 0 && uio->uio_resid > 0) { 545 zy7_devcfg_init_hw(sc); 546 zy7_slcr_preload_pl(); 547 err = zy7_devcfg_reset_pl(sc); 548 if (err != 0) { 549 DEVCFG_SC_UNLOCK(sc); 550 return (err); 551 } 552 } 553 554 /* Allocate dma memory and load. */ 555 err = bus_dmamem_alloc(sc->dma_tag, &dma_mem, BUS_DMA_NOWAIT, 556 &sc->dma_map); 557 if (err != 0) { 558 DEVCFG_SC_UNLOCK(sc); 559 return (err); 560 } 561 err = bus_dmamap_load(sc->dma_tag, sc->dma_map, dma_mem, PAGE_SIZE, 562 zy7_dma_cb2, &dma_physaddr, 0); 563 if (err != 0) { 564 bus_dmamem_free(sc->dma_tag, dma_mem, sc->dma_map); 565 DEVCFG_SC_UNLOCK(sc); 566 return (err); 567 } 568 569 while (uio->uio_resid > 0) { 570 /* If DONE signal has been set, we shouldn't write anymore. */ 571 if ((RD4(sc, ZY7_DEVCFG_INT_STATUS) & 572 ZY7_DEVCFG_INT_PCFG_DONE) != 0) { 573 err = EIO; 574 break; 575 } 576 577 /* uiomove the data from user buffer to our dma map. */ 578 segsz = MIN(PAGE_SIZE, uio->uio_resid); 579 DEVCFG_SC_UNLOCK(sc); 580 err = uiomove(dma_mem, segsz, uio); 581 DEVCFG_SC_LOCK(sc); 582 if (err != 0) 583 break; 584 585 /* Flush the cache to memory. */ 586 bus_dmamap_sync(sc->dma_tag, sc->dma_map, 587 BUS_DMASYNC_PREWRITE); 588 589 /* Program devcfg's DMA engine. The ordering of these 590 * register writes is critical. 591 */ 592 if (uio->uio_resid > segsz) 593 WR4(sc, ZY7_DEVCFG_DMA_SRC_ADDR, 594 (uint32_t) dma_physaddr); 595 else 596 WR4(sc, ZY7_DEVCFG_DMA_SRC_ADDR, 597 (uint32_t) dma_physaddr | 598 ZY7_DEVCFG_DMA_ADDR_WAIT_PCAP); 599 WR4(sc, ZY7_DEVCFG_DMA_DST_ADDR, ZY7_DEVCFG_DMA_ADDR_ILLEGAL); 600 WR4(sc, ZY7_DEVCFG_DMA_SRC_LEN, (segsz+3)/4); 601 WR4(sc, ZY7_DEVCFG_DMA_DST_LEN, 0); 602 603 /* Now clear done bit and set up DMA done interrupt. */ 604 WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL); 605 WR4(sc, ZY7_DEVCFG_INT_MASK, ~ZY7_DEVCFG_INT_DMA_DONE); 606 607 /* Wait for DMA done interrupt. */ 608 err = mtx_sleep(sc->dma_map, &sc->sc_mtx, PCATCH, 609 "zy7dma", hz); 610 if (err != 0) 611 break; 612 613 bus_dmamap_sync(sc->dma_tag, sc->dma_map, 614 BUS_DMASYNC_POSTWRITE); 615 616 /* Check DONE signal. */ 617 if ((RD4(sc, ZY7_DEVCFG_INT_STATUS) & 618 ZY7_DEVCFG_INT_PCFG_DONE) != 0) 619 zy7_slcr_postload_pl(zy7_en_level_shifters); 620 } 621 622 bus_dmamap_unload(sc->dma_tag, sc->dma_map); 623 bus_dmamem_free(sc->dma_tag, dma_mem, sc->dma_map); 624 DEVCFG_SC_UNLOCK(sc); 625 return (err); 626 } 627 628 static int 629 zy7_devcfg_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 630 { 631 struct zy7_devcfg_softc *sc = dev->si_drv1; 632 633 DEVCFG_SC_LOCK(sc); 634 sc->is_open = 0; 635 bus_dma_tag_destroy(sc->dma_tag); 636 DEVCFG_SC_UNLOCK(sc); 637 638 zy7_slcr_postload_pl(zy7_en_level_shifters); 639 640 return (0); 641 } 642 643 static void 644 zy7_devcfg_intr(void *arg) 645 { 646 struct zy7_devcfg_softc *sc = (struct zy7_devcfg_softc *)arg; 647 uint32_t istatus, imask; 648 649 DEVCFG_SC_LOCK(sc); 650 651 istatus = RD4(sc, ZY7_DEVCFG_INT_STATUS); 652 imask = ~RD4(sc, ZY7_DEVCFG_INT_MASK); 653 654 /* Turn interrupt off. */ 655 WR4(sc, ZY7_DEVCFG_INT_MASK, ~0); 656 657 if ((istatus & imask) == 0) { 658 DEVCFG_SC_UNLOCK(sc); 659 return; 660 } 661 662 /* DMA done? */ 663 if ((istatus & ZY7_DEVCFG_INT_DMA_DONE) != 0) 664 wakeup(sc->dma_map); 665 666 /* INIT_B positive edge? */ 667 if ((istatus & ZY7_DEVCFG_INT_PCFG_INIT_PE) != 0) 668 wakeup(sc); 669 670 DEVCFG_SC_UNLOCK(sc); 671 } 672 673 /* zy7_devcfg_sysctl_pl_done() returns status of the PL_DONE signal. 674 */ 675 static int 676 zy7_devcfg_sysctl_pl_done(SYSCTL_HANDLER_ARGS) 677 { 678 struct zy7_devcfg_softc *sc = zy7_devcfg_softc_p; 679 int pl_done = 0; 680 681 if (sc) { 682 DEVCFG_SC_LOCK(sc); 683 684 /* PCFG_DONE bit is sticky. Clear it before checking it. */ 685 WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_PCFG_DONE); 686 pl_done = ((RD4(sc, ZY7_DEVCFG_INT_STATUS) & 687 ZY7_DEVCFG_INT_PCFG_DONE) != 0); 688 689 DEVCFG_SC_UNLOCK(sc); 690 } 691 return (sysctl_handle_int(oidp, &pl_done, 0, req)); 692 } 693 694 static int 695 zy7_devcfg_probe(device_t dev) 696 { 697 698 if (!ofw_bus_status_okay(dev)) 699 return (ENXIO); 700 701 if (!ofw_bus_is_compatible(dev, "xlnx,zy7_devcfg")) 702 return (ENXIO); 703 704 device_set_desc(dev, "Zynq devcfg block"); 705 return (0); 706 } 707 708 static int zy7_devcfg_detach(device_t dev); 709 710 static int 711 zy7_devcfg_attach(device_t dev) 712 { 713 struct zy7_devcfg_softc *sc = device_get_softc(dev); 714 int i; 715 int rid, err; 716 717 /* Allow only one attach. */ 718 if (zy7_devcfg_softc_p != NULL) 719 return (ENXIO); 720 721 sc->dev = dev; 722 723 DEVCFG_SC_LOCK_INIT(sc); 724 725 /* Get memory resource. */ 726 rid = 0; 727 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 728 RF_ACTIVE); 729 if (sc->mem_res == NULL) { 730 device_printf(dev, "could not allocate memory resources.\n"); 731 zy7_devcfg_detach(dev); 732 return (ENOMEM); 733 } 734 735 /* Allocate IRQ. */ 736 rid = 0; 737 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 738 RF_ACTIVE); 739 if (sc->irq_res == NULL) { 740 device_printf(dev, "cannot allocate IRQ\n"); 741 zy7_devcfg_detach(dev); 742 return (ENOMEM); 743 } 744 745 /* Activate the interrupt. */ 746 err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 747 NULL, zy7_devcfg_intr, sc, &sc->intrhandle); 748 if (err) { 749 device_printf(dev, "cannot setup IRQ\n"); 750 zy7_devcfg_detach(dev); 751 return (err); 752 } 753 754 /* Create /dev/devcfg */ 755 sc->sc_ctl_dev = make_dev(&zy7_devcfg_cdevsw, 0, 756 UID_ROOT, GID_WHEEL, 0600, "devcfg"); 757 if (sc->sc_ctl_dev == NULL) { 758 device_printf(dev, "failed to create /dev/devcfg"); 759 zy7_devcfg_detach(dev); 760 return (ENXIO); 761 } 762 sc->sc_ctl_dev->si_drv1 = sc; 763 764 zy7_devcfg_softc_p = sc; 765 766 /* Unlock devcfg registers. */ 767 WR4(sc, ZY7_DEVCFG_UNLOCK, ZY7_DEVCFG_UNLOCK_MAGIC); 768 769 /* Make sure interrupts are completely disabled. */ 770 WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL); 771 WR4(sc, ZY7_DEVCFG_INT_MASK, 0xffffffff); 772 773 /* Get PS_VERS for SYSCTL. */ 774 zy7_ps_vers = (RD4(sc, ZY7_DEVCFG_MCTRL) & 775 ZY7_DEVCFG_MCTRL_PS_VERS_MASK) >> 776 ZY7_DEVCFG_MCTRL_PS_VERS_SHIFT; 777 778 for (i = 0; i < FCLK_NUM; i++) { 779 fclk_configs[i].source = zy7_pl_fclk_get_source(i); 780 fclk_configs[i].actual_frequency = 781 zy7_pl_fclk_enabled(i) ? zy7_pl_fclk_get_freq(i) : 0; 782 /* Initially assume actual frequency is the configure one */ 783 fclk_configs[i].frequency = fclk_configs[i].actual_frequency; 784 } 785 786 if (zy7_devcfg_init_fclk_sysctl(sc) < 0) 787 device_printf(dev, "failed to initialized sysctl tree\n"); 788 789 return (0); 790 } 791 792 static int 793 zy7_devcfg_detach(device_t dev) 794 { 795 struct zy7_devcfg_softc *sc = device_get_softc(dev); 796 797 if (sc->sysctl_tree_top != NULL) { 798 sysctl_ctx_free(&sc->sysctl_tree); 799 sc->sysctl_tree_top = NULL; 800 } 801 802 if (device_is_attached(dev)) 803 bus_generic_detach(dev); 804 805 /* Get rid of /dev/devcfg0. */ 806 if (sc->sc_ctl_dev != NULL) 807 destroy_dev(sc->sc_ctl_dev); 808 809 /* Teardown and release interrupt. */ 810 if (sc->irq_res != NULL) { 811 if (sc->intrhandle) 812 bus_teardown_intr(dev, sc->irq_res, sc->intrhandle); 813 bus_release_resource(dev, SYS_RES_IRQ, 814 rman_get_rid(sc->irq_res), sc->irq_res); 815 } 816 817 /* Release memory resource. */ 818 if (sc->mem_res != NULL) 819 bus_release_resource(dev, SYS_RES_MEMORY, 820 rman_get_rid(sc->mem_res), sc->mem_res); 821 822 zy7_devcfg_softc_p = NULL; 823 824 DEVCFG_SC_LOCK_DESTROY(sc); 825 826 return (0); 827 } 828 829 static device_method_t zy7_devcfg_methods[] = { 830 /* device_if */ 831 DEVMETHOD(device_probe, zy7_devcfg_probe), 832 DEVMETHOD(device_attach, zy7_devcfg_attach), 833 DEVMETHOD(device_detach, zy7_devcfg_detach), 834 835 DEVMETHOD_END 836 }; 837 838 static driver_t zy7_devcfg_driver = { 839 "zy7_devcfg", 840 zy7_devcfg_methods, 841 sizeof(struct zy7_devcfg_softc), 842 }; 843 static devclass_t zy7_devcfg_devclass; 844 845 DRIVER_MODULE(zy7_devcfg, simplebus, zy7_devcfg_driver, zy7_devcfg_devclass, \ 846 0, 0); 847 MODULE_DEPEND(zy7_devcfg, zy7_slcr, 1, 1, 1); 848