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