From 08302ed7d424ac02a7660af312220c09a4c59eeb Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Fri, 8 Sep 2023 15:50:30 +0200 Subject: [PATCH] inertial commit, libxil built externally --- .gitignore | 6 + .gitmodules | 3 + CMakeLists.txt | 80 + FreeRTOS-Kernel | 1 + bsp_z7/CMakeLists.txt | 1 + bsp_z7/coraZ7-10/bspconfig.h | 15 + bsp_z7/coraZ7-10/drivers.txt | 15 + bsp_z7/coraZ7-10/inbyte.c | 18 + bsp_z7/coraZ7-10/outbyte.c | 19 + bsp_z7/coraZ7-10/ps7_init.c | 13020 +++++++++++++ bsp_z7/coraZ7-10/ps7_init.h | 114 + bsp_z7/coraZ7-10/xparameters.h | 484 + bsp_z7/freeRTOS/CMakeLists.txt | 1 + bsp_z7/freeRTOS/FreeRTOSConfig.h | 224 + bsp_z7/freeRTOS/FreeRTOS_asm_vectors.S | 144 + bsp_z7/freeRTOS/FreeRTOS_tick_config.c | 136 + bsp_z7/freeRTOS/Xilinx.spec | 2 + bsp_z7/freeRTOS/lscript.ld | 289 + bsp_z7/lib/libxil.a | 1 + .../include/_profile_timer_hw.h | 281 + bsp_z7/ps7_cortexa9_0/include/bspconfig.h | 15 + bsp_z7/ps7_cortexa9_0/include/diskio.h | 83 + bsp_z7/ps7_cortexa9_0/include/ff.h | 448 + bsp_z7/ps7_cortexa9_0/include/ffconf.h | 397 + .../ps7_cortexa9_0/include/mblaze_nt_types.h | 28 + bsp_z7/ps7_cortexa9_0/include/print.c | 36 + bsp_z7/ps7_cortexa9_0/include/profile.h | 105 + bsp_z7/ps7_cortexa9_0/include/sleep.h | 105 + bsp_z7/ps7_cortexa9_0/include/smc.h | 97 + bsp_z7/ps7_cortexa9_0/include/vectors.h | 64 + bsp_z7/ps7_cortexa9_0/include/xadcps.h | 571 + bsp_z7/ps7_cortexa9_0/include/xadcps_hw.h | 477 + bsp_z7/ps7_cortexa9_0/include/xbasic_types.h | 113 + bsp_z7/ps7_cortexa9_0/include/xcpu_cortexa9.h | 25 + bsp_z7/ps7_cortexa9_0/include/xdebug.h | 78 + bsp_z7/ps7_cortexa9_0/include/xdevcfg.h | 377 + bsp_z7/ps7_cortexa9_0/include/xdevcfg_hw.h | 369 + bsp_z7/ps7_cortexa9_0/include/xdmaps.h | 329 + bsp_z7/ps7_cortexa9_0/include/xdmaps_hw.h | 267 + bsp_z7/ps7_cortexa9_0/include/xemacps.h | 843 + bsp_z7/ps7_cortexa9_0/include/xemacps_bd.h | 762 + .../ps7_cortexa9_0/include/xemacps_bdring.h | 215 + bsp_z7/ps7_cortexa9_0/include/xemacps_hw.h | 664 + bsp_z7/ps7_cortexa9_0/include/xenv.h | 169 + .../ps7_cortexa9_0/include/xenv_standalone.h | 350 + bsp_z7/ps7_cortexa9_0/include/xgpiops.h | 299 + bsp_z7/ps7_cortexa9_0/include/xgpiops_hw.h | 147 + bsp_z7/ps7_cortexa9_0/include/xil_assert.c | 126 + bsp_z7/ps7_cortexa9_0/include/xil_assert.h | 176 + bsp_z7/ps7_cortexa9_0/include/xil_cache.h | 105 + bsp_z7/ps7_cortexa9_0/include/xil_cache_l.h | 75 + .../include/xil_cache_vxworks.h | 75 + bsp_z7/ps7_cortexa9_0/include/xil_errata.h | 101 + bsp_z7/ps7_cortexa9_0/include/xil_exception.h | 530 + bsp_z7/ps7_cortexa9_0/include/xil_hal.h | 43 + bsp_z7/ps7_cortexa9_0/include/xil_io.h | 412 + bsp_z7/ps7_cortexa9_0/include/xil_macroback.h | 1113 ++ bsp_z7/ps7_cortexa9_0/include/xil_mem.c | 70 + bsp_z7/ps7_cortexa9_0/include/xil_mem.h | 48 + .../include/xil_misc_psreset_api.h | 261 + bsp_z7/ps7_cortexa9_0/include/xil_mmu.h | 92 + bsp_z7/ps7_cortexa9_0/include/xil_printf.c | 447 + bsp_z7/ps7_cortexa9_0/include/xil_printf.h | 53 + .../ps7_cortexa9_0/include/xil_sleepcommon.c | 85 + .../ps7_cortexa9_0/include/xil_sleeptimer.h | 115 + bsp_z7/ps7_cortexa9_0/include/xil_spinlock.h | 80 + bsp_z7/ps7_cortexa9_0/include/xil_testcache.c | 341 + bsp_z7/ps7_cortexa9_0/include/xil_testcache.h | 54 + bsp_z7/ps7_cortexa9_0/include/xil_testio.c | 273 + bsp_z7/ps7_cortexa9_0/include/xil_testio.h | 76 + bsp_z7/ps7_cortexa9_0/include/xil_testmem.c | 1575 ++ bsp_z7/ps7_cortexa9_0/include/xil_testmem.h | 165 + bsp_z7/ps7_cortexa9_0/include/xil_types.h | 222 + bsp_z7/ps7_cortexa9_0/include/xil_util.c | 1377 ++ bsp_z7/ps7_cortexa9_0/include/xil_util.h | 318 + bsp_z7/ps7_cortexa9_0/include/xilrsa.h | 230 + bsp_z7/ps7_cortexa9_0/include/xl2cc.h | 155 + bsp_z7/ps7_cortexa9_0/include/xl2cc_counter.h | 96 + bsp_z7/ps7_cortexa9_0/include/xparameters.h | 484 + .../ps7_cortexa9_0/include/xparameters_ps.h | 334 + .../ps7_cortexa9_0/include/xplatform_info.c | 206 + .../ps7_cortexa9_0/include/xplatform_info.h | 124 + bsp_z7/ps7_cortexa9_0/include/xpm_counter.h | 575 + bsp_z7/ps7_cortexa9_0/include/xpseudo_asm.h | 60 + .../ps7_cortexa9_0/include/xpseudo_asm_gcc.h | 285 + bsp_z7/ps7_cortexa9_0/include/xqspips.h | 788 + bsp_z7/ps7_cortexa9_0/include/xqspips_hw.h | 399 + bsp_z7/ps7_cortexa9_0/include/xreg_cortexa9.h | 573 + bsp_z7/ps7_cortexa9_0/include/xscugic.h | 689 + bsp_z7/ps7_cortexa9_0/include/xscugic_hw.h | 753 + bsp_z7/ps7_cortexa9_0/include/xscutimer.h | 350 + bsp_z7/ps7_cortexa9_0/include/xscutimer_hw.h | 261 + bsp_z7/ps7_cortexa9_0/include/xscuwdt.h | 365 + bsp_z7/ps7_cortexa9_0/include/xscuwdt_hw.h | 156 + bsp_z7/ps7_cortexa9_0/include/xsdps.h | 389 + bsp_z7/ps7_cortexa9_0/include/xsdps_core.h | 127 + bsp_z7/ps7_cortexa9_0/include/xsdps_hw.h | 1507 ++ bsp_z7/ps7_cortexa9_0/include/xstatus.h | 524 + bsp_z7/ps7_cortexa9_0/include/xtime_l.h | 86 + bsp_z7/ps7_cortexa9_0/include/xttcps.h | 526 + bsp_z7/ps7_cortexa9_0/include/xttcps_hw.h | 208 + bsp_z7/ps7_cortexa9_0/include/xuartps.h | 508 + bsp_z7/ps7_cortexa9_0/include/xuartps_hw.h | 426 + bsp_z7/ps7_cortexa9_0/include/xusbps.h | 1132 ++ .../ps7_cortexa9_0/include/xusbps_endpoint.h | 507 + bsp_z7/ps7_cortexa9_0/include/xusbps_hw.h | 505 + bsp_z7/ps7_cortexa9_0/lib/librsa.a | Bin 0 -> 12530 bytes bsp_z7/ps7_cortexa9_0/lib/libxil.a | Bin 0 -> 1267772 bytes bsp_z7/ps7_cortexa9_0/lib/libxilffs.a | Bin 0 -> 122322 bytes .../libsrc/cpu_cortexa9/src/Makefile | 39 + .../libsrc/cpu_cortexa9/src/xcpu_cortexa9.h | 25 + .../ps7_cortexa9_0/libsrc/devcfg/src/Makefile | 37 + .../libsrc/devcfg/src/xdevcfg.c | 919 + .../libsrc/devcfg/src/xdevcfg.h | 377 + .../libsrc/devcfg/src/xdevcfg_g.c | 52 + .../libsrc/devcfg/src/xdevcfg_hw.c | 87 + .../libsrc/devcfg/src/xdevcfg_hw.h | 369 + .../libsrc/devcfg/src/xdevcfg_intr.c | 284 + .../libsrc/devcfg/src/xdevcfg_selftest.c | 88 + .../libsrc/devcfg/src/xdevcfg_sinit.c | 68 + .../ps7_cortexa9_0/libsrc/dmaps/src/Makefile | 41 + .../ps7_cortexa9_0/libsrc/dmaps/src/xdmaps.c | 1961 ++ .../ps7_cortexa9_0/libsrc/dmaps/src/xdmaps.h | 329 + .../libsrc/dmaps/src/xdmaps_g.c | 54 + .../libsrc/dmaps/src/xdmaps_hw.c | 90 + .../libsrc/dmaps/src/xdmaps_hw.h | 267 + .../libsrc/dmaps/src/xdmaps_selftest.c | 84 + .../libsrc/dmaps/src/xdmaps_sinit.c | 78 + .../ps7_cortexa9_0/libsrc/emacps/src/Makefile | 41 + .../libsrc/emacps/src/xemacps.c | 487 + .../libsrc/emacps/src/xemacps.h | 843 + .../libsrc/emacps/src/xemacps_bd.h | 762 + .../libsrc/emacps/src/xemacps_bdring.c | 1090 ++ .../libsrc/emacps/src/xemacps_bdring.h | 215 + .../libsrc/emacps/src/xemacps_control.c | 1133 ++ .../libsrc/emacps/src/xemacps_g.c | 87 + .../libsrc/emacps/src/xemacps_hw.c | 97 + .../libsrc/emacps/src/xemacps_hw.h | 664 + .../libsrc/emacps/src/xemacps_intr.c | 242 + .../libsrc/emacps/src/xemacps_sinit.c | 71 + .../ps7_cortexa9_0/libsrc/gpiops/src/Makefile | 39 + .../libsrc/gpiops/src/xgpiops.c | 820 + .../libsrc/gpiops/src/xgpiops.h | 299 + .../libsrc/gpiops/src/xgpiops_g.c | 53 + .../libsrc/gpiops/src/xgpiops_hw.c | 241 + .../libsrc/gpiops/src/xgpiops_hw.h | 147 + .../libsrc/gpiops/src/xgpiops_intr.c | 767 + .../libsrc/gpiops/src/xgpiops_selftest.c | 113 + .../libsrc/gpiops/src/xgpiops_sinit.c | 74 + .../ps7_cortexa9_0/libsrc/qspips/src/Makefile | 39 + .../libsrc/qspips/src/xqspips.c | 1603 ++ .../libsrc/qspips/src/xqspips.h | 788 + .../libsrc/qspips/src/xqspips_g.c | 57 + .../libsrc/qspips/src/xqspips_hw.c | 198 + .../libsrc/qspips/src/xqspips_hw.h | 399 + .../libsrc/qspips/src/xqspips_options.c | 404 + .../libsrc/qspips/src/xqspips_selftest.c | 113 + .../libsrc/qspips/src/xqspips_sinit.c | 74 + .../ps7_cortexa9_0/libsrc/scugic/src/Makefile | 39 + .../libsrc/scugic/src/xscugic.c | 1504 ++ .../libsrc/scugic/src/xscugic.h | 689 + .../libsrc/scugic/src/xscugic_g.c | 73 + .../libsrc/scugic/src/xscugic_hw.c | 1079 ++ .../libsrc/scugic/src/xscugic_hw.h | 753 + .../libsrc/scugic/src/xscugic_intr.c | 164 + .../libsrc/scugic/src/xscugic_selftest.c | 93 + .../libsrc/scugic/src/xscugic_sinit.c | 95 + .../libsrc/scutimer/src/Makefile | 39 + .../libsrc/scutimer/src/xscutimer.c | 264 + .../libsrc/scutimer/src/xscutimer.h | 350 + .../libsrc/scutimer/src/xscutimer_g.c | 52 + .../libsrc/scutimer/src/xscutimer_hw.h | 261 + .../libsrc/scutimer/src/xscutimer_selftest.c | 113 + .../libsrc/scutimer/src/xscutimer_sinit.c | 70 + .../ps7_cortexa9_0/libsrc/scuwdt/src/Makefile | 39 + .../libsrc/scuwdt/src/xscuwdt.c | 191 + .../libsrc/scuwdt/src/xscuwdt.h | 365 + .../libsrc/scuwdt/src/xscuwdt_g.c | 53 + .../libsrc/scuwdt/src/xscuwdt_hw.h | 156 + .../libsrc/scuwdt/src/xscuwdt_selftest.c | 105 + .../libsrc/scuwdt/src/xscuwdt_sinit.c | 66 + .../ps7_cortexa9_0/libsrc/sdps/src/Makefile | 39 + bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps.c | 548 + bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps.h | 389 + .../libsrc/sdps/src/xsdps_card.c | 1782 ++ .../libsrc/sdps/src/xsdps_core.h | 127 + .../ps7_cortexa9_0/libsrc/sdps/src/xsdps_g.c | 60 + .../libsrc/sdps/src/xsdps_host.c | 1795 ++ .../ps7_cortexa9_0/libsrc/sdps/src/xsdps_hw.h | 1507 ++ .../libsrc/sdps/src/xsdps_options.c | 901 + .../libsrc/sdps/src/xsdps_sinit.c | 79 + .../libsrc/standalone/src/Makefile | 83 + .../libsrc/standalone/src/_exit.c | 18 + .../libsrc/standalone/src/_open.c | 32 + .../libsrc/standalone/src/_sbrk.c | 43 + .../libsrc/standalone/src/abort.c | 16 + .../libsrc/standalone/src/asm_vectors.S | 176 + .../libsrc/standalone/src/boot.S | 463 + .../libsrc/standalone/src/close.c | 27 + .../libsrc/standalone/src/config.make | 8 + .../libsrc/standalone/src/cpputest_time.c | 31 + .../libsrc/standalone/src/cpu_init.S | 53 + .../libsrc/standalone/src/errno.c | 29 + .../libsrc/standalone/src/fcntl.c | 22 + .../libsrc/standalone/src/fstat.c | 28 + .../libsrc/standalone/src/getentropy.c | 26 + .../libsrc/standalone/src/getpid.c | 30 + .../libsrc/standalone/src/inbyte.c | 18 + .../libsrc/standalone/src/isatty.c | 34 + .../libsrc/standalone/src/kill.c | 38 + .../libsrc/standalone/src/lseek.c | 40 + .../libsrc/standalone/src/open.c | 31 + .../libsrc/standalone/src/outbyte.c | 19 + .../libsrc/standalone/src/print.c | 36 + .../libsrc/standalone/src/profile/Makefile | 51 + .../standalone/src/profile/_profile_clean.c | 21 + .../standalone/src/profile/_profile_init.c | 59 + .../src/profile/_profile_timer_hw.c | 356 + .../src/profile/_profile_timer_hw.h | 281 + .../libsrc/standalone/src/profile/dummy.S | 37 + .../standalone/src/profile/mblaze_nt_types.h | 28 + .../libsrc/standalone/src/profile/profile.h | 105 + .../standalone/src/profile/profile_cg.c | 145 + .../standalone/src/profile/profile_config.h | 30 + .../standalone/src/profile/profile_hist.c | 45 + .../src/profile/profile_mcount_arm.S | 18 + .../src/profile/profile_mcount_mb.S | 42 + .../src/profile/profile_mcount_ppc.S | 44 + .../libsrc/standalone/src/putnum.c | 55 + .../libsrc/standalone/src/read.c | 83 + .../libsrc/standalone/src/sbrk.c | 39 + .../libsrc/standalone/src/sleep.c | 66 + .../libsrc/standalone/src/sleep.h | 105 + .../libsrc/standalone/src/smc.h | 97 + .../libsrc/standalone/src/time.c | 27 + .../libsrc/standalone/src/translation_table.S | 202 + .../libsrc/standalone/src/unlink.c | 28 + .../libsrc/standalone/src/usleep.c | 81 + .../libsrc/standalone/src/vectors.c | 166 + .../libsrc/standalone/src/vectors.h | 64 + .../libsrc/standalone/src/write.c | 100 + .../libsrc/standalone/src/xbasic_types.h | 113 + .../libsrc/standalone/src/xdebug.h | 78 + .../libsrc/standalone/src/xenv.h | 169 + .../libsrc/standalone/src/xenv_standalone.h | 350 + .../libsrc/standalone/src/xil-crt0.S | 136 + .../libsrc/standalone/src/xil_assert.c | 126 + .../libsrc/standalone/src/xil_assert.h | 176 + .../libsrc/standalone/src/xil_cache.c | 1530 ++ .../libsrc/standalone/src/xil_cache.h | 105 + .../libsrc/standalone/src/xil_cache_l.h | 75 + .../libsrc/standalone/src/xil_cache_vxworks.h | 75 + .../libsrc/standalone/src/xil_errata.h | 101 + .../libsrc/standalone/src/xil_exception.c | 861 + .../libsrc/standalone/src/xil_exception.h | 530 + .../libsrc/standalone/src/xil_hal.h | 43 + .../libsrc/standalone/src/xil_io.h | 412 + .../libsrc/standalone/src/xil_macroback.h | 1113 ++ .../libsrc/standalone/src/xil_mem.c | 70 + .../libsrc/standalone/src/xil_mem.h | 48 + .../standalone/src/xil_misc_psreset_api.c | 436 + .../standalone/src/xil_misc_psreset_api.h | 261 + .../libsrc/standalone/src/xil_mmu.c | 202 + .../libsrc/standalone/src/xil_mmu.h | 92 + .../libsrc/standalone/src/xil_printf.c | 447 + .../libsrc/standalone/src/xil_printf.h | 53 + .../libsrc/standalone/src/xil_sleepcommon.c | 85 + .../libsrc/standalone/src/xil_sleeptimer.c | 152 + .../libsrc/standalone/src/xil_sleeptimer.h | 115 + .../libsrc/standalone/src/xil_spinlock.c | 368 + .../libsrc/standalone/src/xil_spinlock.h | 80 + .../libsrc/standalone/src/xil_testcache.c | 341 + .../libsrc/standalone/src/xil_testcache.h | 54 + .../libsrc/standalone/src/xil_testio.c | 273 + .../libsrc/standalone/src/xil_testio.h | 76 + .../libsrc/standalone/src/xil_testmem.c | 1575 ++ .../libsrc/standalone/src/xil_testmem.h | 165 + .../libsrc/standalone/src/xil_types.h | 222 + .../libsrc/standalone/src/xil_util.c | 1377 ++ .../libsrc/standalone/src/xil_util.h | 318 + .../libsrc/standalone/src/xl2cc.h | 155 + .../libsrc/standalone/src/xl2cc_counter.c | 133 + .../libsrc/standalone/src/xl2cc_counter.h | 96 + .../libsrc/standalone/src/xparameters_ps.h | 334 + .../libsrc/standalone/src/xplatform_info.c | 206 + .../libsrc/standalone/src/xplatform_info.h | 124 + .../libsrc/standalone/src/xpm_counter.c | 610 + .../libsrc/standalone/src/xpm_counter.h | 575 + .../libsrc/standalone/src/xpseudo_asm.h | 60 + .../libsrc/standalone/src/xpseudo_asm_gcc.h | 285 + .../libsrc/standalone/src/xreg_cortexa9.h | 573 + .../libsrc/standalone/src/xstatus.h | 524 + .../libsrc/standalone/src/xtime_l.c | 100 + .../libsrc/standalone/src/xtime_l.h | 86 + .../ps7_cortexa9_0/libsrc/ttcps/src/Makefile | 39 + .../ps7_cortexa9_0/libsrc/ttcps/src/xttcps.c | 540 + .../ps7_cortexa9_0/libsrc/ttcps/src/xttcps.h | 526 + .../libsrc/ttcps/src/xttcps_g.c | 98 + .../libsrc/ttcps/src/xttcps_hw.h | 208 + .../libsrc/ttcps/src/xttcps_options.c | 193 + .../libsrc/ttcps/src/xttcps_selftest.c | 84 + .../libsrc/ttcps/src/xttcps_sinit.c | 73 + .../ps7_cortexa9_0/libsrc/uartps/src/Makefile | 39 + .../libsrc/uartps/src/xuartps.c | 631 + .../libsrc/uartps/src/xuartps.h | 508 + .../libsrc/uartps/src/xuartps_g.c | 67 + .../libsrc/uartps/src/xuartps_hw.c | 155 + .../libsrc/uartps/src/xuartps_hw.h | 426 + .../libsrc/uartps/src/xuartps_intr.c | 426 + .../libsrc/uartps/src/xuartps_options.c | 742 + .../libsrc/uartps/src/xuartps_selftest.c | 147 + .../libsrc/uartps/src/xuartps_sinit.c | 74 + .../ps7_cortexa9_0/libsrc/usbps/src/Makefile | 39 + .../ps7_cortexa9_0/libsrc/usbps/src/xusbps.c | 351 + .../ps7_cortexa9_0/libsrc/usbps/src/xusbps.h | 1132 ++ .../libsrc/usbps/src/xusbps_endpoint.c | 1649 ++ .../libsrc/usbps/src/xusbps_endpoint.h | 507 + .../libsrc/usbps/src/xusbps_g.c | 54 + .../libsrc/usbps/src/xusbps_hw.c | 96 + .../libsrc/usbps/src/xusbps_hw.h | 505 + .../libsrc/usbps/src/xusbps_intr.c | 495 + .../libsrc/usbps/src/xusbps_sinit.c | 73 + .../ps7_cortexa9_0/libsrc/xadcps/src/Makefile | 39 + .../ps7_cortexa9_0/libsrc/xadcps/src/xadcps.c | 1813 ++ .../ps7_cortexa9_0/libsrc/xadcps/src/xadcps.h | 571 + .../libsrc/xadcps/src/xadcps_g.c | 59 + .../libsrc/xadcps/src/xadcps_hw.h | 477 + .../libsrc/xadcps/src/xadcps_intr.c | 224 + .../libsrc/xadcps/src/xadcps_selftest.c | 116 + .../libsrc/xadcps/src/xadcps_sinit.c | 78 + .../libsrc/xilffs/data/xilffs.mld | 44 + .../libsrc/xilffs/data/xilffs.tcl | 212 + .../xilffs/doc/html/api/HTML_custom.css | 1430 ++ .../libsrc/xilffs/doc/html/api/arrowdown.png | Bin 0 -> 246 bytes .../libsrc/xilffs/doc/html/api/bc_s.png | Bin 0 -> 676 bytes .../libsrc/xilffs/doc/html/api/bdwn.png | Bin 0 -> 147 bytes .../libsrc/xilffs/doc/html/api/diskio_8c.html | 333 + .../libsrc/xilffs/doc/html/api/diskio_8c.js | 8 + .../libsrc/xilffs/doc/html/api/dynsections.js | 97 + .../libsrc/xilffs/doc/html/api/files.html | 79 + .../libsrc/xilffs/doc/html/api/files.js | 5 + .../libsrc/xilffs/doc/html/api/ftv2blank.png | Bin 0 -> 86 bytes .../libsrc/xilffs/doc/html/api/ftv2cl.png | Bin 0 -> 453 bytes .../libsrc/xilffs/doc/html/api/ftv2doc.png | Bin 0 -> 746 bytes .../xilffs/doc/html/api/ftv2folderclosed.png | Bin 0 -> 616 bytes .../xilffs/doc/html/api/ftv2folderopen.png | Bin 0 -> 597 bytes .../xilffs/doc/html/api/ftv2lastnode.png | Bin 0 -> 86 bytes .../libsrc/xilffs/doc/html/api/ftv2link.png | Bin 0 -> 746 bytes .../xilffs/doc/html/api/ftv2mlastnode.png | Bin 0 -> 246 bytes .../libsrc/xilffs/doc/html/api/ftv2mnode.png | Bin 0 -> 246 bytes .../libsrc/xilffs/doc/html/api/ftv2mo.png | Bin 0 -> 403 bytes .../libsrc/xilffs/doc/html/api/ftv2node.png | Bin 0 -> 86 bytes .../libsrc/xilffs/doc/html/api/ftv2ns.png | Bin 0 -> 388 bytes .../xilffs/doc/html/api/ftv2plastnode.png | Bin 0 -> 229 bytes .../libsrc/xilffs/doc/html/api/ftv2pnode.png | Bin 0 -> 229 bytes .../xilffs/doc/html/api/ftv2splitbar.png | Bin 0 -> 314 bytes .../xilffs/doc/html/api/ftv2vertline.png | Bin 0 -> 86 bytes .../libsrc/xilffs/doc/html/api/globals.html | 98 + .../xilffs/doc/html/api/globals_func.html | 98 + .../libsrc/xilffs/doc/html/api/index.html | 73 + .../libsrc/xilffs/doc/html/api/jquery.js | 72 + .../libsrc/xilffs/doc/html/api/navtree.css | 143 + .../libsrc/xilffs/doc/html/api/navtree.js | 533 + .../xilffs/doc/html/api/navtreeindex0.js | 17 + .../libsrc/xilffs/doc/html/api/open.png | Bin 0 -> 123 bytes .../libsrc/xilffs/doc/html/api/resize.js | 93 + .../libsrc/xilffs/doc/html/api/sync_off.png | Bin 0 -> 853 bytes .../libsrc/xilffs/doc/html/api/sync_on.png | Bin 0 -> 845 bytes .../libsrc/xilffs/doc/html/api/tab_a.png | Bin 0 -> 142 bytes .../libsrc/xilffs/doc/html/api/tab_b.png | Bin 0 -> 169 bytes .../libsrc/xilffs/doc/html/api/tab_h.png | Bin 0 -> 177 bytes .../libsrc/xilffs/doc/html/api/tab_s.png | Bin 0 -> 184 bytes .../libsrc/xilffs/doc/html/api/tabs.css | 60 + .../html/api/xilffs__polled__example_8c.html | 157 + .../html/api/xilffs__polled__example_8c.js | 5 + .../libsrc/xilffs/doc/html/api/xlogo_bg.gif | Bin 0 -> 3317 bytes .../xilffs/examples/xilffs_polled_example.c | 234 + .../ps7_cortexa9_0/libsrc/xilffs/src/Makefile | 58 + .../ps7_cortexa9_0/libsrc/xilffs/src/diskio.c | 558 + bsp_z7/ps7_cortexa9_0/libsrc/xilffs/src/ff.c | 7151 +++++++ .../libsrc/xilffs/src/ffsystem.c | 207 + .../libsrc/xilffs/src/ffunicode.c | 15593 ++++++++++++++++ .../libsrc/xilffs/src/include/diskio.h | 83 + .../libsrc/xilffs/src/include/ff.h | 448 + .../libsrc/xilffs/src/include/ffconf.h | 397 + .../libsrc/xilrsa/data/xilrsa.mld | 27 + .../libsrc/xilrsa/data/xilrsa.tcl | 64 + .../xilrsa/doc/html/api/HTML_custom.css | 1430 ++ .../libsrc/xilrsa/doc/html/api/arrowdown.png | Bin 0 -> 246 bytes .../libsrc/xilrsa/doc/html/api/bc_s.png | Bin 0 -> 676 bytes .../libsrc/xilrsa/doc/html/api/bdwn.png | Bin 0 -> 147 bytes .../libsrc/xilrsa/doc/html/api/dynsections.js | 97 + .../libsrc/xilrsa/doc/html/api/files.html | 78 + .../libsrc/xilrsa/doc/html/api/files.js | 4 + .../libsrc/xilrsa/doc/html/api/ftv2blank.png | Bin 0 -> 86 bytes .../libsrc/xilrsa/doc/html/api/ftv2cl.png | Bin 0 -> 453 bytes .../libsrc/xilrsa/doc/html/api/ftv2doc.png | Bin 0 -> 746 bytes .../xilrsa/doc/html/api/ftv2folderclosed.png | Bin 0 -> 616 bytes .../xilrsa/doc/html/api/ftv2folderopen.png | Bin 0 -> 597 bytes .../xilrsa/doc/html/api/ftv2lastnode.png | Bin 0 -> 86 bytes .../libsrc/xilrsa/doc/html/api/ftv2link.png | Bin 0 -> 746 bytes .../xilrsa/doc/html/api/ftv2mlastnode.png | Bin 0 -> 246 bytes .../libsrc/xilrsa/doc/html/api/ftv2mnode.png | Bin 0 -> 246 bytes .../libsrc/xilrsa/doc/html/api/ftv2mo.png | Bin 0 -> 403 bytes .../libsrc/xilrsa/doc/html/api/ftv2node.png | Bin 0 -> 86 bytes .../libsrc/xilrsa/doc/html/api/ftv2ns.png | Bin 0 -> 388 bytes .../xilrsa/doc/html/api/ftv2plastnode.png | Bin 0 -> 229 bytes .../libsrc/xilrsa/doc/html/api/ftv2pnode.png | Bin 0 -> 229 bytes .../xilrsa/doc/html/api/ftv2splitbar.png | Bin 0 -> 314 bytes .../xilrsa/doc/html/api/ftv2vertline.png | Bin 0 -> 86 bytes .../libsrc/xilrsa/doc/html/api/globals.html | 95 + .../xilrsa/doc/html/api/globals_func.html | 95 + .../doc/html/api/group__xilrsa__apis.html | 359 + .../libsrc/xilrsa/doc/html/api/index.html | 73 + .../libsrc/xilrsa/doc/html/api/jquery.js | 72 + .../libsrc/xilrsa/doc/html/api/modules.html | 78 + .../libsrc/xilrsa/doc/html/api/navtree.css | 143 + .../libsrc/xilrsa/doc/html/api/navtree.js | 533 + .../xilrsa/doc/html/api/navtreeindex0.js | 15 + .../libsrc/xilrsa/doc/html/api/open.png | Bin 0 -> 123 bytes .../libsrc/xilrsa/doc/html/api/resize.js | 93 + .../libsrc/xilrsa/doc/html/api/sync_off.png | Bin 0 -> 853 bytes .../libsrc/xilrsa/doc/html/api/sync_on.png | Bin 0 -> 845 bytes .../libsrc/xilrsa/doc/html/api/tab_a.png | Bin 0 -> 142 bytes .../libsrc/xilrsa/doc/html/api/tab_b.png | Bin 0 -> 169 bytes .../libsrc/xilrsa/doc/html/api/tab_h.png | Bin 0 -> 177 bytes .../libsrc/xilrsa/doc/html/api/tab_s.png | Bin 0 -> 184 bytes .../libsrc/xilrsa/doc/html/api/tabs.css | 60 + .../libsrc/xilrsa/doc/html/api/xilrsa_8h.html | 97 + .../libsrc/xilrsa/doc/html/api/xilrsa_8h.js | 9 + .../libsrc/xilrsa/doc/html/api/xlogo_bg.gif | Bin 0 -> 3317 bytes .../ps7_cortexa9_0/libsrc/xilrsa/src/Makefile | 29 + .../libsrc/xilrsa/src/include/xilrsa.h | 230 + .../ps7_cortexa9_0/libsrc/xilrsa/src/librsa.a | Bin 0 -> 12530 bytes .../libsrc/xilrsa/src/librsa_armcc.a | Bin 0 -> 35266 bytes mission/CMakeLists.txt | 1 + mission/main.c | 559 + 437 files changed, 141193 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 160000 FreeRTOS-Kernel create mode 100644 bsp_z7/CMakeLists.txt create mode 100644 bsp_z7/coraZ7-10/bspconfig.h create mode 100644 bsp_z7/coraZ7-10/drivers.txt create mode 100644 bsp_z7/coraZ7-10/inbyte.c create mode 100644 bsp_z7/coraZ7-10/outbyte.c create mode 100644 bsp_z7/coraZ7-10/ps7_init.c create mode 100644 bsp_z7/coraZ7-10/ps7_init.h create mode 100644 bsp_z7/coraZ7-10/xparameters.h create mode 100644 bsp_z7/freeRTOS/CMakeLists.txt create mode 100644 bsp_z7/freeRTOS/FreeRTOSConfig.h create mode 100644 bsp_z7/freeRTOS/FreeRTOS_asm_vectors.S create mode 100644 bsp_z7/freeRTOS/FreeRTOS_tick_config.c create mode 100644 bsp_z7/freeRTOS/Xilinx.spec create mode 100644 bsp_z7/freeRTOS/lscript.ld create mode 120000 bsp_z7/lib/libxil.a create mode 100644 bsp_z7/ps7_cortexa9_0/include/_profile_timer_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/bspconfig.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/diskio.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/ff.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/ffconf.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/mblaze_nt_types.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/print.c create mode 100644 bsp_z7/ps7_cortexa9_0/include/profile.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/sleep.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/smc.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/vectors.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xadcps.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xadcps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xbasic_types.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xcpu_cortexa9.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xdebug.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xdevcfg.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xdevcfg_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xdmaps.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xdmaps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xemacps.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xemacps_bd.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xemacps_bdring.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xemacps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xenv.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xenv_standalone.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xgpiops.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xgpiops_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_assert.c create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_assert.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_cache.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_cache_l.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_cache_vxworks.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_errata.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_exception.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_hal.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_io.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_macroback.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_mem.c create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_mem.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_misc_psreset_api.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_mmu.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_printf.c create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_printf.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_sleepcommon.c create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_sleeptimer.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_spinlock.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_testcache.c create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_testcache.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_testio.c create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_testio.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_testmem.c create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_testmem.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_types.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_util.c create mode 100644 bsp_z7/ps7_cortexa9_0/include/xil_util.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xilrsa.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xl2cc.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xl2cc_counter.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xparameters.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xparameters_ps.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xplatform_info.c create mode 100644 bsp_z7/ps7_cortexa9_0/include/xplatform_info.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xpm_counter.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xpseudo_asm.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xpseudo_asm_gcc.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xqspips.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xqspips_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xreg_cortexa9.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xscugic.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xscugic_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xscutimer.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xscutimer_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xscuwdt.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xscuwdt_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xsdps.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xsdps_core.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xsdps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xstatus.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xtime_l.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xttcps.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xttcps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xuartps.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xuartps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xusbps.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xusbps_endpoint.h create mode 100644 bsp_z7/ps7_cortexa9_0/include/xusbps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/lib/librsa.a create mode 100644 bsp_z7/ps7_cortexa9_0/lib/libxil.a create mode 100644 bsp_z7/ps7_cortexa9_0/lib/libxilffs.a create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/cpu_cortexa9/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/cpu_cortexa9/src/xcpu_cortexa9.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_hw.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_intr.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_selftest.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_hw.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_selftest.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bd.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bdring.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bdring.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_control.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_hw.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_intr.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_hw.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_intr.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_selftest.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_hw.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_options.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_selftest.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_hw.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_intr.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_selftest.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_selftest.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_selftest.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_card.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_core.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_host.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_options.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_exit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_open.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_sbrk.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/abort.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/asm_vectors.S create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/boot.S create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/close.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/config.make create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/cpputest_time.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/cpu_init.S create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/errno.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/fcntl.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/fstat.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/getentropy.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/getpid.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/inbyte.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/isatty.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/kill.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/lseek.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/open.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/outbyte.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/print.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_clean.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_init.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_timer_hw.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_timer_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/dummy.S create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/mblaze_nt_types.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_cg.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_config.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_hist.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_arm.S create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_mb.S create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_ppc.S create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/putnum.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/read.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sbrk.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sleep.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sleep.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/smc.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/time.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/translation_table.S create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/unlink.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/usleep.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/vectors.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/vectors.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/write.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xbasic_types.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xdebug.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xenv.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xenv_standalone.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil-crt0.S create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_assert.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_assert.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache_l.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache_vxworks.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_errata.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_exception.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_exception.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_hal.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_io.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_macroback.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mem.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mem.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_misc_psreset_api.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_misc_psreset_api.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mmu.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mmu.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_printf.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_printf.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleepcommon.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleeptimer.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleeptimer.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_spinlock.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_spinlock.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testcache.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testcache.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testio.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testio.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testmem.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testmem.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_types.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_util.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_util.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc_counter.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc_counter.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xparameters_ps.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xplatform_info.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xplatform_info.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpm_counter.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpm_counter.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpseudo_asm.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpseudo_asm_gcc.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xreg_cortexa9.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xstatus.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xtime_l.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xtime_l.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_options.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_selftest.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_hw.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_intr.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_options.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_selftest.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_endpoint.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_endpoint.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_hw.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_intr.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_g.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_hw.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_intr.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_selftest.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_sinit.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/data/xilffs.mld create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/data/xilffs.tcl create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/HTML_custom.css create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/arrowdown.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/bc_s.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/bdwn.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/diskio_8c.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/diskio_8c.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/dynsections.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/files.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/files.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2blank.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2cl.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2doc.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2folderclosed.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2folderopen.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2lastnode.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2link.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2mlastnode.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2mnode.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2mo.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2node.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2ns.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2plastnode.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2pnode.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2splitbar.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2vertline.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/globals.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/globals_func.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/index.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/jquery.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/navtree.css create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/navtree.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/navtreeindex0.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/open.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/resize.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/sync_off.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/sync_on.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/tab_a.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/tab_b.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/tab_h.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/tab_s.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/tabs.css create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/xilffs__polled__example_8c.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/xilffs__polled__example_8c.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/xlogo_bg.gif create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/examples/xilffs_polled_example.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/src/diskio.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/src/ff.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/src/ffsystem.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/src/ffunicode.c create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/src/include/diskio.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/src/include/ff.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilffs/src/include/ffconf.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/data/xilrsa.mld create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/data/xilrsa.tcl create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/HTML_custom.css create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/arrowdown.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/bc_s.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/bdwn.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/dynsections.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/files.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/files.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2blank.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2cl.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2doc.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2folderclosed.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2folderopen.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2lastnode.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2link.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2mlastnode.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2mnode.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2mo.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2node.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2ns.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2plastnode.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2pnode.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2splitbar.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/ftv2vertline.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/globals.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/globals_func.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/group__xilrsa__apis.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/index.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/jquery.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/modules.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/navtree.css create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/navtree.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/navtreeindex0.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/open.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/resize.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/sync_off.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/sync_on.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/tab_a.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/tab_b.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/tab_h.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/tab_s.png create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/tabs.css create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/xilrsa_8h.html create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/xilrsa_8h.js create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/doc/html/api/xlogo_bg.gif create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/src/Makefile create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/src/include/xilrsa.h create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/src/librsa.a create mode 100644 bsp_z7/ps7_cortexa9_0/libsrc/xilrsa/src/librsa_armcc.a create mode 100644 mission/CMakeLists.txt create mode 100644 mission/main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..02fe6db --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.o +*.d +/build* +.vscode +__pycache__/* +**/__pycache__/* \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9ddfc2b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "FreeRTOS-Kernel"] + path = FreeRTOS-Kernel + url = https://github.com/FreeRTOS/FreeRTOS-Kernel diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e043e73 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,80 @@ +cmake_minimum_required(VERSION 3.13) + +# Project Name +project(freeRTOS C CXX ASM) + + +# ############################################################################## +# Pre-Sources preparation +# ############################################################################## + +set(CMAKE_C_COMPILER arm-none-eabi-gcc) +set(CMAKE_CXX_COMPILER arm-none-eabi-g++) +set(CMAKE_ASM_COMPILER arm-none-eabi-gcc) + +# Specify the C++ standard +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +# Set names and variables +set(TARGET_NAME ${CMAKE_PROJECT_NAME}) + +# Set path names +set(FreeRTOS_PATH FreeRTOS-Kernel/) +set(MISSION_PATH mission/) +set(FreeRTOS_CONFIG_PATH bsp_z7/freeRTOS) +set(BSP_PATH bsp_z7/ps7_cortexa9_0) + +# ############################################################################## +# Executable and Sources +# ############################################################################## + +# Add executable +add_executable(${TARGET_NAME}) + +#target_compile_options(${TARGET_NAME} PUBLIC -g -O0 -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard) + +# Add freeRTOS +set(FREERTOS_PORT GCC_ARM_CA9 CACHE STRING "") +add_library(freertos_config INTERFACE) +target_include_directories(freertos_config SYSTEM + INTERFACE ${FreeRTOS_CONFIG_PATH}) # The config file directory +target_compile_definitions(freertos_config + INTERFACE + projCOVERAGE_TEST=0) +target_include_directories( + freertos_config INTERFACE ${BSP_PATH}/include) +# our compiler options, will trickle down through the project +target_compile_options(freertos_config INTERFACE -c -fmessage-length=0 -g -O0 -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -ffunction-sections -fdata-sections) +add_subdirectory(${FreeRTOS_PATH}) + +add_subdirectory(bsp_z7) + +add_subdirectory(${MISSION_PATH}) + +# ############################################################################## +# Post-Sources preparation +# ############################################################################## + +# Add libraries for all sources. +target_link_libraries(${TARGET_NAME} PRIVATE freertos_kernel ${CMAKE_SOURCE_DIR}/${BSP_PATH}/lib/libxil.a) + +# Add include paths for all sources. +target_include_directories( + freertos_kernel PUBLIC ${BSP_PATH}/ps7_cortexa9_0/include) + +# target_include_directories( +# ${TARGET_NAME} PUBLIC ${COMMON_DIR}/include) + + +target_link_options(${TARGET_NAME} PRIVATE -Wl,--start-group,-lgcc,-lc,--end-group -Wl,-Map=${TARGET_NAME}.map -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -Wl,-build-id=none -T${CMAKE_SOURCE_DIR}/${FreeRTOS_CONFIG_PATH}/lscript.ld -specs=${CMAKE_SOURCE_DIR}/${FreeRTOS_CONFIG_PATH}/Xilinx.spec) + +# Removed unused sections. +target_link_options(${TARGET_NAME} PRIVATE "-Wl,--gc-sections") + +if(CMAKE_VERBOSE) + message(STATUS "Warning flags: ${WARNING_FLAGS}") +endif() + +# Compile options for all sources. +target_compile_options(${TARGET_NAME} PRIVATE ${WARNING_FLAGS}) \ No newline at end of file diff --git a/FreeRTOS-Kernel b/FreeRTOS-Kernel new file mode 160000 index 0000000..2f94b18 --- /dev/null +++ b/FreeRTOS-Kernel @@ -0,0 +1 @@ +Subproject commit 2f94b181a2f049ec342deba0927bed51f7174ab0 diff --git a/bsp_z7/CMakeLists.txt b/bsp_z7/CMakeLists.txt new file mode 100644 index 0000000..15478b6 --- /dev/null +++ b/bsp_z7/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(freeRTOS) \ No newline at end of file diff --git a/bsp_z7/coraZ7-10/bspconfig.h b/bsp_z7/coraZ7-10/bspconfig.h new file mode 100644 index 0000000..4ff1d52 --- /dev/null +++ b/bsp_z7/coraZ7-10/bspconfig.h @@ -0,0 +1,15 @@ + +/******************************************************************* +* Copyright (c) 2010-2020 Xilinx, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +*******************************************************************/ + +#ifndef BSPCONFIG_H /* prevent circular inclusions */ +#define BSPCONFIG_H /* by using protection macros */ + +#define MICROBLAZE_PVR_NONE + +/* Definition for hard-float ABI */ +#define FPU_HARD_FLOAT_ABI_ENABLED 1 + +#endif /*end of __BSPCONFIG_H_*/ diff --git a/bsp_z7/coraZ7-10/drivers.txt b/bsp_z7/coraZ7-10/drivers.txt new file mode 100644 index 0000000..837735c --- /dev/null +++ b/bsp_z7/coraZ7-10/drivers.txt @@ -0,0 +1,15 @@ +cpu_cortexa9 +devcfg +dmaps +emacps +gpiops +qspips +scugic +scutimer +scuwdt +sdps +ttcps +uartps +usbps +xadcps + diff --git a/bsp_z7/coraZ7-10/inbyte.c b/bsp_z7/coraZ7-10/inbyte.c new file mode 100644 index 0000000..3b662d2 --- /dev/null +++ b/bsp_z7/coraZ7-10/inbyte.c @@ -0,0 +1,18 @@ +/****************************************************************************** +* Copyright (c) 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +#include "xparameters.h" +#include "xuartps_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif +char inbyte(void); +#ifdef __cplusplus +} +#endif + +char inbyte(void) { + return XUartPs_RecvByte(STDIN_BASEADDRESS); +} diff --git a/bsp_z7/coraZ7-10/outbyte.c b/bsp_z7/coraZ7-10/outbyte.c new file mode 100644 index 0000000..db60e6d --- /dev/null +++ b/bsp_z7/coraZ7-10/outbyte.c @@ -0,0 +1,19 @@ +/****************************************************************************** +* Copyright (c) 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +#include "xparameters.h" +#include "xuartps_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif +void outbyte(char c); + +#ifdef __cplusplus +} +#endif + +void outbyte(char c) { + XUartPs_SendByte(STDOUT_BASEADDRESS, c); +} diff --git a/bsp_z7/coraZ7-10/ps7_init.c b/bsp_z7/coraZ7-10/ps7_init.c new file mode 100644 index 0000000..00f0f06 --- /dev/null +++ b/bsp_z7/coraZ7-10/ps7_init.c @@ -0,0 +1,13020 @@ +/****************************************************************************** +* +* (c) Copyright 2010-2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this +* software and associated documentation files (the "Software"), to deal in the Software +* without restriction, including without limitation the rights to use, copy, modify, merge, +* publish, distribute, sublicense, and/or sell copies of the Software, and to permit +* persons to whom the Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* Use of the Software is limited solely to applications: (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used in advertising or +* otherwise to promote the sale, use or other dealings in this Software without prior written +* authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** +* +* @file ps7_init.c +* +* This file is automatically generated +* +*****************************************************************************/ + +#include "ps7_init.h" + +unsigned long ps7_pll_init_data_3_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: PLL SLCR REGISTERS + // .. .. START: ARM PLL INIT + // .. .. PLL_RES = 0xc + // .. .. ==> 0XF8000110[7:4] = 0x0000000CU + // .. .. ==> MASK : 0x000000F0U VAL : 0x000000C0U + // .. .. PLL_CP = 0x2 + // .. .. ==> 0XF8000110[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. LOCK_CNT = 0x177 + // .. .. ==> 0XF8000110[21:12] = 0x00000177U + // .. .. ==> MASK : 0x003FF000U VAL : 0x00177000U + // .. .. + EMIT_MASKWRITE(0XF8000110, 0x003FFFF0U ,0x001772C0U), + // .. .. .. START: UPDATE FB_DIV + // .. .. .. PLL_FDIV = 0x1a + // .. .. .. ==> 0XF8000100[18:12] = 0x0000001AU + // .. .. .. ==> MASK : 0x0007F000U VAL : 0x0001A000U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x0007F000U ,0x0001A000U), + // .. .. .. FINISH: UPDATE FB_DIV + // .. .. .. START: BY PASS PLL + // .. .. .. PLL_BYPASS_FORCE = 1 + // .. .. .. ==> 0XF8000100[4:4] = 0x00000001U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000010U ,0x00000010U), + // .. .. .. FINISH: BY PASS PLL + // .. .. .. START: ASSERT RESET + // .. .. .. PLL_RESET = 1 + // .. .. .. ==> 0XF8000100[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000001U ,0x00000001U), + // .. .. .. FINISH: ASSERT RESET + // .. .. .. START: DEASSERT RESET + // .. .. .. PLL_RESET = 0 + // .. .. .. ==> 0XF8000100[0:0] = 0x00000000U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000001U ,0x00000000U), + // .. .. .. FINISH: DEASSERT RESET + // .. .. .. START: CHECK PLL STATUS + // .. .. .. ARM_PLL_LOCK = 1 + // .. .. .. ==> 0XF800010C[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKPOLL(0XF800010C, 0x00000001U), + // .. .. .. FINISH: CHECK PLL STATUS + // .. .. .. START: REMOVE PLL BY PASS + // .. .. .. PLL_BYPASS_FORCE = 0 + // .. .. .. ==> 0XF8000100[4:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000010U ,0x00000000U), + // .. .. .. FINISH: REMOVE PLL BY PASS + // .. .. .. SRCSEL = 0x0 + // .. .. .. ==> 0XF8000120[5:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. .. .. DIVISOR = 0x2 + // .. .. .. ==> 0XF8000120[13:8] = 0x00000002U + // .. .. .. ==> MASK : 0x00003F00U VAL : 0x00000200U + // .. .. .. CPU_6OR4XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[24:24] = 0x00000001U + // .. .. .. ==> MASK : 0x01000000U VAL : 0x01000000U + // .. .. .. CPU_3OR2XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[25:25] = 0x00000001U + // .. .. .. ==> MASK : 0x02000000U VAL : 0x02000000U + // .. .. .. CPU_2XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[26:26] = 0x00000001U + // .. .. .. ==> MASK : 0x04000000U VAL : 0x04000000U + // .. .. .. CPU_1XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[27:27] = 0x00000001U + // .. .. .. ==> MASK : 0x08000000U VAL : 0x08000000U + // .. .. .. CPU_PERI_CLKACT = 0x1 + // .. .. .. ==> 0XF8000120[28:28] = 0x00000001U + // .. .. .. ==> MASK : 0x10000000U VAL : 0x10000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000120, 0x1F003F30U ,0x1F000200U), + // .. .. FINISH: ARM PLL INIT + // .. .. START: DDR PLL INIT + // .. .. PLL_RES = 0xc + // .. .. ==> 0XF8000114[7:4] = 0x0000000CU + // .. .. ==> MASK : 0x000000F0U VAL : 0x000000C0U + // .. .. PLL_CP = 0x2 + // .. .. ==> 0XF8000114[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. LOCK_CNT = 0x1db + // .. .. ==> 0XF8000114[21:12] = 0x000001DBU + // .. .. ==> MASK : 0x003FF000U VAL : 0x001DB000U + // .. .. + EMIT_MASKWRITE(0XF8000114, 0x003FFFF0U ,0x001DB2C0U), + // .. .. .. START: UPDATE FB_DIV + // .. .. .. PLL_FDIV = 0x15 + // .. .. .. ==> 0XF8000104[18:12] = 0x00000015U + // .. .. .. ==> MASK : 0x0007F000U VAL : 0x00015000U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x0007F000U ,0x00015000U), + // .. .. .. FINISH: UPDATE FB_DIV + // .. .. .. START: BY PASS PLL + // .. .. .. PLL_BYPASS_FORCE = 1 + // .. .. .. ==> 0XF8000104[4:4] = 0x00000001U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000010U ,0x00000010U), + // .. .. .. FINISH: BY PASS PLL + // .. .. .. START: ASSERT RESET + // .. .. .. PLL_RESET = 1 + // .. .. .. ==> 0XF8000104[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000001U ,0x00000001U), + // .. .. .. FINISH: ASSERT RESET + // .. .. .. START: DEASSERT RESET + // .. .. .. PLL_RESET = 0 + // .. .. .. ==> 0XF8000104[0:0] = 0x00000000U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000001U ,0x00000000U), + // .. .. .. FINISH: DEASSERT RESET + // .. .. .. START: CHECK PLL STATUS + // .. .. .. DDR_PLL_LOCK = 1 + // .. .. .. ==> 0XF800010C[1:1] = 0x00000001U + // .. .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. .. + EMIT_MASKPOLL(0XF800010C, 0x00000002U), + // .. .. .. FINISH: CHECK PLL STATUS + // .. .. .. START: REMOVE PLL BY PASS + // .. .. .. PLL_BYPASS_FORCE = 0 + // .. .. .. ==> 0XF8000104[4:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000010U ,0x00000000U), + // .. .. .. FINISH: REMOVE PLL BY PASS + // .. .. .. DDR_3XCLKACT = 0x1 + // .. .. .. ==> 0XF8000124[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. DDR_2XCLKACT = 0x1 + // .. .. .. ==> 0XF8000124[1:1] = 0x00000001U + // .. .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. .. DDR_3XCLK_DIVISOR = 0x2 + // .. .. .. ==> 0XF8000124[25:20] = 0x00000002U + // .. .. .. ==> MASK : 0x03F00000U VAL : 0x00200000U + // .. .. .. DDR_2XCLK_DIVISOR = 0x3 + // .. .. .. ==> 0XF8000124[31:26] = 0x00000003U + // .. .. .. ==> MASK : 0xFC000000U VAL : 0x0C000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000124, 0xFFF00003U ,0x0C200003U), + // .. .. FINISH: DDR PLL INIT + // .. .. START: IO PLL INIT + // .. .. PLL_RES = 0xc + // .. .. ==> 0XF8000118[7:4] = 0x0000000CU + // .. .. ==> MASK : 0x000000F0U VAL : 0x000000C0U + // .. .. PLL_CP = 0x2 + // .. .. ==> 0XF8000118[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. LOCK_CNT = 0x1f4 + // .. .. ==> 0XF8000118[21:12] = 0x000001F4U + // .. .. ==> MASK : 0x003FF000U VAL : 0x001F4000U + // .. .. + EMIT_MASKWRITE(0XF8000118, 0x003FFFF0U ,0x001F42C0U), + // .. .. .. START: UPDATE FB_DIV + // .. .. .. PLL_FDIV = 0x14 + // .. .. .. ==> 0XF8000108[18:12] = 0x00000014U + // .. .. .. ==> MASK : 0x0007F000U VAL : 0x00014000U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x0007F000U ,0x00014000U), + // .. .. .. FINISH: UPDATE FB_DIV + // .. .. .. START: BY PASS PLL + // .. .. .. PLL_BYPASS_FORCE = 1 + // .. .. .. ==> 0XF8000108[4:4] = 0x00000001U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000010U ,0x00000010U), + // .. .. .. FINISH: BY PASS PLL + // .. .. .. START: ASSERT RESET + // .. .. .. PLL_RESET = 1 + // .. .. .. ==> 0XF8000108[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000001U ,0x00000001U), + // .. .. .. FINISH: ASSERT RESET + // .. .. .. START: DEASSERT RESET + // .. .. .. PLL_RESET = 0 + // .. .. .. ==> 0XF8000108[0:0] = 0x00000000U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000001U ,0x00000000U), + // .. .. .. FINISH: DEASSERT RESET + // .. .. .. START: CHECK PLL STATUS + // .. .. .. IO_PLL_LOCK = 1 + // .. .. .. ==> 0XF800010C[2:2] = 0x00000001U + // .. .. .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. .. .. + EMIT_MASKPOLL(0XF800010C, 0x00000004U), + // .. .. .. FINISH: CHECK PLL STATUS + // .. .. .. START: REMOVE PLL BY PASS + // .. .. .. PLL_BYPASS_FORCE = 0 + // .. .. .. ==> 0XF8000108[4:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000010U ,0x00000000U), + // .. .. .. FINISH: REMOVE PLL BY PASS + // .. .. FINISH: IO PLL INIT + // .. FINISH: PLL SLCR REGISTERS + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_clock_init_data_3_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: CLOCK CONTROL SLCR REGISTERS + // .. CLKACT = 0x1 + // .. ==> 0XF8000128[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. DIVISOR0 = 0x34 + // .. ==> 0XF8000128[13:8] = 0x00000034U + // .. ==> MASK : 0x00003F00U VAL : 0x00003400U + // .. DIVISOR1 = 0x2 + // .. ==> 0XF8000128[25:20] = 0x00000002U + // .. ==> MASK : 0x03F00000U VAL : 0x00200000U + // .. + EMIT_MASKWRITE(0XF8000128, 0x03F03F01U ,0x00203401U), + // .. CLKACT = 0x1 + // .. ==> 0XF8000138[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000138[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000138, 0x00000011U ,0x00000001U), + // .. CLKACT = 0x1 + // .. ==> 0XF8000140[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000140[6:4] = 0x00000000U + // .. ==> MASK : 0x00000070U VAL : 0x00000000U + // .. DIVISOR = 0x8 + // .. ==> 0XF8000140[13:8] = 0x00000008U + // .. ==> MASK : 0x00003F00U VAL : 0x00000800U + // .. DIVISOR1 = 0x1 + // .. ==> 0XF8000140[25:20] = 0x00000001U + // .. ==> MASK : 0x03F00000U VAL : 0x00100000U + // .. + EMIT_MASKWRITE(0XF8000140, 0x03F03F71U ,0x00100801U), + // .. CLKACT0 = 0x1 + // .. ==> 0XF8000150[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. CLKACT1 = 0x0 + // .. ==> 0XF8000150[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000150[5:4] = 0x00000000U + // .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. DIVISOR = 0x14 + // .. ==> 0XF8000150[13:8] = 0x00000014U + // .. ==> MASK : 0x00003F00U VAL : 0x00001400U + // .. + EMIT_MASKWRITE(0XF8000150, 0x00003F33U ,0x00001401U), + // .. CLKACT0 = 0x1 + // .. ==> 0XF8000154[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. CLKACT1 = 0x0 + // .. ==> 0XF8000154[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000154[5:4] = 0x00000000U + // .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. DIVISOR = 0xa + // .. ==> 0XF8000154[13:8] = 0x0000000AU + // .. ==> MASK : 0x00003F00U VAL : 0x00000A00U + // .. + EMIT_MASKWRITE(0XF8000154, 0x00003F33U ,0x00000A01U), + // .. CLKACT0 = 0x1 + // .. ==> 0XF8000158[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. CLKACT1 = 0x0 + // .. ==> 0XF8000158[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000158[5:4] = 0x00000000U + // .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. DIVISOR = 0x6 + // .. ==> 0XF8000158[13:8] = 0x00000006U + // .. ==> MASK : 0x00003F00U VAL : 0x00000600U + // .. + EMIT_MASKWRITE(0XF8000158, 0x00003F33U ,0x00000601U), + // .. .. START: TRACE CLOCK + // .. .. FINISH: TRACE CLOCK + // .. .. CLKACT = 0x1 + // .. .. ==> 0XF8000168[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. SRCSEL = 0x0 + // .. .. ==> 0XF8000168[5:4] = 0x00000000U + // .. .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. .. DIVISOR = 0x5 + // .. .. ==> 0XF8000168[13:8] = 0x00000005U + // .. .. ==> MASK : 0x00003F00U VAL : 0x00000500U + // .. .. + EMIT_MASKWRITE(0XF8000168, 0x00003F31U ,0x00000501U), + // .. .. SRCSEL = 0x0 + // .. .. ==> 0XF8000170[5:4] = 0x00000000U + // .. .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. .. DIVISOR0 = 0x5 + // .. .. ==> 0XF8000170[13:8] = 0x00000005U + // .. .. ==> MASK : 0x00003F00U VAL : 0x00000500U + // .. .. DIVISOR1 = 0x2 + // .. .. ==> 0XF8000170[25:20] = 0x00000002U + // .. .. ==> MASK : 0x03F00000U VAL : 0x00200000U + // .. .. + EMIT_MASKWRITE(0XF8000170, 0x03F03F30U ,0x00200500U), + // .. .. CLK_621_TRUE = 0x1 + // .. .. ==> 0XF80001C4[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. + EMIT_MASKWRITE(0XF80001C4, 0x00000001U ,0x00000001U), + // .. .. DMA_CPU_2XCLKACT = 0x1 + // .. .. ==> 0XF800012C[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. USB0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[2:2] = 0x00000001U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. .. USB1_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[3:3] = 0x00000001U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000008U + // .. .. GEM0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[6:6] = 0x00000001U + // .. .. ==> MASK : 0x00000040U VAL : 0x00000040U + // .. .. GEM1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[7:7] = 0x00000000U + // .. .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. .. SDI0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[10:10] = 0x00000001U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000400U + // .. .. SDI1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. SPI0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[14:14] = 0x00000001U + // .. .. ==> MASK : 0x00004000U VAL : 0x00004000U + // .. .. SPI1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. CAN0_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. CAN1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. I2C0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[18:18] = 0x00000001U + // .. .. ==> MASK : 0x00040000U VAL : 0x00040000U + // .. .. I2C1_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[19:19] = 0x00000001U + // .. .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. .. UART0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[20:20] = 0x00000001U + // .. .. ==> MASK : 0x00100000U VAL : 0x00100000U + // .. .. UART1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[21:21] = 0x00000000U + // .. .. ==> MASK : 0x00200000U VAL : 0x00000000U + // .. .. GPIO_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[22:22] = 0x00000001U + // .. .. ==> MASK : 0x00400000U VAL : 0x00400000U + // .. .. LQSPI_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[23:23] = 0x00000000U + // .. .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. .. SMC_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[24:24] = 0x00000001U + // .. .. ==> MASK : 0x01000000U VAL : 0x01000000U + // .. .. + EMIT_MASKWRITE(0XF800012C, 0x01FFCCCDU ,0x015C444DU), + // .. FINISH: CLOCK CONTROL SLCR REGISTERS + // .. START: THIS SHOULD BE BLANK + // .. FINISH: THIS SHOULD BE BLANK + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_ddr_init_data_3_0[] = { + // START: top + // .. START: DDR INITIALIZATION + // .. .. START: LOCK DDR + // .. .. reg_ddrc_soft_rstb = 0 + // .. .. ==> 0XF8006000[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_powerdown_en = 0x0 + // .. .. ==> 0XF8006000[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_ddrc_data_bus_width = 0x1 + // .. .. ==> 0XF8006000[3:2] = 0x00000001U + // .. .. ==> MASK : 0x0000000CU VAL : 0x00000004U + // .. .. reg_ddrc_burst8_refresh = 0x0 + // .. .. ==> 0XF8006000[6:4] = 0x00000000U + // .. .. ==> MASK : 0x00000070U VAL : 0x00000000U + // .. .. reg_ddrc_rdwr_idle_gap = 0x1 + // .. .. ==> 0XF8006000[13:7] = 0x00000001U + // .. .. ==> MASK : 0x00003F80U VAL : 0x00000080U + // .. .. reg_ddrc_dis_rd_bypass = 0x0 + // .. .. ==> 0XF8006000[14:14] = 0x00000000U + // .. .. ==> MASK : 0x00004000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_act_bypass = 0x0 + // .. .. ==> 0XF8006000[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_auto_refresh = 0x0 + // .. .. ==> 0XF8006000[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006000, 0x0001FFFFU ,0x00000084U), + // .. .. FINISH: LOCK DDR + // .. .. reg_ddrc_t_rfc_nom_x32 = 0x7f + // .. .. ==> 0XF8006004[11:0] = 0x0000007FU + // .. .. ==> MASK : 0x00000FFFU VAL : 0x0000007FU + // .. .. reserved_reg_ddrc_active_ranks = 0x1 + // .. .. ==> 0XF8006004[13:12] = 0x00000001U + // .. .. ==> MASK : 0x00003000U VAL : 0x00001000U + // .. .. reg_ddrc_addrmap_cs_bit0 = 0x0 + // .. .. ==> 0XF8006004[18:14] = 0x00000000U + // .. .. ==> MASK : 0x0007C000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006004, 0x0007FFFFU ,0x0000107FU), + // .. .. reg_ddrc_hpr_min_non_critical_x32 = 0xf + // .. .. ==> 0XF8006008[10:0] = 0x0000000FU + // .. .. ==> MASK : 0x000007FFU VAL : 0x0000000FU + // .. .. reg_ddrc_hpr_max_starve_x32 = 0xf + // .. .. ==> 0XF8006008[21:11] = 0x0000000FU + // .. .. ==> MASK : 0x003FF800U VAL : 0x00007800U + // .. .. reg_ddrc_hpr_xact_run_length = 0xf + // .. .. ==> 0XF8006008[25:22] = 0x0000000FU + // .. .. ==> MASK : 0x03C00000U VAL : 0x03C00000U + // .. .. + EMIT_MASKWRITE(0XF8006008, 0x03FFFFFFU ,0x03C0780FU), + // .. .. reg_ddrc_lpr_min_non_critical_x32 = 0x1 + // .. .. ==> 0XF800600C[10:0] = 0x00000001U + // .. .. ==> MASK : 0x000007FFU VAL : 0x00000001U + // .. .. reg_ddrc_lpr_max_starve_x32 = 0x2 + // .. .. ==> 0XF800600C[21:11] = 0x00000002U + // .. .. ==> MASK : 0x003FF800U VAL : 0x00001000U + // .. .. reg_ddrc_lpr_xact_run_length = 0x8 + // .. .. ==> 0XF800600C[25:22] = 0x00000008U + // .. .. ==> MASK : 0x03C00000U VAL : 0x02000000U + // .. .. + EMIT_MASKWRITE(0XF800600C, 0x03FFFFFFU ,0x02001001U), + // .. .. reg_ddrc_w_min_non_critical_x32 = 0x1 + // .. .. ==> 0XF8006010[10:0] = 0x00000001U + // .. .. ==> MASK : 0x000007FFU VAL : 0x00000001U + // .. .. reg_ddrc_w_xact_run_length = 0x8 + // .. .. ==> 0XF8006010[14:11] = 0x00000008U + // .. .. ==> MASK : 0x00007800U VAL : 0x00004000U + // .. .. reg_ddrc_w_max_starve_x32 = 0x2 + // .. .. ==> 0XF8006010[25:15] = 0x00000002U + // .. .. ==> MASK : 0x03FF8000U VAL : 0x00010000U + // .. .. + EMIT_MASKWRITE(0XF8006010, 0x03FFFFFFU ,0x00014001U), + // .. .. reg_ddrc_t_rc = 0x1a + // .. .. ==> 0XF8006014[5:0] = 0x0000001AU + // .. .. ==> MASK : 0x0000003FU VAL : 0x0000001AU + // .. .. reg_ddrc_t_rfc_min = 0x9e + // .. .. ==> 0XF8006014[13:6] = 0x0000009EU + // .. .. ==> MASK : 0x00003FC0U VAL : 0x00002780U + // .. .. reg_ddrc_post_selfref_gap_x32 = 0x10 + // .. .. ==> 0XF8006014[20:14] = 0x00000010U + // .. .. ==> MASK : 0x001FC000U VAL : 0x00040000U + // .. .. + EMIT_MASKWRITE(0XF8006014, 0x001FFFFFU ,0x0004279AU), + // .. .. reg_ddrc_wr2pre = 0x12 + // .. .. ==> 0XF8006018[4:0] = 0x00000012U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000012U + // .. .. reg_ddrc_powerdown_to_x32 = 0x6 + // .. .. ==> 0XF8006018[9:5] = 0x00000006U + // .. .. ==> MASK : 0x000003E0U VAL : 0x000000C0U + // .. .. reg_ddrc_t_faw = 0x15 + // .. .. ==> 0XF8006018[15:10] = 0x00000015U + // .. .. ==> MASK : 0x0000FC00U VAL : 0x00005400U + // .. .. reg_ddrc_t_ras_max = 0x23 + // .. .. ==> 0XF8006018[21:16] = 0x00000023U + // .. .. ==> MASK : 0x003F0000U VAL : 0x00230000U + // .. .. reg_ddrc_t_ras_min = 0x13 + // .. .. ==> 0XF8006018[26:22] = 0x00000013U + // .. .. ==> MASK : 0x07C00000U VAL : 0x04C00000U + // .. .. reg_ddrc_t_cke = 0x4 + // .. .. ==> 0XF8006018[31:28] = 0x00000004U + // .. .. ==> MASK : 0xF0000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006018, 0xF7FFFFFFU ,0x44E354D2U), + // .. .. reg_ddrc_write_latency = 0x5 + // .. .. ==> 0XF800601C[4:0] = 0x00000005U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000005U + // .. .. reg_ddrc_rd2wr = 0x7 + // .. .. ==> 0XF800601C[9:5] = 0x00000007U + // .. .. ==> MASK : 0x000003E0U VAL : 0x000000E0U + // .. .. reg_ddrc_wr2rd = 0xe + // .. .. ==> 0XF800601C[14:10] = 0x0000000EU + // .. .. ==> MASK : 0x00007C00U VAL : 0x00003800U + // .. .. reg_ddrc_t_xp = 0x4 + // .. .. ==> 0XF800601C[19:15] = 0x00000004U + // .. .. ==> MASK : 0x000F8000U VAL : 0x00020000U + // .. .. reg_ddrc_pad_pd = 0x0 + // .. .. ==> 0XF800601C[22:20] = 0x00000000U + // .. .. ==> MASK : 0x00700000U VAL : 0x00000000U + // .. .. reg_ddrc_rd2pre = 0x4 + // .. .. ==> 0XF800601C[27:23] = 0x00000004U + // .. .. ==> MASK : 0x0F800000U VAL : 0x02000000U + // .. .. reg_ddrc_t_rcd = 0x7 + // .. .. ==> 0XF800601C[31:28] = 0x00000007U + // .. .. ==> MASK : 0xF0000000U VAL : 0x70000000U + // .. .. + EMIT_MASKWRITE(0XF800601C, 0xFFFFFFFFU ,0x720238E5U), + // .. .. reg_ddrc_t_ccd = 0x4 + // .. .. ==> 0XF8006020[4:2] = 0x00000004U + // .. .. ==> MASK : 0x0000001CU VAL : 0x00000010U + // .. .. reg_ddrc_t_rrd = 0x6 + // .. .. ==> 0XF8006020[7:5] = 0x00000006U + // .. .. ==> MASK : 0x000000E0U VAL : 0x000000C0U + // .. .. reg_ddrc_refresh_margin = 0x2 + // .. .. ==> 0XF8006020[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. reg_ddrc_t_rp = 0x7 + // .. .. ==> 0XF8006020[15:12] = 0x00000007U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00007000U + // .. .. reg_ddrc_refresh_to_x32 = 0x8 + // .. .. ==> 0XF8006020[20:16] = 0x00000008U + // .. .. ==> MASK : 0x001F0000U VAL : 0x00080000U + // .. .. reg_ddrc_mobile = 0x0 + // .. .. ==> 0XF8006020[22:22] = 0x00000000U + // .. .. ==> MASK : 0x00400000U VAL : 0x00000000U + // .. .. reg_ddrc_en_dfi_dram_clk_disable = 0x0 + // .. .. ==> 0XF8006020[23:23] = 0x00000000U + // .. .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. .. reg_ddrc_read_latency = 0x7 + // .. .. ==> 0XF8006020[28:24] = 0x00000007U + // .. .. ==> MASK : 0x1F000000U VAL : 0x07000000U + // .. .. reg_phy_mode_ddr1_ddr2 = 0x1 + // .. .. ==> 0XF8006020[29:29] = 0x00000001U + // .. .. ==> MASK : 0x20000000U VAL : 0x20000000U + // .. .. reg_ddrc_dis_pad_pd = 0x0 + // .. .. ==> 0XF8006020[30:30] = 0x00000000U + // .. .. ==> MASK : 0x40000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006020, 0x7FDFFFFCU ,0x270872D0U), + // .. .. reg_ddrc_en_2t_timing_mode = 0x0 + // .. .. ==> 0XF8006024[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_prefer_write = 0x0 + // .. .. ==> 0XF8006024[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_ddrc_mr_wr = 0x0 + // .. .. ==> 0XF8006024[6:6] = 0x00000000U + // .. .. ==> MASK : 0x00000040U VAL : 0x00000000U + // .. .. reg_ddrc_mr_addr = 0x0 + // .. .. ==> 0XF8006024[8:7] = 0x00000000U + // .. .. ==> MASK : 0x00000180U VAL : 0x00000000U + // .. .. reg_ddrc_mr_data = 0x0 + // .. .. ==> 0XF8006024[24:9] = 0x00000000U + // .. .. ==> MASK : 0x01FFFE00U VAL : 0x00000000U + // .. .. ddrc_reg_mr_wr_busy = 0x0 + // .. .. ==> 0XF8006024[25:25] = 0x00000000U + // .. .. ==> MASK : 0x02000000U VAL : 0x00000000U + // .. .. reg_ddrc_mr_type = 0x0 + // .. .. ==> 0XF8006024[26:26] = 0x00000000U + // .. .. ==> MASK : 0x04000000U VAL : 0x00000000U + // .. .. reg_ddrc_mr_rdata_valid = 0x0 + // .. .. ==> 0XF8006024[27:27] = 0x00000000U + // .. .. ==> MASK : 0x08000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006024, 0x0FFFFFC3U ,0x00000000U), + // .. .. reg_ddrc_final_wait_x32 = 0x7 + // .. .. ==> 0XF8006028[6:0] = 0x00000007U + // .. .. ==> MASK : 0x0000007FU VAL : 0x00000007U + // .. .. reg_ddrc_pre_ocd_x32 = 0x0 + // .. .. ==> 0XF8006028[10:7] = 0x00000000U + // .. .. ==> MASK : 0x00000780U VAL : 0x00000000U + // .. .. reg_ddrc_t_mrd = 0x4 + // .. .. ==> 0XF8006028[13:11] = 0x00000004U + // .. .. ==> MASK : 0x00003800U VAL : 0x00002000U + // .. .. + EMIT_MASKWRITE(0XF8006028, 0x00003FFFU ,0x00002007U), + // .. .. reg_ddrc_emr2 = 0x8 + // .. .. ==> 0XF800602C[15:0] = 0x00000008U + // .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000008U + // .. .. reg_ddrc_emr3 = 0x0 + // .. .. ==> 0XF800602C[31:16] = 0x00000000U + // .. .. ==> MASK : 0xFFFF0000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800602C, 0xFFFFFFFFU ,0x00000008U), + // .. .. reg_ddrc_mr = 0x930 + // .. .. ==> 0XF8006030[15:0] = 0x00000930U + // .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000930U + // .. .. reg_ddrc_emr = 0x4 + // .. .. ==> 0XF8006030[31:16] = 0x00000004U + // .. .. ==> MASK : 0xFFFF0000U VAL : 0x00040000U + // .. .. + EMIT_MASKWRITE(0XF8006030, 0xFFFFFFFFU ,0x00040930U), + // .. .. reg_ddrc_burst_rdwr = 0x4 + // .. .. ==> 0XF8006034[3:0] = 0x00000004U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000004U + // .. .. reg_ddrc_pre_cke_x1024 = 0x167 + // .. .. ==> 0XF8006034[13:4] = 0x00000167U + // .. .. ==> MASK : 0x00003FF0U VAL : 0x00001670U + // .. .. reg_ddrc_post_cke_x1024 = 0x1 + // .. .. ==> 0XF8006034[25:16] = 0x00000001U + // .. .. ==> MASK : 0x03FF0000U VAL : 0x00010000U + // .. .. reg_ddrc_burstchop = 0x0 + // .. .. ==> 0XF8006034[28:28] = 0x00000000U + // .. .. ==> MASK : 0x10000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006034, 0x13FF3FFFU ,0x00011674U), + // .. .. reg_ddrc_force_low_pri_n = 0x0 + // .. .. ==> 0XF8006038[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_dis_dq = 0x0 + // .. .. ==> 0XF8006038[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006038, 0x00000003U ,0x00000000U), + // .. .. reg_ddrc_addrmap_bank_b0 = 0x6 + // .. .. ==> 0XF800603C[3:0] = 0x00000006U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000006U + // .. .. reg_ddrc_addrmap_bank_b1 = 0x6 + // .. .. ==> 0XF800603C[7:4] = 0x00000006U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000060U + // .. .. reg_ddrc_addrmap_bank_b2 = 0x6 + // .. .. ==> 0XF800603C[11:8] = 0x00000006U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000600U + // .. .. reg_ddrc_addrmap_col_b5 = 0x0 + // .. .. ==> 0XF800603C[15:12] = 0x00000000U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b6 = 0x0 + // .. .. ==> 0XF800603C[19:16] = 0x00000000U + // .. .. ==> MASK : 0x000F0000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800603C, 0x000FFFFFU ,0x00000666U), + // .. .. reg_ddrc_addrmap_col_b2 = 0x0 + // .. .. ==> 0XF8006040[3:0] = 0x00000000U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b3 = 0x0 + // .. .. ==> 0XF8006040[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b4 = 0x0 + // .. .. ==> 0XF8006040[11:8] = 0x00000000U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b7 = 0x0 + // .. .. ==> 0XF8006040[15:12] = 0x00000000U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b8 = 0xf + // .. .. ==> 0XF8006040[19:16] = 0x0000000FU + // .. .. ==> MASK : 0x000F0000U VAL : 0x000F0000U + // .. .. reg_ddrc_addrmap_col_b9 = 0xf + // .. .. ==> 0XF8006040[23:20] = 0x0000000FU + // .. .. ==> MASK : 0x00F00000U VAL : 0x00F00000U + // .. .. reg_ddrc_addrmap_col_b10 = 0xf + // .. .. ==> 0XF8006040[27:24] = 0x0000000FU + // .. .. ==> MASK : 0x0F000000U VAL : 0x0F000000U + // .. .. reg_ddrc_addrmap_col_b11 = 0xf + // .. .. ==> 0XF8006040[31:28] = 0x0000000FU + // .. .. ==> MASK : 0xF0000000U VAL : 0xF0000000U + // .. .. + EMIT_MASKWRITE(0XF8006040, 0xFFFFFFFFU ,0xFFFF0000U), + // .. .. reg_ddrc_addrmap_row_b0 = 0x5 + // .. .. ==> 0XF8006044[3:0] = 0x00000005U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000005U + // .. .. reg_ddrc_addrmap_row_b1 = 0x5 + // .. .. ==> 0XF8006044[7:4] = 0x00000005U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000050U + // .. .. reg_ddrc_addrmap_row_b2_11 = 0x5 + // .. .. ==> 0XF8006044[11:8] = 0x00000005U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000500U + // .. .. reg_ddrc_addrmap_row_b12 = 0x5 + // .. .. ==> 0XF8006044[15:12] = 0x00000005U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00005000U + // .. .. reg_ddrc_addrmap_row_b13 = 0x5 + // .. .. ==> 0XF8006044[19:16] = 0x00000005U + // .. .. ==> MASK : 0x000F0000U VAL : 0x00050000U + // .. .. reg_ddrc_addrmap_row_b14 = 0x5 + // .. .. ==> 0XF8006044[23:20] = 0x00000005U + // .. .. ==> MASK : 0x00F00000U VAL : 0x00500000U + // .. .. reg_ddrc_addrmap_row_b15 = 0xf + // .. .. ==> 0XF8006044[27:24] = 0x0000000FU + // .. .. ==> MASK : 0x0F000000U VAL : 0x0F000000U + // .. .. + EMIT_MASKWRITE(0XF8006044, 0x0FFFFFFFU ,0x0F555555U), + // .. .. reg_phy_rd_local_odt = 0x0 + // .. .. ==> 0XF8006048[13:12] = 0x00000000U + // .. .. ==> MASK : 0x00003000U VAL : 0x00000000U + // .. .. reg_phy_wr_local_odt = 0x3 + // .. .. ==> 0XF8006048[15:14] = 0x00000003U + // .. .. ==> MASK : 0x0000C000U VAL : 0x0000C000U + // .. .. reg_phy_idle_local_odt = 0x3 + // .. .. ==> 0XF8006048[17:16] = 0x00000003U + // .. .. ==> MASK : 0x00030000U VAL : 0x00030000U + // .. .. reserved_reg_ddrc_rank0_wr_odt = 0x1 + // .. .. ==> 0XF8006048[5:3] = 0x00000001U + // .. .. ==> MASK : 0x00000038U VAL : 0x00000008U + // .. .. reserved_reg_ddrc_rank0_rd_odt = 0x0 + // .. .. ==> 0XF8006048[2:0] = 0x00000000U + // .. .. ==> MASK : 0x00000007U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006048, 0x0003F03FU ,0x0003C008U), + // .. .. reg_phy_rd_cmd_to_data = 0x0 + // .. .. ==> 0XF8006050[3:0] = 0x00000000U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000000U + // .. .. reg_phy_wr_cmd_to_data = 0x0 + // .. .. ==> 0XF8006050[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. reg_phy_rdc_we_to_re_delay = 0x8 + // .. .. ==> 0XF8006050[11:8] = 0x00000008U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000800U + // .. .. reg_phy_rdc_fifo_rst_disable = 0x0 + // .. .. ==> 0XF8006050[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. reg_phy_use_fixed_re = 0x1 + // .. .. ==> 0XF8006050[16:16] = 0x00000001U + // .. .. ==> MASK : 0x00010000U VAL : 0x00010000U + // .. .. reg_phy_rdc_fifo_rst_err_cnt_clr = 0x0 + // .. .. ==> 0XF8006050[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_phy_dis_phy_ctrl_rstn = 0x0 + // .. .. ==> 0XF8006050[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_phy_clk_stall_level = 0x0 + // .. .. ==> 0XF8006050[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_num_of_dq0 = 0x7 + // .. .. ==> 0XF8006050[27:24] = 0x00000007U + // .. .. ==> MASK : 0x0F000000U VAL : 0x07000000U + // .. .. reg_phy_wrlvl_num_of_dq0 = 0x7 + // .. .. ==> 0XF8006050[31:28] = 0x00000007U + // .. .. ==> MASK : 0xF0000000U VAL : 0x70000000U + // .. .. + EMIT_MASKWRITE(0XF8006050, 0xFF0F8FFFU ,0x77010800U), + // .. .. reg_ddrc_dis_dll_calib = 0x0 + // .. .. ==> 0XF8006058[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006058, 0x00010000U ,0x00000000U), + // .. .. reg_ddrc_rd_odt_delay = 0x3 + // .. .. ==> 0XF800605C[3:0] = 0x00000003U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000003U + // .. .. reg_ddrc_wr_odt_delay = 0x0 + // .. .. ==> 0XF800605C[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. reg_ddrc_rd_odt_hold = 0x0 + // .. .. ==> 0XF800605C[11:8] = 0x00000000U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000000U + // .. .. reg_ddrc_wr_odt_hold = 0x5 + // .. .. ==> 0XF800605C[15:12] = 0x00000005U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00005000U + // .. .. + EMIT_MASKWRITE(0XF800605C, 0x0000FFFFU ,0x00005003U), + // .. .. reg_ddrc_pageclose = 0x0 + // .. .. ==> 0XF8006060[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_lpr_num_entries = 0x1f + // .. .. ==> 0XF8006060[6:1] = 0x0000001FU + // .. .. ==> MASK : 0x0000007EU VAL : 0x0000003EU + // .. .. reg_ddrc_auto_pre_en = 0x0 + // .. .. ==> 0XF8006060[7:7] = 0x00000000U + // .. .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. .. reg_ddrc_refresh_update_level = 0x0 + // .. .. ==> 0XF8006060[8:8] = 0x00000000U + // .. .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. .. reg_ddrc_dis_wc = 0x0 + // .. .. ==> 0XF8006060[9:9] = 0x00000000U + // .. .. ==> MASK : 0x00000200U VAL : 0x00000000U + // .. .. reg_ddrc_dis_collision_page_opt = 0x0 + // .. .. ==> 0XF8006060[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_ddrc_selfref_en = 0x0 + // .. .. ==> 0XF8006060[12:12] = 0x00000000U + // .. .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006060, 0x000017FFU ,0x0000003EU), + // .. .. reg_ddrc_go2critical_hysteresis = 0x0 + // .. .. ==> 0XF8006064[12:5] = 0x00000000U + // .. .. ==> MASK : 0x00001FE0U VAL : 0x00000000U + // .. .. reg_arb_go2critical_en = 0x1 + // .. .. ==> 0XF8006064[17:17] = 0x00000001U + // .. .. ==> MASK : 0x00020000U VAL : 0x00020000U + // .. .. + EMIT_MASKWRITE(0XF8006064, 0x00021FE0U ,0x00020000U), + // .. .. reg_ddrc_wrlvl_ww = 0x41 + // .. .. ==> 0XF8006068[7:0] = 0x00000041U + // .. .. ==> MASK : 0x000000FFU VAL : 0x00000041U + // .. .. reg_ddrc_rdlvl_rr = 0x41 + // .. .. ==> 0XF8006068[15:8] = 0x00000041U + // .. .. ==> MASK : 0x0000FF00U VAL : 0x00004100U + // .. .. reg_ddrc_dfi_t_wlmrd = 0x28 + // .. .. ==> 0XF8006068[25:16] = 0x00000028U + // .. .. ==> MASK : 0x03FF0000U VAL : 0x00280000U + // .. .. + EMIT_MASKWRITE(0XF8006068, 0x03FFFFFFU ,0x00284141U), + // .. .. dfi_t_ctrlupd_interval_min_x1024 = 0x10 + // .. .. ==> 0XF800606C[7:0] = 0x00000010U + // .. .. ==> MASK : 0x000000FFU VAL : 0x00000010U + // .. .. dfi_t_ctrlupd_interval_max_x1024 = 0x16 + // .. .. ==> 0XF800606C[15:8] = 0x00000016U + // .. .. ==> MASK : 0x0000FF00U VAL : 0x00001600U + // .. .. + EMIT_MASKWRITE(0XF800606C, 0x0000FFFFU ,0x00001610U), + // .. .. reg_ddrc_dfi_t_ctrl_delay = 0x1 + // .. .. ==> 0XF8006078[3:0] = 0x00000001U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000001U + // .. .. reg_ddrc_dfi_t_dram_clk_disable = 0x1 + // .. .. ==> 0XF8006078[7:4] = 0x00000001U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000010U + // .. .. reg_ddrc_dfi_t_dram_clk_enable = 0x1 + // .. .. ==> 0XF8006078[11:8] = 0x00000001U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000100U + // .. .. reg_ddrc_t_cksre = 0x6 + // .. .. ==> 0XF8006078[15:12] = 0x00000006U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00006000U + // .. .. reg_ddrc_t_cksrx = 0x6 + // .. .. ==> 0XF8006078[19:16] = 0x00000006U + // .. .. ==> MASK : 0x000F0000U VAL : 0x00060000U + // .. .. reg_ddrc_t_ckesr = 0x4 + // .. .. ==> 0XF8006078[25:20] = 0x00000004U + // .. .. ==> MASK : 0x03F00000U VAL : 0x00400000U + // .. .. + EMIT_MASKWRITE(0XF8006078, 0x03FFFFFFU ,0x00466111U), + // .. .. reg_ddrc_t_ckpde = 0x2 + // .. .. ==> 0XF800607C[3:0] = 0x00000002U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000002U + // .. .. reg_ddrc_t_ckpdx = 0x2 + // .. .. ==> 0XF800607C[7:4] = 0x00000002U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000020U + // .. .. reg_ddrc_t_ckdpde = 0x2 + // .. .. ==> 0XF800607C[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. reg_ddrc_t_ckdpdx = 0x2 + // .. .. ==> 0XF800607C[15:12] = 0x00000002U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00002000U + // .. .. reg_ddrc_t_ckcsx = 0x3 + // .. .. ==> 0XF800607C[19:16] = 0x00000003U + // .. .. ==> MASK : 0x000F0000U VAL : 0x00030000U + // .. .. + EMIT_MASKWRITE(0XF800607C, 0x000FFFFFU ,0x00032222U), + // .. .. reg_ddrc_dis_auto_zq = 0x0 + // .. .. ==> 0XF80060A4[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_ddr3 = 0x1 + // .. .. ==> 0XF80060A4[1:1] = 0x00000001U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. reg_ddrc_t_mod = 0x200 + // .. .. ==> 0XF80060A4[11:2] = 0x00000200U + // .. .. ==> MASK : 0x00000FFCU VAL : 0x00000800U + // .. .. reg_ddrc_t_zq_long_nop = 0x200 + // .. .. ==> 0XF80060A4[21:12] = 0x00000200U + // .. .. ==> MASK : 0x003FF000U VAL : 0x00200000U + // .. .. reg_ddrc_t_zq_short_nop = 0x40 + // .. .. ==> 0XF80060A4[31:22] = 0x00000040U + // .. .. ==> MASK : 0xFFC00000U VAL : 0x10000000U + // .. .. + EMIT_MASKWRITE(0XF80060A4, 0xFFFFFFFFU ,0x10200802U), + // .. .. t_zq_short_interval_x1024 = 0xc845 + // .. .. ==> 0XF80060A8[19:0] = 0x0000C845U + // .. .. ==> MASK : 0x000FFFFFU VAL : 0x0000C845U + // .. .. dram_rstn_x1024 = 0x67 + // .. .. ==> 0XF80060A8[27:20] = 0x00000067U + // .. .. ==> MASK : 0x0FF00000U VAL : 0x06700000U + // .. .. + EMIT_MASKWRITE(0XF80060A8, 0x0FFFFFFFU ,0x0670C845U), + // .. .. deeppowerdown_en = 0x0 + // .. .. ==> 0XF80060AC[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. deeppowerdown_to_x1024 = 0xff + // .. .. ==> 0XF80060AC[8:1] = 0x000000FFU + // .. .. ==> MASK : 0x000001FEU VAL : 0x000001FEU + // .. .. + EMIT_MASKWRITE(0XF80060AC, 0x000001FFU ,0x000001FEU), + // .. .. dfi_wrlvl_max_x1024 = 0xfff + // .. .. ==> 0XF80060B0[11:0] = 0x00000FFFU + // .. .. ==> MASK : 0x00000FFFU VAL : 0x00000FFFU + // .. .. dfi_rdlvl_max_x1024 = 0xfff + // .. .. ==> 0XF80060B0[23:12] = 0x00000FFFU + // .. .. ==> MASK : 0x00FFF000U VAL : 0x00FFF000U + // .. .. ddrc_reg_twrlvl_max_error = 0x0 + // .. .. ==> 0XF80060B0[24:24] = 0x00000000U + // .. .. ==> MASK : 0x01000000U VAL : 0x00000000U + // .. .. ddrc_reg_trdlvl_max_error = 0x0 + // .. .. ==> 0XF80060B0[25:25] = 0x00000000U + // .. .. ==> MASK : 0x02000000U VAL : 0x00000000U + // .. .. reg_ddrc_dfi_wr_level_en = 0x1 + // .. .. ==> 0XF80060B0[26:26] = 0x00000001U + // .. .. ==> MASK : 0x04000000U VAL : 0x04000000U + // .. .. reg_ddrc_dfi_rd_dqs_gate_level = 0x1 + // .. .. ==> 0XF80060B0[27:27] = 0x00000001U + // .. .. ==> MASK : 0x08000000U VAL : 0x08000000U + // .. .. reg_ddrc_dfi_rd_data_eye_train = 0x1 + // .. .. ==> 0XF80060B0[28:28] = 0x00000001U + // .. .. ==> MASK : 0x10000000U VAL : 0x10000000U + // .. .. + EMIT_MASKWRITE(0XF80060B0, 0x1FFFFFFFU ,0x1CFFFFFFU), + // .. .. reg_ddrc_skip_ocd = 0x1 + // .. .. ==> 0XF80060B4[9:9] = 0x00000001U + // .. .. ==> MASK : 0x00000200U VAL : 0x00000200U + // .. .. + EMIT_MASKWRITE(0XF80060B4, 0x00000200U ,0x00000200U), + // .. .. reg_ddrc_dfi_t_rddata_en = 0x6 + // .. .. ==> 0XF80060B8[4:0] = 0x00000006U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000006U + // .. .. reg_ddrc_dfi_t_ctrlup_min = 0x3 + // .. .. ==> 0XF80060B8[14:5] = 0x00000003U + // .. .. ==> MASK : 0x00007FE0U VAL : 0x00000060U + // .. .. reg_ddrc_dfi_t_ctrlup_max = 0x40 + // .. .. ==> 0XF80060B8[24:15] = 0x00000040U + // .. .. ==> MASK : 0x01FF8000U VAL : 0x00200000U + // .. .. + EMIT_MASKWRITE(0XF80060B8, 0x01FFFFFFU ,0x00200066U), + // .. .. Clear_Uncorrectable_DRAM_ECC_error = 0x0 + // .. .. ==> 0XF80060C4[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. Clear_Correctable_DRAM_ECC_error = 0x0 + // .. .. ==> 0XF80060C4[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060C4, 0x00000003U ,0x00000000U), + // .. .. CORR_ECC_LOG_VALID = 0x0 + // .. .. ==> 0XF80060C8[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. ECC_CORRECTED_BIT_NUM = 0x0 + // .. .. ==> 0XF80060C8[7:1] = 0x00000000U + // .. .. ==> MASK : 0x000000FEU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060C8, 0x000000FFU ,0x00000000U), + // .. .. UNCORR_ECC_LOG_VALID = 0x0 + // .. .. ==> 0XF80060DC[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060DC, 0x00000001U ,0x00000000U), + // .. .. STAT_NUM_CORR_ERR = 0x0 + // .. .. ==> 0XF80060F0[15:8] = 0x00000000U + // .. .. ==> MASK : 0x0000FF00U VAL : 0x00000000U + // .. .. STAT_NUM_UNCORR_ERR = 0x0 + // .. .. ==> 0XF80060F0[7:0] = 0x00000000U + // .. .. ==> MASK : 0x000000FFU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060F0, 0x0000FFFFU ,0x00000000U), + // .. .. reg_ddrc_ecc_mode = 0x0 + // .. .. ==> 0XF80060F4[2:0] = 0x00000000U + // .. .. ==> MASK : 0x00000007U VAL : 0x00000000U + // .. .. reg_ddrc_dis_scrub = 0x1 + // .. .. ==> 0XF80060F4[3:3] = 0x00000001U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000008U + // .. .. + EMIT_MASKWRITE(0XF80060F4, 0x0000000FU ,0x00000008U), + // .. .. reg_phy_dif_on = 0x0 + // .. .. ==> 0XF8006114[3:0] = 0x00000000U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000000U + // .. .. reg_phy_dif_off = 0x0 + // .. .. ==> 0XF8006114[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006114, 0x000000FFU ,0x00000000U), + // .. .. reg_phy_data_slice_in_use = 0x1 + // .. .. ==> 0XF8006118[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006118[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF8006118[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006118[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF8006118[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF8006118[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF8006118[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006118, 0x7FFFFFCFU ,0x40000001U), + // .. .. reg_phy_data_slice_in_use = 0x1 + // .. .. ==> 0XF800611C[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF800611C[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF800611C[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF800611C[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF800611C[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF800611C[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF800611C[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF800611C, 0x7FFFFFCFU ,0x40000001U), + // .. .. reg_phy_data_slice_in_use = 0x0 + // .. .. ==> 0XF8006120[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF8006120[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF8006120[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF8006120[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006120, 0x7FFFFFCFU ,0x40000000U), + // .. .. reg_phy_data_slice_in_use = 0x0 + // .. .. ==> 0XF8006124[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006124[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF8006124[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006124[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF8006124[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF8006124[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF8006124[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006124, 0x7FFFFFCFU ,0x40000000U), + // .. .. reg_phy_wrlvl_init_ratio = 0x5 + // .. .. ==> 0XF800612C[9:0] = 0x00000005U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000005U + // .. .. reg_phy_gatelvl_init_ratio = 0x9b + // .. .. ==> 0XF800612C[19:10] = 0x0000009BU + // .. .. ==> MASK : 0x000FFC00U VAL : 0x00026C00U + // .. .. + EMIT_MASKWRITE(0XF800612C, 0x000FFFFFU ,0x00026C05U), + // .. .. reg_phy_wrlvl_init_ratio = 0x7 + // .. .. ==> 0XF8006130[9:0] = 0x00000007U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000007U + // .. .. reg_phy_gatelvl_init_ratio = 0x98 + // .. .. ==> 0XF8006130[19:10] = 0x00000098U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x00026000U + // .. .. + EMIT_MASKWRITE(0XF8006130, 0x000FFFFFU ,0x00026007U), + // .. .. reg_phy_wrlvl_init_ratio = 0x0 + // .. .. ==> 0XF8006134[9:0] = 0x00000000U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000000U + // .. .. reg_phy_gatelvl_init_ratio = 0x76 + // .. .. ==> 0XF8006134[19:10] = 0x00000076U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x0001D800U + // .. .. + EMIT_MASKWRITE(0XF8006134, 0x000FFFFFU ,0x0001D800U), + // .. .. reg_phy_wrlvl_init_ratio = 0x0 + // .. .. ==> 0XF8006138[9:0] = 0x00000000U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000000U + // .. .. reg_phy_gatelvl_init_ratio = 0x78 + // .. .. ==> 0XF8006138[19:10] = 0x00000078U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x0001E000U + // .. .. + EMIT_MASKWRITE(0XF8006138, 0x000FFFFFU ,0x0001E000U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF8006140[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006140[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006140[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006140, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF8006144[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006144[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006144[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006144, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF8006148[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006148[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006148[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006148, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF800614C[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF800614C[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF800614C[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800614C, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x85 + // .. .. ==> 0XF8006154[9:0] = 0x00000085U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000085U + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006154[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006154[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006154, 0x000FFFFFU ,0x00000085U), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x87 + // .. .. ==> 0XF8006158[9:0] = 0x00000087U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000087U + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006158[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006158[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006158, 0x000FFFFFU ,0x00000087U), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x7f + // .. .. ==> 0XF800615C[9:0] = 0x0000007FU + // .. .. ==> MASK : 0x000003FFU VAL : 0x0000007FU + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF800615C[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF800615C[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800615C, 0x000FFFFFU ,0x0000007FU), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x7c + // .. .. ==> 0XF8006160[9:0] = 0x0000007CU + // .. .. ==> MASK : 0x000003FFU VAL : 0x0000007CU + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006160[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006160[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006160, 0x000FFFFFU ,0x0000007CU), + // .. .. reg_phy_fifo_we_slave_ratio = 0xf0 + // .. .. ==> 0XF8006168[10:0] = 0x000000F0U + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000F0U + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF8006168[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF8006168[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006168, 0x001FFFFFU ,0x000000F0U), + // .. .. reg_phy_fifo_we_slave_ratio = 0xed + // .. .. ==> 0XF800616C[10:0] = 0x000000EDU + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000EDU + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF800616C[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF800616C[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800616C, 0x001FFFFFU ,0x000000EDU), + // .. .. reg_phy_fifo_we_slave_ratio = 0xcb + // .. .. ==> 0XF8006170[10:0] = 0x000000CBU + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000CBU + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF8006170[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF8006170[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006170, 0x001FFFFFU ,0x000000CBU), + // .. .. reg_phy_fifo_we_slave_ratio = 0xcd + // .. .. ==> 0XF8006174[10:0] = 0x000000CDU + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000CDU + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF8006174[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF8006174[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006174, 0x001FFFFFU ,0x000000CDU), + // .. .. reg_phy_wr_data_slave_ratio = 0xc5 + // .. .. ==> 0XF800617C[9:0] = 0x000000C5U + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000C5U + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF800617C[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF800617C[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800617C, 0x000FFFFFU ,0x000000C5U), + // .. .. reg_phy_wr_data_slave_ratio = 0xc7 + // .. .. ==> 0XF8006180[9:0] = 0x000000C7U + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000C7U + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF8006180[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF8006180[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006180, 0x000FFFFFU ,0x000000C7U), + // .. .. reg_phy_wr_data_slave_ratio = 0xbf + // .. .. ==> 0XF8006184[9:0] = 0x000000BFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000BFU + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF8006184[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF8006184[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006184, 0x000FFFFFU ,0x000000BFU), + // .. .. reg_phy_wr_data_slave_ratio = 0xbc + // .. .. ==> 0XF8006188[9:0] = 0x000000BCU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000BCU + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF8006188[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF8006188[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006188, 0x000FFFFFU ,0x000000BCU), + // .. .. reg_phy_bl2 = 0x0 + // .. .. ==> 0XF8006190[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_at_spd_atpg = 0x0 + // .. .. ==> 0XF8006190[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_bist_enable = 0x0 + // .. .. ==> 0XF8006190[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_bist_force_err = 0x0 + // .. .. ==> 0XF8006190[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_bist_mode = 0x0 + // .. .. ==> 0XF8006190[6:5] = 0x00000000U + // .. .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. .. reg_phy_invert_clkout = 0x1 + // .. .. ==> 0XF8006190[7:7] = 0x00000001U + // .. .. ==> MASK : 0x00000080U VAL : 0x00000080U + // .. .. reg_phy_sel_logic = 0x0 + // .. .. ==> 0XF8006190[9:9] = 0x00000000U + // .. .. ==> MASK : 0x00000200U VAL : 0x00000000U + // .. .. reg_phy_ctrl_slave_ratio = 0x100 + // .. .. ==> 0XF8006190[19:10] = 0x00000100U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x00040000U + // .. .. reg_phy_ctrl_slave_force = 0x0 + // .. .. ==> 0XF8006190[20:20] = 0x00000000U + // .. .. ==> MASK : 0x00100000U VAL : 0x00000000U + // .. .. reg_phy_ctrl_slave_delay = 0x0 + // .. .. ==> 0XF8006190[27:21] = 0x00000000U + // .. .. ==> MASK : 0x0FE00000U VAL : 0x00000000U + // .. .. reg_phy_lpddr = 0x0 + // .. .. ==> 0XF8006190[29:29] = 0x00000000U + // .. .. ==> MASK : 0x20000000U VAL : 0x00000000U + // .. .. reg_phy_cmd_latency = 0x0 + // .. .. ==> 0XF8006190[30:30] = 0x00000000U + // .. .. ==> MASK : 0x40000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006190, 0x6FFFFEFEU ,0x00040080U), + // .. .. reg_phy_wr_rl_delay = 0x2 + // .. .. ==> 0XF8006194[4:0] = 0x00000002U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000002U + // .. .. reg_phy_rd_rl_delay = 0x4 + // .. .. ==> 0XF8006194[9:5] = 0x00000004U + // .. .. ==> MASK : 0x000003E0U VAL : 0x00000080U + // .. .. reg_phy_dll_lock_diff = 0xf + // .. .. ==> 0XF8006194[13:10] = 0x0000000FU + // .. .. ==> MASK : 0x00003C00U VAL : 0x00003C00U + // .. .. reg_phy_use_wr_level = 0x1 + // .. .. ==> 0XF8006194[14:14] = 0x00000001U + // .. .. ==> MASK : 0x00004000U VAL : 0x00004000U + // .. .. reg_phy_use_rd_dqs_gate_level = 0x1 + // .. .. ==> 0XF8006194[15:15] = 0x00000001U + // .. .. ==> MASK : 0x00008000U VAL : 0x00008000U + // .. .. reg_phy_use_rd_data_eye_level = 0x1 + // .. .. ==> 0XF8006194[16:16] = 0x00000001U + // .. .. ==> MASK : 0x00010000U VAL : 0x00010000U + // .. .. reg_phy_dis_calib_rst = 0x0 + // .. .. ==> 0XF8006194[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_phy_ctrl_slave_delay = 0x0 + // .. .. ==> 0XF8006194[19:18] = 0x00000000U + // .. .. ==> MASK : 0x000C0000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006194, 0x000FFFFFU ,0x0001FC82U), + // .. .. reg_arb_page_addr_mask = 0x0 + // .. .. ==> 0XF8006204[31:0] = 0x00000000U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006204, 0xFFFFFFFFU ,0x00000000U), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF8006208[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF8006208[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF8006208[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF8006208[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006208, 0x000703FFU ,0x000003FFU), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF800620C[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF800620C[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF800620C[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF800620C[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800620C, 0x000703FFU ,0x000003FFU), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF8006210[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF8006210[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF8006210[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF8006210[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006210, 0x000703FFU ,0x000003FFU), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF8006214[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF8006214[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF8006214[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF8006214[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006214, 0x000703FFU ,0x000003FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF8006218[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF8006218[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF8006218[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF8006218[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF8006218[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006218, 0x000F03FFU ,0x000003FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF800621C[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF800621C[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF800621C[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF800621C[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF800621C[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800621C, 0x000F03FFU ,0x000003FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF8006220[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF8006220[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF8006220[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF8006220[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF8006220[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006220, 0x000F03FFU ,0x000003FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF8006224[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF8006224[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF8006224[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF8006224[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF8006224[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006224, 0x000F03FFU ,0x000003FFU), + // .. .. reg_ddrc_lpddr2 = 0x0 + // .. .. ==> 0XF80062A8[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_derate_enable = 0x0 + // .. .. ==> 0XF80062A8[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_ddrc_mr4_margin = 0x0 + // .. .. ==> 0XF80062A8[11:4] = 0x00000000U + // .. .. ==> MASK : 0x00000FF0U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80062A8, 0x00000FF5U ,0x00000000U), + // .. .. reg_ddrc_mr4_read_interval = 0x0 + // .. .. ==> 0XF80062AC[31:0] = 0x00000000U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80062AC, 0xFFFFFFFFU ,0x00000000U), + // .. .. reg_ddrc_min_stable_clock_x1 = 0x5 + // .. .. ==> 0XF80062B0[3:0] = 0x00000005U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000005U + // .. .. reg_ddrc_idle_after_reset_x32 = 0x12 + // .. .. ==> 0XF80062B0[11:4] = 0x00000012U + // .. .. ==> MASK : 0x00000FF0U VAL : 0x00000120U + // .. .. reg_ddrc_t_mrw = 0x5 + // .. .. ==> 0XF80062B0[21:12] = 0x00000005U + // .. .. ==> MASK : 0x003FF000U VAL : 0x00005000U + // .. .. + EMIT_MASKWRITE(0XF80062B0, 0x003FFFFFU ,0x00005125U), + // .. .. reg_ddrc_max_auto_init_x1024 = 0xa6 + // .. .. ==> 0XF80062B4[7:0] = 0x000000A6U + // .. .. ==> MASK : 0x000000FFU VAL : 0x000000A6U + // .. .. reg_ddrc_dev_zqinit_x32 = 0x12 + // .. .. ==> 0XF80062B4[17:8] = 0x00000012U + // .. .. ==> MASK : 0x0003FF00U VAL : 0x00001200U + // .. .. + EMIT_MASKWRITE(0XF80062B4, 0x0003FFFFU ,0x000012A6U), + // .. .. START: POLL ON DCI STATUS + // .. .. DONE = 1 + // .. .. ==> 0XF8000B74[13:13] = 0x00000001U + // .. .. ==> MASK : 0x00002000U VAL : 0x00002000U + // .. .. + EMIT_MASKPOLL(0XF8000B74, 0x00002000U), + // .. .. FINISH: POLL ON DCI STATUS + // .. .. START: UNLOCK DDR + // .. .. reg_ddrc_soft_rstb = 0x1 + // .. .. ==> 0XF8006000[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. reg_ddrc_powerdown_en = 0x0 + // .. .. ==> 0XF8006000[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_ddrc_data_bus_width = 0x1 + // .. .. ==> 0XF8006000[3:2] = 0x00000001U + // .. .. ==> MASK : 0x0000000CU VAL : 0x00000004U + // .. .. reg_ddrc_burst8_refresh = 0x0 + // .. .. ==> 0XF8006000[6:4] = 0x00000000U + // .. .. ==> MASK : 0x00000070U VAL : 0x00000000U + // .. .. reg_ddrc_rdwr_idle_gap = 1 + // .. .. ==> 0XF8006000[13:7] = 0x00000001U + // .. .. ==> MASK : 0x00003F80U VAL : 0x00000080U + // .. .. reg_ddrc_dis_rd_bypass = 0x0 + // .. .. ==> 0XF8006000[14:14] = 0x00000000U + // .. .. ==> MASK : 0x00004000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_act_bypass = 0x0 + // .. .. ==> 0XF8006000[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_auto_refresh = 0x0 + // .. .. ==> 0XF8006000[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006000, 0x0001FFFFU ,0x00000085U), + // .. .. FINISH: UNLOCK DDR + // .. .. START: CHECK DDR STATUS + // .. .. ddrc_reg_operating_mode = 1 + // .. .. ==> 0XF8006054[2:0] = 0x00000001U + // .. .. ==> MASK : 0x00000007U VAL : 0x00000001U + // .. .. + EMIT_MASKPOLL(0XF8006054, 0x00000007U), + // .. .. FINISH: CHECK DDR STATUS + // .. FINISH: DDR INITIALIZATION + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_mio_init_data_3_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: OCM REMAPPING + // .. FINISH: OCM REMAPPING + // .. START: DDRIOB SETTINGS + // .. reserved_INP_POWER = 0x0 + // .. ==> 0XF8000B40[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B40[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE_B = 0x0 + // .. ==> 0XF8000B40[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B40[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCI_TYPE = 0x0 + // .. ==> 0XF8000B40[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B40[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B40[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B40[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B40[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B40, 0x00000FFFU ,0x00000600U), + // .. reserved_INP_POWER = 0x0 + // .. ==> 0XF8000B44[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B44[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE_B = 0x0 + // .. ==> 0XF8000B44[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B44[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCI_TYPE = 0x0 + // .. ==> 0XF8000B44[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B44[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B44[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B44[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B44[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B44, 0x00000FFFU ,0x00000600U), + // .. reserved_INP_POWER = 0x0 + // .. ==> 0XF8000B48[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x1 + // .. ==> 0XF8000B48[2:1] = 0x00000001U + // .. ==> MASK : 0x00000006U VAL : 0x00000002U + // .. DCI_UPDATE_B = 0x0 + // .. ==> 0XF8000B48[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x1 + // .. ==> 0XF8000B48[4:4] = 0x00000001U + // .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. DCI_TYPE = 0x3 + // .. ==> 0XF8000B48[6:5] = 0x00000003U + // .. ==> MASK : 0x00000060U VAL : 0x00000060U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B48[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B48[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B48[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B48[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B48, 0x00000FFFU ,0x00000672U), + // .. reserved_INP_POWER = 0x0 + // .. ==> 0XF8000B4C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B4C[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE_B = 0x0 + // .. ==> 0XF8000B4C[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B4C[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCI_TYPE = 0x0 + // .. ==> 0XF8000B4C[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B4C[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B4C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x0 + // .. ==> 0XF8000B4C[10:9] = 0x00000000U + // .. ==> MASK : 0x00000600U VAL : 0x00000000U + // .. PULLUP_EN = 0x1 + // .. ==> 0XF8000B4C[11:11] = 0x00000001U + // .. ==> MASK : 0x00000800U VAL : 0x00000800U + // .. + EMIT_MASKWRITE(0XF8000B4C, 0x00000FFFU ,0x00000800U), + // .. reserved_INP_POWER = 0x0 + // .. ==> 0XF8000B50[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x2 + // .. ==> 0XF8000B50[2:1] = 0x00000002U + // .. ==> MASK : 0x00000006U VAL : 0x00000004U + // .. DCI_UPDATE_B = 0x0 + // .. ==> 0XF8000B50[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x1 + // .. ==> 0XF8000B50[4:4] = 0x00000001U + // .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. DCI_TYPE = 0x3 + // .. ==> 0XF8000B50[6:5] = 0x00000003U + // .. ==> MASK : 0x00000060U VAL : 0x00000060U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B50[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B50[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B50[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B50[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B50, 0x00000FFFU ,0x00000674U), + // .. reserved_INP_POWER = 0x0 + // .. ==> 0XF8000B54[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B54[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE_B = 0x0 + // .. ==> 0XF8000B54[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B54[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCI_TYPE = 0x0 + // .. ==> 0XF8000B54[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B54[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B54[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x0 + // .. ==> 0XF8000B54[10:9] = 0x00000000U + // .. ==> MASK : 0x00000600U VAL : 0x00000000U + // .. PULLUP_EN = 0x1 + // .. ==> 0XF8000B54[11:11] = 0x00000001U + // .. ==> MASK : 0x00000800U VAL : 0x00000800U + // .. + EMIT_MASKWRITE(0XF8000B54, 0x00000FFFU ,0x00000800U), + // .. reserved_INP_POWER = 0x0 + // .. ==> 0XF8000B58[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B58[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE_B = 0x0 + // .. ==> 0XF8000B58[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B58[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCI_TYPE = 0x0 + // .. ==> 0XF8000B58[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B58[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B58[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B58[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B58[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B58, 0x00000FFFU ,0x00000600U), + // .. reserved_DRIVE_P = 0x1c + // .. ==> 0XF8000B5C[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. reserved_DRIVE_N = 0xc + // .. ==> 0XF8000B5C[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. reserved_SLEW_P = 0x3 + // .. ==> 0XF8000B5C[18:14] = 0x00000003U + // .. ==> MASK : 0x0007C000U VAL : 0x0000C000U + // .. reserved_SLEW_N = 0x3 + // .. ==> 0XF8000B5C[23:19] = 0x00000003U + // .. ==> MASK : 0x00F80000U VAL : 0x00180000U + // .. reserved_GTL = 0x0 + // .. ==> 0XF8000B5C[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. reserved_RTERM = 0x0 + // .. ==> 0XF8000B5C[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B5C, 0xFFFFFFFFU ,0x0018C61CU), + // .. reserved_DRIVE_P = 0x1c + // .. ==> 0XF8000B60[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. reserved_DRIVE_N = 0xc + // .. ==> 0XF8000B60[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. reserved_SLEW_P = 0x6 + // .. ==> 0XF8000B60[18:14] = 0x00000006U + // .. ==> MASK : 0x0007C000U VAL : 0x00018000U + // .. reserved_SLEW_N = 0x1f + // .. ==> 0XF8000B60[23:19] = 0x0000001FU + // .. ==> MASK : 0x00F80000U VAL : 0x00F80000U + // .. reserved_GTL = 0x0 + // .. ==> 0XF8000B60[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. reserved_RTERM = 0x0 + // .. ==> 0XF8000B60[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B60, 0xFFFFFFFFU ,0x00F9861CU), + // .. reserved_DRIVE_P = 0x1c + // .. ==> 0XF8000B64[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. reserved_DRIVE_N = 0xc + // .. ==> 0XF8000B64[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. reserved_SLEW_P = 0x6 + // .. ==> 0XF8000B64[18:14] = 0x00000006U + // .. ==> MASK : 0x0007C000U VAL : 0x00018000U + // .. reserved_SLEW_N = 0x1f + // .. ==> 0XF8000B64[23:19] = 0x0000001FU + // .. ==> MASK : 0x00F80000U VAL : 0x00F80000U + // .. reserved_GTL = 0x0 + // .. ==> 0XF8000B64[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. reserved_RTERM = 0x0 + // .. ==> 0XF8000B64[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B64, 0xFFFFFFFFU ,0x00F9861CU), + // .. reserved_DRIVE_P = 0x1c + // .. ==> 0XF8000B68[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. reserved_DRIVE_N = 0xc + // .. ==> 0XF8000B68[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. reserved_SLEW_P = 0x6 + // .. ==> 0XF8000B68[18:14] = 0x00000006U + // .. ==> MASK : 0x0007C000U VAL : 0x00018000U + // .. reserved_SLEW_N = 0x1f + // .. ==> 0XF8000B68[23:19] = 0x0000001FU + // .. ==> MASK : 0x00F80000U VAL : 0x00F80000U + // .. reserved_GTL = 0x0 + // .. ==> 0XF8000B68[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. reserved_RTERM = 0x0 + // .. ==> 0XF8000B68[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B68, 0xFFFFFFFFU ,0x00F9861CU), + // .. VREF_INT_EN = 0x0 + // .. ==> 0XF8000B6C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. VREF_SEL = 0x0 + // .. ==> 0XF8000B6C[4:1] = 0x00000000U + // .. ==> MASK : 0x0000001EU VAL : 0x00000000U + // .. VREF_EXT_EN = 0x1 + // .. ==> 0XF8000B6C[6:5] = 0x00000001U + // .. ==> MASK : 0x00000060U VAL : 0x00000020U + // .. reserved_VREF_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[8:7] = 0x00000000U + // .. ==> MASK : 0x00000180U VAL : 0x00000000U + // .. REFIO_EN = 0x1 + // .. ==> 0XF8000B6C[9:9] = 0x00000001U + // .. ==> MASK : 0x00000200U VAL : 0x00000200U + // .. reserved_REFIO_TEST = 0x0 + // .. ==> 0XF8000B6C[11:10] = 0x00000000U + // .. ==> MASK : 0x00000C00U VAL : 0x00000000U + // .. reserved_REFIO_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. reserved_DRST_B_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. reserved_CKE_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[14:14] = 0x00000000U + // .. ==> MASK : 0x00004000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B6C, 0x00007FFFU ,0x00000220U), + // .. .. START: ASSERT RESET + // .. .. RESET = 1 + // .. .. ==> 0XF8000B70[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. + EMIT_MASKWRITE(0XF8000B70, 0x00000001U ,0x00000001U), + // .. .. FINISH: ASSERT RESET + // .. .. START: DEASSERT RESET + // .. .. RESET = 0 + // .. .. ==> 0XF8000B70[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reserved_VRN_OUT = 0x1 + // .. .. ==> 0XF8000B70[5:5] = 0x00000001U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000020U + // .. .. + EMIT_MASKWRITE(0XF8000B70, 0x00000021U ,0x00000020U), + // .. .. FINISH: DEASSERT RESET + // .. .. RESET = 0x1 + // .. .. ==> 0XF8000B70[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. ENABLE = 0x1 + // .. .. ==> 0XF8000B70[1:1] = 0x00000001U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. reserved_VRP_TRI = 0x0 + // .. .. ==> 0XF8000B70[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reserved_VRN_TRI = 0x0 + // .. .. ==> 0XF8000B70[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reserved_VRP_OUT = 0x0 + // .. .. ==> 0XF8000B70[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reserved_VRN_OUT = 0x1 + // .. .. ==> 0XF8000B70[5:5] = 0x00000001U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000020U + // .. .. NREF_OPT1 = 0x0 + // .. .. ==> 0XF8000B70[7:6] = 0x00000000U + // .. .. ==> MASK : 0x000000C0U VAL : 0x00000000U + // .. .. NREF_OPT2 = 0x0 + // .. .. ==> 0XF8000B70[10:8] = 0x00000000U + // .. .. ==> MASK : 0x00000700U VAL : 0x00000000U + // .. .. NREF_OPT4 = 0x1 + // .. .. ==> 0XF8000B70[13:11] = 0x00000001U + // .. .. ==> MASK : 0x00003800U VAL : 0x00000800U + // .. .. PREF_OPT1 = 0x0 + // .. .. ==> 0XF8000B70[15:14] = 0x00000000U + // .. .. ==> MASK : 0x0000C000U VAL : 0x00000000U + // .. .. PREF_OPT2 = 0x0 + // .. .. ==> 0XF8000B70[19:17] = 0x00000000U + // .. .. ==> MASK : 0x000E0000U VAL : 0x00000000U + // .. .. UPDATE_CONTROL = 0x0 + // .. .. ==> 0XF8000B70[20:20] = 0x00000000U + // .. .. ==> MASK : 0x00100000U VAL : 0x00000000U + // .. .. reserved_INIT_COMPLETE = 0x0 + // .. .. ==> 0XF8000B70[21:21] = 0x00000000U + // .. .. ==> MASK : 0x00200000U VAL : 0x00000000U + // .. .. reserved_TST_CLK = 0x0 + // .. .. ==> 0XF8000B70[22:22] = 0x00000000U + // .. .. ==> MASK : 0x00400000U VAL : 0x00000000U + // .. .. reserved_TST_HLN = 0x0 + // .. .. ==> 0XF8000B70[23:23] = 0x00000000U + // .. .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. .. reserved_TST_HLP = 0x0 + // .. .. ==> 0XF8000B70[24:24] = 0x00000000U + // .. .. ==> MASK : 0x01000000U VAL : 0x00000000U + // .. .. reserved_TST_RST = 0x0 + // .. .. ==> 0XF8000B70[25:25] = 0x00000000U + // .. .. ==> MASK : 0x02000000U VAL : 0x00000000U + // .. .. reserved_INT_DCI_EN = 0x0 + // .. .. ==> 0XF8000B70[26:26] = 0x00000000U + // .. .. ==> MASK : 0x04000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8000B70, 0x07FEFFFFU ,0x00000823U), + // .. FINISH: DDRIOB SETTINGS + // .. START: MIO PROGRAMMING + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000700[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000700[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000700[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000700[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000700[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000700[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000700[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000700[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000700[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000700, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000704[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000704[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000704[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000704[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000704[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000704[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000704[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000704[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000704[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000704, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000708[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000708[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000708[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000708[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000708[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000708[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000708[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000708[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000708[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000708, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800070C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800070C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800070C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800070C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800070C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800070C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800070C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF800070C[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF800070C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800070C, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000710[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000710[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000710[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000710[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000710[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000710[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000710[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000710[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000710[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000710, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000714[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000714[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000714[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000714[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000714[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000714[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000714[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000714[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000714[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000714, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000718[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000718[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000718[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000718[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000718[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000718[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000718[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000718[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000718[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000718, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800071C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800071C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800071C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800071C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800071C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800071C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800071C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF800071C[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF800071C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800071C, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000720[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000720[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000720[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000720[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000720[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000720[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000720[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000720[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000720[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000720, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000724[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000724[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000724[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000724[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000724[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000724[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000724[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000724[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000724[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000724, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000728[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000728[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000728[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000728[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000728[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000728[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000728[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000728[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000728[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000728, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800072C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800072C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800072C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800072C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800072C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800072C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800072C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF800072C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800072C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800072C, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000730[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000730[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000730[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000730[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000730[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000730[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000730[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000730[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000730[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000730, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000734[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000734[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000734[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000734[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000734[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000734[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000734[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000734[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000734[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000734, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000738[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF8000738[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000738[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000738[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 7 + // .. ==> 0XF8000738[7:5] = 0x00000007U + // .. ==> MASK : 0x000000E0U VAL : 0x000000E0U + // .. Speed = 0 + // .. ==> 0XF8000738[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000738[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000738[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000738[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000738, 0x00003FFFU ,0x000016E1U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800073C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800073C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800073C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800073C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 7 + // .. ==> 0XF800073C[7:5] = 0x00000007U + // .. ==> MASK : 0x000000E0U VAL : 0x000000E0U + // .. Speed = 0 + // .. ==> 0XF800073C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800073C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF800073C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800073C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800073C, 0x00003FFFU ,0x000016E0U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000740[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000740[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000740[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000740[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000740[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000740[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000740[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000740[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000740[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000740, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000744[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000744[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000744[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000744[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000744[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000744[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000744[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000744[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000744[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000744, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000748[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000748[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000748[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000748[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000748[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000748[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000748[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000748[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000748[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000748, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800074C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF800074C[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF800074C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800074C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800074C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800074C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800074C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800074C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800074C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800074C, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000750[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000750[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000750[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000750[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000750[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000750[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000750[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000750[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000750[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000750, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000754[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000754[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000754[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000754[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000754[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000754[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000754[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000754[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000754[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000754, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000758[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000758[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000758[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000758[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000758[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000758[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000758[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000758[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000758[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000758, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF800075C[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF800075C[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF800075C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800075C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800075C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800075C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800075C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800075C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800075C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800075C, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000760[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000760[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000760[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000760[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000760[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000760[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000760[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000760[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000760[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000760, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000764[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000764[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000764[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000764[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000764[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000764[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000764[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000764[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000764[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000764, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000768[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000768[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000768[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000768[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000768[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000768[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000768[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000768[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000768[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000768, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF800076C[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF800076C[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF800076C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800076C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800076C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800076C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800076C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800076C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800076C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800076C, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000770[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000770[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000770[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000770[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000770[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000770[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000770[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000770[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000770[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000770, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000774[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF8000774[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000774[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000774[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000774[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000774[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000774[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000774[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000774[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000774, 0x00003FFFU ,0x00001205U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000778[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000778[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000778[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000778[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000778[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000778[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000778[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000778[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000778[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000778, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF800077C[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF800077C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF800077C[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF800077C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800077C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800077C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800077C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800077C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800077C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800077C, 0x00003FFFU ,0x00001205U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000780[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000780[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000780[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000780[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000780[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000780[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000780[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000780[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000780[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000780, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000784[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000784[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000784[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000784[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000784[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000784[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000784[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000784[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000784[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000784, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000788[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000788[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000788[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000788[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000788[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000788[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000788[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000788[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000788[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000788, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800078C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800078C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF800078C[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF800078C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800078C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800078C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800078C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800078C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800078C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800078C, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000790[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF8000790[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000790[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000790[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000790[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000790[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000790[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000790[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000790[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000790, 0x00003FFFU ,0x00001205U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000794[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000794[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000794[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000794[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000794[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000794[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000794[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000794[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000794[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000794, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000798[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000798[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000798[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000798[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000798[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000798[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000798[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000798[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000798[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000798, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800079C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800079C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF800079C[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF800079C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800079C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800079C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800079C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800079C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800079C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800079C, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007A0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007A0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007A0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007A0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007A0[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007A0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007A0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007A0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007A0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007A0, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007A4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007A4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007A4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007A4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007A4[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007A4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007A4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007A4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007A4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007A4, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007A8[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007A8[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007A8[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007A8[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007A8[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007A8[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007A8[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007A8[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007A8[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007A8, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007AC[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007AC[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007AC[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007AC[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007AC[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007AC[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007AC[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007AC[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007AC[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007AC, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007B0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007B0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007B0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007B0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007B0[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007B0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007B0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007B0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007B0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007B0, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007B4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007B4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007B4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007B4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007B4[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007B4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007B4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007B4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007B4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007B4, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007B8[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007B8[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007B8[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007B8[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007B8[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007B8[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007B8[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007B8[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007B8[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007B8, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF80007BC[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. Speed = 0 + // .. ==> 0XF80007BC[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007BC[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007BC[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007BC[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007BC, 0x00003F01U ,0x00001201U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007C0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007C0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007C0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007C0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007C0[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007C0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007C0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007C0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007C0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007C0, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007C4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007C4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007C4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007C4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007C4[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007C4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007C4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007C4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007C4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007C4, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007C8[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007C8[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007C8[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007C8[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007C8[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007C8[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007C8[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007C8[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007C8[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007C8, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007CC[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007CC[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007CC[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007CC[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007CC[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007CC[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007CC[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007CC[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007CC[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007CC, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007D0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007D0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007D0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007D0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007D0[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007D0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007D0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007D0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007D0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007D0, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007D4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007D4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007D4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007D4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007D4[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007D4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007D4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007D4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007D4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007D4, 0x00003FFFU ,0x00001280U), + // .. SDIO0_WP_SEL = 55 + // .. ==> 0XF8000830[5:0] = 0x00000037U + // .. ==> MASK : 0x0000003FU VAL : 0x00000037U + // .. SDIO0_CD_SEL = 47 + // .. ==> 0XF8000830[21:16] = 0x0000002FU + // .. ==> MASK : 0x003F0000U VAL : 0x002F0000U + // .. + EMIT_MASKWRITE(0XF8000830, 0x003F003FU ,0x002F0037U), + // .. FINISH: MIO PROGRAMMING + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_peripherals_init_data_3_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: DDR TERM/IBUF_DISABLE_MODE SETTINGS + // .. IBUF_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B48[7:7] = 0x00000001U + // .. ==> MASK : 0x00000080U VAL : 0x00000080U + // .. TERM_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B48[8:8] = 0x00000001U + // .. ==> MASK : 0x00000100U VAL : 0x00000100U + // .. + EMIT_MASKWRITE(0XF8000B48, 0x00000180U ,0x00000180U), + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B4C[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B4C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B4C, 0x00000180U ,0x00000000U), + // .. IBUF_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B50[7:7] = 0x00000001U + // .. ==> MASK : 0x00000080U VAL : 0x00000080U + // .. TERM_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B50[8:8] = 0x00000001U + // .. ==> MASK : 0x00000100U VAL : 0x00000100U + // .. + EMIT_MASKWRITE(0XF8000B50, 0x00000180U ,0x00000180U), + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B54[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B54[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B54, 0x00000180U ,0x00000000U), + // .. FINISH: DDR TERM/IBUF_DISABLE_MODE SETTINGS + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // .. START: SRAM/NOR SET OPMODE + // .. FINISH: SRAM/NOR SET OPMODE + // .. START: UART REGISTERS + // .. BDIV = 0x5 + // .. ==> 0XE0000034[7:0] = 0x00000005U + // .. ==> MASK : 0x000000FFU VAL : 0x00000005U + // .. + EMIT_MASKWRITE(0XE0000034, 0x000000FFU ,0x00000006U), + // .. CD = 0x12 + // .. ==> 0XE0000018[15:0] = 0x00000012U + // .. ==> MASK : 0x0000FFFFU VAL : 0x00000012U + // .. + EMIT_MASKWRITE(0XE0000018, 0x0000FFFFU ,0x0000007CU), + // .. STPBRK = 0x0 + // .. ==> 0XE0000000[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. STTBRK = 0x0 + // .. ==> 0XE0000000[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. RSTTO = 0x0 + // .. ==> 0XE0000000[6:6] = 0x00000000U + // .. ==> MASK : 0x00000040U VAL : 0x00000000U + // .. TXDIS = 0x0 + // .. ==> 0XE0000000[5:5] = 0x00000000U + // .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. TXEN = 0x1 + // .. ==> 0XE0000000[4:4] = 0x00000001U + // .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. RXDIS = 0x0 + // .. ==> 0XE0000000[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. RXEN = 0x1 + // .. ==> 0XE0000000[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. TXRES = 0x1 + // .. ==> 0XE0000000[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. RXRES = 0x1 + // .. ==> 0XE0000000[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. + EMIT_MASKWRITE(0XE0000000, 0x000001FFU ,0x00000017U), + // .. CHMODE = 0x0 + // .. ==> 0XE0000004[9:8] = 0x00000000U + // .. ==> MASK : 0x00000300U VAL : 0x00000000U + // .. NBSTOP = 0x0 + // .. ==> 0XE0000004[7:6] = 0x00000000U + // .. ==> MASK : 0x000000C0U VAL : 0x00000000U + // .. PAR = 0x4 + // .. ==> 0XE0000004[5:3] = 0x00000004U + // .. ==> MASK : 0x00000038U VAL : 0x00000020U + // .. CHRL = 0x0 + // .. ==> 0XE0000004[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. CLKS = 0x0 + // .. ==> 0XE0000004[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XE0000004, 0x000003FFU ,0x00000020U), + // .. FINISH: UART REGISTERS + // .. START: QSPI REGISTERS + // .. Holdb_dr = 1 + // .. ==> 0XE000D000[19:19] = 0x00000001U + // .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. + EMIT_MASKWRITE(0XE000D000, 0x00080000U ,0x00080000U), + // .. FINISH: QSPI REGISTERS + // .. START: PL POWER ON RESET REGISTERS + // .. PCFG_POR_CNT_4K = 0 + // .. ==> 0XF8007000[29:29] = 0x00000000U + // .. ==> MASK : 0x20000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8007000, 0x20000000U ,0x00000000U), + // .. FINISH: PL POWER ON RESET REGISTERS + // .. START: SMC TIMING CALCULATION REGISTER UPDATE + // .. .. START: NAND SET CYCLE + // .. .. FINISH: NAND SET CYCLE + // .. .. START: OPMODE + // .. .. FINISH: OPMODE + // .. .. START: DIRECT COMMAND + // .. .. FINISH: DIRECT COMMAND + // .. .. START: SRAM/NOR CS0 SET CYCLE + // .. .. FINISH: SRAM/NOR CS0 SET CYCLE + // .. .. START: DIRECT COMMAND + // .. .. FINISH: DIRECT COMMAND + // .. .. START: NOR CS0 BASE ADDRESS + // .. .. FINISH: NOR CS0 BASE ADDRESS + // .. .. START: SRAM/NOR CS1 SET CYCLE + // .. .. FINISH: SRAM/NOR CS1 SET CYCLE + // .. .. START: DIRECT COMMAND + // .. .. FINISH: DIRECT COMMAND + // .. .. START: NOR CS1 BASE ADDRESS + // .. .. FINISH: NOR CS1 BASE ADDRESS + // .. .. START: USB RESET + // .. .. .. START: USB0 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. DIRECTION_1 = 0x4000 + // .. .. .. .. ==> 0XE000A244[21:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x003FFFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A244, 0x003FFFFFU ,0x00004000U), + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. MASK_1_LSW = 0xbfff + // .. .. .. .. ==> 0XE000A008[31:16] = 0x0000BFFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xBFFF0000U + // .. .. .. .. DATA_1_LSW = 0x4000 + // .. .. .. .. ==> 0XE000A008[15:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A008, 0xFFFFFFFFU ,0xBFFF4000U), + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. OP_ENABLE_1 = 0x4000 + // .. .. .. .. ==> 0XE000A248[21:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x003FFFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A248, 0x003FFFFFU ,0x00004000U), + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. MASK_1_LSW = 0xbfff + // .. .. .. .. ==> 0XE000A008[31:16] = 0x0000BFFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xBFFF0000U + // .. .. .. .. DATA_1_LSW = 0x0 + // .. .. .. .. ==> 0XE000A008[15:0] = 0x00000000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A008, 0xFFFFFFFFU ,0xBFFF0000U), + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. MASK_1_LSW = 0xbfff + // .. .. .. .. ==> 0XE000A008[31:16] = 0x0000BFFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xBFFF0000U + // .. .. .. .. DATA_1_LSW = 0x4000 + // .. .. .. .. ==> 0XE000A008[15:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A008, 0xFFFFFFFFU ,0xBFFF4000U), + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: USB0 RESET + // .. .. .. START: USB1 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: USB1 RESET + // .. .. FINISH: USB RESET + // .. .. START: ENET RESET + // .. .. .. START: ENET0 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. DIRECTION_0 = 0x200 + // .. .. .. .. ==> 0XE000A204[31:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A204, 0xFFFFFFFFU ,0x00000200U), + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. MASK_0_LSW = 0xfdff + // .. .. .. .. ==> 0XE000A000[31:16] = 0x0000FDFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xFDFF0000U + // .. .. .. .. DATA_0_LSW = 0x200 + // .. .. .. .. ==> 0XE000A000[15:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A000, 0xFFFFFFFFU ,0xFDFF0200U), + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. OP_ENABLE_0 = 0x200 + // .. .. .. .. ==> 0XE000A208[31:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A208, 0xFFFFFFFFU ,0x00000200U), + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. MASK_0_LSW = 0xfdff + // .. .. .. .. ==> 0XE000A000[31:16] = 0x0000FDFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xFDFF0000U + // .. .. .. .. DATA_0_LSW = 0x0 + // .. .. .. .. ==> 0XE000A000[15:0] = 0x00000000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A000, 0xFFFFFFFFU ,0xFDFF0000U), + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. MASK_0_LSW = 0xfdff + // .. .. .. .. ==> 0XE000A000[31:16] = 0x0000FDFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xFDFF0000U + // .. .. .. .. DATA_0_LSW = 0x200 + // .. .. .. .. ==> 0XE000A000[15:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A000, 0xFFFFFFFFU ,0xFDFF0200U), + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: ENET0 RESET + // .. .. .. START: ENET1 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: ENET1 RESET + // .. .. FINISH: ENET RESET + // .. .. START: I2C RESET + // .. .. .. START: I2C0 RESET + // .. .. .. .. START: DIR MODE GPIO BANK0 + // .. .. .. .. FINISH: DIR MODE GPIO BANK0 + // .. .. .. .. START: DIR MODE GPIO BANK1 + // .. .. .. .. FINISH: DIR MODE GPIO BANK1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: I2C0 RESET + // .. .. .. START: I2C1 RESET + // .. .. .. .. START: DIR MODE GPIO BANK0 + // .. .. .. .. FINISH: DIR MODE GPIO BANK0 + // .. .. .. .. START: DIR MODE GPIO BANK1 + // .. .. .. .. FINISH: DIR MODE GPIO BANK1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: I2C1 RESET + // .. .. FINISH: I2C RESET + // .. .. START: NOR CHIP SELECT + // .. .. .. START: DIR MODE BANK 0 + // .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. FINISH: NOR CHIP SELECT + // .. FINISH: SMC TIMING CALCULATION REGISTER UPDATE + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_post_config_3_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: ENABLING LEVEL SHIFTER + // .. USER_LVL_INP_EN_0 = 1 + // .. ==> 0XF8000900[3:3] = 0x00000001U + // .. ==> MASK : 0x00000008U VAL : 0x00000008U + // .. USER_LVL_OUT_EN_0 = 1 + // .. ==> 0XF8000900[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. USER_LVL_INP_EN_1 = 1 + // .. ==> 0XF8000900[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. USER_LVL_OUT_EN_1 = 1 + // .. ==> 0XF8000900[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. + EMIT_MASKWRITE(0XF8000900, 0x0000000FU ,0x0000000FU), + // .. FINISH: ENABLING LEVEL SHIFTER + // .. START: FPGA RESETS TO 0 + // .. reserved_3 = 0 + // .. ==> 0XF8000240[31:25] = 0x00000000U + // .. ==> MASK : 0xFE000000U VAL : 0x00000000U + // .. reserved_FPGA_ACP_RST = 0 + // .. ==> 0XF8000240[24:24] = 0x00000000U + // .. ==> MASK : 0x01000000U VAL : 0x00000000U + // .. reserved_FPGA_AXDS3_RST = 0 + // .. ==> 0XF8000240[23:23] = 0x00000000U + // .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. reserved_FPGA_AXDS2_RST = 0 + // .. ==> 0XF8000240[22:22] = 0x00000000U + // .. ==> MASK : 0x00400000U VAL : 0x00000000U + // .. reserved_FPGA_AXDS1_RST = 0 + // .. ==> 0XF8000240[21:21] = 0x00000000U + // .. ==> MASK : 0x00200000U VAL : 0x00000000U + // .. reserved_FPGA_AXDS0_RST = 0 + // .. ==> 0XF8000240[20:20] = 0x00000000U + // .. ==> MASK : 0x00100000U VAL : 0x00000000U + // .. reserved_2 = 0 + // .. ==> 0XF8000240[19:18] = 0x00000000U + // .. ==> MASK : 0x000C0000U VAL : 0x00000000U + // .. reserved_FSSW1_FPGA_RST = 0 + // .. ==> 0XF8000240[17:17] = 0x00000000U + // .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. reserved_FSSW0_FPGA_RST = 0 + // .. ==> 0XF8000240[16:16] = 0x00000000U + // .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. reserved_1 = 0 + // .. ==> 0XF8000240[15:14] = 0x00000000U + // .. ==> MASK : 0x0000C000U VAL : 0x00000000U + // .. reserved_FPGA_FMSW1_RST = 0 + // .. ==> 0XF8000240[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. reserved_FPGA_FMSW0_RST = 0 + // .. ==> 0XF8000240[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. reserved_FPGA_DMA3_RST = 0 + // .. ==> 0XF8000240[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. reserved_FPGA_DMA2_RST = 0 + // .. ==> 0XF8000240[10:10] = 0x00000000U + // .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. reserved_FPGA_DMA1_RST = 0 + // .. ==> 0XF8000240[9:9] = 0x00000000U + // .. ==> MASK : 0x00000200U VAL : 0x00000000U + // .. reserved_FPGA_DMA0_RST = 0 + // .. ==> 0XF8000240[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. reserved = 0 + // .. ==> 0XF8000240[7:4] = 0x00000000U + // .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. FPGA3_OUT_RST = 0 + // .. ==> 0XF8000240[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. FPGA2_OUT_RST = 0 + // .. ==> 0XF8000240[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. FPGA1_OUT_RST = 0 + // .. ==> 0XF8000240[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. FPGA0_OUT_RST = 0 + // .. ==> 0XF8000240[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000240, 0xFFFFFFFFU ,0x00000000U), + // .. FINISH: FPGA RESETS TO 0 + // .. START: AFI REGISTERS + // .. .. START: AFI0 REGISTERS + // .. .. FINISH: AFI0 REGISTERS + // .. .. START: AFI1 REGISTERS + // .. .. FINISH: AFI1 REGISTERS + // .. .. START: AFI2 REGISTERS + // .. .. FINISH: AFI2 REGISTERS + // .. .. START: AFI3 REGISTERS + // .. .. FINISH: AFI3 REGISTERS + // .. .. START: AFI2 SECURE REGISTER + // .. .. FINISH: AFI2 SECURE REGISTER + // .. FINISH: AFI REGISTERS + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_debug_3_0[] = { + // START: top + // .. START: CROSS TRIGGER CONFIGURATIONS + // .. .. START: UNLOCKING CTI REGISTERS + // .. .. KEY = 0XC5ACCE55 + // .. .. ==> 0XF8898FB0[31:0] = 0xC5ACCE55U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0xC5ACCE55U + // .. .. + EMIT_WRITE(0XF8898FB0, 0xC5ACCE55U), + // .. .. KEY = 0XC5ACCE55 + // .. .. ==> 0XF8899FB0[31:0] = 0xC5ACCE55U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0xC5ACCE55U + // .. .. + EMIT_WRITE(0XF8899FB0, 0xC5ACCE55U), + // .. .. KEY = 0XC5ACCE55 + // .. .. ==> 0XF8809FB0[31:0] = 0xC5ACCE55U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0xC5ACCE55U + // .. .. + EMIT_WRITE(0XF8809FB0, 0xC5ACCE55U), + // .. .. FINISH: UNLOCKING CTI REGISTERS + // .. .. START: ENABLING CTI MODULES AND CHANNELS + // .. .. FINISH: ENABLING CTI MODULES AND CHANNELS + // .. .. START: MAPPING CPU0, CPU1 AND FTM EVENTS TO CTM CHANNELS + // .. .. FINISH: MAPPING CPU0, CPU1 AND FTM EVENTS TO CTM CHANNELS + // .. FINISH: CROSS TRIGGER CONFIGURATIONS + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_pll_init_data_2_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: PLL SLCR REGISTERS + // .. .. START: ARM PLL INIT + // .. .. PLL_RES = 0xc + // .. .. ==> 0XF8000110[7:4] = 0x0000000CU + // .. .. ==> MASK : 0x000000F0U VAL : 0x000000C0U + // .. .. PLL_CP = 0x2 + // .. .. ==> 0XF8000110[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. LOCK_CNT = 0x177 + // .. .. ==> 0XF8000110[21:12] = 0x00000177U + // .. .. ==> MASK : 0x003FF000U VAL : 0x00177000U + // .. .. + EMIT_MASKWRITE(0XF8000110, 0x003FFFF0U ,0x001772C0U), + // .. .. .. START: UPDATE FB_DIV + // .. .. .. PLL_FDIV = 0x1a + // .. .. .. ==> 0XF8000100[18:12] = 0x0000001AU + // .. .. .. ==> MASK : 0x0007F000U VAL : 0x0001A000U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x0007F000U ,0x0001A000U), + // .. .. .. FINISH: UPDATE FB_DIV + // .. .. .. START: BY PASS PLL + // .. .. .. PLL_BYPASS_FORCE = 1 + // .. .. .. ==> 0XF8000100[4:4] = 0x00000001U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000010U ,0x00000010U), + // .. .. .. FINISH: BY PASS PLL + // .. .. .. START: ASSERT RESET + // .. .. .. PLL_RESET = 1 + // .. .. .. ==> 0XF8000100[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000001U ,0x00000001U), + // .. .. .. FINISH: ASSERT RESET + // .. .. .. START: DEASSERT RESET + // .. .. .. PLL_RESET = 0 + // .. .. .. ==> 0XF8000100[0:0] = 0x00000000U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000001U ,0x00000000U), + // .. .. .. FINISH: DEASSERT RESET + // .. .. .. START: CHECK PLL STATUS + // .. .. .. ARM_PLL_LOCK = 1 + // .. .. .. ==> 0XF800010C[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKPOLL(0XF800010C, 0x00000001U), + // .. .. .. FINISH: CHECK PLL STATUS + // .. .. .. START: REMOVE PLL BY PASS + // .. .. .. PLL_BYPASS_FORCE = 0 + // .. .. .. ==> 0XF8000100[4:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000010U ,0x00000000U), + // .. .. .. FINISH: REMOVE PLL BY PASS + // .. .. .. SRCSEL = 0x0 + // .. .. .. ==> 0XF8000120[5:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. .. .. DIVISOR = 0x2 + // .. .. .. ==> 0XF8000120[13:8] = 0x00000002U + // .. .. .. ==> MASK : 0x00003F00U VAL : 0x00000200U + // .. .. .. CPU_6OR4XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[24:24] = 0x00000001U + // .. .. .. ==> MASK : 0x01000000U VAL : 0x01000000U + // .. .. .. CPU_3OR2XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[25:25] = 0x00000001U + // .. .. .. ==> MASK : 0x02000000U VAL : 0x02000000U + // .. .. .. CPU_2XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[26:26] = 0x00000001U + // .. .. .. ==> MASK : 0x04000000U VAL : 0x04000000U + // .. .. .. CPU_1XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[27:27] = 0x00000001U + // .. .. .. ==> MASK : 0x08000000U VAL : 0x08000000U + // .. .. .. CPU_PERI_CLKACT = 0x1 + // .. .. .. ==> 0XF8000120[28:28] = 0x00000001U + // .. .. .. ==> MASK : 0x10000000U VAL : 0x10000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000120, 0x1F003F30U ,0x1F000200U), + // .. .. FINISH: ARM PLL INIT + // .. .. START: DDR PLL INIT + // .. .. PLL_RES = 0xc + // .. .. ==> 0XF8000114[7:4] = 0x0000000CU + // .. .. ==> MASK : 0x000000F0U VAL : 0x000000C0U + // .. .. PLL_CP = 0x2 + // .. .. ==> 0XF8000114[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. LOCK_CNT = 0x1db + // .. .. ==> 0XF8000114[21:12] = 0x000001DBU + // .. .. ==> MASK : 0x003FF000U VAL : 0x001DB000U + // .. .. + EMIT_MASKWRITE(0XF8000114, 0x003FFFF0U ,0x001DB2C0U), + // .. .. .. START: UPDATE FB_DIV + // .. .. .. PLL_FDIV = 0x15 + // .. .. .. ==> 0XF8000104[18:12] = 0x00000015U + // .. .. .. ==> MASK : 0x0007F000U VAL : 0x00015000U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x0007F000U ,0x00015000U), + // .. .. .. FINISH: UPDATE FB_DIV + // .. .. .. START: BY PASS PLL + // .. .. .. PLL_BYPASS_FORCE = 1 + // .. .. .. ==> 0XF8000104[4:4] = 0x00000001U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000010U ,0x00000010U), + // .. .. .. FINISH: BY PASS PLL + // .. .. .. START: ASSERT RESET + // .. .. .. PLL_RESET = 1 + // .. .. .. ==> 0XF8000104[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000001U ,0x00000001U), + // .. .. .. FINISH: ASSERT RESET + // .. .. .. START: DEASSERT RESET + // .. .. .. PLL_RESET = 0 + // .. .. .. ==> 0XF8000104[0:0] = 0x00000000U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000001U ,0x00000000U), + // .. .. .. FINISH: DEASSERT RESET + // .. .. .. START: CHECK PLL STATUS + // .. .. .. DDR_PLL_LOCK = 1 + // .. .. .. ==> 0XF800010C[1:1] = 0x00000001U + // .. .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. .. + EMIT_MASKPOLL(0XF800010C, 0x00000002U), + // .. .. .. FINISH: CHECK PLL STATUS + // .. .. .. START: REMOVE PLL BY PASS + // .. .. .. PLL_BYPASS_FORCE = 0 + // .. .. .. ==> 0XF8000104[4:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000010U ,0x00000000U), + // .. .. .. FINISH: REMOVE PLL BY PASS + // .. .. .. DDR_3XCLKACT = 0x1 + // .. .. .. ==> 0XF8000124[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. DDR_2XCLKACT = 0x1 + // .. .. .. ==> 0XF8000124[1:1] = 0x00000001U + // .. .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. .. DDR_3XCLK_DIVISOR = 0x2 + // .. .. .. ==> 0XF8000124[25:20] = 0x00000002U + // .. .. .. ==> MASK : 0x03F00000U VAL : 0x00200000U + // .. .. .. DDR_2XCLK_DIVISOR = 0x3 + // .. .. .. ==> 0XF8000124[31:26] = 0x00000003U + // .. .. .. ==> MASK : 0xFC000000U VAL : 0x0C000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000124, 0xFFF00003U ,0x0C200003U), + // .. .. FINISH: DDR PLL INIT + // .. .. START: IO PLL INIT + // .. .. PLL_RES = 0xc + // .. .. ==> 0XF8000118[7:4] = 0x0000000CU + // .. .. ==> MASK : 0x000000F0U VAL : 0x000000C0U + // .. .. PLL_CP = 0x2 + // .. .. ==> 0XF8000118[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. LOCK_CNT = 0x1f4 + // .. .. ==> 0XF8000118[21:12] = 0x000001F4U + // .. .. ==> MASK : 0x003FF000U VAL : 0x001F4000U + // .. .. + EMIT_MASKWRITE(0XF8000118, 0x003FFFF0U ,0x001F42C0U), + // .. .. .. START: UPDATE FB_DIV + // .. .. .. PLL_FDIV = 0x14 + // .. .. .. ==> 0XF8000108[18:12] = 0x00000014U + // .. .. .. ==> MASK : 0x0007F000U VAL : 0x00014000U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x0007F000U ,0x00014000U), + // .. .. .. FINISH: UPDATE FB_DIV + // .. .. .. START: BY PASS PLL + // .. .. .. PLL_BYPASS_FORCE = 1 + // .. .. .. ==> 0XF8000108[4:4] = 0x00000001U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000010U ,0x00000010U), + // .. .. .. FINISH: BY PASS PLL + // .. .. .. START: ASSERT RESET + // .. .. .. PLL_RESET = 1 + // .. .. .. ==> 0XF8000108[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000001U ,0x00000001U), + // .. .. .. FINISH: ASSERT RESET + // .. .. .. START: DEASSERT RESET + // .. .. .. PLL_RESET = 0 + // .. .. .. ==> 0XF8000108[0:0] = 0x00000000U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000001U ,0x00000000U), + // .. .. .. FINISH: DEASSERT RESET + // .. .. .. START: CHECK PLL STATUS + // .. .. .. IO_PLL_LOCK = 1 + // .. .. .. ==> 0XF800010C[2:2] = 0x00000001U + // .. .. .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. .. .. + EMIT_MASKPOLL(0XF800010C, 0x00000004U), + // .. .. .. FINISH: CHECK PLL STATUS + // .. .. .. START: REMOVE PLL BY PASS + // .. .. .. PLL_BYPASS_FORCE = 0 + // .. .. .. ==> 0XF8000108[4:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000010U ,0x00000000U), + // .. .. .. FINISH: REMOVE PLL BY PASS + // .. .. FINISH: IO PLL INIT + // .. FINISH: PLL SLCR REGISTERS + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_clock_init_data_2_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: CLOCK CONTROL SLCR REGISTERS + // .. CLKACT = 0x1 + // .. ==> 0XF8000128[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. DIVISOR0 = 0x34 + // .. ==> 0XF8000128[13:8] = 0x00000034U + // .. ==> MASK : 0x00003F00U VAL : 0x00003400U + // .. DIVISOR1 = 0x2 + // .. ==> 0XF8000128[25:20] = 0x00000002U + // .. ==> MASK : 0x03F00000U VAL : 0x00200000U + // .. + EMIT_MASKWRITE(0XF8000128, 0x03F03F01U ,0x00203401U), + // .. CLKACT = 0x1 + // .. ==> 0XF8000138[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000138[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000138, 0x00000011U ,0x00000001U), + // .. CLKACT = 0x1 + // .. ==> 0XF8000140[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000140[6:4] = 0x00000000U + // .. ==> MASK : 0x00000070U VAL : 0x00000000U + // .. DIVISOR = 0x8 + // .. ==> 0XF8000140[13:8] = 0x00000008U + // .. ==> MASK : 0x00003F00U VAL : 0x00000800U + // .. DIVISOR1 = 0x1 + // .. ==> 0XF8000140[25:20] = 0x00000001U + // .. ==> MASK : 0x03F00000U VAL : 0x00100000U + // .. + EMIT_MASKWRITE(0XF8000140, 0x03F03F71U ,0x00100801U), + // .. CLKACT0 = 0x1 + // .. ==> 0XF8000150[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. CLKACT1 = 0x0 + // .. ==> 0XF8000150[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000150[5:4] = 0x00000000U + // .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. DIVISOR = 0x14 + // .. ==> 0XF8000150[13:8] = 0x00000014U + // .. ==> MASK : 0x00003F00U VAL : 0x00001400U + // .. + EMIT_MASKWRITE(0XF8000150, 0x00003F33U ,0x00001401U), + // .. CLKACT0 = 0x1 + // .. ==> 0XF8000154[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. CLKACT1 = 0x0 + // .. ==> 0XF8000154[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000154[5:4] = 0x00000000U + // .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. DIVISOR = 0xa + // .. ==> 0XF8000154[13:8] = 0x0000000AU + // .. ==> MASK : 0x00003F00U VAL : 0x00000A00U + // .. + EMIT_MASKWRITE(0XF8000154, 0x00003F33U ,0x00000A01U), + // .. CLKACT0 = 0x1 + // .. ==> 0XF8000158[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. CLKACT1 = 0x0 + // .. ==> 0XF8000158[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000158[5:4] = 0x00000000U + // .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. DIVISOR = 0x6 + // .. ==> 0XF8000158[13:8] = 0x00000006U + // .. ==> MASK : 0x00003F00U VAL : 0x00000600U + // .. + EMIT_MASKWRITE(0XF8000158, 0x00003F33U ,0x00000601U), + // .. .. START: TRACE CLOCK + // .. .. FINISH: TRACE CLOCK + // .. .. CLKACT = 0x1 + // .. .. ==> 0XF8000168[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. SRCSEL = 0x0 + // .. .. ==> 0XF8000168[5:4] = 0x00000000U + // .. .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. .. DIVISOR = 0x5 + // .. .. ==> 0XF8000168[13:8] = 0x00000005U + // .. .. ==> MASK : 0x00003F00U VAL : 0x00000500U + // .. .. + EMIT_MASKWRITE(0XF8000168, 0x00003F31U ,0x00000501U), + // .. .. SRCSEL = 0x0 + // .. .. ==> 0XF8000170[5:4] = 0x00000000U + // .. .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. .. DIVISOR0 = 0x5 + // .. .. ==> 0XF8000170[13:8] = 0x00000005U + // .. .. ==> MASK : 0x00003F00U VAL : 0x00000500U + // .. .. DIVISOR1 = 0x2 + // .. .. ==> 0XF8000170[25:20] = 0x00000002U + // .. .. ==> MASK : 0x03F00000U VAL : 0x00200000U + // .. .. + EMIT_MASKWRITE(0XF8000170, 0x03F03F30U ,0x00200500U), + // .. .. CLK_621_TRUE = 0x1 + // .. .. ==> 0XF80001C4[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. + EMIT_MASKWRITE(0XF80001C4, 0x00000001U ,0x00000001U), + // .. .. DMA_CPU_2XCLKACT = 0x1 + // .. .. ==> 0XF800012C[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. USB0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[2:2] = 0x00000001U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. .. USB1_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[3:3] = 0x00000001U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000008U + // .. .. GEM0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[6:6] = 0x00000001U + // .. .. ==> MASK : 0x00000040U VAL : 0x00000040U + // .. .. GEM1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[7:7] = 0x00000000U + // .. .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. .. SDI0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[10:10] = 0x00000001U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000400U + // .. .. SDI1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. SPI0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[14:14] = 0x00000001U + // .. .. ==> MASK : 0x00004000U VAL : 0x00004000U + // .. .. SPI1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. CAN0_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. CAN1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. I2C0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[18:18] = 0x00000001U + // .. .. ==> MASK : 0x00040000U VAL : 0x00040000U + // .. .. I2C1_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[19:19] = 0x00000001U + // .. .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. .. UART0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[20:20] = 0x00000001U + // .. .. ==> MASK : 0x00100000U VAL : 0x00100000U + // .. .. UART1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[21:21] = 0x00000000U + // .. .. ==> MASK : 0x00200000U VAL : 0x00000000U + // .. .. GPIO_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[22:22] = 0x00000001U + // .. .. ==> MASK : 0x00400000U VAL : 0x00400000U + // .. .. LQSPI_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[23:23] = 0x00000000U + // .. .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. .. SMC_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[24:24] = 0x00000001U + // .. .. ==> MASK : 0x01000000U VAL : 0x01000000U + // .. .. + EMIT_MASKWRITE(0XF800012C, 0x01FFCCCDU ,0x015C444DU), + // .. FINISH: CLOCK CONTROL SLCR REGISTERS + // .. START: THIS SHOULD BE BLANK + // .. FINISH: THIS SHOULD BE BLANK + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_ddr_init_data_2_0[] = { + // START: top + // .. START: DDR INITIALIZATION + // .. .. START: LOCK DDR + // .. .. reg_ddrc_soft_rstb = 0 + // .. .. ==> 0XF8006000[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_powerdown_en = 0x0 + // .. .. ==> 0XF8006000[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_ddrc_data_bus_width = 0x1 + // .. .. ==> 0XF8006000[3:2] = 0x00000001U + // .. .. ==> MASK : 0x0000000CU VAL : 0x00000004U + // .. .. reg_ddrc_burst8_refresh = 0x0 + // .. .. ==> 0XF8006000[6:4] = 0x00000000U + // .. .. ==> MASK : 0x00000070U VAL : 0x00000000U + // .. .. reg_ddrc_rdwr_idle_gap = 0x1 + // .. .. ==> 0XF8006000[13:7] = 0x00000001U + // .. .. ==> MASK : 0x00003F80U VAL : 0x00000080U + // .. .. reg_ddrc_dis_rd_bypass = 0x0 + // .. .. ==> 0XF8006000[14:14] = 0x00000000U + // .. .. ==> MASK : 0x00004000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_act_bypass = 0x0 + // .. .. ==> 0XF8006000[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_auto_refresh = 0x0 + // .. .. ==> 0XF8006000[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006000, 0x0001FFFFU ,0x00000084U), + // .. .. FINISH: LOCK DDR + // .. .. reg_ddrc_t_rfc_nom_x32 = 0x7f + // .. .. ==> 0XF8006004[11:0] = 0x0000007FU + // .. .. ==> MASK : 0x00000FFFU VAL : 0x0000007FU + // .. .. reg_ddrc_active_ranks = 0x1 + // .. .. ==> 0XF8006004[13:12] = 0x00000001U + // .. .. ==> MASK : 0x00003000U VAL : 0x00001000U + // .. .. reg_ddrc_addrmap_cs_bit0 = 0x0 + // .. .. ==> 0XF8006004[18:14] = 0x00000000U + // .. .. ==> MASK : 0x0007C000U VAL : 0x00000000U + // .. .. reg_ddrc_wr_odt_block = 0x1 + // .. .. ==> 0XF8006004[20:19] = 0x00000001U + // .. .. ==> MASK : 0x00180000U VAL : 0x00080000U + // .. .. reg_ddrc_diff_rank_rd_2cycle_gap = 0x0 + // .. .. ==> 0XF8006004[21:21] = 0x00000000U + // .. .. ==> MASK : 0x00200000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_cs_bit1 = 0x0 + // .. .. ==> 0XF8006004[26:22] = 0x00000000U + // .. .. ==> MASK : 0x07C00000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_open_bank = 0x0 + // .. .. ==> 0XF8006004[27:27] = 0x00000000U + // .. .. ==> MASK : 0x08000000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_4bank_ram = 0x0 + // .. .. ==> 0XF8006004[28:28] = 0x00000000U + // .. .. ==> MASK : 0x10000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006004, 0x1FFFFFFFU ,0x0008107FU), + // .. .. reg_ddrc_hpr_min_non_critical_x32 = 0xf + // .. .. ==> 0XF8006008[10:0] = 0x0000000FU + // .. .. ==> MASK : 0x000007FFU VAL : 0x0000000FU + // .. .. reg_ddrc_hpr_max_starve_x32 = 0xf + // .. .. ==> 0XF8006008[21:11] = 0x0000000FU + // .. .. ==> MASK : 0x003FF800U VAL : 0x00007800U + // .. .. reg_ddrc_hpr_xact_run_length = 0xf + // .. .. ==> 0XF8006008[25:22] = 0x0000000FU + // .. .. ==> MASK : 0x03C00000U VAL : 0x03C00000U + // .. .. + EMIT_MASKWRITE(0XF8006008, 0x03FFFFFFU ,0x03C0780FU), + // .. .. reg_ddrc_lpr_min_non_critical_x32 = 0x1 + // .. .. ==> 0XF800600C[10:0] = 0x00000001U + // .. .. ==> MASK : 0x000007FFU VAL : 0x00000001U + // .. .. reg_ddrc_lpr_max_starve_x32 = 0x2 + // .. .. ==> 0XF800600C[21:11] = 0x00000002U + // .. .. ==> MASK : 0x003FF800U VAL : 0x00001000U + // .. .. reg_ddrc_lpr_xact_run_length = 0x8 + // .. .. ==> 0XF800600C[25:22] = 0x00000008U + // .. .. ==> MASK : 0x03C00000U VAL : 0x02000000U + // .. .. + EMIT_MASKWRITE(0XF800600C, 0x03FFFFFFU ,0x02001001U), + // .. .. reg_ddrc_w_min_non_critical_x32 = 0x1 + // .. .. ==> 0XF8006010[10:0] = 0x00000001U + // .. .. ==> MASK : 0x000007FFU VAL : 0x00000001U + // .. .. reg_ddrc_w_xact_run_length = 0x8 + // .. .. ==> 0XF8006010[14:11] = 0x00000008U + // .. .. ==> MASK : 0x00007800U VAL : 0x00004000U + // .. .. reg_ddrc_w_max_starve_x32 = 0x2 + // .. .. ==> 0XF8006010[25:15] = 0x00000002U + // .. .. ==> MASK : 0x03FF8000U VAL : 0x00010000U + // .. .. + EMIT_MASKWRITE(0XF8006010, 0x03FFFFFFU ,0x00014001U), + // .. .. reg_ddrc_t_rc = 0x1a + // .. .. ==> 0XF8006014[5:0] = 0x0000001AU + // .. .. ==> MASK : 0x0000003FU VAL : 0x0000001AU + // .. .. reg_ddrc_t_rfc_min = 0x9e + // .. .. ==> 0XF8006014[13:6] = 0x0000009EU + // .. .. ==> MASK : 0x00003FC0U VAL : 0x00002780U + // .. .. reg_ddrc_post_selfref_gap_x32 = 0x10 + // .. .. ==> 0XF8006014[20:14] = 0x00000010U + // .. .. ==> MASK : 0x001FC000U VAL : 0x00040000U + // .. .. + EMIT_MASKWRITE(0XF8006014, 0x001FFFFFU ,0x0004279AU), + // .. .. reg_ddrc_wr2pre = 0x12 + // .. .. ==> 0XF8006018[4:0] = 0x00000012U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000012U + // .. .. reg_ddrc_powerdown_to_x32 = 0x6 + // .. .. ==> 0XF8006018[9:5] = 0x00000006U + // .. .. ==> MASK : 0x000003E0U VAL : 0x000000C0U + // .. .. reg_ddrc_t_faw = 0x15 + // .. .. ==> 0XF8006018[15:10] = 0x00000015U + // .. .. ==> MASK : 0x0000FC00U VAL : 0x00005400U + // .. .. reg_ddrc_t_ras_max = 0x23 + // .. .. ==> 0XF8006018[21:16] = 0x00000023U + // .. .. ==> MASK : 0x003F0000U VAL : 0x00230000U + // .. .. reg_ddrc_t_ras_min = 0x13 + // .. .. ==> 0XF8006018[26:22] = 0x00000013U + // .. .. ==> MASK : 0x07C00000U VAL : 0x04C00000U + // .. .. reg_ddrc_t_cke = 0x4 + // .. .. ==> 0XF8006018[31:28] = 0x00000004U + // .. .. ==> MASK : 0xF0000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006018, 0xF7FFFFFFU ,0x44E354D2U), + // .. .. reg_ddrc_write_latency = 0x5 + // .. .. ==> 0XF800601C[4:0] = 0x00000005U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000005U + // .. .. reg_ddrc_rd2wr = 0x7 + // .. .. ==> 0XF800601C[9:5] = 0x00000007U + // .. .. ==> MASK : 0x000003E0U VAL : 0x000000E0U + // .. .. reg_ddrc_wr2rd = 0xe + // .. .. ==> 0XF800601C[14:10] = 0x0000000EU + // .. .. ==> MASK : 0x00007C00U VAL : 0x00003800U + // .. .. reg_ddrc_t_xp = 0x4 + // .. .. ==> 0XF800601C[19:15] = 0x00000004U + // .. .. ==> MASK : 0x000F8000U VAL : 0x00020000U + // .. .. reg_ddrc_pad_pd = 0x0 + // .. .. ==> 0XF800601C[22:20] = 0x00000000U + // .. .. ==> MASK : 0x00700000U VAL : 0x00000000U + // .. .. reg_ddrc_rd2pre = 0x4 + // .. .. ==> 0XF800601C[27:23] = 0x00000004U + // .. .. ==> MASK : 0x0F800000U VAL : 0x02000000U + // .. .. reg_ddrc_t_rcd = 0x7 + // .. .. ==> 0XF800601C[31:28] = 0x00000007U + // .. .. ==> MASK : 0xF0000000U VAL : 0x70000000U + // .. .. + EMIT_MASKWRITE(0XF800601C, 0xFFFFFFFFU ,0x720238E5U), + // .. .. reg_ddrc_t_ccd = 0x4 + // .. .. ==> 0XF8006020[4:2] = 0x00000004U + // .. .. ==> MASK : 0x0000001CU VAL : 0x00000010U + // .. .. reg_ddrc_t_rrd = 0x6 + // .. .. ==> 0XF8006020[7:5] = 0x00000006U + // .. .. ==> MASK : 0x000000E0U VAL : 0x000000C0U + // .. .. reg_ddrc_refresh_margin = 0x2 + // .. .. ==> 0XF8006020[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. reg_ddrc_t_rp = 0x7 + // .. .. ==> 0XF8006020[15:12] = 0x00000007U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00007000U + // .. .. reg_ddrc_refresh_to_x32 = 0x8 + // .. .. ==> 0XF8006020[20:16] = 0x00000008U + // .. .. ==> MASK : 0x001F0000U VAL : 0x00080000U + // .. .. reg_ddrc_sdram = 0x1 + // .. .. ==> 0XF8006020[21:21] = 0x00000001U + // .. .. ==> MASK : 0x00200000U VAL : 0x00200000U + // .. .. reg_ddrc_mobile = 0x0 + // .. .. ==> 0XF8006020[22:22] = 0x00000000U + // .. .. ==> MASK : 0x00400000U VAL : 0x00000000U + // .. .. reg_ddrc_clock_stop_en = 0x0 + // .. .. ==> 0XF8006020[23:23] = 0x00000000U + // .. .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. .. reg_ddrc_read_latency = 0x7 + // .. .. ==> 0XF8006020[28:24] = 0x00000007U + // .. .. ==> MASK : 0x1F000000U VAL : 0x07000000U + // .. .. reg_phy_mode_ddr1_ddr2 = 0x1 + // .. .. ==> 0XF8006020[29:29] = 0x00000001U + // .. .. ==> MASK : 0x20000000U VAL : 0x20000000U + // .. .. reg_ddrc_dis_pad_pd = 0x0 + // .. .. ==> 0XF8006020[30:30] = 0x00000000U + // .. .. ==> MASK : 0x40000000U VAL : 0x00000000U + // .. .. reg_ddrc_loopback = 0x0 + // .. .. ==> 0XF8006020[31:31] = 0x00000000U + // .. .. ==> MASK : 0x80000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006020, 0xFFFFFFFCU ,0x272872D0U), + // .. .. reg_ddrc_en_2t_timing_mode = 0x0 + // .. .. ==> 0XF8006024[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_prefer_write = 0x0 + // .. .. ==> 0XF8006024[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_ddrc_max_rank_rd = 0xf + // .. .. ==> 0XF8006024[5:2] = 0x0000000FU + // .. .. ==> MASK : 0x0000003CU VAL : 0x0000003CU + // .. .. reg_ddrc_mr_wr = 0x0 + // .. .. ==> 0XF8006024[6:6] = 0x00000000U + // .. .. ==> MASK : 0x00000040U VAL : 0x00000000U + // .. .. reg_ddrc_mr_addr = 0x0 + // .. .. ==> 0XF8006024[8:7] = 0x00000000U + // .. .. ==> MASK : 0x00000180U VAL : 0x00000000U + // .. .. reg_ddrc_mr_data = 0x0 + // .. .. ==> 0XF8006024[24:9] = 0x00000000U + // .. .. ==> MASK : 0x01FFFE00U VAL : 0x00000000U + // .. .. ddrc_reg_mr_wr_busy = 0x0 + // .. .. ==> 0XF8006024[25:25] = 0x00000000U + // .. .. ==> MASK : 0x02000000U VAL : 0x00000000U + // .. .. reg_ddrc_mr_type = 0x0 + // .. .. ==> 0XF8006024[26:26] = 0x00000000U + // .. .. ==> MASK : 0x04000000U VAL : 0x00000000U + // .. .. reg_ddrc_mr_rdata_valid = 0x0 + // .. .. ==> 0XF8006024[27:27] = 0x00000000U + // .. .. ==> MASK : 0x08000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006024, 0x0FFFFFFFU ,0x0000003CU), + // .. .. reg_ddrc_final_wait_x32 = 0x7 + // .. .. ==> 0XF8006028[6:0] = 0x00000007U + // .. .. ==> MASK : 0x0000007FU VAL : 0x00000007U + // .. .. reg_ddrc_pre_ocd_x32 = 0x0 + // .. .. ==> 0XF8006028[10:7] = 0x00000000U + // .. .. ==> MASK : 0x00000780U VAL : 0x00000000U + // .. .. reg_ddrc_t_mrd = 0x4 + // .. .. ==> 0XF8006028[13:11] = 0x00000004U + // .. .. ==> MASK : 0x00003800U VAL : 0x00002000U + // .. .. + EMIT_MASKWRITE(0XF8006028, 0x00003FFFU ,0x00002007U), + // .. .. reg_ddrc_emr2 = 0x8 + // .. .. ==> 0XF800602C[15:0] = 0x00000008U + // .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000008U + // .. .. reg_ddrc_emr3 = 0x0 + // .. .. ==> 0XF800602C[31:16] = 0x00000000U + // .. .. ==> MASK : 0xFFFF0000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800602C, 0xFFFFFFFFU ,0x00000008U), + // .. .. reg_ddrc_mr = 0x930 + // .. .. ==> 0XF8006030[15:0] = 0x00000930U + // .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000930U + // .. .. reg_ddrc_emr = 0x4 + // .. .. ==> 0XF8006030[31:16] = 0x00000004U + // .. .. ==> MASK : 0xFFFF0000U VAL : 0x00040000U + // .. .. + EMIT_MASKWRITE(0XF8006030, 0xFFFFFFFFU ,0x00040930U), + // .. .. reg_ddrc_burst_rdwr = 0x4 + // .. .. ==> 0XF8006034[3:0] = 0x00000004U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000004U + // .. .. reg_ddrc_pre_cke_x1024 = 0x167 + // .. .. ==> 0XF8006034[13:4] = 0x00000167U + // .. .. ==> MASK : 0x00003FF0U VAL : 0x00001670U + // .. .. reg_ddrc_post_cke_x1024 = 0x1 + // .. .. ==> 0XF8006034[25:16] = 0x00000001U + // .. .. ==> MASK : 0x03FF0000U VAL : 0x00010000U + // .. .. reg_ddrc_burstchop = 0x0 + // .. .. ==> 0XF8006034[28:28] = 0x00000000U + // .. .. ==> MASK : 0x10000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006034, 0x13FF3FFFU ,0x00011674U), + // .. .. reg_ddrc_force_low_pri_n = 0x0 + // .. .. ==> 0XF8006038[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_dis_dq = 0x0 + // .. .. ==> 0XF8006038[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_debug_mode = 0x0 + // .. .. ==> 0XF8006038[6:6] = 0x00000000U + // .. .. ==> MASK : 0x00000040U VAL : 0x00000000U + // .. .. reg_phy_wr_level_start = 0x0 + // .. .. ==> 0XF8006038[7:7] = 0x00000000U + // .. .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. .. reg_phy_rd_level_start = 0x0 + // .. .. ==> 0XF8006038[8:8] = 0x00000000U + // .. .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. .. reg_phy_dq0_wait_t = 0x0 + // .. .. ==> 0XF8006038[12:9] = 0x00000000U + // .. .. ==> MASK : 0x00001E00U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006038, 0x00001FC3U ,0x00000000U), + // .. .. reg_ddrc_addrmap_bank_b0 = 0x6 + // .. .. ==> 0XF800603C[3:0] = 0x00000006U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000006U + // .. .. reg_ddrc_addrmap_bank_b1 = 0x6 + // .. .. ==> 0XF800603C[7:4] = 0x00000006U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000060U + // .. .. reg_ddrc_addrmap_bank_b2 = 0x6 + // .. .. ==> 0XF800603C[11:8] = 0x00000006U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000600U + // .. .. reg_ddrc_addrmap_col_b5 = 0x0 + // .. .. ==> 0XF800603C[15:12] = 0x00000000U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b6 = 0x0 + // .. .. ==> 0XF800603C[19:16] = 0x00000000U + // .. .. ==> MASK : 0x000F0000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800603C, 0x000FFFFFU ,0x00000666U), + // .. .. reg_ddrc_addrmap_col_b2 = 0x0 + // .. .. ==> 0XF8006040[3:0] = 0x00000000U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b3 = 0x0 + // .. .. ==> 0XF8006040[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b4 = 0x0 + // .. .. ==> 0XF8006040[11:8] = 0x00000000U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b7 = 0x0 + // .. .. ==> 0XF8006040[15:12] = 0x00000000U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b8 = 0xf + // .. .. ==> 0XF8006040[19:16] = 0x0000000FU + // .. .. ==> MASK : 0x000F0000U VAL : 0x000F0000U + // .. .. reg_ddrc_addrmap_col_b9 = 0xf + // .. .. ==> 0XF8006040[23:20] = 0x0000000FU + // .. .. ==> MASK : 0x00F00000U VAL : 0x00F00000U + // .. .. reg_ddrc_addrmap_col_b10 = 0xf + // .. .. ==> 0XF8006040[27:24] = 0x0000000FU + // .. .. ==> MASK : 0x0F000000U VAL : 0x0F000000U + // .. .. reg_ddrc_addrmap_col_b11 = 0xf + // .. .. ==> 0XF8006040[31:28] = 0x0000000FU + // .. .. ==> MASK : 0xF0000000U VAL : 0xF0000000U + // .. .. + EMIT_MASKWRITE(0XF8006040, 0xFFFFFFFFU ,0xFFFF0000U), + // .. .. reg_ddrc_addrmap_row_b0 = 0x5 + // .. .. ==> 0XF8006044[3:0] = 0x00000005U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000005U + // .. .. reg_ddrc_addrmap_row_b1 = 0x5 + // .. .. ==> 0XF8006044[7:4] = 0x00000005U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000050U + // .. .. reg_ddrc_addrmap_row_b2_11 = 0x5 + // .. .. ==> 0XF8006044[11:8] = 0x00000005U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000500U + // .. .. reg_ddrc_addrmap_row_b12 = 0x5 + // .. .. ==> 0XF8006044[15:12] = 0x00000005U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00005000U + // .. .. reg_ddrc_addrmap_row_b13 = 0x5 + // .. .. ==> 0XF8006044[19:16] = 0x00000005U + // .. .. ==> MASK : 0x000F0000U VAL : 0x00050000U + // .. .. reg_ddrc_addrmap_row_b14 = 0x5 + // .. .. ==> 0XF8006044[23:20] = 0x00000005U + // .. .. ==> MASK : 0x00F00000U VAL : 0x00500000U + // .. .. reg_ddrc_addrmap_row_b15 = 0xf + // .. .. ==> 0XF8006044[27:24] = 0x0000000FU + // .. .. ==> MASK : 0x0F000000U VAL : 0x0F000000U + // .. .. + EMIT_MASKWRITE(0XF8006044, 0x0FFFFFFFU ,0x0F555555U), + // .. .. reg_ddrc_rank0_rd_odt = 0x0 + // .. .. ==> 0XF8006048[2:0] = 0x00000000U + // .. .. ==> MASK : 0x00000007U VAL : 0x00000000U + // .. .. reg_ddrc_rank0_wr_odt = 0x1 + // .. .. ==> 0XF8006048[5:3] = 0x00000001U + // .. .. ==> MASK : 0x00000038U VAL : 0x00000008U + // .. .. reg_ddrc_rank1_rd_odt = 0x1 + // .. .. ==> 0XF8006048[8:6] = 0x00000001U + // .. .. ==> MASK : 0x000001C0U VAL : 0x00000040U + // .. .. reg_ddrc_rank1_wr_odt = 0x1 + // .. .. ==> 0XF8006048[11:9] = 0x00000001U + // .. .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. .. reg_phy_rd_local_odt = 0x0 + // .. .. ==> 0XF8006048[13:12] = 0x00000000U + // .. .. ==> MASK : 0x00003000U VAL : 0x00000000U + // .. .. reg_phy_wr_local_odt = 0x3 + // .. .. ==> 0XF8006048[15:14] = 0x00000003U + // .. .. ==> MASK : 0x0000C000U VAL : 0x0000C000U + // .. .. reg_phy_idle_local_odt = 0x3 + // .. .. ==> 0XF8006048[17:16] = 0x00000003U + // .. .. ==> MASK : 0x00030000U VAL : 0x00030000U + // .. .. reg_ddrc_rank2_rd_odt = 0x0 + // .. .. ==> 0XF8006048[20:18] = 0x00000000U + // .. .. ==> MASK : 0x001C0000U VAL : 0x00000000U + // .. .. reg_ddrc_rank2_wr_odt = 0x0 + // .. .. ==> 0XF8006048[23:21] = 0x00000000U + // .. .. ==> MASK : 0x00E00000U VAL : 0x00000000U + // .. .. reg_ddrc_rank3_rd_odt = 0x0 + // .. .. ==> 0XF8006048[26:24] = 0x00000000U + // .. .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. .. reg_ddrc_rank3_wr_odt = 0x0 + // .. .. ==> 0XF8006048[29:27] = 0x00000000U + // .. .. ==> MASK : 0x38000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006048, 0x3FFFFFFFU ,0x0003C248U), + // .. .. reg_phy_rd_cmd_to_data = 0x0 + // .. .. ==> 0XF8006050[3:0] = 0x00000000U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000000U + // .. .. reg_phy_wr_cmd_to_data = 0x0 + // .. .. ==> 0XF8006050[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. reg_phy_rdc_we_to_re_delay = 0x8 + // .. .. ==> 0XF8006050[11:8] = 0x00000008U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000800U + // .. .. reg_phy_rdc_fifo_rst_disable = 0x0 + // .. .. ==> 0XF8006050[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. reg_phy_use_fixed_re = 0x1 + // .. .. ==> 0XF8006050[16:16] = 0x00000001U + // .. .. ==> MASK : 0x00010000U VAL : 0x00010000U + // .. .. reg_phy_rdc_fifo_rst_err_cnt_clr = 0x0 + // .. .. ==> 0XF8006050[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_phy_dis_phy_ctrl_rstn = 0x0 + // .. .. ==> 0XF8006050[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_phy_clk_stall_level = 0x0 + // .. .. ==> 0XF8006050[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_num_of_dq0 = 0x7 + // .. .. ==> 0XF8006050[27:24] = 0x00000007U + // .. .. ==> MASK : 0x0F000000U VAL : 0x07000000U + // .. .. reg_phy_wrlvl_num_of_dq0 = 0x7 + // .. .. ==> 0XF8006050[31:28] = 0x00000007U + // .. .. ==> MASK : 0xF0000000U VAL : 0x70000000U + // .. .. + EMIT_MASKWRITE(0XF8006050, 0xFF0F8FFFU ,0x77010800U), + // .. .. reg_ddrc_dll_calib_to_min_x1024 = 0x1 + // .. .. ==> 0XF8006058[7:0] = 0x00000001U + // .. .. ==> MASK : 0x000000FFU VAL : 0x00000001U + // .. .. reg_ddrc_dll_calib_to_max_x1024 = 0x1 + // .. .. ==> 0XF8006058[15:8] = 0x00000001U + // .. .. ==> MASK : 0x0000FF00U VAL : 0x00000100U + // .. .. reg_ddrc_dis_dll_calib = 0x0 + // .. .. ==> 0XF8006058[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006058, 0x0001FFFFU ,0x00000101U), + // .. .. reg_ddrc_rd_odt_delay = 0x3 + // .. .. ==> 0XF800605C[3:0] = 0x00000003U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000003U + // .. .. reg_ddrc_wr_odt_delay = 0x0 + // .. .. ==> 0XF800605C[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. reg_ddrc_rd_odt_hold = 0x0 + // .. .. ==> 0XF800605C[11:8] = 0x00000000U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000000U + // .. .. reg_ddrc_wr_odt_hold = 0x5 + // .. .. ==> 0XF800605C[15:12] = 0x00000005U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00005000U + // .. .. + EMIT_MASKWRITE(0XF800605C, 0x0000FFFFU ,0x00005003U), + // .. .. reg_ddrc_pageclose = 0x0 + // .. .. ==> 0XF8006060[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_lpr_num_entries = 0x1f + // .. .. ==> 0XF8006060[6:1] = 0x0000001FU + // .. .. ==> MASK : 0x0000007EU VAL : 0x0000003EU + // .. .. reg_ddrc_auto_pre_en = 0x0 + // .. .. ==> 0XF8006060[7:7] = 0x00000000U + // .. .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. .. reg_ddrc_refresh_update_level = 0x0 + // .. .. ==> 0XF8006060[8:8] = 0x00000000U + // .. .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. .. reg_ddrc_dis_wc = 0x0 + // .. .. ==> 0XF8006060[9:9] = 0x00000000U + // .. .. ==> MASK : 0x00000200U VAL : 0x00000000U + // .. .. reg_ddrc_dis_collision_page_opt = 0x0 + // .. .. ==> 0XF8006060[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_ddrc_selfref_en = 0x0 + // .. .. ==> 0XF8006060[12:12] = 0x00000000U + // .. .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006060, 0x000017FFU ,0x0000003EU), + // .. .. reg_ddrc_go2critical_hysteresis = 0x0 + // .. .. ==> 0XF8006064[12:5] = 0x00000000U + // .. .. ==> MASK : 0x00001FE0U VAL : 0x00000000U + // .. .. reg_arb_go2critical_en = 0x1 + // .. .. ==> 0XF8006064[17:17] = 0x00000001U + // .. .. ==> MASK : 0x00020000U VAL : 0x00020000U + // .. .. + EMIT_MASKWRITE(0XF8006064, 0x00021FE0U ,0x00020000U), + // .. .. reg_ddrc_wrlvl_ww = 0x41 + // .. .. ==> 0XF8006068[7:0] = 0x00000041U + // .. .. ==> MASK : 0x000000FFU VAL : 0x00000041U + // .. .. reg_ddrc_rdlvl_rr = 0x41 + // .. .. ==> 0XF8006068[15:8] = 0x00000041U + // .. .. ==> MASK : 0x0000FF00U VAL : 0x00004100U + // .. .. reg_ddrc_dfi_t_wlmrd = 0x28 + // .. .. ==> 0XF8006068[25:16] = 0x00000028U + // .. .. ==> MASK : 0x03FF0000U VAL : 0x00280000U + // .. .. + EMIT_MASKWRITE(0XF8006068, 0x03FFFFFFU ,0x00284141U), + // .. .. dfi_t_ctrlupd_interval_min_x1024 = 0x10 + // .. .. ==> 0XF800606C[7:0] = 0x00000010U + // .. .. ==> MASK : 0x000000FFU VAL : 0x00000010U + // .. .. dfi_t_ctrlupd_interval_max_x1024 = 0x16 + // .. .. ==> 0XF800606C[15:8] = 0x00000016U + // .. .. ==> MASK : 0x0000FF00U VAL : 0x00001600U + // .. .. + EMIT_MASKWRITE(0XF800606C, 0x0000FFFFU ,0x00001610U), + // .. .. reg_ddrc_dfi_t_ctrl_delay = 0x1 + // .. .. ==> 0XF8006078[3:0] = 0x00000001U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000001U + // .. .. reg_ddrc_dfi_t_dram_clk_disable = 0x1 + // .. .. ==> 0XF8006078[7:4] = 0x00000001U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000010U + // .. .. reg_ddrc_dfi_t_dram_clk_enable = 0x1 + // .. .. ==> 0XF8006078[11:8] = 0x00000001U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000100U + // .. .. reg_ddrc_t_cksre = 0x6 + // .. .. ==> 0XF8006078[15:12] = 0x00000006U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00006000U + // .. .. reg_ddrc_t_cksrx = 0x6 + // .. .. ==> 0XF8006078[19:16] = 0x00000006U + // .. .. ==> MASK : 0x000F0000U VAL : 0x00060000U + // .. .. reg_ddrc_t_ckesr = 0x4 + // .. .. ==> 0XF8006078[25:20] = 0x00000004U + // .. .. ==> MASK : 0x03F00000U VAL : 0x00400000U + // .. .. + EMIT_MASKWRITE(0XF8006078, 0x03FFFFFFU ,0x00466111U), + // .. .. reg_ddrc_t_ckpde = 0x2 + // .. .. ==> 0XF800607C[3:0] = 0x00000002U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000002U + // .. .. reg_ddrc_t_ckpdx = 0x2 + // .. .. ==> 0XF800607C[7:4] = 0x00000002U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000020U + // .. .. reg_ddrc_t_ckdpde = 0x2 + // .. .. ==> 0XF800607C[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. reg_ddrc_t_ckdpdx = 0x2 + // .. .. ==> 0XF800607C[15:12] = 0x00000002U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00002000U + // .. .. reg_ddrc_t_ckcsx = 0x3 + // .. .. ==> 0XF800607C[19:16] = 0x00000003U + // .. .. ==> MASK : 0x000F0000U VAL : 0x00030000U + // .. .. + EMIT_MASKWRITE(0XF800607C, 0x000FFFFFU ,0x00032222U), + // .. .. refresh_timer0_start_value_x32 = 0x0 + // .. .. ==> 0XF80060A0[11:0] = 0x00000000U + // .. .. ==> MASK : 0x00000FFFU VAL : 0x00000000U + // .. .. refresh_timer1_start_value_x32 = 0x8 + // .. .. ==> 0XF80060A0[23:12] = 0x00000008U + // .. .. ==> MASK : 0x00FFF000U VAL : 0x00008000U + // .. .. + EMIT_MASKWRITE(0XF80060A0, 0x00FFFFFFU ,0x00008000U), + // .. .. reg_ddrc_dis_auto_zq = 0x0 + // .. .. ==> 0XF80060A4[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_ddr3 = 0x1 + // .. .. ==> 0XF80060A4[1:1] = 0x00000001U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. reg_ddrc_t_mod = 0x200 + // .. .. ==> 0XF80060A4[11:2] = 0x00000200U + // .. .. ==> MASK : 0x00000FFCU VAL : 0x00000800U + // .. .. reg_ddrc_t_zq_long_nop = 0x200 + // .. .. ==> 0XF80060A4[21:12] = 0x00000200U + // .. .. ==> MASK : 0x003FF000U VAL : 0x00200000U + // .. .. reg_ddrc_t_zq_short_nop = 0x40 + // .. .. ==> 0XF80060A4[31:22] = 0x00000040U + // .. .. ==> MASK : 0xFFC00000U VAL : 0x10000000U + // .. .. + EMIT_MASKWRITE(0XF80060A4, 0xFFFFFFFFU ,0x10200802U), + // .. .. t_zq_short_interval_x1024 = 0xc845 + // .. .. ==> 0XF80060A8[19:0] = 0x0000C845U + // .. .. ==> MASK : 0x000FFFFFU VAL : 0x0000C845U + // .. .. dram_rstn_x1024 = 0x67 + // .. .. ==> 0XF80060A8[27:20] = 0x00000067U + // .. .. ==> MASK : 0x0FF00000U VAL : 0x06700000U + // .. .. + EMIT_MASKWRITE(0XF80060A8, 0x0FFFFFFFU ,0x0670C845U), + // .. .. deeppowerdown_en = 0x0 + // .. .. ==> 0XF80060AC[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. deeppowerdown_to_x1024 = 0xff + // .. .. ==> 0XF80060AC[8:1] = 0x000000FFU + // .. .. ==> MASK : 0x000001FEU VAL : 0x000001FEU + // .. .. + EMIT_MASKWRITE(0XF80060AC, 0x000001FFU ,0x000001FEU), + // .. .. dfi_wrlvl_max_x1024 = 0xfff + // .. .. ==> 0XF80060B0[11:0] = 0x00000FFFU + // .. .. ==> MASK : 0x00000FFFU VAL : 0x00000FFFU + // .. .. dfi_rdlvl_max_x1024 = 0xfff + // .. .. ==> 0XF80060B0[23:12] = 0x00000FFFU + // .. .. ==> MASK : 0x00FFF000U VAL : 0x00FFF000U + // .. .. ddrc_reg_twrlvl_max_error = 0x0 + // .. .. ==> 0XF80060B0[24:24] = 0x00000000U + // .. .. ==> MASK : 0x01000000U VAL : 0x00000000U + // .. .. ddrc_reg_trdlvl_max_error = 0x0 + // .. .. ==> 0XF80060B0[25:25] = 0x00000000U + // .. .. ==> MASK : 0x02000000U VAL : 0x00000000U + // .. .. reg_ddrc_dfi_wr_level_en = 0x1 + // .. .. ==> 0XF80060B0[26:26] = 0x00000001U + // .. .. ==> MASK : 0x04000000U VAL : 0x04000000U + // .. .. reg_ddrc_dfi_rd_dqs_gate_level = 0x1 + // .. .. ==> 0XF80060B0[27:27] = 0x00000001U + // .. .. ==> MASK : 0x08000000U VAL : 0x08000000U + // .. .. reg_ddrc_dfi_rd_data_eye_train = 0x1 + // .. .. ==> 0XF80060B0[28:28] = 0x00000001U + // .. .. ==> MASK : 0x10000000U VAL : 0x10000000U + // .. .. + EMIT_MASKWRITE(0XF80060B0, 0x1FFFFFFFU ,0x1CFFFFFFU), + // .. .. reg_ddrc_2t_delay = 0x0 + // .. .. ==> 0XF80060B4[8:0] = 0x00000000U + // .. .. ==> MASK : 0x000001FFU VAL : 0x00000000U + // .. .. reg_ddrc_skip_ocd = 0x1 + // .. .. ==> 0XF80060B4[9:9] = 0x00000001U + // .. .. ==> MASK : 0x00000200U VAL : 0x00000200U + // .. .. reg_ddrc_dis_pre_bypass = 0x0 + // .. .. ==> 0XF80060B4[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060B4, 0x000007FFU ,0x00000200U), + // .. .. reg_ddrc_dfi_t_rddata_en = 0x6 + // .. .. ==> 0XF80060B8[4:0] = 0x00000006U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000006U + // .. .. reg_ddrc_dfi_t_ctrlup_min = 0x3 + // .. .. ==> 0XF80060B8[14:5] = 0x00000003U + // .. .. ==> MASK : 0x00007FE0U VAL : 0x00000060U + // .. .. reg_ddrc_dfi_t_ctrlup_max = 0x40 + // .. .. ==> 0XF80060B8[24:15] = 0x00000040U + // .. .. ==> MASK : 0x01FF8000U VAL : 0x00200000U + // .. .. + EMIT_MASKWRITE(0XF80060B8, 0x01FFFFFFU ,0x00200066U), + // .. .. Clear_Uncorrectable_DRAM_ECC_error = 0x0 + // .. .. ==> 0XF80060C4[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. Clear_Correctable_DRAM_ECC_error = 0x0 + // .. .. ==> 0XF80060C4[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060C4, 0x00000003U ,0x00000000U), + // .. .. CORR_ECC_LOG_VALID = 0x0 + // .. .. ==> 0XF80060C8[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. ECC_CORRECTED_BIT_NUM = 0x0 + // .. .. ==> 0XF80060C8[7:1] = 0x00000000U + // .. .. ==> MASK : 0x000000FEU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060C8, 0x000000FFU ,0x00000000U), + // .. .. UNCORR_ECC_LOG_VALID = 0x0 + // .. .. ==> 0XF80060DC[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060DC, 0x00000001U ,0x00000000U), + // .. .. STAT_NUM_CORR_ERR = 0x0 + // .. .. ==> 0XF80060F0[15:8] = 0x00000000U + // .. .. ==> MASK : 0x0000FF00U VAL : 0x00000000U + // .. .. STAT_NUM_UNCORR_ERR = 0x0 + // .. .. ==> 0XF80060F0[7:0] = 0x00000000U + // .. .. ==> MASK : 0x000000FFU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060F0, 0x0000FFFFU ,0x00000000U), + // .. .. reg_ddrc_ecc_mode = 0x0 + // .. .. ==> 0XF80060F4[2:0] = 0x00000000U + // .. .. ==> MASK : 0x00000007U VAL : 0x00000000U + // .. .. reg_ddrc_dis_scrub = 0x1 + // .. .. ==> 0XF80060F4[3:3] = 0x00000001U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000008U + // .. .. + EMIT_MASKWRITE(0XF80060F4, 0x0000000FU ,0x00000008U), + // .. .. reg_phy_dif_on = 0x0 + // .. .. ==> 0XF8006114[3:0] = 0x00000000U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000000U + // .. .. reg_phy_dif_off = 0x0 + // .. .. ==> 0XF8006114[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006114, 0x000000FFU ,0x00000000U), + // .. .. reg_phy_data_slice_in_use = 0x1 + // .. .. ==> 0XF8006118[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006118[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF8006118[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006118[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_tx = 0x0 + // .. .. ==> 0XF8006118[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_rx = 0x0 + // .. .. ==> 0XF8006118[5:5] = 0x00000000U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF8006118[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF8006118[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF8006118[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006118, 0x7FFFFFFFU ,0x40000001U), + // .. .. reg_phy_data_slice_in_use = 0x1 + // .. .. ==> 0XF800611C[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF800611C[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF800611C[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF800611C[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_tx = 0x0 + // .. .. ==> 0XF800611C[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_rx = 0x0 + // .. .. ==> 0XF800611C[5:5] = 0x00000000U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF800611C[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF800611C[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF800611C[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF800611C, 0x7FFFFFFFU ,0x40000001U), + // .. .. reg_phy_data_slice_in_use = 0x0 + // .. .. ==> 0XF8006120[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_tx = 0x0 + // .. .. ==> 0XF8006120[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_rx = 0x0 + // .. .. ==> 0XF8006120[5:5] = 0x00000000U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF8006120[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF8006120[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF8006120[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. reg_phy_data_slice_in_use = 0x0 + // .. .. ==> 0XF8006120[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_tx = 0x0 + // .. .. ==> 0XF8006120[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_rx = 0x0 + // .. .. ==> 0XF8006120[5:5] = 0x00000000U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF8006120[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF8006120[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF8006120[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006120, 0x7FFFFFFFU ,0x40000000U), + // .. .. reg_phy_data_slice_in_use = 0x0 + // .. .. ==> 0XF8006124[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006124[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF8006124[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006124[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_tx = 0x0 + // .. .. ==> 0XF8006124[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_rx = 0x0 + // .. .. ==> 0XF8006124[5:5] = 0x00000000U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF8006124[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF8006124[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF8006124[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006124, 0x7FFFFFFFU ,0x40000000U), + // .. .. reg_phy_wrlvl_init_ratio = 0x5 + // .. .. ==> 0XF800612C[9:0] = 0x00000005U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000005U + // .. .. reg_phy_gatelvl_init_ratio = 0x9b + // .. .. ==> 0XF800612C[19:10] = 0x0000009BU + // .. .. ==> MASK : 0x000FFC00U VAL : 0x00026C00U + // .. .. + EMIT_MASKWRITE(0XF800612C, 0x000FFFFFU ,0x00026C05U), + // .. .. reg_phy_wrlvl_init_ratio = 0x7 + // .. .. ==> 0XF8006130[9:0] = 0x00000007U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000007U + // .. .. reg_phy_gatelvl_init_ratio = 0x98 + // .. .. ==> 0XF8006130[19:10] = 0x00000098U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x00026000U + // .. .. + EMIT_MASKWRITE(0XF8006130, 0x000FFFFFU ,0x00026007U), + // .. .. reg_phy_wrlvl_init_ratio = 0x0 + // .. .. ==> 0XF8006134[9:0] = 0x00000000U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000000U + // .. .. reg_phy_gatelvl_init_ratio = 0x76 + // .. .. ==> 0XF8006134[19:10] = 0x00000076U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x0001D800U + // .. .. + EMIT_MASKWRITE(0XF8006134, 0x000FFFFFU ,0x0001D800U), + // .. .. reg_phy_wrlvl_init_ratio = 0x0 + // .. .. ==> 0XF8006138[9:0] = 0x00000000U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000000U + // .. .. reg_phy_gatelvl_init_ratio = 0x78 + // .. .. ==> 0XF8006138[19:10] = 0x00000078U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x0001E000U + // .. .. + EMIT_MASKWRITE(0XF8006138, 0x000FFFFFU ,0x0001E000U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF8006140[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006140[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006140[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006140, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF8006144[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006144[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006144[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006144, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF8006148[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006148[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006148[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006148, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF800614C[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF800614C[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF800614C[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800614C, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x85 + // .. .. ==> 0XF8006154[9:0] = 0x00000085U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000085U + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006154[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006154[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006154, 0x000FFFFFU ,0x00000085U), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x87 + // .. .. ==> 0XF8006158[9:0] = 0x00000087U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000087U + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006158[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006158[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006158, 0x000FFFFFU ,0x00000087U), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x7f + // .. .. ==> 0XF800615C[9:0] = 0x0000007FU + // .. .. ==> MASK : 0x000003FFU VAL : 0x0000007FU + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF800615C[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF800615C[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800615C, 0x000FFFFFU ,0x0000007FU), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x7c + // .. .. ==> 0XF8006160[9:0] = 0x0000007CU + // .. .. ==> MASK : 0x000003FFU VAL : 0x0000007CU + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006160[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006160[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006160, 0x000FFFFFU ,0x0000007CU), + // .. .. reg_phy_fifo_we_slave_ratio = 0xf0 + // .. .. ==> 0XF8006168[10:0] = 0x000000F0U + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000F0U + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF8006168[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF8006168[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006168, 0x001FFFFFU ,0x000000F0U), + // .. .. reg_phy_fifo_we_slave_ratio = 0xed + // .. .. ==> 0XF800616C[10:0] = 0x000000EDU + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000EDU + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF800616C[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF800616C[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800616C, 0x001FFFFFU ,0x000000EDU), + // .. .. reg_phy_fifo_we_slave_ratio = 0xcb + // .. .. ==> 0XF8006170[10:0] = 0x000000CBU + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000CBU + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF8006170[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF8006170[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006170, 0x001FFFFFU ,0x000000CBU), + // .. .. reg_phy_fifo_we_slave_ratio = 0xcd + // .. .. ==> 0XF8006174[10:0] = 0x000000CDU + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000CDU + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF8006174[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF8006174[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006174, 0x001FFFFFU ,0x000000CDU), + // .. .. reg_phy_wr_data_slave_ratio = 0xc5 + // .. .. ==> 0XF800617C[9:0] = 0x000000C5U + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000C5U + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF800617C[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF800617C[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800617C, 0x000FFFFFU ,0x000000C5U), + // .. .. reg_phy_wr_data_slave_ratio = 0xc7 + // .. .. ==> 0XF8006180[9:0] = 0x000000C7U + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000C7U + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF8006180[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF8006180[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006180, 0x000FFFFFU ,0x000000C7U), + // .. .. reg_phy_wr_data_slave_ratio = 0xbf + // .. .. ==> 0XF8006184[9:0] = 0x000000BFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000BFU + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF8006184[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF8006184[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006184, 0x000FFFFFU ,0x000000BFU), + // .. .. reg_phy_wr_data_slave_ratio = 0xbc + // .. .. ==> 0XF8006188[9:0] = 0x000000BCU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000BCU + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF8006188[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF8006188[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006188, 0x000FFFFFU ,0x000000BCU), + // .. .. reg_phy_loopback = 0x0 + // .. .. ==> 0XF8006190[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_phy_bl2 = 0x0 + // .. .. ==> 0XF8006190[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_at_spd_atpg = 0x0 + // .. .. ==> 0XF8006190[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_bist_enable = 0x0 + // .. .. ==> 0XF8006190[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_bist_force_err = 0x0 + // .. .. ==> 0XF8006190[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_bist_mode = 0x0 + // .. .. ==> 0XF8006190[6:5] = 0x00000000U + // .. .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. .. reg_phy_invert_clkout = 0x1 + // .. .. ==> 0XF8006190[7:7] = 0x00000001U + // .. .. ==> MASK : 0x00000080U VAL : 0x00000080U + // .. .. reg_phy_all_dq_mpr_rd_resp = 0x0 + // .. .. ==> 0XF8006190[8:8] = 0x00000000U + // .. .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. .. reg_phy_sel_logic = 0x0 + // .. .. ==> 0XF8006190[9:9] = 0x00000000U + // .. .. ==> MASK : 0x00000200U VAL : 0x00000000U + // .. .. reg_phy_ctrl_slave_ratio = 0x100 + // .. .. ==> 0XF8006190[19:10] = 0x00000100U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x00040000U + // .. .. reg_phy_ctrl_slave_force = 0x0 + // .. .. ==> 0XF8006190[20:20] = 0x00000000U + // .. .. ==> MASK : 0x00100000U VAL : 0x00000000U + // .. .. reg_phy_ctrl_slave_delay = 0x0 + // .. .. ==> 0XF8006190[27:21] = 0x00000000U + // .. .. ==> MASK : 0x0FE00000U VAL : 0x00000000U + // .. .. reg_phy_use_rank0_delays = 0x1 + // .. .. ==> 0XF8006190[28:28] = 0x00000001U + // .. .. ==> MASK : 0x10000000U VAL : 0x10000000U + // .. .. reg_phy_lpddr = 0x0 + // .. .. ==> 0XF8006190[29:29] = 0x00000000U + // .. .. ==> MASK : 0x20000000U VAL : 0x00000000U + // .. .. reg_phy_cmd_latency = 0x0 + // .. .. ==> 0XF8006190[30:30] = 0x00000000U + // .. .. ==> MASK : 0x40000000U VAL : 0x00000000U + // .. .. reg_phy_int_lpbk = 0x0 + // .. .. ==> 0XF8006190[31:31] = 0x00000000U + // .. .. ==> MASK : 0x80000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006190, 0xFFFFFFFFU ,0x10040080U), + // .. .. reg_phy_wr_rl_delay = 0x2 + // .. .. ==> 0XF8006194[4:0] = 0x00000002U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000002U + // .. .. reg_phy_rd_rl_delay = 0x4 + // .. .. ==> 0XF8006194[9:5] = 0x00000004U + // .. .. ==> MASK : 0x000003E0U VAL : 0x00000080U + // .. .. reg_phy_dll_lock_diff = 0xf + // .. .. ==> 0XF8006194[13:10] = 0x0000000FU + // .. .. ==> MASK : 0x00003C00U VAL : 0x00003C00U + // .. .. reg_phy_use_wr_level = 0x1 + // .. .. ==> 0XF8006194[14:14] = 0x00000001U + // .. .. ==> MASK : 0x00004000U VAL : 0x00004000U + // .. .. reg_phy_use_rd_dqs_gate_level = 0x1 + // .. .. ==> 0XF8006194[15:15] = 0x00000001U + // .. .. ==> MASK : 0x00008000U VAL : 0x00008000U + // .. .. reg_phy_use_rd_data_eye_level = 0x1 + // .. .. ==> 0XF8006194[16:16] = 0x00000001U + // .. .. ==> MASK : 0x00010000U VAL : 0x00010000U + // .. .. reg_phy_dis_calib_rst = 0x0 + // .. .. ==> 0XF8006194[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_phy_ctrl_slave_delay = 0x0 + // .. .. ==> 0XF8006194[19:18] = 0x00000000U + // .. .. ==> MASK : 0x000C0000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006194, 0x000FFFFFU ,0x0001FC82U), + // .. .. reg_arb_page_addr_mask = 0x0 + // .. .. ==> 0XF8006204[31:0] = 0x00000000U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006204, 0xFFFFFFFFU ,0x00000000U), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF8006208[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF8006208[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF8006208[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF8006208[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_dis_rmw_portn = 0x1 + // .. .. ==> 0XF8006208[19:19] = 0x00000001U + // .. .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. .. + EMIT_MASKWRITE(0XF8006208, 0x000F03FFU ,0x000803FFU), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF800620C[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF800620C[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF800620C[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF800620C[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_dis_rmw_portn = 0x1 + // .. .. ==> 0XF800620C[19:19] = 0x00000001U + // .. .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. .. + EMIT_MASKWRITE(0XF800620C, 0x000F03FFU ,0x000803FFU), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF8006210[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF8006210[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF8006210[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF8006210[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_dis_rmw_portn = 0x1 + // .. .. ==> 0XF8006210[19:19] = 0x00000001U + // .. .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. .. + EMIT_MASKWRITE(0XF8006210, 0x000F03FFU ,0x000803FFU), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF8006214[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF8006214[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF8006214[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF8006214[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_dis_rmw_portn = 0x1 + // .. .. ==> 0XF8006214[19:19] = 0x00000001U + // .. .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. .. + EMIT_MASKWRITE(0XF8006214, 0x000F03FFU ,0x000803FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF8006218[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF8006218[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF8006218[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF8006218[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF8006218[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006218, 0x000F03FFU ,0x000003FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF800621C[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF800621C[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF800621C[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF800621C[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF800621C[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800621C, 0x000F03FFU ,0x000003FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF8006220[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF8006220[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF8006220[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF8006220[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF8006220[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006220, 0x000F03FFU ,0x000003FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF8006224[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF8006224[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF8006224[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF8006224[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF8006224[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006224, 0x000F03FFU ,0x000003FFU), + // .. .. reg_ddrc_lpddr2 = 0x0 + // .. .. ==> 0XF80062A8[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_per_bank_refresh = 0x0 + // .. .. ==> 0XF80062A8[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_ddrc_derate_enable = 0x0 + // .. .. ==> 0XF80062A8[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_ddrc_mr4_margin = 0x0 + // .. .. ==> 0XF80062A8[11:4] = 0x00000000U + // .. .. ==> MASK : 0x00000FF0U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80062A8, 0x00000FF7U ,0x00000000U), + // .. .. reg_ddrc_mr4_read_interval = 0x0 + // .. .. ==> 0XF80062AC[31:0] = 0x00000000U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80062AC, 0xFFFFFFFFU ,0x00000000U), + // .. .. reg_ddrc_min_stable_clock_x1 = 0x5 + // .. .. ==> 0XF80062B0[3:0] = 0x00000005U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000005U + // .. .. reg_ddrc_idle_after_reset_x32 = 0x12 + // .. .. ==> 0XF80062B0[11:4] = 0x00000012U + // .. .. ==> MASK : 0x00000FF0U VAL : 0x00000120U + // .. .. reg_ddrc_t_mrw = 0x5 + // .. .. ==> 0XF80062B0[21:12] = 0x00000005U + // .. .. ==> MASK : 0x003FF000U VAL : 0x00005000U + // .. .. + EMIT_MASKWRITE(0XF80062B0, 0x003FFFFFU ,0x00005125U), + // .. .. reg_ddrc_max_auto_init_x1024 = 0xa6 + // .. .. ==> 0XF80062B4[7:0] = 0x000000A6U + // .. .. ==> MASK : 0x000000FFU VAL : 0x000000A6U + // .. .. reg_ddrc_dev_zqinit_x32 = 0x12 + // .. .. ==> 0XF80062B4[17:8] = 0x00000012U + // .. .. ==> MASK : 0x0003FF00U VAL : 0x00001200U + // .. .. + EMIT_MASKWRITE(0XF80062B4, 0x0003FFFFU ,0x000012A6U), + // .. .. START: POLL ON DCI STATUS + // .. .. DONE = 1 + // .. .. ==> 0XF8000B74[13:13] = 0x00000001U + // .. .. ==> MASK : 0x00002000U VAL : 0x00002000U + // .. .. + EMIT_MASKPOLL(0XF8000B74, 0x00002000U), + // .. .. FINISH: POLL ON DCI STATUS + // .. .. START: UNLOCK DDR + // .. .. reg_ddrc_soft_rstb = 0x1 + // .. .. ==> 0XF8006000[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. reg_ddrc_powerdown_en = 0x0 + // .. .. ==> 0XF8006000[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_ddrc_data_bus_width = 0x1 + // .. .. ==> 0XF8006000[3:2] = 0x00000001U + // .. .. ==> MASK : 0x0000000CU VAL : 0x00000004U + // .. .. reg_ddrc_burst8_refresh = 0x0 + // .. .. ==> 0XF8006000[6:4] = 0x00000000U + // .. .. ==> MASK : 0x00000070U VAL : 0x00000000U + // .. .. reg_ddrc_rdwr_idle_gap = 1 + // .. .. ==> 0XF8006000[13:7] = 0x00000001U + // .. .. ==> MASK : 0x00003F80U VAL : 0x00000080U + // .. .. reg_ddrc_dis_rd_bypass = 0x0 + // .. .. ==> 0XF8006000[14:14] = 0x00000000U + // .. .. ==> MASK : 0x00004000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_act_bypass = 0x0 + // .. .. ==> 0XF8006000[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_auto_refresh = 0x0 + // .. .. ==> 0XF8006000[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006000, 0x0001FFFFU ,0x00000085U), + // .. .. FINISH: UNLOCK DDR + // .. .. START: CHECK DDR STATUS + // .. .. ddrc_reg_operating_mode = 1 + // .. .. ==> 0XF8006054[2:0] = 0x00000001U + // .. .. ==> MASK : 0x00000007U VAL : 0x00000001U + // .. .. + EMIT_MASKPOLL(0XF8006054, 0x00000007U), + // .. .. FINISH: CHECK DDR STATUS + // .. FINISH: DDR INITIALIZATION + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_mio_init_data_2_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: OCM REMAPPING + // .. FINISH: OCM REMAPPING + // .. START: DDRIOB SETTINGS + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B40[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B40[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B40[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B40[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCR_TYPE = 0x0 + // .. ==> 0XF8000B40[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B40[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B40[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B40[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B40[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B40, 0x00000FFFU ,0x00000600U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B44[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B44[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B44[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B44[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCR_TYPE = 0x0 + // .. ==> 0XF8000B44[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B44[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B44[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B44[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B44[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B44, 0x00000FFFU ,0x00000600U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B48[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x1 + // .. ==> 0XF8000B48[2:1] = 0x00000001U + // .. ==> MASK : 0x00000006U VAL : 0x00000002U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B48[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x1 + // .. ==> 0XF8000B48[4:4] = 0x00000001U + // .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. DCR_TYPE = 0x3 + // .. ==> 0XF8000B48[6:5] = 0x00000003U + // .. ==> MASK : 0x00000060U VAL : 0x00000060U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B48[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B48[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B48[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B48[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B48, 0x00000FFFU ,0x00000672U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B4C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B4C[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B4C[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B4C[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCR_TYPE = 0x0 + // .. ==> 0XF8000B4C[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B4C[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B4C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x0 + // .. ==> 0XF8000B4C[10:9] = 0x00000000U + // .. ==> MASK : 0x00000600U VAL : 0x00000000U + // .. PULLUP_EN = 0x1 + // .. ==> 0XF8000B4C[11:11] = 0x00000001U + // .. ==> MASK : 0x00000800U VAL : 0x00000800U + // .. + EMIT_MASKWRITE(0XF8000B4C, 0x00000FFFU ,0x00000800U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B50[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x2 + // .. ==> 0XF8000B50[2:1] = 0x00000002U + // .. ==> MASK : 0x00000006U VAL : 0x00000004U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B50[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x1 + // .. ==> 0XF8000B50[4:4] = 0x00000001U + // .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. DCR_TYPE = 0x3 + // .. ==> 0XF8000B50[6:5] = 0x00000003U + // .. ==> MASK : 0x00000060U VAL : 0x00000060U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B50[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B50[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B50[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B50[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B50, 0x00000FFFU ,0x00000674U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B54[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B54[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B54[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B54[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCR_TYPE = 0x0 + // .. ==> 0XF8000B54[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B54[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B54[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x0 + // .. ==> 0XF8000B54[10:9] = 0x00000000U + // .. ==> MASK : 0x00000600U VAL : 0x00000000U + // .. PULLUP_EN = 0x1 + // .. ==> 0XF8000B54[11:11] = 0x00000001U + // .. ==> MASK : 0x00000800U VAL : 0x00000800U + // .. + EMIT_MASKWRITE(0XF8000B54, 0x00000FFFU ,0x00000800U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B58[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B58[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B58[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B58[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCR_TYPE = 0x0 + // .. ==> 0XF8000B58[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B58[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B58[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B58[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B58[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B58, 0x00000FFFU ,0x00000600U), + // .. DRIVE_P = 0x1c + // .. ==> 0XF8000B5C[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. DRIVE_N = 0xc + // .. ==> 0XF8000B5C[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. SLEW_P = 0x3 + // .. ==> 0XF8000B5C[18:14] = 0x00000003U + // .. ==> MASK : 0x0007C000U VAL : 0x0000C000U + // .. SLEW_N = 0x3 + // .. ==> 0XF8000B5C[23:19] = 0x00000003U + // .. ==> MASK : 0x00F80000U VAL : 0x00180000U + // .. GTL = 0x0 + // .. ==> 0XF8000B5C[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. RTERM = 0x0 + // .. ==> 0XF8000B5C[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B5C, 0xFFFFFFFFU ,0x0018C61CU), + // .. DRIVE_P = 0x1c + // .. ==> 0XF8000B60[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. DRIVE_N = 0xc + // .. ==> 0XF8000B60[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. SLEW_P = 0x6 + // .. ==> 0XF8000B60[18:14] = 0x00000006U + // .. ==> MASK : 0x0007C000U VAL : 0x00018000U + // .. SLEW_N = 0x1f + // .. ==> 0XF8000B60[23:19] = 0x0000001FU + // .. ==> MASK : 0x00F80000U VAL : 0x00F80000U + // .. GTL = 0x0 + // .. ==> 0XF8000B60[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. RTERM = 0x0 + // .. ==> 0XF8000B60[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B60, 0xFFFFFFFFU ,0x00F9861CU), + // .. DRIVE_P = 0x1c + // .. ==> 0XF8000B64[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. DRIVE_N = 0xc + // .. ==> 0XF8000B64[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. SLEW_P = 0x6 + // .. ==> 0XF8000B64[18:14] = 0x00000006U + // .. ==> MASK : 0x0007C000U VAL : 0x00018000U + // .. SLEW_N = 0x1f + // .. ==> 0XF8000B64[23:19] = 0x0000001FU + // .. ==> MASK : 0x00F80000U VAL : 0x00F80000U + // .. GTL = 0x0 + // .. ==> 0XF8000B64[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. RTERM = 0x0 + // .. ==> 0XF8000B64[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B64, 0xFFFFFFFFU ,0x00F9861CU), + // .. DRIVE_P = 0x1c + // .. ==> 0XF8000B68[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. DRIVE_N = 0xc + // .. ==> 0XF8000B68[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. SLEW_P = 0x6 + // .. ==> 0XF8000B68[18:14] = 0x00000006U + // .. ==> MASK : 0x0007C000U VAL : 0x00018000U + // .. SLEW_N = 0x1f + // .. ==> 0XF8000B68[23:19] = 0x0000001FU + // .. ==> MASK : 0x00F80000U VAL : 0x00F80000U + // .. GTL = 0x0 + // .. ==> 0XF8000B68[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. RTERM = 0x0 + // .. ==> 0XF8000B68[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B68, 0xFFFFFFFFU ,0x00F9861CU), + // .. VREF_INT_EN = 0x0 + // .. ==> 0XF8000B6C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. VREF_SEL = 0x0 + // .. ==> 0XF8000B6C[4:1] = 0x00000000U + // .. ==> MASK : 0x0000001EU VAL : 0x00000000U + // .. VREF_EXT_EN = 0x1 + // .. ==> 0XF8000B6C[6:5] = 0x00000001U + // .. ==> MASK : 0x00000060U VAL : 0x00000020U + // .. VREF_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[8:7] = 0x00000000U + // .. ==> MASK : 0x00000180U VAL : 0x00000000U + // .. REFIO_EN = 0x1 + // .. ==> 0XF8000B6C[9:9] = 0x00000001U + // .. ==> MASK : 0x00000200U VAL : 0x00000200U + // .. REFIO_TEST = 0x0 + // .. ==> 0XF8000B6C[11:10] = 0x00000000U + // .. ==> MASK : 0x00000C00U VAL : 0x00000000U + // .. REFIO_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DRST_B_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. CKE_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[14:14] = 0x00000000U + // .. ==> MASK : 0x00004000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B6C, 0x00007FFFU ,0x00000220U), + // .. .. START: ASSERT RESET + // .. .. RESET = 1 + // .. .. ==> 0XF8000B70[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. VRN_OUT = 0x1 + // .. .. ==> 0XF8000B70[5:5] = 0x00000001U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000020U + // .. .. + EMIT_MASKWRITE(0XF8000B70, 0x00000021U ,0x00000021U), + // .. .. FINISH: ASSERT RESET + // .. .. START: DEASSERT RESET + // .. .. RESET = 0 + // .. .. ==> 0XF8000B70[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. VRN_OUT = 0x1 + // .. .. ==> 0XF8000B70[5:5] = 0x00000001U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000020U + // .. .. + EMIT_MASKWRITE(0XF8000B70, 0x00000021U ,0x00000020U), + // .. .. FINISH: DEASSERT RESET + // .. .. RESET = 0x1 + // .. .. ==> 0XF8000B70[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. ENABLE = 0x1 + // .. .. ==> 0XF8000B70[1:1] = 0x00000001U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. VRP_TRI = 0x0 + // .. .. ==> 0XF8000B70[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. VRN_TRI = 0x0 + // .. .. ==> 0XF8000B70[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. VRP_OUT = 0x0 + // .. .. ==> 0XF8000B70[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. VRN_OUT = 0x1 + // .. .. ==> 0XF8000B70[5:5] = 0x00000001U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000020U + // .. .. NREF_OPT1 = 0x0 + // .. .. ==> 0XF8000B70[7:6] = 0x00000000U + // .. .. ==> MASK : 0x000000C0U VAL : 0x00000000U + // .. .. NREF_OPT2 = 0x0 + // .. .. ==> 0XF8000B70[10:8] = 0x00000000U + // .. .. ==> MASK : 0x00000700U VAL : 0x00000000U + // .. .. NREF_OPT4 = 0x1 + // .. .. ==> 0XF8000B70[13:11] = 0x00000001U + // .. .. ==> MASK : 0x00003800U VAL : 0x00000800U + // .. .. PREF_OPT1 = 0x0 + // .. .. ==> 0XF8000B70[16:14] = 0x00000000U + // .. .. ==> MASK : 0x0001C000U VAL : 0x00000000U + // .. .. PREF_OPT2 = 0x0 + // .. .. ==> 0XF8000B70[19:17] = 0x00000000U + // .. .. ==> MASK : 0x000E0000U VAL : 0x00000000U + // .. .. UPDATE_CONTROL = 0x0 + // .. .. ==> 0XF8000B70[20:20] = 0x00000000U + // .. .. ==> MASK : 0x00100000U VAL : 0x00000000U + // .. .. INIT_COMPLETE = 0x0 + // .. .. ==> 0XF8000B70[21:21] = 0x00000000U + // .. .. ==> MASK : 0x00200000U VAL : 0x00000000U + // .. .. TST_CLK = 0x0 + // .. .. ==> 0XF8000B70[22:22] = 0x00000000U + // .. .. ==> MASK : 0x00400000U VAL : 0x00000000U + // .. .. TST_HLN = 0x0 + // .. .. ==> 0XF8000B70[23:23] = 0x00000000U + // .. .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. .. TST_HLP = 0x0 + // .. .. ==> 0XF8000B70[24:24] = 0x00000000U + // .. .. ==> MASK : 0x01000000U VAL : 0x00000000U + // .. .. TST_RST = 0x0 + // .. .. ==> 0XF8000B70[25:25] = 0x00000000U + // .. .. ==> MASK : 0x02000000U VAL : 0x00000000U + // .. .. INT_DCI_EN = 0x0 + // .. .. ==> 0XF8000B70[26:26] = 0x00000000U + // .. .. ==> MASK : 0x04000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8000B70, 0x07FFFFFFU ,0x00000823U), + // .. FINISH: DDRIOB SETTINGS + // .. START: MIO PROGRAMMING + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000700[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000700[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000700[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000700[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000700[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000700[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000700[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000700[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000700[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000700, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000704[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000704[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000704[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000704[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000704[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000704[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000704[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000704[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000704[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000704, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000708[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000708[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000708[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000708[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000708[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000708[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000708[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000708[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000708[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000708, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800070C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800070C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800070C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800070C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800070C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800070C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800070C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF800070C[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF800070C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800070C, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000710[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000710[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000710[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000710[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000710[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000710[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000710[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000710[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000710[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000710, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000714[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000714[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000714[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000714[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000714[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000714[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000714[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000714[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000714[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000714, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000718[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000718[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000718[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000718[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000718[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000718[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000718[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000718[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000718[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000718, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800071C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800071C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800071C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800071C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800071C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800071C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800071C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF800071C[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF800071C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800071C, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000720[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000720[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000720[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000720[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000720[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000720[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000720[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000720[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000720[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000720, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000724[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000724[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000724[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000724[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000724[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000724[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000724[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000724[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000724[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000724, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000728[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000728[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000728[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000728[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000728[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000728[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000728[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000728[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000728[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000728, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800072C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800072C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800072C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800072C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800072C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800072C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800072C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF800072C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800072C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800072C, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000730[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000730[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000730[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000730[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000730[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000730[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000730[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000730[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000730[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000730, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000734[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000734[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000734[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000734[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000734[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000734[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000734[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000734[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000734[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000734, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000738[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF8000738[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000738[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000738[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 7 + // .. ==> 0XF8000738[7:5] = 0x00000007U + // .. ==> MASK : 0x000000E0U VAL : 0x000000E0U + // .. Speed = 0 + // .. ==> 0XF8000738[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000738[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000738[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000738[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000738, 0x00003FFFU ,0x000016E1U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800073C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800073C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800073C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800073C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 7 + // .. ==> 0XF800073C[7:5] = 0x00000007U + // .. ==> MASK : 0x000000E0U VAL : 0x000000E0U + // .. Speed = 0 + // .. ==> 0XF800073C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800073C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF800073C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800073C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800073C, 0x00003FFFU ,0x000016E0U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000740[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000740[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000740[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000740[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000740[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000740[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000740[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000740[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000740[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000740, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000744[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000744[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000744[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000744[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000744[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000744[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000744[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000744[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000744[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000744, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000748[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000748[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000748[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000748[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000748[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000748[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000748[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000748[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000748[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000748, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800074C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF800074C[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF800074C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800074C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800074C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800074C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800074C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800074C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800074C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800074C, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000750[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000750[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000750[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000750[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000750[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000750[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000750[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000750[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000750[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000750, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000754[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000754[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000754[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000754[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000754[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000754[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000754[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000754[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000754[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000754, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000758[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000758[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000758[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000758[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000758[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000758[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000758[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000758[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000758[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000758, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF800075C[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF800075C[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF800075C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800075C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800075C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800075C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800075C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800075C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800075C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800075C, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000760[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000760[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000760[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000760[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000760[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000760[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000760[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000760[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000760[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000760, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000764[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000764[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000764[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000764[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000764[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000764[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000764[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000764[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000764[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000764, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000768[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000768[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000768[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000768[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000768[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000768[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000768[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000768[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000768[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000768, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF800076C[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF800076C[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF800076C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800076C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800076C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800076C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800076C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800076C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800076C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800076C, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000770[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000770[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000770[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000770[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000770[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000770[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000770[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000770[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000770[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000770, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000774[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF8000774[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000774[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000774[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000774[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000774[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000774[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000774[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000774[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000774, 0x00003FFFU ,0x00001205U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000778[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000778[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000778[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000778[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000778[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000778[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000778[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000778[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000778[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000778, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF800077C[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF800077C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF800077C[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF800077C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800077C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800077C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800077C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800077C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800077C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800077C, 0x00003FFFU ,0x00001205U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000780[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000780[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000780[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000780[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000780[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000780[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000780[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000780[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000780[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000780, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000784[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000784[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000784[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000784[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000784[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000784[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000784[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000784[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000784[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000784, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000788[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000788[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000788[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000788[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000788[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000788[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000788[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000788[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000788[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000788, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800078C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800078C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF800078C[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF800078C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800078C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800078C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800078C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800078C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800078C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800078C, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000790[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF8000790[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000790[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000790[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000790[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000790[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000790[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000790[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000790[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000790, 0x00003FFFU ,0x00001205U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000794[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000794[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000794[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000794[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000794[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000794[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000794[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000794[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000794[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000794, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000798[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000798[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000798[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000798[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000798[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000798[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000798[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000798[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000798[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000798, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800079C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800079C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF800079C[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF800079C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800079C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800079C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800079C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800079C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800079C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800079C, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007A0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007A0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007A0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007A0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007A0[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007A0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007A0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007A0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007A0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007A0, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007A4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007A4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007A4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007A4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007A4[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007A4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007A4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007A4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007A4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007A4, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007A8[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007A8[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007A8[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007A8[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007A8[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007A8[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007A8[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007A8[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007A8[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007A8, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007AC[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007AC[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007AC[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007AC[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007AC[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007AC[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007AC[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007AC[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007AC[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007AC, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007B0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007B0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007B0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007B0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007B0[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007B0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007B0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007B0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007B0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007B0, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007B4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007B4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007B4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007B4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007B4[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007B4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007B4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007B4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007B4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007B4, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007B8[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007B8[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007B8[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007B8[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007B8[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007B8[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007B8[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007B8[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007B8[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007B8, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF80007BC[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. Speed = 0 + // .. ==> 0XF80007BC[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007BC[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007BC[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007BC[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007BC, 0x00003F01U ,0x00001201U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007C0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007C0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007C0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007C0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007C0[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007C0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007C0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007C0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007C0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007C0, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007C4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007C4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007C4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007C4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007C4[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007C4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007C4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007C4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007C4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007C4, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007C8[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007C8[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007C8[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007C8[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007C8[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007C8[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007C8[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007C8[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007C8[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007C8, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007CC[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007CC[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007CC[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007CC[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007CC[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007CC[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007CC[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007CC[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007CC[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007CC, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007D0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007D0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007D0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007D0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007D0[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007D0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007D0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007D0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007D0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007D0, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007D4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007D4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007D4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007D4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007D4[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007D4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007D4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007D4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007D4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007D4, 0x00003FFFU ,0x00001280U), + // .. SDIO0_WP_SEL = 55 + // .. ==> 0XF8000830[5:0] = 0x00000037U + // .. ==> MASK : 0x0000003FU VAL : 0x00000037U + // .. SDIO0_CD_SEL = 47 + // .. ==> 0XF8000830[21:16] = 0x0000002FU + // .. ==> MASK : 0x003F0000U VAL : 0x002F0000U + // .. + EMIT_MASKWRITE(0XF8000830, 0x003F003FU ,0x002F0037U), + // .. FINISH: MIO PROGRAMMING + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_peripherals_init_data_2_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: DDR TERM/IBUF_DISABLE_MODE SETTINGS + // .. IBUF_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B48[7:7] = 0x00000001U + // .. ==> MASK : 0x00000080U VAL : 0x00000080U + // .. TERM_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B48[8:8] = 0x00000001U + // .. ==> MASK : 0x00000100U VAL : 0x00000100U + // .. + EMIT_MASKWRITE(0XF8000B48, 0x00000180U ,0x00000180U), + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B4C[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B4C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B4C, 0x00000180U ,0x00000000U), + // .. IBUF_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B50[7:7] = 0x00000001U + // .. ==> MASK : 0x00000080U VAL : 0x00000080U + // .. TERM_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B50[8:8] = 0x00000001U + // .. ==> MASK : 0x00000100U VAL : 0x00000100U + // .. + EMIT_MASKWRITE(0XF8000B50, 0x00000180U ,0x00000180U), + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B54[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B54[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B54, 0x00000180U ,0x00000000U), + // .. FINISH: DDR TERM/IBUF_DISABLE_MODE SETTINGS + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // .. START: SRAM/NOR SET OPMODE + // .. FINISH: SRAM/NOR SET OPMODE + // .. START: UART REGISTERS + // .. BDIV = 0x5 + // .. ==> 0XE0000034[7:0] = 0x00000005U + // .. ==> MASK : 0x000000FFU VAL : 0x00000005U + // .. + EMIT_MASKWRITE(0XE0000034, 0x000000FFU ,0x00000006U), + // .. CD = 0x12 + // .. ==> 0XE0000018[15:0] = 0x00000012U + // .. ==> MASK : 0x0000FFFFU VAL : 0x00000012U + // .. + EMIT_MASKWRITE(0XE0000018, 0x0000FFFFU ,0x0000007CU), + // .. STPBRK = 0x0 + // .. ==> 0XE0000000[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. STTBRK = 0x0 + // .. ==> 0XE0000000[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. RSTTO = 0x0 + // .. ==> 0XE0000000[6:6] = 0x00000000U + // .. ==> MASK : 0x00000040U VAL : 0x00000000U + // .. TXDIS = 0x0 + // .. ==> 0XE0000000[5:5] = 0x00000000U + // .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. TXEN = 0x1 + // .. ==> 0XE0000000[4:4] = 0x00000001U + // .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. RXDIS = 0x0 + // .. ==> 0XE0000000[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. RXEN = 0x1 + // .. ==> 0XE0000000[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. TXRES = 0x1 + // .. ==> 0XE0000000[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. RXRES = 0x1 + // .. ==> 0XE0000000[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. + EMIT_MASKWRITE(0XE0000000, 0x000001FFU ,0x00000017U), + // .. IRMODE = 0x0 + // .. ==> 0XE0000004[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. UCLKEN = 0x0 + // .. ==> 0XE0000004[10:10] = 0x00000000U + // .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. CHMODE = 0x0 + // .. ==> 0XE0000004[9:8] = 0x00000000U + // .. ==> MASK : 0x00000300U VAL : 0x00000000U + // .. NBSTOP = 0x0 + // .. ==> 0XE0000004[7:6] = 0x00000000U + // .. ==> MASK : 0x000000C0U VAL : 0x00000000U + // .. PAR = 0x4 + // .. ==> 0XE0000004[5:3] = 0x00000004U + // .. ==> MASK : 0x00000038U VAL : 0x00000020U + // .. CHRL = 0x0 + // .. ==> 0XE0000004[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. CLKS = 0x0 + // .. ==> 0XE0000004[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XE0000004, 0x00000FFFU ,0x00000020U), + // .. FINISH: UART REGISTERS + // .. START: QSPI REGISTERS + // .. Holdb_dr = 1 + // .. ==> 0XE000D000[19:19] = 0x00000001U + // .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. + EMIT_MASKWRITE(0XE000D000, 0x00080000U ,0x00080000U), + // .. FINISH: QSPI REGISTERS + // .. START: PL POWER ON RESET REGISTERS + // .. PCFG_POR_CNT_4K = 0 + // .. ==> 0XF8007000[29:29] = 0x00000000U + // .. ==> MASK : 0x20000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8007000, 0x20000000U ,0x00000000U), + // .. FINISH: PL POWER ON RESET REGISTERS + // .. START: SMC TIMING CALCULATION REGISTER UPDATE + // .. .. START: NAND SET CYCLE + // .. .. FINISH: NAND SET CYCLE + // .. .. START: OPMODE + // .. .. FINISH: OPMODE + // .. .. START: DIRECT COMMAND + // .. .. FINISH: DIRECT COMMAND + // .. .. START: SRAM/NOR CS0 SET CYCLE + // .. .. FINISH: SRAM/NOR CS0 SET CYCLE + // .. .. START: DIRECT COMMAND + // .. .. FINISH: DIRECT COMMAND + // .. .. START: NOR CS0 BASE ADDRESS + // .. .. FINISH: NOR CS0 BASE ADDRESS + // .. .. START: SRAM/NOR CS1 SET CYCLE + // .. .. FINISH: SRAM/NOR CS1 SET CYCLE + // .. .. START: DIRECT COMMAND + // .. .. FINISH: DIRECT COMMAND + // .. .. START: NOR CS1 BASE ADDRESS + // .. .. FINISH: NOR CS1 BASE ADDRESS + // .. .. START: USB RESET + // .. .. .. START: USB0 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. DIRECTION_1 = 0x4000 + // .. .. .. .. ==> 0XE000A244[21:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x003FFFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A244, 0x003FFFFFU ,0x00004000U), + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. MASK_1_LSW = 0xbfff + // .. .. .. .. ==> 0XE000A008[31:16] = 0x0000BFFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xBFFF0000U + // .. .. .. .. DATA_1_LSW = 0x4000 + // .. .. .. .. ==> 0XE000A008[15:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A008, 0xFFFFFFFFU ,0xBFFF4000U), + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. OP_ENABLE_1 = 0x4000 + // .. .. .. .. ==> 0XE000A248[21:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x003FFFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A248, 0x003FFFFFU ,0x00004000U), + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. MASK_1_LSW = 0xbfff + // .. .. .. .. ==> 0XE000A008[31:16] = 0x0000BFFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xBFFF0000U + // .. .. .. .. DATA_1_LSW = 0x0 + // .. .. .. .. ==> 0XE000A008[15:0] = 0x00000000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A008, 0xFFFFFFFFU ,0xBFFF0000U), + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. MASK_1_LSW = 0xbfff + // .. .. .. .. ==> 0XE000A008[31:16] = 0x0000BFFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xBFFF0000U + // .. .. .. .. DATA_1_LSW = 0x4000 + // .. .. .. .. ==> 0XE000A008[15:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A008, 0xFFFFFFFFU ,0xBFFF4000U), + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: USB0 RESET + // .. .. .. START: USB1 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: USB1 RESET + // .. .. FINISH: USB RESET + // .. .. START: ENET RESET + // .. .. .. START: ENET0 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. DIRECTION_0 = 0x200 + // .. .. .. .. ==> 0XE000A204[31:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A204, 0xFFFFFFFFU ,0x00000200U), + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. MASK_0_LSW = 0xfdff + // .. .. .. .. ==> 0XE000A000[31:16] = 0x0000FDFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xFDFF0000U + // .. .. .. .. DATA_0_LSW = 0x200 + // .. .. .. .. ==> 0XE000A000[15:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A000, 0xFFFFFFFFU ,0xFDFF0200U), + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. OP_ENABLE_0 = 0x200 + // .. .. .. .. ==> 0XE000A208[31:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A208, 0xFFFFFFFFU ,0x00000200U), + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. MASK_0_LSW = 0xfdff + // .. .. .. .. ==> 0XE000A000[31:16] = 0x0000FDFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xFDFF0000U + // .. .. .. .. DATA_0_LSW = 0x0 + // .. .. .. .. ==> 0XE000A000[15:0] = 0x00000000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A000, 0xFFFFFFFFU ,0xFDFF0000U), + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. MASK_0_LSW = 0xfdff + // .. .. .. .. ==> 0XE000A000[31:16] = 0x0000FDFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xFDFF0000U + // .. .. .. .. DATA_0_LSW = 0x200 + // .. .. .. .. ==> 0XE000A000[15:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A000, 0xFFFFFFFFU ,0xFDFF0200U), + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: ENET0 RESET + // .. .. .. START: ENET1 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: ENET1 RESET + // .. .. FINISH: ENET RESET + // .. .. START: I2C RESET + // .. .. .. START: I2C0 RESET + // .. .. .. .. START: DIR MODE GPIO BANK0 + // .. .. .. .. FINISH: DIR MODE GPIO BANK0 + // .. .. .. .. START: DIR MODE GPIO BANK1 + // .. .. .. .. FINISH: DIR MODE GPIO BANK1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: I2C0 RESET + // .. .. .. START: I2C1 RESET + // .. .. .. .. START: DIR MODE GPIO BANK0 + // .. .. .. .. FINISH: DIR MODE GPIO BANK0 + // .. .. .. .. START: DIR MODE GPIO BANK1 + // .. .. .. .. FINISH: DIR MODE GPIO BANK1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: I2C1 RESET + // .. .. FINISH: I2C RESET + // .. .. START: NOR CHIP SELECT + // .. .. .. START: DIR MODE BANK 0 + // .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. FINISH: NOR CHIP SELECT + // .. FINISH: SMC TIMING CALCULATION REGISTER UPDATE + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_post_config_2_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: ENABLING LEVEL SHIFTER + // .. USER_INP_ICT_EN_0 = 3 + // .. ==> 0XF8000900[1:0] = 0x00000003U + // .. ==> MASK : 0x00000003U VAL : 0x00000003U + // .. USER_INP_ICT_EN_1 = 3 + // .. ==> 0XF8000900[3:2] = 0x00000003U + // .. ==> MASK : 0x0000000CU VAL : 0x0000000CU + // .. + EMIT_MASKWRITE(0XF8000900, 0x0000000FU ,0x0000000FU), + // .. FINISH: ENABLING LEVEL SHIFTER + // .. START: FPGA RESETS TO 0 + // .. reserved_3 = 0 + // .. ==> 0XF8000240[31:25] = 0x00000000U + // .. ==> MASK : 0xFE000000U VAL : 0x00000000U + // .. FPGA_ACP_RST = 0 + // .. ==> 0XF8000240[24:24] = 0x00000000U + // .. ==> MASK : 0x01000000U VAL : 0x00000000U + // .. FPGA_AXDS3_RST = 0 + // .. ==> 0XF8000240[23:23] = 0x00000000U + // .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. FPGA_AXDS2_RST = 0 + // .. ==> 0XF8000240[22:22] = 0x00000000U + // .. ==> MASK : 0x00400000U VAL : 0x00000000U + // .. FPGA_AXDS1_RST = 0 + // .. ==> 0XF8000240[21:21] = 0x00000000U + // .. ==> MASK : 0x00200000U VAL : 0x00000000U + // .. FPGA_AXDS0_RST = 0 + // .. ==> 0XF8000240[20:20] = 0x00000000U + // .. ==> MASK : 0x00100000U VAL : 0x00000000U + // .. reserved_2 = 0 + // .. ==> 0XF8000240[19:18] = 0x00000000U + // .. ==> MASK : 0x000C0000U VAL : 0x00000000U + // .. FSSW1_FPGA_RST = 0 + // .. ==> 0XF8000240[17:17] = 0x00000000U + // .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. FSSW0_FPGA_RST = 0 + // .. ==> 0XF8000240[16:16] = 0x00000000U + // .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. reserved_1 = 0 + // .. ==> 0XF8000240[15:14] = 0x00000000U + // .. ==> MASK : 0x0000C000U VAL : 0x00000000U + // .. FPGA_FMSW1_RST = 0 + // .. ==> 0XF8000240[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. FPGA_FMSW0_RST = 0 + // .. ==> 0XF8000240[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. FPGA_DMA3_RST = 0 + // .. ==> 0XF8000240[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. FPGA_DMA2_RST = 0 + // .. ==> 0XF8000240[10:10] = 0x00000000U + // .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. FPGA_DMA1_RST = 0 + // .. ==> 0XF8000240[9:9] = 0x00000000U + // .. ==> MASK : 0x00000200U VAL : 0x00000000U + // .. FPGA_DMA0_RST = 0 + // .. ==> 0XF8000240[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. reserved = 0 + // .. ==> 0XF8000240[7:4] = 0x00000000U + // .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. FPGA3_OUT_RST = 0 + // .. ==> 0XF8000240[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. FPGA2_OUT_RST = 0 + // .. ==> 0XF8000240[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. FPGA1_OUT_RST = 0 + // .. ==> 0XF8000240[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. FPGA0_OUT_RST = 0 + // .. ==> 0XF8000240[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000240, 0xFFFFFFFFU ,0x00000000U), + // .. FINISH: FPGA RESETS TO 0 + // .. START: AFI REGISTERS + // .. .. START: AFI0 REGISTERS + // .. .. FINISH: AFI0 REGISTERS + // .. .. START: AFI1 REGISTERS + // .. .. FINISH: AFI1 REGISTERS + // .. .. START: AFI2 REGISTERS + // .. .. FINISH: AFI2 REGISTERS + // .. .. START: AFI3 REGISTERS + // .. .. FINISH: AFI3 REGISTERS + // .. FINISH: AFI REGISTERS + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_debug_2_0[] = { + // START: top + // .. START: CROSS TRIGGER CONFIGURATIONS + // .. .. START: UNLOCKING CTI REGISTERS + // .. .. KEY = 0XC5ACCE55 + // .. .. ==> 0XF8898FB0[31:0] = 0xC5ACCE55U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0xC5ACCE55U + // .. .. + EMIT_WRITE(0XF8898FB0, 0xC5ACCE55U), + // .. .. KEY = 0XC5ACCE55 + // .. .. ==> 0XF8899FB0[31:0] = 0xC5ACCE55U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0xC5ACCE55U + // .. .. + EMIT_WRITE(0XF8899FB0, 0xC5ACCE55U), + // .. .. KEY = 0XC5ACCE55 + // .. .. ==> 0XF8809FB0[31:0] = 0xC5ACCE55U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0xC5ACCE55U + // .. .. + EMIT_WRITE(0XF8809FB0, 0xC5ACCE55U), + // .. .. FINISH: UNLOCKING CTI REGISTERS + // .. .. START: ENABLING CTI MODULES AND CHANNELS + // .. .. FINISH: ENABLING CTI MODULES AND CHANNELS + // .. .. START: MAPPING CPU0, CPU1 AND FTM EVENTS TO CTM CHANNELS + // .. .. FINISH: MAPPING CPU0, CPU1 AND FTM EVENTS TO CTM CHANNELS + // .. FINISH: CROSS TRIGGER CONFIGURATIONS + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_pll_init_data_1_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: PLL SLCR REGISTERS + // .. .. START: ARM PLL INIT + // .. .. PLL_RES = 0xc + // .. .. ==> 0XF8000110[7:4] = 0x0000000CU + // .. .. ==> MASK : 0x000000F0U VAL : 0x000000C0U + // .. .. PLL_CP = 0x2 + // .. .. ==> 0XF8000110[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. LOCK_CNT = 0x177 + // .. .. ==> 0XF8000110[21:12] = 0x00000177U + // .. .. ==> MASK : 0x003FF000U VAL : 0x00177000U + // .. .. + EMIT_MASKWRITE(0XF8000110, 0x003FFFF0U ,0x001772C0U), + // .. .. .. START: UPDATE FB_DIV + // .. .. .. PLL_FDIV = 0x1a + // .. .. .. ==> 0XF8000100[18:12] = 0x0000001AU + // .. .. .. ==> MASK : 0x0007F000U VAL : 0x0001A000U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x0007F000U ,0x0001A000U), + // .. .. .. FINISH: UPDATE FB_DIV + // .. .. .. START: BY PASS PLL + // .. .. .. PLL_BYPASS_FORCE = 1 + // .. .. .. ==> 0XF8000100[4:4] = 0x00000001U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000010U ,0x00000010U), + // .. .. .. FINISH: BY PASS PLL + // .. .. .. START: ASSERT RESET + // .. .. .. PLL_RESET = 1 + // .. .. .. ==> 0XF8000100[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000001U ,0x00000001U), + // .. .. .. FINISH: ASSERT RESET + // .. .. .. START: DEASSERT RESET + // .. .. .. PLL_RESET = 0 + // .. .. .. ==> 0XF8000100[0:0] = 0x00000000U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000001U ,0x00000000U), + // .. .. .. FINISH: DEASSERT RESET + // .. .. .. START: CHECK PLL STATUS + // .. .. .. ARM_PLL_LOCK = 1 + // .. .. .. ==> 0XF800010C[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKPOLL(0XF800010C, 0x00000001U), + // .. .. .. FINISH: CHECK PLL STATUS + // .. .. .. START: REMOVE PLL BY PASS + // .. .. .. PLL_BYPASS_FORCE = 0 + // .. .. .. ==> 0XF8000100[4:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000100, 0x00000010U ,0x00000000U), + // .. .. .. FINISH: REMOVE PLL BY PASS + // .. .. .. SRCSEL = 0x0 + // .. .. .. ==> 0XF8000120[5:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. .. .. DIVISOR = 0x2 + // .. .. .. ==> 0XF8000120[13:8] = 0x00000002U + // .. .. .. ==> MASK : 0x00003F00U VAL : 0x00000200U + // .. .. .. CPU_6OR4XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[24:24] = 0x00000001U + // .. .. .. ==> MASK : 0x01000000U VAL : 0x01000000U + // .. .. .. CPU_3OR2XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[25:25] = 0x00000001U + // .. .. .. ==> MASK : 0x02000000U VAL : 0x02000000U + // .. .. .. CPU_2XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[26:26] = 0x00000001U + // .. .. .. ==> MASK : 0x04000000U VAL : 0x04000000U + // .. .. .. CPU_1XCLKACT = 0x1 + // .. .. .. ==> 0XF8000120[27:27] = 0x00000001U + // .. .. .. ==> MASK : 0x08000000U VAL : 0x08000000U + // .. .. .. CPU_PERI_CLKACT = 0x1 + // .. .. .. ==> 0XF8000120[28:28] = 0x00000001U + // .. .. .. ==> MASK : 0x10000000U VAL : 0x10000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000120, 0x1F003F30U ,0x1F000200U), + // .. .. FINISH: ARM PLL INIT + // .. .. START: DDR PLL INIT + // .. .. PLL_RES = 0xc + // .. .. ==> 0XF8000114[7:4] = 0x0000000CU + // .. .. ==> MASK : 0x000000F0U VAL : 0x000000C0U + // .. .. PLL_CP = 0x2 + // .. .. ==> 0XF8000114[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. LOCK_CNT = 0x1db + // .. .. ==> 0XF8000114[21:12] = 0x000001DBU + // .. .. ==> MASK : 0x003FF000U VAL : 0x001DB000U + // .. .. + EMIT_MASKWRITE(0XF8000114, 0x003FFFF0U ,0x001DB2C0U), + // .. .. .. START: UPDATE FB_DIV + // .. .. .. PLL_FDIV = 0x15 + // .. .. .. ==> 0XF8000104[18:12] = 0x00000015U + // .. .. .. ==> MASK : 0x0007F000U VAL : 0x00015000U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x0007F000U ,0x00015000U), + // .. .. .. FINISH: UPDATE FB_DIV + // .. .. .. START: BY PASS PLL + // .. .. .. PLL_BYPASS_FORCE = 1 + // .. .. .. ==> 0XF8000104[4:4] = 0x00000001U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000010U ,0x00000010U), + // .. .. .. FINISH: BY PASS PLL + // .. .. .. START: ASSERT RESET + // .. .. .. PLL_RESET = 1 + // .. .. .. ==> 0XF8000104[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000001U ,0x00000001U), + // .. .. .. FINISH: ASSERT RESET + // .. .. .. START: DEASSERT RESET + // .. .. .. PLL_RESET = 0 + // .. .. .. ==> 0XF8000104[0:0] = 0x00000000U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000001U ,0x00000000U), + // .. .. .. FINISH: DEASSERT RESET + // .. .. .. START: CHECK PLL STATUS + // .. .. .. DDR_PLL_LOCK = 1 + // .. .. .. ==> 0XF800010C[1:1] = 0x00000001U + // .. .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. .. + EMIT_MASKPOLL(0XF800010C, 0x00000002U), + // .. .. .. FINISH: CHECK PLL STATUS + // .. .. .. START: REMOVE PLL BY PASS + // .. .. .. PLL_BYPASS_FORCE = 0 + // .. .. .. ==> 0XF8000104[4:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000104, 0x00000010U ,0x00000000U), + // .. .. .. FINISH: REMOVE PLL BY PASS + // .. .. .. DDR_3XCLKACT = 0x1 + // .. .. .. ==> 0XF8000124[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. DDR_2XCLKACT = 0x1 + // .. .. .. ==> 0XF8000124[1:1] = 0x00000001U + // .. .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. .. DDR_3XCLK_DIVISOR = 0x2 + // .. .. .. ==> 0XF8000124[25:20] = 0x00000002U + // .. .. .. ==> MASK : 0x03F00000U VAL : 0x00200000U + // .. .. .. DDR_2XCLK_DIVISOR = 0x3 + // .. .. .. ==> 0XF8000124[31:26] = 0x00000003U + // .. .. .. ==> MASK : 0xFC000000U VAL : 0x0C000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000124, 0xFFF00003U ,0x0C200003U), + // .. .. FINISH: DDR PLL INIT + // .. .. START: IO PLL INIT + // .. .. PLL_RES = 0xc + // .. .. ==> 0XF8000118[7:4] = 0x0000000CU + // .. .. ==> MASK : 0x000000F0U VAL : 0x000000C0U + // .. .. PLL_CP = 0x2 + // .. .. ==> 0XF8000118[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. LOCK_CNT = 0x1f4 + // .. .. ==> 0XF8000118[21:12] = 0x000001F4U + // .. .. ==> MASK : 0x003FF000U VAL : 0x001F4000U + // .. .. + EMIT_MASKWRITE(0XF8000118, 0x003FFFF0U ,0x001F42C0U), + // .. .. .. START: UPDATE FB_DIV + // .. .. .. PLL_FDIV = 0x14 + // .. .. .. ==> 0XF8000108[18:12] = 0x00000014U + // .. .. .. ==> MASK : 0x0007F000U VAL : 0x00014000U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x0007F000U ,0x00014000U), + // .. .. .. FINISH: UPDATE FB_DIV + // .. .. .. START: BY PASS PLL + // .. .. .. PLL_BYPASS_FORCE = 1 + // .. .. .. ==> 0XF8000108[4:4] = 0x00000001U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000010U ,0x00000010U), + // .. .. .. FINISH: BY PASS PLL + // .. .. .. START: ASSERT RESET + // .. .. .. PLL_RESET = 1 + // .. .. .. ==> 0XF8000108[0:0] = 0x00000001U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000001U ,0x00000001U), + // .. .. .. FINISH: ASSERT RESET + // .. .. .. START: DEASSERT RESET + // .. .. .. PLL_RESET = 0 + // .. .. .. ==> 0XF8000108[0:0] = 0x00000000U + // .. .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000001U ,0x00000000U), + // .. .. .. FINISH: DEASSERT RESET + // .. .. .. START: CHECK PLL STATUS + // .. .. .. IO_PLL_LOCK = 1 + // .. .. .. ==> 0XF800010C[2:2] = 0x00000001U + // .. .. .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. .. .. + EMIT_MASKPOLL(0XF800010C, 0x00000004U), + // .. .. .. FINISH: CHECK PLL STATUS + // .. .. .. START: REMOVE PLL BY PASS + // .. .. .. PLL_BYPASS_FORCE = 0 + // .. .. .. ==> 0XF8000108[4:4] = 0x00000000U + // .. .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. .. + EMIT_MASKWRITE(0XF8000108, 0x00000010U ,0x00000000U), + // .. .. .. FINISH: REMOVE PLL BY PASS + // .. .. FINISH: IO PLL INIT + // .. FINISH: PLL SLCR REGISTERS + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_clock_init_data_1_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: CLOCK CONTROL SLCR REGISTERS + // .. CLKACT = 0x1 + // .. ==> 0XF8000128[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. DIVISOR0 = 0x34 + // .. ==> 0XF8000128[13:8] = 0x00000034U + // .. ==> MASK : 0x00003F00U VAL : 0x00003400U + // .. DIVISOR1 = 0x2 + // .. ==> 0XF8000128[25:20] = 0x00000002U + // .. ==> MASK : 0x03F00000U VAL : 0x00200000U + // .. + EMIT_MASKWRITE(0XF8000128, 0x03F03F01U ,0x00203401U), + // .. CLKACT = 0x1 + // .. ==> 0XF8000138[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000138[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000138, 0x00000011U ,0x00000001U), + // .. CLKACT = 0x1 + // .. ==> 0XF8000140[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000140[6:4] = 0x00000000U + // .. ==> MASK : 0x00000070U VAL : 0x00000000U + // .. DIVISOR = 0x8 + // .. ==> 0XF8000140[13:8] = 0x00000008U + // .. ==> MASK : 0x00003F00U VAL : 0x00000800U + // .. DIVISOR1 = 0x1 + // .. ==> 0XF8000140[25:20] = 0x00000001U + // .. ==> MASK : 0x03F00000U VAL : 0x00100000U + // .. + EMIT_MASKWRITE(0XF8000140, 0x03F03F71U ,0x00100801U), + // .. CLKACT0 = 0x1 + // .. ==> 0XF8000150[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. CLKACT1 = 0x0 + // .. ==> 0XF8000150[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000150[5:4] = 0x00000000U + // .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. DIVISOR = 0x14 + // .. ==> 0XF8000150[13:8] = 0x00000014U + // .. ==> MASK : 0x00003F00U VAL : 0x00001400U + // .. + EMIT_MASKWRITE(0XF8000150, 0x00003F33U ,0x00001401U), + // .. CLKACT0 = 0x1 + // .. ==> 0XF8000154[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. CLKACT1 = 0x0 + // .. ==> 0XF8000154[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000154[5:4] = 0x00000000U + // .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. DIVISOR = 0xa + // .. ==> 0XF8000154[13:8] = 0x0000000AU + // .. ==> MASK : 0x00003F00U VAL : 0x00000A00U + // .. + EMIT_MASKWRITE(0XF8000154, 0x00003F33U ,0x00000A01U), + // .. CLKACT0 = 0x1 + // .. ==> 0XF8000158[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. CLKACT1 = 0x0 + // .. ==> 0XF8000158[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. SRCSEL = 0x0 + // .. ==> 0XF8000158[5:4] = 0x00000000U + // .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. DIVISOR = 0x6 + // .. ==> 0XF8000158[13:8] = 0x00000006U + // .. ==> MASK : 0x00003F00U VAL : 0x00000600U + // .. + EMIT_MASKWRITE(0XF8000158, 0x00003F33U ,0x00000601U), + // .. .. START: TRACE CLOCK + // .. .. FINISH: TRACE CLOCK + // .. .. CLKACT = 0x1 + // .. .. ==> 0XF8000168[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. SRCSEL = 0x0 + // .. .. ==> 0XF8000168[5:4] = 0x00000000U + // .. .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. .. DIVISOR = 0x5 + // .. .. ==> 0XF8000168[13:8] = 0x00000005U + // .. .. ==> MASK : 0x00003F00U VAL : 0x00000500U + // .. .. + EMIT_MASKWRITE(0XF8000168, 0x00003F31U ,0x00000501U), + // .. .. SRCSEL = 0x0 + // .. .. ==> 0XF8000170[5:4] = 0x00000000U + // .. .. ==> MASK : 0x00000030U VAL : 0x00000000U + // .. .. DIVISOR0 = 0x5 + // .. .. ==> 0XF8000170[13:8] = 0x00000005U + // .. .. ==> MASK : 0x00003F00U VAL : 0x00000500U + // .. .. DIVISOR1 = 0x2 + // .. .. ==> 0XF8000170[25:20] = 0x00000002U + // .. .. ==> MASK : 0x03F00000U VAL : 0x00200000U + // .. .. + EMIT_MASKWRITE(0XF8000170, 0x03F03F30U ,0x00200500U), + // .. .. CLK_621_TRUE = 0x1 + // .. .. ==> 0XF80001C4[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. + EMIT_MASKWRITE(0XF80001C4, 0x00000001U ,0x00000001U), + // .. .. DMA_CPU_2XCLKACT = 0x1 + // .. .. ==> 0XF800012C[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. USB0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[2:2] = 0x00000001U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. .. USB1_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[3:3] = 0x00000001U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000008U + // .. .. GEM0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[6:6] = 0x00000001U + // .. .. ==> MASK : 0x00000040U VAL : 0x00000040U + // .. .. GEM1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[7:7] = 0x00000000U + // .. .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. .. SDI0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[10:10] = 0x00000001U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000400U + // .. .. SDI1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. SPI0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[14:14] = 0x00000001U + // .. .. ==> MASK : 0x00004000U VAL : 0x00004000U + // .. .. SPI1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. CAN0_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. CAN1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. I2C0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[18:18] = 0x00000001U + // .. .. ==> MASK : 0x00040000U VAL : 0x00040000U + // .. .. I2C1_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[19:19] = 0x00000001U + // .. .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. .. UART0_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[20:20] = 0x00000001U + // .. .. ==> MASK : 0x00100000U VAL : 0x00100000U + // .. .. UART1_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[21:21] = 0x00000000U + // .. .. ==> MASK : 0x00200000U VAL : 0x00000000U + // .. .. GPIO_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[22:22] = 0x00000001U + // .. .. ==> MASK : 0x00400000U VAL : 0x00400000U + // .. .. LQSPI_CPU_1XCLKACT = 0x0 + // .. .. ==> 0XF800012C[23:23] = 0x00000000U + // .. .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. .. SMC_CPU_1XCLKACT = 0x1 + // .. .. ==> 0XF800012C[24:24] = 0x00000001U + // .. .. ==> MASK : 0x01000000U VAL : 0x01000000U + // .. .. + EMIT_MASKWRITE(0XF800012C, 0x01FFCCCDU ,0x015C444DU), + // .. FINISH: CLOCK CONTROL SLCR REGISTERS + // .. START: THIS SHOULD BE BLANK + // .. FINISH: THIS SHOULD BE BLANK + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_ddr_init_data_1_0[] = { + // START: top + // .. START: DDR INITIALIZATION + // .. .. START: LOCK DDR + // .. .. reg_ddrc_soft_rstb = 0 + // .. .. ==> 0XF8006000[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_powerdown_en = 0x0 + // .. .. ==> 0XF8006000[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_ddrc_data_bus_width = 0x1 + // .. .. ==> 0XF8006000[3:2] = 0x00000001U + // .. .. ==> MASK : 0x0000000CU VAL : 0x00000004U + // .. .. reg_ddrc_burst8_refresh = 0x0 + // .. .. ==> 0XF8006000[6:4] = 0x00000000U + // .. .. ==> MASK : 0x00000070U VAL : 0x00000000U + // .. .. reg_ddrc_rdwr_idle_gap = 0x1 + // .. .. ==> 0XF8006000[13:7] = 0x00000001U + // .. .. ==> MASK : 0x00003F80U VAL : 0x00000080U + // .. .. reg_ddrc_dis_rd_bypass = 0x0 + // .. .. ==> 0XF8006000[14:14] = 0x00000000U + // .. .. ==> MASK : 0x00004000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_act_bypass = 0x0 + // .. .. ==> 0XF8006000[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_auto_refresh = 0x0 + // .. .. ==> 0XF8006000[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006000, 0x0001FFFFU ,0x00000084U), + // .. .. FINISH: LOCK DDR + // .. .. reg_ddrc_t_rfc_nom_x32 = 0x7f + // .. .. ==> 0XF8006004[11:0] = 0x0000007FU + // .. .. ==> MASK : 0x00000FFFU VAL : 0x0000007FU + // .. .. reg_ddrc_active_ranks = 0x1 + // .. .. ==> 0XF8006004[13:12] = 0x00000001U + // .. .. ==> MASK : 0x00003000U VAL : 0x00001000U + // .. .. reg_ddrc_addrmap_cs_bit0 = 0x0 + // .. .. ==> 0XF8006004[18:14] = 0x00000000U + // .. .. ==> MASK : 0x0007C000U VAL : 0x00000000U + // .. .. reg_ddrc_wr_odt_block = 0x1 + // .. .. ==> 0XF8006004[20:19] = 0x00000001U + // .. .. ==> MASK : 0x00180000U VAL : 0x00080000U + // .. .. reg_ddrc_diff_rank_rd_2cycle_gap = 0x0 + // .. .. ==> 0XF8006004[21:21] = 0x00000000U + // .. .. ==> MASK : 0x00200000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_cs_bit1 = 0x0 + // .. .. ==> 0XF8006004[26:22] = 0x00000000U + // .. .. ==> MASK : 0x07C00000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_open_bank = 0x0 + // .. .. ==> 0XF8006004[27:27] = 0x00000000U + // .. .. ==> MASK : 0x08000000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_4bank_ram = 0x0 + // .. .. ==> 0XF8006004[28:28] = 0x00000000U + // .. .. ==> MASK : 0x10000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006004, 0x1FFFFFFFU ,0x0008107FU), + // .. .. reg_ddrc_hpr_min_non_critical_x32 = 0xf + // .. .. ==> 0XF8006008[10:0] = 0x0000000FU + // .. .. ==> MASK : 0x000007FFU VAL : 0x0000000FU + // .. .. reg_ddrc_hpr_max_starve_x32 = 0xf + // .. .. ==> 0XF8006008[21:11] = 0x0000000FU + // .. .. ==> MASK : 0x003FF800U VAL : 0x00007800U + // .. .. reg_ddrc_hpr_xact_run_length = 0xf + // .. .. ==> 0XF8006008[25:22] = 0x0000000FU + // .. .. ==> MASK : 0x03C00000U VAL : 0x03C00000U + // .. .. + EMIT_MASKWRITE(0XF8006008, 0x03FFFFFFU ,0x03C0780FU), + // .. .. reg_ddrc_lpr_min_non_critical_x32 = 0x1 + // .. .. ==> 0XF800600C[10:0] = 0x00000001U + // .. .. ==> MASK : 0x000007FFU VAL : 0x00000001U + // .. .. reg_ddrc_lpr_max_starve_x32 = 0x2 + // .. .. ==> 0XF800600C[21:11] = 0x00000002U + // .. .. ==> MASK : 0x003FF800U VAL : 0x00001000U + // .. .. reg_ddrc_lpr_xact_run_length = 0x8 + // .. .. ==> 0XF800600C[25:22] = 0x00000008U + // .. .. ==> MASK : 0x03C00000U VAL : 0x02000000U + // .. .. + EMIT_MASKWRITE(0XF800600C, 0x03FFFFFFU ,0x02001001U), + // .. .. reg_ddrc_w_min_non_critical_x32 = 0x1 + // .. .. ==> 0XF8006010[10:0] = 0x00000001U + // .. .. ==> MASK : 0x000007FFU VAL : 0x00000001U + // .. .. reg_ddrc_w_xact_run_length = 0x8 + // .. .. ==> 0XF8006010[14:11] = 0x00000008U + // .. .. ==> MASK : 0x00007800U VAL : 0x00004000U + // .. .. reg_ddrc_w_max_starve_x32 = 0x2 + // .. .. ==> 0XF8006010[25:15] = 0x00000002U + // .. .. ==> MASK : 0x03FF8000U VAL : 0x00010000U + // .. .. + EMIT_MASKWRITE(0XF8006010, 0x03FFFFFFU ,0x00014001U), + // .. .. reg_ddrc_t_rc = 0x1a + // .. .. ==> 0XF8006014[5:0] = 0x0000001AU + // .. .. ==> MASK : 0x0000003FU VAL : 0x0000001AU + // .. .. reg_ddrc_t_rfc_min = 0x9e + // .. .. ==> 0XF8006014[13:6] = 0x0000009EU + // .. .. ==> MASK : 0x00003FC0U VAL : 0x00002780U + // .. .. reg_ddrc_post_selfref_gap_x32 = 0x10 + // .. .. ==> 0XF8006014[20:14] = 0x00000010U + // .. .. ==> MASK : 0x001FC000U VAL : 0x00040000U + // .. .. + EMIT_MASKWRITE(0XF8006014, 0x001FFFFFU ,0x0004279AU), + // .. .. reg_ddrc_wr2pre = 0x12 + // .. .. ==> 0XF8006018[4:0] = 0x00000012U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000012U + // .. .. reg_ddrc_powerdown_to_x32 = 0x6 + // .. .. ==> 0XF8006018[9:5] = 0x00000006U + // .. .. ==> MASK : 0x000003E0U VAL : 0x000000C0U + // .. .. reg_ddrc_t_faw = 0x15 + // .. .. ==> 0XF8006018[15:10] = 0x00000015U + // .. .. ==> MASK : 0x0000FC00U VAL : 0x00005400U + // .. .. reg_ddrc_t_ras_max = 0x23 + // .. .. ==> 0XF8006018[21:16] = 0x00000023U + // .. .. ==> MASK : 0x003F0000U VAL : 0x00230000U + // .. .. reg_ddrc_t_ras_min = 0x13 + // .. .. ==> 0XF8006018[26:22] = 0x00000013U + // .. .. ==> MASK : 0x07C00000U VAL : 0x04C00000U + // .. .. reg_ddrc_t_cke = 0x4 + // .. .. ==> 0XF8006018[31:28] = 0x00000004U + // .. .. ==> MASK : 0xF0000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006018, 0xF7FFFFFFU ,0x44E354D2U), + // .. .. reg_ddrc_write_latency = 0x5 + // .. .. ==> 0XF800601C[4:0] = 0x00000005U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000005U + // .. .. reg_ddrc_rd2wr = 0x7 + // .. .. ==> 0XF800601C[9:5] = 0x00000007U + // .. .. ==> MASK : 0x000003E0U VAL : 0x000000E0U + // .. .. reg_ddrc_wr2rd = 0xe + // .. .. ==> 0XF800601C[14:10] = 0x0000000EU + // .. .. ==> MASK : 0x00007C00U VAL : 0x00003800U + // .. .. reg_ddrc_t_xp = 0x4 + // .. .. ==> 0XF800601C[19:15] = 0x00000004U + // .. .. ==> MASK : 0x000F8000U VAL : 0x00020000U + // .. .. reg_ddrc_pad_pd = 0x0 + // .. .. ==> 0XF800601C[22:20] = 0x00000000U + // .. .. ==> MASK : 0x00700000U VAL : 0x00000000U + // .. .. reg_ddrc_rd2pre = 0x4 + // .. .. ==> 0XF800601C[27:23] = 0x00000004U + // .. .. ==> MASK : 0x0F800000U VAL : 0x02000000U + // .. .. reg_ddrc_t_rcd = 0x7 + // .. .. ==> 0XF800601C[31:28] = 0x00000007U + // .. .. ==> MASK : 0xF0000000U VAL : 0x70000000U + // .. .. + EMIT_MASKWRITE(0XF800601C, 0xFFFFFFFFU ,0x720238E5U), + // .. .. reg_ddrc_t_ccd = 0x4 + // .. .. ==> 0XF8006020[4:2] = 0x00000004U + // .. .. ==> MASK : 0x0000001CU VAL : 0x00000010U + // .. .. reg_ddrc_t_rrd = 0x6 + // .. .. ==> 0XF8006020[7:5] = 0x00000006U + // .. .. ==> MASK : 0x000000E0U VAL : 0x000000C0U + // .. .. reg_ddrc_refresh_margin = 0x2 + // .. .. ==> 0XF8006020[11:8] = 0x00000002U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000200U + // .. .. reg_ddrc_t_rp = 0x7 + // .. .. ==> 0XF8006020[15:12] = 0x00000007U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00007000U + // .. .. reg_ddrc_refresh_to_x32 = 0x8 + // .. .. ==> 0XF8006020[20:16] = 0x00000008U + // .. .. ==> MASK : 0x001F0000U VAL : 0x00080000U + // .. .. reg_ddrc_sdram = 0x1 + // .. .. ==> 0XF8006020[21:21] = 0x00000001U + // .. .. ==> MASK : 0x00200000U VAL : 0x00200000U + // .. .. reg_ddrc_mobile = 0x0 + // .. .. ==> 0XF8006020[22:22] = 0x00000000U + // .. .. ==> MASK : 0x00400000U VAL : 0x00000000U + // .. .. reg_ddrc_clock_stop_en = 0x0 + // .. .. ==> 0XF8006020[23:23] = 0x00000000U + // .. .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. .. reg_ddrc_read_latency = 0x7 + // .. .. ==> 0XF8006020[28:24] = 0x00000007U + // .. .. ==> MASK : 0x1F000000U VAL : 0x07000000U + // .. .. reg_phy_mode_ddr1_ddr2 = 0x1 + // .. .. ==> 0XF8006020[29:29] = 0x00000001U + // .. .. ==> MASK : 0x20000000U VAL : 0x20000000U + // .. .. reg_ddrc_dis_pad_pd = 0x0 + // .. .. ==> 0XF8006020[30:30] = 0x00000000U + // .. .. ==> MASK : 0x40000000U VAL : 0x00000000U + // .. .. reg_ddrc_loopback = 0x0 + // .. .. ==> 0XF8006020[31:31] = 0x00000000U + // .. .. ==> MASK : 0x80000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006020, 0xFFFFFFFCU ,0x272872D0U), + // .. .. reg_ddrc_en_2t_timing_mode = 0x0 + // .. .. ==> 0XF8006024[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_prefer_write = 0x0 + // .. .. ==> 0XF8006024[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_ddrc_max_rank_rd = 0xf + // .. .. ==> 0XF8006024[5:2] = 0x0000000FU + // .. .. ==> MASK : 0x0000003CU VAL : 0x0000003CU + // .. .. reg_ddrc_mr_wr = 0x0 + // .. .. ==> 0XF8006024[6:6] = 0x00000000U + // .. .. ==> MASK : 0x00000040U VAL : 0x00000000U + // .. .. reg_ddrc_mr_addr = 0x0 + // .. .. ==> 0XF8006024[8:7] = 0x00000000U + // .. .. ==> MASK : 0x00000180U VAL : 0x00000000U + // .. .. reg_ddrc_mr_data = 0x0 + // .. .. ==> 0XF8006024[24:9] = 0x00000000U + // .. .. ==> MASK : 0x01FFFE00U VAL : 0x00000000U + // .. .. ddrc_reg_mr_wr_busy = 0x0 + // .. .. ==> 0XF8006024[25:25] = 0x00000000U + // .. .. ==> MASK : 0x02000000U VAL : 0x00000000U + // .. .. reg_ddrc_mr_type = 0x0 + // .. .. ==> 0XF8006024[26:26] = 0x00000000U + // .. .. ==> MASK : 0x04000000U VAL : 0x00000000U + // .. .. reg_ddrc_mr_rdata_valid = 0x0 + // .. .. ==> 0XF8006024[27:27] = 0x00000000U + // .. .. ==> MASK : 0x08000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006024, 0x0FFFFFFFU ,0x0000003CU), + // .. .. reg_ddrc_final_wait_x32 = 0x7 + // .. .. ==> 0XF8006028[6:0] = 0x00000007U + // .. .. ==> MASK : 0x0000007FU VAL : 0x00000007U + // .. .. reg_ddrc_pre_ocd_x32 = 0x0 + // .. .. ==> 0XF8006028[10:7] = 0x00000000U + // .. .. ==> MASK : 0x00000780U VAL : 0x00000000U + // .. .. reg_ddrc_t_mrd = 0x4 + // .. .. ==> 0XF8006028[13:11] = 0x00000004U + // .. .. ==> MASK : 0x00003800U VAL : 0x00002000U + // .. .. + EMIT_MASKWRITE(0XF8006028, 0x00003FFFU ,0x00002007U), + // .. .. reg_ddrc_emr2 = 0x8 + // .. .. ==> 0XF800602C[15:0] = 0x00000008U + // .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000008U + // .. .. reg_ddrc_emr3 = 0x0 + // .. .. ==> 0XF800602C[31:16] = 0x00000000U + // .. .. ==> MASK : 0xFFFF0000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800602C, 0xFFFFFFFFU ,0x00000008U), + // .. .. reg_ddrc_mr = 0x930 + // .. .. ==> 0XF8006030[15:0] = 0x00000930U + // .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000930U + // .. .. reg_ddrc_emr = 0x4 + // .. .. ==> 0XF8006030[31:16] = 0x00000004U + // .. .. ==> MASK : 0xFFFF0000U VAL : 0x00040000U + // .. .. + EMIT_MASKWRITE(0XF8006030, 0xFFFFFFFFU ,0x00040930U), + // .. .. reg_ddrc_burst_rdwr = 0x4 + // .. .. ==> 0XF8006034[3:0] = 0x00000004U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000004U + // .. .. reg_ddrc_pre_cke_x1024 = 0x167 + // .. .. ==> 0XF8006034[13:4] = 0x00000167U + // .. .. ==> MASK : 0x00003FF0U VAL : 0x00001670U + // .. .. reg_ddrc_post_cke_x1024 = 0x1 + // .. .. ==> 0XF8006034[25:16] = 0x00000001U + // .. .. ==> MASK : 0x03FF0000U VAL : 0x00010000U + // .. .. reg_ddrc_burstchop = 0x0 + // .. .. ==> 0XF8006034[28:28] = 0x00000000U + // .. .. ==> MASK : 0x10000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006034, 0x13FF3FFFU ,0x00011674U), + // .. .. reg_ddrc_force_low_pri_n = 0x0 + // .. .. ==> 0XF8006038[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_dis_dq = 0x0 + // .. .. ==> 0XF8006038[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_debug_mode = 0x0 + // .. .. ==> 0XF8006038[6:6] = 0x00000000U + // .. .. ==> MASK : 0x00000040U VAL : 0x00000000U + // .. .. reg_phy_wr_level_start = 0x0 + // .. .. ==> 0XF8006038[7:7] = 0x00000000U + // .. .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. .. reg_phy_rd_level_start = 0x0 + // .. .. ==> 0XF8006038[8:8] = 0x00000000U + // .. .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. .. reg_phy_dq0_wait_t = 0x0 + // .. .. ==> 0XF8006038[12:9] = 0x00000000U + // .. .. ==> MASK : 0x00001E00U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006038, 0x00001FC3U ,0x00000000U), + // .. .. reg_ddrc_addrmap_bank_b0 = 0x6 + // .. .. ==> 0XF800603C[3:0] = 0x00000006U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000006U + // .. .. reg_ddrc_addrmap_bank_b1 = 0x6 + // .. .. ==> 0XF800603C[7:4] = 0x00000006U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000060U + // .. .. reg_ddrc_addrmap_bank_b2 = 0x6 + // .. .. ==> 0XF800603C[11:8] = 0x00000006U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000600U + // .. .. reg_ddrc_addrmap_col_b5 = 0x0 + // .. .. ==> 0XF800603C[15:12] = 0x00000000U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b6 = 0x0 + // .. .. ==> 0XF800603C[19:16] = 0x00000000U + // .. .. ==> MASK : 0x000F0000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800603C, 0x000FFFFFU ,0x00000666U), + // .. .. reg_ddrc_addrmap_col_b2 = 0x0 + // .. .. ==> 0XF8006040[3:0] = 0x00000000U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b3 = 0x0 + // .. .. ==> 0XF8006040[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b4 = 0x0 + // .. .. ==> 0XF8006040[11:8] = 0x00000000U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b7 = 0x0 + // .. .. ==> 0XF8006040[15:12] = 0x00000000U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00000000U + // .. .. reg_ddrc_addrmap_col_b8 = 0xf + // .. .. ==> 0XF8006040[19:16] = 0x0000000FU + // .. .. ==> MASK : 0x000F0000U VAL : 0x000F0000U + // .. .. reg_ddrc_addrmap_col_b9 = 0xf + // .. .. ==> 0XF8006040[23:20] = 0x0000000FU + // .. .. ==> MASK : 0x00F00000U VAL : 0x00F00000U + // .. .. reg_ddrc_addrmap_col_b10 = 0xf + // .. .. ==> 0XF8006040[27:24] = 0x0000000FU + // .. .. ==> MASK : 0x0F000000U VAL : 0x0F000000U + // .. .. reg_ddrc_addrmap_col_b11 = 0xf + // .. .. ==> 0XF8006040[31:28] = 0x0000000FU + // .. .. ==> MASK : 0xF0000000U VAL : 0xF0000000U + // .. .. + EMIT_MASKWRITE(0XF8006040, 0xFFFFFFFFU ,0xFFFF0000U), + // .. .. reg_ddrc_addrmap_row_b0 = 0x5 + // .. .. ==> 0XF8006044[3:0] = 0x00000005U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000005U + // .. .. reg_ddrc_addrmap_row_b1 = 0x5 + // .. .. ==> 0XF8006044[7:4] = 0x00000005U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000050U + // .. .. reg_ddrc_addrmap_row_b2_11 = 0x5 + // .. .. ==> 0XF8006044[11:8] = 0x00000005U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000500U + // .. .. reg_ddrc_addrmap_row_b12 = 0x5 + // .. .. ==> 0XF8006044[15:12] = 0x00000005U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00005000U + // .. .. reg_ddrc_addrmap_row_b13 = 0x5 + // .. .. ==> 0XF8006044[19:16] = 0x00000005U + // .. .. ==> MASK : 0x000F0000U VAL : 0x00050000U + // .. .. reg_ddrc_addrmap_row_b14 = 0x5 + // .. .. ==> 0XF8006044[23:20] = 0x00000005U + // .. .. ==> MASK : 0x00F00000U VAL : 0x00500000U + // .. .. reg_ddrc_addrmap_row_b15 = 0xf + // .. .. ==> 0XF8006044[27:24] = 0x0000000FU + // .. .. ==> MASK : 0x0F000000U VAL : 0x0F000000U + // .. .. + EMIT_MASKWRITE(0XF8006044, 0x0FFFFFFFU ,0x0F555555U), + // .. .. reg_ddrc_rank0_rd_odt = 0x0 + // .. .. ==> 0XF8006048[2:0] = 0x00000000U + // .. .. ==> MASK : 0x00000007U VAL : 0x00000000U + // .. .. reg_ddrc_rank0_wr_odt = 0x1 + // .. .. ==> 0XF8006048[5:3] = 0x00000001U + // .. .. ==> MASK : 0x00000038U VAL : 0x00000008U + // .. .. reg_ddrc_rank1_rd_odt = 0x1 + // .. .. ==> 0XF8006048[8:6] = 0x00000001U + // .. .. ==> MASK : 0x000001C0U VAL : 0x00000040U + // .. .. reg_ddrc_rank1_wr_odt = 0x1 + // .. .. ==> 0XF8006048[11:9] = 0x00000001U + // .. .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. .. reg_phy_rd_local_odt = 0x0 + // .. .. ==> 0XF8006048[13:12] = 0x00000000U + // .. .. ==> MASK : 0x00003000U VAL : 0x00000000U + // .. .. reg_phy_wr_local_odt = 0x3 + // .. .. ==> 0XF8006048[15:14] = 0x00000003U + // .. .. ==> MASK : 0x0000C000U VAL : 0x0000C000U + // .. .. reg_phy_idle_local_odt = 0x3 + // .. .. ==> 0XF8006048[17:16] = 0x00000003U + // .. .. ==> MASK : 0x00030000U VAL : 0x00030000U + // .. .. reg_ddrc_rank2_rd_odt = 0x0 + // .. .. ==> 0XF8006048[20:18] = 0x00000000U + // .. .. ==> MASK : 0x001C0000U VAL : 0x00000000U + // .. .. reg_ddrc_rank2_wr_odt = 0x0 + // .. .. ==> 0XF8006048[23:21] = 0x00000000U + // .. .. ==> MASK : 0x00E00000U VAL : 0x00000000U + // .. .. reg_ddrc_rank3_rd_odt = 0x0 + // .. .. ==> 0XF8006048[26:24] = 0x00000000U + // .. .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. .. reg_ddrc_rank3_wr_odt = 0x0 + // .. .. ==> 0XF8006048[29:27] = 0x00000000U + // .. .. ==> MASK : 0x38000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006048, 0x3FFFFFFFU ,0x0003C248U), + // .. .. reg_phy_rd_cmd_to_data = 0x0 + // .. .. ==> 0XF8006050[3:0] = 0x00000000U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000000U + // .. .. reg_phy_wr_cmd_to_data = 0x0 + // .. .. ==> 0XF8006050[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. reg_phy_rdc_we_to_re_delay = 0x8 + // .. .. ==> 0XF8006050[11:8] = 0x00000008U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000800U + // .. .. reg_phy_rdc_fifo_rst_disable = 0x0 + // .. .. ==> 0XF8006050[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. reg_phy_use_fixed_re = 0x1 + // .. .. ==> 0XF8006050[16:16] = 0x00000001U + // .. .. ==> MASK : 0x00010000U VAL : 0x00010000U + // .. .. reg_phy_rdc_fifo_rst_err_cnt_clr = 0x0 + // .. .. ==> 0XF8006050[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_phy_dis_phy_ctrl_rstn = 0x0 + // .. .. ==> 0XF8006050[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_phy_clk_stall_level = 0x0 + // .. .. ==> 0XF8006050[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_num_of_dq0 = 0x7 + // .. .. ==> 0XF8006050[27:24] = 0x00000007U + // .. .. ==> MASK : 0x0F000000U VAL : 0x07000000U + // .. .. reg_phy_wrlvl_num_of_dq0 = 0x7 + // .. .. ==> 0XF8006050[31:28] = 0x00000007U + // .. .. ==> MASK : 0xF0000000U VAL : 0x70000000U + // .. .. + EMIT_MASKWRITE(0XF8006050, 0xFF0F8FFFU ,0x77010800U), + // .. .. reg_ddrc_dll_calib_to_min_x1024 = 0x1 + // .. .. ==> 0XF8006058[7:0] = 0x00000001U + // .. .. ==> MASK : 0x000000FFU VAL : 0x00000001U + // .. .. reg_ddrc_dll_calib_to_max_x1024 = 0x1 + // .. .. ==> 0XF8006058[15:8] = 0x00000001U + // .. .. ==> MASK : 0x0000FF00U VAL : 0x00000100U + // .. .. reg_ddrc_dis_dll_calib = 0x0 + // .. .. ==> 0XF8006058[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006058, 0x0001FFFFU ,0x00000101U), + // .. .. reg_ddrc_rd_odt_delay = 0x3 + // .. .. ==> 0XF800605C[3:0] = 0x00000003U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000003U + // .. .. reg_ddrc_wr_odt_delay = 0x0 + // .. .. ==> 0XF800605C[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. reg_ddrc_rd_odt_hold = 0x0 + // .. .. ==> 0XF800605C[11:8] = 0x00000000U + // .. .. ==> MASK : 0x00000F00U VAL : 0x00000000U + // .. .. reg_ddrc_wr_odt_hold = 0x5 + // .. .. ==> 0XF800605C[15:12] = 0x00000005U + // .. .. ==> MASK : 0x0000F000U VAL : 0x00005000U + // .. .. + EMIT_MASKWRITE(0XF800605C, 0x0000FFFFU ,0x00005003U), + // .. .. reg_ddrc_pageclose = 0x0 + // .. .. ==> 0XF8006060[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_lpr_num_entries = 0x1f + // .. .. ==> 0XF8006060[6:1] = 0x0000001FU + // .. .. ==> MASK : 0x0000007EU VAL : 0x0000003EU + // .. .. reg_ddrc_auto_pre_en = 0x0 + // .. .. ==> 0XF8006060[7:7] = 0x00000000U + // .. .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. .. reg_ddrc_refresh_update_level = 0x0 + // .. .. ==> 0XF8006060[8:8] = 0x00000000U + // .. .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. .. reg_ddrc_dis_wc = 0x0 + // .. .. ==> 0XF8006060[9:9] = 0x00000000U + // .. .. ==> MASK : 0x00000200U VAL : 0x00000000U + // .. .. reg_ddrc_dis_collision_page_opt = 0x0 + // .. .. ==> 0XF8006060[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_ddrc_selfref_en = 0x0 + // .. .. ==> 0XF8006060[12:12] = 0x00000000U + // .. .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006060, 0x000017FFU ,0x0000003EU), + // .. .. reg_ddrc_go2critical_hysteresis = 0x0 + // .. .. ==> 0XF8006064[12:5] = 0x00000000U + // .. .. ==> MASK : 0x00001FE0U VAL : 0x00000000U + // .. .. reg_arb_go2critical_en = 0x1 + // .. .. ==> 0XF8006064[17:17] = 0x00000001U + // .. .. ==> MASK : 0x00020000U VAL : 0x00020000U + // .. .. + EMIT_MASKWRITE(0XF8006064, 0x00021FE0U ,0x00020000U), + // .. .. reg_ddrc_wrlvl_ww = 0x41 + // .. .. ==> 0XF8006068[7:0] = 0x00000041U + // .. .. ==> MASK : 0x000000FFU VAL : 0x00000041U + // .. .. reg_ddrc_rdlvl_rr = 0x41 + // .. .. ==> 0XF8006068[15:8] = 0x00000041U + // .. .. ==> MASK : 0x0000FF00U VAL : 0x00004100U + // .. .. reg_ddrc_dfi_t_wlmrd = 0x28 + // .. .. ==> 0XF8006068[25:16] = 0x00000028U + // .. .. ==> MASK : 0x03FF0000U VAL : 0x00280000U + // .. .. + EMIT_MASKWRITE(0XF8006068, 0x03FFFFFFU ,0x00284141U), + // .. .. dfi_t_ctrlupd_interval_min_x1024 = 0x10 + // .. .. ==> 0XF800606C[7:0] = 0x00000010U + // .. .. ==> MASK : 0x000000FFU VAL : 0x00000010U + // .. .. dfi_t_ctrlupd_interval_max_x1024 = 0x16 + // .. .. ==> 0XF800606C[15:8] = 0x00000016U + // .. .. ==> MASK : 0x0000FF00U VAL : 0x00001600U + // .. .. + EMIT_MASKWRITE(0XF800606C, 0x0000FFFFU ,0x00001610U), + // .. .. refresh_timer0_start_value_x32 = 0x0 + // .. .. ==> 0XF80060A0[11:0] = 0x00000000U + // .. .. ==> MASK : 0x00000FFFU VAL : 0x00000000U + // .. .. refresh_timer1_start_value_x32 = 0x8 + // .. .. ==> 0XF80060A0[23:12] = 0x00000008U + // .. .. ==> MASK : 0x00FFF000U VAL : 0x00008000U + // .. .. + EMIT_MASKWRITE(0XF80060A0, 0x00FFFFFFU ,0x00008000U), + // .. .. reg_ddrc_dis_auto_zq = 0x0 + // .. .. ==> 0XF80060A4[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_ddr3 = 0x1 + // .. .. ==> 0XF80060A4[1:1] = 0x00000001U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. reg_ddrc_t_mod = 0x200 + // .. .. ==> 0XF80060A4[11:2] = 0x00000200U + // .. .. ==> MASK : 0x00000FFCU VAL : 0x00000800U + // .. .. reg_ddrc_t_zq_long_nop = 0x200 + // .. .. ==> 0XF80060A4[21:12] = 0x00000200U + // .. .. ==> MASK : 0x003FF000U VAL : 0x00200000U + // .. .. reg_ddrc_t_zq_short_nop = 0x40 + // .. .. ==> 0XF80060A4[31:22] = 0x00000040U + // .. .. ==> MASK : 0xFFC00000U VAL : 0x10000000U + // .. .. + EMIT_MASKWRITE(0XF80060A4, 0xFFFFFFFFU ,0x10200802U), + // .. .. t_zq_short_interval_x1024 = 0xc845 + // .. .. ==> 0XF80060A8[19:0] = 0x0000C845U + // .. .. ==> MASK : 0x000FFFFFU VAL : 0x0000C845U + // .. .. dram_rstn_x1024 = 0x67 + // .. .. ==> 0XF80060A8[27:20] = 0x00000067U + // .. .. ==> MASK : 0x0FF00000U VAL : 0x06700000U + // .. .. + EMIT_MASKWRITE(0XF80060A8, 0x0FFFFFFFU ,0x0670C845U), + // .. .. deeppowerdown_en = 0x0 + // .. .. ==> 0XF80060AC[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. deeppowerdown_to_x1024 = 0xff + // .. .. ==> 0XF80060AC[8:1] = 0x000000FFU + // .. .. ==> MASK : 0x000001FEU VAL : 0x000001FEU + // .. .. + EMIT_MASKWRITE(0XF80060AC, 0x000001FFU ,0x000001FEU), + // .. .. dfi_wrlvl_max_x1024 = 0xfff + // .. .. ==> 0XF80060B0[11:0] = 0x00000FFFU + // .. .. ==> MASK : 0x00000FFFU VAL : 0x00000FFFU + // .. .. dfi_rdlvl_max_x1024 = 0xfff + // .. .. ==> 0XF80060B0[23:12] = 0x00000FFFU + // .. .. ==> MASK : 0x00FFF000U VAL : 0x00FFF000U + // .. .. ddrc_reg_twrlvl_max_error = 0x0 + // .. .. ==> 0XF80060B0[24:24] = 0x00000000U + // .. .. ==> MASK : 0x01000000U VAL : 0x00000000U + // .. .. ddrc_reg_trdlvl_max_error = 0x0 + // .. .. ==> 0XF80060B0[25:25] = 0x00000000U + // .. .. ==> MASK : 0x02000000U VAL : 0x00000000U + // .. .. reg_ddrc_dfi_wr_level_en = 0x1 + // .. .. ==> 0XF80060B0[26:26] = 0x00000001U + // .. .. ==> MASK : 0x04000000U VAL : 0x04000000U + // .. .. reg_ddrc_dfi_rd_dqs_gate_level = 0x1 + // .. .. ==> 0XF80060B0[27:27] = 0x00000001U + // .. .. ==> MASK : 0x08000000U VAL : 0x08000000U + // .. .. reg_ddrc_dfi_rd_data_eye_train = 0x1 + // .. .. ==> 0XF80060B0[28:28] = 0x00000001U + // .. .. ==> MASK : 0x10000000U VAL : 0x10000000U + // .. .. + EMIT_MASKWRITE(0XF80060B0, 0x1FFFFFFFU ,0x1CFFFFFFU), + // .. .. reg_ddrc_2t_delay = 0x0 + // .. .. ==> 0XF80060B4[8:0] = 0x00000000U + // .. .. ==> MASK : 0x000001FFU VAL : 0x00000000U + // .. .. reg_ddrc_skip_ocd = 0x1 + // .. .. ==> 0XF80060B4[9:9] = 0x00000001U + // .. .. ==> MASK : 0x00000200U VAL : 0x00000200U + // .. .. reg_ddrc_dis_pre_bypass = 0x0 + // .. .. ==> 0XF80060B4[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060B4, 0x000007FFU ,0x00000200U), + // .. .. reg_ddrc_dfi_t_rddata_en = 0x6 + // .. .. ==> 0XF80060B8[4:0] = 0x00000006U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000006U + // .. .. reg_ddrc_dfi_t_ctrlup_min = 0x3 + // .. .. ==> 0XF80060B8[14:5] = 0x00000003U + // .. .. ==> MASK : 0x00007FE0U VAL : 0x00000060U + // .. .. reg_ddrc_dfi_t_ctrlup_max = 0x40 + // .. .. ==> 0XF80060B8[24:15] = 0x00000040U + // .. .. ==> MASK : 0x01FF8000U VAL : 0x00200000U + // .. .. + EMIT_MASKWRITE(0XF80060B8, 0x01FFFFFFU ,0x00200066U), + // .. .. Clear_Uncorrectable_DRAM_ECC_error = 0x0 + // .. .. ==> 0XF80060C4[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. Clear_Correctable_DRAM_ECC_error = 0x0 + // .. .. ==> 0XF80060C4[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060C4, 0x00000003U ,0x00000000U), + // .. .. CORR_ECC_LOG_VALID = 0x0 + // .. .. ==> 0XF80060C8[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. ECC_CORRECTED_BIT_NUM = 0x0 + // .. .. ==> 0XF80060C8[7:1] = 0x00000000U + // .. .. ==> MASK : 0x000000FEU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060C8, 0x000000FFU ,0x00000000U), + // .. .. UNCORR_ECC_LOG_VALID = 0x0 + // .. .. ==> 0XF80060DC[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060DC, 0x00000001U ,0x00000000U), + // .. .. STAT_NUM_CORR_ERR = 0x0 + // .. .. ==> 0XF80060F0[15:8] = 0x00000000U + // .. .. ==> MASK : 0x0000FF00U VAL : 0x00000000U + // .. .. STAT_NUM_UNCORR_ERR = 0x0 + // .. .. ==> 0XF80060F0[7:0] = 0x00000000U + // .. .. ==> MASK : 0x000000FFU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80060F0, 0x0000FFFFU ,0x00000000U), + // .. .. reg_ddrc_ecc_mode = 0x0 + // .. .. ==> 0XF80060F4[2:0] = 0x00000000U + // .. .. ==> MASK : 0x00000007U VAL : 0x00000000U + // .. .. reg_ddrc_dis_scrub = 0x1 + // .. .. ==> 0XF80060F4[3:3] = 0x00000001U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000008U + // .. .. + EMIT_MASKWRITE(0XF80060F4, 0x0000000FU ,0x00000008U), + // .. .. reg_phy_dif_on = 0x0 + // .. .. ==> 0XF8006114[3:0] = 0x00000000U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000000U + // .. .. reg_phy_dif_off = 0x0 + // .. .. ==> 0XF8006114[7:4] = 0x00000000U + // .. .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006114, 0x000000FFU ,0x00000000U), + // .. .. reg_phy_data_slice_in_use = 0x1 + // .. .. ==> 0XF8006118[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006118[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF8006118[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006118[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_tx = 0x0 + // .. .. ==> 0XF8006118[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_rx = 0x0 + // .. .. ==> 0XF8006118[5:5] = 0x00000000U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF8006118[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF8006118[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF8006118[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006118, 0x7FFFFFFFU ,0x40000001U), + // .. .. reg_phy_data_slice_in_use = 0x1 + // .. .. ==> 0XF800611C[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF800611C[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF800611C[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF800611C[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_tx = 0x0 + // .. .. ==> 0XF800611C[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_rx = 0x0 + // .. .. ==> 0XF800611C[5:5] = 0x00000000U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF800611C[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF800611C[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF800611C[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF800611C, 0x7FFFFFFFU ,0x40000001U), + // .. .. reg_phy_data_slice_in_use = 0x0 + // .. .. ==> 0XF8006120[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006120[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_tx = 0x0 + // .. .. ==> 0XF8006120[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_rx = 0x0 + // .. .. ==> 0XF8006120[5:5] = 0x00000000U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF8006120[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF8006120[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF8006120[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006120, 0x7FFFFFFFU ,0x40000000U), + // .. .. reg_phy_data_slice_in_use = 0x0 + // .. .. ==> 0XF8006124[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_phy_rdlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006124[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_gatelvl_inc_mode = 0x0 + // .. .. ==> 0XF8006124[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_wrlvl_inc_mode = 0x0 + // .. .. ==> 0XF8006124[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_tx = 0x0 + // .. .. ==> 0XF8006124[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_board_lpbk_rx = 0x0 + // .. .. ==> 0XF8006124[5:5] = 0x00000000U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. .. reg_phy_bist_shift_dq = 0x0 + // .. .. ==> 0XF8006124[14:6] = 0x00000000U + // .. .. ==> MASK : 0x00007FC0U VAL : 0x00000000U + // .. .. reg_phy_bist_err_clr = 0x0 + // .. .. ==> 0XF8006124[23:15] = 0x00000000U + // .. .. ==> MASK : 0x00FF8000U VAL : 0x00000000U + // .. .. reg_phy_dq_offset = 0x40 + // .. .. ==> 0XF8006124[30:24] = 0x00000040U + // .. .. ==> MASK : 0x7F000000U VAL : 0x40000000U + // .. .. + EMIT_MASKWRITE(0XF8006124, 0x7FFFFFFFU ,0x40000000U), + // .. .. reg_phy_wrlvl_init_ratio = 0x5 + // .. .. ==> 0XF800612C[9:0] = 0x00000005U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000005U + // .. .. reg_phy_gatelvl_init_ratio = 0x9b + // .. .. ==> 0XF800612C[19:10] = 0x0000009BU + // .. .. ==> MASK : 0x000FFC00U VAL : 0x00026C00U + // .. .. + EMIT_MASKWRITE(0XF800612C, 0x000FFFFFU ,0x00026C05U), + // .. .. reg_phy_wrlvl_init_ratio = 0x7 + // .. .. ==> 0XF8006130[9:0] = 0x00000007U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000007U + // .. .. reg_phy_gatelvl_init_ratio = 0x98 + // .. .. ==> 0XF8006130[19:10] = 0x00000098U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x00026000U + // .. .. + EMIT_MASKWRITE(0XF8006130, 0x000FFFFFU ,0x00026007U), + // .. .. reg_phy_wrlvl_init_ratio = 0x0 + // .. .. ==> 0XF8006134[9:0] = 0x00000000U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000000U + // .. .. reg_phy_gatelvl_init_ratio = 0x76 + // .. .. ==> 0XF8006134[19:10] = 0x00000076U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x0001D800U + // .. .. + EMIT_MASKWRITE(0XF8006134, 0x000FFFFFU ,0x0001D800U), + // .. .. reg_phy_wrlvl_init_ratio = 0x0 + // .. .. ==> 0XF8006138[9:0] = 0x00000000U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000000U + // .. .. reg_phy_gatelvl_init_ratio = 0x78 + // .. .. ==> 0XF8006138[19:10] = 0x00000078U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x0001E000U + // .. .. + EMIT_MASKWRITE(0XF8006138, 0x000FFFFFU ,0x0001E000U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF8006140[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006140[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006140[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006140, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF8006144[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006144[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006144[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006144, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF8006148[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006148[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006148[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006148, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_rd_dqs_slave_ratio = 0x35 + // .. .. ==> 0XF800614C[9:0] = 0x00000035U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000035U + // .. .. reg_phy_rd_dqs_slave_force = 0x0 + // .. .. ==> 0XF800614C[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_rd_dqs_slave_delay = 0x0 + // .. .. ==> 0XF800614C[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800614C, 0x000FFFFFU ,0x00000035U), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x85 + // .. .. ==> 0XF8006154[9:0] = 0x00000085U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000085U + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006154[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006154[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006154, 0x000FFFFFU ,0x00000085U), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x87 + // .. .. ==> 0XF8006158[9:0] = 0x00000087U + // .. .. ==> MASK : 0x000003FFU VAL : 0x00000087U + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006158[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006158[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006158, 0x000FFFFFU ,0x00000087U), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x7f + // .. .. ==> 0XF800615C[9:0] = 0x0000007FU + // .. .. ==> MASK : 0x000003FFU VAL : 0x0000007FU + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF800615C[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF800615C[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800615C, 0x000FFFFFU ,0x0000007FU), + // .. .. reg_phy_wr_dqs_slave_ratio = 0x7c + // .. .. ==> 0XF8006160[9:0] = 0x0000007CU + // .. .. ==> MASK : 0x000003FFU VAL : 0x0000007CU + // .. .. reg_phy_wr_dqs_slave_force = 0x0 + // .. .. ==> 0XF8006160[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_dqs_slave_delay = 0x0 + // .. .. ==> 0XF8006160[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006160, 0x000FFFFFU ,0x0000007CU), + // .. .. reg_phy_fifo_we_slave_ratio = 0xf0 + // .. .. ==> 0XF8006168[10:0] = 0x000000F0U + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000F0U + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF8006168[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF8006168[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006168, 0x001FFFFFU ,0x000000F0U), + // .. .. reg_phy_fifo_we_slave_ratio = 0xed + // .. .. ==> 0XF800616C[10:0] = 0x000000EDU + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000EDU + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF800616C[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF800616C[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800616C, 0x001FFFFFU ,0x000000EDU), + // .. .. reg_phy_fifo_we_slave_ratio = 0xcb + // .. .. ==> 0XF8006170[10:0] = 0x000000CBU + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000CBU + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF8006170[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF8006170[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006170, 0x001FFFFFU ,0x000000CBU), + // .. .. reg_phy_fifo_we_slave_ratio = 0xcd + // .. .. ==> 0XF8006174[10:0] = 0x000000CDU + // .. .. ==> MASK : 0x000007FFU VAL : 0x000000CDU + // .. .. reg_phy_fifo_we_in_force = 0x0 + // .. .. ==> 0XF8006174[11:11] = 0x00000000U + // .. .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. .. reg_phy_fifo_we_in_delay = 0x0 + // .. .. ==> 0XF8006174[20:12] = 0x00000000U + // .. .. ==> MASK : 0x001FF000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006174, 0x001FFFFFU ,0x000000CDU), + // .. .. reg_phy_wr_data_slave_ratio = 0xc5 + // .. .. ==> 0XF800617C[9:0] = 0x000000C5U + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000C5U + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF800617C[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF800617C[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800617C, 0x000FFFFFU ,0x000000C5U), + // .. .. reg_phy_wr_data_slave_ratio = 0xc7 + // .. .. ==> 0XF8006180[9:0] = 0x000000C7U + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000C7U + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF8006180[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF8006180[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006180, 0x000FFFFFU ,0x000000C7U), + // .. .. reg_phy_wr_data_slave_ratio = 0xbf + // .. .. ==> 0XF8006184[9:0] = 0x000000BFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000BFU + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF8006184[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF8006184[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006184, 0x000FFFFFU ,0x000000BFU), + // .. .. reg_phy_wr_data_slave_ratio = 0xbc + // .. .. ==> 0XF8006188[9:0] = 0x000000BCU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000000BCU + // .. .. reg_phy_wr_data_slave_force = 0x0 + // .. .. ==> 0XF8006188[10:10] = 0x00000000U + // .. .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. .. reg_phy_wr_data_slave_delay = 0x0 + // .. .. ==> 0XF8006188[19:11] = 0x00000000U + // .. .. ==> MASK : 0x000FF800U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006188, 0x000FFFFFU ,0x000000BCU), + // .. .. reg_phy_loopback = 0x0 + // .. .. ==> 0XF8006190[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_phy_bl2 = 0x0 + // .. .. ==> 0XF8006190[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_phy_at_spd_atpg = 0x0 + // .. .. ==> 0XF8006190[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_phy_bist_enable = 0x0 + // .. .. ==> 0XF8006190[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. reg_phy_bist_force_err = 0x0 + // .. .. ==> 0XF8006190[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. reg_phy_bist_mode = 0x0 + // .. .. ==> 0XF8006190[6:5] = 0x00000000U + // .. .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. .. reg_phy_invert_clkout = 0x1 + // .. .. ==> 0XF8006190[7:7] = 0x00000001U + // .. .. ==> MASK : 0x00000080U VAL : 0x00000080U + // .. .. reg_phy_all_dq_mpr_rd_resp = 0x0 + // .. .. ==> 0XF8006190[8:8] = 0x00000000U + // .. .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. .. reg_phy_sel_logic = 0x0 + // .. .. ==> 0XF8006190[9:9] = 0x00000000U + // .. .. ==> MASK : 0x00000200U VAL : 0x00000000U + // .. .. reg_phy_ctrl_slave_ratio = 0x100 + // .. .. ==> 0XF8006190[19:10] = 0x00000100U + // .. .. ==> MASK : 0x000FFC00U VAL : 0x00040000U + // .. .. reg_phy_ctrl_slave_force = 0x0 + // .. .. ==> 0XF8006190[20:20] = 0x00000000U + // .. .. ==> MASK : 0x00100000U VAL : 0x00000000U + // .. .. reg_phy_ctrl_slave_delay = 0x0 + // .. .. ==> 0XF8006190[27:21] = 0x00000000U + // .. .. ==> MASK : 0x0FE00000U VAL : 0x00000000U + // .. .. reg_phy_use_rank0_delays = 0x1 + // .. .. ==> 0XF8006190[28:28] = 0x00000001U + // .. .. ==> MASK : 0x10000000U VAL : 0x10000000U + // .. .. reg_phy_lpddr = 0x0 + // .. .. ==> 0XF8006190[29:29] = 0x00000000U + // .. .. ==> MASK : 0x20000000U VAL : 0x00000000U + // .. .. reg_phy_cmd_latency = 0x0 + // .. .. ==> 0XF8006190[30:30] = 0x00000000U + // .. .. ==> MASK : 0x40000000U VAL : 0x00000000U + // .. .. reg_phy_int_lpbk = 0x0 + // .. .. ==> 0XF8006190[31:31] = 0x00000000U + // .. .. ==> MASK : 0x80000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006190, 0xFFFFFFFFU ,0x10040080U), + // .. .. reg_phy_wr_rl_delay = 0x2 + // .. .. ==> 0XF8006194[4:0] = 0x00000002U + // .. .. ==> MASK : 0x0000001FU VAL : 0x00000002U + // .. .. reg_phy_rd_rl_delay = 0x4 + // .. .. ==> 0XF8006194[9:5] = 0x00000004U + // .. .. ==> MASK : 0x000003E0U VAL : 0x00000080U + // .. .. reg_phy_dll_lock_diff = 0xf + // .. .. ==> 0XF8006194[13:10] = 0x0000000FU + // .. .. ==> MASK : 0x00003C00U VAL : 0x00003C00U + // .. .. reg_phy_use_wr_level = 0x1 + // .. .. ==> 0XF8006194[14:14] = 0x00000001U + // .. .. ==> MASK : 0x00004000U VAL : 0x00004000U + // .. .. reg_phy_use_rd_dqs_gate_level = 0x1 + // .. .. ==> 0XF8006194[15:15] = 0x00000001U + // .. .. ==> MASK : 0x00008000U VAL : 0x00008000U + // .. .. reg_phy_use_rd_data_eye_level = 0x1 + // .. .. ==> 0XF8006194[16:16] = 0x00000001U + // .. .. ==> MASK : 0x00010000U VAL : 0x00010000U + // .. .. reg_phy_dis_calib_rst = 0x0 + // .. .. ==> 0XF8006194[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_phy_ctrl_slave_delay = 0x0 + // .. .. ==> 0XF8006194[19:18] = 0x00000000U + // .. .. ==> MASK : 0x000C0000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006194, 0x000FFFFFU ,0x0001FC82U), + // .. .. reg_arb_page_addr_mask = 0x0 + // .. .. ==> 0XF8006204[31:0] = 0x00000000U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006204, 0xFFFFFFFFU ,0x00000000U), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF8006208[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF8006208[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF8006208[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF8006208[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_dis_rmw_portn = 0x1 + // .. .. ==> 0XF8006208[19:19] = 0x00000001U + // .. .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. .. + EMIT_MASKWRITE(0XF8006208, 0x000F03FFU ,0x000803FFU), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF800620C[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF800620C[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF800620C[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF800620C[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_dis_rmw_portn = 0x1 + // .. .. ==> 0XF800620C[19:19] = 0x00000001U + // .. .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. .. + EMIT_MASKWRITE(0XF800620C, 0x000F03FFU ,0x000803FFU), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF8006210[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF8006210[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF8006210[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF8006210[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_dis_rmw_portn = 0x1 + // .. .. ==> 0XF8006210[19:19] = 0x00000001U + // .. .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. .. + EMIT_MASKWRITE(0XF8006210, 0x000F03FFU ,0x000803FFU), + // .. .. reg_arb_pri_wr_portn = 0x3ff + // .. .. ==> 0XF8006214[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_wr_portn = 0x0 + // .. .. ==> 0XF8006214[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_wr_portn = 0x0 + // .. .. ==> 0XF8006214[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_wr_portn = 0x0 + // .. .. ==> 0XF8006214[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_dis_rmw_portn = 0x1 + // .. .. ==> 0XF8006214[19:19] = 0x00000001U + // .. .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. .. + EMIT_MASKWRITE(0XF8006214, 0x000F03FFU ,0x000803FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF8006218[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF8006218[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF8006218[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF8006218[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF8006218[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006218, 0x000F03FFU ,0x000003FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF800621C[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF800621C[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF800621C[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF800621C[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF800621C[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF800621C, 0x000F03FFU ,0x000003FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF8006220[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF8006220[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF8006220[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF8006220[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF8006220[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006220, 0x000F03FFU ,0x000003FFU), + // .. .. reg_arb_pri_rd_portn = 0x3ff + // .. .. ==> 0XF8006224[9:0] = 0x000003FFU + // .. .. ==> MASK : 0x000003FFU VAL : 0x000003FFU + // .. .. reg_arb_disable_aging_rd_portn = 0x0 + // .. .. ==> 0XF8006224[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. reg_arb_disable_urgent_rd_portn = 0x0 + // .. .. ==> 0XF8006224[17:17] = 0x00000000U + // .. .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. .. reg_arb_dis_page_match_rd_portn = 0x0 + // .. .. ==> 0XF8006224[18:18] = 0x00000000U + // .. .. ==> MASK : 0x00040000U VAL : 0x00000000U + // .. .. reg_arb_set_hpr_rd_portn = 0x0 + // .. .. ==> 0XF8006224[19:19] = 0x00000000U + // .. .. ==> MASK : 0x00080000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006224, 0x000F03FFU ,0x000003FFU), + // .. .. reg_ddrc_lpddr2 = 0x0 + // .. .. ==> 0XF80062A8[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. reg_ddrc_per_bank_refresh = 0x0 + // .. .. ==> 0XF80062A8[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_ddrc_derate_enable = 0x0 + // .. .. ==> 0XF80062A8[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. reg_ddrc_mr4_margin = 0x0 + // .. .. ==> 0XF80062A8[11:4] = 0x00000000U + // .. .. ==> MASK : 0x00000FF0U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80062A8, 0x00000FF7U ,0x00000000U), + // .. .. reg_ddrc_mr4_read_interval = 0x0 + // .. .. ==> 0XF80062AC[31:0] = 0x00000000U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF80062AC, 0xFFFFFFFFU ,0x00000000U), + // .. .. reg_ddrc_min_stable_clock_x1 = 0x5 + // .. .. ==> 0XF80062B0[3:0] = 0x00000005U + // .. .. ==> MASK : 0x0000000FU VAL : 0x00000005U + // .. .. reg_ddrc_idle_after_reset_x32 = 0x12 + // .. .. ==> 0XF80062B0[11:4] = 0x00000012U + // .. .. ==> MASK : 0x00000FF0U VAL : 0x00000120U + // .. .. reg_ddrc_t_mrw = 0x5 + // .. .. ==> 0XF80062B0[21:12] = 0x00000005U + // .. .. ==> MASK : 0x003FF000U VAL : 0x00005000U + // .. .. + EMIT_MASKWRITE(0XF80062B0, 0x003FFFFFU ,0x00005125U), + // .. .. reg_ddrc_max_auto_init_x1024 = 0xa6 + // .. .. ==> 0XF80062B4[7:0] = 0x000000A6U + // .. .. ==> MASK : 0x000000FFU VAL : 0x000000A6U + // .. .. reg_ddrc_dev_zqinit_x32 = 0x12 + // .. .. ==> 0XF80062B4[17:8] = 0x00000012U + // .. .. ==> MASK : 0x0003FF00U VAL : 0x00001200U + // .. .. + EMIT_MASKWRITE(0XF80062B4, 0x0003FFFFU ,0x000012A6U), + // .. .. START: POLL ON DCI STATUS + // .. .. DONE = 1 + // .. .. ==> 0XF8000B74[13:13] = 0x00000001U + // .. .. ==> MASK : 0x00002000U VAL : 0x00002000U + // .. .. + EMIT_MASKPOLL(0XF8000B74, 0x00002000U), + // .. .. FINISH: POLL ON DCI STATUS + // .. .. START: UNLOCK DDR + // .. .. reg_ddrc_soft_rstb = 0x1 + // .. .. ==> 0XF8006000[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. reg_ddrc_powerdown_en = 0x0 + // .. .. ==> 0XF8006000[1:1] = 0x00000000U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. .. reg_ddrc_data_bus_width = 0x1 + // .. .. ==> 0XF8006000[3:2] = 0x00000001U + // .. .. ==> MASK : 0x0000000CU VAL : 0x00000004U + // .. .. reg_ddrc_burst8_refresh = 0x0 + // .. .. ==> 0XF8006000[6:4] = 0x00000000U + // .. .. ==> MASK : 0x00000070U VAL : 0x00000000U + // .. .. reg_ddrc_rdwr_idle_gap = 1 + // .. .. ==> 0XF8006000[13:7] = 0x00000001U + // .. .. ==> MASK : 0x00003F80U VAL : 0x00000080U + // .. .. reg_ddrc_dis_rd_bypass = 0x0 + // .. .. ==> 0XF8006000[14:14] = 0x00000000U + // .. .. ==> MASK : 0x00004000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_act_bypass = 0x0 + // .. .. ==> 0XF8006000[15:15] = 0x00000000U + // .. .. ==> MASK : 0x00008000U VAL : 0x00000000U + // .. .. reg_ddrc_dis_auto_refresh = 0x0 + // .. .. ==> 0XF8006000[16:16] = 0x00000000U + // .. .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8006000, 0x0001FFFFU ,0x00000085U), + // .. .. FINISH: UNLOCK DDR + // .. .. START: CHECK DDR STATUS + // .. .. ddrc_reg_operating_mode = 1 + // .. .. ==> 0XF8006054[2:0] = 0x00000001U + // .. .. ==> MASK : 0x00000007U VAL : 0x00000001U + // .. .. + EMIT_MASKPOLL(0XF8006054, 0x00000007U), + // .. .. FINISH: CHECK DDR STATUS + // .. FINISH: DDR INITIALIZATION + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_mio_init_data_1_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: OCM REMAPPING + // .. FINISH: OCM REMAPPING + // .. START: DDRIOB SETTINGS + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B40[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B40[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B40[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B40[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCR_TYPE = 0x0 + // .. ==> 0XF8000B40[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B40[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B40[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B40[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B40[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B40, 0x00000FFFU ,0x00000600U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B44[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B44[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B44[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B44[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCR_TYPE = 0x0 + // .. ==> 0XF8000B44[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B44[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B44[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B44[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B44[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B44, 0x00000FFFU ,0x00000600U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B48[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x1 + // .. ==> 0XF8000B48[2:1] = 0x00000001U + // .. ==> MASK : 0x00000006U VAL : 0x00000002U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B48[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x1 + // .. ==> 0XF8000B48[4:4] = 0x00000001U + // .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. DCR_TYPE = 0x3 + // .. ==> 0XF8000B48[6:5] = 0x00000003U + // .. ==> MASK : 0x00000060U VAL : 0x00000060U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B48[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B48[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B48[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B48[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B48, 0x00000FFFU ,0x00000672U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B4C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B4C[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B4C[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B4C[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCR_TYPE = 0x0 + // .. ==> 0XF8000B4C[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B4C[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B4C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x0 + // .. ==> 0XF8000B4C[10:9] = 0x00000000U + // .. ==> MASK : 0x00000600U VAL : 0x00000000U + // .. PULLUP_EN = 0x1 + // .. ==> 0XF8000B4C[11:11] = 0x00000001U + // .. ==> MASK : 0x00000800U VAL : 0x00000800U + // .. + EMIT_MASKWRITE(0XF8000B4C, 0x00000FFFU ,0x00000800U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B50[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x2 + // .. ==> 0XF8000B50[2:1] = 0x00000002U + // .. ==> MASK : 0x00000006U VAL : 0x00000004U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B50[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x1 + // .. ==> 0XF8000B50[4:4] = 0x00000001U + // .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. DCR_TYPE = 0x3 + // .. ==> 0XF8000B50[6:5] = 0x00000003U + // .. ==> MASK : 0x00000060U VAL : 0x00000060U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B50[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B50[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B50[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B50[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B50, 0x00000FFFU ,0x00000674U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B54[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B54[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B54[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B54[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCR_TYPE = 0x0 + // .. ==> 0XF8000B54[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0 + // .. ==> 0XF8000B54[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0 + // .. ==> 0XF8000B54[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x0 + // .. ==> 0XF8000B54[10:9] = 0x00000000U + // .. ==> MASK : 0x00000600U VAL : 0x00000000U + // .. PULLUP_EN = 0x1 + // .. ==> 0XF8000B54[11:11] = 0x00000001U + // .. ==> MASK : 0x00000800U VAL : 0x00000800U + // .. + EMIT_MASKWRITE(0XF8000B54, 0x00000FFFU ,0x00000800U), + // .. INP_POWER = 0x0 + // .. ==> 0XF8000B58[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. INP_TYPE = 0x0 + // .. ==> 0XF8000B58[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. DCI_UPDATE = 0x0 + // .. ==> 0XF8000B58[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. TERM_EN = 0x0 + // .. ==> 0XF8000B58[4:4] = 0x00000000U + // .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. DCR_TYPE = 0x0 + // .. ==> 0XF8000B58[6:5] = 0x00000000U + // .. ==> MASK : 0x00000060U VAL : 0x00000000U + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B58[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B58[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. OUTPUT_EN = 0x3 + // .. ==> 0XF8000B58[10:9] = 0x00000003U + // .. ==> MASK : 0x00000600U VAL : 0x00000600U + // .. PULLUP_EN = 0x0 + // .. ==> 0XF8000B58[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B58, 0x00000FFFU ,0x00000600U), + // .. DRIVE_P = 0x1c + // .. ==> 0XF8000B5C[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. DRIVE_N = 0xc + // .. ==> 0XF8000B5C[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. SLEW_P = 0x3 + // .. ==> 0XF8000B5C[18:14] = 0x00000003U + // .. ==> MASK : 0x0007C000U VAL : 0x0000C000U + // .. SLEW_N = 0x3 + // .. ==> 0XF8000B5C[23:19] = 0x00000003U + // .. ==> MASK : 0x00F80000U VAL : 0x00180000U + // .. GTL = 0x0 + // .. ==> 0XF8000B5C[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. RTERM = 0x0 + // .. ==> 0XF8000B5C[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B5C, 0xFFFFFFFFU ,0x0018C61CU), + // .. DRIVE_P = 0x1c + // .. ==> 0XF8000B60[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. DRIVE_N = 0xc + // .. ==> 0XF8000B60[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. SLEW_P = 0x6 + // .. ==> 0XF8000B60[18:14] = 0x00000006U + // .. ==> MASK : 0x0007C000U VAL : 0x00018000U + // .. SLEW_N = 0x1f + // .. ==> 0XF8000B60[23:19] = 0x0000001FU + // .. ==> MASK : 0x00F80000U VAL : 0x00F80000U + // .. GTL = 0x0 + // .. ==> 0XF8000B60[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. RTERM = 0x0 + // .. ==> 0XF8000B60[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B60, 0xFFFFFFFFU ,0x00F9861CU), + // .. DRIVE_P = 0x1c + // .. ==> 0XF8000B64[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. DRIVE_N = 0xc + // .. ==> 0XF8000B64[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. SLEW_P = 0x6 + // .. ==> 0XF8000B64[18:14] = 0x00000006U + // .. ==> MASK : 0x0007C000U VAL : 0x00018000U + // .. SLEW_N = 0x1f + // .. ==> 0XF8000B64[23:19] = 0x0000001FU + // .. ==> MASK : 0x00F80000U VAL : 0x00F80000U + // .. GTL = 0x0 + // .. ==> 0XF8000B64[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. RTERM = 0x0 + // .. ==> 0XF8000B64[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B64, 0xFFFFFFFFU ,0x00F9861CU), + // .. DRIVE_P = 0x1c + // .. ==> 0XF8000B68[6:0] = 0x0000001CU + // .. ==> MASK : 0x0000007FU VAL : 0x0000001CU + // .. DRIVE_N = 0xc + // .. ==> 0XF8000B68[13:7] = 0x0000000CU + // .. ==> MASK : 0x00003F80U VAL : 0x00000600U + // .. SLEW_P = 0x6 + // .. ==> 0XF8000B68[18:14] = 0x00000006U + // .. ==> MASK : 0x0007C000U VAL : 0x00018000U + // .. SLEW_N = 0x1f + // .. ==> 0XF8000B68[23:19] = 0x0000001FU + // .. ==> MASK : 0x00F80000U VAL : 0x00F80000U + // .. GTL = 0x0 + // .. ==> 0XF8000B68[26:24] = 0x00000000U + // .. ==> MASK : 0x07000000U VAL : 0x00000000U + // .. RTERM = 0x0 + // .. ==> 0XF8000B68[31:27] = 0x00000000U + // .. ==> MASK : 0xF8000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B68, 0xFFFFFFFFU ,0x00F9861CU), + // .. VREF_INT_EN = 0x0 + // .. ==> 0XF8000B6C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. VREF_SEL = 0x0 + // .. ==> 0XF8000B6C[4:1] = 0x00000000U + // .. ==> MASK : 0x0000001EU VAL : 0x00000000U + // .. VREF_EXT_EN = 0x1 + // .. ==> 0XF8000B6C[6:5] = 0x00000001U + // .. ==> MASK : 0x00000060U VAL : 0x00000020U + // .. VREF_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[8:7] = 0x00000000U + // .. ==> MASK : 0x00000180U VAL : 0x00000000U + // .. REFIO_EN = 0x1 + // .. ==> 0XF8000B6C[9:9] = 0x00000001U + // .. ==> MASK : 0x00000200U VAL : 0x00000200U + // .. REFIO_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DRST_B_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. CKE_PULLUP_EN = 0x0 + // .. ==> 0XF8000B6C[14:14] = 0x00000000U + // .. ==> MASK : 0x00004000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B6C, 0x000073FFU ,0x00000220U), + // .. .. START: ASSERT RESET + // .. .. RESET = 1 + // .. .. ==> 0XF8000B70[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. VRN_OUT = 0x1 + // .. .. ==> 0XF8000B70[5:5] = 0x00000001U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000020U + // .. .. + EMIT_MASKWRITE(0XF8000B70, 0x00000021U ,0x00000021U), + // .. .. FINISH: ASSERT RESET + // .. .. START: DEASSERT RESET + // .. .. RESET = 0 + // .. .. ==> 0XF8000B70[0:0] = 0x00000000U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. .. VRN_OUT = 0x1 + // .. .. ==> 0XF8000B70[5:5] = 0x00000001U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000020U + // .. .. + EMIT_MASKWRITE(0XF8000B70, 0x00000021U ,0x00000020U), + // .. .. FINISH: DEASSERT RESET + // .. .. RESET = 0x1 + // .. .. ==> 0XF8000B70[0:0] = 0x00000001U + // .. .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. .. ENABLE = 0x1 + // .. .. ==> 0XF8000B70[1:1] = 0x00000001U + // .. .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. .. VRP_TRI = 0x0 + // .. .. ==> 0XF8000B70[2:2] = 0x00000000U + // .. .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. .. VRN_TRI = 0x0 + // .. .. ==> 0XF8000B70[3:3] = 0x00000000U + // .. .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. .. VRP_OUT = 0x0 + // .. .. ==> 0XF8000B70[4:4] = 0x00000000U + // .. .. ==> MASK : 0x00000010U VAL : 0x00000000U + // .. .. VRN_OUT = 0x1 + // .. .. ==> 0XF8000B70[5:5] = 0x00000001U + // .. .. ==> MASK : 0x00000020U VAL : 0x00000020U + // .. .. NREF_OPT1 = 0x0 + // .. .. ==> 0XF8000B70[7:6] = 0x00000000U + // .. .. ==> MASK : 0x000000C0U VAL : 0x00000000U + // .. .. NREF_OPT2 = 0x0 + // .. .. ==> 0XF8000B70[10:8] = 0x00000000U + // .. .. ==> MASK : 0x00000700U VAL : 0x00000000U + // .. .. NREF_OPT4 = 0x1 + // .. .. ==> 0XF8000B70[13:11] = 0x00000001U + // .. .. ==> MASK : 0x00003800U VAL : 0x00000800U + // .. .. PREF_OPT1 = 0x0 + // .. .. ==> 0XF8000B70[16:14] = 0x00000000U + // .. .. ==> MASK : 0x0001C000U VAL : 0x00000000U + // .. .. PREF_OPT2 = 0x0 + // .. .. ==> 0XF8000B70[19:17] = 0x00000000U + // .. .. ==> MASK : 0x000E0000U VAL : 0x00000000U + // .. .. UPDATE_CONTROL = 0x0 + // .. .. ==> 0XF8000B70[20:20] = 0x00000000U + // .. .. ==> MASK : 0x00100000U VAL : 0x00000000U + // .. .. INIT_COMPLETE = 0x0 + // .. .. ==> 0XF8000B70[21:21] = 0x00000000U + // .. .. ==> MASK : 0x00200000U VAL : 0x00000000U + // .. .. TST_CLK = 0x0 + // .. .. ==> 0XF8000B70[22:22] = 0x00000000U + // .. .. ==> MASK : 0x00400000U VAL : 0x00000000U + // .. .. TST_HLN = 0x0 + // .. .. ==> 0XF8000B70[23:23] = 0x00000000U + // .. .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. .. TST_HLP = 0x0 + // .. .. ==> 0XF8000B70[24:24] = 0x00000000U + // .. .. ==> MASK : 0x01000000U VAL : 0x00000000U + // .. .. TST_RST = 0x0 + // .. .. ==> 0XF8000B70[25:25] = 0x00000000U + // .. .. ==> MASK : 0x02000000U VAL : 0x00000000U + // .. .. INT_DCI_EN = 0x0 + // .. .. ==> 0XF8000B70[26:26] = 0x00000000U + // .. .. ==> MASK : 0x04000000U VAL : 0x00000000U + // .. .. + EMIT_MASKWRITE(0XF8000B70, 0x07FFFFFFU ,0x00000823U), + // .. FINISH: DDRIOB SETTINGS + // .. START: MIO PROGRAMMING + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000700[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000700[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000700[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000700[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000700[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000700[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000700[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000700[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000700[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000700, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000704[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000704[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000704[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000704[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000704[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000704[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000704[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000704[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000704[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000704, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000708[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000708[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000708[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000708[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000708[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000708[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000708[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000708[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000708[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000708, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800070C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800070C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800070C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800070C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800070C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800070C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800070C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF800070C[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF800070C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800070C, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000710[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000710[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000710[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000710[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000710[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000710[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000710[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000710[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000710[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000710, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000714[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000714[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000714[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000714[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000714[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000714[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000714[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000714[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000714[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000714, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000718[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000718[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000718[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000718[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000718[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000718[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000718[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000718[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000718[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000718, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800071C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800071C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800071C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800071C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800071C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800071C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800071C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF800071C[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF800071C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800071C, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000720[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000720[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000720[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000720[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000720[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000720[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000720[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 0 + // .. ==> 0XF8000720[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000720[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000720, 0x00003FFFU ,0x00000600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000724[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000724[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000724[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000724[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000724[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000724[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000724[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000724[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000724[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000724, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000728[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000728[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000728[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000728[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000728[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000728[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000728[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000728[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000728[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000728, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800072C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800072C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800072C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800072C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800072C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800072C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800072C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF800072C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800072C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800072C, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000730[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000730[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000730[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000730[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000730[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000730[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000730[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000730[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000730[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000730, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000734[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000734[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000734[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000734[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000734[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000734[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000734[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000734[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000734[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000734, 0x00003FFFU ,0x00001600U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000738[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF8000738[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF8000738[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000738[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 7 + // .. ==> 0XF8000738[7:5] = 0x00000007U + // .. ==> MASK : 0x000000E0U VAL : 0x000000E0U + // .. Speed = 0 + // .. ==> 0XF8000738[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF8000738[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF8000738[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000738[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000738, 0x00003FFFU ,0x000016E1U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800073C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800073C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF800073C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800073C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 7 + // .. ==> 0XF800073C[7:5] = 0x00000007U + // .. ==> MASK : 0x000000E0U VAL : 0x000000E0U + // .. Speed = 0 + // .. ==> 0XF800073C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 3 + // .. ==> 0XF800073C[11:9] = 0x00000003U + // .. ==> MASK : 0x00000E00U VAL : 0x00000600U + // .. PULLUP = 1 + // .. ==> 0XF800073C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800073C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800073C, 0x00003FFFU ,0x000016E0U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000740[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000740[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000740[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000740[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000740[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000740[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000740[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000740[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000740[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000740, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000744[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000744[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000744[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000744[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000744[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000744[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000744[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000744[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000744[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000744, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000748[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000748[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000748[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000748[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000748[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000748[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000748[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000748[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000748[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000748, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800074C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF800074C[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF800074C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800074C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800074C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800074C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800074C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800074C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800074C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800074C, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000750[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000750[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000750[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000750[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000750[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000750[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000750[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000750[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000750[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000750, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000754[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 1 + // .. ==> 0XF8000754[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000754[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000754[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000754[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000754[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000754[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000754[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000754[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000754, 0x00003FFFU ,0x00001202U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000758[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000758[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000758[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000758[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000758[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000758[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000758[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000758[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000758[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000758, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF800075C[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF800075C[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF800075C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800075C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800075C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800075C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800075C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800075C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800075C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800075C, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000760[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000760[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000760[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000760[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000760[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000760[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000760[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000760[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000760[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000760, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000764[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000764[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000764[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000764[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000764[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000764[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000764[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000764[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000764[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000764, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000768[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF8000768[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF8000768[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF8000768[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000768[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000768[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000768[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000768[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000768[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000768, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF800076C[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 1 + // .. ==> 0XF800076C[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. L1_SEL = 0 + // .. ==> 0XF800076C[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF800076C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800076C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800076C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800076C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800076C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800076C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800076C, 0x00003FFFU ,0x00001203U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000770[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000770[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000770[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000770[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000770[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000770[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000770[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000770[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000770[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000770, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000774[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF8000774[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000774[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000774[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000774[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000774[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000774[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000774[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000774[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000774, 0x00003FFFU ,0x00001205U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000778[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000778[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000778[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000778[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000778[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000778[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000778[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000778[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000778[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000778, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF800077C[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF800077C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF800077C[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF800077C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800077C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800077C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800077C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800077C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800077C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800077C, 0x00003FFFU ,0x00001205U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000780[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000780[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000780[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000780[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000780[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000780[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000780[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000780[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000780[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000780, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000784[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000784[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000784[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000784[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000784[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000784[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000784[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000784[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000784[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000784, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000788[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000788[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000788[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000788[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000788[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000788[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000788[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000788[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000788[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000788, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800078C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800078C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF800078C[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF800078C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800078C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800078C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800078C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800078C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800078C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800078C, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF8000790[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. L0_SEL = 0 + // .. ==> 0XF8000790[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000790[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000790[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000790[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000790[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000790[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000790[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000790[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000790, 0x00003FFFU ,0x00001205U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000794[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000794[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000794[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000794[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000794[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000794[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000794[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000794[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000794[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000794, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF8000798[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF8000798[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF8000798[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF8000798[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF8000798[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF8000798[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF8000798[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF8000798[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF8000798[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000798, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF800079C[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF800079C[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 1 + // .. ==> 0XF800079C[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. L2_SEL = 0 + // .. ==> 0XF800079C[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF800079C[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF800079C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF800079C[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF800079C[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF800079C[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF800079C, 0x00003FFFU ,0x00001204U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007A0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007A0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007A0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007A0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007A0[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007A0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007A0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007A0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007A0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007A0, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007A4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007A4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007A4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007A4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007A4[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007A4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007A4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007A4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007A4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007A4, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007A8[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007A8[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007A8[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007A8[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007A8[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007A8[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007A8[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007A8[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007A8[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007A8, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007AC[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007AC[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007AC[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007AC[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007AC[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007AC[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007AC[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007AC[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007AC[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007AC, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007B0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007B0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007B0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007B0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007B0[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007B0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007B0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007B0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007B0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007B0, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007B4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007B4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007B4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007B4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007B4[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007B4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007B4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007B4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007B4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007B4, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007B8[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007B8[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007B8[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007B8[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007B8[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007B8[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007B8[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007B8[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007B8[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007B8, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 1 + // .. ==> 0XF80007BC[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. Speed = 0 + // .. ==> 0XF80007BC[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007BC[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007BC[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007BC[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007BC, 0x00003F01U ,0x00001201U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007C0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007C0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007C0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007C0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007C0[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007C0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007C0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007C0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007C0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007C0, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007C4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007C4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007C4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007C4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007C4[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007C4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007C4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007C4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007C4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007C4, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007C8[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007C8[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007C8[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007C8[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007C8[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007C8[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007C8[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007C8[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007C8[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007C8, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007CC[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007CC[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007CC[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007CC[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 0 + // .. ==> 0XF80007CC[7:5] = 0x00000000U + // .. ==> MASK : 0x000000E0U VAL : 0x00000000U + // .. Speed = 0 + // .. ==> 0XF80007CC[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007CC[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007CC[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007CC[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007CC, 0x00003FFFU ,0x00001200U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007D0[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007D0[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007D0[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007D0[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007D0[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007D0[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007D0[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007D0[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007D0[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007D0, 0x00003FFFU ,0x00001280U), + // .. TRI_ENABLE = 0 + // .. ==> 0XF80007D4[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. L0_SEL = 0 + // .. ==> 0XF80007D4[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. L1_SEL = 0 + // .. ==> 0XF80007D4[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. L2_SEL = 0 + // .. ==> 0XF80007D4[4:3] = 0x00000000U + // .. ==> MASK : 0x00000018U VAL : 0x00000000U + // .. L3_SEL = 4 + // .. ==> 0XF80007D4[7:5] = 0x00000004U + // .. ==> MASK : 0x000000E0U VAL : 0x00000080U + // .. Speed = 0 + // .. ==> 0XF80007D4[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. IO_Type = 1 + // .. ==> 0XF80007D4[11:9] = 0x00000001U + // .. ==> MASK : 0x00000E00U VAL : 0x00000200U + // .. PULLUP = 1 + // .. ==> 0XF80007D4[12:12] = 0x00000001U + // .. ==> MASK : 0x00001000U VAL : 0x00001000U + // .. DisableRcvr = 0 + // .. ==> 0XF80007D4[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF80007D4, 0x00003FFFU ,0x00001280U), + // .. SDIO0_WP_SEL = 55 + // .. ==> 0XF8000830[5:0] = 0x00000037U + // .. ==> MASK : 0x0000003FU VAL : 0x00000037U + // .. SDIO0_CD_SEL = 47 + // .. ==> 0XF8000830[21:16] = 0x0000002FU + // .. ==> MASK : 0x003F0000U VAL : 0x002F0000U + // .. + EMIT_MASKWRITE(0XF8000830, 0x003F003FU ,0x002F0037U), + // .. FINISH: MIO PROGRAMMING + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_peripherals_init_data_1_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: DDR TERM/IBUF_DISABLE_MODE SETTINGS + // .. IBUF_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B48[7:7] = 0x00000001U + // .. ==> MASK : 0x00000080U VAL : 0x00000080U + // .. TERM_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B48[8:8] = 0x00000001U + // .. ==> MASK : 0x00000100U VAL : 0x00000100U + // .. + EMIT_MASKWRITE(0XF8000B48, 0x00000180U ,0x00000180U), + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B4C[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B4C[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B4C, 0x00000180U ,0x00000000U), + // .. IBUF_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B50[7:7] = 0x00000001U + // .. ==> MASK : 0x00000080U VAL : 0x00000080U + // .. TERM_DISABLE_MODE = 0x1 + // .. ==> 0XF8000B50[8:8] = 0x00000001U + // .. ==> MASK : 0x00000100U VAL : 0x00000100U + // .. + EMIT_MASKWRITE(0XF8000B50, 0x00000180U ,0x00000180U), + // .. IBUF_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B54[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. TERM_DISABLE_MODE = 0x0 + // .. ==> 0XF8000B54[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000B54, 0x00000180U ,0x00000000U), + // .. FINISH: DDR TERM/IBUF_DISABLE_MODE SETTINGS + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // .. START: SRAM/NOR SET OPMODE + // .. FINISH: SRAM/NOR SET OPMODE + // .. START: UART REGISTERS + // .. BDIV = 0x5 + // .. ==> 0XE0000034[7:0] = 0x00000005U + // .. ==> MASK : 0x000000FFU VAL : 0x00000005U + // .. + EMIT_MASKWRITE(0XE0000034, 0x000000FFU ,0x00000006U), + // .. CD = 0x12 + // .. ==> 0XE0000018[15:0] = 0x00000012U + // .. ==> MASK : 0x0000FFFFU VAL : 0x00000012U + // .. + EMIT_MASKWRITE(0XE0000018, 0x0000FFFFU ,0x0000007CU), + // .. STPBRK = 0x0 + // .. ==> 0XE0000000[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. STTBRK = 0x0 + // .. ==> 0XE0000000[7:7] = 0x00000000U + // .. ==> MASK : 0x00000080U VAL : 0x00000000U + // .. RSTTO = 0x0 + // .. ==> 0XE0000000[6:6] = 0x00000000U + // .. ==> MASK : 0x00000040U VAL : 0x00000000U + // .. TXDIS = 0x0 + // .. ==> 0XE0000000[5:5] = 0x00000000U + // .. ==> MASK : 0x00000020U VAL : 0x00000000U + // .. TXEN = 0x1 + // .. ==> 0XE0000000[4:4] = 0x00000001U + // .. ==> MASK : 0x00000010U VAL : 0x00000010U + // .. RXDIS = 0x0 + // .. ==> 0XE0000000[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. RXEN = 0x1 + // .. ==> 0XE0000000[2:2] = 0x00000001U + // .. ==> MASK : 0x00000004U VAL : 0x00000004U + // .. TXRES = 0x1 + // .. ==> 0XE0000000[1:1] = 0x00000001U + // .. ==> MASK : 0x00000002U VAL : 0x00000002U + // .. RXRES = 0x1 + // .. ==> 0XE0000000[0:0] = 0x00000001U + // .. ==> MASK : 0x00000001U VAL : 0x00000001U + // .. + EMIT_MASKWRITE(0XE0000000, 0x000001FFU ,0x00000017U), + // .. IRMODE = 0x0 + // .. ==> 0XE0000004[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. UCLKEN = 0x0 + // .. ==> 0XE0000004[10:10] = 0x00000000U + // .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. CHMODE = 0x0 + // .. ==> 0XE0000004[9:8] = 0x00000000U + // .. ==> MASK : 0x00000300U VAL : 0x00000000U + // .. NBSTOP = 0x0 + // .. ==> 0XE0000004[7:6] = 0x00000000U + // .. ==> MASK : 0x000000C0U VAL : 0x00000000U + // .. PAR = 0x4 + // .. ==> 0XE0000004[5:3] = 0x00000004U + // .. ==> MASK : 0x00000038U VAL : 0x00000020U + // .. CHRL = 0x0 + // .. ==> 0XE0000004[2:1] = 0x00000000U + // .. ==> MASK : 0x00000006U VAL : 0x00000000U + // .. CLKS = 0x0 + // .. ==> 0XE0000004[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XE0000004, 0x00000FFFU ,0x00000020U), + // .. FINISH: UART REGISTERS + // .. START: QSPI REGISTERS + // .. Holdb_dr = 1 + // .. ==> 0XE000D000[19:19] = 0x00000001U + // .. ==> MASK : 0x00080000U VAL : 0x00080000U + // .. + EMIT_MASKWRITE(0XE000D000, 0x00080000U ,0x00080000U), + // .. FINISH: QSPI REGISTERS + // .. START: PL POWER ON RESET REGISTERS + // .. PCFG_POR_CNT_4K = 0 + // .. ==> 0XF8007000[29:29] = 0x00000000U + // .. ==> MASK : 0x20000000U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8007000, 0x20000000U ,0x00000000U), + // .. FINISH: PL POWER ON RESET REGISTERS + // .. START: SMC TIMING CALCULATION REGISTER UPDATE + // .. .. START: NAND SET CYCLE + // .. .. FINISH: NAND SET CYCLE + // .. .. START: OPMODE + // .. .. FINISH: OPMODE + // .. .. START: DIRECT COMMAND + // .. .. FINISH: DIRECT COMMAND + // .. .. START: SRAM/NOR CS0 SET CYCLE + // .. .. FINISH: SRAM/NOR CS0 SET CYCLE + // .. .. START: DIRECT COMMAND + // .. .. FINISH: DIRECT COMMAND + // .. .. START: NOR CS0 BASE ADDRESS + // .. .. FINISH: NOR CS0 BASE ADDRESS + // .. .. START: SRAM/NOR CS1 SET CYCLE + // .. .. FINISH: SRAM/NOR CS1 SET CYCLE + // .. .. START: DIRECT COMMAND + // .. .. FINISH: DIRECT COMMAND + // .. .. START: NOR CS1 BASE ADDRESS + // .. .. FINISH: NOR CS1 BASE ADDRESS + // .. .. START: USB RESET + // .. .. .. START: USB0 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. DIRECTION_1 = 0x4000 + // .. .. .. .. ==> 0XE000A244[21:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x003FFFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A244, 0x003FFFFFU ,0x00004000U), + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. MASK_1_LSW = 0xbfff + // .. .. .. .. ==> 0XE000A008[31:16] = 0x0000BFFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xBFFF0000U + // .. .. .. .. DATA_1_LSW = 0x4000 + // .. .. .. .. ==> 0XE000A008[15:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A008, 0xFFFFFFFFU ,0xBFFF4000U), + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. OP_ENABLE_1 = 0x4000 + // .. .. .. .. ==> 0XE000A248[21:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x003FFFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A248, 0x003FFFFFU ,0x00004000U), + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. MASK_1_LSW = 0xbfff + // .. .. .. .. ==> 0XE000A008[31:16] = 0x0000BFFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xBFFF0000U + // .. .. .. .. DATA_1_LSW = 0x0 + // .. .. .. .. ==> 0XE000A008[15:0] = 0x00000000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A008, 0xFFFFFFFFU ,0xBFFF0000U), + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. MASK_1_LSW = 0xbfff + // .. .. .. .. ==> 0XE000A008[31:16] = 0x0000BFFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xBFFF0000U + // .. .. .. .. DATA_1_LSW = 0x4000 + // .. .. .. .. ==> 0XE000A008[15:0] = 0x00004000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00004000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A008, 0xFFFFFFFFU ,0xBFFF4000U), + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: USB0 RESET + // .. .. .. START: USB1 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: USB1 RESET + // .. .. FINISH: USB RESET + // .. .. START: ENET RESET + // .. .. .. START: ENET0 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. DIRECTION_0 = 0x200 + // .. .. .. .. ==> 0XE000A204[31:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A204, 0xFFFFFFFFU ,0x00000200U), + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. MASK_0_LSW = 0xfdff + // .. .. .. .. ==> 0XE000A000[31:16] = 0x0000FDFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xFDFF0000U + // .. .. .. .. DATA_0_LSW = 0x200 + // .. .. .. .. ==> 0XE000A000[15:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A000, 0xFFFFFFFFU ,0xFDFF0200U), + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. OP_ENABLE_0 = 0x200 + // .. .. .. .. ==> 0XE000A208[31:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0xFFFFFFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A208, 0xFFFFFFFFU ,0x00000200U), + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. MASK_0_LSW = 0xfdff + // .. .. .. .. ==> 0XE000A000[31:16] = 0x0000FDFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xFDFF0000U + // .. .. .. .. DATA_0_LSW = 0x0 + // .. .. .. .. ==> 0XE000A000[15:0] = 0x00000000U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000000U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A000, 0xFFFFFFFFU ,0xFDFF0000U), + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. MASK_0_LSW = 0xfdff + // .. .. .. .. ==> 0XE000A000[31:16] = 0x0000FDFFU + // .. .. .. .. ==> MASK : 0xFFFF0000U VAL : 0xFDFF0000U + // .. .. .. .. DATA_0_LSW = 0x200 + // .. .. .. .. ==> 0XE000A000[15:0] = 0x00000200U + // .. .. .. .. ==> MASK : 0x0000FFFFU VAL : 0x00000200U + // .. .. .. .. + EMIT_MASKWRITE(0XE000A000, 0xFFFFFFFFU ,0xFDFF0200U), + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: ENET0 RESET + // .. .. .. START: ENET1 RESET + // .. .. .. .. START: DIR MODE BANK 0 + // .. .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. .. START: DIR MODE BANK 1 + // .. .. .. .. FINISH: DIR MODE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. .. .. START: OUTPUT ENABLE BANK 1 + // .. .. .. .. FINISH: OUTPUT ENABLE BANK 1 + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: ENET1 RESET + // .. .. FINISH: ENET RESET + // .. .. START: I2C RESET + // .. .. .. START: I2C0 RESET + // .. .. .. .. START: DIR MODE GPIO BANK0 + // .. .. .. .. FINISH: DIR MODE GPIO BANK0 + // .. .. .. .. START: DIR MODE GPIO BANK1 + // .. .. .. .. FINISH: DIR MODE GPIO BANK1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: I2C0 RESET + // .. .. .. START: I2C1 RESET + // .. .. .. .. START: DIR MODE GPIO BANK0 + // .. .. .. .. FINISH: DIR MODE GPIO BANK0 + // .. .. .. .. START: DIR MODE GPIO BANK1 + // .. .. .. .. FINISH: DIR MODE GPIO BANK1 + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: OUTPUT ENABLE + // .. .. .. .. FINISH: OUTPUT ENABLE + // .. .. .. .. START: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW LOW BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW LOW BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW LOW BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW LOW BANK [53:48] + // .. .. .. .. START: ADD 1 MS DELAY + // .. .. .. .. + EMIT_MASKDELAY(0XF8F00200, 1), + // .. .. .. .. FINISH: ADD 1 MS DELAY + // .. .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. .. START: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. FINISH: MASK_DATA_0_MSW HIGH BANK [31:16] + // .. .. .. .. START: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. FINISH: MASK_DATA_1_LSW HIGH BANK [47:32] + // .. .. .. .. START: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. .. FINISH: MASK_DATA_1_MSW HIGH BANK [53:48] + // .. .. .. FINISH: I2C1 RESET + // .. .. FINISH: I2C RESET + // .. .. START: NOR CHIP SELECT + // .. .. .. START: DIR MODE BANK 0 + // .. .. .. FINISH: DIR MODE BANK 0 + // .. .. .. START: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. FINISH: MASK_DATA_0_LSW HIGH BANK [15:0] + // .. .. .. START: OUTPUT ENABLE BANK 0 + // .. .. .. FINISH: OUTPUT ENABLE BANK 0 + // .. .. FINISH: NOR CHIP SELECT + // .. FINISH: SMC TIMING CALCULATION REGISTER UPDATE + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_post_config_1_0[] = { + // START: top + // .. START: SLCR SETTINGS + // .. UNLOCK_KEY = 0XDF0D + // .. ==> 0XF8000008[15:0] = 0x0000DF0DU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000DF0DU + // .. + EMIT_WRITE(0XF8000008, 0x0000DF0DU), + // .. FINISH: SLCR SETTINGS + // .. START: ENABLING LEVEL SHIFTER + // .. USER_INP_ICT_EN_0 = 3 + // .. ==> 0XF8000900[1:0] = 0x00000003U + // .. ==> MASK : 0x00000003U VAL : 0x00000003U + // .. USER_INP_ICT_EN_1 = 3 + // .. ==> 0XF8000900[3:2] = 0x00000003U + // .. ==> MASK : 0x0000000CU VAL : 0x0000000CU + // .. + EMIT_MASKWRITE(0XF8000900, 0x0000000FU ,0x0000000FU), + // .. FINISH: ENABLING LEVEL SHIFTER + // .. START: FPGA RESETS TO 0 + // .. reserved_3 = 0 + // .. ==> 0XF8000240[31:25] = 0x00000000U + // .. ==> MASK : 0xFE000000U VAL : 0x00000000U + // .. FPGA_ACP_RST = 0 + // .. ==> 0XF8000240[24:24] = 0x00000000U + // .. ==> MASK : 0x01000000U VAL : 0x00000000U + // .. FPGA_AXDS3_RST = 0 + // .. ==> 0XF8000240[23:23] = 0x00000000U + // .. ==> MASK : 0x00800000U VAL : 0x00000000U + // .. FPGA_AXDS2_RST = 0 + // .. ==> 0XF8000240[22:22] = 0x00000000U + // .. ==> MASK : 0x00400000U VAL : 0x00000000U + // .. FPGA_AXDS1_RST = 0 + // .. ==> 0XF8000240[21:21] = 0x00000000U + // .. ==> MASK : 0x00200000U VAL : 0x00000000U + // .. FPGA_AXDS0_RST = 0 + // .. ==> 0XF8000240[20:20] = 0x00000000U + // .. ==> MASK : 0x00100000U VAL : 0x00000000U + // .. reserved_2 = 0 + // .. ==> 0XF8000240[19:18] = 0x00000000U + // .. ==> MASK : 0x000C0000U VAL : 0x00000000U + // .. FSSW1_FPGA_RST = 0 + // .. ==> 0XF8000240[17:17] = 0x00000000U + // .. ==> MASK : 0x00020000U VAL : 0x00000000U + // .. FSSW0_FPGA_RST = 0 + // .. ==> 0XF8000240[16:16] = 0x00000000U + // .. ==> MASK : 0x00010000U VAL : 0x00000000U + // .. reserved_1 = 0 + // .. ==> 0XF8000240[15:14] = 0x00000000U + // .. ==> MASK : 0x0000C000U VAL : 0x00000000U + // .. FPGA_FMSW1_RST = 0 + // .. ==> 0XF8000240[13:13] = 0x00000000U + // .. ==> MASK : 0x00002000U VAL : 0x00000000U + // .. FPGA_FMSW0_RST = 0 + // .. ==> 0XF8000240[12:12] = 0x00000000U + // .. ==> MASK : 0x00001000U VAL : 0x00000000U + // .. FPGA_DMA3_RST = 0 + // .. ==> 0XF8000240[11:11] = 0x00000000U + // .. ==> MASK : 0x00000800U VAL : 0x00000000U + // .. FPGA_DMA2_RST = 0 + // .. ==> 0XF8000240[10:10] = 0x00000000U + // .. ==> MASK : 0x00000400U VAL : 0x00000000U + // .. FPGA_DMA1_RST = 0 + // .. ==> 0XF8000240[9:9] = 0x00000000U + // .. ==> MASK : 0x00000200U VAL : 0x00000000U + // .. FPGA_DMA0_RST = 0 + // .. ==> 0XF8000240[8:8] = 0x00000000U + // .. ==> MASK : 0x00000100U VAL : 0x00000000U + // .. reserved = 0 + // .. ==> 0XF8000240[7:4] = 0x00000000U + // .. ==> MASK : 0x000000F0U VAL : 0x00000000U + // .. FPGA3_OUT_RST = 0 + // .. ==> 0XF8000240[3:3] = 0x00000000U + // .. ==> MASK : 0x00000008U VAL : 0x00000000U + // .. FPGA2_OUT_RST = 0 + // .. ==> 0XF8000240[2:2] = 0x00000000U + // .. ==> MASK : 0x00000004U VAL : 0x00000000U + // .. FPGA1_OUT_RST = 0 + // .. ==> 0XF8000240[1:1] = 0x00000000U + // .. ==> MASK : 0x00000002U VAL : 0x00000000U + // .. FPGA0_OUT_RST = 0 + // .. ==> 0XF8000240[0:0] = 0x00000000U + // .. ==> MASK : 0x00000001U VAL : 0x00000000U + // .. + EMIT_MASKWRITE(0XF8000240, 0xFFFFFFFFU ,0x00000000U), + // .. FINISH: FPGA RESETS TO 0 + // .. START: AFI REGISTERS + // .. .. START: AFI0 REGISTERS + // .. .. FINISH: AFI0 REGISTERS + // .. .. START: AFI1 REGISTERS + // .. .. FINISH: AFI1 REGISTERS + // .. .. START: AFI2 REGISTERS + // .. .. FINISH: AFI2 REGISTERS + // .. .. START: AFI3 REGISTERS + // .. .. FINISH: AFI3 REGISTERS + // .. FINISH: AFI REGISTERS + // .. START: LOCK IT BACK + // .. LOCK_KEY = 0X767B + // .. ==> 0XF8000004[15:0] = 0x0000767BU + // .. ==> MASK : 0x0000FFFFU VAL : 0x0000767BU + // .. + EMIT_WRITE(0XF8000004, 0x0000767BU), + // .. FINISH: LOCK IT BACK + // FINISH: top + // + EMIT_EXIT(), + + // +}; + +unsigned long ps7_debug_1_0[] = { + // START: top + // .. START: CROSS TRIGGER CONFIGURATIONS + // .. .. START: UNLOCKING CTI REGISTERS + // .. .. KEY = 0XC5ACCE55 + // .. .. ==> 0XF8898FB0[31:0] = 0xC5ACCE55U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0xC5ACCE55U + // .. .. + EMIT_WRITE(0XF8898FB0, 0xC5ACCE55U), + // .. .. KEY = 0XC5ACCE55 + // .. .. ==> 0XF8899FB0[31:0] = 0xC5ACCE55U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0xC5ACCE55U + // .. .. + EMIT_WRITE(0XF8899FB0, 0xC5ACCE55U), + // .. .. KEY = 0XC5ACCE55 + // .. .. ==> 0XF8809FB0[31:0] = 0xC5ACCE55U + // .. .. ==> MASK : 0xFFFFFFFFU VAL : 0xC5ACCE55U + // .. .. + EMIT_WRITE(0XF8809FB0, 0xC5ACCE55U), + // .. .. FINISH: UNLOCKING CTI REGISTERS + // .. .. START: ENABLING CTI MODULES AND CHANNELS + // .. .. FINISH: ENABLING CTI MODULES AND CHANNELS + // .. .. START: MAPPING CPU0, CPU1 AND FTM EVENTS TO CTM CHANNELS + // .. .. FINISH: MAPPING CPU0, CPU1 AND FTM EVENTS TO CTM CHANNELS + // .. FINISH: CROSS TRIGGER CONFIGURATIONS + // FINISH: top + // + EMIT_EXIT(), + + // +}; + + +#include "xil_io.h" +#define PS7_MASK_POLL_TIME 100000000 + +char* +getPS7MessageInfo(unsigned key) { + + char* err_msg = ""; + switch (key) { + case PS7_INIT_SUCCESS: err_msg = "PS7 initialization successful"; break; + case PS7_INIT_CORRUPT: err_msg = "PS7 init Data Corrupted"; break; + case PS7_INIT_TIMEOUT: err_msg = "PS7 init mask poll timeout"; break; + case PS7_POLL_FAILED_DDR_INIT: err_msg = "Mask Poll failed for DDR Init"; break; + case PS7_POLL_FAILED_DMA: err_msg = "Mask Poll failed for PLL Init"; break; + case PS7_POLL_FAILED_PLL: err_msg = "Mask Poll failed for DMA done bit"; break; + default: err_msg = "Undefined error status"; break; + } + + return err_msg; +} + +unsigned long +ps7GetSiliconVersion () { + // Read PS version from MCTRL register [31:28] + unsigned long mask = 0xF0000000; + unsigned long *addr = (unsigned long*) 0XF8007080; + unsigned long ps_version = (*addr & mask) >> 28; + return ps_version; +} + +void mask_write (unsigned long add , unsigned long mask, unsigned long val ) { + volatile unsigned long *addr = (volatile unsigned long*) add; + *addr = ( val & mask ) | ( *addr & ~mask); + //xil_printf("MaskWrite : 0x%x--> 0x%x \n \r" ,add, *addr); +} + + +int mask_poll(unsigned long add , unsigned long mask ) { + volatile unsigned long *addr = (volatile unsigned long*) add; + int i = 0; + while (!(*addr & mask)) { + if (i == PS7_MASK_POLL_TIME) { + return -1; + } + i++; + } + return 1; + //xil_printf("MaskPoll : 0x%x --> 0x%x \n \r" , add, *addr); +} + +unsigned long mask_read(unsigned long add , unsigned long mask ) { + volatile unsigned long *addr = (volatile unsigned long*) add; + unsigned long val = (*addr & mask); + //xil_printf("MaskRead : 0x%x --> 0x%x \n \r" , add, val); + return val; +} + + + +int +ps7_config(unsigned long * ps7_config_init) +{ + unsigned long *ptr = ps7_config_init; + + unsigned long opcode; // current instruction .. + unsigned long args[16]; // no opcode has so many args ... + int numargs; // number of arguments of this instruction + int j; // general purpose index + + volatile unsigned long *addr; // some variable to make code readable + unsigned long val,mask; // some variable to make code readable + + int finish = -1 ; // loop while this is negative ! + int i = 0; // Timeout variable + + while( finish < 0 ) { + numargs = ptr[0] & 0xF; + opcode = ptr[0] >> 4; + + for( j = 0 ; j < numargs ; j ++ ) + args[j] = ptr[j+1]; + ptr += numargs + 1; + + + switch ( opcode ) { + + case OPCODE_EXIT: + finish = PS7_INIT_SUCCESS; + break; + + case OPCODE_CLEAR: + addr = (unsigned long*) args[0]; + *addr = 0; + break; + + case OPCODE_WRITE: + addr = (unsigned long*) args[0]; + val = args[1]; + *addr = val; + break; + + case OPCODE_MASKWRITE: + addr = (unsigned long*) args[0]; + mask = args[1]; + val = args[2]; + *addr = ( val & mask ) | ( *addr & ~mask); + break; + + case OPCODE_MASKPOLL: + addr = (unsigned long*) args[0]; + mask = args[1]; + i = 0; + while (!(*addr & mask)) { + if (i == PS7_MASK_POLL_TIME) { + finish = PS7_INIT_TIMEOUT; + break; + } + i++; + } + break; + case OPCODE_MASKDELAY: + addr = (unsigned long*) args[0]; + mask = args[1]; + int delay = get_number_of_cycles_for_delay(mask); + perf_reset_and_start_timer(); + while ((*addr < delay)) { + } + break; + default: + finish = PS7_INIT_CORRUPT; + break; + } + } + return finish; +} + +unsigned long *ps7_mio_init_data = ps7_mio_init_data_3_0; +unsigned long *ps7_pll_init_data = ps7_pll_init_data_3_0; +unsigned long *ps7_clock_init_data = ps7_clock_init_data_3_0; +unsigned long *ps7_ddr_init_data = ps7_ddr_init_data_3_0; +unsigned long *ps7_peripherals_init_data = ps7_peripherals_init_data_3_0; + +int +ps7_post_config() +{ + // Get the PS_VERSION on run time + unsigned long si_ver = ps7GetSiliconVersion (); + int ret = -1; + if (si_ver == PCW_SILICON_VERSION_1) { + ret = ps7_config (ps7_post_config_1_0); + if (ret != PS7_INIT_SUCCESS) return ret; + } else if (si_ver == PCW_SILICON_VERSION_2) { + ret = ps7_config (ps7_post_config_2_0); + if (ret != PS7_INIT_SUCCESS) return ret; + } else { + ret = ps7_config (ps7_post_config_3_0); + if (ret != PS7_INIT_SUCCESS) return ret; + } + return PS7_INIT_SUCCESS; +} + +int +ps7_debug() +{ + // Get the PS_VERSION on run time + unsigned long si_ver = ps7GetSiliconVersion (); + int ret = -1; + if (si_ver == PCW_SILICON_VERSION_1) { + ret = ps7_config (ps7_debug_1_0); + if (ret != PS7_INIT_SUCCESS) return ret; + } else if (si_ver == PCW_SILICON_VERSION_2) { + ret = ps7_config (ps7_debug_2_0); + if (ret != PS7_INIT_SUCCESS) return ret; + } else { + ret = ps7_config (ps7_debug_3_0); + if (ret != PS7_INIT_SUCCESS) return ret; + } + return PS7_INIT_SUCCESS; +} + + +int +ps7_init() +{ + // Get the PS_VERSION on run time + unsigned long si_ver = ps7GetSiliconVersion (); + int ret; + //int pcw_ver = 0; + + if (si_ver == PCW_SILICON_VERSION_1) { + ps7_mio_init_data = ps7_mio_init_data_1_0; + ps7_pll_init_data = ps7_pll_init_data_1_0; + ps7_clock_init_data = ps7_clock_init_data_1_0; + ps7_ddr_init_data = ps7_ddr_init_data_1_0; + ps7_peripherals_init_data = ps7_peripherals_init_data_1_0; + //pcw_ver = 1; + + } else if (si_ver == PCW_SILICON_VERSION_2) { + ps7_mio_init_data = ps7_mio_init_data_2_0; + ps7_pll_init_data = ps7_pll_init_data_2_0; + ps7_clock_init_data = ps7_clock_init_data_2_0; + ps7_ddr_init_data = ps7_ddr_init_data_2_0; + ps7_peripherals_init_data = ps7_peripherals_init_data_2_0; + //pcw_ver = 2; + + } else { + ps7_mio_init_data = ps7_mio_init_data_3_0; + ps7_pll_init_data = ps7_pll_init_data_3_0; + ps7_clock_init_data = ps7_clock_init_data_3_0; + ps7_ddr_init_data = ps7_ddr_init_data_3_0; + ps7_peripherals_init_data = ps7_peripherals_init_data_3_0; + //pcw_ver = 3; + } + + // MIO init + ret = ps7_config (ps7_mio_init_data); + if (ret != PS7_INIT_SUCCESS) return ret; + + // PLL init + ret = ps7_config (ps7_pll_init_data); + if (ret != PS7_INIT_SUCCESS) return ret; + + // Clock init + ret = ps7_config (ps7_clock_init_data); + if (ret != PS7_INIT_SUCCESS) return ret; + + // DDR init + ret = ps7_config (ps7_ddr_init_data); + if (ret != PS7_INIT_SUCCESS) return ret; + + + + // Peripherals init + ret = ps7_config (ps7_peripherals_init_data); + if (ret != PS7_INIT_SUCCESS) return ret; + //xil_printf ("\n PCW Silicon Version : %d.0", pcw_ver); + return PS7_INIT_SUCCESS; +} + + + + +/* For delay calculation using global timer */ + +/* start timer */ + void perf_start_clock(void) +{ + *(volatile unsigned int*)SCU_GLOBAL_TIMER_CONTROL = ((1 << 0) | // Timer Enable + (1 << 3) | // Auto-increment + (0 << 8) // Pre-scale + ); +} + +/* stop timer and reset timer count regs */ + void perf_reset_clock(void) +{ + perf_disable_clock(); + *(volatile unsigned int*)SCU_GLOBAL_TIMER_COUNT_L32 = 0; + *(volatile unsigned int*)SCU_GLOBAL_TIMER_COUNT_U32 = 0; +} + +/* Compute mask for given delay in miliseconds*/ +int get_number_of_cycles_for_delay(unsigned int delay) +{ + // GTC is always clocked at 1/2 of the CPU frequency (CPU_3x2x) + return (APU_FREQ*delay/(2*1000)); + +} + +/* stop timer */ + void perf_disable_clock(void) +{ + *(volatile unsigned int*)SCU_GLOBAL_TIMER_CONTROL = 0; +} + +void perf_reset_and_start_timer() +{ + perf_reset_clock(); + perf_start_clock(); +} + + + + diff --git a/bsp_z7/coraZ7-10/ps7_init.h b/bsp_z7/coraZ7-10/ps7_init.h new file mode 100644 index 0000000..8db7e13 --- /dev/null +++ b/bsp_z7/coraZ7-10/ps7_init.h @@ -0,0 +1,114 @@ +/****************************************************************************** +* Copyright (c) 2018 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file ps7_init.h +* +* This file can be included in FSBL code +* to get prototype of ps7_init() function +* and error codes +* +*****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + + +//typedef unsigned int u32; + + +/** do we need to make this name more unique ? **/ +//extern u32 ps7_init_data[]; +extern unsigned long * ps7_ddr_init_data; +extern unsigned long * ps7_mio_init_data; +extern unsigned long * ps7_pll_init_data; +extern unsigned long * ps7_clock_init_data; +extern unsigned long * ps7_peripherals_init_data; + + + +#define OPCODE_EXIT 0U +#define OPCODE_CLEAR 1U +#define OPCODE_WRITE 2U +#define OPCODE_MASKWRITE 3U +#define OPCODE_MASKPOLL 4U +#define OPCODE_MASKDELAY 5U +#define NEW_PS7_ERR_CODE 1 + +/* Encode number of arguments in last nibble */ +#define EMIT_EXIT() ( (OPCODE_EXIT << 4 ) | 0 ) +#define EMIT_CLEAR(addr) ( (OPCODE_CLEAR << 4 ) | 1 ) , addr +#define EMIT_WRITE(addr,val) ( (OPCODE_WRITE << 4 ) | 2 ) , addr, val +#define EMIT_MASKWRITE(addr,mask,val) ( (OPCODE_MASKWRITE << 4 ) | 3 ) , addr, mask, val +#define EMIT_MASKPOLL(addr,mask) ( (OPCODE_MASKPOLL << 4 ) | 2 ) , addr, mask +#define EMIT_MASKDELAY(addr,mask) ( (OPCODE_MASKDELAY << 4 ) | 2 ) , addr, mask + +/* Returns codes of PS7_Init */ +#define PS7_INIT_SUCCESS (0) // 0 is success in good old C +#define PS7_INIT_CORRUPT (1) // 1 the data is corrupted, and slcr reg are in corrupted state now +#define PS7_INIT_TIMEOUT (2) // 2 when a poll operation timed out +#define PS7_POLL_FAILED_DDR_INIT (3) // 3 when a poll operation timed out for ddr init +#define PS7_POLL_FAILED_DMA (4) // 4 when a poll operation timed out for dma done bit +#define PS7_POLL_FAILED_PLL (5) // 5 when a poll operation timed out for pll sequence init + + +/* Silicon Versions */ +#define PCW_SILICON_VERSION_1 0 +#define PCW_SILICON_VERSION_2 1 +#define PCW_SILICON_VERSION_3 2 + +/* This flag to be used by FSBL to check whether ps7_post_config() proc exixts */ +#define PS7_POST_CONFIG + +/* Freq of all peripherals */ + +#define APU_FREQ 666666687 +#define DDR_FREQ 533333374 +#define DCI_FREQ 10158730 +#define QSPI_FREQ 200000000 +#define SMC_FREQ 10000000 +#define ENET0_FREQ 125000000 +#define ENET1_FREQ 10000000 +#define USB0_FREQ 60000000 +#define USB1_FREQ 60000000 +#define SDIO_FREQ 50000000 +#define UART_FREQ 50000000 +#define SPI_FREQ 10000000 +#define I2C_FREQ 111111115 +#define WDT_FREQ 111111115 +#define TTC_FREQ 50000000 +#define CAN_FREQ 10000000 +#define PCAP_FREQ 200000000 +#define TPIU_FREQ 200000000 +#define FPGA0_FREQ 100000000 +#define FPGA1_FREQ 10000000 +#define FPGA2_FREQ 10000000 +#define FPGA3_FREQ 10000000 + + +/* For delay calculation using global registers*/ +#define SCU_GLOBAL_TIMER_COUNT_L32 0xF8F00200 +#define SCU_GLOBAL_TIMER_COUNT_U32 0xF8F00204 +#define SCU_GLOBAL_TIMER_CONTROL 0xF8F00208 +#define SCU_GLOBAL_TIMER_AUTO_INC 0xF8F00218 + +int ps7_config( unsigned long*); +int ps7_init(); +int ps7_post_config(); +int ps7_debug(); +char* getPS7MessageInfo(unsigned key); + +void perf_start_clock(void); +void perf_disable_clock(void); +void perf_reset_clock(void); +void perf_reset_and_start_timer(); +int get_number_of_cycles_for_delay(unsigned int delay); +#ifdef __cplusplus +} +#endif + diff --git a/bsp_z7/coraZ7-10/xparameters.h b/bsp_z7/coraZ7-10/xparameters.h new file mode 100644 index 0000000..5d4b817 --- /dev/null +++ b/bsp_z7/coraZ7-10/xparameters.h @@ -0,0 +1,484 @@ +/****************************************************************************** +* Copyright (c) 2021 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +#ifndef XPARAMETERS_H /* prevent circular inclusions */ +#define XPARAMETERS_H /* by using protection macros */ + +/* Definition for CPU ID */ +#define XPAR_CPU_ID 0U + +/* Definitions for peripheral PS7_CORTEXA9_0 */ +#define XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ 666666687 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_CORTEXA9_0 */ +#define XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ 666666687 + + +/******************************************************************/ + +#include "xparameters_ps.h" + +#define STDIN_BASEADDRESS 0xE0000000 +#define STDOUT_BASEADDRESS 0xE0000000 + +/******************************************************************/ + +/* Platform specific definitions */ +#define PLATFORM_ZYNQ + +/* Definitions for sleep timer configuration */ +#define XSLEEP_TIMER_IS_DEFAULT_TIMER + + +/******************************************************************/ + +/* Definitions for peripheral PS7_DDR_0 */ +#define XPAR_PS7_DDR_0_S_AXI_BASEADDR 0x00100000 +#define XPAR_PS7_DDR_0_S_AXI_HIGHADDR 0x1FFFFFFF + + +/******************************************************************/ + +/* Definitions for driver DEVCFG */ +#define XPAR_XDCFG_NUM_INSTANCES 1U + +/* Definitions for peripheral PS7_DEV_CFG_0 */ +#define XPAR_PS7_DEV_CFG_0_DEVICE_ID 0U +#define XPAR_PS7_DEV_CFG_0_BASEADDR 0xF8007000U +#define XPAR_PS7_DEV_CFG_0_HIGHADDR 0xF80070FFU + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_DEV_CFG_0 */ +#define XPAR_XDCFG_0_DEVICE_ID XPAR_PS7_DEV_CFG_0_DEVICE_ID +#define XPAR_XDCFG_0_BASEADDR 0xF8007000U +#define XPAR_XDCFG_0_HIGHADDR 0xF80070FFU + + +/******************************************************************/ + +/* Definitions for driver DMAPS */ +#define XPAR_XDMAPS_NUM_INSTANCES 2 + +/* Definitions for peripheral PS7_DMA_NS */ +#define XPAR_PS7_DMA_NS_DEVICE_ID 0 +#define XPAR_PS7_DMA_NS_BASEADDR 0xF8004000 +#define XPAR_PS7_DMA_NS_HIGHADDR 0xF8004FFF + + +/* Definitions for peripheral PS7_DMA_S */ +#define XPAR_PS7_DMA_S_DEVICE_ID 1 +#define XPAR_PS7_DMA_S_BASEADDR 0xF8003000 +#define XPAR_PS7_DMA_S_HIGHADDR 0xF8003FFF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_DMA_NS */ +#define XPAR_XDMAPS_0_DEVICE_ID XPAR_PS7_DMA_NS_DEVICE_ID +#define XPAR_XDMAPS_0_BASEADDR 0xF8004000 +#define XPAR_XDMAPS_0_HIGHADDR 0xF8004FFF + +/* Canonical definitions for peripheral PS7_DMA_S */ +#define XPAR_XDMAPS_1_DEVICE_ID XPAR_PS7_DMA_S_DEVICE_ID +#define XPAR_XDMAPS_1_BASEADDR 0xF8003000 +#define XPAR_XDMAPS_1_HIGHADDR 0xF8003FFF + + +/******************************************************************/ + +/* Definitions for driver EMACPS */ +#define XPAR_XEMACPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_ETHERNET_0 */ +#define XPAR_PS7_ETHERNET_0_DEVICE_ID 0 +#define XPAR_PS7_ETHERNET_0_BASEADDR 0xE000B000 +#define XPAR_PS7_ETHERNET_0_HIGHADDR 0xE000BFFF +#define XPAR_PS7_ETHERNET_0_ENET_CLK_FREQ_HZ 125000000 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 8 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1 1 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 8 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1 5 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0 8 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1 50 +#define XPAR_PS7_ETHERNET_0_ENET_TSU_CLK_FREQ_HZ 0 + + +/******************************************************************/ + +#define XPAR_PS7_ETHERNET_0_IS_CACHE_COHERENT 0 +#define XPAR_XEMACPS_0_IS_CACHE_COHERENT 0 +/* Canonical definitions for peripheral PS7_ETHERNET_0 */ +#define XPAR_XEMACPS_0_DEVICE_ID XPAR_PS7_ETHERNET_0_DEVICE_ID +#define XPAR_XEMACPS_0_BASEADDR 0xE000B000 +#define XPAR_XEMACPS_0_HIGHADDR 0xE000BFFF +#define XPAR_XEMACPS_0_ENET_CLK_FREQ_HZ 125000000 +#define XPAR_XEMACPS_0_ENET_SLCR_1000Mbps_DIV0 8 +#define XPAR_XEMACPS_0_ENET_SLCR_1000Mbps_DIV1 1 +#define XPAR_XEMACPS_0_ENET_SLCR_100Mbps_DIV0 8 +#define XPAR_XEMACPS_0_ENET_SLCR_100Mbps_DIV1 5 +#define XPAR_XEMACPS_0_ENET_SLCR_10Mbps_DIV0 8 +#define XPAR_XEMACPS_0_ENET_SLCR_10Mbps_DIV1 50 +#define XPAR_XEMACPS_0_ENET_TSU_CLK_FREQ_HZ 0 + + +/******************************************************************/ + + +/* Definitions for peripheral PS7_AFI_0 */ +#define XPAR_PS7_AFI_0_S_AXI_BASEADDR 0xF8008000 +#define XPAR_PS7_AFI_0_S_AXI_HIGHADDR 0xF8008FFF + + +/* Definitions for peripheral PS7_AFI_1 */ +#define XPAR_PS7_AFI_1_S_AXI_BASEADDR 0xF8009000 +#define XPAR_PS7_AFI_1_S_AXI_HIGHADDR 0xF8009FFF + + +/* Definitions for peripheral PS7_AFI_2 */ +#define XPAR_PS7_AFI_2_S_AXI_BASEADDR 0xF800A000 +#define XPAR_PS7_AFI_2_S_AXI_HIGHADDR 0xF800AFFF + + +/* Definitions for peripheral PS7_AFI_3 */ +#define XPAR_PS7_AFI_3_S_AXI_BASEADDR 0xF800B000 +#define XPAR_PS7_AFI_3_S_AXI_HIGHADDR 0xF800BFFF + + +/* Definitions for peripheral PS7_DDRC_0 */ +#define XPAR_PS7_DDRC_0_S_AXI_BASEADDR 0xF8006000 +#define XPAR_PS7_DDRC_0_S_AXI_HIGHADDR 0xF8006FFF + + +/* Definitions for peripheral PS7_GLOBALTIMER_0 */ +#define XPAR_PS7_GLOBALTIMER_0_S_AXI_BASEADDR 0xF8F00200 +#define XPAR_PS7_GLOBALTIMER_0_S_AXI_HIGHADDR 0xF8F002FF + + +/* Definitions for peripheral PS7_GPV_0 */ +#define XPAR_PS7_GPV_0_S_AXI_BASEADDR 0xF8900000 +#define XPAR_PS7_GPV_0_S_AXI_HIGHADDR 0xF89FFFFF + + +/* Definitions for peripheral PS7_INTC_DIST_0 */ +#define XPAR_PS7_INTC_DIST_0_S_AXI_BASEADDR 0xF8F01000 +#define XPAR_PS7_INTC_DIST_0_S_AXI_HIGHADDR 0xF8F01FFF + + +/* Definitions for peripheral PS7_IOP_BUS_CONFIG_0 */ +#define XPAR_PS7_IOP_BUS_CONFIG_0_S_AXI_BASEADDR 0xE0200000 +#define XPAR_PS7_IOP_BUS_CONFIG_0_S_AXI_HIGHADDR 0xE0200FFF + + +/* Definitions for peripheral PS7_L2CACHEC_0 */ +#define XPAR_PS7_L2CACHEC_0_S_AXI_BASEADDR 0xF8F02000 +#define XPAR_PS7_L2CACHEC_0_S_AXI_HIGHADDR 0xF8F02FFF + + +/* Definitions for peripheral PS7_OCMC_0 */ +#define XPAR_PS7_OCMC_0_S_AXI_BASEADDR 0xF800C000 +#define XPAR_PS7_OCMC_0_S_AXI_HIGHADDR 0xF800CFFF + + +/* Definitions for peripheral PS7_PL310_0 */ +#define XPAR_PS7_PL310_0_S_AXI_BASEADDR 0xF8F02000 +#define XPAR_PS7_PL310_0_S_AXI_HIGHADDR 0xF8F02FFF + + +/* Definitions for peripheral PS7_PMU_0 */ +#define XPAR_PS7_PMU_0_S_AXI_BASEADDR 0xF8891000 +#define XPAR_PS7_PMU_0_S_AXI_HIGHADDR 0xF8891FFF +#define XPAR_PS7_PMU_0_PMU1_S_AXI_BASEADDR 0xF8893000 +#define XPAR_PS7_PMU_0_PMU1_S_AXI_HIGHADDR 0xF8893FFF + + +/* Definitions for peripheral PS7_QSPI_LINEAR_0 */ +#define XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR 0xFC000000 +#define XPAR_PS7_QSPI_LINEAR_0_S_AXI_HIGHADDR 0xFCFFFFFF + + +/* Definitions for peripheral PS7_RAM_0 */ +#define XPAR_PS7_RAM_0_S_AXI_BASEADDR 0x00000000 +#define XPAR_PS7_RAM_0_S_AXI_HIGHADDR 0x0003FFFF + + +/* Definitions for peripheral PS7_RAM_1 */ +#define XPAR_PS7_RAM_1_S_AXI_BASEADDR 0xFFFC0000 +#define XPAR_PS7_RAM_1_S_AXI_HIGHADDR 0xFFFFFFFF + + +/* Definitions for peripheral PS7_SCUC_0 */ +#define XPAR_PS7_SCUC_0_S_AXI_BASEADDR 0xF8F00000 +#define XPAR_PS7_SCUC_0_S_AXI_HIGHADDR 0xF8F000FC + + +/* Definitions for peripheral PS7_SLCR_0 */ +#define XPAR_PS7_SLCR_0_S_AXI_BASEADDR 0xF8000000 +#define XPAR_PS7_SLCR_0_S_AXI_HIGHADDR 0xF8000FFF + + +/******************************************************************/ + +/* Definitions for driver GPIOPS */ +#define XPAR_XGPIOPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_GPIO_0 */ +#define XPAR_PS7_GPIO_0_DEVICE_ID 0 +#define XPAR_PS7_GPIO_0_BASEADDR 0xE000A000 +#define XPAR_PS7_GPIO_0_HIGHADDR 0xE000AFFF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_GPIO_0 */ +#define XPAR_XGPIOPS_0_DEVICE_ID XPAR_PS7_GPIO_0_DEVICE_ID +#define XPAR_XGPIOPS_0_BASEADDR 0xE000A000 +#define XPAR_XGPIOPS_0_HIGHADDR 0xE000AFFF + + +/******************************************************************/ + +/* Definitions for driver QSPIPS */ +#define XPAR_XQSPIPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_QSPI_0 */ +#define XPAR_PS7_QSPI_0_DEVICE_ID 0 +#define XPAR_PS7_QSPI_0_BASEADDR 0xE000D000 +#define XPAR_PS7_QSPI_0_HIGHADDR 0xE000DFFF +#define XPAR_PS7_QSPI_0_QSPI_CLK_FREQ_HZ 200000000 +#define XPAR_PS7_QSPI_0_QSPI_MODE 0 +#define XPAR_PS7_QSPI_0_QSPI_BUS_WIDTH 2 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_QSPI_0 */ +#define XPAR_XQSPIPS_0_DEVICE_ID XPAR_PS7_QSPI_0_DEVICE_ID +#define XPAR_XQSPIPS_0_BASEADDR 0xE000D000 +#define XPAR_XQSPIPS_0_HIGHADDR 0xE000DFFF +#define XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ 200000000 +#define XPAR_XQSPIPS_0_QSPI_MODE 0 +#define XPAR_XQSPIPS_0_QSPI_BUS_WIDTH 2 + + +/******************************************************************/ + +/* Definitions for driver SCUGIC */ +#define XPAR_XSCUGIC_NUM_INSTANCES 1U + +/* Definitions for peripheral PS7_SCUGIC_0 */ +#define XPAR_PS7_SCUGIC_0_DEVICE_ID 0U +#define XPAR_PS7_SCUGIC_0_BASEADDR 0xF8F00100U +#define XPAR_PS7_SCUGIC_0_HIGHADDR 0xF8F001FFU +#define XPAR_PS7_SCUGIC_0_DIST_BASEADDR 0xF8F01000U + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUGIC_0 */ +#define XPAR_SCUGIC_0_DEVICE_ID 0U +#define XPAR_SCUGIC_0_CPU_BASEADDR 0xF8F00100U +#define XPAR_SCUGIC_0_CPU_HIGHADDR 0xF8F001FFU +#define XPAR_SCUGIC_0_DIST_BASEADDR 0xF8F01000U + + +/******************************************************************/ + +/* Definitions for driver SCUTIMER */ +#define XPAR_XSCUTIMER_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_SCUTIMER_0 */ +#define XPAR_PS7_SCUTIMER_0_DEVICE_ID 0 +#define XPAR_PS7_SCUTIMER_0_BASEADDR 0xF8F00600 +#define XPAR_PS7_SCUTIMER_0_HIGHADDR 0xF8F0061F + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUTIMER_0 */ +#define XPAR_XSCUTIMER_0_DEVICE_ID XPAR_PS7_SCUTIMER_0_DEVICE_ID +#define XPAR_XSCUTIMER_0_BASEADDR 0xF8F00600 +#define XPAR_XSCUTIMER_0_HIGHADDR 0xF8F0061F + + +/******************************************************************/ + +/* Definitions for driver SCUWDT */ +#define XPAR_XSCUWDT_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_SCUWDT_0 */ +#define XPAR_PS7_SCUWDT_0_DEVICE_ID 0 +#define XPAR_PS7_SCUWDT_0_BASEADDR 0xF8F00620 +#define XPAR_PS7_SCUWDT_0_HIGHADDR 0xF8F006FF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUWDT_0 */ +#define XPAR_SCUWDT_0_DEVICE_ID XPAR_PS7_SCUWDT_0_DEVICE_ID +#define XPAR_SCUWDT_0_BASEADDR 0xF8F00620 +#define XPAR_SCUWDT_0_HIGHADDR 0xF8F006FF + + +/******************************************************************/ + +/* Definitions for driver SDPS */ +#define XPAR_XSDPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_SD_0 */ +#define XPAR_PS7_SD_0_DEVICE_ID 0 +#define XPAR_PS7_SD_0_BASEADDR 0xE0100000 +#define XPAR_PS7_SD_0_HIGHADDR 0xE0100FFF +#define XPAR_PS7_SD_0_SDIO_CLK_FREQ_HZ 50000000 +#define XPAR_PS7_SD_0_HAS_CD 1 +#define XPAR_PS7_SD_0_HAS_WP 1 +#define XPAR_PS7_SD_0_BUS_WIDTH 0 +#define XPAR_PS7_SD_0_MIO_BANK 0 +#define XPAR_PS7_SD_0_HAS_EMIO 0 +#define XPAR_PS7_SD_0_SLOT_TYPE 0 +#define XPAR_PS7_SD_0_CLK_50_SDR_ITAP_DLY 0 +#define XPAR_PS7_SD_0_CLK_50_SDR_OTAP_DLY 0 +#define XPAR_PS7_SD_0_CLK_50_DDR_ITAP_DLY 0 +#define XPAR_PS7_SD_0_CLK_50_DDR_OTAP_DLY 0 +#define XPAR_PS7_SD_0_CLK_100_SDR_OTAP_DLY 0 +#define XPAR_PS7_SD_0_CLK_200_SDR_OTAP_DLY 0 + + +/******************************************************************/ + +#define XPAR_PS7_SD_0_IS_CACHE_COHERENT 0 +/* Canonical definitions for peripheral PS7_SD_0 */ +#define XPAR_XSDPS_0_DEVICE_ID XPAR_PS7_SD_0_DEVICE_ID +#define XPAR_XSDPS_0_BASEADDR 0xE0100000 +#define XPAR_XSDPS_0_HIGHADDR 0xE0100FFF +#define XPAR_XSDPS_0_SDIO_CLK_FREQ_HZ 50000000 +#define XPAR_XSDPS_0_HAS_CD 1 +#define XPAR_XSDPS_0_HAS_WP 1 +#define XPAR_XSDPS_0_BUS_WIDTH 0 +#define XPAR_XSDPS_0_MIO_BANK 0 +#define XPAR_XSDPS_0_HAS_EMIO 0 +#define XPAR_XSDPS_0_SLOT_TYPE 0 +#define XPAR_XSDPS_0_IS_CACHE_COHERENT 0 +#define XPAR_XSDPS_0_CLK_50_SDR_ITAP_DLY 0 +#define XPAR_XSDPS_0_CLK_50_SDR_OTAP_DLY 0 +#define XPAR_XSDPS_0_CLK_50_DDR_ITAP_DLY 0 +#define XPAR_XSDPS_0_CLK_50_DDR_OTAP_DLY 0 +#define XPAR_XSDPS_0_CLK_100_SDR_OTAP_DLY 0 +#define XPAR_XSDPS_0_CLK_200_SDR_OTAP_DLY 0 + + +/******************************************************************/ + +/* Definitions for driver TTCPS */ +#define XPAR_XTTCPS_NUM_INSTANCES 3U + +/* Definitions for peripheral PS7_TTC_0 */ +#define XPAR_PS7_TTC_0_DEVICE_ID 0U +#define XPAR_PS7_TTC_0_BASEADDR 0XF8001000U +#define XPAR_PS7_TTC_0_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_PS7_TTC_0_TTC_CLK_CLKSRC 0U +#define XPAR_PS7_TTC_1_DEVICE_ID 1U +#define XPAR_PS7_TTC_1_BASEADDR 0XF8001004U +#define XPAR_PS7_TTC_1_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_PS7_TTC_1_TTC_CLK_CLKSRC 0U +#define XPAR_PS7_TTC_2_DEVICE_ID 2U +#define XPAR_PS7_TTC_2_BASEADDR 0XF8001008U +#define XPAR_PS7_TTC_2_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_PS7_TTC_2_TTC_CLK_CLKSRC 0U + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_TTC_0 */ +#define XPAR_XTTCPS_0_DEVICE_ID XPAR_PS7_TTC_0_DEVICE_ID +#define XPAR_XTTCPS_0_BASEADDR 0xF8001000U +#define XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_XTTCPS_0_TTC_CLK_CLKSRC 0U + +#define XPAR_XTTCPS_1_DEVICE_ID XPAR_PS7_TTC_1_DEVICE_ID +#define XPAR_XTTCPS_1_BASEADDR 0xF8001004U +#define XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_XTTCPS_1_TTC_CLK_CLKSRC 0U + +#define XPAR_XTTCPS_2_DEVICE_ID XPAR_PS7_TTC_2_DEVICE_ID +#define XPAR_XTTCPS_2_BASEADDR 0xF8001008U +#define XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_XTTCPS_2_TTC_CLK_CLKSRC 0U + + +/******************************************************************/ + +/* Definitions for driver UARTPS */ +#define XPAR_XUARTPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_UART_1 */ +#define XPAR_PS7_UART_1_DEVICE_ID 0 +#define XPAR_PS7_UART_1_BASEADDR 0xE0001000 +#define XPAR_PS7_UART_1_HIGHADDR 0xE0001FFF +#define XPAR_PS7_UART_1_UART_CLK_FREQ_HZ 50000000 +#define XPAR_PS7_UART_1_HAS_MODEM 0 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_UART_1 */ +#define XPAR_XUARTPS_0_DEVICE_ID XPAR_PS7_UART_1_DEVICE_ID +#define XPAR_XUARTPS_0_BASEADDR 0xE0001000 +#define XPAR_XUARTPS_0_HIGHADDR 0xE0001FFF +#define XPAR_XUARTPS_0_UART_CLK_FREQ_HZ 50000000 +#define XPAR_XUARTPS_0_HAS_MODEM 0 + + +/******************************************************************/ + +/* Definitions for driver USBPS */ +#define XPAR_XUSBPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_USB_0 */ +#define XPAR_PS7_USB_0_DEVICE_ID 0 +#define XPAR_PS7_USB_0_BASEADDR 0xE0002000 +#define XPAR_PS7_USB_0_HIGHADDR 0xE0002FFF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_USB_0 */ +#define XPAR_XUSBPS_0_DEVICE_ID XPAR_PS7_USB_0_DEVICE_ID +#define XPAR_XUSBPS_0_BASEADDR 0xE0002000 +#define XPAR_XUSBPS_0_HIGHADDR 0xE0002FFF + + +/******************************************************************/ + +/* Definitions for driver XADCPS */ +#define XPAR_XADCPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_XADC_0 */ +#define XPAR_PS7_XADC_0_DEVICE_ID 0 +#define XPAR_PS7_XADC_0_BASEADDR 0xF8007100 +#define XPAR_PS7_XADC_0_HIGHADDR 0xF8007120 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_XADC_0 */ +#define XPAR_XADCPS_0_DEVICE_ID XPAR_PS7_XADC_0_DEVICE_ID +#define XPAR_XADCPS_0_BASEADDR 0xF8007100 +#define XPAR_XADCPS_0_HIGHADDR 0xF8007120 + + +/******************************************************************/ + +/* Xilinx FAT File System Library (XilFFs) User Settings */ +#define FILE_SYSTEM_INTERFACE_SD +#define FILE_SYSTEM_USE_MKFS +#define FILE_SYSTEM_NUM_LOGIC_VOL 2 +#define FILE_SYSTEM_USE_STRFUNC 0 +#define FILE_SYSTEM_SET_FS_RPATH 0 +#define FILE_SYSTEM_WORD_ACCESS +#endif /* end of protection macro */ diff --git a/bsp_z7/freeRTOS/CMakeLists.txt b/bsp_z7/freeRTOS/CMakeLists.txt new file mode 100644 index 0000000..9fb0aa9 --- /dev/null +++ b/bsp_z7/freeRTOS/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${TARGET_NAME} PRIVATE FreeRTOS_asm_vectors.S FreeRTOS_tick_config.c) \ No newline at end of file diff --git a/bsp_z7/freeRTOS/FreeRTOSConfig.h b/bsp_z7/freeRTOS/FreeRTOSConfig.h new file mode 100644 index 0000000..bee124f --- /dev/null +++ b/bsp_z7/freeRTOS/FreeRTOSConfig.h @@ -0,0 +1,224 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* + * The FreeRTOS Cortex-A port implements a full interrupt nesting model. + * + * Interrupts that are assigned a priority at or below + * configMAX_API_CALL_INTERRUPT_PRIORITY (which counter-intuitively in the ARM + * generic interrupt controller [GIC] means a priority that has a numerical + * value above configMAX_API_CALL_INTERRUPT_PRIORITY) can call FreeRTOS safe API + * functions and will nest. + * + * Interrupts that are assigned a priority above + * configMAX_API_CALL_INTERRUPT_PRIORITY (which in the GIC means a numerical + * value below configMAX_API_CALL_INTERRUPT_PRIORITY) cannot call any FreeRTOS + * API functions, will nest, and will not be masked by FreeRTOS critical + * sections (although it is necessary for interrupts to be globally disabled + * extremely briefly as the interrupt mask is updated in the GIC). + * + * FreeRTOS functions that can be called from an interrupt are those that end in + * "FromISR". FreeRTOS maintains a separate interrupt safe API to enable + * interrupt entry to be shorter, faster, simpler and smaller. + * + * The Zynq implements 256 unique interrupt priorities. For the purpose of + * setting configMAX_API_CALL_INTERRUPT_PRIORITY 255 represents the lowest + * priority. + */ +#define configMAX_API_CALL_INTERRUPT_PRIORITY 18 + +#define configCPU_CLOCK_HZ 100000000UL +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configUSE_TICKLESS_IDLE 0 +#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) +#define configPERIPHERAL_CLOCK_HZ ( 33333000UL ) +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 1 +#define configMAX_PRIORITIES ( 7 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 250 ) /* Large in case configUSE_TASK_FPU_SUPPORT is 2 in which case all tasks have an FPU context. */ +#define configTOTAL_HEAP_SIZE ( 125 * 1024 ) +#define configMAX_TASK_NAME_LEN ( 10 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_QUEUE_SETS 1 +#define configSUPPORT_STATIC_ALLOCATION 1 + +/* Include the query-heap CLI command to query the free heap space. */ +#define configINCLUDE_QUERY_HEAP_COMMAND 1 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 5 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or undefined) then each task will +be created without an FPU context, and a task must call vTaskUsesFPU() before +making use of any FPU registers. If configUSE_TASK_FPU_SUPPORT is set to 2 then +tasks are created with an FPU context by default, and calling vTaskUsesFPU() has +no effect. */ +#define configUSE_TASK_FPU_SUPPORT 2 + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 + +/* This demo makes use of one or more example stats formatting functions. These +format the raw data provided by the uxTaskGetSystemState() function in to human +readable ASCII form. See the notes in the implementation of vTaskList() within +FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* The private watchdog is used to generate run time stats. */ +#include "xscuwdt.h" +extern XScuWdt xWatchDogInstance; +extern void vInitialiseTimerForRunTimeStats( void ); +#define configGENERATE_RUN_TIME_STATS 1 +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vInitialiseTimerForRunTimeStats() +#define portGET_RUN_TIME_COUNTER_VALUE() ( ( 0xffffffffUL - XScuWdt_ReadReg( xWatchDogInstance.Config.BaseAddr, XSCUWDT_COUNTER_OFFSET ) ) >> 1 ) + +/* The size of the global output buffer that is available for use when there +are multiple command interpreters running at once (for example, one on a UART +and one on TCP/IP). This is done to prevent an output buffer being defined by +each implementation - which would waste RAM. In this case, there is only one +command interpreter running. */ +#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096 + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +void vAssertCalled( const char * pcFile, unsigned long ulLine ); +#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ); + +/* If configTASK_RETURN_ADDRESS is not defined then a task that attempts to +return from its implementing function will end up in a "task exit error" +function - which contains a call to configASSERT(). However this can give GCC +some problems when it tries to unwind the stack, as the exit error function has +nothing to return to. To avoid this define configTASK_RETURN_ADDRESS to 0. */ +#define configTASK_RETURN_ADDRESS NULL + + +/****** Hardware specific settings. *******************************************/ + +/* + * The application must provide a function that configures a peripheral to + * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() + * in FreeRTOSConfig.h to call the function. This file contains a function + * that is suitable for use on the Zynq MPU. FreeRTOS_Tick_Handler() must + * be installed as the peripheral's interrupt handler. + */ +void vConfigureTickInterrupt( void ); +#define configSETUP_TICK_INTERRUPT() vConfigureTickInterrupt() + +void vClearTickInterrupt( void ); +#define configCLEAR_TICK_INTERRUPT() vClearTickInterrupt() + +/* The following constant describe the hardware, and are correct for the +Zynq MPU. */ +#define configINTERRUPT_CONTROLLER_BASE_ADDRESS ( XPAR_PS7_SCUGIC_0_DIST_BASEADDR ) +#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET ( -0xf00 ) +#define configUNIQUE_INTERRUPT_PRIORITIES 32 + + + +/****** Network configuration settings - only used when the lwIP example is +built. See the page that documents this demo on the http://www.FreeRTOS.org +website for more information. ***********************************************/ + +/* The priority for the task that unblocked by the MAC interrupt to process +received packets. */ +#define configMAC_INPUT_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) + +/* The priority of the task that runs the lwIP stack. */ +#define configLWIP_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) + +/* The priority of the task that uses lwIP sockets to provide a simple command +line interface. */ +#define configCLI_TASK_PRIORITY ( tskIDLE_PRIORITY ) + +/* MAC address configuration. */ +#define configMAC_ADDR0 0x00 +#define configMAC_ADDR1 0x13 +#define configMAC_ADDR2 0x14 +#define configMAC_ADDR3 0x15 +#define configMAC_ADDR4 0x15 +#define configMAC_ADDR5 0x16 + +/* IP address configuration. */ +#define configIP_ADDR0 172 +#define configIP_ADDR1 25 +#define configIP_ADDR2 218 +#define configIP_ADDR3 200 + +/* Netmask configuration. */ +#define configNET_MASK0 255 +#define configNET_MASK1 255 +#define configNET_MASK2 255 +#define configNET_MASK3 0 + +#endif /* FREERTOS_CONFIG_H */ + diff --git a/bsp_z7/freeRTOS/FreeRTOS_asm_vectors.S b/bsp_z7/freeRTOS/FreeRTOS_asm_vectors.S new file mode 100644 index 0000000..f46de6e --- /dev/null +++ b/bsp_z7/freeRTOS/FreeRTOS_asm_vectors.S @@ -0,0 +1,144 @@ +/****************************************************************************** +* +* (c) Copyright 2009-13 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file asm_vectors.s +* +* This file contains the initial vector table for the Cortex A9 processor +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 10/20/09 Initial version
+* 3.05a sdm	02/02/12 Save lr when profiling is enabled
+* 3.10a srt     04/18/13 Implemented ARM Erratas. Please refer to file
+*			 'xil_errata.h' for errata description
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#include "xil_errata.h" + +.org 0 +.text +.arm + +.global _boot +.global _freertos_vector_table + +.global FIQInterrupt +.global DataAbortInterrupt +.global PrefetchAbortInterrupt +.global vPortInstallFreeRTOSVectorTable + +.extern FreeRTOS_IRQ_Handler +.extern FreeRTOS_SWI_Handler + +.section .freertos_vectors +_freertos_vector_table: + B _boot + B FreeRTOS_Undefined + ldr pc, _swi + B FreeRTOS_PrefetchAbortHandler + B FreeRTOS_DataAbortHandler + NOP /* Placeholder for address exception vector*/ + LDR PC, _irq + B FreeRTOS_FIQHandler + +_irq: .word FreeRTOS_IRQ_Handler +_swi: .word FreeRTOS_SWI_Handler + + +.align 4 +FreeRTOS_FIQHandler: /* FIQ vector handler */ + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ +FIQLoop: + blx FIQInterrupt /* FIQ vector */ + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + subs pc, lr, #4 /* adjust return */ + +.align 4 +FreeRTOS_Undefined: /* Undefined handler */ + b . + +.align 4 +FreeRTOS_DataAbortHandler: /* Data Abort handler */ +#ifdef CONFIG_ARM_ERRATA_775420 + dsb +#endif + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + blx DataAbortInterrupt /*DataAbortInterrupt :call C function here */ + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + subs pc, lr, #4 /* adjust return */ + +.align 4 +FreeRTOS_PrefetchAbortHandler: /* Prefetch Abort handler */ +#ifdef CONFIG_ARM_ERRATA_775420 + dsb +#endif + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + blx PrefetchAbortInterrupt /* PrefetchAbortInterrupt: call C function here */ + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + subs pc, lr, #4 /* adjust return */ + +.align 4 +.type vPortInstallFreeRTOSVectorTable, %function +vPortInstallFreeRTOSVectorTable: + + /* Set VBAR to the vector table that contains the FreeRTOS handlers. */ + ldr r0, =_freertos_vector_table + mcr p15, 0, r0, c12, c0, 0 + dsb + isb + bx lr + + +.end + + + + diff --git a/bsp_z7/freeRTOS/FreeRTOS_tick_config.c b/bsp_z7/freeRTOS/FreeRTOS_tick_config.c new file mode 100644 index 0000000..bec08b3 --- /dev/null +++ b/bsp_z7/freeRTOS/FreeRTOS_tick_config.c @@ -0,0 +1,136 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Xilinx includes. */ +#include "xscutimer.h" +#include "xscugic.h" + +#define XSCUTIMER_CLOCK_HZ ( XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ / 2UL ) + +static XScuTimer xTimer; +extern XScuGic xInterruptController; /* Interrupt controller instance */ + +/* + * The application must provide a function that configures a peripheral to + * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() + * in FreeRTOSConfig.h to call the function. This file contains a function + * that is suitable for use on the Zynq SoC. + */ +void vConfigureTickInterrupt( void ) +{ +BaseType_t xStatus; +extern void FreeRTOS_Tick_Handler( void ); +XScuTimer_Config *pxTimerConfig; +XScuGic_Config *pxGICConfig; +const uint8_t ucRisingEdge = 3; + + /* This function is called with the IRQ interrupt disabled, and the IRQ + interrupt should be left disabled. It is enabled automatically when the + scheduler is started. */ + + /* Ensure XScuGic_CfgInitialize() has been called. In this demo it has + already been called from prvSetupHardware() in main(). */ + pxGICConfig = XScuGic_LookupConfig( XPAR_SCUGIC_SINGLE_DEVICE_ID ); + xStatus = XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress ); + configASSERT( xStatus == XST_SUCCESS ); + ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ + + /* The priority must be the lowest possible. */ + XScuGic_SetPriorityTriggerType( &xInterruptController, XPAR_SCUTIMER_INTR, portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, ucRisingEdge ); + + /* Install the FreeRTOS tick handler. */ + xStatus = XScuGic_Connect( &xInterruptController, XPAR_SCUTIMER_INTR, (Xil_ExceptionHandler) FreeRTOS_Tick_Handler, ( void * ) &xTimer ); + configASSERT( xStatus == XST_SUCCESS ); + ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ + + /* Initialise the timer. */ + pxTimerConfig = XScuTimer_LookupConfig( XPAR_SCUTIMER_DEVICE_ID ); + xStatus = XScuTimer_CfgInitialize( &xTimer, pxTimerConfig, pxTimerConfig->BaseAddr ); + configASSERT( xStatus == XST_SUCCESS ); + ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ + + /* Enable Auto reload mode. */ + XScuTimer_EnableAutoReload( &xTimer ); + + /* Ensure there is no prescale. */ + XScuTimer_SetPrescaler( &xTimer, 0 ); + + /* Load the timer counter register. */ + XScuTimer_LoadTimer( &xTimer, XSCUTIMER_CLOCK_HZ / configTICK_RATE_HZ ); + + /* Start the timer counter and then wait for it to timeout a number of + times. */ + XScuTimer_Start( &xTimer ); + + /* Enable the interrupt for the xTimer in the interrupt controller. */ + XScuGic_Enable( &xInterruptController, XPAR_SCUTIMER_INTR ); + + /* Enable the interrupt in the xTimer itself. */ + vClearTickInterrupt(); + XScuTimer_EnableInterrupt( &xTimer ); +} +/*-----------------------------------------------------------*/ + +void vClearTickInterrupt( void ) +{ + XScuTimer_ClearInterruptStatus( &xTimer ); +} +/*-----------------------------------------------------------*/ + +/* This is the callback function which is called by the FreeRTOS Cortex-A port +layer in response to an interrupt. If the function is called +vApplicationFPUSafeIRQHandler() then it is called after the floating point +registers have been saved. If the function is called vApplicationIRQHandler() +then it will be called without first having saved the FPU registers. See +http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html for +more information */ +void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) +{ +extern XScuGic_Config XScuGic_ConfigTable[]; +static const XScuGic_VectorTableEntry *pxVectorTable = XScuGic_ConfigTable[ XPAR_SCUGIC_SINGLE_DEVICE_ID ].HandlerTable; +uint32_t ulInterruptID; +const XScuGic_VectorTableEntry *pxVectorEntry; + + /* Re-enable interrupts. */ + __asm ( "cpsie i" ); + + /* The ID of the interrupt is obtained by bitwise anding the ICCIAR value + with 0x3FF. */ + ulInterruptID = ulICCIAR & 0x3FFUL; + if( ulInterruptID < XSCUGIC_MAX_NUM_INTR_INPUTS ) + { + /* Call the function installed in the array of installed handler functions. */ + pxVectorEntry = &( pxVectorTable[ ulInterruptID ] ); + pxVectorEntry->Handler( pxVectorEntry->CallBackRef ); + } +} + + + diff --git a/bsp_z7/freeRTOS/Xilinx.spec b/bsp_z7/freeRTOS/Xilinx.spec new file mode 100644 index 0000000..9c27dca --- /dev/null +++ b/bsp_z7/freeRTOS/Xilinx.spec @@ -0,0 +1,2 @@ +*startfile: +crti%O%s crtbegin%O%s diff --git a/bsp_z7/freeRTOS/lscript.ld b/bsp_z7/freeRTOS/lscript.ld new file mode 100644 index 0000000..8608f22 --- /dev/null +++ b/bsp_z7/freeRTOS/lscript.ld @@ -0,0 +1,289 @@ +/*******************************************************************/ +/* */ +/* This file is automatically generated by linker script generator.*/ +/* */ +/* Version: */ +/* */ +/* Copyright (c) 2010 Xilinx, Inc. All rights reserved. */ +/* */ +/* Description : Cortex-A9 Linker Script */ +/* */ +/*******************************************************************/ + +_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000; +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000; + +_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024; +_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048; +_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024; +_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024; +_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024; + +/* Define Memories in the system */ + +MEMORY +{ + ps7_ddr_0_S_AXI_BASEADDR : ORIGIN = 0x00100000, LENGTH = 0x01000000 + ps7_qspi_linear_0_S_AXI_BASEADDR : ORIGIN = 0xFC000000, LENGTH = 0x1000000 + ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0x0, LENGTH = 0x30000 + ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0xFE00 +} + +/* Specify the default entry point to the program */ + +ENTRY(_vector_table) + +/* Define the sections, and where they are mapped in memory */ + +SECTIONS +{ +.text : { + *(.freertos_vectors) + *(.vectors) + *(.boot) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.plt) + *(.gnu_warning) + *(.gcc_execpt_table) + *(.glue_7) + *(.glue_7t) + *(.vfp11_veneer) + *(.ARM.extab) + *(.gnu.linkonce.armextab.*) +} > ps7_ddr_0_S_AXI_BASEADDR + +.init : { + KEEP (*(.init)) +} > ps7_ddr_0_S_AXI_BASEADDR + +.fini : { + KEEP (*(.fini)) +} > ps7_ddr_0_S_AXI_BASEADDR + +.rodata : { + __rodata_start = .; + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + __rodata_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.rodata1 : { + __rodata1_start = .; + *(.rodata1) + *(.rodata1.*) + __rodata1_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.sdata2 : { + __sdata2_start = .; + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + __sdata2_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.sbss2 : { + __sbss2_start = .; + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + __sbss2_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.data : { + __data_start = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.jcr) + *(.got) + *(.got.plt) + __data_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.data1 : { + __data1_start = .; + *(.data1) + *(.data1.*) + __data1_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.got : { + *(.got) +} > ps7_ddr_0_S_AXI_BASEADDR + +.ctors : { + __CTOR_LIST__ = .; + ___CTORS_LIST___ = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + ___CTORS_END___ = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.dtors : { + __DTOR_LIST__ = .; + ___DTORS_LIST___ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + ___DTORS_END___ = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.fixup : { + __fixup_start = .; + *(.fixup) + __fixup_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.eh_frame : { + *(.eh_frame) +} > ps7_ddr_0_S_AXI_BASEADDR + +.eh_framehdr : { + __eh_framehdr_start = .; + *(.eh_framehdr) + __eh_framehdr_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.gcc_except_table : { + *(.gcc_except_table) +} > ps7_ddr_0_S_AXI_BASEADDR + +.mmu_tbl (ALIGN(16384)) : { + __mmu_tbl_start = .; + *(.mmu_tbl) + __mmu_tbl_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + *(.gnu.linkonce.armexidix.*.*) + __exidx_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.preinit_array : { + __preinit_array_start = .; + KEEP (*(SORT(.preinit_array.*))) + KEEP (*(.preinit_array)) + __preinit_array_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.init_array : { + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.fini_array : { + __fini_array_start = .; + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + __fini_array_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.ARM.attributes : { + __ARM.attributes_start = .; + *(.ARM.attributes) + __ARM.attributes_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.sdata : { + __sdata_start = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + __sdata_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.sbss (NOLOAD) : { + __sbss_start = .; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + __sbss_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.tdata : { + __tdata_start = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + __tdata_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.tbss : { + __tbss_start = .; + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + __tbss_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.bss (NOLOAD) : { + __bss_start = .; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + __bss_end = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); + +_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); + +/* Generate Stack and Heap definitions */ + +.heap (NOLOAD) : { + . = ALIGN(16); + _heap = .; + HeapBase = .; + _heap_start = .; + . += _HEAP_SIZE; + _heap_end = .; + HeapLimit = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +.stack (NOLOAD) : { + . = ALIGN(16); + _stack_end = .; + . += _STACK_SIZE; + . = ALIGN(16); + _stack = .; + __stack = _stack; + . = ALIGN(16); + _irq_stack_end = .; + . += _IRQ_STACK_SIZE; + . = ALIGN(16); + __irq_stack = .; + _supervisor_stack_end = .; + . += _SUPERVISOR_STACK_SIZE; + . = ALIGN(16); + __supervisor_stack = .; + _abort_stack_end = .; + . += _ABORT_STACK_SIZE; + . = ALIGN(16); + __abort_stack = .; + _fiq_stack_end = .; + . += _FIQ_STACK_SIZE; + . = ALIGN(16); + __fiq_stack = .; + _undef_stack_end = .; + . += _UNDEF_STACK_SIZE; + . = ALIGN(16); + __undef_stack = .; +} > ps7_ddr_0_S_AXI_BASEADDR + +_end = .; +} + diff --git a/bsp_z7/lib/libxil.a b/bsp_z7/lib/libxil.a new file mode 120000 index 0000000..6304922 --- /dev/null +++ b/bsp_z7/lib/libxil.a @@ -0,0 +1 @@ +../ps7_cortexa9_0/lib/libxil.a \ No newline at end of file diff --git a/bsp_z7/ps7_cortexa9_0/include/_profile_timer_hw.h b/bsp_z7/ps7_cortexa9_0/include/_profile_timer_hw.h new file mode 100644 index 0000000..b80c577 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/_profile_timer_hw.h @@ -0,0 +1,281 @@ +/****************************************************************************** +* Copyright (c) 2004 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#ifndef PROFILE_TIMER_HW_H +#define PROFILE_TIMER_HW_H + +#include "profile.h" + +#ifdef PROC_PPC +#if defined __GNUC__ +# define SYNCHRONIZE_IO __asm__ volatile ("eieio") +#elif defined __DCC__ +# define SYNCHRONIZE_IO __asm volatile(" eieio") +#else +# define SYNCHRONIZE_IO +#endif +#endif + +#ifdef PROC_PPC +#define ProfIo_In32(InputPtr) { (*(volatile u32 *)(InputPtr)); SYNCHRONIZE_IO; } +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = Value); SYNCHRONIZE_IO; } +#else +#define ProfIo_In32(InputPtr) (*(volatile u32 *)(InputPtr)); +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = (Value)); } +#endif + +#define ProfTmrCtr_mWriteReg(BaseAddress, TmrCtrNumber, RegOffset, ValueToWrite)\ + ProfIo_Out32(((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (u32)(RegOffset)), (u32)(ValueToWrite)) + +#define ProfTimerCtr_mReadReg(BaseAddress, TmrCtrNumber, RegOffset) \ + ProfIo_In32((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + (u32)(RegOffset)) + +#define ProfTmrCtr_mSetControlStatusReg(BaseAddress, TmrCtrNumber, RegisterValue)\ + ProfTmrCtr_mWriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (RegisterValue)) + +#define ProfTmrCtr_mGetControlStatusReg(BaseAddress, TmrCtrNumber) \ + ProfTimerCtr_mReadReg((u32)(BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET) + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PROC_PPC +#include "xexception_l.h" +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +#ifdef PROC_CORTEXA9 +#include "xscutimer_hw.h" +#include "xscugic.h" +#endif + +extern u32 timer_clk_ticks ; + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC + +#ifdef PPC_PIT_INTERRUPT +u32 timer_lo_clk_ticks ; /* Clk ticks when Timer is disabled in CG */ +#endif + +#ifdef PROC_PPC440 +#define XREG_TCR_PIT_INTERRUPT_ENABLE XREG_TCR_DEC_INTERRUPT_ENABLE +#define XREG_TSR_PIT_INTERRUPT_STATUS XREG_TSR_DEC_INTERRUPT_STATUS +#define XREG_SPR_PIT XREG_SPR_DEC +#define XEXC_ID_PIT_INT XEXC_ID_DEC_INT +#endif + +/* -------------------------------------------------------------------- + * Disable the Timer - During Profiling + * + * For PIT Timer - + * 1. XTime_PITDisableInterrupt() ; + * 2. Store the remaining timer clk tick + * 3. Stop the PIT Timer + *-------------------------------------------------------------------- */ + +#ifdef PPC_PIT_INTERRUPT +#define disable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val & (~XREG_TCR_PIT_INTERRUPT_ENABLE)); \ + timer_lo_clk_ticks = mfspr(XREG_SPR_PIT); \ + mtspr(XREG_SPR_PIT, 0); \ + } +#else +#define disable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v & (~XTC_CSR_ENABLE_TMR_MASK); \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Enable the Timer + * + * For PIT Timer - + * 1. Load the remaining timer clk ticks + * 2. XTime_PITEnableInterrupt() ; + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define enable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_PIT, timer_lo_clk_ticks); \ + mtspr(XREG_SPR_TCR, val | XREG_TCR_PIT_INTERRUPT_ENABLE); \ + } +#else +#define enable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v | XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + * For PIT Timer - + * 1. Load the timer clk ticks + * 2. Enable AutoReload and Interrupt + * 3. Clear PIT Timer Status bits + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define timer_ack() \ + { \ + u32 val; \ + mtspr(XREG_SPR_PIT, timer_clk_ticks); \ + mtspr(XREG_SPR_TSR, XREG_TSR_PIT_INTERRUPT_STATUS); \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val| XREG_TCR_PIT_INTERRUPT_ENABLE| XREG_TCR_AUTORELOAD_ENABLE); \ + } +#else +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg(PROFILE_TIMER_BASEADDR, 0); \ + ProfTmrCtr_mSetControlStatusReg(PROFILE_TIMER_BASEADDR, 0, csr); \ + } +#endif + +/*-------------------------------------------------------------------- */ +#endif /* PROC_PPC */ +/* -------------------------------------------------------------------- */ + + + + +/* -------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(Addr); \ + tmp_v = tmp_v & (u32)(~XTC_CSR_ENABLE_TMR_MASK); \ + u32 OutAddr = (u32)PROFILE_TIMER_BASEADDR; \ + OutAddr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + OutAddr += (u32)XTC_TCSR_OFFSET; \ + ProfIo_Out32(OutAddr, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = (u32)ProfIo_In32(Addr); \ + tmp_v = tmp_v | (u32)XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((u32)(PROFILE_TIMER_BASEADDR) + (u32)XTmrCtr_Offsets[(u16)(0)] + (u32)XTC_TCSR_OFFSET, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0); \ + ProfTmrCtr_mSetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)csr); \ + } + +/*-------------------------------------------------------------------- */ +#endif /* PROC_MICROBLAZE */ +/*-------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg &= (~XSCUTIMER_CONTROL_ENABLE_MASK);\ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg |= XSCUTIMER_CONTROL_ENABLE_MASK; \ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ +{ \ + Xil_Out32((u32)PROFILE_TIMER_BASEADDR + (u32)XSCUTIMER_ISR_OFFSET, \ + (u32)XSCUTIMER_ISR_EVENT_FLAG_MASK);\ +} + +/*-------------------------------------------------------------------- */ +#endif /* PROC_CORTEXA9 */ +/*-------------------------------------------------------------------- */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/include/bspconfig.h b/bsp_z7/ps7_cortexa9_0/include/bspconfig.h new file mode 100644 index 0000000..4ff1d52 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/bspconfig.h @@ -0,0 +1,15 @@ + +/******************************************************************* +* Copyright (c) 2010-2020 Xilinx, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +*******************************************************************/ + +#ifndef BSPCONFIG_H /* prevent circular inclusions */ +#define BSPCONFIG_H /* by using protection macros */ + +#define MICROBLAZE_PVR_NONE + +/* Definition for hard-float ABI */ +#define FPU_HARD_FLOAT_ABI_ENABLED 1 + +#endif /*end of __BSPCONFIG_H_*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/diskio.h b/bsp_z7/ps7_cortexa9_0/include/diskio.h new file mode 100644 index 0000000..1c2b4a4 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/diskio.h @@ -0,0 +1,83 @@ +/*-----------------------------------------------------------------------/ +/ Low level disk interface modlue include file (C)ChaN, 2022 / +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO_DEFINED +#define _DISKIO_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + +#define USE_WRITE 1 /* 1: Enable disk_write function */ +#define USE_IOCTL 1 /* 1: Enable disk_ioctl function */ + +#include "ff.h" +#include "xil_types.h" + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ + + +DSTATUS disk_initialize (BYTE pdrv); +DSTATUS disk_status (BYTE pdrv); +DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count); +DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count); +DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); + + +/* Disk Status Bits (DSTATUS) */ + +#define STA_NOINIT 0x01U /* Drive not initialized */ +#define STA_NODISK 0x02U /* No medium in the drive */ +#define STA_PROTECT 0x04U /* Write protected */ + + +/* Command code for disk_ioctrl fucntion */ + +/* Generic command (Used by FatFs) */ +#define CTRL_SYNC 0U /* Complete pending write process (needed at FF_FS_READONLY == 0) */ +#define GET_SECTOR_COUNT 1U /* Get media size (needed at FF_USE_MKFS == 1) */ +#define GET_SECTOR_SIZE 2U /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ +#define GET_BLOCK_SIZE 3U /* Get erase block size (needed at FF_USE_MKFS == 1) */ +#define CTRL_TRIM 4U /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ + +/* Generic command (Not used by FatFs) */ +#define CTRL_POWER 5U /* Get/Set power status */ +#define CTRL_LOCK 6U /* Lock/Unlock media removal */ +#define CTRL_EJECT 7U /* Eject media */ +#define CTRL_FORMAT 8U /* Create physical format on the media */ + +/* MMC/SDC specific ioctl command */ +#define MMC_GET_TYPE 10U /* Get card type */ +#define MMC_GET_CSD 11U /* Get CSD */ +#define MMC_GET_CID 12U /* Get CID */ +#define MMC_GET_OCR 13U /* Get OCR */ +#define MMC_GET_SDSTAT 14U /* Get SD status */ +#define ISDIO_READ 55 /* Read data form SD iSDIO register */ +#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ +#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ + +/* ATA/CF specific ioctl command */ +#define ATA_GET_REV 20U /* Get F/W revision */ +#define ATA_GET_MODEL 21U /* Get model name */ +#define ATA_GET_SN 22U /* Get serial number */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/include/ff.h b/bsp_z7/ps7_cortexa9_0/include/ff.h new file mode 100644 index 0000000..6f522f9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/ff.h @@ -0,0 +1,448 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT Filesystem module R0.15 / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 2022, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: + +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/ +/----------------------------------------------------------------------------*/ + + +#ifndef FF_DEFINED +#define FF_DEFINED 80286 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_types.h" +#include "ffconf.h" /* FatFs configuration options */ + +#if FF_DEFINED != FFCONF_DEF +#error Wrong configuration file (ffconf.h). +#endif + + +/* Integer types used for FatFs API */ + +#if defined(_WIN32) /* Windows VC++ (for development only) */ +#define FF_INTDEF 2 +#include +typedef unsigned __int64 QWORD; +#include +#define isnan(v) _isnan(v) +#define isinf(v) (!_finite(v)) + +#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */ +#define FF_INTDEF 2 +#include +typedef unsigned int UINT; /* int must be 16-bit or 32-bit */ +typedef unsigned char BYTE; /* char must be 8-bit */ +typedef uint16_t WORD; /* 16-bit unsigned integer */ +typedef uint32_t DWORD; /* 32-bit unsigned integer */ +typedef uint64_t QWORD; /* 64-bit unsigned integer */ +typedef WORD WCHAR; /* UTF-16 character type */ + +#else /* Earlier than C99 */ +#define FF_INTDEF 1 +typedef unsigned int UINT; /* int must be 16-bit or 32-bit */ +typedef unsigned char BYTE; /* char must be 8-bit */ +typedef unsigned short WORD; /* 16-bit unsigned integer */ +typedef unsigned long DWORD; /* 32-bit unsigned integer */ +typedef WORD WCHAR; /* UTF-16 character type */ +#endif + + +/* Type of file size and LBA variables */ + +#if FF_FS_EXFAT +#if FF_INTDEF != 2 +#error exFAT feature wants C99 or later +#endif +typedef QWORD FSIZE_t; +#if FF_LBA64 +typedef QWORD LBA_t; +#else +typedef DWORD LBA_t; +#endif +#else +#if FF_LBA64 +#error exFAT needs to be enabled when enable 64-bit LBA +#endif +typedef DWORD FSIZE_t; +typedef DWORD LBA_t; +#endif + + + +/* Type of path name strings on FatFs API (TCHAR) */ + +#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */ +typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */ +typedef char TCHAR; +#define _T(x) u8 ## x +#define _TEXT(x) u8 ## x +#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */ +typedef DWORD TCHAR; +#define _T(x) U ## x +#define _TEXT(x) U ## x +#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3) +#error Wrong FF_LFN_UNICODE setting +#else /* ANSI/OEM code in SBCS/DBCS */ +typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#endif + + + +/* Definitions of volume management */ + +#if FF_MULTI_PARTITION /* Multiple partition configuration */ +typedef struct { + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ +} PARTITION; +extern PARTITION VolToPart[]; /* Volume - Partition mapping table */ +#endif + +#if FF_STR_VOLUME_ID +#ifndef FF_VOLUME_STRS +extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */ +#endif +#endif + + + +/* Filesystem object structure (FATFS) */ + +typedef struct { + BYTE fs_type; /* Filesystem type (0:not mounted) */ + BYTE pdrv; /* Volume hosting physical drive */ + BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */ + BYTE n_fats; /* Number of FATs (1 or 2) */ + BYTE wflag; /* win[] status (b0:dirty) */ + BYTE fsi_flag; /* FSINFO status (b7:disabled, b0:dirty) */ + WORD id; /* Volume mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ + WORD csize; /* Cluster size [sectors] */ +#if FF_MAX_SS != FF_MIN_SS + WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ +#endif +#if FF_USE_LFN + WCHAR* lfnbuf; /* LFN working buffer */ +#endif +#if FF_FS_EXFAT + BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ +#endif +#if !FF_FS_READONLY + DWORD last_clst; /* Last allocated cluster */ + DWORD free_clst; /* Number of free clusters */ +#endif +#if FF_FS_RPATH + DWORD cdir; /* Current directory start cluster (0:root) */ +#if FF_FS_EXFAT + DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ + DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ + DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ +#endif +#endif + DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ + DWORD fsize; /* Number of sectors per FAT */ + LBA_t volbase; /* Volume base sector */ + LBA_t fatbase; /* FAT base sector */ + LBA_t dirbase; /* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */ + LBA_t database; /* Data base sector */ +#if FF_FS_EXFAT + LBA_t bitbase; /* Allocation bitmap base sector */ +#endif + LBA_t winsect; /* Current sector appearing in the win[] */ +#ifdef __ICCARM__ +#pragma data_alignment = 32 + BYTE win[FF_MAX_SS]; +#else +#ifdef __aarch64__ + BYTE win[FF_MAX_SS] __attribute__ ((aligned(64))); /* Disk access window for Directory, FAT (and file data at tiny cfg) */ +#else + BYTE win[FF_MAX_SS] __attribute__ ((aligned(32))); /* Disk access window for Directory, FAT (and file data at tiny cfg) */ +#endif +#endif +} FATFS; + + + +/* Object ID and allocation information (FFOBJID) */ + +typedef struct { + FATFS* fs; /* Pointer to the hosting volume of this object */ + WORD id; /* Hosting volume's mount ID */ + BYTE attr; /* Object attribute */ + BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */ + DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ + FSIZE_t objsize; /* Object size (valid when sclust != 0) */ +#if FF_FS_EXFAT + DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */ + DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ + DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ + DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ + DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ +#endif +#if FF_FS_LOCK + UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ +#endif +} FFOBJID; + + + +/* File object structure (FIL) */ + +typedef struct { + FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ + BYTE flag; /* File status flags */ + BYTE err; /* Abort flag (error code) */ + FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ + DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ + LBA_t sect; /* Sector number appearing in buf[] (0:invalid) */ +#if !FF_FS_READONLY + LBA_t dir_sect; /* Sector number containing the directory entry (not used at exFAT) */ + BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */ +#endif +#if FF_USE_FASTSEEK + DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ +#endif +#if !FF_FS_TINY +#ifdef __ICCARM__ +#pragma data_alignment = 32 + BYTE buf[FF_MAX_SS]; /* File private data read/write window */ +#else +#ifdef __aarch64__ + BYTE buf[FF_MAX_SS] __attribute__ ((aligned(64))); /* File private data read/write window */ +#else + BYTE buf[FF_MAX_SS] __attribute__ ((aligned(32))); /* File private data read/write window */ +#endif +#endif +#endif +} FIL; + + + +/* Directory object structure (DIR) */ + +typedef struct { + FFOBJID obj; /* Object identifier */ + DWORD dptr; /* Current read/write offset */ + DWORD clust; /* Current cluster */ + LBA_t sect; /* Current sector (0:Read operation has terminated) */ + BYTE* dir; /* Pointer to the directory item in the win[] */ + BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ +#if FF_USE_LFN + DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ +#endif +#if FF_USE_FIND + const TCHAR* pat; /* Pointer to the name matching pattern */ +#endif +} DIR; + + + +/* File information structure (FILINFO) */ + +typedef struct { + FSIZE_t fsize; /* File size */ + WORD fdate; /* Modified date */ + WORD ftime; /* Modified time */ + BYTE fattrib; /* File attribute */ +#if FF_USE_LFN + TCHAR altname[FF_SFN_BUF + 1];/* Alternative file name */ + TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */ +#else + TCHAR fname[12 + 1]; /* File name */ +#endif +} FILINFO; + + + +/* Format parameter structure (MKFS_PARM) */ + +typedef struct { + BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */ + BYTE n_fat; /* Number of FATs */ + UINT align; /* Data area alignment (sector) */ + UINT n_root; /* Number of root directory entries */ + DWORD au_size; /* Cluster size (byte) */ +} MKFS_PARM; + + + +/* File function return code (FRESULT) */ + +typedef enum { + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Access denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ + FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ +} FRESULT; + + + + +/*--------------------------------------------------------------*/ +/* FatFs Module Application Interface */ +/*--------------------------------------------------------------*/ + +FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ +FRESULT f_close (FIL* fp); /* Close an open file object */ +FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ +FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ +FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ +FRESULT f_truncate (FIL* fp); /* Truncate the file */ +FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ +FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ +FRESULT f_closedir (DIR* dp); /* Close an open directory */ +FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ +FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ +FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ +FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ +FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ +FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ +FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ +FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ +FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ +FRESULT f_chdir (const TCHAR* path); /* Change current directory */ +FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ +FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ +FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ +FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ +FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ +FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ +FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */ +FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ +FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void* work, UINT len); /* Create a FAT volume */ +FRESULT f_fdisk (BYTE pdrv, const LBA_t ptbl[], void* work); /* Divide a physical drive into some partitions */ +FRESULT f_setcp (WORD cp); /* Set current code page */ +int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ +int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ +int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ +TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ + +/* Some API fucntions are implemented as macro */ + +#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) +#define f_error(fp) ((fp)->err) +#define f_tell(fp) ((fp)->fptr) +#define f_size(fp) ((fp)->obj.objsize) +#define f_rewind(fp) f_lseek((fp), 0) +#define f_rewinddir(dp) f_readdir((dp), 0) +#define f_rmdir(path) f_unlink(path) +#define f_unmount(path) f_mount(0, path, 0) + + + + +/*--------------------------------------------------------------*/ +/* Additional Functions */ +/*--------------------------------------------------------------*/ + +/* RTC function (provided by user) */ +#if !FF_FS_READONLY && !FF_FS_NORTC +DWORD get_fattime (void); /* Get current time */ +#endif + + +/* LFN support functions (defined in ffunicode.c) */ + +#if FF_USE_LFN >= 1 +WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ +WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */ +DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */ +#endif + + +/* O/S dependent functions (samples available in ffsystem.c) */ + +#if FF_USE_LFN == 3 /* Dynamic memory allocation */ +void* ff_memalloc (UINT msize); /* Allocate memory block */ +void ff_memfree (void* mblock); /* Free memory block */ +#endif +#if FF_FS_REENTRANT /* Sync functions */ +int ff_mutex_create (int vol); /* Create a sync object */ +void ff_mutex_delete (int vol); /* Delete a sync object */ +int ff_mutex_take (int vol); /* Lock sync object */ +void ff_mutex_give (int vol); /* Unlock sync object */ +#endif + + + + +/*--------------------------------------------------------------*/ +/* Flags and Offset Address */ +/*--------------------------------------------------------------*/ + +/* File access mode and open method flags (3rd argument of f_open) */ +#define FA_READ 0x01 +#define FA_WRITE 0x02 +#define FA_OPEN_EXISTING 0x00 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA_OPEN_APPEND 0x30 + +/* Fast seek controls (2nd argument of f_lseek) */ +#define CREATE_LINKMAP ((FSIZE_t)0 - 1) + +/* Format options (2nd argument of f_mkfs) */ +#define FM_FAT 0x01 +#define FM_FAT32 0x02 +#define FM_EXFAT 0x04 +#define FM_ANY 0x07 +#define FM_SFD 0x08 + +/* Filesystem type (FATFS.fs_type) */ +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 +#define FS_EXFAT 4 + +/* File attribute bits for directory entry (FILINFO.fattrib) */ +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ + + +#ifdef __cplusplus +} +#endif + +#endif /* FF_DEFINED */ diff --git a/bsp_z7/ps7_cortexa9_0/include/ffconf.h b/bsp_z7/ps7_cortexa9_0/include/ffconf.h new file mode 100644 index 0000000..007d807 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/ffconf.h @@ -0,0 +1,397 @@ +/*---------------------------------------------------------------------------/ +/ Configurations of FatFs Module +/---------------------------------------------------------------------------*/ + +#define FFCONF_DEF 80286 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xparameters.h" + +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ + +#ifdef FILE_SYSTEM_READ_ONLY +#define FF_FS_READONLY 1 /* 1:Read only */ +#else +#define FF_FS_READONLY 0 /* 0:Read/Write */ +#endif +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define FF_FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: Basic functions are fully enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#if FILE_SYSTEM_USE_STRFUNC == 0 +#define FF_USE_STRFUNC 0 /* 0:Disable */ +#elif FILE_SYSTEM_USE_STRFUNC == 1 +#define FF_USE_STRFUNC 1 /* 1:Enable */ +#elif FILE_SYSTEM_USE_STRFUNC == 2 +#define FF_USE_STRFUNC 2 /* 2:Enable */ +#endif +/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). +/ +/ 0: Disable string functions. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. */ + + +#define FF_USE_FIND 0 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + +#ifdef FILE_SYSTEM_USE_MKFS +#define FF_USE_MKFS 1 /* 1:Enable */ +#else +#define FF_USE_MKFS 0 /* 0:Disable */ +#endif +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define FF_USE_EXPAND 0 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#ifdef FILE_SYSTEM_USE_CHMOD +#define FF_USE_CHMOD 1 /* 1:Enable */ +#else +#define FF_USE_CHMOD 0 /* 0:Disable */ +#endif +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ + + +#define FF_USE_LABEL 0 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define FF_USE_FORWARD 0 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_STRFUNC 0 +#define FF_PRINT_LLI 1 +#define FF_PRINT_FLOAT 1 +#define FF_STRF_ENCODE 3 +/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and +/ f_printf(). +/ +/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. +/ +/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2 +/ makes f_printf() support floating point argument. These features want C99 or later. +/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character +/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE +/ to be read/written via those functions. +/ +/ 0: ANSI/OEM in current CP +/ 1: Unicode in UTF-16LE +/ 2: Unicode in UTF-16BE +/ 3: Unicode in UTF-8 +*/ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define FF_CODE_PAGE 932 +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect code page setting can cause a file open failure. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +/ 0 - Include all code pages above and configured by f_setcp() +*/ + + +#ifdef FILE_SYSTEM_USE_LFN +#define FF_USE_LFN FILE_SYSTEM_USE_LFN /* 0 to 3 */ +#else +#define FF_USE_LFN 0 /* 0 to 3 */ +#endif +#define FF_MAX_LFN 255 +/* The FF_USE_LFN switches the support for LFN (long file name). +/ +/ 0: Disable LFN. FF_MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function +/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and +/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. +/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can +/ be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN +/ specification. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */ + + +#define FF_LFN_UNICODE 0 +/* This option switches the character encoding on the API when LFN is enabled. +/ +/ 0: ANSI/OEM in current CP (TCHAR = char) +/ 1: Unicode in UTF-16 (TCHAR = WCHAR) +/ 2: Unicode in UTF-8 (TCHAR = char) +/ 3: Unicode in UTF-32 (TCHAR = DWORD) +/ +/ Also behavior of string I/O functions will be affected by this option. +/ When LFN is not enabled, this option has no effect. */ + + +#define FF_LFN_BUF 255 +#define FF_SFN_BUF 12 +/* This set of options defines size of file name members in the FILINFO structure +/ which is used to read out directory items. These values should be suffcient for +/ the file names to read. The maximum possible length of the read file name depends +/ on character encoding. When LFN is not enabled, these options have no effect. */ + + +#if FILE_SYSTEM_SET_FS_RPATH == 0 +#define FF_FS_RPATH 0U +#elif FILE_SYSTEM_SET_FS_RPATH == 1 +#define FF_FS_RPATH 1U +#elif FILE_SYSTEM_SET_FS_RPATH == 2 +#define FF_FS_RPATH 2U +#endif +/* This option configures support for relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#if FILE_SYSTEM_NUM_LOGIC_VOL == 1 +#define FF_VOLUMES 1U +#elif FILE_SYSTEM_NUM_LOGIC_VOL == 2 +#define FF_VOLUMES 2U +#elif FILE_SYSTEM_NUM_LOGIC_VOL == 3 +#define FF_VOLUMES 3U +#elif FILE_SYSTEM_NUM_LOGIC_VOL == 4 +#define FF_VOLUMES 4U +#elif FILE_SYSTEM_NUM_LOGIC_VOL == 5 +#define FF_VOLUMES 5U +#elif FILE_SYSTEM_NUM_LOGIC_VOL == 6 +#define FF_VOLUMES 6U +#elif FILE_SYSTEM_NUM_LOGIC_VOL == 7 +#define FF_VOLUMES 7U +#elif FILE_SYSTEM_NUM_LOGIC_VOL == 8 +#define FF_VOLUMES 8U +#elif FILE_SYSTEM_NUM_LOGIC_VOL == 9 +#define FF_VOLUMES 9U +#else +#define FF_VOLUMES 10U +#endif +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define FF_STR_VOLUME_ID 0 +#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. +/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each +/ logical drives. Number of items must not be less than FF_VOLUMES. Valid +/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are +/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is +/ not defined, a user defined volume string table is needed as: +/ +/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... +*/ + + +#ifdef FILE_SYSTEM_MULTI_PARTITION +#define FF_MULTI_PARTITION 1 /* 1:Enable multiple partition */ +#else +#define FF_MULTI_PARTITION 0 /* 0:Single partition */ +#endif +/* This option switches support for multiple volumes on the physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When this function is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ function will be available. */ + + +#define FF_MIN_SS 512 +#define FF_MAX_SS 512 +/* This set of options configures the range of sector size to be supported. (512, +/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk, but a larger value may be required for on-board flash memory and some +/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured +/ for variable sector size mode and disk_ioctl() function needs to implement +/ GET_SECTOR_SIZE command. */ + + +#define FF_LBA64 0 +/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable) +/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */ + + +#define FF_MIN_GPT 0x10000000 +/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and +/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */ + + +#ifdef FILE_SYSTEM_USE_TRIM +#define FF_USE_TRIM 1 +#else +#define FF_USE_TRIM 0 +#endif +/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_TINY 0 +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ + + +#ifdef FILE_SYSTEM_FS_EXFAT +#define FF_FS_EXFAT 1 +#else +#define FF_FS_EXFAT 0 +#endif +/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) +/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define FF_FS_NORTC 0 +#define FF_NORTC_MON 1 +#define FF_NORTC_MDAY 1 +#define FF_NORTC_YEAR 2022 +/* The option FF_FS_NORTC switches timestamp feature. If the system does not have +/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the +/ timestamp feature. Every object modified by FatFs will have a fixed timestamp +/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. +/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to read current time form real-time clock. FF_NORTC_MON, +/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. +/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */ + + +#define FF_FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at the first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + +#define FF_FS_LOCK 0 +/* The option FF_FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +#define FF_FS_REENTRANT 0 +#define FF_FS_TIMEOUT 1000 +/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this featuer. +/ +/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give() +/ function, must be added to the project. Samples are available in ffsystem.c. +/ +/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick. +*/ +#ifdef FILE_SYSTEM_WORD_ACCESS +#define FF_WORD_ACCESS 1 +#else +#define FF_WORD_ACCESS 0 +#endif +/* The FF_WORD_ACCESS option is an only platform dependent option. It defines +/ which access method is used to the word data on the FAT volume. +/ +/ 0: Byte-by-byte access. Always compatible with all platforms. +/ 1: Word access. Do not choose this unless under both the following conditions. +/ +/ * Address misaligned memory access is always allowed for ALL instructions. +/ * Byte order on the memory is little-endian. +/ +/ If it is the case, FF_WORD_ACCESS can also be set to 1 to improve performance and +/ reduce code size. Following table shows an example of some processor types. +/ +/ ARM7TDMI 0 ColdFire 0 V850E 0 +/ Cortex-M3 0 Z80 0/1 V850ES 0/1 +/ Cortex-M0 0 RX600(LE) 0/1 TLCS-870 0/1 +/ AVR 0/1 RX600(BE) 0 TLCS-900 0/1 +/ AVR32 0 RL78 0 R32C 0 +/ PIC18 0/1 SH-2 0 M16C 0/1 +/ PIC24 0 H8S 0 MSP430 0 +/ PIC32 0 H8/300H 0 x86 0/1 +*/ + +#ifdef __cplusplus +} +#endif + +/*--- End of configuration options ---*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/mblaze_nt_types.h b/bsp_z7/ps7_cortexa9_0/include/mblaze_nt_types.h new file mode 100644 index 0000000..6b51ea9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/mblaze_nt_types.h @@ -0,0 +1,28 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + + +#ifndef _MBLAZE_NT_TYPES_H +#define _MBLAZE_NT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char byte; +typedef short half; +typedef int word; +typedef unsigned char ubyte; +typedef unsigned short uhalf; +typedef unsigned int uword; +typedef ubyte boolean; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/include/print.c b/bsp_z7/ps7_cortexa9_0/include/print.c new file mode 100644 index 0000000..e8ac3d4 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/print.c @@ -0,0 +1,36 @@ +/* print.c -- print a string on the output device. + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + * + */ + +/* + * print -- do a raw print of a string + */ +#include "xil_printf.h" + +void print(const char8 *ptr) +{ +#if defined (__aarch64__) && (HYP_GUEST == 1) && (EL1_NONSECURE == 1) && defined (XEN_USE_PV_CONSOLE) + XPVXenConsole_Write(ptr); +#else +#ifdef STDOUT_BASEADDRESS + while (*ptr != (char8)0) { + outbyte (*ptr); + ptr++; + } +#else +(void)ptr; +#endif +#endif +} diff --git a/bsp_z7/ps7_cortexa9_0/include/profile.h b/bsp_z7/ps7_cortexa9_0/include/profile.h new file mode 100644 index 0000000..27b3df1 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/profile.h @@ -0,0 +1,105 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#ifndef PROFILE_H +#define PROFILE_H 1 + +#include +#include "xil_types.h" +#include "profile_config.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void _system_init( void ) ; +void _system_clean( void ) ; +void mcount(u32 frompc, u32 selfpc); +void profile_intr_handler( void ) ; +void _profile_init( void ); + + + +/**************************************************************************** + * Profiling on hardware - Hash table maintained on hardware and data sent + * to xmd for gmon.out generation. + ****************************************************************************/ +/* + * histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER u16 + +struct tostruct { + u32 selfpc; + s32 count; + s16 link; + u16 pad; +}; + +struct fromstruct { + u32 frompc ; + s16 link ; + u16 pad ; +} ; + +/* + * general rounding functions. + */ +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) + +/* + * The profiling data structures are housed in this structure. + */ +struct gmonparam { + s32 state; + + /* Histogram Information */ + u16 *kcount; /* No. of bins in histogram */ + u32 kcountsize; /* Histogram samples */ + + /* Call-graph Information */ + struct fromstruct *froms; + u32 fromssize; + struct tostruct *tos; + u32 tossize; + + /* Initialization I/Ps */ + u32 lowpc; + u32 highpc; + u32 textsize; + /* u32 cg_froms, */ + /* u32 cg_tos, */ +}; +extern struct gmonparam *_gmonparam; +extern s32 n_gmon_sections; + +/* + * Possible states of profiling. + */ +#define GMON_PROF_ON 0 +#define GMON_PROF_BUSY 1 +#define GMON_PROF_ERROR 2 +#define GMON_PROF_OFF 3 + +/* + * Sysctl definitions for extracting profiling information from the kernel. + */ +#define GPROF_STATE 0 /* int: profiling enabling variable */ +#define GPROF_COUNT 1 /* struct: profile tick count buffer */ +#define GPROF_FROMS 2 /* struct: from location hash bucket */ +#define GPROF_TOS 3 /* struct: destination/count structure */ +#define GPROF_GMONPARAM 4 /* struct: profiling parameters (see above) */ + +#ifdef __cplusplus +} +#endif + +#endif /* PROFILE_H */ diff --git a/bsp_z7/ps7_cortexa9_0/include/sleep.h b/bsp_z7/ps7_cortexa9_0/include/sleep.h new file mode 100644 index 0000000..3c9c788 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/sleep.h @@ -0,0 +1,105 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +/*****************************************************************************/ +/** +* @file sleep.h +* +* This header file contains ARM Cortex A53,A9,R5,Microblaze specific sleep +* related APIs. +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6   srm  11/02/17 Added processor specific sleep routines
+*								 function prototypes.
+* 7.7	sk   01/10/22 Typecast sleep declaration argument from unsigned int to
+* 		      u32 to fix misra_c_2012_directive_4_6 violation.
+* 7.7	sk   01/10/22 Modify the return type of sleep_R5 and usleep_R5 from
+* 		      unsigned to void to fix misra_c_2012_rule_17_7 violation.
+* 8.0	sk   03/02/22 Update usleep_R5 and usleep parameter types to fix misra_
+*		      c_2012_directive_4_6 violation.
+* 8.0	sk   03/17/22 Modify the return type of usleep_MB from int to void and
+*		      sleep_MB from unsigned to void to fix misra_c_2012_rule_
+*		      17_7 violation.
+* 8.0	sk   03/17/22 Modify sleep_MB parameter type from unsigned int to
+*		      u32 and usleep_MB parameter type from unsigned long to
+*		      ULONG to fix misra_c_2012_rule_4_6 violation.
+*
+* 
+* +******************************************************************************/ + +#ifndef SLEEP_H +#define SLEEP_H + +#include "xil_types.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/** +* +* This macro polls an address periodically until a condition is met or till the +* timeout occurs. +* The minimum timeout for calling this macro is 100us. If the timeout is less +* than 100us, it still waits for 100us. Also the unit for the timeout is 100us. +* If the timeout is not a multiple of 100us, it waits for a timeout of +* the next usec value which is a multiple of 100us. +* +* @param IO_func - accessor function to read the register contents. +* Depends on the register width. +* @param ADDR - Address to be polled +* @param VALUE - variable to read the value +* @param COND - Condition to checked (usually involves VALUE) +* @param TIMEOUT_US - timeout in micro seconds +* +* @return 0 - when the condition is met +* -1 - when the condition is not met till the timeout period +* +* @note none +* +*****************************************************************************/ +#define Xil_poll_timeout(IO_func, ADDR, VALUE, COND, TIMEOUT_US) \ + ( { \ + u64 timeout = TIMEOUT_US/100; \ + if(TIMEOUT_US%100!=0) \ + timeout++; \ + for(;;) { \ + VALUE = IO_func(ADDR); \ + if(COND) \ + break; \ + else { \ + usleep(100); \ + timeout--; \ + if(timeout==0) \ + break; \ + } \ + } \ + (timeout>0) ? 0 : -1; \ + } ) + +void usleep(ULONG useconds); +void sleep(u32 seconds); +void usleep_R5(ULONG useconds); +void sleep_R5(u32 seconds); +void usleep_MB(ULONG useconds); +void sleep_MB(u32 seconds); +int usleep_A53(unsigned long useconds); +unsigned sleep_A53(unsigned int seconds); +int usleep_A9(unsigned long useconds); +unsigned sleep_A9(unsigned int seconds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/include/smc.h b/bsp_z7/ps7_cortexa9_0/include/smc.h new file mode 100644 index 0000000..b4fa9d3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/smc.h @@ -0,0 +1,97 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file smc.h +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  11/03/09 Initial release.
+* 4.2	pkp	 08/04/14 Removed function definition of XSmc_NorInit and XSmc_NorInit
+*					  as smc.c is removed
+* 
+* +* @note None. +* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef SMC_H /* prevent circular inclusions */ +#define SMC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xil_io.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory controller configuration register offset */ +#define XSMCPSS_MC_STATUS 0x000U /* Controller status reg, RO */ +#define XSMCPSS_MC_INTERFACE_CONFIG 0x004U /* Interface config reg, RO */ +#define XSMCPSS_MC_SET_CONFIG 0x008U /* Set configuration reg, WO */ +#define XSMCPSS_MC_CLR_CONFIG 0x00CU /* Clear config reg, WO */ +#define XSMCPSS_MC_DIRECT_CMD 0x010U /* Direct command reg, WO */ +#define XSMCPSS_MC_SET_CYCLES 0x014U /* Set cycles register, WO */ +#define XSMCPSS_MC_SET_OPMODE 0x018U /* Set opmode register, WO */ +#define XSMCPSS_MC_REFRESH_PERIOD_0 0x020U /* Refresh period_0 reg, RW */ +#define XSMCPSS_MC_REFRESH_PERIOD_1 0x024U /* Refresh period_1 reg, RW */ + +/* Chip select configuration register offset */ +#define XSMCPSS_CS_IF0_CHIP_0_OFFSET 0x100U /* Interface 0 chip 0 config */ +#define XSMCPSS_CS_IF0_CHIP_1_OFFSET 0x120U /* Interface 0 chip 1 config */ +#define XSMCPSS_CS_IF0_CHIP_2_OFFSET 0x140U /* Interface 0 chip 2 config */ +#define XSMCPSS_CS_IF0_CHIP_3_OFFSET 0x160U /* Interface 0 chip 3 config */ +#define XSMCPSS_CS_IF1_CHIP_0_OFFSET 0x180U /* Interface 1 chip 0 config */ +#define XSMCPSS_CS_IF1_CHIP_1_OFFSET 0x1A0U /* Interface 1 chip 1 config */ +#define XSMCPSS_CS_IF1_CHIP_2_OFFSET 0x1C0U /* Interface 1 chip 2 config */ +#define XSMCPSS_CS_IF1_CHIP_3_OFFSET 0x1E0U /* Interface 1 chip 3 config */ + +/* User configuration register offset */ +#define XSMCPSS_UC_STATUS_OFFSET 0x200U /* User status reg, RO */ +#define XSMCPSS_UC_CONFIG_OFFSET 0x204U /* User config reg, WO */ + +/* Integration test register offset */ +#define XSMCPSS_IT_OFFSET 0xE00U + +/* ID configuration register offset */ +#define XSMCPSS_ID_PERIP_0_OFFSET 0xFE0U +#define XSMCPSS_ID_PERIP_1_OFFSET 0xFE4U +#define XSMCPSS_ID_PERIP_2_OFFSET 0xFE8U +#define XSMCPSS_ID_PERIP_3_OFFSET 0xFECU +#define XSMCPSS_ID_PCELL_0_OFFSET 0xFF0U +#define XSMCPSS_ID_PCELL_1_OFFSET 0xFF4U +#define XSMCPSS_ID_PCELL_2_OFFSET 0xFF8U +#define XSMCPSS_ID_PCELL_3_OFFSET 0xFFCU + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SMC_H */ + +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/include/vectors.h b/bsp_z7/ps7_cortexa9_0/include/vectors.h new file mode 100644 index 0000000..f9747c7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/vectors.h @@ -0,0 +1,64 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file vectors.h +* +* This file contains the C level vector prototypes for the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/10 Initial version, moved over from bsp area
+* 6.0   mus  07/27/16 Consolidated vectors for a9,a53 and r5 processors
+* 8.0	sk   03/02/22 Update _VECTORS_H_ with VECTORS_H_ to fix misra_c_
+* 		      2012_rule_21_1 violation.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef VECTORS_H_ +#define VECTORS_H_ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void FIQInterrupt(void); +void IRQInterrupt(void); +#if !defined (__aarch64__) +void SWInterrupt(void); +void DataAbortInterrupt(void); +void PrefetchAbortInterrupt(void); +void UndefinedException(void); +#else +void SynchronousInterrupt(void); +void SErrorInterrupt(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xadcps.h b/bsp_z7/ps7_cortexa9_0/include/xadcps.h new file mode 100644 index 0000000..980f394 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xadcps.h @@ -0,0 +1,571 @@ +/****************************************************************************** +* Copyright (C) 2011 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xadcps.h +* @addtogroup xadcps_v2_6 +* @{ +* @details +* +* The XAdcPs driver supports the Xilinx XADC/ADC device. +* +* The XADC/ADC device has the following features: +* - 10-bit, 200-KSPS (kilo samples per second) +* Analog-to-Digital Converter (ADC) +* - Monitoring of on-chip supply voltages and temperature +* - 1 dedicated differential analog-input pair and +* 16 auxiliary differential analog-input pairs +* - Automatic alarms based on user defined limits for the on-chip +* supply voltages and temperature +* - Automatic Channel Sequencer, programmable averaging, programmable +* acquisition time for the external inputs, unipolar or differential +* input selection for the external inputs +* - Inbuilt Calibration +* - Optional interrupt request generation +* +* +* The user should refer to the hardware device specification for detailed +* information about the device. +* +* This header file contains the prototypes of driver functions that can +* be used to access the XADC/ADC device. +* +* +* XADC Channel Sequencer Modes +* +* The XADC Channel Sequencer supports the following operating modes: +* +* - Default : This is the default mode after power up. +* In this mode of operation the XADC operates in +* a sequence mode, monitoring the on chip sensors: +* Temperature, VCCINT, and VCCAUX. +* - One pass through sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers for a single pass and then stops. +* - Continuous cycling of sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers continuously. +* - Single channel mode: In this mode the XADC Channel +* Sequencer is disabled and the XADC operates in a +* Single Channel Mode. +* The XADC can operate either in a Continuous or Event +* driven sampling mode in the single channel mode. +* - Simultaneous Sampling Mode: In this mode the XADC Channel +* Sequencer will automatically sequence through eight fixed pairs +* of auxiliary analog input channels for simulataneous conversion. +* - Independent ADC mode: In this mode the first ADC (A) is used to +* is used to implement a fixed monitoring mode similar to the +* default mode but the alarm fucntions ar eenabled. +* The second ADC (B) is available to be used with external analog +* input channels only. +* +* Read the XADC spec for more information about the sequencer modes. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the XADC/ADC device. +* +* XAdcPs_CfgInitialize() API is used to initialize the XADC/ADC +* device. The user needs to first call the XAdcPs_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XAdcPs_CfgInitialize() API. +* +* +* Interrupts +* +* The XADC/ADC device supports interrupt driven mode and the default +* operation mode is polling mode. +* +* The interrupt mode is available only if hardware is configured to support +* interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* device in interrupt mode. +* +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* +* Building the driver +* +* The XAdcPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +* Limitations of the driver +* +* XADC/ADC device can be accessed through the JTAG port and the PLB +* interface. The driver implementation does not support the simultaneous access +* of the device by both these interfaces. The user has to care of this situation +* in the user application code. +* +*

+* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.01a bss    02/18/13	Modified XAdcPs_SetSeqChEnables,XAdcPs_SetSeqAvgEnables
+*			XAdcPs_SetSeqInputMode and XAdcPs_SetSeqAcqTime APIs
+*			in xadcps.c to fix CR #693371
+* 1.03a bss    11/01/13 Modified xadcps_hw.h to use correct Register offsets
+*			CR#749687
+* 2.1   bss    08/05/14 Added declarations for XAdcPs_SetSequencerEvent,
+*			XAdcPs_GetSamplingMode, XAdcPs_SetMuxMode,
+*			XAdcPs_SetPowerdownMode and XAdcPs_GetPowerdownMode
+*			functions.
+*			Modified Assert for XAdcPs_SetSingleChParams in
+*			xadcps.c to fix CR #807563.
+* 2.2   bss    04/27/14 Modified to use correct Device Config base address in
+*						xadcps.c (CR#854437).
+*       ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+*       ms     04/05/17 Modified Comment lines in functions of xadcps
+*                       examples to recognize it as documentation block
+*                       for doxygen generation.
+* 2.3   mn     07/09/18 Fix Doxygen warning
+* 2.6   aad    11/02/20 Fix MISRAC Mandatory and Advisory errors.
+*       aad    12/17/20 Added missing function declarations and removed
+*			functions with no definitions.
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_H /* Prevent circular inclusions */ +#define XADCPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xadcps_hw.h" + +/************************** Constant Definitions ****************************/ + + +/** + * @name Indexes for the different channels. + * @{ + */ +#define XADCPS_CH_TEMP 0x0U /**< On Chip Temperature */ +#define XADCPS_CH_VCCINT 0x1U /**< VCCINT */ +#define XADCPS_CH_VCCAUX 0x2U /**< VCCAUX */ +#define XADCPS_CH_VPVN 0x3U /**< VP/VN Dedicated analog inputs */ +#define XADCPS_CH_VREFP 0x4U /**< VREFP */ +#define XADCPS_CH_VREFN 0x5U /**< VREFN */ +#define XADCPS_CH_VBRAM 0x6U /**< On-chip VBRAM Data Reg, 7 series */ +#define XADCPS_CH_SUPPLY_CALIB 0x07U /**< Supply Calib Data Reg */ +#define XADCPS_CH_ADC_CALIB 0x08U /**< ADC Offset Channel Reg */ +#define XADCPS_CH_GAINERR_CALIB 0x09U /**< Gain Error Channel Reg */ +#define XADCPS_CH_VCCPINT 0x0DU /**< On-chip PS VCCPINT Channel , Zynq */ +#define XADCPS_CH_VCCPAUX 0x0EU /**< On-chip PS VCCPAUX Channel , Zynq */ +#define XADCPS_CH_VCCPDRO 0x0FU /**< On-chip PS VCCPDRO Channel , Zynq */ +#define XADCPS_CH_AUX_MIN 16U /**< Channel number for 1st Aux Channel */ +#define XADCPS_CH_AUX_MAX 31U /**< Channel number for Last Aux channel */ + +/*@}*/ + + +/** + * @name Indexes for reading the Calibration Coefficient Data. + * @{ + */ +#define XADCPS_CALIB_SUPPLY_COEFF 0U /**< Supply Offset Calib Coefficient */ +#define XADCPS_CALIB_ADC_COEFF 1U /**< ADC Offset Calib Coefficient */ +#define XADCPS_CALIB_GAIN_ERROR_COEFF 2U /**< Gain Error Calib Coefficient*/ +/*@}*/ + + +/** + * @name Indexes for reading the Minimum/Maximum Measurement Data. + * @{ + */ +#define XADCPS_MAX_TEMP 0U /**< Maximum Temperature Data */ +#define XADCPS_MAX_VCCINT 1U /**< Maximum VCCINT Data */ +#define XADCPS_MAX_VCCAUX 2U /**< Maximum VCCAUX Data */ +#define XADCPS_MAX_VBRAM 3U /**< Maximum VBRAM Data */ +#define XADCPS_MIN_TEMP 4U /**< Minimum Temperature Data */ +#define XADCPS_MIN_VCCINT 5U /**< Minimum VCCINT Data */ +#define XADCPS_MIN_VCCAUX 6U /**< Minimum VCCAUX Data */ +#define XADCPS_MIN_VBRAM 7U /**< Minimum VBRAM Data */ +#define XADCPS_MAX_VCCPINT 8U /**< Maximum VCCPINT Register , Zynq */ +#define XADCPS_MAX_VCCPAUX 9U /**< Maximum VCCPAUX Register , Zynq */ +#define XADCPS_MAX_VCCPDRO 0xAU /**< Maximum VCCPDRO Register , Zynq */ +#define XADCPS_MIN_VCCPINT 0xCU /**< Minimum VCCPINT Register , Zynq */ +#define XADCPS_MIN_VCCPAUX 0xDU /**< Minimum VCCPAUX Register , Zynq */ +#define XADCPS_MIN_VCCPDRO 0xEU /**< Minimum VCCPDRO Register , Zynq */ + +/*@}*/ + + +/** + * @name Alarm Threshold(Limit) Register (ATR) indexes. + * @{ + */ +#define XADCPS_ATR_TEMP_UPPER 0U /**< High user Temperature */ +#define XADCPS_ATR_VCCINT_UPPER 1U /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_UPPER 2U /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_OT_UPPER 3U /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_TEMP_LOWER 4U /**< Upper Over Temperature limit Reg */ +#define XADCPS_ATR_VCCINT_LOWER 5U /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_LOWER 6U /**< VCCAUX low voltage limit register */ +#define XADCPS_ATR_OT_LOWER 7U /**< Lower Over Temperature limit */ +#define XADCPS_ATR_VBRAM_UPPER_ 8U /**< VRBAM Upper Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_UPPER 9U /**< VCCPINT Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER 0xAU /**< VCCPAUX Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER 0xBU /**< VCCPDRO Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER 0xCU /**< VRBAM Lower Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER 0xDU /**< VCCPINT Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER 0xEU /**< VCCPAUX Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER 0xFU /**< VCCPDRO Lower Alarm Reg , Zynq */ + +/*@}*/ + + +/** + * @name Averaging to be done for the channels. + * @{ + */ +#define XADCPS_AVG_0_SAMPLES 0U /**< No Averaging */ +#define XADCPS_AVG_16_SAMPLES 1U /**< Average 16 samples */ +#define XADCPS_AVG_64_SAMPLES 2U /**< Average 64 samples */ +#define XADCPS_AVG_256_SAMPLES 3U /**< Average 256 samples */ + +/*@}*/ + + +/** + * @name Channel Sequencer Modes of operation + * @{ + */ +#define XADCPS_SEQ_MODE_SAFE 0U /**< Default Safe Mode */ +#define XADCPS_SEQ_MODE_ONEPASS 1U /**< Onepass through Sequencer */ +#define XADCPS_SEQ_MODE_CONTINPASS 2U /**< Continuous Cycling Sequencer */ +#define XADCPS_SEQ_MODE_SINGCHAN 3U /**< Single channel -No Sequencing */ +#define XADCPS_SEQ_MODE_SIMUL_SAMPLING 4U /**< Simultaneous sampling */ +#define XADCPS_SEQ_MODE_INDEPENDENT 8U /**< Independent mode */ + +/*@}*/ + + + +/** + * @name Power Down Modes + * @{ + */ +#define XADCPS_PD_MODE_NONE 0U /**< No Power Down */ +#define XADCPS_PD_MODE_ADCB 1U /**< Power Down ADC B */ +#define XADCPS_PD_MODE_XADC 2U /**< Power Down ADC A and ADC B */ +/*@}*/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the XADC/ADC + * device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Device base address */ +} XAdcPs_Config; + + +/** + * The driver's instance data. The user is required to allocate a variable + * of this type for every XADC/ADC device in the system. A pointer to + * a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XAdcPs_Config Config; /**< XAdcPs_Config of current device */ + u32 IsReady; /**< Device is initialized and ready */ + +} XAdcPs; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in Event Sampling mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in Event Sampling Mode. +* - FALSE if the device is in Continuous Sampling Mode. +* +* @note C-Style signature: +* int XAdcPs_IsEventSamplingMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsEventSamplingModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_EC_MASK) ? \ + TRUE : FALSE)) + + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in External Mux mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in External Mux Mode. +* - FALSE if the device is NOT in External Mux Mode. +* +* @note C-Style signature: +* int XAdcPs_IsExternalMuxMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsExternalMuxModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_MUX_MASK) ? \ + TRUE : FALSE)) + +/****************************************************************************/ +/** +* +* This macro converts XADC Raw Data to Temperature(centigrades). +* +* @param AdcData is the Raw ADC Data from XADC. +* +* @return The Temperature in centigrades. +* +* @note C-Style signature: +* float XAdcPs_RawToTemperature(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToTemperature(AdcData) \ + ((((float)(AdcData)/65536.0f)/0.00198421639f ) - 273.15f) + +/****************************************************************************/ +/** +* +* This macro converts XADC/ADC Raw Data to Voltage(volts). +* +* @param AdcData is the XADC/ADC Raw Data. +* +* @return The Voltage in volts. +* +* @note C-Style signature: +* float XAdcPs_RawToVoltage(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToVoltage(AdcData) \ + ((((float)(AdcData))* (3.0f))/65536.0f) + +/****************************************************************************/ +/** +* +* This macro converts Temperature in centigrades to XADC/ADC Raw Data. +* +* @param Temperature is the Temperature in centigrades to be +* converted to XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_TemperatureToRaw(float Temperature); +* +*****************************************************************************/ +#define XAdcPs_TemperatureToRaw(Temperature) \ + ((int)(((Temperature) + 273.15f)*65536.0f*0.00198421639f)) + +/****************************************************************************/ +/** +* +* This macro converts Voltage in Volts to XADC/ADC Raw Data. +* +* @param Voltage is the Voltage in volts to be converted to +* XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_VoltageToRaw(float Voltage); +* +*****************************************************************************/ +#define XAdcPs_VoltageToRaw(Voltage) \ + ((int)((Voltage)*65536.0f/3.0f)) + + +/****************************************************************************/ +/** +* +* This macro is used for writing to the XADC Registers using the +* command FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the value to be written to XADC register. +* +* @return None. +* +* @note C-Style signature: +* void XAdcPs_WriteFifo(XAdcPs *InstancePtr, u32 Data); +* +*****************************************************************************/ +#define XAdcPs_WriteFifo(InstancePtr, Data) \ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_CMDFIFO_OFFSET, Data); + + +/****************************************************************************/ +/** +* +* This macro is used for reading from the XADC Registers using the +* data FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Data read from the FIFO +* +* @note C-Style signature: +* u32 XAdcPs_ReadFifo(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_ReadFifo(InstancePtr) \ + XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_RDFIFO_OFFSET); + + +/************************** Function Prototypes *****************************/ + + + +/** + * Functions in xadcps_sinit.c + */ +XAdcPs_Config *XAdcPs_LookupConfig(u16 DeviceId); + +/** + * Functions in xadcps.c + */ +int XAdcPs_CfgInitialize(XAdcPs *InstancePtr, + XAdcPs_Config *ConfigPtr, + u32 EffectiveAddr); + +void XAdcPs_SetConfigRegister(XAdcPs *InstancePtr, u32 Data); +u32 XAdcPs_GetConfigRegister(XAdcPs *InstancePtr); + +u32 XAdcPs_GetMiscStatus(XAdcPs *InstancePtr); + +void XAdcPs_SetMiscCtrlRegister(XAdcPs *InstancePtr, u32 Data); +u32 XAdcPs_GetMiscCtrlRegister(XAdcPs *InstancePtr); + +void XAdcPs_Reset(XAdcPs *InstancePtr); + +u16 XAdcPs_GetAdcData(XAdcPs *InstancePtr, u8 Channel); + +u16 XAdcPs_GetCalibCoefficient(XAdcPs *InstancePtr, u8 CoeffType); + +u16 XAdcPs_GetMinMaxMeasurement(XAdcPs *InstancePtr, u8 MeasurementType); + +void XAdcPs_SetAvg(XAdcPs *InstancePtr, u8 Average); +u8 XAdcPs_GetAvg(XAdcPs *InstancePtr); + +int XAdcPs_SetSingleChParams(XAdcPs *InstancePtr, + u8 Channel, + int IncreaseAcqCycles, + int IsEventMode, + int IsDifferentialMode); + + +void XAdcPs_SetAlarmEnables(XAdcPs *InstancePtr, u16 AlmEnableMask); +u16 XAdcPs_GetAlarmEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetCalibEnables(XAdcPs *InstancePtr, u16 Calibration); +u16 XAdcPs_GetCalibEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerMode(XAdcPs *InstancePtr, u8 SequencerMode); +u8 XAdcPs_GetSequencerMode(XAdcPs *InstancePtr); + +void XAdcPs_SetAdcClkDivisor(XAdcPs *InstancePtr, u8 Divisor); +u8 XAdcPs_GetAdcClkDivisor(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqChEnables(XAdcPs *InstancePtr, u32 ChEnableMask); +u32 XAdcPs_GetSeqChEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAvgEnables(XAdcPs *InstancePtr, u32 AvgEnableChMask); +u32 XAdcPs_GetSeqAvgEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqInputMode(XAdcPs *InstancePtr, u32 InputModeChMask); +u32 XAdcPs_GetSeqInputMode(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAcqTime(XAdcPs *InstancePtr, u32 AcqCyclesChMask); +u32 XAdcPs_GetSeqAcqTime(XAdcPs *InstancePtr); + +void XAdcPs_SetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg, u16 Value); +u16 XAdcPs_GetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg); + +void XAdcPs_EnableUserOverTemp(XAdcPs *InstancePtr); +void XAdcPs_DisableUserOverTemp(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerEvent(XAdcPs *InstancePtr, int IsEventMode); + +int XAdcPs_GetSamplingMode(XAdcPs *InstancePtr); + +void XAdcPs_SetMuxMode(XAdcPs *InstancePtr, int MuxMode, u8 Channel); + +void XAdcPs_SetPowerdownMode(XAdcPs *InstancePtr, u32 Mode); + +u32 XAdcPs_GetPowerdownMode(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_selftest.c + */ +int XAdcPs_SelfTest(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_intr.c + */ +void XAdcPs_IntrEnable(XAdcPs *InstancePtr, u32 Mask); +void XAdcPs_IntrDisable(XAdcPs *InstancePtr, u32 Mask); +u32 XAdcPs_IntrGetEnabled(XAdcPs *InstancePtr); + +u32 XAdcPs_IntrGetStatus(XAdcPs *InstancePtr); +void XAdcPs_IntrClear(XAdcPs *InstancePtr, u32 Mask); + + +#ifdef __cplusplus +} +#endif + +#endif /* End of protection macro. */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xadcps_hw.h b/bsp_z7/ps7_cortexa9_0/include/xadcps_hw.h new file mode 100644 index 0000000..51cc7c5 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xadcps_hw.h @@ -0,0 +1,477 @@ +/****************************************************************************** +* Copyright (C) 2011 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xadcps_hw.h +* @addtogroup xadcps_v2_6 +* @{ +* +* This header file contains identifiers and basic driver functions (or +* macros) that can be used to access the XADC device through the Device +* Config Interface of the Zynq. +* +* +* Refer to the device specification for more information about this driver. +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a bss    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.03a bss    11/01/13 Modified macros to use correct Register offsets
+*			CR#749687
+* 2.6   aad    11/02/20 Fix MISRAC Mandatory and Advisory errors.
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_HW_H /* Prevent circular inclusions */ +#define XADCPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ + + +/**@name Register offsets of XADC in the Device Config + * + * The following constants provide access to each of the registers of the + * XADC device. + * @{ + */ + +#define XADCPS_CFG_OFFSET 0x00U /**< Configuration Register */ +#define XADCPS_INT_STS_OFFSET 0x04U /**< Interrupt Status Register */ +#define XADCPS_INT_MASK_OFFSET 0x08U /**< Interrupt Mask Register */ +#define XADCPS_MSTS_OFFSET 0x0CU /**< Misc status register */ +#define XADCPS_CMDFIFO_OFFSET 0x10U /**< Command FIFO Register */ +#define XADCPS_RDFIFO_OFFSET 0x14U /**< Read FIFO Register */ +#define XADCPS_MCTL_OFFSET 0x18U /**< Misc control register */ + +/* @} */ + + + + + +/** @name XADC Config Register Bit definitions + * @{ + */ +#define XADCPS_CFG_ENABLE_MASK 0x80000000U /**< Enable access from PS mask */ +#define XADCPS_CFG_CFIFOTH_MASK 0x00F00000U /**< Command FIFO Threshold mask */ +#define XADCPS_CFG_DFIFOTH_MASK 0x000F0000U /**< Data FIFO Threshold mask */ +#define XADCPS_CFG_WEDGE_MASK 0x00002000U /**< Write Edge Mask */ +#define XADCPS_CFG_REDGE_MASK 0x00001000U /**< Read Edge Mask */ +#define XADCPS_CFG_TCKRATE_MASK 0x00000300U /**< Clock freq control */ +#define XADCPS_CFG_IGAP_MASK 0x0000001FU /**< Idle Gap between + * successive commands */ +/* @} */ + + +/** @name XADC Interrupt Status/Mask Register Bit definitions + * + * The definitions are same for the Interrupt Status Register and + * Interrupt Mask Register. They are defined only once. + * @{ + */ +#define XADCPS_INTX_ALL_MASK 0x000003FFU /**< Alarm Signals Mask */ +#define XADCPS_INTX_CFIFO_LTH_MASK 0x00000200U /**< CMD FIFO less than threshold */ +#define XADCPS_INTX_DFIFO_GTH_MASK 0x00000100U /**< Data FIFO greater than threshold */ +#define XADCPS_INTX_OT_MASK 0x00000080U /**< Over temperature Alarm Status */ +#define XADCPS_INTX_ALM_ALL_MASK 0x0000007FU /**< Alarm Signals Mask */ +#define XADCPS_INTX_ALM6_MASK 0x00000040U /**< Alarm 6 Mask */ +#define XADCPS_INTX_ALM5_MASK 0x00000020U /**< Alarm 5 Mask */ +#define XADCPS_INTX_ALM4_MASK 0x00000010U /**< Alarm 4 Mask */ +#define XADCPS_INTX_ALM3_MASK 0x00000008U /**< Alarm 3 Mask */ +#define XADCPS_INTX_ALM2_MASK 0x00000004U /**< Alarm 2 Mask */ +#define XADCPS_INTX_ALM1_MASK 0x00000002U /**< Alarm 1 Mask */ +#define XADCPS_INTX_ALM0_MASK 0x00000001U /**< Alarm 0 Mask */ + +/* @} */ + + +/** @name XADC Miscellaneous Register Bit definitions + * @{ + */ +#define XADCPS_MSTS_CFIFO_LVL_MASK 0x000F0000U /**< Command FIFO Level mask */ +#define XADCPS_MSTS_DFIFO_LVL_MASK 0x0000F000U /**< Data FIFO Level Mask */ +#define XADCPS_MSTS_CFIFOF_MASK 0x00000800U /**< Command FIFO Full Mask */ +#define XADCPS_MSTS_CFIFOE_MASK 0x00000400U /**< Command FIFO Empty Mask */ +#define XADCPS_MSTS_DFIFOF_MASK 0x00000200U /**< Data FIFO Full Mask */ +#define XADCPS_MSTS_DFIFOE_MASK 0x00000100U /**< Data FIFO Empty Mask */ +#define XADCPS_MSTS_OT_MASK 0x00000080U /**< Over Temperature Mask */ +#define XADCPS_MSTS_ALM_MASK 0x0000007FU /**< Alarms Mask */ +/* @} */ + + +/** @name XADC Miscellaneous Control Register Bit definitions + * @{ + */ +#define XADCPS_MCTL_RESET_MASK 0x00000010U /**< Reset XADC */ +#define XADCPS_MCTL_FLUSH_MASK 0x00000001U /**< Flush the FIFOs */ +/* @} */ + + +/**@name Internal Register offsets of the XADC + * + * The following constants provide access to each of the internal registers of + * the XADC device. + * @{ + */ + +/* + * XADC Internal Channel Registers + */ +#define XADCPS_TEMP_OFFSET 0x00U /**< On-chip Temperature Reg */ +#define XADCPS_VCCINT_OFFSET 0x01U /**< On-chip VCCINT Data Reg */ +#define XADCPS_VCCAUX_OFFSET 0x02U /**< On-chip VCCAUX Data Reg */ +#define XADCPS_VPVN_OFFSET 0x03U /**< ADC out of VP/VN */ +#define XADCPS_VREFP_OFFSET 0x04U /**< On-chip VREFP Data Reg */ +#define XADCPS_VREFN_OFFSET 0x05U /**< On-chip VREFN Data Reg */ +#define XADCPS_VBRAM_OFFSET 0x06U /**< On-chip VBRAM , 7 Series */ +#define XADCPS_ADC_A_SUPPLY_CALIB_OFFSET 0x08U /**< ADC A Supply Offset Reg */ +#define XADCPS_ADC_A_OFFSET_CALIB_OFFSET 0x09U /**< ADC A Offset Data Reg */ +#define XADCPS_ADC_A_GAINERR_CALIB_OFFSET 0x0AU /**< ADC A Gain Error Reg */ +#define XADCPS_VCCPINT_OFFSET 0x0DU /**< On-chip VCCPINT Reg, Zynq */ +#define XADCPS_VCCPAUX_OFFSET 0x0EU /**< On-chip VCCPAUX Reg, Zynq */ +#define XADCPS_VCCPDRO_OFFSET 0x0FU /**< On-chip VCCPDRO Reg, Zynq */ + +/* + * XADC External Channel Registers + */ +#define XADCPS_AUX00_OFFSET 0x10U /**< ADC out of VAUXP0/VAUXN0 */ +#define XADCPS_AUX01_OFFSET 0x11U /**< ADC out of VAUXP1/VAUXN1 */ +#define XADCPS_AUX02_OFFSET 0x12U /**< ADC out of VAUXP2/VAUXN2 */ +#define XADCPS_AUX03_OFFSET 0x13U /**< ADC out of VAUXP3/VAUXN3 */ +#define XADCPS_AUX04_OFFSET 0x14U /**< ADC out of VAUXP4/VAUXN4 */ +#define XADCPS_AUX05_OFFSET 0x15U /**< ADC out of VAUXP5/VAUXN5 */ +#define XADCPS_AUX06_OFFSET 0x16U /**< ADC out of VAUXP6/VAUXN6 */ +#define XADCPS_AUX07_OFFSET 0x17U /**< ADC out of VAUXP7/VAUXN7 */ +#define XADCPS_AUX08_OFFSET 0x18U /**< ADC out of VAUXP8/VAUXN8 */ +#define XADCPS_AUX09_OFFSET 0x19U /**< ADC out of VAUXP9/VAUXN9 */ +#define XADCPS_AUX10_OFFSET 0x1AU /**< ADC out of VAUXP10/VAUXN10 */ +#define XADCPS_AUX11_OFFSET 0x1BU /**< ADC out of VAUXP11/VAUXN11 */ +#define XADCPS_AUX12_OFFSET 0x1CU /**< ADC out of VAUXP12/VAUXN12 */ +#define XADCPS_AUX13_OFFSET 0x1DU /**< ADC out of VAUXP13/VAUXN13 */ +#define XADCPS_AUX14_OFFSET 0x1EU /**< ADC out of VAUXP14/VAUXN14 */ +#define XADCPS_AUX15_OFFSET 0x1FU /**< ADC out of VAUXP15/VAUXN15 */ + +/* + * XADC Registers for Maximum/Minimum data captured for the + * on chip Temperature/VCCINT/VCCAUX data. + */ +#define XADCPS_MAX_TEMP_OFFSET 0x20U /**< Max Temperature Reg */ +#define XADCPS_MAX_VCCINT_OFFSET 0x21U /**< Max VCCINT Register */ +#define XADCPS_MAX_VCCAUX_OFFSET 0x22U /**< Max VCCAUX Register */ +#define XADCPS_MAX_VCCBRAM_OFFSET 0x23U /**< Max BRAM Register, 7 series */ +#define XADCPS_MIN_TEMP_OFFSET 0x24U /**< Min Temperature Reg */ +#define XADCPS_MIN_VCCINT_OFFSET 0x25U /**< Min VCCINT Register */ +#define XADCPS_MIN_VCCAUX_OFFSET 0x26U /**< Min VCCAUX Register */ +#define XADCPS_MIN_VCCBRAM_OFFSET 0x27U /**< Min BRAM Register, 7 series */ +#define XADCPS_MAX_VCCPINT_OFFSET 0x28U /**< Max VCCPINT Register, Zynq */ +#define XADCPS_MAX_VCCPAUX_OFFSET 0x29U /**< Max VCCPAUX Register, Zynq */ +#define XADCPS_MAX_VCCPDRO_OFFSET 0x2AU /**< Max VCCPDRO Register, Zynq */ +#define XADCPS_MIN_VCCPINT_OFFSET 0x2CU /**< Min VCCPINT Register, Zynq */ +#define XADCPS_MIN_VCCPAUX_OFFSET 0x2DU /**< Min VCCPAUX Register, Zynq */ +#define XADCPS_MIN_VCCPDRO_OFFSET 0x2EU /**< Min VCCPDRO Register,Zynq */ + /* Undefined 0x2F to 0x3E */ +#define XADCPS_FLAG_OFFSET 0x3FU /**< Flag Register */ + +/* + * XADC Configuration Registers + */ +#define XADCPS_CFR0_OFFSET 0x40U /**< Configuration Register 0 */ +#define XADCPS_CFR1_OFFSET 0x41U /**< Configuration Register 1 */ +#define XADCPS_CFR2_OFFSET 0x42U /**< Configuration Register 2 */ + +/* Test Registers 0x43 to 0x47 */ + +/* + * XADC Sequence Registers + */ +#define XADCPS_SEQ00_OFFSET 0x48U /**< Seq Reg 00 Adc Channel Selection */ +#define XADCPS_SEQ01_OFFSET 0x49U /**< Seq Reg 01 Adc Channel Selection */ +#define XADCPS_SEQ02_OFFSET 0x4AU /**< Seq Reg 02 Adc Average Enable */ +#define XADCPS_SEQ03_OFFSET 0x4BU /**< Seq Reg 03 Adc Average Enable */ +#define XADCPS_SEQ04_OFFSET 0x4CU /**< Seq Reg 04 Adc Input Mode Select */ +#define XADCPS_SEQ05_OFFSET 0x4DU /**< Seq Reg 05 Adc Input Mode Select */ +#define XADCPS_SEQ06_OFFSET 0x4EU /**< Seq Reg 06 Adc Acquisition Select */ +#define XADCPS_SEQ07_OFFSET 0x4FU /**< Seq Reg 07 Adc Acquisition Select */ + +/* + * XADC Alarm Threshold/Limit Registers (ATR) + */ +#define XADCPS_ATR_TEMP_UPPER_OFFSET 0x50U /**< Temp Upper Alarm Register */ +#define XADCPS_ATR_VCCINT_UPPER_OFFSET 0x51U /**< VCCINT Upper Alarm Reg */ +#define XADCPS_ATR_VCCAUX_UPPER_OFFSET 0x52U /**< VCCAUX Upper Alarm Reg */ +#define XADCPS_ATR_OT_UPPER_OFFSET 0x53U /**< Over Temp Upper Alarm Reg */ +#define XADCPS_ATR_TEMP_LOWER_OFFSET 0x54U /**< Temp Lower Alarm Register */ +#define XADCPS_ATR_VCCINT_LOWER_OFFSET 0x55U /**< VCCINT Lower Alarm Reg */ +#define XADCPS_ATR_VCCAUX_LOWER_OFFSET 0x56U /**< VCCAUX Lower Alarm Reg */ +#define XADCPS_ATR_OT_LOWER_OFFSET 0x57U /**< Over Temp Lower Alarm Reg */ +#define XADCPS_ATR_VBRAM_UPPER_OFFSET 0x58U /**< VBRAM Upper Alarm, 7 series */ +#define XADCPS_ATR_VCCPINT_UPPER_OFFSET 0x59U /**< VCCPINT Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER_OFFSET 0x5AU /**< VCCPAUX Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER_OFFSET 0x5BU /**< VCCPDRO Upper Alarm, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER_OFFSET 0x5CU /**< VRBAM Lower Alarm, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER_OFFSET 0x5DU /**< VCCPINT Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER_OFFSET 0x5EU /**< VCCPAUX Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER_OFFSET 0x5FU /**< VCCPDRO Lower Alarm, Zynq */ + +/* Undefined 0x60 to 0x7F */ + +/*@}*/ + + + +/** + * @name Configuration Register 0 (CFR0) mask(s) + * @{ + */ +#define XADCPS_CFR0_CAL_AVG_MASK 0x00008000U /**< Averaging enable Mask */ +#define XADCPS_CFR0_AVG_VALID_MASK 0x00003000U /**< Averaging bit Mask */ +#define XADCPS_CFR0_AVG1_MASK 0x00000000U /**< No Averaging */ +#define XADCPS_CFR0_AVG16_MASK 0x00001000U /**< Average 16 samples */ +#define XADCPS_CFR0_AVG64_MASK 0x00002000U /**< Average 64 samples */ +#define XADCPS_CFR0_AVG256_MASK 0x00003000U /**< Average 256 samples */ +#define XADCPS_CFR0_AVG_SHIFT 12U /**< Averaging bits shift */ +#define XADCPS_CFR0_MUX_MASK 0x00000800U /**< External Mask Enable */ +#define XADCPS_CFR0_DU_MASK 0x00000400U /**< Bipolar/Unipolar mode */ +#define XADCPS_CFR0_EC_MASK 0x00000200U /**< Event driven/ + * Continuous mode selection + */ +#define XADCPS_CFR0_ACQ_MASK 0x00000100U /**< Add acquisition by 6 ADCCLK */ +#define XADCPS_CFR0_CHANNEL_MASK 0x0000001FU /**< Channel number bit Mask */ + +/*@}*/ + +/** + * @name Configuration Register 1 (CFR1) mask(s) + * @{ + */ +#define XADCPS_CFR1_SEQ_VALID_MASK 0x0000F000U /**< Sequence bit Mask */ +#define XADCPS_CFR1_SEQ_SAFEMODE_MASK 0x00000000U /**< Default Safe Mode */ +#define XADCPS_CFR1_SEQ_ONEPASS_MASK 0x00001000U /**< Onepass through Seq */ +#define XADCPS_CFR1_SEQ_CONTINPASS_MASK 0x00002000U /**< Continuous Cycling Seq */ +#define XADCPS_CFR1_SEQ_SINGCHAN_MASK 0x00003000U /**< Single channel - No Seq */ +#define XADCPS_CFR1_SEQ_SIMUL_SAMPLING_MASK 0x00004000U /**< Simulataneous Sampling Mask */ +#define XADCPS_CFR1_SEQ_INDEPENDENT_MASK 0x00008000U /**< Independent Mode */ +#define XADCPS_CFR1_SEQ_SHIFT 12U /**< Sequence bit shift */ +#define XADCPS_CFR1_ALM_VCCPDRO_MASK 0x00000800U /**< Alm 6 - VCCPDRO, Zynq */ +#define XADCPS_CFR1_ALM_VCCPAUX_MASK 0x00000400U /**< Alm 5 - VCCPAUX, Zynq */ +#define XADCPS_CFR1_ALM_VCCPINT_MASK 0x00000200U /**< Alm 4 - VCCPINT, Zynq */ +#define XADCPS_CFR1_ALM_VBRAM_MASK 0x00000100U /**< Alm 3 - VBRAM, 7 series */ +#define XADCPS_CFR1_CAL_VALID_MASK 0x000000F0U /**< Valid Calibration Mask */ +#define XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK 0x00000080U /**< Calibration 3 -Power + Supply Gain/Offset + Enable */ +#define XADCPS_CFR1_CAL_PS_OFFSET_MASK 0x00000040U /**< Calibration 2 -Power + Supply Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK 0x00000020U /**< Calibration 1 -ADC Gain + Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_OFFSET_MASK 0x00000010U /**< Calibration 0 -ADC Offset + Enable */ +#define XADCPS_CFR1_CAL_DISABLE_MASK 0x00000000U /**< No Calibration */ +#define XADCPS_CFR1_ALM_ALL_MASK 0x00000F0FU /**< Mask for all alarms */ +#define XADCPS_CFR1_ALM_VCCAUX_MASK 0x00000008U /**< Alarm 2 - VCCAUX Enable */ +#define XADCPS_CFR1_ALM_VCCINT_MASK 0x00000004U /**< Alarm 1 - VCCINT Enable */ +#define XADCPS_CFR1_ALM_TEMP_MASK 0x00000002U /**< Alarm 0 - Temperature */ +#define XADCPS_CFR1_OT_MASK 0x00000001U /**< Over Temperature Enable */ + +/*@}*/ + +/** + * @name Configuration Register 2 (CFR2) mask(s) + * @{ + */ +#define XADCPS_CFR2_CD_VALID_MASK 0xFF00U /** +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00a adk 1/31/14 Added in bsp common folder for backward compatibility +* 7.0 aru 01/21/19 Modified the typedef of u32,u16,u8 +* 7.0 aru 02/06/19 Included stdint.h and stddef.h +* +* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XBASIC_TYPES_H /* prevent circular inclusions */ +#define XBASIC_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** @name Legacy types + * Deprecated legacy types. + * @{ + */ +typedef uint8_t Xuint8; /**< unsigned 8-bit */ +typedef char Xint8; /**< signed 8-bit */ +typedef uint16_t Xuint16; /**< unsigned 16-bit */ +typedef short Xint16; /**< signed 16-bit */ +typedef uint32_t Xuint32; /**< unsigned 32-bit */ +typedef long Xint32; /**< signed 32-bit */ +typedef float Xfloat32; /**< 32-bit floating point */ +typedef double Xfloat64; /**< 64-bit double precision FP */ +typedef unsigned long Xboolean; /**< boolean (XTRUE or XFALSE) */ + +#if !defined __XUINT64__ +typedef struct +{ + Xuint32 Upper; + Xuint32 Lower; +} Xuint64; +#endif + +/** @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XIL_TYPES_H +typedef Xuint32 u32; +typedef Xuint16 u16; +typedef Xuint8 u8; +#endif +#else +#include +#endif + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +/* + * Xilinx NULL, TRUE and FALSE legacy support. Deprecated. + * Please use NULL, TRUE and FALSE + */ +#define XNULL NULL +#define XTRUE TRUE +#define XFALSE FALSE + +/* + * This file is deprecated and users + * should use xil_types.h and xil_assert.h\n\r + */ +#warning The xbasics_type.h file is deprecated and users should use xil_types.h and xil_assert. +#warning Please refer the Standalone BSP UG647 for further details + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ + +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xcpu_cortexa9.h b/bsp_z7/ps7_cortexa9_0/include/xcpu_cortexa9.h new file mode 100644 index 0000000..3c23a5f --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xcpu_cortexa9.h @@ -0,0 +1,25 @@ +/****************************************************************************** +* Copyright (C) 2011 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xcpu_cortexa9.h +* @addtogroup cpu_cortexa9_v2_11 +* @{ +* @details +* +* dummy file +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- --------------------------------------------------------- +* 2.5 ms 04/18/17 Modified tcl file to add suffix U for XPAR_CPU_ID +* parameter of cpu_cortexa9 in xparameters.h +# 2.7 mus 07/03/18 Updated tcl to not to add default flags forcefully into +# extra compiler flags. Now, user can remove default flags +# from extra compiler flags. It fixes CR#998768. +******************************************************************************/ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xdebug.h b/bsp_z7/ps7_cortexa9_0/include/xdebug.h new file mode 100644 index 0000000..8e6b3ef --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xdebug.h @@ -0,0 +1,78 @@ +/****************************************************************************** +* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#ifndef XDEBUG +#define XDEBUG + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_printf.h" + +#if defined(DEBUG) && !defined(NDEBUG) + +#ifndef XDEBUG_WARNING +#define XDEBUG_WARNING +#warning DEBUG is enabled +#endif + +int printf(const char *format, ...); + +#define XDBG_DEBUG_ERROR 0x00000001U /* error condition messages */ +#define XDBG_DEBUG_GENERAL 0x00000002U /* general debug messages */ +#define XDBG_DEBUG_ALL 0xFFFFFFFFU /* all debugging data */ + +#define XDBG_DEBUG_FIFO_REG 0x00000100U /* display register reads/writes */ +#define XDBG_DEBUG_FIFO_RX 0x00000101U /* receive debug messages */ +#define XDBG_DEBUG_FIFO_TX 0x00000102U /* transmit debug messages */ +#define XDBG_DEBUG_FIFO_ALL 0x0000010FU /* all fifo debug messages */ + +#define XDBG_DEBUG_TEMAC_REG 0x00000400U /* display register reads/writes */ +#define XDBG_DEBUG_TEMAC_RX 0x00000401U /* receive debug messages */ +#define XDBG_DEBUG_TEMAC_TX 0x00000402U /* transmit debug messages */ +#define XDBG_DEBUG_TEMAC_ALL 0x0000040FU /* all temac debug messages */ + +#define XDBG_DEBUG_TEMAC_ADPT_RX 0x00000800U /* receive debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_TX 0x00000801U /* transmit debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_IOCTL 0x00000802U /* ioctl debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_MISC 0x00000803U /* debug msg for other routines */ +#define XDBG_DEBUG_TEMAC_ADPT_ALL 0x0000080FU /* all temac adapter debug messages */ + + +#define xdbg_current_types (XDBG_DEBUG_GENERAL | XDBG_DEBUG_ERROR | XDBG_DEBUG_TEMAC_REG | XDBG_DEBUG_FIFO_RX | XDBG_DEBUG_FIFO_TX | XDBG_DEBUG_FIFO_REG) + +#define xdbg_stmnt(x) x + +/* In VxWorks, if _WRS_GNU_VAR_MACROS is defined, special syntax is needed for + * macros that accept variable number of arguments + */ +#if defined(XENV_VXWORKS) && defined(_WRS_GNU_VAR_MACROS) +#define xdbg_printf(type, args...) (((type) & xdbg_current_types) ? printf (## args) : 0) +#else /* ANSI Syntax */ +#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) +#endif + +#define xdbg_exception_printf(type, ...) (((type) & xdbg_current_types) ? xil_printf (__VA_ARGS__) : 0) + +#else /* defined(DEBUG) && !defined(NDEBUG) */ + +#define xdbg_stmnt(x) + +/* See VxWorks comments above */ +#if defined(XENV_VXWORKS) && defined(_WRS_GNU_VAR_MACROS) +#define xdbg_printf(type, args...) +#else /* ANSI Syntax */ +#define xdbg_printf(...) +#endif +#endif /* defined(DEBUG) && !defined(NDEBUG) */ + +#ifdef __cplusplus +} +#endif + +#endif /* XDEBUG */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xdevcfg.h b/bsp_z7/ps7_cortexa9_0/include/xdevcfg.h new file mode 100644 index 0000000..e567699 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xdevcfg.h @@ -0,0 +1,377 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdevcfg.h +* @addtogroup devcfg_v3_7 +* @{ +* @details +* +* The is the main header file for the Device Configuration Interface of the Zynq +* device. The device configuration interface has three main functionality. +* 1. AXI-PCAP +* 2. Security Policy +* 3. XADC +* This current version of the driver supports only the AXI-PCAP and Security +* Policy blocks. There is a separate driver for XADC. +* +* AXI-PCAP is used for download/upload an encrypted or decrypted bitstream. +* DMA embedded in the AXI PCAP provides the master interface to +* the Device configuration block for any DMA transfers. The data transfer can +* take place between the Tx/RxFIFOs of AXI-PCAP and memory (on chip +* RAM/DDR/peripheral memory). +* +* The current driver only supports the downloading the FPGA bitstream and +* readback of the decrypted image (sort of loopback). +* The driver does not know what information needs to be written to the FPGA to +* readback FPGA configuration register or memory data. The application above the +* driver should take care of creating the data that needs to be downloaded to +* the FPGA so that the bitstream can be readback. +* This driver also does not support the reading of the internal registers of the +* PCAP. The driver has no knowledge of the PCAP internals. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Device Configuration device. +* +* XDcfg_CfgInitialize() API is used to initialize the Device Configuration +* Interface. The user needs to first call the XDcfg_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XDcfg_CfgInitialize() API. +* +* Interrupts +* The Driver implements an interrupt handler to support the interrupts provided +* by this interface. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XDcfg driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.00a nm  05/31/12 Updated the driver for CR 660835 so that input length for
+*		     source/destination to the XDcfg_InitiateDma, XDcfg_Transfer
+*		     APIs is words (32 bit) and not bytes.
+* 		     Updated the notes for XDcfg_InitiateDma/XDcfg_Transfer APIs
+*		     to add information that 2 LSBs of the Source/Destination
+*		     address when equal to 2�b01 indicate the last DMA command
+*		     of an overall transfer.
+*		     Destination Address passed to this API for secure transfers
+*		     instead of using 0xFFFFFFFF for CR 662197. This issue was
+*		     resulting in the failure of secure transfers of
+*		     non-bitstream images.
+* 2.01a nm  07/07/12 Updated the XDcfg_IntrClear function to directly
+*		     set the mask instead of oring it with the
+*		     value read from the interrupt status register
+* 		     Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg.
+*		     Added XDcfg_GetPsVersion, XDcfg_SelectIcapInterface
+*		     and XDcfg_SelectPcapInterface APIs for CR 643295
+*		     The user has to call the XDcfg_SelectIcapInterface API
+*		     for the PL reconfiguration using AXI HwIcap.
+*		     Updated the XDcfg_Transfer API to clear the
+*		     QUARTER_PCAP_RATE_EN bit in the control register for
+*		     non secure writes for CR 675543.
+* 2.02a nm  01/31/13 Fixed CR# 679335.
+* 		     Added Setting and Clearing the internal PCAP loopback.
+*		     Removed code for enabling/disabling AES engine as BootROM
+*		     locks down this setting.
+*		     Fixed CR# 681976.
+*		     Skip Checking the PCFG_INIT in case of non-secure DMA
+*		     loopback.
+*		     Fixed CR# 699558.
+*		     XDcfg_Transfer fails to transfer data in loopback mode.
+*		     Fixed CR# 701348.
+*                    Peripheral test fails with  Running
+* 		     DcfgSelfTestExample() in SECURE bootmode.
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 3.0   adk 10/12/13 Updated as per the New Tcl API's
+* 3.0   kpc 21/02/14 Added function prototype for XDcfg_ClearControlRegister
+* 3.2   sb  08/25/14 Fixed XDcfg_PcapReadback() function
+*		     updated driver code with != instead of ==,
+*		     while checking for Interrupt Status with DMA and
+*		     PCAP Done Mask
+*		     ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
+*			XDCFG_INT_STS_OFFSET) &
+*			XDCFG_IXR_D_P_DONE_MASK) !=
+*			XDCFG_IXR_D_P_DONE_MASK);
+*		     A new example has been added to read back the
+*		     configuration registers from the PL region.
+*		     xdevcfg_reg_readback_example.c
+* 3.3   sk  04/06/15 Modified XDcfg_ReadMultiBootConfig Macro CR# 851335.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/10/17 Modified filename tag in interrupt and polled examples
+*                    to include them in doxygen examples.
+* 3.5   ms  04/18/17 Modified tcl file to add suffix U for all macros
+*                    definitions of devcfg in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xdevcfg_sinit.c
+* 
+* +******************************************************************************/ +#ifndef XDCFG_H /* prevent circular inclusions */ +#define XDCFG_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xdevcfg_hw.h" +#include "xstatus.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/* Types of PCAP transfers */ + +#define XDCFG_NON_SECURE_PCAP_WRITE 1 +#define XDCFG_SECURE_PCAP_WRITE 2 +#define XDCFG_PCAP_READBACK 3 +#define XDCFG_CONCURRENT_SECURE_READ_WRITE 4 +#define XDCFG_CONCURRENT_NONSEC_READ_WRITE 5 + + +/**************************** Type Definitions *******************************/ +/** +* The handler data type allows the user to define a callback function to +* respond to interrupt events in the system. This function is executed +* in interrupt context, so amount of processing should be minimized. +* +* @param CallBackRef is the callback reference passed in by the upper +* layer when setting the callback functions, and passed back to +* the upper layer when the callback is invoked. Its type is +* unimportant to the driver component, so it is a void pointer. +* @param Status is the Interrupt status of the XDcfg device. +*/ +typedef void (*XDcfg_IntrHandler) (void *CallBackRef, u32 Status); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XDcfg_Config; + +/** + * The XDcfg driver instance data. + */ +typedef struct { + XDcfg_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device Configuration Interface + * is running + */ + XDcfg_IntrHandler StatusHandler; /* Event handler function */ + void *CallBackRef; /* Callback reference for event handler */ +} XDcfg; + +/****************************************************************************/ +/** +* +* Unlock the Device Config Interface block. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_Unlock(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_Unlock(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_UNLOCK_OFFSET, XDCFG_UNLOCK_DATA) + + + +/****************************************************************************/ +/** +* +* Get the version number of the PS from the Miscellaneous Control Register. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return Version of the PS. +* +* @note C-style signature: +* void XDcfg_GetPsVersion(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_GetPsVersion(InstancePtr) \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MCTRL_OFFSET)) & \ + XDCFG_MCTRL_PCAP_PS_VERSION_MASK) >> \ + XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT + + + +/****************************************************************************/ +/** +* +* Read the multiboot config register value. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* u32 XDcfg_ReadMultiBootConfig(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_ReadMultiBootConfig(InstancePtr) \ + XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MULTIBOOT_ADDR_OFFSET) + + +/****************************************************************************/ +/** +* +* Selects ICAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectIcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectIcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + & ( ~XDCFG_CTRL_PCAP_PR_MASK))) + +/****************************************************************************/ +/** +* +* Selects PCAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectPcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectPcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + | XDCFG_CTRL_PCAP_PR_MASK)) + + + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xdevcfg_sinit.c. + */ +XDcfg_Config *XDcfg_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xdevcfg_selftest.c + */ +int XDcfg_SelfTest(XDcfg *InstancePtr); + +/* + * Interface functions in xdevcfg.c + */ +int XDcfg_CfgInitialize(XDcfg *InstancePtr, + XDcfg_Config *ConfigPtr, u32 EffectiveAddress); + +void XDcfg_EnablePCAP(XDcfg *InstancePtr); + +void XDcfg_DisablePCAP(XDcfg *InstancePtr); + +void XDcfg_SetControlRegister(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_ClearControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetControlRegister(XDcfg *InstancePtr); + +void XDcfg_SetLockRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetLockRegister(XDcfg *InstancePtr); + +void XDcfg_SetConfigRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetConfigRegister(XDcfg *InstancePtr); + +void XDcfg_SetStatusRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetStatusRegister(XDcfg *InstancePtr); + +void XDcfg_SetRomShadowRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetSoftwareIdRegister(XDcfg *InstancePtr); + +void XDcfg_SetMiscControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetMiscControlRegister(XDcfg *InstancePtr); + +u32 XDcfg_IsDmaBusy(XDcfg *InstancePtr); + +void XDcfg_InitiateDma(XDcfg *InstancePtr, u32 SourcePtr, u32 DestPtr, + u32 SrcWordLength, u32 DestWordLength); + +u32 XDcfg_Transfer(XDcfg *InstancePtr, + void *SourcePtr, u32 SrcWordLength, + void *DestPtr, u32 DestWordLength, + u32 TransferType); + +/* + * Interrupt related function prototypes implemented in xdevcfg_intr.c + */ +void XDcfg_IntrEnable(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_IntrDisable(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_IntrGetEnabled(XDcfg *InstancePtr); + +u32 XDcfg_IntrGetStatus(XDcfg *InstancePtr); + +void XDcfg_IntrClear(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_InterruptHandler(XDcfg *InstancePtr); + +void XDcfg_SetHandler(XDcfg *InstancePtr, void *CallBackFunc, + void *CallBackRef); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xdevcfg_hw.h b/bsp_z7/ps7_cortexa9_0/include/xdevcfg_hw.h new file mode 100644 index 0000000..1b7d881 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xdevcfg_hw.h @@ -0,0 +1,369 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdevcfg_hw.h +* @addtogroup devcfg_v3_7 +* @{ +* +* This file contains the hardware interface to the Device Config Interface. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.01a nm  08/01/12 Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 2.04a	kpc	10/07/13 Added function prototype.
+* 3.00a	kpc	25/02/14 Corrected the XDCFG_BASE_ADDRESS macro value.
+* 
+* +******************************************************************************/ +#ifndef XDCFG_HW_H /* prevent circular inclusions */ +#define XDCFG_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XDCFG_CTRL_OFFSET 0x00 /**< Control Register */ +#define XDCFG_LOCK_OFFSET 0x04 /**< Lock Register */ +#define XDCFG_CFG_OFFSET 0x08 /**< Configuration Register */ +#define XDCFG_INT_STS_OFFSET 0x0C /**< Interrupt Status Register */ +#define XDCFG_INT_MASK_OFFSET 0x10 /**< Interrupt Mask Register */ +#define XDCFG_STATUS_OFFSET 0x14 /**< Status Register */ +#define XDCFG_DMA_SRC_ADDR_OFFSET 0x18 /**< DMA Source Address Register */ +#define XDCFG_DMA_DEST_ADDR_OFFSET 0x1C /**< DMA Destination Address Reg */ +#define XDCFG_DMA_SRC_LEN_OFFSET 0x20 /**< DMA Source Transfer Length */ +#define XDCFG_DMA_DEST_LEN_OFFSET 0x24 /**< DMA Destination Transfer */ +#define XDCFG_ROM_SHADOW_OFFSET 0x28 /**< DMA ROM Shadow Register */ +#define XDCFG_MULTIBOOT_ADDR_OFFSET 0x2C /**< Multi BootAddress Pointer */ +#define XDCFG_SW_ID_OFFSET 0x30 /**< Software ID Register */ +#define XDCFG_UNLOCK_OFFSET 0x34 /**< Unlock Register */ +#define XDCFG_MCTRL_OFFSET 0x80 /**< Miscellaneous Control Reg */ + +/* @} */ + +/** @name Control Register Bit definitions + * @{ + */ + +#define XDCFG_CTRL_FORCE_RST_MASK 0x80000000 /**< Force into + * Secure Reset + */ +#define XDCFG_CTRL_PCFG_PROG_B_MASK 0x40000000 /**< Program signal to + * Reset FPGA + */ +#define XDCFG_CTRL_PCFG_POR_CNT_4K_MASK 0x20000000 /**< Control PL POR timer */ +#define XDCFG_CTRL_PCAP_PR_MASK 0x08000000 /**< Enable PCAP for PR */ +#define XDCFG_CTRL_PCAP_MODE_MASK 0x04000000 /**< Enable PCAP */ +#define XDCFG_CTRL_PCAP_RATE_EN_MASK 0x02000000 /**< Enable PCAP send data + * to FPGA every 4 PCAP + * cycles + */ +#define XDCFG_CTRL_MULTIBOOT_EN_MASK 0x01000000 /**< Multiboot Enable */ +#define XDCFG_CTRL_JTAG_CHAIN_DIS_MASK 0x00800000 /**< JTAG Chain Disable */ +#define XDCFG_CTRL_USER_MODE_MASK 0x00008000 /**< User Mode Mask */ +#define XDCFG_CTRL_PCFG_AES_FUSE_MASK 0x00001000 /**< AES key source */ +#define XDCFG_CTRL_PCFG_AES_EN_MASK 0x00000E00 /**< AES Enable Mask */ +#define XDCFG_CTRL_SEU_EN_MASK 0x00000100 /**< SEU Enable Mask */ +#define XDCFG_CTRL_SEC_EN_MASK 0x00000080 /**< Secure/Non Secure + * Status mask + */ +#define XDCFG_CTRL_SPNIDEN_MASK 0x00000040 /**< Secure Non Invasive + * Debug Enable + */ +#define XDCFG_CTRL_SPIDEN_MASK 0x00000020 /**< Secure Invasive + * Debug Enable + */ +#define XDCFG_CTRL_NIDEN_MASK 0x00000010 /**< Non-Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DBGEN_MASK 0x00000008 /**< Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DAP_EN_MASK 0x00000007 /**< DAP Enable Mask */ + +/* @} */ + +/** @name Lock register bit definitions + * @{ + */ + +#define XDCFG_LOCK_AES_EFUSE_MASK 0x00000010 /**< Lock AES Efuse bit */ +#define XDCFG_LOCK_AES_EN_MASK 0x00000008 /**< Lock AES_EN update */ +#define XDCFG_LOCK_SEU_MASK 0x00000004 /**< Lock SEU_En update */ +#define XDCFG_LOCK_SEC_MASK 0x00000002 /**< Lock SEC_EN and + * USER_MODE + */ +#define XDCFG_LOCK_DBG_MASK 0x00000001 /**< This bit locks + * security config + * including: DAP_En, + * DBGEN,, + * NIDEN, SPNIEN + */ +/*@}*/ + + + +/** @name Config Register Bit definitions + * @{ + */ +#define XDCFG_CFG_RFIFO_TH_MASK 0x00000C00 /**< Read FIFO + * Threshold Mask + */ +#define XDCFG_CFG_WFIFO_TH_MASK 0x00000300 /**< Write FIFO Threshold + * Mask + */ +#define XDCFG_CFG_RCLK_EDGE_MASK 0x00000080 /**< Read data active + * clock edge + */ +#define XDCFG_CFG_WCLK_EDGE_MASK 0x00000040 /**< Write data active + * clock edge + */ +#define XDCFG_CFG_DISABLE_SRC_INC_MASK 0x00000020 /**< Disable Source address + * increment mask + */ +#define XDCFG_CFG_DISABLE_DST_INC_MASK 0x00000010 /**< Disable Destination + * address increment + * mask + */ +/* @} */ + + +/** @name Interrupt Status/Mask Register Bit definitions + * @{ + */ +#define XDCFG_IXR_PSS_GTS_USR_B_MASK 0x80000000 /**< Tri-state IO during + * HIZ + */ +#define XDCFG_IXR_PSS_FST_CFG_B_MASK 0x40000000 /**< First configuration + * done + */ +#define XDCFG_IXR_PSS_GPWRDWN_B_MASK 0x20000000 /**< Global power down */ +#define XDCFG_IXR_PSS_GTS_CFG_B_MASK 0x10000000 /**< Tri-state IO during + * configuration + */ +#define XDCFG_IXR_PSS_CFG_RESET_B_MASK 0x08000000 /**< PL configuration + * reset + */ +#define XDCFG_IXR_AXI_WTO_MASK 0x00800000 /**< AXI Write Address + * or Data or response + * timeout + */ +#define XDCFG_IXR_AXI_WERR_MASK 0x00400000 /**< AXI Write response + * error + */ +#define XDCFG_IXR_AXI_RTO_MASK 0x00200000 /**< AXI Read Address or + * response timeout + */ +#define XDCFG_IXR_AXI_RERR_MASK 0x00100000 /**< AXI Read response + * error + */ +#define XDCFG_IXR_RX_FIFO_OV_MASK 0x00040000 /**< Rx FIFO Overflow */ +#define XDCFG_IXR_WR_FIFO_LVL_MASK 0x00020000 /**< Tx FIFO less than + * threshold */ +#define XDCFG_IXR_RD_FIFO_LVL_MASK 0x00010000 /**< Rx FIFO greater than + * threshold */ +#define XDCFG_IXR_DMA_CMD_ERR_MASK 0x00008000 /**< Illegal DMA command */ +#define XDCFG_IXR_DMA_Q_OV_MASK 0x00004000 /**< DMA command queue + * overflow + */ +#define XDCFG_IXR_DMA_DONE_MASK 0x00002000 /**< DMA Command Done */ +#define XDCFG_IXR_D_P_DONE_MASK 0x00001000 /**< DMA and PCAP + * transfers Done + */ +#define XDCFG_IXR_P2D_LEN_ERR_MASK 0x00000800 /**< PCAP to DMA transfer + * length error + */ +#define XDCFG_IXR_PCFG_HMAC_ERR_MASK 0x00000040 /**< HMAC error mask */ +#define XDCFG_IXR_PCFG_SEU_ERR_MASK 0x00000020 /**< SEU Error mask */ +#define XDCFG_IXR_PCFG_POR_B_MASK 0x00000010 /**< FPGA POR mask */ +#define XDCFG_IXR_PCFG_CFG_RST_MASK 0x00000008 /**< FPGA Reset mask */ +#define XDCFG_IXR_PCFG_DONE_MASK 0x00000004 /**< Done Signal Mask */ +#define XDCFG_IXR_PCFG_INIT_PE_MASK 0x00000002 /**< Detect Positive edge + * of Init Signal + */ +#define XDCFG_IXR_PCFG_INIT_NE_MASK 0x00000001 /**< Detect Negative edge + * of Init Signal + */ +#define XDCFG_IXR_ERROR_FLAGS_MASK (XDCFG_IXR_AXI_WTO_MASK | \ + XDCFG_IXR_AXI_WERR_MASK | \ + XDCFG_IXR_AXI_RTO_MASK | \ + XDCFG_IXR_AXI_RERR_MASK | \ + XDCFG_IXR_RX_FIFO_OV_MASK | \ + XDCFG_IXR_DMA_CMD_ERR_MASK |\ + XDCFG_IXR_DMA_Q_OV_MASK | \ + XDCFG_IXR_P2D_LEN_ERR_MASK |\ + XDCFG_IXR_PCFG_HMAC_ERR_MASK) + + +#define XDCFG_IXR_ALL_MASK 0x00F7F8EF + + + +/* @} */ + + +/** @name Status Register Bit definitions + * @{ + */ +#define XDCFG_STATUS_DMA_CMD_Q_F_MASK 0x80000000 /**< DMA command + * Queue full + */ +#define XDCFG_STATUS_DMA_CMD_Q_E_MASK 0x40000000 /**< DMA command + * Queue empty + */ +#define XDCFG_STATUS_DMA_DONE_CNT_MASK 0x30000000 /**< Number of + * completed DMA + * transfers + */ +#define XDCFG_STATUS_RX_FIFO_LVL_MASK 0x01F000000 /**< Rx FIFO level */ +#define XDCFG_STATUS_TX_FIFO_LVL_MASK 0x0007F000 /**< Tx FIFO level */ + +#define XDCFG_STATUS_PSS_GTS_USR_B 0x00000800 /**< Tri-state IO + * during HIZ + */ +#define XDCFG_STATUS_PSS_FST_CFG_B 0x00000400 /**< First PL config + * done + */ +#define XDCFG_STATUS_PSS_GPWRDWN_B 0x00000200 /**< Global power down */ +#define XDCFG_STATUS_PSS_GTS_CFG_B 0x00000100 /**< Tri-state IO during + * config + */ +#define XDCFG_STATUS_SECURE_RST_MASK 0x00000080 /**< Secure Reset + * POR Status + */ +#define XDCFG_STATUS_ILLEGAL_APB_ACCESS_MASK 0x00000040 /**< Illegal APB + * access + */ +#define XDCFG_STATUS_PSS_CFG_RESET_B 0x00000020 /**< PL config + * reset status + */ +#define XDCFG_STATUS_PCFG_INIT_MASK 0x00000010 /**< FPGA Init + * Status + */ +#define XDCFG_STATUS_EFUSE_BBRAM_KEY_DISABLE_MASK 0x00000008 + /**< BBRAM key + * disable + */ +#define XDCFG_STATUS_EFUSE_SEC_EN_MASK 0x00000004 /**< Efuse Security + * Enable Status + */ +#define XDCFG_STATUS_EFUSE_JTAG_DIS_MASK 0x00000002 /**< EFuse JTAG + * Disable + * status + */ +/* @} */ + + +/** @name DMA Source/Destination Transfer Length Register Bit definitions + * @{ + */ +#define XDCFG_DMA_LEN_MASK 0x7FFFFFF /**< Length Mask */ +/*@}*/ + + + + +/** @name Miscellaneous Control Register Bit definitions + * @{ + */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_MASK 0xF0000000 /**< PS Version Mask */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT 28 /**< PS Version Shift */ +#define XDCFG_MCTRL_PCAP_LPBK_MASK 0x00000010 /**< PCAP loopback mask */ +/* @} */ + +/** @name FIFO Threshold Bit definitions + * @{ + */ + +#define XDCFG_CFG_FIFO_QUARTER 0x0 /**< Quarter empty */ +#define XDCFG_CFG_FIFO_HALF 0x1 /**< Half empty */ +#define XDCFG_CFG_FIFO_3QUARTER 0x2 /**< 3/4 empty */ +#define XDCFG_CFG_FIFO_EMPTY 0x4 /**< Empty */ +/* @}*/ + + +/* Miscellaneous constant values */ +#define XDCFG_DMA_INVALID_ADDRESS 0xFFFFFFFF /**< Invalid DMA address */ +#define XDCFG_UNLOCK_DATA 0x757BDF0D /**< First APB access data*/ +#define XDCFG_BASE_ADDRESS 0xF8007000 /**< Device Config base + * address + */ +#define XDCFG_CONFIG_RESET_VALUE 0x508 /**< Config reg reset value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XDcfg_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XDcfg_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XDcfg_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XDcfg_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ +/* + * Perform reset operation to the devcfg interface + */ +void XDcfg_ResetHw(u32 BaseAddr); +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xdmaps.h b/bsp_z7/ps7_cortexa9_0/include/xdmaps.h new file mode 100644 index 0000000..179c840 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xdmaps.h @@ -0,0 +1,329 @@ +/****************************************************************************** +* Copyright (C) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdmaps.h +* @addtogroup dmaps_v2_8 +* @{ +* @details +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	hbm    08/19/10 First Release
+* 1.01a nm     12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		        the maximum number of channels.
+*		        Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                       with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h.
+*			Added the tcl file to automatically generate the
+*			xparameters.h
+* 1.02a sg     05/16/12 Made changes for doxygen and moved some function
+*			header from the xdmaps.h file to xdmaps.c file
+*			Other cleanup for coding guidelines and CR 657109
+*			and CR 657898
+*			The xdmaps_example_no_intr.c example is removed
+*			as it is using interrupts  and is similar to
+*			the interrupt example - CR 652477
+* 1.03a sg     07/16/2012 changed inline to __inline for CR665681
+* 1.04a nm     10/22/2012 Fixed CR# 681671.
+* 1.05a nm     04/15/2013 Fixed CR# 704396. Removed warnings when compiled
+*			  with -Wall and -Wextra option in bsp.
+*	       05/01/2013 Fixed CR# 700189. Changed XDmaPs_BuildDmaProg()
+*			  function description.
+*			  Fixed CR# 704396. Removed unused variables
+*			  UseM2MByte & MemBurstLen from XDmaPs_BuildDmaProg()
+*			  function.
+* 1.07a asa    11/02/13. Made changes to fix compilation issues for iarcc.
+*			   Removed the PDBG prints. By default they were always
+*			   defined out and never used. The PDBG is non-standard for
+*			   Xilinx drivers and no other driver does something similar.
+*			   Since there is no easy way to fix compilation issues with
+*			   the IARCC compiler around PDBG, it is better to remove it.
+*			   Users can always use xil_printfs if they want to debug.
+* 2.0   adk    10/12/13  Updated as per the New Tcl API's
+* 2.01  kpc    08/23/14  Fixed the IAR compiler reported errors
+* 2.2   mus    08/12/16  Declared all inline functions in xdmaps.c as extern, to avoid
+*                        linker error for IAR compiler
+* 2.3   ms     01/23/17 Modified xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 2.4   adk    13/08/18 Fixed armcc compiler warnings in the driver CR-1008310.
+* 2.8	sk     05/18/21 Modify all inline functions declarations from extern inline
+*			to static inline to avoid the linkage conflict for IAR compiler.
+* 
+* +*****************************************************************************/ + +#ifndef XDMAPS_H /* prevent circular inclusions */ +#define XDMAPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xparameters.h" +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" + +#include "xdmaps_hw.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ +} XDmaPs_Config; + + +/** DMA channle control structure. It's for AXI bus transaction. + * This struct will be translated into a 32-bit channel control register value. + */ +typedef struct { + unsigned int EndianSwapSize; /**< Endian swap size. */ + unsigned int DstCacheCtrl; /**< Destination cache control */ + unsigned int DstProtCtrl; /**< Destination protection control */ + unsigned int DstBurstLen; /**< Destination burst length */ + unsigned int DstBurstSize; /**< Destination burst size */ + unsigned int DstInc; /**< Destination incrementing or fixed + * address */ + unsigned int SrcCacheCtrl; /**< Source cache control */ + unsigned int SrcProtCtrl; /**< Source protection control */ + unsigned int SrcBurstLen; /**< Source burst length */ + unsigned int SrcBurstSize; /**< Source burst size */ + unsigned int SrcInc; /**< Source incrementing or fixed + * address */ +} XDmaPs_ChanCtrl; + +/** DMA block descriptor stucture. + */ +typedef struct { + u32 SrcAddr; /**< Source starting address */ + u32 DstAddr; /**< Destination starting address */ + unsigned int Length; /**< Number of bytes for the block */ +} XDmaPs_BD; + +/** + * A DMA command consisits of a channel control struct, a block descriptor, + * a user defined program, a pointer pointing to generated DMA program, and + * execution result. + * + */ +typedef struct { + XDmaPs_ChanCtrl ChanCtrl; /**< Channel Control Struct */ + XDmaPs_BD BD; /**< Together with SgLength field, + * it's a scatter-gather list. + */ + void *UserDmaProg; /**< If user wants the driver to + * execute their own DMA program, + * this field points to the DMA + * program. + */ + int UserDmaProgLength; /**< The length of user defined + * DMA program. + */ + + void *GeneratedDmaProg; /**< The DMA program genreated + * by the driver. This field will be + * set if a user invokes the DMA + * program generation function. Or + * the DMA command is finished and + * a user informs the driver not to + * release the program buffer. + * This field has two purposes, one + * is to ask the driver to generate + * a DMA program while the DMAC is + * performaning DMA transactions. The + * other purpose is to debug the + * driver. + */ + int GeneratedDmaProgLength; /**< The length of the DMA program + * generated by the driver + */ + int DmaStatus; /**< 0 on success, otherwise error code + */ + u32 ChanFaultType; /**< Channel fault type in case of fault + */ + u32 ChanFaultPCAddr; /**< Channel fault PC address + */ +} XDmaPs_Cmd; + +/** + * It's the done handler a user can set for a channel + */ +typedef void (*XDmaPsDoneHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +/** + * It's the fault handler a user can set for a channel + */ +typedef void (*XDmaPsFaultHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +#define XDMAPS_MAX_CHAN_BUFS 2 +#define XDMAPS_CHAN_BUF_LEN 128 + +/** + * The XDmaPs_ProgBuf is the struct for a DMA program buffer. + */ +typedef struct { + char Buf[XDMAPS_CHAN_BUF_LEN]; /**< The actual buffer the holds the + * content */ + unsigned Len; /**< The actual length of the DMA + * program in bytes. */ + int Allocated; /**< A tag indicating whether the + * buffer is allocated or not */ +} XDmaPs_ProgBuf; + +/** + * The XDmaPs_ChannelData is a struct to book keep individual channel of + * the DMAC. + */ +typedef struct { + unsigned DevId; /**< Device id indicating which DMAC */ + unsigned ChanId; /**< Channel number of the DMAC */ + XDmaPs_ProgBuf ProgBufPool[XDMAPS_MAX_CHAN_BUFS]; /**< A pool of + program buffers*/ + XDmaPsDoneHandler DoneHandler; /**< Done interrupt handler */ + void *DoneRef; /**< Done interrupt callback data */ + XDmaPs_Cmd *DmaCmdToHw; /**< DMA command being executed */ + XDmaPs_Cmd *DmaCmdFromHw; /**< DMA command that is finished. + * This field is for debugging purpose + */ + int HoldDmaProg; /**< A tag indicating whether to hold the + * DMA program after the DMA is done. + */ + +} XDmaPs_ChannelData; + +/** + * The XDmaPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XDmaPs_Config Config; /**< Configuration data structure */ + int IsReady; /**< Device is Ready */ + int CacheLength; /**< icache length */ + XDmaPsFaultHandler FaultHandler; /**< fault interrupt handler */ + void *FaultRef; /**< fault call back data */ + XDmaPs_ChannelData Chans[XDMAPS_CHANNELS_PER_DEV]; + /**< + * channel data + */ +} XDmaPs; + +/* + * Functions implemented in xdmaps.c + */ +int XDmaPs_CfgInitialize(XDmaPs *InstPtr, + XDmaPs_Config *Config, + u32 EffectiveAddr); + +int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd, + int HoldDmaProg); + +int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel); +int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); + + +int XDmaPs_ResetManager(XDmaPs *InstPtr); +int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel); + + +int XDmaPs_SetDoneHandler(XDmaPs *InstPtr, + unsigned Channel, + XDmaPsDoneHandler DoneHandler, + void *CallbackRef); + +int XDmaPs_SetFaultHandler(XDmaPs *InstPtr, + XDmaPsFaultHandler FaultHandler, + void *CallbackRef); + +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); +int XDmaPs_Instr_DMARMB(char *DmaProg); +int XDmaPs_Instr_DMAWMB(char *DmaProg); + +/** + * To avoid linkage error,modify all inline functions from extern + * inline to static inline for IAR compiler + */ +#ifdef __ICCARM__ +static INLINE int XDmaPs_Instr_DMAEND(char *DmaProg); +static INLINE void XDmaPs_Memcpy4(char *Dst, char *Src); +static INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn, + u32 Imm, unsigned int Ns); +static INLINE int XDmaPs_Instr_DMALD(char *DmaProg); +static INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc, + unsigned LoopIterations); +static INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc); +static INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm); +static INLINE int XDmaPs_Instr_DMANOP(char *DmaProg); +static INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber); +static INLINE int XDmaPs_Instr_DMAST(char *DmaProg); +static INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize); +static INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize); +#endif + +/** + * Driver done interrupt service routines for the channels. + * We need this done ISR mainly because the driver needs to release the + * DMA program buffer. This is the one that connects the GIC + */ +void XDmaPs_DoneISR_0(XDmaPs *InstPtr); +void XDmaPs_DoneISR_1(XDmaPs *InstPtr); +void XDmaPs_DoneISR_2(XDmaPs *InstPtr); +void XDmaPs_DoneISR_3(XDmaPs *InstPtr); +void XDmaPs_DoneISR_4(XDmaPs *InstPtr); +void XDmaPs_DoneISR_5(XDmaPs *InstPtr); +void XDmaPs_DoneISR_6(XDmaPs *InstPtr); +void XDmaPs_DoneISR_7(XDmaPs *InstPtr); + +/** + * Driver fault interrupt service routine + */ +void XDmaPs_FaultISR(XDmaPs *InstPtr); + + +/* + * Static loopup function implemented in xdmaps_sinit.c + */ +XDmaPs_Config *XDmaPs_LookupConfig(u16 DeviceId); + + +/* + * self-test functions in xdmaps_selftest.c + */ +int XDmaPs_SelfTest(XDmaPs *InstPtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xdmaps_hw.h b/bsp_z7/ps7_cortexa9_0/include/xdmaps_hw.h new file mode 100644 index 0000000..d039278 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xdmaps_hw.h @@ -0,0 +1,267 @@ +/****************************************************************************** +* Copyright (C) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xdmaps_hw.h +* @addtogroup dmaps_v2_8 +* @{ +* +* This header file contains the hardware interface of an XDmaPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who   Date     Changes
+* ----- ----  -------- ----------------------------------------------
+* 1.00a	hbm   08/18/10 First Release
+* 1.01a nm    12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		       the maximum number of channels.
+*		       Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                      with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h
+* 1.02a sg    05/16/12 Made changes for doxygen
+* 1.06a kpc   07/10/13 Added function prototype
+* 
+* +******************************************************************************/ + +#ifndef XDMAPS_HW_H /* prevent circular inclusions */ +#define XDMAPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the DMAC. + * @{ + */ + +#define XDMAPS_DS_OFFSET 0x000 /* DMA Status Register */ +#define XDMAPS_DPC_OFFSET 0x004 /* DMA Program Counter Rregister */ +#define XDMAPS_INTEN_OFFSET 0X020 /* DMA Interrupt Enable Register */ +#define XDMAPS_ES_OFFSET 0x024 /* DMA Event Status Register */ +#define XDMAPS_INTSTATUS_OFFSET 0x028 /* DMA Interrupt Status Register + */ +#define XDMAPS_INTCLR_OFFSET 0x02c /* DMA Interrupt Clear Register */ +#define XDMAPS_FSM_OFFSET 0x030 /* DMA Fault Status DMA Manager + * Register + */ +#define XDMAPS_FSC_OFFSET 0x034 /* DMA Fault Status DMA Chanel Register + */ +#define XDMAPS_FTM_OFFSET 0x038 /* DMA Fault Type DMA Manager Register */ + +#define XDMAPS_FTC0_OFFSET 0x040 /* DMA Fault Type for DMA Channel 0 */ +/* + * The offset for the rest of the FTC registers is calculated as + * FTC0 + dev_chan_num * 4 + */ +#define XDmaPs_FTCn_OFFSET(ch) (XDMAPS_FTC0_OFFSET + (ch) * 4) + +#define XDMAPS_CS0_OFFSET 0x100 /* Channel Status for DMA Channel 0 */ +/* + * The offset for the rest of the CS registers is calculated as + * CS0 + * dev_chan_num * 0x08 + */ +#define XDmaPs_CSn_OFFSET(ch) (XDMAPS_CS0_OFFSET + (ch) * 8) + +#define XDMAPS_CPC0_OFFSET 0x104 /* Channel Program Counter for DMA + * Channel 0 + */ +/* + * The offset for the rest of the CPC registers is calculated as + * CPC0 + dev_chan_num * 0x08 + */ +#define XDmaPs_CPCn_OFFSET(ch) (XDMAPS_CPC0_OFFSET + (ch) * 8) + +#define XDMAPS_SA_0_OFFSET 0x400 /* Source Address Register for DMA + * Channel 0 + */ +/* The offset for the rest of the SA registers is calculated as + * SA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_SA_n_OFFSET(ch) (XDMAPS_SA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DA_0_OFFSET 0x404 /* Destination Address Register for + * DMA Channel 0 + */ +/* The offset for the rest of the DA registers is calculated as + * DA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_DA_n_OFFSET(ch) (XDMAPS_DA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_CC_0_OFFSET 0x408 /* Channel Control Register for + * DMA Channel 0 + */ +/* + * The offset for the rest of the CC registers is calculated as + * CC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_CC_n_OFFSET(ch) (XDMAPS_CC_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_LC0_0_OFFSET 0x40C /* Loop Counter 0 for DMA Channel 0 */ +/* + * The offset for the rest of the LC0 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC0_n_OFFSET(ch) (XDMAPS_LC0_0_OFFSET + (ch) * 0x20) +#define XDMAPS_LC1_0_OFFSET 0x410 /* Loop Counter 1 for DMA Channel 0 */ +/* + * The offset for the rest of the LC1 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC1_n_OFFSET(ch) (XDMAPS_LC1_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DBGSTATUS_OFFSET 0xD00 /* Debug Status Register */ +#define XDMAPS_DBGCMD_OFFSET 0xD04 /* Debug Command Register */ +#define XDMAPS_DBGINST0_OFFSET 0xD08 /* Debug Instruction 0 Register */ +#define XDMAPS_DBGINST1_OFFSET 0xD0C /* Debug Instruction 1 Register */ + +#define XDMAPS_CR0_OFFSET 0xE00 /* Configuration Register 0 */ +#define XDMAPS_CR1_OFFSET 0xE04 /* Configuration Register 1 */ +#define XDMAPS_CR2_OFFSET 0xE08 /* Configuration Register 2 */ +#define XDMAPS_CR3_OFFSET 0xE0C /* Configuration Register 3 */ +#define XDMAPS_CR4_OFFSET 0xE10 /* Configuration Register 4 */ +#define XDMAPS_CRDN_OFFSET 0xE14 /* Configuration Register Dn */ + +#define XDMAPS_PERIPH_ID_0_OFFSET 0xFE0 /* Peripheral Identification + * Register 0 + */ +#define XDMAPS_PERIPH_ID_1_OFFSET 0xFE4 /* Peripheral Identification + * Register 1 + */ +#define XDMAPS_PERIPH_ID_2_OFFSET 0xFE8 /* Peripheral Identification + * Register 2 + */ +#define XDMAPS_PERIPH_ID_3_OFFSET 0xFEC /* Peripheral Identification + * Register 3 + */ +#define XDMAPS_PCELL_ID_0_OFFSET 0xFF0 /* PrimeCell Identification + * Register 0 + */ +#define XDMAPS_PCELL_ID_1_OFFSET 0xFF4 /* PrimeCell Identification + * Register 1 + */ +#define XDMAPS_PCELL_ID_2_OFFSET 0xFF8 /* PrimeCell Identification + * Register 2 + */ +#define XDMAPS_PCELL_ID_3_OFFSET 0xFFC /* PrimeCell Identification + * Register 3 + */ + +/* + * Some useful register masks + */ +#define XDMAPS_DS_DMA_STATUS 0x0F /* DMA status mask */ +#define XDMAPS_DS_DMA_STATUS_STOPPED 0x00 /* debug status busy mask */ + +#define XDMAPS_DBGSTATUS_BUSY 0x01 /* debug status busy mask */ + +#define XDMAPS_CS_ACTIVE_MASK 0x07 /* channel status active mask, + * llast 3 bits of CS register + */ + +#define XDMAPS_CR1_I_CACHE_LEN_MASK 0x07 /* i_cache_len mask */ + + +/* + * XDMAPS_DBGINST0 - constructs the word for the Debug Instruction-0 Register. + * @b1: Instruction byte 1 + * @b0: Instruction byte 0 + * @ch: Channel number + * @dbg_th: Debug thread encoding: 0 = DMA manager thread, 1 = DMA channel + */ +#define XDmaPs_DBGINST0(b1, b0, ch, dbg_th) \ + (((b1) << 24) | ((b0) << 16) | (((ch) & 0x7) << 8) | ((dbg_th & 0x1))) + +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +/* @}*/ + + +#define XDMAPS_CHANNELS_PER_DEV 8 + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ + +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ + +/* @} */ +#define XDMAPS_INTCLR_ALL_MASK 0xFF + +#define XDmaPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write a DMAC register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note +* C-Style signature: +* void XDmaPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +******************************************************************************/ +#define XDmaPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (RegOffset), (RegisterValue)) +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes *****************************/ +/* + * Perform reset operation to the dmaps interface + */ +void XDmaPs_ResetHw(u32 BaseAddr); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xemacps.h b/bsp_z7/ps7_cortexa9_0/include/xemacps.h new file mode 100644 index 0000000..ac3e7a7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xemacps.h @@ -0,0 +1,843 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** + * + * @file xemacps.h +* @addtogroup emacps_v3_16 +* @{ +* @details + * + * The Xilinx Embedded Processor Block Ethernet driver. + * + * For a full description of XEMACPS features, please see the hardware spec. + * This driver supports the following features: + * - Memory mapped access to host interface registers + * - Statistics counter registers for RMON/MIB + * - API for interrupt driven frame transfers for hardware configured DMA + * - Virtual memory support + * - Unicast, broadcast, and multicast receive address filtering + * - Full and half duplex operation + * - Automatic PAD & FCS insertion and stripping + * - Flow control + * - Support up to four 48bit addresses + * - Address checking for four specific 48bit addresses + * - VLAN frame support + * - Pause frame support + * - Large frame support up to 1536 bytes + * - Checksum offload + * + * Driver Description + * + * The device driver enables higher layer software (e.g., an application) to + * communicate to the XEmacPs. The driver handles transmission and reception + * of Ethernet frames, as well as configuration and control. No pre or post + * processing of frame data is performed. The driver does not validate the + * contents of an incoming frame in addition to what has already occurred in + * hardware. + * A single device driver can support multiple devices even when those devices + * have significantly different configurations. + * + * Initialization & Configuration + * + * The XEmacPs_Config structure is used by the driver to configure itself. + * This configuration structure is typically created by the tool-chain based + * on hardware build properties. + * + * The driver instance can be initialized in + * + * - XEmacPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddress): Uses a + * configuration structure provided by the caller. If running in a system + * with address translation, the provided virtual memory base address + * replaces the physical address present in the configuration structure. + * + * The device supports DMA only as current development plan. No FIFO mode is + * supported. The driver expects to start the DMA channels and expects that + * the user has set up the buffer descriptor lists. + * + * Interrupts and Asynchronous Callbacks + * + * The driver has no dependencies on the interrupt controller. When an + * interrupt occurs, the handler will perform a small amount of + * housekeeping work, determine the source of the interrupt, and call the + * appropriate callback function. All callbacks are registered by the user + * level application. + * + * Virtual Memory + * + * All virtual to physical memory mappings must occur prior to accessing the + * driver API. + * + * For DMA transactions, user buffers supplied to the driver must be in terms + * of their physical address. + * + * DMA + * + * The DMA engine uses buffer descriptors (BDs) to describe Ethernet frames. + * These BDs are typically chained together into a list the hardware follows + * when transferring data in and out of the packet buffers. Each BD describes + * a memory region containing either a full or partial Ethernet packet. + * + * Interrupt coalescing is not supported from this built-in DMA engine. + * + * This API requires the user to understand how the DMA operates. The + * following paragraphs provide some explanation, but the user is encouraged + * to read documentation in xemacps_bdring.h as well as study example code + * that accompanies this driver. + * + * The API is designed to get BDs to and from the DMA engine in the most + * efficient means possible. The first step is to establish a memory region + * to contain all BDs for a specific channel. This is done with + * XEmacPs_BdRingCreate(). This function sets up a BD ring that hardware will + * follow as BDs are processed. The ring will consist of a user defined number + * of BDs which will all be partially initialized. For example on the transmit + * channel, the driver will initialize all BDs' so that they are configured + * for transmit. The more fields that can be permanently setup at + * initialization, then the fewer accesses will be needed to each BD while + * the DMA engine is in operation resulting in better throughput and CPU + * utilization. The best case initialization would require the user to set + * only a frame buffer address and length prior to submitting the BD to the + * engine. + * + * BDs move through the engine with the help of functions + * XEmacPs_BdRingAlloc(), XEmacPs_BdRingToHw(), XEmacPs_BdRingFromHw(), + * and XEmacPs_BdRingFree(). + * All these functions handle BDs that are in place. That is, there are no + * copies of BDs kept anywhere and any BD the user interacts with is an actual + * BD from the same ring hardware accesses. + * + * BDs in the ring go through a series of states as follows: + * 1. Idle. The driver controls BDs in this state. + * 2. The user has data to transfer. XEmacPs_BdRingAlloc() is called to + * reserve BD(s). Once allocated, the user may setup the BD(s) with + * frame buffer address, length, and other attributes. The user controls + * BDs in this state. + * 3. The user submits BDs to the DMA engine with XEmacPs_BdRingToHw. BDs + * in this state are either waiting to be processed by hardware, are in + * process, or have been processed. The DMA engine controls BDs in this + * state. + * 4. Processed BDs are retrieved with XEmacEpv_BdRingFromHw() by the + * user. Once retrieved, the user can examine each BD for the outcome of + * the DMA transfer. The user controls BDs in this state. After examining + * the BDs the user calls XEmacPs_BdRingFree() which places the BDs back + * into state 1. + * + * Each of the four BD accessor functions operate on a set of BDs. A set is + * defined as a segment of the BD ring consisting of one or more BDs. The user + * views the set as a pointer to the first BD along with the number of BDs for + * that set. The set can be navigated by using macros XEmacPs_BdNext(). The + * user must exercise extreme caution when changing BDs in a set as there is + * nothing to prevent doing a mBdNext past the end of the set and modifying a + * BD out of bounds. + * + * XEmacPs_BdRingAlloc() + XEmacPs_BdRingToHw(), as well as + * XEmacPs_BdRingFromHw() + XEmacPs_BdRingFree() are designed to be used in + * tandem. The same BD set retrieved with BdRingAlloc should be the same one + * provided to hardware with BdRingToHw. Same goes with BdRingFromHw and + * BdRIngFree. + * + * Alignment & Data Cache Restrictions + * + * Due to the design of the hardware, all RX buffers, BDs need to be 4-byte + * aligned. Please reference xemacps_bd.h for cache related macros. + * + * DMA Tx: + * + * - If frame buffers exist in cached memory, then they must be flushed + * prior to committing them to hardware. + * + * DMA Rx: + * + * - If frame buffers exist in cached memory, then the cache must be + * invalidated for the memory region containing the frame prior to data + * access + * + * Both cache invalidate/flush are taken care of in driver code. + * + * Buffer Copying + * + * The driver is designed for a zero-copy buffer scheme. That is, the driver + * will not copy buffers. This avoids potential throughput bottlenecks within + * the driver. If byte copying is required, then the transfer will take longer + * to complete. + * + * Checksum Offloading + * + * The Embedded Processor Block Ethernet can be configured to perform IP, TCP + * and UDP checksum offloading in both receive and transmit directions. + * + * IP packets contain a 16-bit checksum field, which is the 16-bit 1s + * complement of the 1s complement sum of all 16-bit words in the header. + * TCP and UDP packets contain a 16-bit checksum field, which is the 16-bit + * 1s complement of the 1s complement sum of all 16-bit words in the header, + * the data and a conceptual pseudo header. + * + * To calculate these checksums in software requires each byte of the packet + * to be read. For TCP and UDP this can use a large amount of processing power. + * Offloading the checksum calculation to hardware can result in significant + * performance improvements. + * + * The transmit checksum offload is only available to use DMA in packet buffer + * mode. This is because the complete frame to be transmitted must be read + * into the packet buffer memory before the checksum can be calculated and + * written to the header at the beginning of the frame. + * + * For IP, TCP or UDP receive checksum offload to be useful, the operating + * system containing the protocol stack must be aware that this offload is + * available so that it can make use of the fact that the hardware has verified + * the checksum. + * + * When receive checksum offloading is enabled in the hardware, the IP header + * checksum is checked, where the packet meets the following criteria: + * + * 1. If present, the VLAN header must be four octets long and the CFI bit + * must not be set. + * 2. Encapsulation must be RFC 894 Ethernet Type Encoding or RFC 1042 SNAP + * encoding. + * 3. IP v4 packet. + * 4. IP header is of a valid length. + * 5. Good IP header checksum. + * 6. No IP fragmentation. + * 7. TCP or UDP packet. + * + * When an IP, TCP or UDP frame is received, the receive buffer descriptor + * gives an indication if the hardware was able to verify the checksums. + * There is also an indication if the frame had SNAP encapsulation. These + * indication bits will replace the type ID match indication bits when the + * receive checksum offload is enabled. + * + * If any of the checksums are verified incorrect by the hardware, the packet + * is discarded and the appropriate statistics counter incremented. + * + * PHY Interfaces + * + * RGMII 1.3 is the only interface supported. + * + * Asserts + * + * Asserts are used within all Xilinx drivers to enforce constraints on + * parameters. Asserts can be turned off on a system-wide basis by defining, + * at compile time, the NDEBUG identifier. By default, asserts are turned on + * and it is recommended that users leave asserts on during development. For + * deployment use -DNDEBUG compiler switch to remove assert code. + * + * @note + * + * Xilinx drivers are typically composed of two parts, one is the driver + * and the other is the adapter. The driver is independent of OS and processor + * and is intended to be highly portable. The adapter is OS-specific and + * facilitates communication between the driver and an OS. + * This driver is intended to be RTOS and processor independent. Any needs for + * dynamic memory management, threads or thread mutual exclusion, or cache + * control must be satisfied bythe layer above this driver. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wsy  01/10/10 First release
+ * 1.00a asa  11/21/11 The function XEmacPs_BdRingFromHwTx in file
+ *		       xemacps_bdring.c is modified. Earlier it was checking for
+ *		       "BdLimit"(passed argument) number of BDs for finding out
+ *		       which BDs are successfully processed. Now one more check
+ *		       is added. It looks for BDs till the current BD pointer
+ *		       reaches HwTail. By doing this processing time is saved.
+ * 1.00a asa  01/24/12 The function XEmacPs_BdRingFromHwTx in file
+ *		       xemacps_bdring.c is modified. Now start of packet is
+ *		       searched for returning the number of BDs processed.
+ * 1.02a asa  11/05/12 Added a new API for deleting an entry from the HASH
+ *		       registers. Added a new API to set the bust length.
+ *		       Added some new hash-defines.
+ * 1.03a asa  01/23/12 Fix for CR #692702 which updates error handling for
+ *		       Rx errors. Under heavy Rx traffic, there will be a large
+ *		       number of errors related to receive buffer not available.
+ *		       Because of a HW bug (SI #692601), under such heavy errors,
+ *		       the Rx data path can become unresponsive. To reduce the
+ *		       probabilities for hitting this HW bug, the SW writes to
+ *		       bit 18 to flush a packet from Rx DPRAM immediately. The
+ *		       changes for it are done in the function
+ *		       XEmacPs_IntrHandler.
+ * 1.05a asa  09/23/13 Cache operations on BDs are not required and hence
+ *		       removed. It is expected that all BDs are allocated in
+ *		       from uncached area.
+ * 1.06a asa  11/02/13 Changed the value for XEMACPS_RXBUF_LEN_MASK from 0x3fff
+ *				to 0x1fff. This fixes the CR#744902.
+ *			  Made changes in example file xemacps_example.h to fix compilation
+ *			  issues with iarcc compiler.
+ * 2.0   adk  10/12/13 Updated as per the New Tcl API's
+ * 2.1   adk  11/08/14 Fixed the CR#811288. Changes are made in the driver tcl file.
+ * 2.1   bss  09/08/14 Modified driver tcl to fix CR#820349 to export phy
+ *		       address in xparameters.h when GMII to RGMII converter
+ *		       is present in hw.
+ * 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification and 64-bit
+ *		       changes.
+ * 2.2   adk  29/10/14 Fixed CR#827686 when PCS/PMA core is configured with
+ *                    1000BASE-X mode export proper values to the xparameters.h
+ *                    file. Changes are made in the driver tcl file.
+ * 3.0   adk  08/1/15  Don't include gem in peripheral test when gem is
+ *                    configured with PCS/PMA Core. Changes are made in the
+ *		       test app tcl(CR:827686).
+ * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+ * 3.0   hk   03/18/15 Added support for jumbo frames. Increase AHB burst.
+ *                     Disable extended mode. Perform all 64 bit changes under
+ *                     check for arch64.
+ *                     Remove "used bit set" from TX error interrupt masks.
+ * 3.1   hk   07/27/15 Do not call error handler with '0' error code when
+ *                     there is no error. CR# 869403
+ *            08/10/15 Update upper 32 bit tx and rx queue ptr registers.
+ * 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
+ * 3.4   ms   01/23/17 Modified xil_printf statement in main function for all
+ *                     examples to ensure that "Successfully ran" and "Failed"
+ *                     strings are available in all examples. This is a fix
+ *                     for CR-965028.
+ *       ms   03/17/17 Modified text file in examples folder for doxygen
+ *                     generation.
+ *       ms   04/05/17 Added tabspace for return statements in functions of
+ *                     xemacps_ieee1588_example.c for proper documentation
+ *                     while generating doxygen.
+ * 3.5   hk   08/14/17 Update cache coherency information of the interface in
+ *                     its config structure.
+ * 3.6   rb   09/08/17 HwCnt variable (in XEmacPs_BdRing structure) is
+ *		       changed to volatile.
+ *		       Add API XEmacPs_BdRingPtrReset() to reset pointers
+ * 3.8   hk   07/19/18 Fixed CPP, GCC and doxygen warnings - CR-1006327
+ *	 hk   09/17/18 Fix PTP interrupt masks and cleanup comments.
+ * 3.9   hk   01/23/19 Add RX watermark support
+ * 3.11  sd   02/14/20 Add clock support
+ * 3.13  nsk  12/14/20 Updated the tcl to not to use the instance names.
+ *
+ * 
+ * + ****************************************************************************/ + +#ifndef XEMACPS_H /* prevent circular inclusions */ +#define XEMACPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xemacps_hw.h" +#include "xemacps_bd.h" +#include "xemacps_bdring.h" +#if defined (XCLOCKING) +#include "xil_clocking.h" +#endif + +/************************** Constant Definitions ****************************/ + +/* + * Device information + */ +#define XEMACPS_DEVICE_NAME "xemacps" +#define XEMACPS_DEVICE_DESC "Xilinx PS 10/100/1000 MAC" + + +/** @name Configuration options + * + * Device configuration options. See the XEmacPs_SetOptions(), + * XEmacPs_ClearOptions() and XEmacPs_GetOptions() for information on how to + * use options. + * + * The default state of the options are noted and are what the device and + * driver will be set to after calling XEmacPs_Reset() or + * XEmacPs_Initialize(). + * + * @{ + */ + +#define XEMACPS_PROMISC_OPTION 0x00000001U +/**< Accept all incoming packets. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_FRAME1536_OPTION 0x00000002U +/**< Frame larger than 1516 support for Tx & Rx. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_VLAN_OPTION 0x00000004U +/**< VLAN Rx & Tx frame support. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_FLOW_CONTROL_OPTION 0x00000010U +/**< Enable recognition of flow control frames on Rx + * This option defaults to enabled (set) */ + +#define XEMACPS_FCS_STRIP_OPTION 0x00000020U +/**< Strip FCS and PAD from incoming frames. Note: PAD from VLAN frames is not + * stripped. + * This option defaults to enabled (set) */ + +#define XEMACPS_FCS_INSERT_OPTION 0x00000040U +/**< Generate FCS field and add PAD automatically for outgoing frames. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_LENTYPE_ERR_OPTION 0x00000080U +/**< Enable Length/Type error checking for incoming frames. When this option is + * set, the MAC will filter frames that have a mismatched type/length field + * and if XEMACPS_REPORT_RXERR_OPTION is set, the user is notified when these + * types of frames are encountered. When this option is cleared, the MAC will + * allow these types of frames to be received. + * + * This option defaults to disabled (cleared) */ + +#define XEMACPS_TRANSMITTER_ENABLE_OPTION 0x00000100U +/**< Enable the transmitter. + * This option defaults to enabled (set) */ + +#define XEMACPS_RECEIVER_ENABLE_OPTION 0x00000200U +/**< Enable the receiver + * This option defaults to enabled (set) */ + +#define XEMACPS_BROADCAST_OPTION 0x00000400U +/**< Allow reception of the broadcast address + * This option defaults to enabled (set) */ + +#define XEMACPS_MULTICAST_OPTION 0x00000800U +/**< Allows reception of multicast addresses programmed into hash + * This option defaults to disabled (clear) */ + +#define XEMACPS_RX_CHKSUM_ENABLE_OPTION 0x00001000U +/**< Enable the RX checksum offload + * This option defaults to enabled (set) */ + +#define XEMACPS_TX_CHKSUM_ENABLE_OPTION 0x00002000U +/**< Enable the TX checksum offload + * This option defaults to enabled (set) */ + +#define XEMACPS_JUMBO_ENABLE_OPTION 0x00004000U +#define XEMACPS_SGMII_ENABLE_OPTION 0x00008000U + +#define XEMACPS_DEFAULT_OPTIONS \ + ((u32)XEMACPS_FLOW_CONTROL_OPTION | \ + (u32)XEMACPS_FCS_INSERT_OPTION | \ + (u32)XEMACPS_FCS_STRIP_OPTION | \ + (u32)XEMACPS_BROADCAST_OPTION | \ + (u32)XEMACPS_LENTYPE_ERR_OPTION | \ + (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION | \ + (u32)XEMACPS_RECEIVER_ENABLE_OPTION | \ + (u32)XEMACPS_RX_CHKSUM_ENABLE_OPTION | \ + (u32)XEMACPS_TX_CHKSUM_ENABLE_OPTION) + +/**< Default options set when device is initialized or reset */ +/*@}*/ + +/** @name Callback identifiers + * + * These constants are used as parameters to XEmacPs_SetHandler() + * @{ + */ +#define XEMACPS_HANDLER_DMASEND 1U +#define XEMACPS_HANDLER_DMARECV 2U +#define XEMACPS_HANDLER_ERROR 3U +/*@}*/ + +/* Constants to determine the configuration of the hardware device. They are + * used to allow the driver to verify it can operate with the hardware. + */ +#define XEMACPS_MDIO_DIV_DFT MDC_DIV_32 /**< Default MDIO clock divisor */ + +/* The next few constants help upper layers determine the size of memory + * pools used for Ethernet buffers and descriptor lists. + */ +#define XEMACPS_MAC_ADDR_SIZE 6U /* size of Ethernet header */ + +#define XEMACPS_MTU 1500U /* max MTU size of Ethernet frame */ +#define XEMACPS_MTU_JUMBO 10240U /* max MTU size of jumbo frame */ +#define XEMACPS_HDR_SIZE 14U /* size of Ethernet header */ +#define XEMACPS_HDR_VLAN_SIZE 18U /* size of Ethernet header with VLAN */ +#define XEMACPS_TRL_SIZE 4U /* size of Ethernet trailer (FCS) */ +#define XEMACPS_MAX_FRAME_SIZE (XEMACPS_MTU + XEMACPS_HDR_SIZE + \ + XEMACPS_TRL_SIZE) +#define XEMACPS_MAX_VLAN_FRAME_SIZE (XEMACPS_MTU + XEMACPS_HDR_SIZE + \ + XEMACPS_HDR_VLAN_SIZE + XEMACPS_TRL_SIZE) +#define XEMACPS_MAX_VLAN_FRAME_SIZE_JUMBO (XEMACPS_MTU_JUMBO + XEMACPS_HDR_SIZE + \ + XEMACPS_HDR_VLAN_SIZE + XEMACPS_TRL_SIZE) + +/* DMACR Bust length hash defines */ + +#define XEMACPS_SINGLE_BURST 0x00000001 +#define XEMACPS_4BYTE_BURST 0x00000004 +#define XEMACPS_8BYTE_BURST 0x00000008 +#define XEMACPS_16BYTE_BURST 0x00000010 + + +/**************************** Type Definitions ******************************/ +/** @name Typedefs for callback functions + * + * These callbacks are invoked in interrupt context. + * @{ + */ +/** + * Callback invoked when frame(s) have been sent or received in interrupt + * driven DMA mode. To set the send callback, invoke XEmacPs_SetHandler(). + * + * @param CallBackRef is user data assigned when the callback was set. + * + * @note + * See xemacps_hw.h for bitmasks definitions and the device hardware spec for + * further information on their meaning. + * + */ +typedef void (*XEmacPs_Handler) (void *CallBackRef); + +/** + * Callback when an asynchronous error occurs. To set this callback, invoke + * XEmacPs_SetHandler() with XEMACPS_HANDLER_ERROR in the HandlerType + * parameter. + * + * @param CallBackRef is user data assigned when the callback was set. + * @param Direction defines either receive or transmit error(s) has occurred. + * @param ErrorWord definition varies with Direction + * + */ +typedef void (*XEmacPs_ErrHandler) (void *CallBackRef, u8 Direction, + u32 ErrorWord); + +/*@}*/ + +/** + * This typedef contains configuration information for a device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddress;/**< Physical base address of IPIF registers */ + u8 IsCacheCoherent; /**< Applicable only to A53 in EL1 mode; + * describes whether Cache Coherent or not */ +#if defined (XCLOCKING) + u32 RefClk; /**< Input clock */ +#endif + u16 S1GDiv0; /**< 1Gbps Clock Divider 0 */ + u8 S1GDiv1; /**< 1Gbps Clock Divider 1 */ + u16 S100MDiv0; /**< 100Mbps Clock Divider 0 */ + u8 S100MDiv1; /**< 100Mbps Clock Divider 1 */ + u16 S10MDiv0; /**< 10Mbps Clock Divider 0 */ + u8 S10MDiv1; /**< 10Mbps Clock Divider 1 */ +} XEmacPs_Config; + + +/** + * The XEmacPs driver instance data. The user is required to allocate a + * structure of this type for every XEmacPs device in the system. A pointer + * to a structure of this type is then passed to the driver API functions. + */ +typedef struct XEmacPs_Instance { + XEmacPs_Config Config; /* Hardware configuration */ + u32 IsStarted; /* Device is currently started */ + u32 IsReady; /* Device is initialized and ready */ + u32 Options; /* Current options word */ + + XEmacPs_BdRing TxBdRing; /* Transmit BD ring */ + XEmacPs_BdRing RxBdRing; /* Receive BD ring */ + + XEmacPs_Handler SendHandler; + XEmacPs_Handler RecvHandler; + void *SendRef; + void *RecvRef; + + XEmacPs_ErrHandler ErrorHandler; + void *ErrorRef; + u32 Version; + u32 RxBufMask; + u32 MaxMtuSize; + u32 MaxFrameSize; + u32 MaxVlanFrameSize; + +} XEmacPs; + + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* Retrieve the Tx ring object. This object can be used in the various Ring +* API functions. +* +* @param InstancePtr is the DMA channel to operate on. +* +* @return TxBdRing attribute +* +* @note +* C-style signature: +* XEmacPs_BdRing XEmacPs_GetTxRing(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_GetTxRing(InstancePtr) ((InstancePtr)->TxBdRing) + +/****************************************************************************/ +/** +* Retrieve the Rx ring object. This object can be used in the various Ring +* API functions. +* +* @param InstancePtr is the DMA channel to operate on. +* +* @return RxBdRing attribute +* +* @note +* C-style signature: +* XEmacPs_BdRing XEmacPs_GetRxRing(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_GetRxRing(InstancePtr) ((InstancePtr)->RxBdRing) + +/****************************************************************************/ +/** +* +* Enable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to enable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntEnable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntEnable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_IER_OFFSET, \ + ((Mask) & XEMACPS_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* Disable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to disable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntDisable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntDisable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_IDR_OFFSET, \ + ((Mask) & XEMACPS_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* Enable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to enable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntQ1Enable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntQ1Enable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_INTQ1_IER_OFFSET, \ + ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* Disable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to disable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntDisable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntQ1Disable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_INTQ1_IDR_OFFSET, \ + ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* This macro triggers trasmit circuit to send data currently in TX buffer(s). +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return +* +* @note +* +* Signature: void XEmacPs_Transmit(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_Transmit(InstancePtr) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_NWCTRL_OFFSET, \ + (XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK)) + +/****************************************************************************/ +/** +* +* This macro determines if the device is configured with checksum offloading +* on the receive channel +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return +* +* Boolean TRUE if the device is configured with checksum offloading, or +* FALSE otherwise. +* +* @note +* +* Signature: u32 XEmacPs_IsRxCsum(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_IsRxCsum(InstancePtr) \ + ((XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_NWCFG_OFFSET) & XEMACPS_NWCFG_RXCHKSUMEN_MASK) != 0U \ + ? TRUE : FALSE) + +/****************************************************************************/ +/** +* +* This macro determines if the device is configured with checksum offloading +* on the transmit channel +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return +* +* Boolean TRUE if the device is configured with checksum offloading, or +* FALSE otherwise. +* +* @note +* +* Signature: u32 XEmacPs_IsTxCsum(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_IsTxCsum(InstancePtr) \ + ((XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_DMACR_OFFSET) & XEMACPS_DMACR_TCPCKSUM_MASK) != 0U \ + ? TRUE : FALSE) + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* This macro sets RX watermark register. +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* @param High is the non-zero RX high watermark value. When SRAM fill level +* is above this, a pause frame will be sent. +* @param Low is the non-zero RX low watermark value. When SRAM fill level +* is below this, a zero length pause frame will be sent IF the last +* pause frame sent was non-zero. +* +* @return None +* +* @note +* +* Signature: void XEmacPs_SetRXWatermark(XEmacPs *InstancePtr, u16 High, +* u16 Low) +* +*****************************************************************************/ +#define XEmacPs_SetRXWatermark(InstancePtr, High, Low) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_RXWATERMARK_OFFSET, \ + (High & XEMACPS_RXWM_HIGH_MASK) | \ + ((Low << XEMACPS_RXWM_LOW_SHFT_MSK) & XEMACPS_RXWM_LOW_MASK) |) + +/****************************************************************************/ +/** +* +* This macro gets RX watermark register. +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return RX watermark register value +* +* @note +* +* Signature: void XEmacPs_GetRXWatermark(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_GetRXWatermark(InstancePtr) \ + XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_RXWATERMARK_OFFSET) +/* + * Initialization functions in xemacps.c + */ +LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config *CfgPtr, + UINTPTR EffectiveAddress); +void XEmacPs_Start(XEmacPs *InstancePtr); +void XEmacPs_Stop(XEmacPs *InstancePtr); +void XEmacPs_Reset(XEmacPs *InstancePtr); +void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum, + u16 Direction); + +/* + * Lookup configuration in xemacps_sinit.c + */ +XEmacPs_Config *XEmacPs_LookupConfig(u16 DeviceId); + +/* + * Interrupt-related functions in xemacps_intr.c + * DMA only and FIFO is not supported. This DMA does not support coalescing. + */ +LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType, + void *FuncPointer, void *CallBackRef); +void XEmacPs_IntrHandler(void *XEmacPsPtr); + +/* + * MAC configuration/control functions in XEmacPs_control.c + */ +LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options); +LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options); +u32 XEmacPs_GetOptions(XEmacPs *InstancePtr); + +LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index); +LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr); +void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index); + +LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr); +void XEmacPs_ClearHash(XEmacPs *InstancePtr); +void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr); + +void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, + XEmacPs_MdcDiv Divisor); +void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed); +u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr); +LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, + u32 RegisterNum, u16 *PhyDataPtr); +LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress, + u32 RegisterNum, u16 PhyData); +LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index); + +LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr); +void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xemacps_bd.h b/bsp_z7/ps7_cortexa9_0/include/xemacps_bd.h new file mode 100644 index 0000000..aff79ff --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xemacps_bd.h @@ -0,0 +1,762 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xemacps_bd.h +* @addtogroup emacps_v3_16 +* @{ + * + * This header provides operations to manage buffer descriptors in support + * of scatter-gather DMA. + * + * The API exported by this header defines abstracted macros that allow the + * user to read/write specific BD fields. + * + * Buffer Descriptors + * + * A buffer descriptor (BD) defines a DMA transaction. The macros defined by + * this header file allow access to most fields within a BD to tailor a DMA + * transaction according to user and hardware requirements. See the hardware + * IP DMA spec for more information on BD fields and how they affect transfers. + * + * The XEmacPs_Bd structure defines a BD. The organization of this structure + * is driven mainly by the hardware for use in scatter-gather DMA transfers. + * + * Performance + * + * Limiting I/O to BDs can improve overall performance of the DMA channel. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wsy  01/10/10 First release
+ * 2.1   srt  07/15/14 Add support for Zynq Ultrascale MP GEM specification
+ *                     and 64-bit changes.
+ * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+ * 3.0   hk   02/20/15 Added support for jumbo frames.
+ *                     Disable extended mode. Perform all 64 bit changes under
+ *                     check for arch64.
+ * 3.2   hk   11/18/15 Change BD typedef and number of words.
+ * 3.8   hk   08/18/18 Remove duplicate definition of XEmacPs_BdSetLength
+ * 3.8   mus  11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
+ *
+ * 
+ * + * *************************************************************************** + */ + +#ifndef XEMACPS_BD_H /* prevent circular inclusions */ +#define XEMACPS_BD_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ +#ifdef __aarch64__ +/* Minimum BD alignment */ +#define XEMACPS_DMABD_MINIMUM_ALIGNMENT 64U +#define XEMACPS_BD_NUM_WORDS 4U +#else +/* Minimum BD alignment */ +#define XEMACPS_DMABD_MINIMUM_ALIGNMENT 4U +#define XEMACPS_BD_NUM_WORDS 2U +#endif + +/** + * The XEmacPs_Bd is the type for buffer descriptors (BDs). + */ +typedef u32 XEmacPs_Bd[XEMACPS_BD_NUM_WORDS]; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * Zero out BD fields + * + * @param BdPtr is the BD pointer to operate on + * + * @return Nothing + * + * @note + * C-style signature: + * void XEmacPs_BdClear(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClear(BdPtr) \ + memset((BdPtr), 0, sizeof(XEmacPs_Bd)) + +/****************************************************************************/ +/** +* +* Read the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to read +* @param Offset is the word offset to be read +* +* @return The 32-bit value of the field +* +* @note +* C-style signature: +* u32 XEmacPs_BdRead(UINTPTR BaseAddress, UINTPTR Offset) +* +*****************************************************************************/ +#define XEmacPs_BdRead(BaseAddress, Offset) \ + (*(u32 *)((UINTPTR)((void*)(BaseAddress)) + (u32)(Offset))) + +/****************************************************************************/ +/** +* +* Write the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to write +* @param Offset is the word offset to be written +* @param Data is the 32-bit value to write to the field +* +* @return None. +* +* @note +* C-style signature: +* void XEmacPs_BdWrite(UINTPTR BaseAddress, UINTPTR Offset, UINTPTR Data) +* +*****************************************************************************/ +#define XEmacPs_BdWrite(BaseAddress, Offset, Data) \ + (*(u32 *)((UINTPTR)(void*)(BaseAddress) + (u32)(Offset)) = (u32)(Data)) + +/*****************************************************************************/ +/** + * Set the BD's Address field (word 0). + * + * @param BdPtr is the BD pointer to operate on + * @param Addr is the value to write to BD's status field. + * + * @note : + * + * C-style signature: + * void XEmacPs_BdSetAddressTx(XEmacPs_Bd* BdPtr, UINTPTR Addr) + * + *****************************************************************************/ +#if defined(__aarch64__) || defined(__arch64__) +#define XEmacPs_BdSetAddressTx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + (u32)((Addr) & ULONG64_LO_MASK)); \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET, \ + (u32)(((Addr) & ULONG64_HI_MASK) >> 32U)); +#else +#define XEmacPs_BdSetAddressTx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, (u32)(Addr)) +#endif + +/*****************************************************************************/ +/** + * Set the BD's Address field (word 0). + * + * @param BdPtr is the BD pointer to operate on + * @param Addr is the value to write to BD's status field. + * + * @note : Due to some bits are mixed within receive BD's address field, + * read-modify-write is performed. + * + * C-style signature: + * void XEmacPs_BdSetAddressRx(XEmacPs_Bd* BdPtr, UINTPTR Addr) + * + *****************************************************************************/ +#ifdef __aarch64__ +#define XEmacPs_BdSetAddressRx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + ~XEMACPS_RXBUF_ADD_MASK) | ((u32)((Addr) & ULONG64_LO_MASK)))); \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET, \ + (u32)(((Addr) & ULONG64_HI_MASK) >> 32U)); +#else +#define XEmacPs_BdSetAddressRx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + ~XEMACPS_RXBUF_ADD_MASK) | (UINTPTR)(Addr))) +#endif + +/*****************************************************************************/ +/** + * Set the BD's Status field (word 1). + * + * @param BdPtr is the BD pointer to operate on + * @param Data is the value to write to BD's status field. + * + * @note + * C-style signature: + * void XEmacPs_BdSetStatus(XEmacPs_Bd* BdPtr, UINTPTR Data) + * + *****************************************************************************/ +#define XEmacPs_BdSetStatus(BdPtr, Data) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | (Data)) + + +/*****************************************************************************/ +/** + * Retrieve the BD's Packet DMA transfer status word (word 1). + * + * @param BdPtr is the BD pointer to operate on + * + * @return Status word + * + * @note + * C-style signature: + * u32 XEmacPs_BdGetStatus(XEmacPs_Bd* BdPtr) + * + * Due to the BD bit layout differences in transmit and receive. User's + * caution is required. + *****************************************************************************/ +#define XEmacPs_BdGetStatus(BdPtr) \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) + + +/*****************************************************************************/ +/** + * Get the address (bits 0..31) of the BD's buffer address (word 0) + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetBufAddr(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#if defined(__aarch64__) || defined(__arch64__) +#define XEmacPs_BdGetBufAddr(BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) | \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET)) << 32U) +#else +#define XEmacPs_BdGetBufAddr(BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET)) +#endif + +/*****************************************************************************/ +/** + * Set transfer length in bytes for the given BD. The length must be set each + * time a BD is submitted to hardware. + * + * @param BdPtr is the BD pointer to operate on + * @param LenBytes is the number of bytes to transfer. + * + * @note + * C-style signature: + * void XEmacPs_BdSetLength(XEmacPs_Bd* BdPtr, u32 LenBytes) + * + *****************************************************************************/ +#define XEmacPs_BdSetLength(BdPtr, LenBytes) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_LEN_MASK) | (LenBytes))) + + +/*****************************************************************************/ +/** + * Retrieve the BD length field. + * + * For Tx channels, the returned value is the same as that written with + * XEmacPs_BdSetLength(). + * + * For Rx channels, the returned value is the size of the received packet. + * + * @param BdPtr is the BD pointer to operate on + * + * @return Length field processed by hardware or set by + * XEmacPs_BdSetLength(). + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetLength(XEmacPs_Bd* BdPtr) + * XEAMCPS_RXBUF_LEN_MASK is same as XEMACPS_TXBUF_LEN_MASK. + * + *****************************************************************************/ +#define XEmacPs_BdGetLength(BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_LEN_MASK) + +/*****************************************************************************/ +/** + * Retrieve the RX frame size. + * + * The returned value is the size of the received packet. + * This API supports jumbo frame sizes if enabled. + * + * @param InstancePtr is the pointer to XEmacps instance + * + * @param BdPtr is the BD pointer to operate on + * + * @return Length field processed by hardware or set by + * XEmacPs_BdSetLength(). + * + * @note + * C-style signature: + * UINTPTR XEmacPs_GetRxFrameSize(XEmacPs* InstancePtr, XEmacPs_Bd* BdPtr) + * RxBufMask is dependent on whether jumbo is enabled or not. + * + *****************************************************************************/ +#define XEmacPs_GetRxFrameSize(InstancePtr, BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + (InstancePtr)->RxBufMask) + +/*****************************************************************************/ +/** + * Test whether the given BD has been marked as the last BD of a packet. + * + * @param BdPtr is the BD pointer to operate on + * + * @return TRUE if BD represents the "Last" BD of a packet, FALSE otherwise + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsLast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsLast(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_EOF_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Tell the DMA engine that the given transmit BD marks the end of the current + * packet to be processed. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetLast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdSetLast(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_LAST_MASK)) + + +/*****************************************************************************/ +/** + * Tell the DMA engine that the current packet does not end with the given + * BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdClearLast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearLast(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_LAST_MASK)) + + +/*****************************************************************************/ +/** + * Set this bit to mark the last descriptor in the receive buffer descriptor + * list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetRxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +/*#define XEmacPs_BdSetRxWrap(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) | \ + XEMACPS_RXBUF_WRAP_MASK)) +*/ + +/*****************************************************************************/ +/** + * Determine the wrap bit of the receive BD which indicates end of the + * BD list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * u8 XEmacPs_BdIsRxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxWrap(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + XEMACPS_RXBUF_WRAP_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Sets this bit to mark the last descriptor in the transmit buffer + * descriptor list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetTxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +/*#define XEmacPs_BdSetTxWrap(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_WRAP_MASK)) +*/ + +/*****************************************************************************/ +/** + * Determine the wrap bit of the transmit BD which indicates end of the + * BD list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * u8 XEmacPs_BdGetTxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxWrap(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_WRAP_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/* + * Must clear this bit to enable the MAC to write data to the receive + * buffer. Hardware sets this bit once it has successfully written a frame to + * memory. Once set, software has to clear the bit before the buffer can be + * used again. This macro clear the new bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdClearRxNew(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearRxNew(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + ~XEMACPS_RXBUF_NEW_MASK)) + + +/*****************************************************************************/ +/** + * Determine the new bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxNew(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxNew(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + XEMACPS_RXBUF_NEW_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Software sets this bit to disable the buffer to be read by the hardware. + * Hardware sets this bit for the first buffer of a frame once it has been + * successfully transmitted. This macro sets this bit of transmit BD to avoid + * confusion. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetTxUsed(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdSetTxUsed(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_USED_MASK)) + + +/*****************************************************************************/ +/** + * Software clears this bit to enable the buffer to be read by the hardware. + * Hardware sets this bit for the first buffer of a frame once it has been + * successfully transmitted. This macro clears this bit of transmit BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdClearTxUsed(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearTxUsed(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_USED_MASK)) + + +/*****************************************************************************/ +/** + * Determine the used bit of the transmit BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxUsed(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxUsed(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_USED_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if a frame fails to be transmitted due to too many retries. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxRetry(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxRetry(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_RETRY_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if a frame fails to be transmitted due to data can not be + * feteched in time or buffers are exhausted. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxUrun(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxUrun(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_URUN_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if a frame fails to be transmitted due to buffer is exhausted + * mid-frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxExh(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxExh(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_EXH_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Sets this bit, no CRC will be appended to the current frame. This control + * bit must be set for the first buffer in a frame and will be ignored for + * the subsequent buffers of a frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * This bit must be clear when using the transmit checksum generation offload, + * otherwise checksum generation and substitution will not occur. + * + * C-style signature: + * UINTPTR XEmacPs_BdSetTxNoCRC(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdSetTxNoCRC(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_NOCRC_MASK)) + + +/*****************************************************************************/ +/** + * Clear this bit, CRC will be appended to the current frame. This control + * bit must be set for the first buffer in a frame and will be ignored for + * the subsequent buffers of a frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * This bit must be clear when using the transmit checksum generation offload, + * otherwise checksum generation and substitution will not occur. + * + * C-style signature: + * UINTPTR XEmacPs_BdClearTxNoCRC(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearTxNoCRC(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_NOCRC_MASK)) + + +/*****************************************************************************/ +/** + * Determine the broadcast bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxBcast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxBcast(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_BCAST_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the multicast hash bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxMultiHash(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxMultiHash(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_MULTIHASH_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the unicast hash bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxUniHash(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxUniHash(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_UNIHASH_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if the received frame is a VLAN Tagged frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxVlan(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxVlan(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_VLAN_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if the received frame has Type ID of 8100h and null VLAN + * identifier(Priority tag). + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxPri(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxPri(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_PRI_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if the received frame's Concatenation Format Indicator (CFI) of + * the frames VLANTCI field was set. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxCFI(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxCFI(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_CFI_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the End Of Frame (EOF) bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetRxEOF(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxEOF(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_EOF_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the Start Of Frame (SOF) bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetRxSOF(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxSOF(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_SOF_MASK)!=0U ? TRUE : FALSE) + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xemacps_bdring.h b/bsp_z7/ps7_cortexa9_0/include/xemacps_bdring.h new file mode 100644 index 0000000..f5653db --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xemacps_bdring.h @@ -0,0 +1,215 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_bdring.h +* @addtogroup emacps_v3_16 +* @{ +* +* The Xiline EmacPs Buffer Descriptor ring driver. This is part of EmacPs +* DMA functionalities. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp architecture.
+* 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.6   rb   09/08/17 HwCnt variable (in XEmacPs_BdRing structure) is
+*		      changed to volatile.
+*
+* 
+* +******************************************************************************/ + +#ifndef XEMACPS_BDRING_H /* prevent curcular inclusions */ +#define XEMACPS_BDRING_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/**************************** Type Definitions *******************************/ + +/** This is an internal structure used to maintain the DMA list */ +typedef struct { + UINTPTR PhysBaseAddr;/**< Physical address of 1st BD in list */ + UINTPTR BaseBdAddr; /**< Virtual address of 1st BD in list */ + UINTPTR HighBdAddr; /**< Virtual address of last BD in the list */ + u32 Length; /**< Total size of ring in bytes */ + u32 RunState; /**< Flag to indicate DMA is started */ + u32 Separation; /**< Number of bytes between the starting address + of adjacent BDs */ + XEmacPs_Bd *FreeHead; + /**< First BD in the free group */ + XEmacPs_Bd *PreHead;/**< First BD in the pre-work group */ + XEmacPs_Bd *HwHead; /**< First BD in the work group */ + XEmacPs_Bd *HwTail; /**< Last BD in the work group */ + XEmacPs_Bd *PostHead; + /**< First BD in the post-work group */ + XEmacPs_Bd *BdaRestart; + /**< BDA to load when channel is started */ + + volatile u32 HwCnt; /**< Number of BDs in work group */ + u32 PreCnt; /**< Number of BDs in pre-work group */ + u32 FreeCnt; /**< Number of allocatable BDs in the free group */ + u32 PostCnt; /**< Number of BDs in post-work group */ + u32 AllCnt; /**< Total Number of BDs for channel */ +} XEmacPs_BdRing; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* Use this macro at initialization time to determine how many BDs will fit +* in a BD list within the given memory constraints. +* +* The results of this macro can be provided to XEmacPs_BdRingCreate(). +* +* @param Alignment specifies what byte alignment the BDs must fall on and +* must be a power of 2 to get an accurate calculation (32, 64, 128,...) +* @param Bytes is the number of bytes to be used to store BDs. +* +* @return Number of BDs that can fit in the given memory area +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingCntCalc(u32 Alignment, u32 Bytes) +* +******************************************************************************/ +#define XEmacPs_BdRingCntCalc(Alignment, Bytes) \ + (u32)((Bytes) / (sizeof(XEmacPs_Bd))) + +/*****************************************************************************/ +/** +* Use this macro at initialization time to determine how many bytes of memory +* is required to contain a given number of BDs at a given alignment. +* +* @param Alignment specifies what byte alignment the BDs must fall on. This +* parameter must be a power of 2 to get an accurate calculation (32, 64, +* 128,...) +* @param NumBd is the number of BDs to calculate memory size requirements for +* +* @return The number of bytes of memory required to create a BD list with the +* given memory constraints. +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingMemCalc(u32 Alignment, u32 NumBd) +* +******************************************************************************/ +#define XEmacPs_BdRingMemCalc(Alignment, NumBd) \ + (u32)(sizeof(XEmacPs_Bd) * (NumBd)) + +/****************************************************************************/ +/** +* Return the total number of BDs allocated by this channel with +* XEmacPs_BdRingCreate(). +* +* @param RingPtr is the DMA channel to operate on. +* +* @return The total number of BDs allocated for this channel. +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingGetCnt(XEmacPs_BdRing* RingPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingGetCnt(RingPtr) ((RingPtr)->AllCnt) + +/****************************************************************************/ +/** +* Return the number of BDs allocatable with XEmacPs_BdRingAlloc() for pre- +* processing. +* +* @param RingPtr is the DMA channel to operate on. +* +* @return The number of BDs currently allocatable. +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingGetFreeCnt(XEmacPs_BdRing* RingPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingGetFreeCnt(RingPtr) ((RingPtr)->FreeCnt) + +/****************************************************************************/ +/** +* Return the next BD from BdPtr in a list. +* +* @param RingPtr is the DMA channel to operate on. +* @param BdPtr is the BD to operate on. +* +* @return The next BD in the list relative to the BdPtr parameter. +* +* @note +* C-style signature: +* XEmacPs_Bd *XEmacPs_BdRingNext(XEmacPs_BdRing* RingPtr, +* XEmacPs_Bd *BdPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingNext(RingPtr, BdPtr) \ + (((UINTPTR)((void *)(BdPtr)) >= (RingPtr)->HighBdAddr) ? \ + (XEmacPs_Bd*)((void*)(RingPtr)->BaseBdAddr) : \ + (XEmacPs_Bd*)((UINTPTR)((void *)(BdPtr)) + (RingPtr)->Separation)) + +/****************************************************************************/ +/** +* Return the previous BD from BdPtr in the list. +* +* @param RingPtr is the DMA channel to operate on. +* @param BdPtr is the BD to operate on +* +* @return The previous BD in the list relative to the BdPtr parameter. +* +* @note +* C-style signature: +* XEmacPs_Bd *XEmacPs_BdRingPrev(XEmacPs_BdRing* RingPtr, +* XEmacPs_Bd *BdPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingPrev(RingPtr, BdPtr) \ + (((UINTPTR)(BdPtr) <= (RingPtr)->BaseBdAddr) ? \ + (XEmacPs_Bd*)(RingPtr)->HighBdAddr : \ + (XEmacPs_Bd*)((UINTPTR)(BdPtr) - (RingPtr)->Separation)) + +/************************** Function Prototypes ******************************/ + +/* + * Scatter gather DMA related functions in xemacps_bdring.c + */ +LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr, + UINTPTR VirtAddr, u32 Alignment, u32 BdCount); +LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr, + u8 Direction); +LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd ** BdSetPtr); +LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr); +LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr); +LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr); +u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, + XEmacPs_Bd ** BdSetPtr); +u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, + XEmacPs_Bd ** BdSetPtr); +LONG XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction); + +void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc); + +#ifdef __cplusplus +} +#endif + + +#endif /* end of protection macros */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xemacps_hw.h b/bsp_z7/ps7_cortexa9_0/include/xemacps_hw.h new file mode 100644 index 0000000..59fe1ec --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xemacps_hw.h @@ -0,0 +1,664 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_hw.h +* @addtogroup emacps_v3_16 +* @{ +* +* This header file contains identifiers and low-level driver functions (or +* macros) that can be used to access the PS Ethernet MAC (XEmacPs) device. +* High-level driver functions are defined in xemacps.h. +* +* @note +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release.
+* 1.02a asa  11/05/12 Added hash defines for DMACR burst length configuration.
+* 1.05a kpc  28/06/13 Added XEmacPs_ResetHw function prototype
+* 1.06a asa  11/02/13 Changed the value for XEMACPS_RXBUF_LEN_MASK from 0x3fff
+*					  to 0x1fff. This fixes the CR#744902.
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification.
+* 3.0   kvn  12/16/14 Changed name of XEMACPS_NWCFG_LENGTHERRDSCRD_MASK to
+*					  XEMACPS_NWCFG_LENERRDSCRD_MASK as it exceeds 31 characters.
+* 3.0  kpc   1/23/15  Corrected the extended descriptor macro values.
+* 3.0  kvn   02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.0  hk   03/18/15 Added support for jumbo frames.
+*                    Remove "used bit set" from TX error interrupt masks.
+* 3.1  hk   08/10/15 Update upper 32 bit tx and rx queue ptr register offsets.
+* 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
+* 3.8  hk   09/17/18 Fix PTP interrupt masks.
+* 3.9  hk   01/23/19 Add RX watermark support
+* 3.10 hk   05/16/19 Clear status registers properly in reset
+* 3.18  sne 01/11/23 Add PCS control and status registers information.
+* 
+* +******************************************************************************/ + +#ifndef XEMACPS_HW_H /* prevent circular inclusions */ +#define XEMACPS_HW_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +#define XEMACPS_MAX_MAC_ADDR 4U /**< Maxmum number of mac address + supported */ +#define XEMACPS_MAX_TYPE_ID 4U /**< Maxmum number of type id supported */ + +#ifdef __aarch64__ +#define XEMACPS_BD_ALIGNMENT 64U /**< Minimum buffer descriptor alignment + on the local bus */ +#else + +#define XEMACPS_BD_ALIGNMENT 4U /**< Minimum buffer descriptor alignment + on the local bus */ +#endif +#define XEMACPS_RX_BUF_ALIGNMENT 4U /**< Minimum buffer alignment when using + options that impose alignment + restrictions on the buffer data on + the local bus */ + +/** @name Direction identifiers + * + * These are used by several functions and callbacks that need + * to specify whether an operation specifies a send or receive channel. + * @{ + */ +#define XEMACPS_SEND 1U /**< send direction */ +#define XEMACPS_RECV 2U /**< receive direction */ +/*@}*/ + +/** @name MDC clock division + * currently supporting 8, 16, 32, 48, 64, 96, 128, 224. + * @{ + */ +typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, + MDC_DIV_64, MDC_DIV_96, MDC_DIV_128, MDC_DIV_224 +} XEmacPs_MdcDiv; + +/*@}*/ + +#define XEMACPS_RX_BUF_SIZE 1536U /**< Specify the receive buffer size in + bytes, 64, 128, ... 10240 */ +#define XEMACPS_RX_BUF_SIZE_JUMBO 10240U + +#define XEMACPS_RX_BUF_UNIT 64U /**< Number of receive buffer bytes as a + unit, this is HW setup */ + +#define XEMACPS_MAX_RXBD 128U /**< Size of RX buffer descriptor queues */ +#define XEMACPS_MAX_TXBD 128U /**< Size of TX buffer descriptor queues */ + +#define XEMACPS_MAX_HASH_BITS 64U /**< Maximum value for hash bits. 2**6 */ + +/* Register offset definitions. Unless otherwise noted, register access is + * 32 bit. Names are self explained here. + */ + +#define XEMACPS_NWCTRL_OFFSET 0x00000000U /**< Network Control reg */ +#define XEMACPS_NWCFG_OFFSET 0x00000004U /**< Network Config reg */ +#define XEMACPS_NWSR_OFFSET 0x00000008U /**< Network Status reg */ + +#define XEMACPS_DMACR_OFFSET 0x00000010U /**< DMA Control reg */ +#define XEMACPS_TXSR_OFFSET 0x00000014U /**< TX Status reg */ +#define XEMACPS_RXQBASE_OFFSET 0x00000018U /**< RX Q Base address reg */ +#define XEMACPS_TXQBASE_OFFSET 0x0000001CU /**< TX Q Base address reg */ +#define XEMACPS_RXSR_OFFSET 0x00000020U /**< RX Status reg */ + +#define XEMACPS_ISR_OFFSET 0x00000024U /**< Interrupt Status reg */ +#define XEMACPS_IER_OFFSET 0x00000028U /**< Interrupt Enable reg */ +#define XEMACPS_IDR_OFFSET 0x0000002CU /**< Interrupt Disable reg */ +#define XEMACPS_IMR_OFFSET 0x00000030U /**< Interrupt Mask reg */ + +#define XEMACPS_PHYMNTNC_OFFSET 0x00000034U /**< Phy Maintaince reg */ +#define XEMACPS_RXPAUSE_OFFSET 0x00000038U /**< RX Pause Time reg */ +#define XEMACPS_TXPAUSE_OFFSET 0x0000003CU /**< TX Pause Time reg */ + +#define XEMACPS_JUMBOMAXLEN_OFFSET 0x00000048U /**< Jumbo max length reg */ + +#define XEMACPS_RXWATERMARK_OFFSET 0x0000007CU /**< RX watermark reg */ + +#define XEMACPS_HASHL_OFFSET 0x00000080U /**< Hash Low address reg */ +#define XEMACPS_HASHH_OFFSET 0x00000084U /**< Hash High address reg */ + +#define XEMACPS_LADDR1L_OFFSET 0x00000088U /**< Specific1 addr low reg */ +#define XEMACPS_LADDR1H_OFFSET 0x0000008CU /**< Specific1 addr high reg */ +#define XEMACPS_LADDR2L_OFFSET 0x00000090U /**< Specific2 addr low reg */ +#define XEMACPS_LADDR2H_OFFSET 0x00000094U /**< Specific2 addr high reg */ +#define XEMACPS_LADDR3L_OFFSET 0x00000098U /**< Specific3 addr low reg */ +#define XEMACPS_LADDR3H_OFFSET 0x0000009CU /**< Specific3 addr high reg */ +#define XEMACPS_LADDR4L_OFFSET 0x000000A0U /**< Specific4 addr low reg */ +#define XEMACPS_LADDR4H_OFFSET 0x000000A4U /**< Specific4 addr high reg */ + +#define XEMACPS_MATCH1_OFFSET 0x000000A8U /**< Type ID1 Match reg */ +#define XEMACPS_MATCH2_OFFSET 0x000000ACU /**< Type ID2 Match reg */ +#define XEMACPS_MATCH3_OFFSET 0x000000B0U /**< Type ID3 Match reg */ +#define XEMACPS_MATCH4_OFFSET 0x000000B4U /**< Type ID4 Match reg */ + +#define XEMACPS_STRETCH_OFFSET 0x000000BCU /**< IPG Stretch reg */ + +#define XEMACPS_OCTTXL_OFFSET 0x00000100U /**< Octects transmitted Low + reg */ +#define XEMACPS_OCTTXH_OFFSET 0x00000104U /**< Octects transmitted High + reg */ + +#define XEMACPS_TXCNT_OFFSET 0x00000108U /**< Error-free Frmaes + transmitted counter */ +#define XEMACPS_TXBCCNT_OFFSET 0x0000010CU /**< Error-free Broadcast + Frames counter*/ +#define XEMACPS_TXMCCNT_OFFSET 0x00000110U /**< Error-free Multicast + Frame counter */ +#define XEMACPS_TXPAUSECNT_OFFSET 0x00000114U /**< Pause Frames Transmitted + Counter */ +#define XEMACPS_TX64CNT_OFFSET 0x00000118U /**< Error-free 64 byte Frames + Transmitted counter */ +#define XEMACPS_TX65CNT_OFFSET 0x0000011CU /**< Error-free 65-127 byte + Frames Transmitted + counter */ +#define XEMACPS_TX128CNT_OFFSET 0x00000120U /**< Error-free 128-255 byte + Frames Transmitted + counter*/ +#define XEMACPS_TX256CNT_OFFSET 0x00000124U /**< Error-free 256-511 byte + Frames transmitted + counter */ +#define XEMACPS_TX512CNT_OFFSET 0x00000128U /**< Error-free 512-1023 byte + Frames transmitted + counter */ +#define XEMACPS_TX1024CNT_OFFSET 0x0000012CU /**< Error-free 1024-1518 byte + Frames transmitted + counter */ +#define XEMACPS_TX1519CNT_OFFSET 0x00000130U /**< Error-free larger than + 1519 byte Frames + transmitted counter */ +#define XEMACPS_TXURUNCNT_OFFSET 0x00000134U /**< TX under run error + counter */ + +#define XEMACPS_SNGLCOLLCNT_OFFSET 0x00000138U /**< Single Collision Frame + Counter */ +#define XEMACPS_MULTICOLLCNT_OFFSET 0x0000013CU /**< Multiple Collision Frame + Counter */ +#define XEMACPS_EXCESSCOLLCNT_OFFSET 0x00000140U /**< Excessive Collision Frame + Counter */ +#define XEMACPS_LATECOLLCNT_OFFSET 0x00000144U /**< Late Collision Frame + Counter */ +#define XEMACPS_TXDEFERCNT_OFFSET 0x00000148U /**< Deferred Transmission + Frame Counter */ +#define XEMACPS_TXCSENSECNT_OFFSET 0x0000014CU /**< Transmit Carrier Sense + Error Counter */ + +#define XEMACPS_OCTRXL_OFFSET 0x00000150U /**< Octects Received register + Low */ +#define XEMACPS_OCTRXH_OFFSET 0x00000154U /**< Octects Received register + High */ + +#define XEMACPS_RXCNT_OFFSET 0x00000158U /**< Error-free Frames + Received Counter */ +#define XEMACPS_RXBROADCNT_OFFSET 0x0000015CU /**< Error-free Broadcast + Frames Received Counter */ +#define XEMACPS_RXMULTICNT_OFFSET 0x00000160U /**< Error-free Multicast + Frames Received Counter */ +#define XEMACPS_RXPAUSECNT_OFFSET 0x00000164U /**< Pause Frames + Received Counter */ +#define XEMACPS_RX64CNT_OFFSET 0x00000168U /**< Error-free 64 byte Frames + Received Counter */ +#define XEMACPS_RX65CNT_OFFSET 0x0000016CU /**< Error-free 65-127 byte + Frames Received Counter */ +#define XEMACPS_RX128CNT_OFFSET 0x00000170U /**< Error-free 128-255 byte + Frames Received Counter */ +#define XEMACPS_RX256CNT_OFFSET 0x00000174U /**< Error-free 256-512 byte + Frames Received Counter */ +#define XEMACPS_RX512CNT_OFFSET 0x00000178U /**< Error-free 512-1023 byte + Frames Received Counter */ +#define XEMACPS_RX1024CNT_OFFSET 0x0000017CU /**< Error-free 1024-1518 byte + Frames Received Counter */ +#define XEMACPS_RX1519CNT_OFFSET 0x00000180U /**< Error-free 1519-max byte + Frames Received Counter */ +#define XEMACPS_RXUNDRCNT_OFFSET 0x00000184U /**< Undersize Frames Received + Counter */ +#define XEMACPS_RXOVRCNT_OFFSET 0x00000188U /**< Oversize Frames Received + Counter */ +#define XEMACPS_RXJABCNT_OFFSET 0x0000018CU /**< Jabbers Received + Counter */ +#define XEMACPS_RXFCSCNT_OFFSET 0x00000190U /**< Frame Check Sequence + Error Counter */ +#define XEMACPS_RXLENGTHCNT_OFFSET 0x00000194U /**< Length Field Error + Counter */ +#define XEMACPS_RXSYMBCNT_OFFSET 0x00000198U /**< Symbol Error Counter */ +#define XEMACPS_RXALIGNCNT_OFFSET 0x0000019CU /**< Alignment Error Counter */ +#define XEMACPS_RXRESERRCNT_OFFSET 0x000001A0U /**< Receive Resource Error + Counter */ +#define XEMACPS_RXORCNT_OFFSET 0x000001A4U /**< Receive Overrun Counter */ +#define XEMACPS_RXIPCCNT_OFFSET 0x000001A8U /**< IP header Checksum Error + Counter */ +#define XEMACPS_RXTCPCCNT_OFFSET 0x000001ACU /**< TCP Checksum Error + Counter */ +#define XEMACPS_RXUDPCCNT_OFFSET 0x000001B0U /**< UDP Checksum Error + Counter */ +#define XEMACPS_LAST_OFFSET 0x000001B4U /**< Last statistic counter + offset, for clearing */ + +#define XEMACPS_1588_SEC_OFFSET 0x000001D0U /**< 1588 second counter */ +#define XEMACPS_1588_NANOSEC_OFFSET 0x000001D4U /**< 1588 nanosecond counter */ +#define XEMACPS_1588_ADJ_OFFSET 0x000001D8U /**< 1588 nanosecond + adjustment counter */ +#define XEMACPS_1588_INC_OFFSET 0x000001DCU /**< 1588 nanosecond + increment counter */ +#define XEMACPS_PTP_TXSEC_OFFSET 0x000001E0U /**< 1588 PTP transmit second + counter */ +#define XEMACPS_PTP_TXNANOSEC_OFFSET 0x000001E4U /**< 1588 PTP transmit + nanosecond counter */ +#define XEMACPS_PTP_RXSEC_OFFSET 0x000001E8U /**< 1588 PTP receive second + counter */ +#define XEMACPS_PTP_RXNANOSEC_OFFSET 0x000001ECU /**< 1588 PTP receive + nanosecond counter */ +#define XEMACPS_PTPP_TXSEC_OFFSET 0x000001F0U /**< 1588 PTP peer transmit + second counter */ +#define XEMACPS_PTPP_TXNANOSEC_OFFSET 0x000001F4U /**< 1588 PTP peer transmit + nanosecond counter */ +#define XEMACPS_PTPP_RXSEC_OFFSET 0x000001F8U /**< 1588 PTP peer receive + second counter */ +#define XEMACPS_PTPP_RXNANOSEC_OFFSET 0x000001FCU /**< 1588 PTP peer receive + nanosecond counter */ +#define XEMACPS_PCS_CONTROL_OFFSET 0x00000200U /** PCS control register */ +#define XEMACPS_PCS_STATUS_OFFSET 0x00000204U /** PCS status register */ + +#define XEMACPS_INTQ1_STS_OFFSET 0x00000400U /**< Interrupt Q1 Status + reg */ +#define XEMACPS_TXQ1BASE_OFFSET 0x00000440U /**< TX Q1 Base address + reg */ +#define XEMACPS_RXQ1BASE_OFFSET 0x00000480U /**< RX Q1 Base address + reg */ +#define XEMACPS_MSBBUF_TXQBASE_OFFSET 0x000004C8U /**< MSB Buffer TX Q Base + reg */ +#define XEMACPS_MSBBUF_RXQBASE_OFFSET 0x000004D4U /**< MSB Buffer RX Q Base + reg */ +#define XEMACPS_INTQ1_IER_OFFSET 0x00000600U /**< Interrupt Q1 Enable + reg */ +#define XEMACPS_INTQ1_IDR_OFFSET 0x00000620U /**< Interrupt Q1 Disable + reg */ +#define XEMACPS_INTQ1_IMR_OFFSET 0x00000640U /**< Interrupt Q1 Mask + reg */ + +/* Define some bit positions for registers. */ + +/** @name network control register bit definitions + * @{ + */ +#define XEMACPS_NWCTRL_FLUSH_DPRAM_MASK 0x00040000U /**< Flush a packet from + Rx SRAM */ +#define XEMACPS_NWCTRL_ZEROPAUSETX_MASK 0x00000800U /**< Transmit zero quantum + pause frame */ +#define XEMACPS_NWCTRL_PAUSETX_MASK 0x00000800U /**< Transmit pause frame */ +#define XEMACPS_NWCTRL_HALTTX_MASK 0x00000400U /**< Halt transmission + after current frame */ +#define XEMACPS_NWCTRL_STARTTX_MASK 0x00000200U /**< Start tx (tx_go) */ + +#define XEMACPS_NWCTRL_STATWEN_MASK 0x00000080U /**< Enable writing to + stat counters */ +#define XEMACPS_NWCTRL_STATINC_MASK 0x00000040U /**< Increment statistic + registers */ +#define XEMACPS_NWCTRL_STATCLR_MASK 0x00000020U /**< Clear statistic + registers */ +#define XEMACPS_NWCTRL_MDEN_MASK 0x00000010U /**< Enable MDIO port */ +#define XEMACPS_NWCTRL_TXEN_MASK 0x00000008U /**< Enable transmit */ +#define XEMACPS_NWCTRL_RXEN_MASK 0x00000004U /**< Enable receive */ +#define XEMACPS_NWCTRL_LOOPEN_MASK 0x00000002U /**< local loopback */ +/*@}*/ + +/** @name network configuration register bit definitions + * @{ + */ +#define XEMACPS_NWCFG_BADPREAMBEN_MASK 0x20000000U /**< disable rejection of + non-standard preamble */ +#define XEMACPS_NWCFG_IPDSTRETCH_MASK 0x10000000U /**< enable transmit IPG */ +#define XEMACPS_NWCFG_SGMIIEN_MASK 0x08000000U /**< SGMII Enable */ +#define XEMACPS_NWCFG_FCSIGNORE_MASK 0x04000000U /**< disable rejection of + FCS error */ +#define XEMACPS_NWCFG_HDRXEN_MASK 0x02000000U /**< RX half duplex */ +#define XEMACPS_NWCFG_RXCHKSUMEN_MASK 0x01000000U /**< enable RX checksum + offload */ +#define XEMACPS_NWCFG_PAUSECOPYDI_MASK 0x00800000U /**< Do not copy pause + Frames to memory */ +#define XEMACPS_NWCFG_DWIDTH_64_MASK 0x00200000U /**< 64 bit Data bus width */ +#define XEMACPS_NWCFG_MDC_SHIFT_MASK 18U /**< shift bits for MDC */ +#define XEMACPS_NWCFG_MDCCLKDIV_MASK 0x001C0000U /**< MDC Mask PCLK divisor */ +#define XEMACPS_NWCFG_FCSREM_MASK 0x00020000U /**< Discard FCS from + received frames */ +#define XEMACPS_NWCFG_LENERRDSCRD_MASK 0x00010000U +/**< RX length error discard */ +#define XEMACPS_NWCFG_RXOFFS_MASK 0x0000C000U /**< RX buffer offset */ +#define XEMACPS_NWCFG_PAUSEEN_MASK 0x00002000U /**< Enable pause RX */ +#define XEMACPS_NWCFG_RETRYTESTEN_MASK 0x00001000U /**< Retry test */ +#define XEMACPS_NWCFG_XTADDMACHEN_MASK 0x00000200U +/**< External address match enable */ +#define XEMACPS_NWCFG_PCSSEL_MASK 0x00000800U /**< PCS Select */ +#define XEMACPS_NWCFG_1000_MASK 0x00000400U /**< 1000 Mbps */ +#define XEMACPS_NWCFG_1536RXEN_MASK 0x00000100U /**< Enable 1536 byte + frames reception */ +#define XEMACPS_NWCFG_UCASTHASHEN_MASK 0x00000080U /**< Receive unicast hash + frames */ +#define XEMACPS_NWCFG_MCASTHASHEN_MASK 0x00000040U /**< Receive multicast hash + frames */ +#define XEMACPS_NWCFG_BCASTDI_MASK 0x00000020U /**< Do not receive + broadcast frames */ +#define XEMACPS_NWCFG_COPYALLEN_MASK 0x00000010U /**< Copy all frames */ +#define XEMACPS_NWCFG_JUMBO_MASK 0x00000008U /**< Jumbo frames */ +#define XEMACPS_NWCFG_NVLANDISC_MASK 0x00000004U /**< Receive only VLAN + frames */ +#define XEMACPS_NWCFG_FDEN_MASK 0x00000002U/**< full duplex */ +#define XEMACPS_NWCFG_100_MASK 0x00000001U /**< 100 Mbps */ +#define XEMACPS_NWCFG_RESET_MASK 0x00080000U/**< reset value */ +/*@}*/ + +/** @name network status register bit definitaions + * @{ + */ +#define XEMACPS_NWSR_MDIOIDLE_MASK 0x00000004U /**< PHY management idle */ +#define XEMACPS_NWSR_MDIO_MASK 0x00000002U /**< Status of mdio_in */ +/*@}*/ + + +/** @name MAC address register word 1 mask + * @{ + */ +#define XEMACPS_LADDR_MACH_MASK 0x0000FFFFU /**< Address bits[47:32] + bit[31:0] are in BOTTOM */ +/*@}*/ + + +/** @name DMA control register bit definitions + * @{ + */ +#define XEMACPS_DMACR_ADDR_WIDTH_64 0x40000000U /**< 64 bit address bus */ +#define XEMACPS_DMACR_TXEXTEND_MASK 0x20000000U /**< Tx Extended desc mode */ +#define XEMACPS_DMACR_RXEXTEND_MASK 0x10000000U /**< Rx Extended desc mode */ +#define XEMACPS_DMACR_RXBUF_MASK 0x00FF0000U /**< Mask bit for RX buffer + size */ +#define XEMACPS_DMACR_RXBUF_SHIFT 16U /**< Shift bit for RX buffer + size */ +#define XEMACPS_DMACR_TCPCKSUM_MASK 0x00000800U /**< enable/disable TX + checksum offload */ +#define XEMACPS_DMACR_TXSIZE_MASK 0x00000400U /**< TX buffer memory size */ +#define XEMACPS_DMACR_RXSIZE_MASK 0x00000300U /**< RX buffer memory size */ +#define XEMACPS_DMACR_ENDIAN_MASK 0x00000080U /**< endian configuration */ +#define XEMACPS_DMACR_BLENGTH_MASK 0x0000001FU /**< buffer burst length */ +#define XEMACPS_DMACR_SINGLE_AHB_BURST 0x00000001U /**< single AHB bursts */ +#define XEMACPS_DMACR_INCR4_AHB_BURST 0x00000004U /**< 4 bytes AHB bursts */ +#define XEMACPS_DMACR_INCR8_AHB_BURST 0x00000008U /**< 8 bytes AHB bursts */ +#define XEMACPS_DMACR_INCR16_AHB_BURST 0x00000010U /**< 16 bytes AHB bursts */ +/*@}*/ + +/** @name transmit status register bit definitions + * @{ + */ +#define XEMACPS_TXSR_HRESPNOK_MASK 0x00000100U /**< Transmit hresp not OK */ +#define XEMACPS_TXSR_URUN_MASK 0x00000040U /**< Transmit underrun */ +#define XEMACPS_TXSR_TXCOMPL_MASK 0x00000020U /**< Transmit completed OK */ +#define XEMACPS_TXSR_BUFEXH_MASK 0x00000010U /**< Transmit buffs exhausted + mid frame */ +#define XEMACPS_TXSR_TXGO_MASK 0x00000008U /**< Status of go flag */ +#define XEMACPS_TXSR_RXOVR_MASK 0x00000004U /**< Retry limit exceeded */ +#define XEMACPS_TXSR_FRAMERX_MASK 0x00000002U /**< Collision tx frame */ +#define XEMACPS_TXSR_USEDREAD_MASK 0x00000001U /**< TX buffer used bit set */ + +#define XEMACPS_TXSR_ERROR_MASK ((u32)XEMACPS_TXSR_HRESPNOK_MASK | \ + (u32)XEMACPS_TXSR_URUN_MASK | \ + (u32)XEMACPS_TXSR_BUFEXH_MASK | \ + (u32)XEMACPS_TXSR_RXOVR_MASK | \ + (u32)XEMACPS_TXSR_FRAMERX_MASK | \ + (u32)XEMACPS_TXSR_USEDREAD_MASK) +/*@}*/ + +/** + * @name receive status register bit definitions + * @{ + */ +#define XEMACPS_RXSR_HRESPNOK_MASK 0x00000008U /**< Receive hresp not OK */ +#define XEMACPS_RXSR_RXOVR_MASK 0x00000004U /**< Receive overrun */ +#define XEMACPS_RXSR_FRAMERX_MASK 0x00000002U /**< Frame received OK */ +#define XEMACPS_RXSR_BUFFNA_MASK 0x00000001U /**< RX buffer used bit set */ + +#define XEMACPS_RXSR_ERROR_MASK ((u32)XEMACPS_RXSR_HRESPNOK_MASK | \ + (u32)XEMACPS_RXSR_RXOVR_MASK | \ + (u32)XEMACPS_RXSR_BUFFNA_MASK) + +#define XEMACPS_SR_ALL_MASK 0xFFFFFFFFU /**< Mask for full register */ + +/*@}*/ + +/** + * @name PCS control register bit definitions + * @{ + */ +#define XEMACPS_PCS_CON_AUTO_NEG_MASK 0x00001000U /**< Auto-negotiation */ +/*@}*/ + +/** + * @name PCS status register bit definitions + * @{ + */ +#define XEMACPS_PCS_STATUS_LINK_STATUS_MASK 0x00000004U /**< Link status */ +/*@}*/ + +/** + * @name Interrupt Q1 status register bit definitions + * @{ + */ +#define XEMACPS_INTQ1SR_TXCOMPL_MASK 0x00000080U /**< Transmit completed OK */ +#define XEMACPS_INTQ1SR_TXERR_MASK 0x00000040U /**< Transmit AMBA Error */ + +#define XEMACPS_INTQ1_IXR_ALL_MASK ((u32)XEMACPS_INTQ1SR_TXCOMPL_MASK | \ + (u32)XEMACPS_INTQ1SR_TXERR_MASK) + +/*@}*/ + +/** + * @name interrupts bit definitions + * Bits definitions are same in XEMACPS_ISR_OFFSET, + * XEMACPS_IER_OFFSET, XEMACPS_IDR_OFFSET, and XEMACPS_IMR_OFFSET + * @{ + */ +#define XEMACPS_IXR_PTPPSTX_MASK 0x02000000U /**< PTP Pdelay_resp TXed */ +#define XEMACPS_IXR_PTPPDRTX_MASK 0x01000000U /**< PTP Pdelay_req TXed */ +#define XEMACPS_IXR_PTPPSRX_MASK 0x00800000U /**< PTP Pdelay_resp RXed */ +#define XEMACPS_IXR_PTPPDRRX_MASK 0x00400000U /**< PTP Pdelay_req RXed */ + +#define XEMACPS_IXR_PTPSTX_MASK 0x00200000U /**< PTP Sync TXed */ +#define XEMACPS_IXR_PTPDRTX_MASK 0x00100000U /**< PTP Delay_req TXed */ +#define XEMACPS_IXR_PTPSRX_MASK 0x00080000U /**< PTP Sync RXed */ +#define XEMACPS_IXR_PTPDRRX_MASK 0x00040000U /**< PTP Delay_req RXed */ + +#define XEMACPS_IXR_PAUSETX_MASK 0x00004000U /**< Pause frame transmitted */ +#define XEMACPS_IXR_PAUSEZERO_MASK 0x00002000U /**< Pause time has reached + zero */ +#define XEMACPS_IXR_PAUSENZERO_MASK 0x00001000U /**< Pause frame received */ +#define XEMACPS_IXR_HRESPNOK_MASK 0x00000800U /**< hresp not ok */ +#define XEMACPS_IXR_RXOVR_MASK 0x00000400U /**< Receive overrun occurred */ +#define XEMACPS_IXR_TXCOMPL_MASK 0x00000080U /**< Frame transmitted ok */ +#define XEMACPS_IXR_TXEXH_MASK 0x00000040U /**< Transmit err occurred or + no buffers*/ +#define XEMACPS_IXR_RETRY_MASK 0x00000020U /**< Retry limit exceeded */ +#define XEMACPS_IXR_URUN_MASK 0x00000010U /**< Transmit underrun */ +#define XEMACPS_IXR_TXUSED_MASK 0x00000008U /**< Tx buffer used bit read */ +#define XEMACPS_IXR_RXUSED_MASK 0x00000004U /**< Rx buffer used bit read */ +#define XEMACPS_IXR_FRAMERX_MASK 0x00000002U /**< Frame received ok */ +#define XEMACPS_IXR_MGMNT_MASK 0x00000001U /**< PHY management complete */ +#define XEMACPS_IXR_ALL_MASK 0x00007FFFU /**< Everything! */ + +#define XEMACPS_IXR_TX_ERR_MASK ((u32)XEMACPS_IXR_TXEXH_MASK | \ + (u32)XEMACPS_IXR_RETRY_MASK | \ + (u32)XEMACPS_IXR_URUN_MASK) + + +#define XEMACPS_IXR_RX_ERR_MASK ((u32)XEMACPS_IXR_HRESPNOK_MASK | \ + (u32)XEMACPS_IXR_RXUSED_MASK | \ + (u32)XEMACPS_IXR_RXOVR_MASK) + +/*@}*/ + +/** @name PHY Maintenance bit definitions + * @{ + */ +#define XEMACPS_PHYMNTNC_OP_MASK 0x40020000U /**< operation mask bits */ +#define XEMACPS_PHYMNTNC_OP_R_MASK 0x20000000U /**< read operation */ +#define XEMACPS_PHYMNTNC_OP_W_MASK 0x10000000U /**< write operation */ +#define XEMACPS_PHYMNTNC_ADDR_MASK 0x0F800000U /**< Address bits */ +#define XEMACPS_PHYMNTNC_REG_MASK 0x007C0000U /**< register bits */ +#define XEMACPS_PHYMNTNC_DATA_MASK 0x00000FFFU /**< data bits */ +#define XEMACPS_PHYMNTNC_PHAD_SHFT_MSK 23U /**< Shift bits for PHYAD */ +#define XEMACPS_PHYMNTNC_PREG_SHFT_MSK 18U /**< Shift bits for PHREG */ +/*@}*/ + +/** @name RX watermark bit definitions + * @{ + */ +#define XEMACPS_RXWM_HIGH_MASK 0x0000FFFFU /**< RXWM high mask */ +#define XEMACPS_RXWM_LOW_MASK 0xFFFF0000U /**< RXWM low mask */ +#define XEMACPS_RXWM_LOW_SHFT_MSK 16U /**< Shift for RXWM low */ +/*@}*/ + +/* Transmit buffer descriptor status words offset + * @{ + */ +#define XEMACPS_BD_ADDR_OFFSET 0x00000000U /**< word 0/addr of BDs */ +#define XEMACPS_BD_STAT_OFFSET 0x00000004U /**< word 1/status of BDs */ +#define XEMACPS_BD_ADDR_HI_OFFSET 0x00000008U /**< word 2/addr of BDs */ + +/* + * @} + */ + +/* Transmit buffer descriptor status words bit positions. + * Transmit buffer descriptor consists of two 32-bit registers, + * the first - word0 contains a 32-bit address pointing to the location of + * the transmit data. + * The following register - word1, consists of various information to control + * the XEmacPs transmit process. After transmit, this is updated with status + * information, whether the frame was transmitted OK or why it had failed. + * @{ + */ +#define XEMACPS_TXBUF_USED_MASK 0x80000000U /**< Used bit. */ +#define XEMACPS_TXBUF_WRAP_MASK 0x40000000U /**< Wrap bit, last descriptor */ +#define XEMACPS_TXBUF_RETRY_MASK 0x20000000U /**< Retry limit exceeded */ +#define XEMACPS_TXBUF_URUN_MASK 0x10000000U /**< Transmit underrun occurred */ +#define XEMACPS_TXBUF_EXH_MASK 0x08000000U /**< Buffers exhausted */ +#define XEMACPS_TXBUF_TCP_MASK 0x04000000U /**< Late collision. */ +#define XEMACPS_TXBUF_NOCRC_MASK 0x00010000U /**< No CRC */ +#define XEMACPS_TXBUF_LAST_MASK 0x00008000U /**< Last buffer */ +#define XEMACPS_TXBUF_LEN_MASK 0x00003FFFU /**< Mask for length field */ +/* + * @} + */ + +/* Receive buffer descriptor status words bit positions. + * Receive buffer descriptor consists of two 32-bit registers, + * the first - word0 contains a 32-bit word aligned address pointing to the + * address of the buffer. The lower two bits make up the wrap bit indicating + * the last descriptor and the ownership bit to indicate it has been used by + * the XEmacPs. + * The following register - word1, contains status information regarding why + * the frame was received (the filter match condition) as well as other + * useful info. + * @{ + */ +#define XEMACPS_RXBUF_BCAST_MASK 0x80000000U /**< Broadcast frame */ +#define XEMACPS_RXBUF_MULTIHASH_MASK 0x40000000U /**< Multicast hashed frame */ +#define XEMACPS_RXBUF_UNIHASH_MASK 0x20000000U /**< Unicast hashed frame */ +#define XEMACPS_RXBUF_EXH_MASK 0x08000000U /**< buffer exhausted */ +#define XEMACPS_RXBUF_AMATCH_MASK 0x06000000U /**< Specific address + matched */ +#define XEMACPS_RXBUF_IDFOUND_MASK 0x01000000U /**< Type ID matched */ +#define XEMACPS_RXBUF_IDMATCH_MASK 0x00C00000U /**< ID matched mask */ +#define XEMACPS_RXBUF_VLAN_MASK 0x00200000U /**< VLAN tagged */ +#define XEMACPS_RXBUF_PRI_MASK 0x00100000U /**< Priority tagged */ +#define XEMACPS_RXBUF_VPRI_MASK 0x000E0000U /**< Vlan priority */ +#define XEMACPS_RXBUF_CFI_MASK 0x00010000U /**< CFI frame */ +#define XEMACPS_RXBUF_EOF_MASK 0x00008000U /**< End of frame. */ +#define XEMACPS_RXBUF_SOF_MASK 0x00004000U /**< Start of frame. */ +#define XEMACPS_RXBUF_LEN_MASK 0x00001FFFU /**< Mask for length field */ +#define XEMACPS_RXBUF_LEN_JUMBO_MASK 0x00003FFFU /**< Mask for jumbo length */ + +#define XEMACPS_RXBUF_WRAP_MASK 0x00000002U /**< Wrap bit, last BD */ +#define XEMACPS_RXBUF_NEW_MASK 0x00000001U /**< Used bit.. */ +#define XEMACPS_RXBUF_ADD_MASK 0xFFFFFFFCU /**< Mask for address */ +/* + * @} + */ + +/* + * Define appropriate I/O access method to memory mapped I/O or other + * interface if necessary. + */ + +#define XEmacPs_In32 Xil_In32 +#define XEmacPs_Out32 Xil_Out32 + + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddress is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XEmacPs_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XEmacPs_ReadReg(BaseAddress, RegOffset) \ + XEmacPs_In32((BaseAddress) + (u32)(RegOffset)) + + +/****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddress is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XEmacPs_WriteReg(u32 BaseAddress, u32 RegOffset, +* u32 Data) +* +*****************************************************************************/ +#define XEmacPs_WriteReg(BaseAddress, RegOffset, Data) \ + XEmacPs_Out32((BaseAddress) + (u32)(RegOffset), (u32)(Data)) + +/************************** Function Prototypes *****************************/ +/* + * Perform reset operation to the emacps interface + */ +void XEmacPs_ResetHw(u32 BaseAddr); + +#ifdef __cplusplus + } +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xenv.h b/bsp_z7/ps7_cortexa9_0/include/xenv.h new file mode 100644 index 0000000..d8aef59 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xenv.h @@ -0,0 +1,169 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xenv.h +* +* Defines common services that are typically found in a host operating. +* environment. This include file simply includes an OS specific file based +* on the compile-time constant BUILD_ENV_*, where * is the name of the target +* environment. +* +* All services are defined as macros. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b ch   10/24/02 Added XENV_LINUX
+* 1.00a rmm  04/17/02 First release
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XENV_H /* prevent circular inclusions */ +#define XENV_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Select which target environment we are operating under + */ + +/* VxWorks target environment */ +#if defined XENV_VXWORKS +#include "xenv_vxworks.h" + +/* Linux target environment */ +#elif defined XENV_LINUX +#include "xenv_linux.h" + +/* Unit test environment */ +#elif defined XENV_UNITTEST +#include "ut_xenv.h" + +/* Integration test environment */ +#elif defined XENV_INTTEST +#include "int_xenv.h" + +/* Standalone environment selected */ +#else +#include "xenv_standalone.h" +#endif + + +/* + * The following comments specify the types and macro wrappers that are + * expected to be defined by the target specific header files + */ + +/**************************** Type Definitions *******************************/ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP + * + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * + * XENV_MEM_COPY(void *DestPtr, void *SrcPtr, unsigned Bytes) + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr is the destination address to copy data to. + * @param SrcPtr is the source address to copy data from. + * @param Bytes is the number of bytes to copy. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_MEM_FILL(void *DestPtr, char Data, unsigned Bytes) + * + * Fills an area of memory with constant data. + * + * @param DestPtr is the destination address to set. + * @param Data contains the value to set. + * @param Bytes is the number of bytes to set. + * + * @return None + */ +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + * + * Samples the processor's or external timer's time base counter. + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_US(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of microseconds. + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_MS(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of milliseconds. + */ + +/*****************************************************************************//** + * + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. + * + * @param delay is the number of microseconds to delay. + * + * @return None + */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ + +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xenv_standalone.h b/bsp_z7/ps7_cortexa9_0/include/xenv_standalone.h new file mode 100644 index 0000000..9794da0 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xenv_standalone.h @@ -0,0 +1,350 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xenv_standalone.h +* +* Defines common services specified by xenv.h. +* +* @note +* This file is not intended to be included directly by driver code. +* Instead, the generic xenv.h file is intended to be included by driver +* code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a wgr  02/28/07 Added cache handling macros.
+* 1.00a wgr  02/27/07 Simplified code. Deprecated old-style macro names.
+* 1.00a rmm  01/24/06 Implemented XENV_USLEEP. Assume implementation is being
+*                     used under Xilinx standalone BSP.
+* 1.00a xd   11/03/04 Improved support for doxygen.
+* 1.00a rmm  03/21/02 First release
+* 1.00a wgr  03/22/07 Converted to new coding style.
+* 1.00a rpm  06/29/07 Added udelay macro for standalone
+* 1.00a xd   07/19/07 Included xparameters.h as XPAR_ constants are referred
+*                     to in MICROBLAZE section
+* 1.00a ecm  09/19/08 updated for v7.20 of Microblaze, new functionality
+*
+* 
+* +* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XENV_STANDALONE_H +#define XENV_STANDALONE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +/****************************************************************************** + * + * Get the processor dependent includes + * + ******************************************************************************/ + +#include + +#if defined __MICROBLAZE__ +# include "mb_interface.h" +# include "xparameters.h" /* XPAR constants used below in MB section */ + +#elif defined __PPC__ +# include "sleep.h" +# include "xcache_l.h" /* also include xcache_l.h for caching macros */ +#endif + +/****************************************************************************** + * + * MEMCPY / MEMSET related macros. + * + * The following are straight forward implementations of memset and memcpy. + * + * NOTE: memcpy may not work if source and target memory area are overlapping. + * + ******************************************************************************/ +/*****************************************************************************/ +/** + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param SrcPtr + * Source address to copy data from. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_COPY is deprecated. Use memcpy() instead. + * + * @note + * This implementation MAY BREAK work if source and target memory + * area are overlapping. + * + *****************************************************************************/ + +#define XENV_MEM_COPY(DestPtr, SrcPtr, Bytes) \ + memcpy((void *) DestPtr, (const void *) SrcPtr, (size_t) Bytes) + + + +/*****************************************************************************/ +/** + * + * Fills an area of memory with constant data. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param Data + * Value to set. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_FILL is deprecated. Use memset() instead. + * + *****************************************************************************/ + +#define XENV_MEM_FILL(DestPtr, Data, Bytes) \ + memset((void *) DestPtr, (s32) Data, (size_t) Bytes) + + + +/****************************************************************************** + * + * TIME related macros + * + ******************************************************************************/ + +/** + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ +typedef s32 XENV_TIME_STAMP; + +/*****************************************************************************/ +/** + * + * Time is derived from the 64 bit PPC timebase register + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None. + * + * @note + * + * Signature: void XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + *

+ * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_GET(StampPtr) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_US(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_MS(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. Not implemented without OS + * support. + * + * @param delay + * Number of microseconds to delay. + * + * @return None. + * + *****************************************************************************/ + +#ifdef __PPC__ +#define XENV_USLEEP(delay) usleep(delay) +#define udelay(delay) usleep(delay) +#else +#define XENV_USLEEP(delay) +#define udelay(delay) +#endif + + +/****************************************************************************** + * + * CACHE handling macros / mappings + * + ******************************************************************************/ +/****************************************************************************** + * + * Processor independent macros + * + ******************************************************************************/ + +#define XCACHE_ENABLE_CACHE() \ + { XCACHE_ENABLE_DCACHE(); XCACHE_ENABLE_ICACHE(); } + +#define XCACHE_DISABLE_CACHE() \ + { XCACHE_DISABLE_DCACHE(); XCACHE_DISABLE_ICACHE(); } + + +/****************************************************************************** + * + * MicroBlaze case + * + * NOTE: Currently the following macros will only work on systems that contain + * only ONE MicroBlaze processor. Also, the macros will only be enabled if the + * system is built using a xparameters.h file. + * + ******************************************************************************/ + +#if defined __MICROBLAZE__ + +/* Check if MicroBlaze data cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_DCACHE == 1) +# define XCACHE_ENABLE_DCACHE() microblaze_enable_dcache() +# define XCACHE_DISABLE_DCACHE() microblaze_disable_dcache() +# define XCACHE_INVALIDATE_DCACHE() microblaze_invalidate_dcache() + +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) + +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define XCACHE_FLUSH_DCACHE() microblaze_flush_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_flush_dcache_range((s32)(Addr), (s32)(Len)) +#else +# define XCACHE_FLUSH_DCACHE() microblaze_invalidate_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) +#endif /*XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK*/ + +#else +# define XCACHE_ENABLE_DCACHE() +# define XCACHE_DISABLE_DCACHE() +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) +#endif /*XPAR_MICROBLAZE_USE_DCACHE*/ + + +/* Check if MicroBlaze instruction cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_ICACHE == 1) +# define XCACHE_ENABLE_ICACHE() microblaze_enable_icache() +# define XCACHE_DISABLE_ICACHE() microblaze_disable_icache() + +# define XCACHE_INVALIDATE_ICACHE() microblaze_invalidate_icache() + +# define XCACHE_INVALIDATE_ICACHE_RANGE(Addr, Len) \ + microblaze_invalidate_icache_range((s32)(Addr), (s32)(Len)) + +#else +# define XCACHE_ENABLE_ICACHE() +# define XCACHE_DISABLE_ICACHE() +#endif /*XPAR_MICROBLAZE_USE_ICACHE*/ + + +/****************************************************************************** + * + * PowerPC case + * + * Note that the XCACHE_ENABLE_xxx functions are hardcoded to enable a + * specific memory region (0x80000001). Each bit (0-30) in the regions + * bitmask stands for 128MB of memory. Bit 31 stands for the upper 2GB + * range. + * + * regions --> cached address range + * ------------|-------------------------------------------------- + * 0x80000000 | [0, 0x7FFFFFF] + * 0x00000001 | [0xF8000000, 0xFFFFFFFF] + * 0x80000001 | [0, 0x7FFFFFF],[0xF8000000, 0xFFFFFFFF] + * + ******************************************************************************/ + +#elif defined __PPC__ + +#define XCACHE_ENABLE_DCACHE() XCache_EnableDCache(0x80000001) +#define XCACHE_DISABLE_DCACHE() XCache_DisableDCache() +#define XCACHE_ENABLE_ICACHE() XCache_EnableICache(0x80000001) +#define XCACHE_DISABLE_ICACHE() XCache_DisableICache() + +#define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + XCache_InvalidateDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + XCache_FlushDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_INVALIDATE_ICACHE() XCache_InvalidateICache() + + +/****************************************************************************** + * + * Unknown processor / architecture + * + ******************************************************************************/ + +#else +/* #error "Unknown processor / architecture. Must be MicroBlaze or PowerPC." */ +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef XENV_STANDALONE_H */ + + /** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xgpiops.h b/bsp_z7/ps7_cortexa9_0/include/xgpiops.h new file mode 100644 index 0000000..8b1d89f --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xgpiops.h @@ -0,0 +1,299 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xgpiops.h +* @addtogroup gpiops Overview +* @{ +* @details +* +* The Xilinx PS GPIO driver. This driver supports the Xilinx PS GPIO +* Controller. +* +* The GPIO Controller supports the following features: +* - 6 banks +* - Masked writes (There are no masked reads) +* - Bypass mode +* - Configurable Interrupts (Level/Edge) +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Here is GPIO Bank and Pin mapping information for different platforms. +* Zynq: +* PS GPIO contain 4 banks and 118 pins +* Bank 0 MIO pins 0 - 31 +* Bank 1 MIO pins 32 - 53 +* Bank 2 MIO pins 54 - 85 +* Bank 3 EMIO signals 86 - 117 +* +* Zynq Ultrascale+ MP: +* PS GPIO contain 6 banks and 174 pins +* Bank 0 MIO pins 0 - 25 +* Bank 1 MIO pins 26 - 51 +* Bank 2 MIO pins 52 - 77 +* Bank 3 EMIO signals 78 - 109 +* Bank 4 EMIO signals 110 - 141 +* Bank 5 EMIO signals 142 - 173 + +* Versal: Two GPIOPS instances PMC GPIO and PS GPIO +* PMC GPIO contain 4 banks and 116 pins +* Bank 0 MIO pins 0 - 25 +* Bank 1 MIO pins 26 - 51 +* Bank 3 EMIO signals 52 - 83 +* Bank 4 EMIO signals 84 - 115 +* PS GPIO contains 2 banks and 58 pins +* Bank 0 MIO pins 0 - 25 +* Bank 3 EMIO signals 26-57 +* +* This driver supports all the features listed above, if applicable. +* +* Driver Description +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the GPIO. +* +* Interrupts +* +* The driver provides interrupt management functions and an interrupt handler. +* Users of this driver need to provide callback functions. An interrupt handler +* example is available with the driver. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XGpioPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +*

+* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.01a sv   04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
+*                     XGpioPs_GetMode, XGpioPs_GetModePin as they are not
+*		      relevant to Zynq device.The interrupts are disabled
+*		      for output pins on all banks during initialization.
+* 1.02a hk   08/22/13 Added low level reset API
+* 2.1   hk   04/29/14 Use Input data register DATA_RO for read. CR# 771667.
+* 2.2	sk	 10/13/14 Used Pin number in Bank instead of pin number
+* 					  passed to APIs. CR# 822636
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+*       ms   04/05/17 Added tabspace for return statements in functions of
+*                     gpiops examples for proper documentation while
+*                     generating doxygen.
+* 3.3   ms   04/17/17 Added notes about gpio input and output pin description
+*                     for zcu102 and zc702 boards in polled and interrupt
+*                     example, configured Interrupt pin to input pin for
+*                     proper functioning of interrupt example.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in safety mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the pointer param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added Versal support.
+* 3.6   mus  04/05/19 Replaced XPLAT_versal macro with XPLAT_VERSAL, to be in
+*                     sync with standalone BSP
+* 3.6	sne  06/12/19 Fixed IAR compiler warning.
+* 3.6   sne  08/14/19 Added interrupt handler support on versal.
+* 3.7	sne  12/04/19 Reverted versal examples support.
+* 3.8   sne  08/28/20 Modify Makefile to support parallel make execution.
+* 3.8	sne  09/17/20 Added description for Versal PS and PMC GPIO pins.
+* 3.9	sne  03/15/21 Fixed MISRA-C violations.
+* 3.11  sg   02/23/23 Update bank and pin mapping information.
+*
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_H /* prevent circular inclusions */ +#define XGPIOPS_H /**< by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xgpiops_hw.h" +#include "xplatform_info.h" + +/************************** Constant Definitions *****************************/ + +/** @name Interrupt types + * @{ + * The following constants define the interrupt types that can be set for each + * GPIO pin. + */ +#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0x00U /**< Interrupt on Rising edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 0x01U /**< Interrupt Falling edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 0x02U /**< Interrupt on both edges */ +#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 0x03U /**< Interrupt on high level */ +#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 0x04U /**< Interrupt on low level */ +/** @}*/ + +#define XGPIOPS_BANK_MAX_PINS (u32)32 /**< Max pins in a GPIO bank */ +#define XGPIOPS_BANK0 0x00U /**< GPIO Bank 0 */ +#define XGPIOPS_BANK1 0x01U /**< GPIO Bank 1 */ +#define XGPIOPS_BANK2 0x02U /**< GPIO Bank 2 */ +#define XGPIOPS_BANK3 0x03U /**< GPIO Bank 3 */ +#define XGPIOPS_BANK4 0x04U /**< GPIO Bank 4 */ +#define XGPIOPS_BANK5 0x05U /**< GPIO Bank 5 */ + +#define XGPIOPS_MAX_BANKS_ZYNQMP 0x06U /**< Max banks in a + * Zynq Ultrascale+ MP GPIO device + */ +#define XGPIOPS_MAX_BANKS 0x04U /**< Max banks in a Zynq GPIO device */ + +#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP (u32)174 /**< Max pins in the + * Zynq Ultrascale+ MP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 + */ +#define XGPIOPS_DEVICE_MAX_PIN_NUM (u32)118 /**< Max pins in the Zynq GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 + */ + +/**************************** Type Definitions *******************************/ + +/****************************************************************************/ +/** + * This handler data type allows the user to define a callback function to + * handle the interrupts for the GPIO device. The application using this + * driver is expected to define a handler of this type, to support interrupt + * driven mode. The handler executes in an interrupt context such that minimal + * processing should be performed. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the callback functions for a GPIO bank. It is + * passed back to the upper layer when the callback is invoked. Its + * type is not important to the driver component, so it is a void + * pointer. + * @param Bank is the bank for which the interrupt status has changed. + * @param Status is the Interrupt status of the GPIO bank. + * + *****************************************************************************/ +typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status); + +/** + * This typedef contains configuration information for a device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddr; /**< Register base address */ +} XGpioPs_Config; + +/** + * The XGpioPs driver instance data. The user is required to allocate a + * variable of this type for the GPIO device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XGpioPs_Config GpioConfig; /**< Device configuration */ + u32 IsReady; /**< Device is initialized and ready */ + XGpioPs_Handler Handler; /**< Status handlers for all banks */ + void *CallBackRef; /**< Callback ref for bank handlers */ + u32 Platform; /**< Platform data */ + u32 MaxPinNum; /**< Max pins in the GPIO device */ + u8 MaxBanks; /**< Max banks in a GPIO device */ + u32 PmcGpio; /**< Flag for accessing PS GPIO for versal*/ +} XGpioPs; + +/************************** Variable Definitions *****************************/ +extern XGpioPs_Config XGpioPs_ConfigTable[]; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/* Functions in xgpiops.c */ +s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, + u32 EffectiveAddr); + +/* Bank APIs in xgpiops.c */ +u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data); +void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction); +u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable); +u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank); +#ifdef versal +void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#else +void XGpioPs_GetBankPin(u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#endif + +/* Pin APIs in xgpiops.c */ +u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data); +void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction); +u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable); +u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin); + +/* Diagnostic functions in xgpiops_selftest.c */ +s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr); + +/* Functions in xgpiops_intr.c */ +/* Bank APIs in xgpiops_intr.c */ +void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank); +u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, + u32 IntrPolarity, u32 IntrOnAny); +void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, + u32 *IntrPolarity, u32 *IntrOnAny); +void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, + XGpioPs_Handler FuncPointer); +void XGpioPs_IntrHandler(const XGpioPs *InstancePtr); + +/* Pin APIs in xgpiops_intr.c */ +void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType); +u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin); + +void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin); + +/* Functions in xgpiops_sinit.c */ +XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xgpiops_hw.h b/bsp_z7/ps7_cortexa9_0/include/xgpiops_hw.h new file mode 100644 index 0000000..d291abb --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xgpiops_hw.h @@ -0,0 +1,147 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xgpiops_hw.h +* @addtogroup gpiops Overview +* @{ +* +* This header file contains the identifiers and basic driver functions (or +* macros) that can be used to access the device. Other driver functions +* are defined in xgpiops.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.02a hk   08/22/13 Added low level reset API function prototype and
+*                     related constant definitions
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Corrected reset values of banks.
+* 3.5   sne  03/14/19 Added versal support.
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_HW_H /* prevent circular inclusions */ +#define XGPIOPS_HW_H /**< by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register offsets for the GPIO. Each register is 32 bits. + * @{ + */ +#define XGPIOPS_DATA_LSW_OFFSET 0x00000000U /**< Mask and Data Register LSW, WO */ +#define XGPIOPS_DATA_MSW_OFFSET 0x00000004U /**< Mask and Data Register MSW, WO */ +#define XGPIOPS_DATA_OFFSET 0x00000040U /**< Data Register, RW */ +#define XGPIOPS_DATA_RO_OFFSET 0x00000060U /**< Data Register - Input, RO */ +#define XGPIOPS_DIRM_OFFSET 0x00000204U /**< Direction Mode Register, RW */ +#define XGPIOPS_OUTEN_OFFSET 0x00000208U /**< Output Enable Register, RW */ +#define XGPIOPS_INTMASK_OFFSET 0x0000020CU /**< Interrupt Mask Register, RO */ +#define XGPIOPS_INTEN_OFFSET 0x00000210U /**< Interrupt Enable Register, WO */ +#define XGPIOPS_INTDIS_OFFSET 0x00000214U /**< Interrupt Disable Register, WO*/ +#define XGPIOPS_INTSTS_OFFSET 0x00000218U /**< Interrupt Status Register, RO */ +#define XGPIOPS_INTTYPE_OFFSET 0x0000021CU /**< Interrupt Type Register, RW */ +#define XGPIOPS_INTPOL_OFFSET 0x00000220U /**< Interrupt Polarity Register, RW */ +#define XGPIOPS_INTANY_OFFSET 0x00000224U /**< Interrupt On Any Register, RW */ +/** @} */ + +/** @name Register offsets for each Bank. + * @{ + */ +#define XGPIOPS_DATA_MASK_OFFSET 0x00000008U /**< Data/Mask Registers offset */ +#define XGPIOPS_DATA_BANK_OFFSET 0x00000004U /**< Data Registers offset */ +#define XGPIOPS_REG_MASK_OFFSET 0x00000040U /**< Registers offset */ +/** @} */ + +/* For backwards compatibility */ +#define XGPIOPS_BYPM_MASK_OFFSET (u32)0x40 /**< Mask for backward support */ + +/** @name Interrupt type reset values for each bank + * @{ + */ +#ifdef XPAR_PSU_GPIO_0_BASEADDR +#define XGPIOPS_INTTYPE_BANK0_RESET 0x03FFFFFFU /**< Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x03FFFFFFU /**< Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK2_RESET 0x03FFFFFFU /**< Resets specific to Zynq Ultrascale+ MP */ +#else +#define XGPIOPS_INTTYPE_BANK0_RESET 0xFFFFFFFFU /**< Resets specific to Zynq */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x003FFFFFU /**< Resets specific to Zynq */ +#define XGPIOPS_INTTYPE_BANK2_RESET 0xFFFFFFFFU /**< Resets specific to Zynq */ +#endif + +#define XGPIOPS_INTTYPE_BANK3_RESET 0xFFFFFFFFU /**< Reset common to both platforms */ +#define XGPIOPS_INTTYPE_BANK4_RESET 0xFFFFFFFFU /**< Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK5_RESET 0xFFFFFFFFU /**< Resets specific to Zynq Ultrascale+ MP */ +/** @} */ +#define XGPIOPS_PS_GPIO_BASEADDR 0xFF0B0000U /**< Flag for Base Address for PS_GPIO in Versal */ +#define XGPIOPS_ZERO 0U /**< Flag for 0 Value */ +#define XGPIOPS_ONE 1U /**< Flag for 1 Value */ +#define XGPIOPS_TWO 2U /**< Flag for 2 Value */ +#define XGPIOPS_THREE 3U /**< Flag for 3 Value */ +#define XGPIOPS_FOUR 4U /**< Flag for 4 Value */ +#define XGPIOPS_SIX 6U /**< Flag for 6 Value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* This macro reads the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the register offset to be read. +* +* @return The 32-bit value of the register +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (u32)(RegOffset)) + +/****************************************************************************/ +/** +* +* This macro writes to the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the offset of the register to be written. +* @param Data is the 32-bit value to write to the register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) + +/************************** Function Prototypes ******************************/ + +void XGpioPs_ResetHw(UINTPTR BaseAddress); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XGPIOPS_HW_H */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_assert.c b/bsp_z7/ps7_cortexa9_0/include/xil_assert.c new file mode 100644 index 0000000..b3dd7e9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_assert.c @@ -0,0 +1,126 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_assert.c +* @addtogroup common_assert_apis Assert APIs and Macros +* @{ +* +* This file contains basic assert related functions for Xilinx software IP. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 Initial release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/** + * @brief This variable allows testing to be done easier with asserts. An assert + * sets this variable such that a driver can evaluate this variable + * to determine if an assert occurred. + */ +u32 Xil_AssertStatus; + +/** + * @brief This variable allows the assert functionality to be changed for testing + * such that it does not wait infinitely. Use the debugger to disable the + * waiting during testing of asserts. + */ +s32 Xil_AssertWait = 1; + +/* The callback function to be invoked when an assert is taken */ +static Xil_AssertCallback Xil_AssertCallbackRoutine = NULL; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* @brief Implement assert. Currently, it calls a user-defined callback +* function if one has been set. Then, it potentially enters an +* infinite loop depending on the value of the Xil_AssertWait +* variable. +* +* @param File: filename of the source +* @param Line: linenumber within File +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void Xil_Assert(const char8 *File, s32 Line) +{ + /* if the callback has been set then invoke it */ + if (Xil_AssertCallbackRoutine != 0) { + (*Xil_AssertCallbackRoutine)(File, Line); + } + + /* if specified, wait indefinitely such that the assert will show up + * in testing + */ + while (Xil_AssertWait != 0) { + } +} + +/*****************************************************************************/ +/** +* +* @brief Set up a callback function to be invoked when an assert occurs. +* If a callback is already installed, then it will be replaced. +* +* @param Routine: callback to be invoked when an assert is taken +* +* @return None. +* +* @note This function has no effect if NDEBUG is set +* +******************************************************************************/ +void Xil_AssertSetCallback(Xil_AssertCallback Routine) +{ + Xil_AssertCallbackRoutine = Routine; +} + +/*****************************************************************************/ +/** +* +* @brief Null handler function. This follows the XInterruptHandler +* signature for interrupt handlers. It can be used to assign a null +* handler (a stub) to an interrupt controller vector table. +* +* @param NullParameter: arbitrary void pointer and not used. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XNullHandler(void *NullParameter) +{ + (void) NullParameter; +} +/** +* @} End of "addtogroup common_assert_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_assert.h b/bsp_z7/ps7_cortexa9_0/include/xil_assert.h new file mode 100644 index 0000000..e8b87b5 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_assert.h @@ -0,0 +1,176 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_assert.h +* +* @addtogroup common_assert_apis Assert APIs and Macros +* +* The xil_assert.h file contains assert related functions and macros. +* Assert APIs/Macros specifies that a application program satisfies certain +* conditions at particular points in its execution. These function can be +* used by application programs to ensure that, application code is satisfying +* certain conditions. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_ASSERT_H /* prevent circular inclusions */ +#define XIL_ASSERT_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + + +/************************** Constant Definitions *****************************/ + +#define XIL_ASSERT_NONE 0U +#define XIL_ASSERT_OCCURRED 1U +#define XNULL NULL + +extern u32 Xil_AssertStatus; +extern s32 Xil_AssertWait; +extern void Xil_Assert(const char8 *File, s32 Line); +/** + *@endcond + */ +void XNullHandler(void *NullParameter); + +/** + * This data type defines a callback to be invoked when an + * assert occurs. The callback is invoked only when asserts are enabled + */ +typedef void (*Xil_AssertCallback) (const char8 *File, s32 Line); + +/***************** Macros (Inline Functions) Definitions *********************/ + +#ifndef NDEBUG + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for void functions. This in +* conjunction with the Xil_AssertWait boolean can be used to +* accommodate tests so that asserts which fail allow execution to +* continue. +* +* @param Expression: expression to be evaluated. If it evaluates to +* false, the assert occurs. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for functions that do return a +* value. This in conjunction with the Xil_AssertWait boolean can be +* used to accommodate tests so that asserts which fail allow execution +* to continue. +* +* @param Expression: expression to be evaluated. If it evaluates to false, +* the assert occurs. +* +* @return Returns 0 unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for void functions. +* Use for instances where an assert should always occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for functions that +* do return a value. Use for instances where an assert should always +* occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ +} + + +#else + +#define Xil_AssertVoid(Expression) +#define Xil_AssertVoidAlways() +#define Xil_AssertNonvoid(Expression) +#define Xil_AssertNonvoidAlways() + +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_AssertSetCallback(Xil_AssertCallback Routine); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_assert_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_cache.h b/bsp_z7/ps7_cortexa9_0/include/xil_cache.h new file mode 100644 index 0000000..75cd6f6 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_cache.h @@ -0,0 +1,105 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_cache.h +* +* @addtogroup a9_cache_apis Cortex A9 Processor Cache Functions +* +* Cache functions provide access to cache related operations such as flush +* and invalidate for instruction and data caches. It gives option to perform +* the cache operations on a single cacheline, a range of memory and an entire +* cache. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/29/10 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb/dmb instructions in cache maintenance
+*		      APIs.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef XIL_CACHE_H +#define XIL_CACHE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNUC__ + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#elif defined (__ICCARM__) + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#endif + +/** +*@endcond +*/ + +void Xil_DCacheEnable(void); +void Xil_DCacheDisable(void); +void Xil_DCacheInvalidate(void); +void Xil_DCacheInvalidateRange(INTPTR adr, u32 len); +void Xil_DCacheFlush(void); +void Xil_DCacheFlushRange(INTPTR adr, u32 len); + +void Xil_ICacheEnable(void); +void Xil_ICacheDisable(void); +void Xil_ICacheInvalidate(void); +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_cache_l.h b/bsp_z7/ps7_cortexa9_0/include/xil_cache_l.h new file mode 100644 index 0000000..21c8ced --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_cache_l.h @@ -0,0 +1,75 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_cache_l.h +* +* Contains L1 and L2 specific functions for the ARM cache functionality +* used by xcache.c. This functionality is being made available here for +* more sophisticated users. +* +* @addtogroup a9_cache_apis +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/24/10 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XIL_CACHE_MACH_H +#define XIL_CACHE_MACH_H + +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_DCacheInvalidateLine(u32 adr); +void Xil_DCacheFlushLine(u32 adr); +void Xil_DCacheStoreLine(u32 adr); +void Xil_ICacheInvalidateLine(u32 adr); + +void Xil_L1DCacheEnable(void); +void Xil_L1DCacheDisable(void); +void Xil_L1DCacheInvalidate(void); +void Xil_L1DCacheInvalidateLine(u32 adr); +void Xil_L1DCacheInvalidateRange(u32 adr, u32 len); +void Xil_L1DCacheFlush(void); +void Xil_L1DCacheFlushLine(u32 adr); +void Xil_L1DCacheFlushRange(u32 adr, u32 len); +void Xil_L1DCacheStoreLine(u32 adr); + +void Xil_L1ICacheEnable(void); +void Xil_L1ICacheDisable(void); +void Xil_L1ICacheInvalidate(void); +void Xil_L1ICacheInvalidateLine(u32 adr); +void Xil_L1ICacheInvalidateRange(u32 adr, u32 len); + +void Xil_L2CacheEnable(void); +void Xil_L2CacheDisable(void); +void Xil_L2CacheInvalidate(void); +void Xil_L2CacheInvalidateLine(u32 adr); +void Xil_L2CacheInvalidateRange(u32 adr, u32 len); +void Xil_L2CacheFlush(void); +void Xil_L2CacheFlushLine(u32 adr); +void Xil_L2CacheFlushRange(u32 adr, u32 len); +void Xil_L2CacheStoreLine(u32 adr); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_cache_vxworks.h b/bsp_z7/ps7_cortexa9_0/include/xil_cache_vxworks.h new file mode 100644 index 0000000..64079e7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_cache_vxworks.h @@ -0,0 +1,75 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_cache_vxworks.h +* +* Contains the cache related functions for VxWorks that is wrapped by +* xil_cache. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  12/11/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_CACHE_VXWORKS_H +#define XIL_CACHE_VXWORKS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "vxWorks.h" +#include "vxLib.h" +#include "sysLibExtra.h" +#include "cacheLib.h" + +#if (CPU_FAMILY==PPC) + +#define Xil_DCacheEnable() cacheEnable(DATA_CACHE) + +#define Xil_DCacheDisable() cacheDisable(DATA_CACHE) + +#define Xil_DCacheInvalidateRange(Addr, Len) \ + cacheInvalidate(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_DCacheFlushRange(Addr, Len) \ + cacheFlush(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_ICacheEnable() cacheEnable(INSTRUCTION_CACHE) + +#define Xil_ICacheDisable() cacheDisable(INSTRUCTION_CACHE) + +#define Xil_ICacheInvalidateRange(Addr, Len) \ + cacheInvalidate(INSTRUCTION_CACHE, (void *)(Addr), (Len)) + + +#else +#error "Unknown processor / architecture. Must be PPC for VxWorks." +#endif + +#ifdef __cplusplus +} +#endif + +#endif +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_errata.h b/bsp_z7/ps7_cortexa9_0/include/xil_errata.h new file mode 100644 index 0000000..5923f44 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_errata.h @@ -0,0 +1,101 @@ +/****************************************************************************** +* Copyright (c) 2013 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_errata.h +* +* @addtogroup a9_errata Cortex A9 Processor and pl310 Errata Support +* @{ +* Various ARM errata are handled in the standalone BSP. The implementation for +* errata handling follows ARM guidelines and is based on the open source Linux +* support for these errata. +* +* @note The errata handling is enabled by default. To disable handling of all the +* errata globally, un-define the macro ENABLE_ARM_ERRATA in xil_errata.h. To +* disable errata on a per-erratum basis, un-define relevant macros in +* xil_errata.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a srt  04/18/13 First release
+* 6.6   mus  12/07/17 Removed errata 753970, It fixes CR#989132
+* 7.7   asa  01/06/22 Removed errata 742230 and 743622. These are
+*                     already fixed in Cortex-A9 r3p0, the revision
+*                     that is being used in Zynq platforms.
+* 
+* +******************************************************************************/ +#ifndef XIL_ERRATA_H +#define XIL_ERRATA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + *@cond nocomments + */ +/** + * @name errata_definitions + * + * The errata conditions handled in the standalone BSP are listed below + * @{ + */ + +#define ENABLE_ARM_ERRATA 1 + +/** + *@endcond + */ + +#ifdef ENABLE_ARM_ERRATA + +/** + * Errata No: 775420 + * Description: A data cache maintenance operation which aborts, + * might lead to deadlock + */ +#define CONFIG_ARM_ERRATA_775420 1 + +/** + * Errata No: 794073 + * Description: Speculative instruction fetches with MMU disabled + * might not comply with architectural requirements + */ +#define CONFIG_ARM_ERRATA_794073 1 + + +/** PL310 L2 Cache Errata */ + +/** + * Errata No: 588369 + * Description: Clean & Invalidate maintenance operations do not + * invalidate clean lines + */ +#define CONFIG_PL310_ERRATA_588369 1 + +/** + * Errata No: 727915 + * Description: Background Clean and Invalidate by Way operation + * can cause data corruption + */ +#define CONFIG_PL310_ERRATA_727915 1 + +/*@}*/ +#endif /* ENABLE_ARM_ERRATA */ + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_ERRATA_H */ +/** +* @} End of "addtogroup a9_errata". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_exception.h b/bsp_z7/ps7_cortexa9_0/include/xil_exception.h new file mode 100644 index 0000000..3a5bb29 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_exception.h @@ -0,0 +1,530 @@ +/****************************************************************************** +* Copyright (c) 2015 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_exception.h +* +* This header file contains ARM Cortex A53,A9,R5 specific exception related APIs. +* For exception related functions that can be used across all Xilinx supported +* processors, please use xil_exception.h. +* +* @addtogroup arm_exception_apis ARM Processor Exception Handling +* @{ +* ARM processors specific exception related APIs for cortex A53,A9 and R5 can +* utilized for enabling/disabling IRQ, registering/removing handler for +* exceptions or initializing exception vector table with null handler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.2	pkp  	 28/05/15 First release
+* 6.0   mus      27/07/16 Consolidated file for a53,a9 and r5 processors
+* 6.7   mna      26/04/18 Add API Xil_GetExceptionRegisterHandler.
+* 6.7   asa      18/05/18 Update signature of API Xil_GetExceptionRegisterHandler.
+* 7.0   mus      01/03/19 Tweak Xil_ExceptionEnableMask and
+*                         Xil_ExceptionDisableMask macros to support legacy
+*                         examples for Cortexa72 EL3 exception level.
+* 7.3   mus      04/15/20 Added Xil_EnableNestedInterrupts and
+*                         Xil_DisableNestedInterrupts macros for ARMv8.
+*                         For Cortexa72, these macro's would not be supported
+*                         at EL3, as Cortexa72 is using GIC-500(GICv3),  which
+*                         triggeres only FIQ at EL3. Fix for CR#1062506
+* 7.6   mus      09/17/21 Updated flag checking to fix warning reported with
+*                         -Wundef compiler option CR#1110261
+* 7.7   mus      01/31/22 Few of the #defines in xil_exception.h in are treated
+*                         in different way based on "versal" flag. In existing
+*                         flow, this flag is defined only in xparameters.h and
+*                         BSP compiler flags, it is not defined in application
+*                         compiler flags. So, including xil_exception.h in
+*                         application source file, without including
+*                         xparameters.h results  in incorrect behavior.
+*                         Including xparameters.h in xil_exception.h to avoid
+*                         such issues. It fixes CR#1120498.
+* 8.0  mus       02/24/22 Updated few macros to support legacy driver examples
+*                         for CortexR52. This is needed, as by default scugic
+*                         driver configures interrupts as group0 and CortexR52
+*                         GIC triggers FIQ for group0 interrupts.
+* 8.0  sk	 03/02/22 Define XExc_VectorTableEntry structure to fix
+* 			  misra_c_2012_rule_5_6 violation.
+* 8.0  sk	 03/02/22 Add XExc_VectorTable as extern to fix misra_c_2012_
+* 			  rule_8_4 violation.
+* 8.1  asa       02/12/23 Updated data abort and prefetch abort fault
+*                         status reporting for ARMv7.
+*						  Updated Sync and SError fault status reporting
+*						  for ARMv8.
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_EXCEPTION_H /* prevent circular inclusions */ +#define XIL_EXCEPTION_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xpseudo_asm.h" +#include "bspconfig.h" +#include "xparameters.h" +#include "xdebug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions ****************************/ + +#define XIL_EXCEPTION_FIQ XREG_CPSR_FIQ_ENABLE +#define XIL_EXCEPTION_IRQ XREG_CPSR_IRQ_ENABLE +#define XIL_EXCEPTION_ALL (XREG_CPSR_FIQ_ENABLE | XREG_CPSR_IRQ_ENABLE) + +#define XIL_EXCEPTION_ID_FIRST 0U +#if defined (__aarch64__) +#define XIL_EXCEPTION_ID_SYNC_INT 1U +#define XIL_EXCEPTION_ID_IRQ_INT 2U +#define XIL_EXCEPTION_ID_FIQ_INT 3U +#define XIL_EXCEPTION_ID_SERROR_ABORT_INT 4U +#define XIL_EXCEPTION_ID_LAST 5U +#else +#define XIL_EXCEPTION_ID_RESET 0U +#define XIL_EXCEPTION_ID_UNDEFINED_INT 1U +#define XIL_EXCEPTION_ID_SWI_INT 2U +#define XIL_EXCEPTION_ID_PREFETCH_ABORT_INT 3U +#define XIL_EXCEPTION_ID_DATA_ABORT_INT 4U +#define XIL_EXCEPTION_ID_IRQ_INT 5U +#define XIL_EXCEPTION_ID_FIQ_INT 6U +#define XIL_EXCEPTION_ID_LAST 6U +#endif + +#ifdef DEBUG + +#if defined (__aarch64__) +#define ARMV8_SYNC_ERROR 0x01U +#define ARMV8_SERROR 0x02U + +#define ARMV8_FAR_VALUE_VALID 0x01U + +#define ARMV8_ESR_EC_SHIFT 26U +#define ARMV8_ESR_EC_MASK ((0x3FU) << ARMV8_ESR_EC_SHIFT) +#define ARMV8_EXTRACT_ESR_EC(Val) \ + (((Val) & ARMV8_ESR_EC_MASK) >> ARMV8_ESR_EC_SHIFT) + +#define ARMV8_ESR_IL_SHIFT (25U) +#define ARMV8_ESR_IL_MASK ((1U) << ARMV8_ESR_IL_SHIFT) +#define ARMV8_EXTRACT_ESR_IL(Val) \ + (((Val) & ARMV8_ESR_IL_MASK) >> ARMV8_ESR_IL_SHIFT) + +#define ARMV8_ESR_ISS_MASK (ARMV8_ESR_IL_MASK - 1U) +#define ARMV8_EXTRACT_ESR_ISS(Val) ((Val) & ARMV8_ESR_ISS_MASK) + + +#define ARMV8_ESR_EC_UNKNOWN_ERR 0x00U +#define ARMV8_ESR_EC_FP_ASIMD 0x07U +#define ARMV8_ESR_ILL_EXECUTION_STATE 0x0EU +#define ARMV8_ESR_EC_DATA_ABORT_LOWER 0x24U +#define ARMV8_ESR_EC_DATA_ABORT 0x25U +#define ARMV8_ESR_EC_INS_ABORT_LOWER 0x20U +#define ARMV8_ESR_EC_INS_ABORT 0x21U +#define ARMV8_ESR_EC_PC_ALIGNMENT_FAULT 0x22U +#define ARMV8_ESR_EC_SP_ALIGNMENT_FAULT 0x26U +#define ARMV8_ESR_EC_SERROR 0x2FU + + +/* ISS field definitions shared by different classes */ +#define ARMV8_ESR_ISS_WNR_SHIFT (6U) +#define ARMV8_ESR_ISS_WNR_MASK ((1U) << ARMV8_ESR_ISS_WNR_SHIFT) + +/* Asynchronous Error Type */ + +#define ARMV8_ESR_ISS_AET_SHIFT (10U) +#define ARMV8_ESR_ISS_AET_MASK ((0x7U) << ARMV8_ESR_ISS_AET_SHIFT) +#define ARMV8_ESR_ISS_AET_UC ((0U) << ARMV8_ESR_ISS_AET_SHIFT) +#define ARMV8_ESR_ISS_AET_UEU ((1U) << ARMV8_ESR_ISS_AET_SHIFT) +#define ARMV8_ESR_ISS_AET_UEO ((2U) << ARMV8_ESR_ISS_AET_SHIFT) +#define ARMV8_ESR_ISS_AET_UER ((3U) << ARMV8_ESR_ISS_AET_SHIFT) +#define ARMV8_ESR_ISS_AET_CE ((6U) << ARMV8_ESR_ISS_AET_SHIFT) + + +/* Shared ISS fault status code(IFSC/DFSC) for Data/Instruction aborts */ +#define ARMV8_ESR_ISS_FSC (0x3FU) +#define ARMV8_ESR_ISS_CM_SHIFT (8U) +#define ARMV8_ESR_ISS_CM_MASK ((1U) << ARMV8_ESR_ISS_CM_SHIFT) + +#define ARMV8_LEVEL_0_ADDR_FAULT 0x00U +#define ARMV8_LEVEL_1_ADDR_FAULT 0x01U +#define ARMV8_LEVEL_2_ADDR_FAULT 0x02U +#define ARMV8_LEVEL_3_ADDR_FAULT 0x03U +#define ARMV8_LEVEL_0_TRANS_FAULT 0x04U +#define ARMV8_LEVEL_1_TRANS_FAULT 0x05U +#define ARMV8_LEVEL_2_TRANS_FAULT 0x06U +#define ARMV8_LEVEL_3_TRANS_FAULT 0x07U +#define ARMV8_LEVEL_0_ACCS_FLAG_FAULT 0x08U +#define ARMV8_LEVEL_1_ACCS_FLAG_FAULT 0x09U +#define ARMV8_LEVEL_2_ACCS_FLAG_FAULT 0x0AU +#define ARMV8_LEVEL_3_ACCS_FLAG_FAULT 0x0BU +#define ARMV8_LEVEL_0_PERMISSION_FAULT 0x0CU +#define ARMV8_LEVEL_1_PERMISSION_FAULT 0x0DU +#define ARMV8_LEVEL_2_PERMISSION_FAULT 0x0EU +#define ARMV8_LEVEL_3_PERMISSION_FAULT 0x0FU + +#define ARMV8_SYNC_EXT_ABORT_NOT_ON_TTW 0x10U +#define ARMV8_LEVEL_0_SYNC_EXT_ABORT 0x14U +#define ARMV8_LEVEL_1_SYNC_EXT_ABORT 0x15U +#define ARMV8_LEVEL_2_SYNC_EXT_ABORT 0x16U +#define ARMV8_LEVEL_3_SYNC_EXT_ABORT 0x17U + +#define ARMV8_SYNC_PAR_OR_ECC_ERROR_NOT_ON_TTW 0x18U +#define ARMV8_LEVEL_0_SYNC_PAR_OR_ECC_ERROR 0x1CU +#define ARMV8_LEVEL_1_SYNC_PAR_OR_ECC_ERROR 0x1DU +#define ARMV8_LEVEL_2_SYNC_PAR_OR_ECC_ERROR 0x1EU +#define ARMV8_LEVEL_3_SYNC_PAR_OR_ECC_ERROR 0x1FU + +#define ARMV8_ALIGNMENT_FAULT 0x21U +#define ARMV8_TLB_CONFLICT_ABORT 0x30U + +#define ARMV8_ASYNC_SEEROR_INTERRUPT 0x11U + +#else /* #if defined (__aarch64__) */ + +#define DATA_ABORT 0x00U +#define INS_PREFETCH_ABORT 0x01U +#define ARMV7_FAULT_STATUS_MASK_BIT3_0 0x0FU +#define ARMV7_DFAR_VALUE_VALID 0x01U +#define ARMV7_FAULT_STATUS_BIT10_MASK 0x400U + +#define ARMV7_BACKGROUND_FAULT 0x00U +#define ARMV7_ALIGNMENT_FAULT 0x01U +#define ARMV7_DEBUG_EVENT 0x02U +#define ARMV7_ACCESS_FLAG_FAULT 0x03U +#define ARMV7_ICACHE_MAINTENANCE_FAULT 0x04U +#define ARMV7_TRANSLATION_FAULT 0x05U +#define ARMV7_SYNC_EXT_ABORT 0x08U +#define ARMV7_DOMAIN_FAULT 0x09U +#define ARMV7_SYNC_ABORT_TRANSTAB_WALK 0x0CU +#define ARMV7_PERMISSION_FAULT 0x0DU +#define ARMV7_TLB_CONFLICT_ABORT 0x10U +#define ARMV7_ASYNC_EXT_ABORT 0x16U +#define ARMV7_MEM_ACS_ASYNC_PAR_ERR 0x18U +#define ARMV7_MEM_ACS_SYNC_PAR_ERR 0x19U +#define ARMV7_SYNCPAR_ERR_TRANSTAB_WALK 0x1CU + +#define EXTRACT_BITS_10_AND_3_TO_0(Val) \ + ((Val & (ARMV7_FAULT_STATUS_BIT10_MASK)) >> 6) | \ + (Val & ARMV7_FAULT_STATUS_MASK_BIT3_0) + +#endif /* #if defined (__aarch64__) */ +#endif /* #ifdef DEBUG */ + +/* + * XIL_EXCEPTION_ID_INT is defined for all Xilinx processors. + */ +#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52) +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_FIQ_INT +#else +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_IRQ_INT +#endif + +/**************************** Type Definitions ******************************/ + +/** + * This typedef is the exception handler function. + */ +typedef void (*Xil_ExceptionHandler)(void *data); +typedef void (*Xil_InterruptHandler)(void *data); + +typedef struct { + Xil_ExceptionHandler Handler; + void *Data; +} XExc_VectorTableEntry; + +extern XExc_VectorTableEntry XExc_VectorTable[]; + +/** +*@endcond +*/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* @brief Enable Exceptions. +* +* @param Mask: Value for enabling the exceptions. +* +* @return None. +* +* @note If bit is 0, exception is enabled. +* C-Style signature: void Xil_ExceptionEnableMask(Mask) +* +******************************************************************************/ +#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52) +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always enable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionEnableMask(Mask) \ + (void)Mask; \ + mtcpsr(mfcpsr() & ~ ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionEnableMask(Mask) \ + mtcpsr(mfcpsr() & ~ ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionEnableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) & (~((Mask) & XIL_EXCEPTION_ALL))); \ + } +#endif +/****************************************************************************/ +/** +* @brief Enable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52) +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_FIQ) +#else +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ) +#endif + +/****************************************************************************/ +/** +* @brief Disable Exceptions. +* +* @param Mask: Value for disabling the exceptions. +* +* @return None. +* +* @note If bit is 1, exception is disabled. +* C-Style signature: Xil_ExceptionDisableMask(Mask) +* +******************************************************************************/ +#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52) +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always disable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionDisableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) | ((Mask) & XIL_EXCEPTION_ALL)); \ + } +#endif +/****************************************************************************/ +/** +* Disable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#define Xil_ExceptionDisable() \ + Xil_ExceptionDisableMask(XIL_EXCEPTION_IRQ) + +#if ( defined (PLATFORM_ZYNQMP) && defined (EL3) && (EL3==1) ) +/****************************************************************************/ +/** +* @brief Enable nested interrupts by clearing the I bit in DAIF.This +* macro is defined for Cortex-A53 64 bit mode BSP configured to run +* at EL3.. However,it is not defined for Versal Cortex-A72 BSP +* configured to run at EL3. Reason is, Cortex-A72 is coupled +* with GIC-500(GICv3 specifications) and it triggers only FIQ at EL3. +* +* @return None. +* +* @note This macro is supposed to be used from interrupt handlers. In the +* interrupt handler the interrupts are disabled by default (I bit +* is set as 1). To allow nesting of interrupts, this macro should be +* used. It clears the I bit. Once that bit is cleared and provided the +* preemption of interrupt conditions are met in the GIC, nesting of +* interrupts will start happening. +* Caution: This macro must be used with caution. Before calling this +* macro, the user must ensure that the source of the current IRQ +* is appropriately cleared. Otherwise, as soon as we clear the I +* bit, there can be an infinite loop of interrupts with an +* eventual crash (all the stack space getting consumed). +******************************************************************************/ +#define Xil_EnableNestedInterrupts() \ + __asm__ __volatile__ ("mrs X1, ELR_EL3"); \ + __asm__ __volatile__ ("mrs X2, SPSR_EL3"); \ + __asm__ __volatile__ ("stp X1,X2, [sp,#-0x10]!"); \ + __asm__ __volatile__ ("mrs X1, DAIF"); \ + __asm__ __volatile__ ("bic X1,X1,#(0x1<<7)"); \ + __asm__ __volatile__ ("msr DAIF, X1"); \ + +/****************************************************************************/ +/** +* @brief Disable the nested interrupts by setting the I bit in DAIF. This +* macro is defined for Cortex-A53 64 bit mode BSP configured to run +* at EL3. +* +* @return None. +* +* @note This macro is meant to be called in the interrupt service routines. +* This macro cannot be used independently. It can only be used when +* nesting of interrupts have been enabled by using the macro +* Xil_EnableNestedInterrupts(). In a typical flow, the user first +* calls the Xil_EnableNestedInterrupts in the ISR at the appropriate +* point. The user then must call this macro before exiting the interrupt +* service routine. This macro puts the ARM back in IRQ mode and +* hence sets back the I bit. +******************************************************************************/ +#define Xil_DisableNestedInterrupts() \ + __asm__ __volatile__ ("ldp X1,X2, [sp,#0x10]!"); \ + __asm__ __volatile__ ("msr ELR_EL3, X1"); \ + __asm__ __volatile__ ("msr SPSR_EL3, X2"); \ + __asm__ __volatile__ ("mrs X1, DAIF"); \ + __asm__ __volatile__ ("orr X1, X1, #(0x1<<7)"); \ + __asm__ __volatile__ ("msr DAIF, X1"); \ + +#elif (defined (EL1_NONSECURE) && (EL1_NONSECURE==1)) +/****************************************************************************/ +/** +* @brief Enable nested interrupts by clearing the I bit in DAIF.This +* macro is defined for Cortex-A53 64 bit mode and Cortex-A72 64 bit +* BSP configured to run at EL1 NON SECURE +* +* @return None. +* +* @note This macro is supposed to be used from interrupt handlers. In the +* interrupt handler the interrupts are disabled by default (I bit +* is set as 1). To allow nesting of interrupts, this macro should be +* used. It clears the I bit. Once that bit is cleared and provided the +* preemption of interrupt conditions are met in the GIC, nesting of +* interrupts will start happening. +* Caution: This macro must be used with caution. Before calling this +* macro, the user must ensure that the source of the current IRQ +* is appropriately cleared. Otherwise, as soon as we clear the I +* bit, there can be an infinite loop of interrupts with an +* eventual crash (all the stack space getting consumed). +******************************************************************************/ +#define Xil_EnableNestedInterrupts() \ + __asm__ __volatile__ ("mrs X1, ELR_EL1"); \ + __asm__ __volatile__ ("mrs X2, SPSR_EL1"); \ + __asm__ __volatile__ ("stp X1,X2, [sp,#-0x10]!"); \ + __asm__ __volatile__ ("mrs X1, DAIF"); \ + __asm__ __volatile__ ("bic X1,X1,#(0x1<<7)"); \ + __asm__ __volatile__ ("msr DAIF, X1"); \ + +/****************************************************************************/ +/** +* @brief Disable the nested interrupts by setting the I bit in DAIF. This +* macro is defined for Cortex-A53 64 bit mode and Cortex-A72 64 bit +* BSP configured to run at EL1 NON SECURE +* +* @return None. +* +* @note This macro is meant to be called in the interrupt service routines. +* This macro cannot be used independently. It can only be used when +* nesting of interrupts have been enabled by using the macro +* Xil_EnableNestedInterrupts(). In a typical flow, the user first +* calls the Xil_EnableNestedInterrupts in the ISR at the appropriate +* point. The user then must call this macro before exiting the interrupt +* service routine. This macro puts the ARM back in IRQ mode and +* hence sets back the I bit. +******************************************************************************/ +#define Xil_DisableNestedInterrupts() \ + __asm__ __volatile__ ("ldp X1,X2, [sp,#0x10]!"); \ + __asm__ __volatile__ ("msr ELR_EL1, X1"); \ + __asm__ __volatile__ ("msr SPSR_EL1, X2"); \ + __asm__ __volatile__ ("mrs X1, DAIF"); \ + __asm__ __volatile__ ("orr X1, X1, #(0x1<<7)"); \ + __asm__ __volatile__ ("msr DAIF, X1"); \ + +#elif (!defined (__aarch64__) && !defined (ARMA53_32)) +/****************************************************************************/ +/** +* @brief Enable nested interrupts by clearing the I and F bits in CPSR. This +* API is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is supposed to be used from interrupt handlers. In the +* interrupt handler the interrupts are disabled by default (I and F +* are 1). To allow nesting of interrupts, this macro should be +* used. It clears the I and F bits by changing the ARM mode to +* system mode. Once these bits are cleared and provided the +* preemption of interrupt conditions are met in the GIC, nesting of +* interrupts will start happening. +* Caution: This macro must be used with caution. Before calling this +* macro, the user must ensure that the source of the current IRQ +* is appropriately cleared. Otherwise, as soon as we clear the I and +* F bits, there can be an infinite loop of interrupts with an +* eventual crash (all the stack space getting consumed). +******************************************************************************/ +#define Xil_EnableNestedInterrupts() \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("mrs lr, spsr"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x1F"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); +/****************************************************************************/ +/** +* @brief Disable the nested interrupts by setting the I and F bits. This API +* is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is meant to be called in the interrupt service routines. +* This macro cannot be used independently. It can only be used when +* nesting of interrupts have been enabled by using the macro +* Xil_EnableNestedInterrupts(). In a typical flow, the user first +* calls the Xil_EnableNestedInterrupts in the ISR at the appropriate +* point. The user then must call this macro before exiting the interrupt +* service routine. This macro puts the ARM back in IRQ/FIQ mode and +* hence sets back the I and F bits. +******************************************************************************/ +#define Xil_DisableNestedInterrupts() \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x92"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr spsr_cxsf, lr"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + +#endif +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +extern void Xil_ExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler Handler, + void *Data); + +extern void Xil_ExceptionRemoveHandler(u32 Exception_id); +extern void Xil_GetExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler *Handler, void **Data); + +extern void Xil_ExceptionInit(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_EXCEPTION_H */ +/** +* @} End of "addtogroup arm_exception_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_hal.h b/bsp_z7/ps7_cortexa9_0/include/xil_hal.h new file mode 100644 index 0000000..4b289a7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_hal.h @@ -0,0 +1,43 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_hal.h +* +* Contains all the HAL header files. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_HAL_H +#define XIL_HAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_cache.h" +#include "xil_io.h" +#include "xil_assert.h" +#include "xil_exception.h" +#include "xil_types.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_io.h b/bsp_z7/ps7_cortexa9_0/include/xil_io.h new file mode 100644 index 0000000..853ef6b --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_io.h @@ -0,0 +1,412 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_io.h +* +* @addtogroup common_io_interfacing_apis Register IO interfacing APIs +* +* The xil_io.h file contains the interface for the general I/O component, which +* encapsulates the Input/Output functions for the processors that do not +* require any special I/O handling. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp  	 05/29/14 First release
+* 6.00  mus      08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
+*                         ARM processors
+* 7.20  har      01/03/20 Added Xil_SecureOut32 for avoiding blindwrite for
+*                         CR-1049218
+* 7.30  kpt      09/21/20 Moved Xil_EndianSwap16 and Xil_EndianSwap32 to
+*                         xil_io.h and made them as static inline
+*       am       10/13/20 Changed the return type of Xil_SecureOut32 function
+*                         from u32 to int
+* 7.50  dp       02/12/21 Fix compilation error in Xil_EndianSwap32() that occur
+*                         when -Werror=conversion compiler flag is enabled
+* 7.5   mus      05/17/21 Update the functions with comments. It fixes CR#1067739.
+*
+* 
+******************************************************************************/ + +#ifndef XIL_IO_H /* prevent circular inclusions */ +#define XIL_IO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_printf.h" +#include "xstatus.h" + +#if defined (__MICROBLAZE__) +#include "mb_interface.h" +#else +#include "xpseudo_asm.h" +#endif + +/************************** Function Prototypes ******************************/ +#ifdef ENABLE_SAFETY +extern u32 XStl_RegUpdate(u32 RegAddr, u32 RegVal); +#endif + +/***************** Macros (Inline Functions) Definitions *********************/ +#if defined __GNUC__ +#if defined (__MICROBLAZE__) +# define INST_SYNC mbar(0) +# define DATA_SYNC mbar(1) +# else +# define SYNCHRONIZE_IO dmb() +# define INST_SYNC isb() +# define DATA_SYNC dsb() +# endif +#else +# define SYNCHRONIZE_IO +# define INST_SYNC +# define DATA_SYNC +# define INST_SYNC +# define DATA_SYNC +#endif + +#if defined (__GNUC__) || defined (__ICCARM__) || defined (__MICROBLAZE__) +#define INLINE inline +#else +#define INLINE __inline +#endif + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading +* from the specified address and returning the 8 bit Value read from +* that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 8 bit Value read from the specified input address. + +* +******************************************************************************/ +static INLINE u8 Xil_In8(UINTPTR Addr) +{ + return *(volatile u8 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading from +* the specified address and returning the 16 bit Value read from that +* address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 16 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u16 Xil_In16(UINTPTR Addr) +{ + return *(volatile u16 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by +* reading from the specified address and returning the 32 bit Value +* read from that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 32 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u32 Xil_In32(UINTPTR Addr) +{ + return *(volatile u32 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading the +* 64 bit Value read from that address. +* +* +* @param Addr: contains the address to perform the input operation +* +* @return The 64 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u64 Xil_In64(UINTPTR Addr) +{ + return *(volatile u64 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for an memory location by +* writing the 8 bit Value to the the specified address. +* +* @param Addr: contains the address to perform the output operation +* @param Value: contains the 8 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out8(UINTPTR Addr, u8 Value) +{ + /* write 8 bit value to specified address */ + volatile u8 *LocalAddr = (volatile u8 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 16 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out16(UINTPTR Addr, u16 Value) +{ + /* write 16 bit value to specified address */ + volatile u16 *LocalAddr = (volatile u16 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 32 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the 32 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out32(UINTPTR Addr, u32 Value) +{ + /* write 32 bit value to specified address */ +#ifndef ENABLE_SAFETY + volatile u32 *LocalAddr = (volatile u32 *)Addr; + *LocalAddr = Value; +#else + XStl_RegUpdate(Addr, Value); +#endif +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 64 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains 64 bit Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out64(UINTPTR Addr, u64 Value) +{ + /* write 64 bit value to specified address */ + volatile u64 *LocalAddr = (volatile u64 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** + * + * @brief Performs an output operation for a memory location by writing the + * 32 bit Value to the the specified address and then reading it + * back to verify the value written in the register. + * + * @param Addr contains the address to perform the output operation + * @param Value contains 32 bit Value to be written at the specified address + * + * @return Returns Status + * - XST_SUCCESS on success + * - XST_FAILURE on failure + * + *****************************************************************************/ +static INLINE int Xil_SecureOut32(UINTPTR Addr, u32 Value) +{ + int Status = XST_FAILURE; + u32 ReadReg; + u32 ReadRegTemp; + + /* writing 32 bit value to specified address */ + Xil_Out32(Addr, Value); + + /* verify value written to specified address with multiple reads */ + ReadReg = Xil_In32(Addr); + ReadRegTemp = Xil_In32(Addr); + + if( (ReadReg == Value) && (ReadRegTemp == Value) ) { + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief Perform a 16-bit endian conversion. +* +* @param Data: 16 bit value to be converted +* +* @return 16 bit Data with converted endianness +* +******************************************************************************/ +static INLINE __attribute__((always_inline)) u16 Xil_EndianSwap16(u16 Data) +{ + return (u16) (((Data & 0xFF00U) >> 8U) | ((Data & 0x00FFU) << 8U)); +} + +/*****************************************************************************/ +/** +* +* @brief Perform a 32-bit endian conversion. +* +* @param Data: 32 bit value to be converted +* +* @return 32 bit data with converted endianness +* +******************************************************************************/ +static INLINE __attribute__((always_inline)) u32 Xil_EndianSwap32(u32 Data) +{ + u16 LoWord; + u16 HiWord; + + /* get each of the half words from the 32 bit word */ + + LoWord = (u16) (Data & 0x0000FFFFU); + HiWord = (u16) ((Data & 0xFFFF0000U) >> 16U); + + /* byte swap each of the 16 bit half words */ + + LoWord = (u16)(((LoWord & 0xFF00U) >> 8U) | ((LoWord & 0x00FFU) << 8U)); + HiWord = (u16)(((HiWord & 0xFF00U) >> 8U) | ((HiWord & 0x00FFU) << 8U)); + + /* swap the half words before returning the value */ + + return ((((u32)LoWord) << (u32)16U) | (u32)HiWord); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +# else +# define Xil_In16BE Xil_In16 +# define Xil_In32BE Xil_In32 +# define Xil_Out16BE Xil_Out16 +# define Xil_Out32BE Xil_Out32 +# define Xil_Htons(Data) (Data) +# define Xil_Htonl(Data) (Data) +# define Xil_Ntohs(Data) (Data) +# define Xil_Ntohl(Data) (Data) +#endif +#else +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +#endif + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#else +static INLINE u16 Xil_In16LE(UINTPTR Addr) +#endif +#else +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#endif +{ + u16 value = Xil_In16(Addr); + return Xil_EndianSwap16(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#else +static INLINE u32 Xil_In32LE(UINTPTR Addr) +#endif +#else +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#endif +{ + u32 value = Xil_In32(Addr); + return Xil_EndianSwap32(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#else +static INLINE void Xil_Out16LE(UINTPTR Addr, u16 Value) +#endif +#else +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#endif +{ + Value = Xil_EndianSwap16(Value); + Xil_Out16(Addr, Value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#else +static INLINE void Xil_Out32LE(UINTPTR Addr, u32 Value) +#endif +#else +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#endif +{ + Value = Xil_EndianSwap32(Value); + Xil_Out32(Addr, Value); +} + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_io_interfacing_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_macroback.h b/bsp_z7/ps7_cortexa9_0/include/xil_macroback.h new file mode 100644 index 0000000..7a0135a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_macroback.h @@ -0,0 +1,1113 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +/*********************************************************************/ +/** + * @file xil_macroback.h + * + * This header file is meant to bring back the removed _m macros. + * This header file must be included last. + * The following macros are not defined here due to the driver change: + * XGpio_mSetDataDirection + * XGpio_mGetDataReg + * XGpio_mSetDataReg + * XIIC_RESET + * XIIC_CLEAR_STATS + * XSpi_mReset + * XSysAce_mSetCfgAddr + * XSysAce_mIsCfgDone + * XTft_mSetPixel + * XTft_mGetPixel + * XWdtTb_mEnableWdt + * XWdtTb_mDisbleWdt + * XWdtTb_mRestartWdt + * XWdtTb_mGetTimebaseReg + * XWdtTb_mHasReset + * + * Please refer the corresponding driver document for replacement. + * + *********************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_MACROBACK_H +#define XIL_MACROBACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************/ +/** + * Macros for Driver XCan + * + *********************************************************************/ +#ifndef XCan_mReadReg +#define XCan_mReadReg XCan_ReadReg +#endif + +#ifndef XCan_mWriteReg +#define XCan_mWriteReg XCan_WriteReg +#endif + +#ifndef XCan_mIsTxDone +#define XCan_mIsTxDone XCan_IsTxDone +#endif + +#ifndef XCan_mIsTxFifoFull +#define XCan_mIsTxFifoFull XCan_IsTxFifoFull +#endif + +#ifndef XCan_mIsHighPriorityBufFull +#define XCan_mIsHighPriorityBufFull XCan_IsHighPriorityBufFull +#endif + +#ifndef XCan_mIsRxEmpty +#define XCan_mIsRxEmpty XCan_IsRxEmpty +#endif + +#ifndef XCan_mIsAcceptFilterBusy +#define XCan_mIsAcceptFilterBusy XCan_IsAcceptFilterBusy +#endif + +#ifndef XCan_mCreateIdValue +#define XCan_mCreateIdValue XCan_CreateIdValue +#endif + +#ifndef XCan_mCreateDlcValue +#define XCan_mCreateDlcValue XCan_CreateDlcValue +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDmaCentral + * + *********************************************************************/ +#ifndef XDmaCentral_mWriteReg +#define XDmaCentral_mWriteReg XDmaCentral_WriteReg +#endif + +#ifndef XDmaCentral_mReadReg +#define XDmaCentral_mReadReg XDmaCentral_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsAdc + * + *********************************************************************/ +#ifndef XDsAdc_mWriteReg +#define XDsAdc_mWriteReg XDsAdc_WriteReg +#endif + +#ifndef XDsAdc_mReadReg +#define XDsAdc_mReadReg XDsAdc_ReadReg +#endif + +#ifndef XDsAdc_mIsEmpty +#define XDsAdc_mIsEmpty XDsAdc_IsEmpty +#endif + +#ifndef XDsAdc_mSetFstmReg +#define XDsAdc_mSetFstmReg XDsAdc_SetFstmReg +#endif + +#ifndef XDsAdc_mGetFstmReg +#define XDsAdc_mGetFstmReg XDsAdc_GetFstmReg +#endif + +#ifndef XDsAdc_mEnableConversion +#define XDsAdc_mEnableConversion XDsAdc_EnableConversion +#endif + +#ifndef XDsAdc_mDisableConversion +#define XDsAdc_mDisableConversion XDsAdc_DisableConversion +#endif + +#ifndef XDsAdc_mGetFifoOccyReg +#define XDsAdc_mGetFifoOccyReg XDsAdc_GetFifoOccyReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsDac + * + *********************************************************************/ +#ifndef XDsDac_mWriteReg +#define XDsDac_mWriteReg XDsDac_WriteReg +#endif + +#ifndef XDsDac_mReadReg +#define XDsDac_mReadReg XDsDac_ReadReg +#endif + +#ifndef XDsDac_mIsEmpty +#define XDsDac_mIsEmpty XDsDac_IsEmpty +#endif + +#ifndef XDsDac_mFifoIsFull +#define XDsDac_mFifoIsFull XDsDac_FifoIsFull +#endif + +#ifndef XDsDac_mGetVacancy +#define XDsDac_mGetVacancy XDsDac_GetVacancy +#endif + +/*********************************************************************/ +/** + * Macros for Driver XEmacLite + * + *********************************************************************/ +#ifndef XEmacLite_mReadReg +#define XEmacLite_mReadReg XEmacLite_ReadReg +#endif + +#ifndef XEmacLite_mWriteReg +#define XEmacLite_mWriteReg XEmacLite_WriteReg +#endif + +#ifndef XEmacLite_mGetTxStatus +#define XEmacLite_mGetTxStatus XEmacLite_GetTxStatus +#endif + +#ifndef XEmacLite_mSetTxStatus +#define XEmacLite_mSetTxStatus XEmacLite_SetTxStatus +#endif + +#ifndef XEmacLite_mGetRxStatus +#define XEmacLite_mGetRxStatus XEmacLite_GetRxStatus +#endif + +#ifndef XEmacLite_mSetRxStatus +#define XEmacLite_mSetRxStatus XEmacLite_SetRxStatus +#endif + +#ifndef XEmacLite_mIsTxDone +#define XEmacLite_mIsTxDone XEmacLite_IsTxDone +#endif + +#ifndef XEmacLite_mIsRxEmpty +#define XEmacLite_mIsRxEmpty XEmacLite_IsRxEmpty +#endif + +#ifndef XEmacLite_mNextTransmitAddr +#define XEmacLite_mNextTransmitAddr XEmacLite_NextTransmitAddr +#endif + +#ifndef XEmacLite_mNextReceiveAddr +#define XEmacLite_mNextReceiveAddr XEmacLite_NextReceiveAddr +#endif + +#ifndef XEmacLite_mIsMdioConfigured +#define XEmacLite_mIsMdioConfigured XEmacLite_IsMdioConfigured +#endif + +#ifndef XEmacLite_mIsLoopbackConfigured +#define XEmacLite_mIsLoopbackConfigured XEmacLite_IsLoopbackConfigured +#endif + +#ifndef XEmacLite_mGetReceiveDataLength +#define XEmacLite_mGetReceiveDataLength XEmacLite_GetReceiveDataLength +#endif + +#ifndef XEmacLite_mGetTxActive +#define XEmacLite_mGetTxActive XEmacLite_GetTxActive +#endif + +#ifndef XEmacLite_mSetTxActive +#define XEmacLite_mSetTxActive XEmacLite_SetTxActive +#endif + +/*********************************************************************/ +/** + * Macros for Driver XGpio + * + *********************************************************************/ +#ifndef XGpio_mWriteReg +#define XGpio_mWriteReg XGpio_WriteReg +#endif + +#ifndef XGpio_mReadReg +#define XGpio_mReadReg XGpio_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XHwIcap + * + *********************************************************************/ +#ifndef XHwIcap_mFifoWrite +#define XHwIcap_mFifoWrite XHwIcap_FifoWrite +#endif + +#ifndef XHwIcap_mFifoRead +#define XHwIcap_mFifoRead XHwIcap_FifoRead +#endif + +#ifndef XHwIcap_mSetSizeReg +#define XHwIcap_mSetSizeReg XHwIcap_SetSizeReg +#endif + +#ifndef XHwIcap_mGetControlReg +#define XHwIcap_mGetControlReg XHwIcap_GetControlReg +#endif + +#ifndef XHwIcap_mStartConfig +#define XHwIcap_mStartConfig XHwIcap_StartConfig +#endif + +#ifndef XHwIcap_mStartReadBack +#define XHwIcap_mStartReadBack XHwIcap_StartReadBack +#endif + +#ifndef XHwIcap_mGetStatusReg +#define XHwIcap_mGetStatusReg XHwIcap_GetStatusReg +#endif + +#ifndef XHwIcap_mIsTransferDone +#define XHwIcap_mIsTransferDone XHwIcap_IsTransferDone +#endif + +#ifndef XHwIcap_mIsDeviceBusy +#define XHwIcap_mIsDeviceBusy XHwIcap_IsDeviceBusy +#endif + +#ifndef XHwIcap_mIntrGlobalEnable +#define XHwIcap_mIntrGlobalEnable XHwIcap_IntrGlobalEnable +#endif + +#ifndef XHwIcap_mIntrGlobalDisable +#define XHwIcap_mIntrGlobalDisable XHwIcap_IntrGlobalDisable +#endif + +#ifndef XHwIcap_mIntrGetStatus +#define XHwIcap_mIntrGetStatus XHwIcap_IntrGetStatus +#endif + +#ifndef XHwIcap_mIntrDisable +#define XHwIcap_mIntrDisable XHwIcap_IntrDisable +#endif + +#ifndef XHwIcap_mIntrEnable +#define XHwIcap_mIntrEnable XHwIcap_IntrEnable +#endif + +#ifndef XHwIcap_mIntrGetEnabled +#define XHwIcap_mIntrGetEnabled XHwIcap_IntrGetEnabled +#endif + +#ifndef XHwIcap_mIntrClear +#define XHwIcap_mIntrClear XHwIcap_IntrClear +#endif + +#ifndef XHwIcap_mGetWrFifoVacancy +#define XHwIcap_mGetWrFifoVacancy XHwIcap_GetWrFifoVacancy +#endif + +#ifndef XHwIcap_mGetRdFifoOccupancy +#define XHwIcap_mGetRdFifoOccupancy XHwIcap_GetRdFifoOccupancy +#endif + +#ifndef XHwIcap_mSliceX2Col +#define XHwIcap_mSliceX2Col XHwIcap_SliceX2Col +#endif + +#ifndef XHwIcap_mSliceY2Row +#define XHwIcap_mSliceY2Row XHwIcap_SliceY2Row +#endif + +#ifndef XHwIcap_mSliceXY2Slice +#define XHwIcap_mSliceXY2Slice XHwIcap_SliceXY2Slice +#endif + +#ifndef XHwIcap_mReadReg +#define XHwIcap_mReadReg XHwIcap_ReadReg +#endif + +#ifndef XHwIcap_mWriteReg +#define XHwIcap_mWriteReg XHwIcap_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIic + * + *********************************************************************/ +#ifndef XIic_mReadReg +#define XIic_mReadReg XIic_ReadReg +#endif + +#ifndef XIic_mWriteReg +#define XIic_mWriteReg XIic_WriteReg +#endif + +#ifndef XIic_mEnterCriticalRegion +#define XIic_mEnterCriticalRegion XIic_IntrGlobalDisable +#endif + +#ifndef XIic_mExitCriticalRegion +#define XIic_mExitCriticalRegion XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_GINTR_DISABLE +#define XIIC_GINTR_DISABLE XIic_IntrGlobalDisable +#endif + +#ifndef XIIC_GINTR_ENABLE +#define XIIC_GINTR_ENABLE XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_IS_GINTR_ENABLED +#define XIIC_IS_GINTR_ENABLED XIic_IsIntrGlobalEnabled +#endif + +#ifndef XIIC_WRITE_IISR +#define XIIC_WRITE_IISR XIic_WriteIisr +#endif + +#ifndef XIIC_READ_IISR +#define XIIC_READ_IISR XIic_ReadIisr +#endif + +#ifndef XIIC_WRITE_IIER +#define XIIC_WRITE_IIER XIic_WriteIier +#endif + +#ifndef XIic_mClearIisr +#define XIic_mClearIisr XIic_ClearIisr +#endif + +#ifndef XIic_mSend7BitAddress +#define XIic_mSend7BitAddress XIic_Send7BitAddress +#endif + +#ifndef XIic_mDynSend7BitAddress +#define XIic_mDynSend7BitAddress XIic_DynSend7BitAddress +#endif + +#ifndef XIic_mDynSendStartStopAddress +#define XIic_mDynSendStartStopAddress XIic_DynSendStartStopAddress +#endif + +#ifndef XIic_mDynSendStop +#define XIic_mDynSendStop XIic_DynSendStop +#endif + +#ifndef XIic_mSend10BitAddrByte1 +#define XIic_mSend10BitAddrByte1 XIic_Send10BitAddrByte1 +#endif + +#ifndef XIic_mSend10BitAddrByte2 +#define XIic_mSend10BitAddrByte2 XIic_Send10BitAddrByte2 +#endif + +#ifndef XIic_mSend7BitAddr +#define XIic_mSend7BitAddr XIic_Send7BitAddr +#endif + +#ifndef XIic_mDisableIntr +#define XIic_mDisableIntr XIic_DisableIntr +#endif + +#ifndef XIic_mEnableIntr +#define XIic_mEnableIntr XIic_EnableIntr +#endif + +#ifndef XIic_mClearIntr +#define XIic_mClearIntr XIic_ClearIntr +#endif + +#ifndef XIic_mClearEnableIntr +#define XIic_mClearEnableIntr XIic_ClearEnableIntr +#endif + +#ifndef XIic_mFlushRxFifo +#define XIic_mFlushRxFifo XIic_FlushRxFifo +#endif + +#ifndef XIic_mFlushTxFifo +#define XIic_mFlushTxFifo XIic_FlushTxFifo +#endif + +#ifndef XIic_mReadRecvByte +#define XIic_mReadRecvByte XIic_ReadRecvByte +#endif + +#ifndef XIic_mWriteSendByte +#define XIic_mWriteSendByte XIic_WriteSendByte +#endif + +#ifndef XIic_mSetControlRegister +#define XIic_mSetControlRegister XIic_SetControlRegister +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIntc + * + *********************************************************************/ +#ifndef XIntc_mMasterEnable +#define XIntc_mMasterEnable XIntc_MasterEnable +#endif + +#ifndef XIntc_mMasterDisable +#define XIntc_mMasterDisable XIntc_MasterDisable +#endif + +#ifndef XIntc_mEnableIntr +#define XIntc_mEnableIntr XIntc_EnableIntr +#endif + +#ifndef XIntc_mDisableIntr +#define XIntc_mDisableIntr XIntc_DisableIntr +#endif + +#ifndef XIntc_mAckIntr +#define XIntc_mAckIntr XIntc_AckIntr +#endif + +#ifndef XIntc_mGetIntrStatus +#define XIntc_mGetIntrStatus XIntc_GetIntrStatus +#endif + +/*********************************************************************/ +/** + * Macros for Driver XLlDma + * + *********************************************************************/ +#ifndef XLlDma_mBdRead +#define XLlDma_mBdRead XLlDma_BdRead +#endif + +#ifndef XLlDma_mBdWrite +#define XLlDma_mBdWrite XLlDma_BdWrite +#endif + +#ifndef XLlDma_mWriteReg +#define XLlDma_mWriteReg XLlDma_WriteReg +#endif + +#ifndef XLlDma_mReadReg +#define XLlDma_mReadReg XLlDma_ReadReg +#endif + +#ifndef XLlDma_mBdClear +#define XLlDma_mBdClear XLlDma_BdClear +#endif + +#ifndef XLlDma_mBdSetStsCtrl +#define XLlDma_mBdSetStsCtrl XLlDma_BdSetStsCtrl +#endif + +#ifndef XLlDma_mBdGetStsCtrl +#define XLlDma_mBdGetStsCtrl XLlDma_BdGetStsCtrl +#endif + +#ifndef XLlDma_mBdSetLength +#define XLlDma_mBdSetLength XLlDma_BdSetLength +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mBdSetId +#define XLlDma_mBdSetId XLlDma_BdSetId +#endif + +#ifndef XLlDma_mBdGetId +#define XLlDma_mBdGetId XLlDma_BdGetId +#endif + +#ifndef XLlDma_mBdSetBufAddr +#define XLlDma_mBdSetBufAddr XLlDma_BdSetBufAddr +#endif + +#ifndef XLlDma_mBdGetBufAddr +#define XLlDma_mBdGetBufAddr XLlDma_BdGetBufAddr +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mGetTxRing +#define XLlDma_mGetTxRing XLlDma_GetTxRing +#endif + +#ifndef XLlDma_mGetRxRing +#define XLlDma_mGetRxRing XLlDma_GetRxRing +#endif + +#ifndef XLlDma_mGetCr +#define XLlDma_mGetCr XLlDma_GetCr +#endif + +#ifndef XLlDma_mSetCr +#define XLlDma_mSetCr XLlDma_SetCr +#endif + +#ifndef XLlDma_mBdRingCntCalc +#define XLlDma_mBdRingCntCalc XLlDma_BdRingCntCalc +#endif + +#ifndef XLlDma_mBdRingMemCalc +#define XLlDma_mBdRingMemCalc XLlDma_BdRingMemCalc +#endif + +#ifndef XLlDma_mBdRingGetCnt +#define XLlDma_mBdRingGetCnt XLlDma_BdRingGetCnt +#endif + +#ifndef XLlDma_mBdRingGetFreeCnt +#define XLlDma_mBdRingGetFreeCnt XLlDma_BdRingGetFreeCnt +#endif + +#ifndef XLlDma_mBdRingSnapShotCurrBd +#define XLlDma_mBdRingSnapShotCurrBd XLlDma_BdRingSnapShotCurrBd +#endif + +#ifndef XLlDma_mBdRingNext +#define XLlDma_mBdRingNext XLlDma_BdRingNext +#endif + +#ifndef XLlDma_mBdRingPrev +#define XLlDma_mBdRingPrev XLlDma_BdRingPrev +#endif + +#ifndef XLlDma_mBdRingGetSr +#define XLlDma_mBdRingGetSr XLlDma_BdRingGetSr +#endif + +#ifndef XLlDma_mBdRingSetSr +#define XLlDma_mBdRingSetSr XLlDma_BdRingSetSr +#endif + +#ifndef XLlDma_mBdRingGetCr +#define XLlDma_mBdRingGetCr XLlDma_BdRingGetCr +#endif + +#ifndef XLlDma_mBdRingSetCr +#define XLlDma_mBdRingSetCr XLlDma_BdRingSetCr +#endif + +#ifndef XLlDma_mBdRingBusy +#define XLlDma_mBdRingBusy XLlDma_BdRingBusy +#endif + +#ifndef XLlDma_mBdRingIntEnable +#define XLlDma_mBdRingIntEnable XLlDma_BdRingIntEnable +#endif + +#ifndef XLlDma_mBdRingIntDisable +#define XLlDma_mBdRingIntDisable XLlDma_BdRingIntDisable +#endif + +#ifndef XLlDma_mBdRingIntGetEnabled +#define XLlDma_mBdRingIntGetEnabled XLlDma_BdRingIntGetEnabled +#endif + +#ifndef XLlDma_mBdRingGetIrq +#define XLlDma_mBdRingGetIrq XLlDma_BdRingGetIrq +#endif + +#ifndef XLlDma_mBdRingAckIrq +#define XLlDma_mBdRingAckIrq XLlDma_BdRingAckIrq +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMbox + * + *********************************************************************/ +#ifndef XMbox_mWriteReg +#define XMbox_mWriteReg XMbox_WriteReg +#endif + +#ifndef XMbox_mReadReg +#define XMbox_mReadReg XMbox_ReadReg +#endif + +#ifndef XMbox_mWriteMBox +#define XMbox_mWriteMBox XMbox_WriteMBox +#endif + +#ifndef XMbox_mReadMBox +#define XMbox_mReadMBox XMbox_ReadMBox +#endif + +#ifndef XMbox_mFSLReadMBox +#define XMbox_mFSLReadMBox XMbox_FSLReadMBox +#endif + +#ifndef XMbox_mFSLWriteMBox +#define XMbox_mFSLWriteMBox XMbox_FSLWriteMBox +#endif + +#ifndef XMbox_mFSLIsEmpty +#define XMbox_mFSLIsEmpty XMbox_FSLIsEmpty +#endif + +#ifndef XMbox_mFSLIsFull +#define XMbox_mFSLIsFull XMbox_FSLIsFull +#endif + +#ifndef XMbox_mIsEmpty +#define XMbox_mIsEmpty XMbox_IsEmptyHw +#endif + +#ifndef XMbox_mIsFull +#define XMbox_mIsFull XMbox_IsFullHw +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMpmc + * + *********************************************************************/ +#ifndef XMpmc_mReadReg +#define XMpmc_mReadReg XMpmc_ReadReg +#endif + +#ifndef XMpmc_mWriteReg +#define XMpmc_mWriteReg XMpmc_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMutex + * + *********************************************************************/ +#ifndef XMutex_mWriteReg +#define XMutex_mWriteReg XMutex_WriteReg +#endif + +#ifndef XMutex_mReadReg +#define XMutex_mReadReg XMutex_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XPcie + * + *********************************************************************/ +#ifndef XPcie_mReadReg +#define XPcie_mReadReg XPcie_ReadReg +#endif + +#ifndef XPcie_mWriteReg +#define XPcie_mWriteReg XPcie_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSpi + * + *********************************************************************/ +#ifndef XSpi_mIntrGlobalEnable +#define XSpi_mIntrGlobalEnable XSpi_IntrGlobalEnable +#endif + +#ifndef XSpi_mIntrGlobalDisable +#define XSpi_mIntrGlobalDisable XSpi_IntrGlobalDisable +#endif + +#ifndef XSpi_mIsIntrGlobalEnabled +#define XSpi_mIsIntrGlobalEnabled XSpi_IsIntrGlobalEnabled +#endif + +#ifndef XSpi_mIntrGetStatus +#define XSpi_mIntrGetStatus XSpi_IntrGetStatus +#endif + +#ifndef XSpi_mIntrClear +#define XSpi_mIntrClear XSpi_IntrClear +#endif + +#ifndef XSpi_mIntrEnable +#define XSpi_mIntrEnable XSpi_IntrEnable +#endif + +#ifndef XSpi_mIntrDisable +#define XSpi_mIntrDisable XSpi_IntrDisable +#endif + +#ifndef XSpi_mIntrGetEnabled +#define XSpi_mIntrGetEnabled XSpi_IntrGetEnabled +#endif + +#ifndef XSpi_mSetControlReg +#define XSpi_mSetControlReg XSpi_SetControlReg +#endif + +#ifndef XSpi_mGetControlReg +#define XSpi_mGetControlReg XSpi_GetControlReg +#endif + +#ifndef XSpi_mGetStatusReg +#define XSpi_mGetStatusReg XSpi_GetStatusReg +#endif + +#ifndef XSpi_mSetSlaveSelectReg +#define XSpi_mSetSlaveSelectReg XSpi_SetSlaveSelectReg +#endif + +#ifndef XSpi_mGetSlaveSelectReg +#define XSpi_mGetSlaveSelectReg XSpi_GetSlaveSelectReg +#endif + +#ifndef XSpi_mEnable +#define XSpi_mEnable XSpi_Enable +#endif + +#ifndef XSpi_mDisable +#define XSpi_mDisable XSpi_Disable +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysAce + * + *********************************************************************/ +#ifndef XSysAce_mGetControlReg +#define XSysAce_mGetControlReg XSysAce_GetControlReg +#endif + +#ifndef XSysAce_mSetControlReg +#define XSysAce_mSetControlReg XSysAce_SetControlReg +#endif + +#ifndef XSysAce_mOrControlReg +#define XSysAce_mOrControlReg XSysAce_OrControlReg +#endif + +#ifndef XSysAce_mAndControlReg +#define XSysAce_mAndControlReg XSysAce_AndControlReg +#endif + +#ifndef XSysAce_mGetErrorReg +#define XSysAce_mGetErrorReg XSysAce_GetErrorReg +#endif + +#ifndef XSysAce_mGetStatusReg +#define XSysAce_mGetStatusReg XSysAce_GetStatusReg +#endif + +#ifndef XSysAce_mWaitForLock +#define XSysAce_mWaitForLock XSysAce_WaitForLock +#endif + +#ifndef XSysAce_mEnableIntr +#define XSysAce_mEnableIntr XSysAce_EnableIntr +#endif + +#ifndef XSysAce_mDisableIntr +#define XSysAce_mDisableIntr XSysAce_DisableIntr +#endif + +#ifndef XSysAce_mIsReadyForCmd +#define XSysAce_mIsReadyForCmd XSysAce_IsReadyForCmd +#endif + +#ifndef XSysAce_mIsMpuLocked +#define XSysAce_mIsMpuLocked XSysAce_IsMpuLocked +#endif + +#ifndef XSysAce_mIsIntrEnabled +#define XSysAce_mIsIntrEnabled XSysAce_IsIntrEnabled +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysMon + * + *********************************************************************/ +#ifndef XSysMon_mIsEventSamplingModeSet +#define XSysMon_mIsEventSamplingModeSet XSysMon_IsEventSamplingModeSet +#endif + +#ifndef XSysMon_mIsDrpBusy +#define XSysMon_mIsDrpBusy XSysMon_IsDrpBusy +#endif + +#ifndef XSysMon_mIsDrpLocked +#define XSysMon_mIsDrpLocked XSysMon_IsDrpLocked +#endif + +#ifndef XSysMon_mRawToTemperature +#define XSysMon_mRawToTemperature XSysMon_RawToTemperature +#endif + +#ifndef XSysMon_mRawToVoltage +#define XSysMon_mRawToVoltage XSysMon_RawToVoltage +#endif + +#ifndef XSysMon_mTemperatureToRaw +#define XSysMon_mTemperatureToRaw XSysMon_TemperatureToRaw +#endif + +#ifndef XSysMon_mVoltageToRaw +#define XSysMon_mVoltageToRaw XSysMon_VoltageToRaw +#endif + +#ifndef XSysMon_mReadReg +#define XSysMon_mReadReg XSysMon_ReadReg +#endif + +#ifndef XSysMon_mWriteReg +#define XSysMon_mWriteReg XSysMon_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XTmrCtr + * + *********************************************************************/ +#ifndef XTimerCtr_mReadReg +#define XTimerCtr_mReadReg XTimerCtr_ReadReg +#endif + +#ifndef XTmrCtr_mWriteReg +#define XTmrCtr_mWriteReg XTmrCtr_WriteReg +#endif + +#ifndef XTmrCtr_mSetControlStatusReg +#define XTmrCtr_mSetControlStatusReg XTmrCtr_SetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetControlStatusReg +#define XTmrCtr_mGetControlStatusReg XTmrCtr_GetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetTimerCounterReg +#define XTmrCtr_mGetTimerCounterReg XTmrCtr_GetTimerCounterReg +#endif + +#ifndef XTmrCtr_mSetLoadReg +#define XTmrCtr_mSetLoadReg XTmrCtr_SetLoadReg +#endif + +#ifndef XTmrCtr_mGetLoadReg +#define XTmrCtr_mGetLoadReg XTmrCtr_GetLoadReg +#endif + +#ifndef XTmrCtr_mEnable +#define XTmrCtr_mEnable XTmrCtr_Enable +#endif + +#ifndef XTmrCtr_mDisable +#define XTmrCtr_mDisable XTmrCtr_Disable +#endif + +#ifndef XTmrCtr_mEnableIntr +#define XTmrCtr_mEnableIntr XTmrCtr_EnableIntr +#endif + +#ifndef XTmrCtr_mDisableIntr +#define XTmrCtr_mDisableIntr XTmrCtr_DisableIntr +#endif + +#ifndef XTmrCtr_mLoadTimerCounterReg +#define XTmrCtr_mLoadTimerCounterReg XTmrCtr_LoadTimerCounterReg +#endif + +#ifndef XTmrCtr_mHasEventOccurred +#define XTmrCtr_mHasEventOccurred XTmrCtr_HasEventOccurred +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartLite + * + *********************************************************************/ +#ifndef XUartLite_mUpdateStats +#define XUartLite_mUpdateStats XUartLite_UpdateStats +#endif + +#ifndef XUartLite_mWriteReg +#define XUartLite_mWriteReg XUartLite_WriteReg +#endif + +#ifndef XUartLite_mReadReg +#define XUartLite_mReadReg XUartLite_ReadReg +#endif + +#ifndef XUartLite_mClearStats +#define XUartLite_mClearStats XUartLite_ClearStats +#endif + +#ifndef XUartLite_mSetControlReg +#define XUartLite_mSetControlReg XUartLite_SetControlReg +#endif + +#ifndef XUartLite_mGetStatusReg +#define XUartLite_mGetStatusReg XUartLite_GetStatusReg +#endif + +#ifndef XUartLite_mIsReceiveEmpty +#define XUartLite_mIsReceiveEmpty XUartLite_IsReceiveEmpty +#endif + +#ifndef XUartLite_mIsTransmitFull +#define XUartLite_mIsTransmitFull XUartLite_IsTransmitFull +#endif + +#ifndef XUartLite_mIsIntrEnabled +#define XUartLite_mIsIntrEnabled XUartLite_IsIntrEnabled +#endif + +#ifndef XUartLite_mEnableIntr +#define XUartLite_mEnableIntr XUartLite_EnableIntr +#endif + +#ifndef XUartLite_mDisableIntr +#define XUartLite_mDisableIntr XUartLite_DisableIntr +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartNs550 + * + *********************************************************************/ +#ifndef XUartNs550_mUpdateStats +#define XUartNs550_mUpdateStats XUartNs550_UpdateStats +#endif + +#ifndef XUartNs550_mReadReg +#define XUartNs550_mReadReg XUartNs550_ReadReg +#endif + +#ifndef XUartNs550_mWriteReg +#define XUartNs550_mWriteReg XUartNs550_WriteReg +#endif + +#ifndef XUartNs550_mClearStats +#define XUartNs550_mClearStats XUartNs550_ClearStats +#endif + +#ifndef XUartNs550_mGetLineStatusReg +#define XUartNs550_mGetLineStatusReg XUartNs550_GetLineStatusReg +#endif + +#ifndef XUartNs550_mGetLineControlReg +#define XUartNs550_mGetLineControlReg XUartNs550_GetLineControlReg +#endif + +#ifndef XUartNs550_mSetLineControlReg +#define XUartNs550_mSetLineControlReg XUartNs550_SetLineControlReg +#endif + +#ifndef XUartNs550_mEnableIntr +#define XUartNs550_mEnableIntr XUartNs550_EnableIntr +#endif + +#ifndef XUartNs550_mDisableIntr +#define XUartNs550_mDisableIntr XUartNs550_DisableIntr +#endif + +#ifndef XUartNs550_mIsReceiveData +#define XUartNs550_mIsReceiveData XUartNs550_IsReceiveData +#endif + +#ifndef XUartNs550_mIsTransmitEmpty +#define XUartNs550_mIsTransmitEmpty XUartNs550_IsTransmitEmpty +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUsb + * + *********************************************************************/ +#ifndef XUsb_mReadReg +#define XUsb_mReadReg XUsb_ReadReg +#endif + +#ifndef XUsb_mWriteReg +#define XUsb_mWriteReg XUsb_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XPmonPsv + * + *********************************************************************/ +#ifndef XpsvPmon_CfgInitialize +#define XpsvPmon_CfgInitialize XPmonPsv_CfgInitialize +#endif + +#ifndef XpsvPmon_LookupConfig +#define XpsvPmon_LookupConfig XPmonPsv_LookupConfig +#endif + +#ifndef XpsvPmon_WriteReg +#define XpsvPmon_WriteReg XPmonPsv_WriteReg +#endif + +#ifndef XpsvPmon_SetMetrics +#define XpsvPmon_SetMetrics XPmonPsv_SetMetrics +#endif + +#ifndef XpsvPmon_GetMetrics +#define XpsvPmon_GetMetrics XPmonPsv_GetMetrics +#endif + +#ifndef XpsvPmon_ResetCounter +#define XpsvPmon_ResetCounter XPmonPsv_ResetCounter +#endif + +#ifndef XpsvPmon_GetWriteCounter +#define XpsvPmon_GetWriteCounter XPmonPsv_GetWriteCounter +#endif + +#ifndef XpsvPmon_GetReadCounter +#define XpsvPmon_GetReadCounter XPmonPsv_GetReadCounter +#endif + +#ifndef XpsvPmon_EnableCounters +#define XpsvPmon_EnableCounters XPmonPsv_EnableCounters +#endif + +#ifndef XpsvPmon_StopCounter +#define XpsvPmon_StopCounter XPmonPsv_StopCounter +#endif + +#ifndef XpsvPmon_SetPort +#define XpsvPmon_SetPort XPmonPsv_SetPort +#endif + +#ifndef XpsvPmon_SetSrc +#define XpsvPmon_SetSrc XPmonPsv_SetSrc +#endif + +#ifndef XpsvPmon_Unlock +#define XpsvPmon_Unlock XPmonPsv_Unlock +#endif + +#ifndef XpsvPmon_Lock +#define XpsvPmon_Lock XPmonPsv_Lock +#endif + + +#ifndef XpsvPmon_RequestCounter +#define XpsvPmon_RequestCounter XPmonPsv_RequestCounter +#endif + +#ifndef XPmonpsv_Config +#define XPmonpsv_Config XPmonPsv_Config +#endif + +typedef XPmonPsv XpsvPmon; +#ifdef __cplusplus +} +#endif + +#endif +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_mem.c b/bsp_z7/ps7_cortexa9_0/include/xil_mem.c new file mode 100644 index 0000000..44e7d9a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_mem.c @@ -0,0 +1,70 @@ +/******************************************************************************/ +/** +* Copyright (c) 2015 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* @file xil_mem.c +* +* This file contains xil mem copy function to use in case of word aligned +* data copies. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+* 7.7	sk	 01/10/22 Update Xil_MemCpy functions variables typecast
+* 			  from int to s32 to fix misra_c_2012_directive_4_6
+* 			  violations.
+* 7.7	sk	 01/10/22 Include xil_mem.h header file to fix Xil_MemCpy
+* 			  prototype misra_c_2012_rule_8_4 violation.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_mem.h" + +/***************** Inline Functions Definitions ********************/ +/*****************************************************************************/ +/** +* @brief This function copies memory from once location to other. +* +* @param dst: pointer pointing to destination memory +* +* @param src: pointer pointing to source memory +* +* @param cnt: 32 bit length of bytes to be copied +* +*****************************************************************************/ +void Xil_MemCpy(void* dst, const void* src, u32 cnt) +{ + char *d = (char*)(void *)dst; + const char *s = src; + + while (cnt >= sizeof (s32)) { + *(s32*)d = *(s32*)s; + d += sizeof (s32); + s += sizeof (s32); + cnt -= sizeof (s32); + } + while (cnt >= sizeof (u16)) { + *(u16*)d = *(u16*)s; + d += sizeof (u16); + s += sizeof (u16); + cnt -= sizeof (u16); + } + while ((cnt) > 0U){ + *d = *s; + d += 1U; + s += 1U; + cnt -= 1U; + } +} diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_mem.h b/bsp_z7/ps7_cortexa9_0/include/xil_mem.h new file mode 100644 index 0000000..4da150e --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_mem.h @@ -0,0 +1,48 @@ +/******************************************************************************/ +/** +* Copyright (c) 2015 - 2020 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* @file xil_mem.h +* +* @addtogroup common_mem_operation_api Customized APIs for Memory Operations +* +* The xil_mem.h file contains prototype for functions related +* to memory operations. These APIs are applicable for all processors supported +* by Xilinx. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+* 7.0   mus      01/07/19 Add cpp extern macro
+*
+* 
+* +*****************************************************************************/ +#ifndef XIL_MEM_H /* prevent circular inclusions */ +#define XIL_MEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes *****************************/ + +void Xil_MemCpy(void* dst, const void* src, u32 cnt); + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MEM_H */ +/** +* @} End of "addtogroup common_mem_operation_api". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_misc_psreset_api.h b/bsp_z7/ps7_cortexa9_0/include/xil_misc_psreset_api.h new file mode 100644 index 0000000..878d575 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_misc_psreset_api.h @@ -0,0 +1,261 @@ +/****************************************************************************** +* Copyright (c) 2013 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xil_misc_psreset_api.h +* +* This file contains the various register definitions and function prototypes for +* implementing the reset functionality of zynq ps devices +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00b kpc 03/07/13 First release. +* +* +******************************************************************************/ + +#ifndef XIL_MISC_RESET_H /* prevent circular inclusions */ +#define XIL_MISC_RESET_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** + *@cond nocomments + */ + +#define XDDRC_CTRL_BASEADDR 0xF8006000U +#define XSLCR_BASEADDR 0xF8000000U +/**< OCM configuration register */ +#define XSLCR_OCM_CFG_ADDR (XSLCR_BASEADDR + 0x00000910U) +/**< SLCR unlock register */ +#define XSLCR_UNLOCK_ADDR (XSLCR_BASEADDR + 0x00000008U) +/**< SLCR GEM0 rx clock control register */ +#define XSLCR_GEM0_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000138U) +/**< SLCR GEM1 rx clock control register */ +#define XSLCR_GEM1_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x0000013CU) +/**< SLCR GEM0 clock control register */ +#define XSLCR_GEM0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000140U) +/**< SLCR GEM1 clock control register */ +#define XSLCR_GEM1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000144U) +/**< SLCR SMC clock control register */ +#define XSLCR_SMC_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000148U) +/**< SLCR GEM reset control register */ +#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U) +/**< SLCR USB0 clock control register */ +#define XSLCR_USB0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000130U) +/**< SLCR USB1 clock control register */ +#define XSLCR_USB1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000134U) +/**< SLCR USB1 reset control register */ +#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U) +/**< SLCR SMC reset control register */ +#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U) +/**< SLCR Level shifter enable register */ +#define XSLCR_LVL_SHFTR_EN_ADDR (XSLCR_BASEADDR + 0x00000900U) +/**< SLCR ARM pll control register */ +#define XSLCR_ARM_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000100U) +/**< SLCR DDR pll control register */ +#define XSLCR_DDR_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000104U) +/**< SLCR IO pll control register */ +#define XSLCR_IO_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000108U) +/**< SLCR ARM pll configuration register */ +#define XSLCR_ARM_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000110U) +/**< SLCR DDR pll configuration register */ +#define XSLCR_DDR_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000114U) +/**< SLCR IO pll configuration register */ +#define XSLCR_IO_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000118U) +/**< SLCR ARM clock control register */ +#define XSLCR_ARM_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000120U) +/**< SLCR DDR clock control register */ +#define XSLCR_DDR_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000124U) +/**< SLCR MIO pin address register */ +#define XSLCR_MIO_PIN_00_ADDR (XSLCR_BASEADDR + 0x00000700U) +/**< SLCR DMAC reset control address register */ +#define XSLCR_DMAC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000020CU) +/**< SLCR USB reset control address register */ +/*#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U)*/ +/**< SLCR GEM reset control address register */ +/*#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U)*/ +/**< SLCR SDIO reset control address register */ +#define XSLCR_SDIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000218U) +/**< SLCR SPI reset control address register */ +#define XSLCR_SPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000021CU) +/**< SLCR CAN reset control address register */ +#define XSLCR_CAN_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000220U) +/**< SLCR I2C reset control address register */ +#define XSLCR_I2C_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000224U) +/**< SLCR UART reset control address register */ +#define XSLCR_UART_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000228U) +/**< SLCR GPIO reset control address register */ +#define XSLCR_GPIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000022CU) +/**< SLCR LQSPI reset control address register */ +#define XSLCR_LQSPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000230U) +/**< SLCR SMC reset control address register */ +/*#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U)*/ +/**< SLCR OCM reset control address register */ +#define XSLCR_OCM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000238U) + +/**< SMC mem controller clear config register */ +#define XSMC_MEMC_CLR_CONFIG_OFFSET 0x0000000CU +/**< SMC idlecount configuration register */ +#define XSMC_REFRESH_PERIOD_0_OFFSET 0x00000020U +#define XSMC_REFRESH_PERIOD_1_OFFSET 0x00000024U +/**< SMC ECC configuration register */ +#define XSMC_ECC_MEMCFG1_OFFSET 0x00000404U +/**< SMC ECC command 1 register */ +#define XSMC_ECC_MEMCMD1_OFFSET 0x00000404U +/**< SMC ECC command 2 register */ +#define XSMC_ECC_MEMCMD2_OFFSET 0x00000404U + +/**< SLCR unlock code */ +#define XSLCR_UNLOCK_CODE 0x0000DF0DU + +/**< SMC mem clear configuration mask */ +#define XSMC_MEMC_CLR_CONFIG_MASK 0x000005FU +/**< SMC ECC memconfig 1 reset value */ +#define XSMC_ECC_MEMCFG1_RESET_VAL 0x0000043U +/**< SMC ECC memcommand 1 reset value */ +#define XSMC_ECC_MEMCMD1_RESET_VAL 0x01300080U +/**< SMC ECC memcommand 2 reset value */ +#define XSMC_ECC_MEMCMD2_RESET_VAL 0x01E00585U + +/**< DDR controller reset bit mask */ +#define XDDRPS_CTRL_RESET_MASK 0x00000001U +/**< SLCR OCM configuration reset value*/ +#define XSLCR_OCM_CFG_RESETVAL 0x00000008U +/**< SLCR OCM bank selection mask*/ +#define XSLCR_OCM_CFG_HIADDR_MASK 0x0000000FU +/**< SLCR level shifter enable mask*/ +#define XSLCR_LVL_SHFTR_EN_MASK 0x0000000FU + +/**< SLCR PLL register reset values */ +#define XSLCR_ARM_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_DDR_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_IO_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_ARM_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_DDR_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_IO_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_ARM_CLK_CTRL_RESET_VAL 0x1F000400U +#define XSLCR_DDR_CLK_CTRL_RESET_VAL 0x18400003U + +/**< SLCR MIO register default values */ +#define XSLCR_MIO_PIN_00_RESET_VAL 0x00001601U +#define XSLCR_MIO_PIN_02_RESET_VAL 0x00000601U + +/**< SLCR Reset control registers default values */ +#define XSLCR_DMAC_RST_CTRL_VAL 0x00000001U +#define XSLCR_GEM_RST_CTRL_VAL 0x000000F3U +#define XSLCR_USB_RST_CTRL_VAL 0x00000003U +#define XSLCR_I2C_RST_CTRL_VAL 0x00000003U +#define XSLCR_SPI_RST_CTRL_VAL 0x0000000FU +#define XSLCR_UART_RST_CTRL_VAL 0x0000000FU +#define XSLCR_QSPI_RST_CTRL_VAL 0x00000003U +#define XSLCR_GPIO_RST_CTRL_VAL 0x00000001U +#define XSLCR_SMC_RST_CTRL_VAL 0x00000003U +#define XSLCR_OCM_RST_CTRL_VAL 0x00000001U +#define XSLCR_SDIO_RST_CTRL_VAL 0x00000033U +#define XSLCR_CAN_RST_CTRL_VAL 0x00000003U + +/** + *@endcond + */ + +/**************************** Type Definitions *******************************/ + +/* the following data type is used to hold a null terminated version string + * consisting of the following format, "X.YYX" + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ +/* + * Performs reset operation to the ddr interface + */ +void XDdr_ResetHw(void); +/* + * Map the ocm region to post bootrom state + */ +void XOcm_Remap(void); +/* + * Performs the smc interface reset + */ +void XSmc_ResetHw(u32 BaseAddress); +/* + * updates the MIO registers with reset values + */ +void XSlcr_MioWriteResetValues(void); +/* + * updates the PLL and clock registers with reset values + */ +void XSlcr_PllWriteResetValues(void); +/* + * Disables the level shifters + */ +void XSlcr_DisableLevelShifters(void); +/* + * provides softreset to the GPIO interface + */ +void XSlcr_GpioPsReset(void); +/* + * provides softreset to the DMA interface + */ +void XSlcr_DmaPsReset(void); +/* + * provides softreset to the SMC interface + */ +void XSlcr_SmcPsReset(void); +/* + * provides softreset to the CAN interface + */ +void XSlcr_CanPsReset(void); +/* + * provides softreset to the Uart interface + */ +void XSlcr_UartPsReset(void); +/* + * provides softreset to the I2C interface + */ +void XSlcr_I2cPsReset(void); +/* + * provides softreset to the SPI interface + */ +void XSlcr_SpiPsReset(void); +/* + * provides softreset to the QSPI interface + */ +void XSlcr_QspiPsReset(void); +/* + * provides softreset to the USB interface + */ +void XSlcr_UsbPsReset(void); +/* + * provides softreset to the GEM interface + */ +void XSlcr_EmacPsReset(void); +/* + * provides softreset to the OCM interface + */ +void XSlcr_OcmReset(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MISC_RESET_H */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_mmu.h b/bsp_z7/ps7_cortexa9_0/include/xil_mmu.h new file mode 100644 index 0000000..d21e13a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_mmu.h @@ -0,0 +1,92 @@ +/****************************************************************************** +* Copyright (c) 2012 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xil_mmu.h +* +* @addtogroup a9_mmu_apis Cortex A9 Processor MMU Functions +* +* MMU functions equip users to enable MMU, disable MMU and modify default +* memory attributes of MMU table as per the need. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  01/12/12 Initial version
+* 4.2	pkp	 07/21/14 Included xil_types.h file which contains definition for
+*					  u32 which resolves issue of CR#805869
+* 5.4	pkp	 23/11/15 Added attribute definitions for Xil_SetTlbAttributes API
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef XIL_MMU_H +#define XIL_MMU_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory type */ +#define NORM_NONCACHE 0x11DE2 /* Normal Non-cacheable */ +#define STRONG_ORDERED 0xC02 /* Strongly ordered */ +#define DEVICE_MEMORY 0xC06 /* Device memory */ +#define RESERVED 0x0 /* reserved memory */ + +/* Normal write-through cacheable shareable */ +#define NORM_WT_CACHE 0x16DEA + +/* Normal write back cacheable shareable */ +#define NORM_WB_CACHE 0x15DE6 + +/* shareability attribute */ +#define SHAREABLE (0x1 << 16) +#define NON_SHAREABLE (~(0x1 << 16)) + +/* Execution type */ +#define EXECUTE_NEVER ((0x1 << 4) | (0x1 << 0)) + +/** +*@endcond +*/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib); +void Xil_EnableMMU(void); +void Xil_DisableMMU(void); +void* Xil_MemMap(UINTPTR PhysAddr, size_t size, u32 flags); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_MMU_H */ +/** +* @} End of "addtogroup a9_mmu_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_printf.c b/bsp_z7/ps7_cortexa9_0/include/xil_printf.c new file mode 100644 index 0000000..bf104fd --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_printf.c @@ -0,0 +1,447 @@ +/****************************************************************************** +* Copyright (c) 1995 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +*******************************************************************************/ +/*---------------------------------------------------*/ +/* Modified from : */ +/* Public Domain version of printf */ +/* Rud Merriam, Compsult, Inc. Houston, Tx. */ +/* For Embedded Systems Programming, 1991 */ +/* */ +/*---------------------------------------------------*/ +#include "xil_printf.h" +#include "xil_types.h" +#include "xil_assert.h" +#include +#include +#include + +static void padding( const s32 l_flag,const struct params_s *par); +static void outs(const charptr lp, struct params_s *par); +static s32 getnum( charptr* linep); + +typedef struct params_s { + s32 len; + s32 num1; + s32 num2; + char8 pad_character; + s32 do_padding; + s32 left_flag; + s32 unsigned_flag; +} params_t; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + + +/*---------------------------------------------------*/ +/* */ +/* This routine puts pad characters into the output */ +/* buffer. */ +/* */ +static void padding( const s32 l_flag, const struct params_s *par) +{ + s32 i; + + if ((par->do_padding != 0) && (l_flag != 0) && (par->len < par->num1)) { + i=(par->len); + for (; i<(par->num1); i++) { +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( par->pad_character); +#endif + } + } +} + +/*---------------------------------------------------*/ +/* */ +/* This routine moves a string to the output buffer */ +/* as directed by the padding and positioning flags. */ +/* */ +static void outs(const charptr lp, struct params_s *par) +{ + charptr LocalPtr; + LocalPtr = lp; + /* pad on left if needed */ + if(LocalPtr != NULL) { + par->len = (s32)strlen( LocalPtr); + padding( !(par->left_flag), par); + /* Move string to the buffer */ + while (((*LocalPtr) != (char8)0) && ((par->num2) != 0)) { + (par->num2)--; +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte(*LocalPtr); +#endif + LocalPtr += 1; + } +} + + /* Pad on right if needed */ + /* CR 439175 - elided next stmt. Seemed bogus. */ + padding( par->left_flag, par); +} + +/*---------------------------------------------------*/ +/* */ +/* This routine moves a number to the output buffer */ +/* as directed by the padding and positioning flags. */ +/* */ + +static void outnum( const s32 n, const s32 base, struct params_s *par) +{ + s32 negative; + s32 i; + char8 outbuf[32]; + const char8 digits[] = "0123456789ABCDEF"; + u32 num; + for(i = 0; i<32; i++) { + outbuf[i] = '0'; + } + + /* Check if number is negative */ + if ((par->unsigned_flag == 0) && (base == 10) && (n < 0L)) { + negative = 1; + num =(-(n)); + } + else{ + num = n; + negative = 0; + } + + /* Build number (backwards) in outbuf */ + i = 0; + do { + outbuf[i] = digits[(num % (u32)base)]; + i++; + num /= base; + } while (num > 0U); + + if (negative != 0) { + outbuf[i] = '-'; + i++; + } + + outbuf[i] = '\0'; + i--; + + /* Move the converted number to the buffer and */ + /* add in the padding where needed. */ + par->len = (s32)strlen(outbuf); + padding( !(par->left_flag), par); + while (&outbuf[i] >= outbuf) { +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( outbuf[i] ); +#endif + i--; +} + padding( par->left_flag, par); +} +/*---------------------------------------------------*/ +/* */ +/* This routine moves a 64-bit number to the output */ +/* buffer as directed by the padding and positioning */ +/* flags. */ +/* */ +#if defined (__aarch64__) || defined (__arch64__) +static void outnum1( const s64 n, const s32 base, params_t *par) +{ + s32 negative; + s32 i; + char8 outbuf[64]; + const char8 digits[] = "0123456789ABCDEF"; + u64 num; + for(i = 0; i<64; i++) { + outbuf[i] = '0'; + } + + /* Check if number is negative */ + if ((par->unsigned_flag == 0) && (base == 10) && (n < 0L)) { + negative = 1; + num =(-(n)); + } + else{ + num = (n); + negative = 0; + } + + /* Build number (backwards) in outbuf */ + i = 0; + do { + outbuf[i] = digits[(num % base)]; + i++; + num /= base; + } while (num > 0); + + if (negative != 0) { + outbuf[i] = '-'; + i++; + } + + outbuf[i] = '\0'; + i--; + + /* Move the converted number to the buffer and */ + /* add in the padding where needed. */ + par->len = (s32)strlen(outbuf); + padding( !(par->left_flag), par); + while (&outbuf[i] >= outbuf) { + outbyte( outbuf[i] ); + i--; +} + padding( par->left_flag, par); +} +#endif +/*---------------------------------------------------*/ +/* */ +/* This routine gets a number from the format */ +/* string. */ +/* */ +static s32 getnum(charptr* linep) +{ + s32 n = 0; + s32 ResultIsDigit = 0; + charptr cptr = *linep; + + while (cptr != NULL) { + ResultIsDigit = isdigit(((u8)*cptr)); + if (ResultIsDigit == 0) { + break; + } + n = ((n*10) + (((s32)*cptr) - (s32)'0')); + cptr += 1; + } + + *linep = ((charptr)(cptr)); + return(n); +} + +/*---------------------------------------------------*/ +/* */ +/* This routine operates just like a printf/sprintf */ +/* routine. It outputs a set of data under the */ +/* control of a formatting string. Not all of the */ +/* standard C format control are supported. The ones */ +/* provided are primarily those needed for embedded */ +/* systems work. Primarily the floating point */ +/* routines are omitted. Other formats could be */ +/* added easily by following the examples shown for */ +/* the supported formats. */ +/* */ + +/* void esp_printf( const func_ptr f_ptr, + const charptr ctrl1, ...) */ +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +void xil_printf( const char8 *ctrl1, ...){ + XPVXenConsole_Printf(ctrl1); +} +#else +void xil_printf( const char8 *ctrl1, ...) +{ + va_list argp; + + va_start(argp, ctrl1); + + xil_vprintf(ctrl1, argp); + + va_end(argp); +} +#endif + +/* This routine is equivalent to vprintf routine */ +void xil_vprintf(const char8 *ctrl1, va_list argp) +{ + s32 Check; +#if defined (__aarch64__) || defined (__arch64__) + s32 long_flag; +#endif + s32 dot_flag; + + params_t par; + + u8 ch; + char8 *ctrl = (char8 *)ctrl1; + + while ((ctrl != NULL) && (*ctrl != (char8)0)) { + + /* move format string chars to buffer until a */ + /* format control is found. */ + if (*ctrl != '%') { +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte(*ctrl); +#endif + ctrl += 1; + continue; + } + + /* initialize all the flags for this format. */ + dot_flag = 0; +#if defined (__aarch64__) || defined (__arch64__) + long_flag = 0; +#endif + par.unsigned_flag = 0; + par.left_flag = 0; + par.do_padding = 0; + par.pad_character = ' '; + par.num2=32767; + par.num1=0; + par.len=0; + + try_next: + if(ctrl != NULL) { + ctrl += 1; + } + if(ctrl != NULL) { + ch = (u8)*ctrl; + } else { + break; + } + + if (isdigit(ch) != 0) { + if (dot_flag != 0) { + par.num2 = getnum(&ctrl); + } + else { + if (ch == (u8)'0') { + par.pad_character = '0'; + } + if(ctrl != NULL) { + par.num1 = getnum(&ctrl); + } + par.do_padding = 1; + } + if(ctrl != NULL) { + ctrl -= 1; + } + goto try_next; + } + + switch (tolower(ch)) { + case '%': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( '%'); +#endif + Check = 1; + break; + + case '-': + par.left_flag = 1; + Check = 0; + break; + + case '.': + dot_flag = 1; + Check = 0; + break; + + case 'l': + #if defined (__aarch64__) || defined (__arch64__) + long_flag = 1; + #endif + Check = 0; + break; + + case 'u': + par.unsigned_flag = 1; + /* fall through */ + case 'i': + case 'd': + #if defined (__aarch64__) || defined (__arch64__) + if (long_flag != 0){ + outnum1((s64)va_arg(argp, s64), 10L, &par); + } + else { + outnum( va_arg(argp, s32), 10L, &par); + } + #else + outnum( va_arg(argp, s32), 10L, &par); + #endif + Check = 1; + break; + case 'p': + #if defined (__aarch64__) || defined (__arch64__) + par.unsigned_flag = 1; + outnum1((s64)va_arg(argp, s64), 16L, &par); + Check = 1; + break; + #endif + case 'X': + case 'x': + par.unsigned_flag = 1; + #if defined (__aarch64__) || defined (__arch64__) + if (long_flag != 0) { + outnum1((s64)va_arg(argp, s64), 16L, &par); + } + else { + outnum((s32)va_arg(argp, s32), 16L, &par); + } + #else + outnum((s32)va_arg(argp, s32), 16L, &par); + #endif + Check = 1; + break; + + case 's': + outs( va_arg( argp, char *), &par); + Check = 1; + break; + + case 'c': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( (char8)va_arg( argp, s32)); +#endif + Check = 1; + break; + + case '\\': + switch (*ctrl) { + case 'a': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( ((char8)0x07)); +#endif + break; + case 'h': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( ((char8)0x08)); +#endif + break; + case 'r': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( ((char8)0x0D)); +#endif + break; + case 'n': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( ((char8)0x0D)); + outbyte( ((char8)0x0A)); +#endif + break; + default: +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( *ctrl); +#endif + break; + } + ctrl += 1; + Check = 0; + break; + + default: + Check = 1; + break; + } + if(Check == 1) { + if(ctrl != NULL) { + ctrl += 1; + } + continue; + } + goto try_next; + } +} +/*---------------------------------------------------*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_printf.h b/bsp_z7/ps7_cortexa9_0/include/xil_printf.h new file mode 100644 index 0000000..062ad6b --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_printf.h @@ -0,0 +1,53 @@ +/****************************************************************************** +* Copyright (c) 1995 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +*******************************************************************************/ + #ifndef XIL_PRINTF_H + #define XIL_PRINTF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "xil_types.h" +#include "xparameters.h" +#include "bspconfig.h" +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +#include "xen_console.h" +#endif + +/*----------------------------------------------------*/ +/* Use the following parameter passing structure to */ +/* make xil_printf re-entrant. */ +/*----------------------------------------------------*/ + +struct params_s; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + +typedef char8* charptr; +typedef s32 (*func_ptr)(int c); + +/* */ + +void xil_printf( const char8 *ctrl1, ...); +void xil_vprintf(const char8 *ctrl1, va_list argp); +void print( const char8 *ptr); +extern void outbyte (char c); +extern char inbyte(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_sleepcommon.c b/bsp_z7/ps7_cortexa9_0/include/xil_sleepcommon.c new file mode 100644 index 0000000..aba3a08 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_sleepcommon.c @@ -0,0 +1,85 @@ +/****************************************************************************** +* Copyright (c) 2017 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +*@file xil_sleepcommon.c +* +* This file contains the sleep API's +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.6 	srm  	 11/02/17 First release
+* 7.7	sk	 01/10/22 Typecast sleep function argument from unsigned
+* 			  int to u32 to fix misra_c_2012_directive_4_6
+* 			  violation.
+* 8.0	sk	 03/02/22 Update usleep argument type to fix misra_c_2012_
+* 			  directive_4_6 violation.
+* 
+******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_io.h" +#include "sleep.h" + +/**************************** Constant Definitions *************************/ + + +/*****************************************************************************/ +/** +* +* This API gives delay in sec +* +* @param seconds - delay time in seconds +* +* @return none +* +* @note none +* +*****************************************************************************/ + void sleep(u32 seconds) + { +#if defined (ARMR5) + sleep_R5(seconds); +#elif defined (__aarch64__) || defined (ARMA53_32) + sleep_A53(seconds); +#elif defined (__MICROBLAZE__) + sleep_MB(seconds); +#else + sleep_A9(seconds); +#endif + + } + +/****************************************************************************/ +/** +* +* This API gives delay in usec +* +* @param useconds - delay time in useconds +* +* @return none +* +* @note none +* +*****************************************************************************/ + void usleep(ULONG useconds) + { +#if defined (ARMR5) + usleep_R5(useconds); +#elif defined (__aarch64__) || defined (ARMA53_32) + usleep_A53(useconds); +#elif defined (__MICROBLAZE__) + usleep_MB(useconds); +#else + usleep_A9(useconds); +#endif + + } diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_sleeptimer.h b/bsp_z7/ps7_cortexa9_0/include/xil_sleeptimer.h new file mode 100644 index 0000000..b133eaf --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_sleeptimer.h @@ -0,0 +1,115 @@ +/****************************************************************************** +* Copyright (c) 2017 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_sleeptimer.h +* +* This header file contains ARM Cortex A53,A9,R5 specific sleep related APIs. +* For sleep related functions that can be used across all Xilinx supported +* processors, please use xil_sleeptimer.h. +* +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6	srm  10/18/17 First Release.
+* 7.0   mus  01/07/19 Add cpp extern macro
+* 7.7	sk   01/10/22 Add explicit parentheses for EL3==1 to fix
+* 		      misra_c_2012_rule_12_1 violation.
+* 7.7	sk   01/10/22 Add void to XTime_StartTTCTimer function declaration
+* 		      to fix misra_c_2012_rule_8_2 violation.
+*
+* 
+*****************************************************************************/ + +/** + *@cond nocomments + */ +#ifndef XIL_SLEEPTIMER_H /* prevent circular inclusions */ +#define XIL_SLEEPTIMER_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files ********************************/ + +#include "xil_io.h" +#include "xparameters.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +#define XSLEEP_TIMER_REG_SHIFT 32U +#define XSleep_ReadCounterVal Xil_In32 +#define XCntrVal u32 +#else +#define XSLEEP_TIMER_REG_SHIFT 16U +#define XSleep_ReadCounterVal Xil_In16 +#define XCntrVal u16 +#endif + +#if defined(ARMR5) || (defined (__aarch64__) && (EL3==1)) || defined (ARMA53_32) +#if defined (versal) +#define CRL_TTC_RST 0xFF5E0344U +#define CRL_TTC_BASE_RST_MASK 0x1U +#else +#define RST_LPD_IOU2 0xFF5E0238U +#define RST_LPD_IOU2_TTC_BASE_RESET_MASK 0x00000800U +#endif +#endif + +#if defined (SLEEP_TIMER_BASEADDR) +/** @name Register Map +* +* Register offsets from the base address of the TTC device +* +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET 0x00000000U + /**< Clock Control Register */ + #define XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET 0x0000000CU + /**< Counter Control Register*/ + #define XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET 0x00000018U + /**< Current Counter Value */ +/* @} */ +/** @name Clock Control Register +* Clock Control Register definitions of TTC +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK 0x00000001U + /**< Prescale enable */ +/* @} */ +/** @name Counter Control Register +* Counter Control Register definitions of TTC +* @{ +*/ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK 0x00000001U + /**< Disable the counter */ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_RST_MASK 0x00000010U + /**< Reset counter */ +/* @} */ + +/**************************** Type Definitions *******************************/ +/** + *@endcond + */ +/************************** Function Prototypes ******************************/ + +void Xil_SleepTTCCommon(u32 delay, u64 frequency); +void XTime_StartTTCTimer(void); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_SLEEPTIMER_H */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_spinlock.h b/bsp_z7/ps7_cortexa9_0/include/xil_spinlock.h new file mode 100644 index 0000000..0cdf288 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_spinlock.h @@ -0,0 +1,80 @@ +/****************************************************************************** +* Copyright (c) 2021 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_spinlock.h +* +* This header file contains function prototypes to be used while using Xilinx +* spinlocking mechanism. +* Please refer to file header contents of xil_spinlock.c to understand in +* detail the spinlocking mechanism. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 7.5 	asa		 02/16/21 First release
+* 7.6	sk	 08/05/21 Add Boolean check and braces for Xil_IsSpinLockEnabled
+* 			  if condition to fix misrac violations.
+* 7.7	sk	 01/10/22 Update XIL_SPINLOCK_ENABLED from signed to unsigned to
+* 			  fix misra_c_2012_rule_10_4 violation.
+* 
+* +******************************************************************************/ + +#ifndef XIL_SPINLOCK_H /* prevent circular inclusions */ +#define XIL_SPINLOCK_H /* by using protection macros */ + +/***************************** Include Files ********************************/ +#include "xil_types.h" +#include "xstatus.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if !defined (__aarch64__) && defined(__GNUC__) && !defined(__clang__) +/************************** Function Prototypes *****************************/ +u32 Xil_SpinLock(void); +u32 Xil_SpinUnlock(void); +u32 Xil_InitializeSpinLock(UINTPTR lockaddr, UINTPTR lockflagaddr, + u32 lockflag); +void Xil_ReleaseSpinLock(void); +u32 Xil_IsSpinLockEnabled(void); + +/************************** MACRO Definitions ****************************/ +#define XIL_SPINLOCK_LOCKVAL 0x10203040 +#define XIL_SPINLOCK_RESETVAL 0x40302010 +#define XIL_SPINLOCK_ENABLE 0x17273747 +#define XIL_SPINLOCK_ENABLED 0x17273747U +/***************** Macros (Inline Functions) Definitions ********************/ + +#endif /* !(__aarch64__) && (__GNUC__) && !(__clang__)*/ +/***************************************************************************/ +#if !defined (__aarch64__) && defined(__GNUC__) && !defined(__clang__) +#define XIL_SPINLOCK() \ + if(Xil_IsSpinLockEnabled()!=(u32)0) { \ + Xil_SpinLock(); } +#else +#define XIL_SPINLOCK() +#endif /* !(__aarch64__) && (__GNUC__) && !(__clang__)*/ + +#if !defined (__aarch64__) && defined(__GNUC__) && !defined(__clang__) +#define XIL_SPINUNLOCK() \ + if(Xil_IsSpinLockEnabled()!=(u32)0) { \ + Xil_SpinUnlock(); } +#else +#define XIL_SPINUNLOCK() +#endif /* !(__aarch64__) && (__GNUC__) && !(__clang__)*/ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_SPINLOCK_H */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_testcache.c b/bsp_z7/ps7_cortexa9_0/include/xil_testcache.c new file mode 100644 index 0000000..f101c14 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_testcache.c @@ -0,0 +1,341 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testcache.c +* @addtogroup common_test_utils +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+* 4.1   asa  05/09/14 Ensured that the address uses for cache test is aligned
+*				      cache line.
+* 
+* +******************************************************************************/ +#ifdef __ARM__ +#include "xil_cache.h" +#include "xil_testcache.h" +#include "xil_types.h" +#include "xpseudo_asm.h" +#ifdef __aarch64__ +#include "xreg_cortexa53.h" +#else +#include "xreg_cortexr5.h" +#endif + +#include "xil_types.h" + +extern void xil_printf(const char8 *ctrl1, ...); + +#define DATA_LENGTH 128 + +#ifdef __aarch64__ +static INTPTR Data[DATA_LENGTH] __attribute__ ((aligned(64))); +#else +static INTPTR Data[DATA_LENGTH] __attribute__ ((aligned(32))); +#endif + + +/*****************************************************************************/ +/** +* +* @brief Perform DCache range related API test such as Xil_DCacheFlushRange +* and Xil_DCacheInvalidateRange. This test function writes a constant +* value to the Data array, flushes the range, writes a new value, then +* invalidates the corresponding range. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ +s32 Xil_TestDCacheRange(void) +{ + s32 Index; + s32 Status = 0; + u32 CtrlReg; + INTPTR Value; + + xil_printf("-- Cache Range Test --\n\r"); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A00505; + + xil_printf(" initialize Data done:\r\n"); + + Xil_DCacheFlushRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + xil_printf(" flush range done\r\n"); + + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0xA0A00505) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Flush worked\r\n"); + } + else { + xil_printf("Error: flush dcache range not working\r\n"); + } + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A0C505; + + + + Xil_DCacheFlushRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = Index + 3; + + Xil_DCacheInvalidateRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + xil_printf(" invalidate dcache range done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A0A05; + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0xA0A0A05) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + + if (!Status) { + xil_printf(" Invalidate worked\r\n"); + } + else { + xil_printf("Error: Invalidate dcache range not working\r\n"); + } + xil_printf("-- Cache Range Test Complete --\r\n"); + return Status; + +} + +/*****************************************************************************/ +/** +* @brief Perform DCache all related API test such as Xil_DCacheFlush and +* Xil_DCacheInvalidate. This test function writes a constant value +* to the Data array, flushes the DCache, writes a new value, +* then invalidates the DCache. +* +* @return +* - 0 is returned for a pass +* - -1 is returned for a failure +*****************************************************************************/ +s32 Xil_TestDCacheAll(void) +{ + s32 Index; + s32 Status; + INTPTR Value; + u32 CtrlReg; + + xil_printf("-- Cache All Test --\n\r"); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x50500A0A; + xil_printf(" initialize Data done:\r\n"); + + Xil_DCacheFlush(); + xil_printf(" flush all done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + + if (Value != 0x50500A0A) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Flush all worked\r\n"); + } + else { + xil_printf("Error: Flush dcache all not working\r\n"); + } + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x505FFA0A; + + Xil_DCacheFlush(); + + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = Index + 3; + + Xil_DCacheInvalidate(); + + xil_printf(" invalidate all done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x50CFA0A; + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0x50CFA0A) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Invalidate all worked\r\n"); + } + else { + xil_printf("Error: Invalidate dcache all not working\r\n"); + } + + xil_printf("-- DCache all Test Complete --\n\r"); + + return Status; +} + +/*****************************************************************************/ +/** +* @brief Perform Xil_ICacheInvalidateRange() on a few function pointers. +* +* @return +* - 0 is returned for a pass +* +* @note The function will hang if it fails. +*****************************************************************************/ +s32 Xil_TestICacheRange(void) +{ + + Xil_ICacheInvalidateRange((INTPTR)Xil_TestICacheRange, 1024); + Xil_ICacheInvalidateRange((INTPTR)Xil_TestDCacheRange, 1024); + Xil_ICacheInvalidateRange((INTPTR)Xil_TestDCacheAll, 1024); + + xil_printf("-- Invalidate icache range done --\r\n"); + + return 0; +} + +/*****************************************************************************/ +/** +* @brief Perform Xil_ICacheInvalidate() on a few function pointers. +* +* @return +* - 0 is returned for a pass +* +* @note The function will hang if it fails. +*****************************************************************************/ +s32 Xil_TestICacheAll(void) +{ + Xil_ICacheInvalidate(); + xil_printf("-- Invalidate icache all done --\r\n"); + return 0; +} +#endif diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_testcache.h b/bsp_z7/ps7_cortexa9_0/include/xil_testcache.h new file mode 100644 index 0000000..5798c21 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_testcache.h @@ -0,0 +1,54 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testcache.h +* +* @addtogroup common_test_utils +*

Cache test

+* The xil_testcache.h file contains utility functions to test cache. +* +* @{ +*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  07/29/09 First release
+* 
+* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef XIL_TESTCACHE_H /* prevent circular inclusions */ +#define XIL_TESTCACHE_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern s32 Xil_TestDCacheRange(void); +extern s32 Xil_TestDCacheAll(void); +extern s32 Xil_TestICacheRange(void); +extern s32 Xil_TestICacheAll(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ + +/** + *@endcond + */ + +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_testio.c b/bsp_z7/ps7_cortexa9_0/include/xil_testio.c new file mode 100644 index 0000000..c05acd9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_testio.c @@ -0,0 +1,273 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testio.c +* @addtogroup common_test_utils +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_testio.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ +/************************** Function Prototypes *****************************/ + + + +/** + * + * Endian swap a 16-bit word. + * @param Data is the 16-bit word to be swapped. + * @return The endian swapped value. + * + */ +static u16 Swap16(u16 Data) +{ + return ((Data >> 8U) & 0x00FFU) | ((Data << 8U) & 0xFF00U); +} + +/** + * + * Endian swap a 32-bit word. + * @param Data is the 32-bit word to be swapped. + * @return The endian swapped value. + * + */ +static u32 Swap32(u32 Data) +{ + u16 Lo16; + u16 Hi16; + + u16 Swap16Lo; + u16 Swap16Hi; + + Hi16 = (u16)((Data >> 16U) & 0x0000FFFFU); + Lo16 = (u16)(Data & 0x0000FFFFU); + + Swap16Lo = Swap16(Lo16); + Swap16Hi = Swap16(Hi16); + + return (((u32)(Swap16Lo)) << 16U) | ((u32)Swap16Hi); +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide register IO test where the +* register is accessed using Xil_Out8 and Xil_In8, and comparing +* the written values by reading them back. +* +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writing the memory. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ + +s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value) +{ + u8 ValueIn; + s32 Index; + s32 Status = 0; + + for (Index = 0; Index < Length; Index++) { + Xil_Out8((INTPTR)Addr, Value); + + ValueIn = Xil_In8((INTPTR)Addr); + + if ((Value != ValueIn) && (Status == 0)) { + Status = -1; + break; + } + } + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide register IO test. Each location +* is tested by sequentially writing a 16-bit wide register, reading +* the register, and comparing value. This function tests three kinds +* of register IO functions, normal register IO, little-endian register +* IO, and big-endian register IO. When testing little/big-endian IO, +* the function performs the following sequence, Xil_Out16LE/Xil_Out16BE, +* Xil_In16, Compare In-Out values, Xil_Out16, Xil_In16LE/Xil_In16BE, +* Compare In-Out values. Whether to swap the read-in value before +* comparing is controlled by the 5th argument. +* +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writing the memory. +* @param Kind: Type of test. Acceptable values are: +* XIL_TESTIO_DEFAULT, XIL_TESTIO_LE, XIL_TESTIO_BE. +* @param Swap: indicates whether to byte swap the read-in value. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ + +s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap) +{ + u16 *TempAddr16; + u16 ValueIn = 0U; + s32 Index; + TempAddr16 = Addr; + Xil_AssertNonvoid(TempAddr16 != NULL); + + for (Index = 0; Index < Length; Index++) { + switch (Kind) { + case XIL_TESTIO_LE: + Xil_Out16LE((INTPTR)TempAddr16, Value); + break; + case XIL_TESTIO_BE: + Xil_Out16BE((INTPTR)TempAddr16, Value); + break; + default: + Xil_Out16((INTPTR)TempAddr16, Value); + break; + } + + ValueIn = Xil_In16((INTPTR)TempAddr16); + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap16(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + + /* second round */ + Xil_Out16((INTPTR)TempAddr16, Value); + + switch (Kind) { + case XIL_TESTIO_LE: + ValueIn = Xil_In16LE((INTPTR)TempAddr16); + break; + case XIL_TESTIO_BE: + ValueIn = Xil_In16BE((INTPTR)TempAddr16); + break; + default: + ValueIn = Xil_In16((INTPTR)TempAddr16); + break; + } + + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap16(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + TempAddr16 += sizeof(u16); + } + return 0; +} + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide register IO test. Each location +* is tested by sequentially writing a 32-bit wide register, reading +* the register, and comparing value. This function tests three kinds +* of register IO functions, normal register IO, little-endian register IO, +* and big-endian register IO. When testing little/big-endian IO, +* the function perform the following sequence, Xil_Out32LE/ +* Xil_Out32BE, Xil_In32, Compare, Xil_Out32, Xil_In32LE/Xil_In32BE, Compare. +* Whether to swap the read-in value *before comparing is controlled +* by the 5th argument. +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writing the memory. +* @param Kind: type of test. Acceptable values are: +* XIL_TESTIO_DEFAULT, XIL_TESTIO_LE, XIL_TESTIO_BE. +* @param Swap: indicates whether to byte swap the read-in value. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ +s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap) +{ + u32 *TempAddr; + u32 ValueIn = 0U; + s32 Index; + TempAddr = Addr; + Xil_AssertNonvoid(TempAddr != NULL); + + for (Index = 0; Index < Length; Index++) { + switch (Kind) { + case XIL_TESTIO_LE: + Xil_Out32LE((INTPTR)TempAddr, Value); + break; + case XIL_TESTIO_BE: + Xil_Out32BE((INTPTR)TempAddr, Value); + break; + default: + Xil_Out32((INTPTR)TempAddr, Value); + break; + } + + ValueIn = Xil_In32((INTPTR)TempAddr); + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap32(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + + /* second round */ + Xil_Out32((INTPTR)TempAddr, Value); + + + switch (Kind) { + case XIL_TESTIO_LE: + ValueIn = Xil_In32LE((INTPTR)TempAddr); + break; + case XIL_TESTIO_BE: + ValueIn = Xil_In32BE((INTPTR)TempAddr); + break; + default: + ValueIn = Xil_In32((INTPTR)TempAddr); + break; + } + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap32(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + TempAddr += sizeof(u32); + } + return 0; +} diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_testio.h b/bsp_z7/ps7_cortexa9_0/include/xil_testio.h new file mode 100644 index 0000000..5a1bda3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_testio.h @@ -0,0 +1,76 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testio.h +* +* @addtogroup common_test_utils Test Utilities for Memory and Caches +*

I/O test

+* The xil_testio.h file contains utility functions to test endian related memory +* IO functions. +* +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00 hbm  08/05/09 First release
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_TESTIO_H /* prevent circular inclusions */ +#define XIL_TESTIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +#define XIL_TESTIO_DEFAULT 0 +#define XIL_TESTIO_LE 1 +#define XIL_TESTIO_BE 2 + +/** + *@endcond + */ + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +extern s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value); +extern s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap); +extern s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_testmem.c b/bsp_z7/ps7_cortexa9_0/include/xil_testmem.c new file mode 100644 index 0000000..aaa0617 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_testmem.c @@ -0,0 +1,1575 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testmem.c +* @addtogroup common_test_utils +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 7.5   mus  03/10/21 Added new set of Xil_TestMem32, Xil_TestMem16 and
+*                     Xil_TestMem8 APIs to support memory test for memory
+*                     regions mapped at extended addresses
+*                     (addresses > 4 GB). These new set of APIs would be
+*                     compiled only for 32 bit Microblaze processor, if
+*                     XPAR_MICROBLAZE_ADDR_SIZE is greater than 32.
+*                     It fixes CR#1089129.
+* 7.6   mus  07/29/21 Updated Xil_TestMem8 to fix issues reported by static
+*                     analysis tool. It fixes CR#1105956.
+* 7.7	sk   01/10/22 Remove commented macro to fix misra_c_2012_directive_4_4
+* 		      violation.
+* 7.7	sk   01/10/22 Modify operands to fix misra_c_2012_rule_10_1 violation.
+* 7.7	sk   01/10/22 Typecast to make the both left and right sides expressions
+* 		      of same type and fix misra_c_2012_rule_10_6 violation.
+* 7.7	sk   01/10/22 Modify varaiable name from I to i to fix misra_c_2012_rule_
+* 		      21_2 violation.
+* 7.7	sk   01/10/22 Remove arithematic operations on pointer varaible to fix
+* 		      misra_c_2012_rule_18_4 violation.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_testmem.h" +#include "xil_io.h" +#include "xil_assert.h" + +/************************** Constant Definitions ****************************/ +/************************** Function Prototypes *****************************/ + +static u32 RotateLeft(u32 Input, u8 Width); + +/* define ROTATE_RIGHT to give access to this functionality */ +#ifdef ROTATE_RIGHT +static u32 RotateRight(u32 Input, u8 Width); +#endif /* ROTATE_RIGHT */ + +#if defined(__MICROBLAZE__) && !defined(__arch64__) && (XPAR_MICROBLAZE_ADDR_SIZE > 32) + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide memory test. +* +* @param Addrlow: lower 32 bit address of memory to be tested. +* @param Addrhigh: upper 32 bit address of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem8(u32 Addrlow, u32 Addrhigh, u32 Words, u8 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u8 Val; + u8 WordMem8; + s32 Status = 0; + u64 Addr = (Addrlow + ((u64)Addrhigh << 32)); + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + + /* + * select the proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from XIL_TESTMEM_INIT_VALUE + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + sbea(Addr+I, Val); + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = XIL_TESTMEM_INIT_VALUE; + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = lbuea(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_BYTE; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + Val = (u8)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + for (I = 0U; I < NUM_OF_BITS_IN_BYTE; I++) { + /* write memory location */ + sbea(Addr+I, Val); + Val = (u8)RotateLeft(Val, 8U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u8)((u32)1 << j); + /* Read the values from each location that was written */ + for (I = 0U; I < NUM_OF_BITS_IN_BYTE; I++) { + /* read memory location */ + WordMem8 = lbuea(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val = (u8)RotateLeft(Val, NUM_OF_BITS_IN_BYTE); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking zeros test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_BYTE; j++) { + /* + * Generate an initial value for walking ones test to test + * for bad data bits + */ + Val = (u8) (~(1U << j)); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + for (I = 0U; I < NUM_OF_BITS_IN_BYTE; I++) { + /* write memory location */ + sbea(Addr+I, Val); + Val = ~((u8)RotateLeft(~Val, NUM_OF_BITS_IN_BYTE)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u8) (~(1U << j)); + /* Read the values from each location that was written */ + for (I = 0U; I < NUM_OF_BITS_IN_BYTE; I++) { + /* read memory location */ + WordMem8 = lbuea(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + + Val = ~((u8)RotateLeft(~Val, NUM_OF_BITS_IN_BYTE)); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + Val = (u8) (~((INTPTR) (Addr + I))); + sbea(Addr+I, Val); + } + + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = lbuea(Addr+I); + Val = (u8) (~((INTPTR) (Addr+I))); + if ((WordMem8 ^ Val) != 0x00U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u8)0) { + Val = 0xA5U; + } + else { + Val = Pattern; + } + /* + * Fill the memory with fixed Pattern + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + sbea(Addr+I, Val); + } + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = lbuea(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide memory test. +* +* @param Addrlow: lower 32 bit address of memory to be tested. +* @param Addrhigh: upper 32 bit address of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant Pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem16(u32 Addrlow,u32 Addrhigh, u32 Words, u16 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u16 Val; + u16 WordMem16; + s32 Status = 0; + u64 Addr = (Addrlow + ((u64)Addrhigh << 32)); + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + + /* + * selectthe proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'XIL_TESTMEM_INIT_VALUE' + */ + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * Words);) { + /* write memory location */ + shea(Addr+I, Val); + Val++; + I = I + NUM_OF_BYTES_IN_HW; + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = XIL_TESTMEM_INIT_VALUE; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference val + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * Words);) { + /* read memory location */ + WordMem16 = lhuea(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val++; + I = I + NUM_OF_BYTES_IN_HW; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking ones test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_HW; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (u16)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * NUM_OF_BITS_IN_HW); ) { + /* write memory location */ + shea(Addr+I,Val); + Val = (u16)RotateLeft(Val, 16U); + I = I + NUM_OF_BYTES_IN_HW; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u16)((u32)1 << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * NUM_OF_BITS_IN_HW); ) { + /* read memory location */ + WordMem16 = lhuea(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = (u16)RotateLeft(Val, NUM_OF_BITS_IN_HW); + I = I + NUM_OF_BYTES_IN_HW; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking zeros test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_HW; j++) { + /* + * Generate an initial value for walking ones + * test to test for bad + * data bits + */ + + Val = ~(1U << j); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * NUM_OF_BITS_IN_HW);) { + shea(Addr+I, Val); + Val = ~((u16)RotateLeft(~Val, 16U)); + I = I + NUM_OF_BYTES_IN_HW; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = ~(1U << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * NUM_OF_BITS_IN_HW); ) { + WordMem16= lhuea(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u16)RotateLeft(~Val, NUM_OF_BITS_IN_HW)); + I = I + NUM_OF_BYTES_IN_HW; + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * Words);) { + /* write memory location */ + Val = (u16) (~((INTPTR)((Addr+I)))); + shea(Addr+I, Val); + I = I + NUM_OF_BYTES_IN_HW; + } + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_HW*Words); ) { + /* read memory location */ + WordMem16 = lhuea(Addr+I); + Val = (u16) (~((INTPTR) ((Addr+I)))); + if ((WordMem16 ^ Val) != 0x0000U) { + Status = -1; + goto End_Label; + } + I = I + NUM_OF_BYTES_IN_HW; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + if (Pattern == (u16)0) { + Val = 0xDEADU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed pattern + */ + + for (I = 0U; I < (2*Words);) { + /* write memory location */ + shea(Addr+I, Val); + I = I + NUM_OF_BYTES_IN_HW; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed pattern + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * Words);) { + /* read memory location */ + WordMem16=lhuea(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + I = I + NUM_OF_BYTES_IN_HW; + } + } +End_Label: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide memory test. +* +* @param Addrlow: lower 32 bit address of memory to be tested. +* @param Addrhigh: upper 32 bit address of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: test type selected. See xil_testmem.h for possible +* values. +* +* @return +* - 0 is returned for a pass +* - 1 is returned for a failure +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem32(u32 Addrlow, u32 Addrhigh, u32 Words, u32 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u32 Val; + u32 WordMem32; + s32 Status = 0; + u64 Addr = (Addrlow + ((u64)Addrhigh << 32)); + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= (u8)XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'XIL_TESTMEM_INIT_VALUE' + */ + for (I = 0U; I <(NUM_OF_BYTES_IN_WORD * Words);) { + swea(Addr+I, Val); + Val++; + I = I + NUM_OF_BYTES_IN_WORD; + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = XIL_TESTMEM_INIT_VALUE; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (I = 0U; I < ( NUM_OF_BYTES_IN_WORD * Words);) { + WordMem32 = lwea(Addr+I); + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val++; + I = I + NUM_OF_BYTES_IN_WORD; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_WORD; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (1U << j); + + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_WORD * NUM_OF_BITS_IN_WORD);) { + /* write memory location */ + swea(Addr+I, Val); + Val = (u32) RotateLeft(Val, NUM_OF_BITS_IN_WORD); + I = I + NUM_OF_BYTES_IN_WORD; + } + + /* + * Restore the reference 'val' to the + * initial value + */ + Val = 1U << j; + + /* Read the values from each location that was + * written */ + for (I = 0U; I < ((u32)32 * NUM_OF_BYTES_IN_WORD);) { + /* read memory location */ + + WordMem32 = lwea(Addr+I); + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val = (u32)RotateLeft(Val, NUM_OF_BITS_IN_WORD); + I = I + NUM_OF_BYTES_IN_WORD; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible + * initial test Patterns for walking zeros test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_WORD; j++) { + + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = ~(1U << j); + + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (NUM_OF_BITS_IN_WORD * NUM_OF_BYTES_IN_WORD);) { + /* write memory location */ + swea(Addr+I, Val); + Val = ~((u32)RotateLeft(~Val, NUM_OF_BITS_IN_WORD)); + I = I + NUM_OF_BYTES_IN_WORD; + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + + Val = ~(1U << j); + + /* Read the values from each location that was + * written */ + for (I = 0U; I < (NUM_OF_BITS_IN_WORD * NUM_OF_BYTES_IN_WORD);) { + /* read memory location */ + WordMem32 = lwea(Addr+I); + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u32)RotateLeft(~Val, NUM_OF_BITS_IN_WORD)); + I = I + NUM_OF_BYTES_IN_WORD; + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < (NUM_OF_BYTES_IN_WORD * Words);) { + /* write memory location */ + Val = (u32) (~((INTPTR) (Addr+I))); + swea(Addr+I, Val); + I = I + NUM_OF_BYTES_IN_WORD; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_WORD * Words);) { + /* Read the location */ + WordMem32 = lwea(Addr+I); + Val = (u32) (~((INTPTR) (Addr+I))); + + if ((WordMem32 ^ Val) != 0x00000000U) { + Status = -1; + goto End_Label; + } + I = I + NUM_OF_BYTES_IN_WORD; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u32)0) { + Val = 0xDEADBEEFU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed Pattern + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_WORD * Words);) { + /* write memory location */ + swea(Addr+I, Val); + I = I + NUM_OF_BYTES_IN_WORD; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_WORD * Words);) { + + /* read memory location */ + + WordMem32 = lwea(Addr+I); + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + I = I + NUM_OF_BYTES_IN_WORD; + } + } + +End_Label: + return Status; +} + +#else +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: test type selected. See xil_testmem.h for possible +* values. +* +* @return +* - 0 is returned for a pass +* - 1 is returned for a failure +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest) +{ + u32 i; + u32 j; + u32 Val; + u32 FirtVal; + u32 WordMem32; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= (u8)XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (i = 0U; i < Words; i++) { + Addr[i] = Val; + Val++; + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (i = 0U; i < Words; i++) { + WordMem32 = Addr[i]; + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < (u32)32; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (1UL << j); + + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (i = 0U; i < (u32)32; i++) { + /* write memory location */ + Addr[i] = Val; + Val = (u32) RotateLeft(Val, 32U); + } + + /* + * Restore the reference 'val' to the + * initial value + */ + Val = 1UL << j; + + /* Read the values from each location that was + * written */ + for (i = 0U; i < (u32)32; i++) { + /* read memory location */ + + WordMem32 = Addr[i]; + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val = (u32)RotateLeft(Val, 32U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible + * initial test Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)32; j++) { + + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = ~(1UL << j); + + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (i = 0U; i < (u32)32; i++) { + /* write memory location */ + Addr[i] = Val; + Val = ~((u32)RotateLeft(~Val, 32U)); + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + + Val = ~(1UL << j); + + /* Read the values from each location that was + * written */ + for (i = 0U; i < (u32)32; i++) { + /* read memory location */ + WordMem32 = Addr[i]; + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u32)RotateLeft(~Val, 32U)); + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Val = ~(u32) (UINTPTR) &Addr[i]; + Addr[i] = Val; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (i = 0U; i < Words; i++) { + /* Read the location */ + WordMem32 = Addr[i]; + Val = ~(u32) (UINTPTR) &Addr[i]; + + if ((WordMem32 ^ Val) != 0x00000000U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u32)0) { + Val = 0xDEADBEEFU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed Pattern + */ + + for (i = 0U; i < Words; i++) { + /* write memory location */ + Addr[i] = Val; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (i = 0U; i < Words; i++) { + + /* read memory location */ + + WordMem32 = Addr[i]; + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant Pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest) +{ + u32 i; + u32 j; + u16 Val; + u16 FirtVal; + u16 WordMem16; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + /* + * selectthe proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Addr[i] = Val; + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference val + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem16 = Addr[i]; + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking ones test + */ + + for (j = 0U; j < (u32)16; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (u16)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (i = 0U; i < (u32)16; i++) { + /* write memory location */ + Addr[i] = Val; + Val = (u16)RotateLeft(Val, 16U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u16)((u32)1 << j); + /* Read the values from each location that was written */ + for (i = 0U; i < (u32)16; i++) { + /* read memory location */ + WordMem16 = Addr[i]; + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = (u16)RotateLeft(Val, 16U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)16; j++) { + /* + * Generate an initial value for walking ones + * test to test for bad + * data bits + */ + + Val = (u16) (~((u16)1U << j)); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (i = 0U; i < (u32)16; i++) { + /* write memory location */ + Addr[i] = Val; + Val = ~((u16)RotateLeft(~((u32)Val), 16U)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u16) (~((u16)1U << j)); + /* Read the values from each location that was written */ + for (i = 0U; i < (u32)16; i++) { + /* read memory location */ + WordMem16 = Addr[i]; + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u16)RotateLeft(~((u32)Val), 16U)); + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Val = ~(u16) (UINTPTR) &Addr[i]; + Addr[i] = Val; + } + /* + * Check every word within the words + * of tested memory + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem16 = Addr[i]; + Val = ~(u16) (UINTPTR) &Addr[i]; + if ((WordMem16 ^ Val) != 0x0000U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + if (Pattern == (u16)0) { + Val = 0xDEADU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed pattern + */ + + for (i = 0U; i < Words; i++) { + /* write memory location */ + Addr[i] = Val; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed pattern + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem16 = Addr[i]; + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest) +{ + u32 i; + u32 j; + u8 Val; + u8 FirtVal; + u8 WordMem8; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + /* + * select the proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Addr[i] = Val; + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem8 = Addr[i]; + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < (u32)8; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + Val = (u8)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + for (i = 0U; i < (u32)8; i++) { + /* write memory location */ + Addr[i] = Val; + Val = (u8)RotateLeft(Val, 8U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u8)((u32)1 << j); + /* Read the values from each location that was written */ + for (i = 0U; i < (u32)8; i++) { + /* read memory location */ + WordMem8 = Addr[i]; + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val = (u8)RotateLeft(Val, 8U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)8; j++) { + /* + * Generate an initial value for walking ones test to test + * for bad data bits + */ + Val = (u8) (~(1U << j)); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + for (i = 0U; i < (u32)8; i++) { + /* write memory location */ + Addr[i] = Val; + Val = ~((u8)RotateLeft(~((u32)Val), 8U)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u8) (~(1U << j)); + /* Read the values from each location that was written */ + for (i = 0U; i < (u32)8; i++) { + /* read memory location */ + WordMem8 = Addr[i]; + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + + Val = ~((u8)RotateLeft(~((u32)Val), 8U)); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Val = ~(u8) (UINTPTR) &Addr[i]; + Addr[i] = Val; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem8 = Addr[i]; + Val = ~(u8) (UINTPTR) &Addr[i]; + if ((WordMem8 ^ Val) != 0x00U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u8)0) { + Val = 0xA5U; + } + else { + Val = Pattern; + } + /* + * Fill the memory with fixed Pattern + */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Addr[i] = Val; + } + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem8 = Addr[i]; + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} +#endif + +/*****************************************************************************/ +/** +* +* @brief Rotates the provided value to the left one bit position +* +* @param Input is value to be rotated to the left +* @param Width is the number of bits in the input data +* +* @return The resulting unsigned long value of the rotate left +* +* +*****************************************************************************/ +static u32 RotateLeft(u32 Input, u8 Width) +{ + u32 Msb; + u32 ReturnVal; + u32 WidthMask; + u32 MsbMask; + u32 LocalInput = Input; + + /* + * set up the WidthMask and the MsbMask + */ + + MsbMask = 1UL << (Width - 1U); + + WidthMask = (MsbMask << (u32)1) - (u32)1; + + /* + * set the Width of the Input to the correct width + */ + + LocalInput = LocalInput & WidthMask; + + Msb = LocalInput & MsbMask; + + ReturnVal = LocalInput << 1U; + + if (Msb != 0x00000000U) { + ReturnVal = ReturnVal | (u32)0x00000001; + } + + ReturnVal = ReturnVal & WidthMask; + + return ReturnVal; + +} + +#ifdef ROTATE_RIGHT +/*****************************************************************************/ +/** +* +* @brief Rotates the provided value to the right one bit position +* +* @param Input: value to be rotated to the right +* @param Width: number of bits in the input data +* +* @return +* The resulting u32 value of the rotate right +* +*****************************************************************************/ +static u32 RotateRight(u32 Input, u8 Width) +{ + u32 Lsb; + u32 ReturnVal; + u32 WidthMask; + u32 MsbMask; + u32 LocalInput = Input; + /* + * set up the WidthMask and the MsbMask + */ + + MsbMask = 1U << (Width - 1U); + + WidthMask = (MsbMask << 1U) - 1U; + + /* + * set the width of the input to the correct width + */ + + LocalInput = LocalInput & WidthMask; + + ReturnVal = LocalInput >> 1U; + + Lsb = LocalInput & 0x00000001U; + + if (Lsb != 0x00000000U) { + ReturnVal = ReturnVal | MsbMask; + } + + ReturnVal = ReturnVal & WidthMask; + + return ReturnVal; + +} +#endif /* ROTATE_RIGHT */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_testmem.h b/bsp_z7/ps7_cortexa9_0/include/xil_testmem.h new file mode 100644 index 0000000..7e29233 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_testmem.h @@ -0,0 +1,165 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testmem.h +* @addtogroup common_test_utils Test Utilities for Memory and Caches +* +* - Cache test: xil_testcache.h contains utility functions to test cache. +* +* - I/O test: The Xil_testio.h file contains endian related memory IO functions. A +* subset of the memory tests can be selected or all of the tests can be run in order. +* If there is an error detected by a subtest, the test stops and the failure code is +* returned. Further tests are not run even if all of the tests are selected. +* +* - Memory test: The xil_testmem.h file contains utility functions to test memory. +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests are selected. +* +* +* Following list describes the supported memory tests: +* +* - XIL_TESTMEM_ALLMEMTESTS: This test runs all of the subtests. +* +* - XIL_TESTMEM_INCREMENT: This test +* starts at 'XIL_TESTMEM_INIT_VALUE' and uses the incrementing value as the +* test value for memory. +* +* - XIL_TESTMEM_WALKONES: Also known as the Walking ones test. This test +* uses a walking '1' as the test value for memory. +* @code +* location 1 = 0x00000001 +* location 2 = 0x00000002 +* ... +* @endcode +* +* - XIL_TESTMEM_WALKZEROS: Also known as the Walking zero's test. +* This test uses the inverse value of the walking ones test +* as the test value for memory. +* @code +* location 1 = 0xFFFFFFFE +* location 2 = 0xFFFFFFFD +* ... +*@endcode +* +* - XIL_TESTMEM_INVERSEADDR: Also known as the inverse address test. +* This test uses the inverse of the address of the location under test +* as the test value for memory. +* +* - XIL_TESTMEM_FIXEDPATTERN: Also known as the fixed pattern test. +* This test uses the provided patters as the test value for memory. +* If zero is provided as the pattern the test uses '0xDEADBEEF". +* +* @warning +* The tests are DESTRUCTIVE. Run before any initialized memory spaces +* have been set up. +* The address provided to the memory tests is not checked for +* validity except for the NULL case. It is possible to provide a code-space +* pointer for this test to start with and ultimately destroy executable code +* causing random failures. +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 7.5   mus  03/10/21 Added new set of Xil_TestMem32, Xil_TestMem16 and
+*                     Xil_TestMem8 APIs to support memory test for memory
+*                     regions mapped at extended addresses
+*                     (addresses > 4 GB). These new set of APIs would be
+*                     compiled only for 32 bit Microblaze processor, if
+*                     XPAR_MICROBLAZE_ADDR_SIZE is greater than 32.
+*                     It fixes CR#1089129.
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_TESTMEM_H /* prevent circular inclusions */ +#define XIL_TESTMEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/* xutil_memtest defines */ + +#define XIL_TESTMEM_INIT_VALUE 1U + +/** @name Memory subtests + * @{ + */ +/** + * See the detailed description of the subtests in the file description. + */ +#define XIL_TESTMEM_ALLMEMTESTS 0x00U +#define XIL_TESTMEM_INCREMENT 0x01U +#define XIL_TESTMEM_WALKONES 0x02U +#define XIL_TESTMEM_WALKZEROS 0x03U +#define XIL_TESTMEM_INVERSEADDR 0x04U +#define XIL_TESTMEM_FIXEDPATTERN 0x05U +#define XIL_TESTMEM_MAXTEST XIL_TESTMEM_FIXEDPATTERN +/* @} */ + +#if !defined(__aarch64__) && !defined(__arch64__) +#define NUM_OF_BITS_IN_BYTE 8U +#define NUM_OF_BYTES_IN_HW 2U +#define NUM_OF_BITS_IN_HW 16U +#define NUM_OF_BYTES_IN_WORD 4U +#define NUM_OF_BITS_IN_WORD 32U +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/** + *@endcond + */ + +/************************** Function Prototypes ******************************/ + +/* xutil_testmem prototypes */ +#if defined(__MICROBLAZE__) && !defined(__arch64__) && (XPAR_MICROBLAZE_ADDR_SIZE > 32) +extern s32 Xil_TestMem32(u32 AddrLow, u32 AddrHigh, u32 Words, u32 Pattern, u8 Subtest); +extern s32 Xil_TestMem16(u32 AddrLow, u32 AddrHigh, u32 Words, u16 Pattern, u8 Subtest); +extern s32 Xil_TestMem8(u32 AddrLow, u32 AddrHigh, u32 Words, u8 Pattern, u8 Subtest); +#else +extern s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest); +extern s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest); +extern s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_types.h b/bsp_z7/ps7_cortexa9_0/include/xil_types.h new file mode 100644 index 0000000..100bddd --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_types.h @@ -0,0 +1,222 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_types.h +* +* @addtogroup common_types Basic Data types for Xilinx® Software IP +* +* The xil_types.h file contains basic types for Xilinx software IP. These data types +* are applicable for all processors supported by Xilinx. +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 3.03a sdm  05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros
+* 5.00 	pkp  05/29/14 Made changes for 64 bit architecture
+*	srt  07/14/14 Use standard definitions from stdint.h and stddef.h
+*		      Define LONG and ULONG datatypes and mask values
+* 7.00  mus  01/07/19 Add cpp extern macro
+* 7.1   aru  08/19/19 Shift the value in UPPER_32_BITS only if it
+*                     is 64-bit processor
+* 8.1    dp  12/23/22 Updated UINTPTR and INTPTR to point to 64bit data types
+*                     incase of microblaze 32-bit with extended address enabled
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ +#ifndef XIL_TYPES_H /* prevent circular inclusions */ +#define XIL_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#define XIL_COMPONENT_IS_READY 0x11111111U /**< In device drivers, This macro will be + assigend to "IsReady" member of driver + instance to indicate that driver + instance is initialized and ready to use. */ +#define XIL_COMPONENT_IS_STARTED 0x22222222U /**< In device drivers, This macro will be assigend to + "IsStarted" member of driver instance + to indicate that driver instance is + started and it can be enabled. */ + +/* @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XBASIC_TYPES_H +/* + * guarded against xbasic_types.h. + */ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +/** @}*/ +#define __XUINT64__ +typedef struct +{ + u32 Upper; + u32 Lower; +} Xuint64; + + +/*****************************************************************************/ +/** +* @brief Return the most significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The upper 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_MSW(x) ((x).Upper) + +/*****************************************************************************/ +/** +* @brief Return the least significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The lower 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_LSW(x) ((x).Lower) + +#endif /* XBASIC_TYPES_H */ + +/* + * xbasic_types.h does not typedef s* or u64 + */ +/** @{ */ +typedef char char8; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint64_t u64; +typedef int sint32; + +#if defined(__MICROBLAZE__) && !defined(__arch64__) && \ + (XPAR_MICROBLAZE_ADDR_SIZE > 32) +typedef uint64_t UINTPTR; +typedef int64_t INTPTR; +#else +typedef uintptr_t UINTPTR; +typedef intptr_t INTPTR; +#endif + +typedef ptrdiff_t PTRDIFF; +/** @}*/ +#if !defined(LONG) || !defined(ULONG) +typedef long LONG; +typedef unsigned long ULONG; +#endif + +#define ULONG64_HI_MASK 0xFFFFFFFF00000000U +#define ULONG64_LO_MASK ~ULONG64_HI_MASK + +#else +#include +#endif + +/** @{ */ +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/** + * This data type defines an exception handler for a processor. + * The argument points to the instance of the component + */ +typedef void (*XExceptionHandler) (void *InstancePtr); + +/** + * @brief Returns 32-63 bits of a number. + * @param n : Number being accessed. + * @return Bits 32-63 of number. + * + * @note A basic shift-right of a 64- or 32-bit quantity. + * Use this to suppress the "right shift count >= width of type" + * warning when that quantity is 32-bits. + */ +#if defined (__aarch64__) || defined (__arch64__) +#define UPPER_32_BITS(n) ((u32)(((n) >> 16) >> 16)) +#else +#define UPPER_32_BITS(n) 0U +#endif +/** + * @brief Returns 0-31 bits of a number + * @param n : Number being accessed. + * @return Bits 0-31 of number + */ +#define LOWER_32_BITS(n) ((u32)(n)) + +/** + * @brief Returns 0-31 bits of a number . + * @param n : Number being accessed. + * @return Bits 0-31 of number. + */ +#if defined (__aarch64__) || defined (__arch64__) +#define LEFT_SHIFT_BY_32_BITS(n) (u64)(((u64)n) << 32) +#else +#define LEFT_SHIFT_BY_32_BITS(n) 0U +#endif + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** + *@endcond + */ +/** +* @} End of "addtogroup common_types". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_util.c b/bsp_z7/ps7_cortexa9_0/include/xil_util.c new file mode 100644 index 0000000..b056c3c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_util.c @@ -0,0 +1,1377 @@ +/******************************************************************************/ +/** +* Copyright (c) 2019 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* @file xil_util.c +* +* xil_util.c file contains xil utility functions +* Except few functions, most of these functions are wrappers to standard functions. +* The standard string functions do not validate the input and that results into +* buffer overflows. To avoid it, the wrapper function validates the input and +* then passed to standard function. There are few constant time functions +* ( xxx_CT() ) which are used to compare the data in constant time. +* The constant time functions should be used while comparing secure data +* like password, keys which prevent disclosing of the data using +* timing analysis. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+* 7.2   nava     08/01/20 Updated Xil_WaitForEvent() and Xil_WaitForEvents(()
+*                         API to use microsecond timeout instead of a free
+*                         counter.
+* 7.3   kal      06/30/20 Converted Xil_Ceil macro to API.
+*       rpo      08/19/20 Added function for read,modify,write
+*       kal      09/22/20 Changed the param type from const char to const char*
+*                         to avoid copying key onto stack
+*       td       10/16/20 Added Xil_Strcpy, Xil_Strcat, Xil_SecureMemCpy and
+*                         Xil_MemCmp functions
+* 7.4   am       11/26/20 Added Xil_StrCpyRange function
+* 7.6   kpt      07/15/21 Added Xil_SecureZeroize function
+* 7.7   kpt      11/09/21 Added Xil_SMemCmp, Xil_SMemCmp_CT, Xil_SMemCpy,
+*                         Xil_SMemSet, Xil_SStrCat, Xil_SStrCmp, Xil_SStrCmp_CT
+*                         Xil_SStrCpy functions
+*       kpt      11/25/21 Added strnlen function to fix ARMCC compilation
+*                         failure
+* 7.7	sk	 01/10/22 Update functions return type and update RetVal variable
+* 			  data type to fix misra_c_2012_directive_4_6 misrac
+* 			  violations.
+* 7.7	sk	 01/10/22 Update values from signed to unsigned to fix
+* 			  misra_c_2012_rule_10_4 violation.
+* 7.7	sk	 01/10/22 Add explicit parentheses to fix misra_c_2012_rule_12_1
+* 			  violation.
+* 7.7	sk	 01/10/22 Typecast character strings to u8 to fix misra_c_2012_rule_
+* 			  10_3 violation.
+* 7.7	sk	 01/10/22 Modify the code to reduce multiple break statements
+* 			  and fix misra_c_2012_rule_15_4 violation.
+* 7.7	sk	 01/10/22 Modify Xil_SMemCmp_CT and Xil_SMemCmp function argument
+* 			  type to fix misra_c_2012_rule_8_3 violation.
+* 7.7	sk	 01/10/22 Update conditional expression to fix misra_c_2012_rule_14_4
+* 			  violation.
+*       bm       01/20/22 Fix compilation warnings in Xil_SMemCpy
+*       mmd      02/28/22 Added Xil_SMemMove function
+* 8.0	sk	 03/02/22 Add explicit parentheses to fix misra_c_2012_rule_12_1
+* 			  violation.
+* 8.0	sk	 03/02/22 Add const qualifier to varaibles to fix misra_c_2012_rule_
+* 			  11_8 violation.
+* 8.0	sk	 03/02/22 Typecast expression with unsigned int to fix
+* 			  misra_c_2012_rule_10_7 violation.
+* 8.0	sk	 03/02/22 Typecast variables with unsigned or signed to fix misra_c
+* 			  _2012_rule_10_3 violation.
+* 8.0	sk	 03/02/22 Add const to unmodified variable to fix misra_c_2012
+* 			  _rule_8_13 violation.
+* 8.0	sk	 03/02/22 Typecast the function with void as return type is
+* 			  not used and fix misra_c_2012_rule_17_7 violation.
+* 8.0	sk	 03/02/22 Remove increment operations during comparision to
+* 			  fix misra_c_2012_rule_13_3 violation.
+* 8.0	sk	 03/02/22 Update values from signed to unsigned to fix
+* 			  misra_c_2012_rule_10_4 violation.
+* 8.0	sk	 03/17/22 Add const to unmodified pointer variable to fix misra_c
+*			  _2012_rule_8_13 violation.
+* 8.0   adk      04/18/22 Added Xil_WaitForEventSet function.
+*       adk	 07/15/22 Updated the Xil_WaitForEventSet() API to
+*			  support variable number of events.
+*	ssc	 08/25/22 Added Xil_SecureRMW32 API
+* 8.1	sa       09/29/22 Change the type of first argument passed to Xil_WaitForEvent
+*			  API from u32 to UINTPTR for supporting 64 bit addressing.
+* 8.1   sa       10/20/22 Change the type of first argument passed to Xil_WaitForEvents
+*                         API from u32 to UINTPTR for supporting 64 bit addressing.
+* 8.1   akm      01/02/23 Added Xil_RegisterPlmHandler() & Xil_PlmStubHandler() APIs.
+* 
+* +*****************************************************************************/ + +/****************************** Include Files *********************************/ +#include "xil_util.h" +#include "sleep.h" + +/************************** Constant Definitions ****************************/ +#define MAX_NIBBLES 8U + +/************************** Function Prototypes *****************************/ +void (*fptr)(void) = NULL; + +#ifdef __ARMCC_VERSION +/******************************************************************************/ +/** + * + * This API returns the length of the input string + * + * @param StartPtr is the pointer to the input string + * @param StrSize is the maximum length of the input string + * + * @return Returns the length of the input string + * + ******************************************************************************/ +static size_t strnlen (const char *StartPtr, size_t StrSize) +{ + const char *EndPtr = StartPtr; + size_t StrLen = 0U; + + EndPtr = memchr(StartPtr, '\0', StrSize); + if (EndPtr == NULL) { + StrLen = StrSize; + } + else { + StrLen = (size_t) (EndPtr - StartPtr); + } + + return StrLen; +} +#endif + +/******************************************************************************/ +/** +* This API ceils the provided float value. +* +* @param Value is a float variable which has to ceiled to nearest +* integer. +* +* @return Returns ceiled value. +* +*******************************************************************************/ +s32 Xil_Ceil(float Value) +{ + s32 Result = Value; + + if (Value > Result) { + Result = Result + 1; + } + + return Result; +} + +/****************************************************************************/ +/** + * Converts the char into the equivalent nibble. + * Ex: 'a' -> 0xa, 'A' -> 0xa, '9'->0x9 + * + * @param InChar - Input character to be converted to nibble. + * Valid characters are between 0-9, a-f, A-F + * @param Num - Memory location where nibble is to be stored + * + * @return + * XST_SUCCESS - Character converted to nibble + * XST_FAILURE - Invalid input character + * + * @note None. + * + *****************************************************************************/ + +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num) +{ + u32 Status; + + /* Convert the char to nibble */ + if ((InChar >= (u8)'0') && (InChar <= (u8)'9')) { + *Num = InChar - (u8)'0'; + Status = XST_SUCCESS; + } + else if ((InChar >= (u8)'a') && (InChar <= (u8)'f')) { + *Num = InChar - (u8)'a' + 10U; + Status = XST_SUCCESS; + } + else if ((InChar >= (u8)'A') && (InChar <= (u8)'F')) { + *Num = InChar - (u8)'A' + 10U; + Status = XST_SUCCESS; + } + else { + Status = XST_FAILURE; + } + + return Status; +} + +/****************************************************************************/ +/* + * Converts the string into the equivalent Hex buffer. + * Ex: "abc123" -> {0xab, 0xc1, 0x23} + * + * @param Str - Pointer to string to be converted to Hex. + * Accepted characters in string are between 0-9, a-f and A-F + * @param Buf - Pointer to memory location where converted hex values are to + * be stored. + * @param Len - Length of input string + * + * @return + * XST_SUCCESS - Input string is converted to hex + * XST_FAILURE - Invalid character in inpit string + * + * @note None. + * + *****************************************************************************/ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len) +{ + u32 Status = XST_FAILURE; + u8 ConvertedLen = 0U, index = 0U; + u8 Nibble[MAX_NIBBLES] = {0U}; + u8 i; + + while (ConvertedLen < Len) { + for (i = 0U; i < MAX_NIBBLES; i++) { + Status = Xil_ConvertCharToNibble((u8)Str[ConvertedLen], + &Nibble[i]); + ConvertedLen = ConvertedLen +1U; + if (Status != XST_SUCCESS) { + /* Error converting char to nibble */ + goto END; + } + } + + buf[index] = (((u32)Nibble[0] << (u8)28U) | ((u32)Nibble[1] << (u8)24U) | + ((u32)Nibble[2] << (u8)20U) | ((u32)Nibble[3] << (u8)16U) | + ((u32)Nibble[4] << (u8)12U) | ((u32)Nibble[5] << (u8)8U) | + ((u32)Nibble[6] << (u8)4U) | (u32)Nibble[7]); + index++; + } +END: + return Status; +} + +#ifdef VERSAL_PLM +/****************************************************************************/ +/* + * Register PLM Alive Handler. + * + * @param PlmAlive - Pointer to PlmAlive API. + * + * @return None. + * + *****************************************************************************/ +void Xil_RegisterPlmHandler(void (*PlmAlive) (void)) { + fptr = PlmAlive; +} + +/****************************************************************************/ +/* + * PLM Stub Handler called while waiting for event. + * + * @param None. + * + * @return None. + * + *****************************************************************************/ +void Xil_PlmStubHandler(void) { + if (fptr != NULL) { + fptr(); + } +} +#endif + +/****************************************************************************/ +/* + * Waits for the event + * + * @param RegAddr - Address of register to be checked for event(s) occurrence + * @param EventMask - Mask indicating event(s) to be checked + * @param Event - Specific event(s) value to be checked + * @param Timeout - Max number of microseconds to wait for an event(s). + * + * @return + * XST_SUCCESS - On occurrence of the event(s). + * XST_FAILURE - Event did not occur before counter reaches 0 + * + * @note None. + * + *****************************************************************************/ +u32 Xil_WaitForEvent(UINTPTR RegAddr, u32 EventMask, u32 Event, u32 Timeout) +{ + u32 EventStatus; + u32 PollCount = Timeout; + u32 Status = XST_FAILURE; + + while(PollCount > 0U) { + EventStatus = Xil_In32(RegAddr) & EventMask; + if (EventStatus == Event) { + Status = XST_SUCCESS; + break; + } + PollCount--; +#ifdef VERSAL_PLM + Xil_PlmStubHandler(); +#endif + usleep(1U); + } + + return Status; +} + + +/******************************************************************************/ +/** + * Waits for the events. Returns on occurrence of first event / timeout. + * + * @param EventsRegAddr - Address of register to be checked for event(s) + * occurrence + * @param EventsMask - Mask indicating event(s) to be checked + * @param WaitEvents - Specific event(s) to be checked + * @param Timeout - Max number of microseconds to wait for an event(s). + * @param Events - Mask of Events occurred returned in memory pointed by + * this variable + * + * @return + * XST_SUCCESS - On occurrence of the event(s). + * XST_FAILURE - Event did not occur before counter reaches 0 + * + ******************************************************************************/ +u32 Xil_WaitForEvents(UINTPTR EventsRegAddr, u32 EventsMask, u32 WaitEvents, + u32 Timeout, u32* Events) +{ + u32 EventStatus; + u32 PollCount = Timeout; + u32 Status = XST_TIMEOUT; + + *Events = 0x00; + do { + EventStatus = Xil_In32(EventsRegAddr); + EventStatus &= EventsMask; + if((EventStatus & WaitEvents) != 0U) { + Status = XST_SUCCESS; + *Events = EventStatus; + break; + } + PollCount--; +#ifdef VERSAL_PLM + Xil_PlmStubHandler(); +#endif + usleep(1U); + } + while(PollCount > 0U); + + return Status; +} + +/******************************************************************************/ +/** + * Checks whether the passed character is a valid hex digit + * + * @param Ch - Pointer to the input character + * + * @return + * XST_SUCCESS - on valid hex digit + * XST_FAILURE - on invalid hex digit + * + * @note None. + * + ******************************************************************************/ +u32 Xil_IsValidHexChar(const char *Ch) +{ + u32 Status = XST_FAILURE; + + if(NULL == Ch) { + goto END; + } + if (((*Ch >= '0') && (*Ch <='9'))|| + ((*Ch >= 'a') && (*Ch <='f'))|| + ((*Ch >= 'A') && (*Ch <='F'))) { + + Status = XST_SUCCESS; + } +END: + return Status; +} + +/******************************************************************************/ +/** + * Validate the input string contains only hexadecimal characters + * + * @param HexStr - Pointer to string to be validated + * + * @return + * XST_SUCCESS - On valid input hex string + * XST_INVALID_PARAM - On invalid length of the input string + * XST_FAILURE - On non hexadecimal character in string + * + * @note None + * + ******************************************************************************/ +u32 Xil_ValidateHexStr(const char *HexStr) +{ + u32 Idx; + u32 Len; + u32 Status = XST_INVALID_PARAM; + + if(NULL == HexStr) { + goto END; + } + + Len = Xil_Strnlen(HexStr, XIL_MAX_HEX_STR_LEN + 1U); + if (Len > XIL_MAX_HEX_STR_LEN) { + goto END; + } + + for (Idx = 0U; Idx < Len; Idx++) { + Status = Xil_IsValidHexChar(&HexStr[Idx]); + if (Status != XST_SUCCESS) { + break; + } + } + +END: + return Status; +} + +/****************************************************************************/ +/** + * Converts the string into the equivalent Hex buffer. + * Ex: "abc123" -> {0xab, 0xc1, 0x23} + * + * @param Str is a Input String. Will support the lower and upper case values. + * Value should be between 0-9, a-f and A-F + * @param Buf is Output buffer. + * @param Len of the input string. Should have even values + * + * @return + * - XST_SUCCESS no errors occurred. + * - XST_FAILURE an error when input parameters are not valid + * - an error when input buffer has invalid values + * + * TDD Test Cases: + * ---Initialization--- + * Len is odd + * Len is zero + * Str is NULL + * Buf is NULL + * ---Functionality--- + * Str input with only numbers + * Str input with All values in A-F + * Str input with All values in a-f + * Str input with values in a-f, 0-9, A-F + * Str input with values in a-z, 0-9, A-Z + * Boundary Cases + * Memory Bounds of buffer checking + * ****************************************************************************/ +u32 Xil_ConvertStringToHexBE(const char *Str, u8 *Buf, u32 Len) +{ + u32 ConvertedLen; + u8 LowerNibble = 0U; + u8 UpperNibble = 0U; + u32 Status = (u32)XST_FAILURE; + + if ((Str == NULL) || (Buf == NULL)) { + Status = (u32)XST_INVALID_PARAM; + goto END; + } + + if ((Len == 0U) || ((Len % XIL_SIZE_OF_BYTE_IN_BITS) != 0U)) { + Status = (u32)XST_INVALID_PARAM; + goto END; + } + + if(Len != (strlen(Str) * XIL_SIZE_OF_NIBBLE_IN_BITS)) { + Status = (u32)XST_INVALID_PARAM; + goto END; + } + + ConvertedLen = 0U; + while (ConvertedLen < (Len / XIL_SIZE_OF_NIBBLE_IN_BITS)) { + if ((Xil_ConvertCharToNibble(((u8)Str[ConvertedLen]),&UpperNibble) + == (u32)XST_SUCCESS) && (Xil_ConvertCharToNibble(((u8)Str[ConvertedLen+1U]), + &LowerNibble) == (u32)XST_SUCCESS)) { + Buf[ConvertedLen/2U] = + (UpperNibble << XIL_SIZE_OF_NIBBLE_IN_BITS) | + LowerNibble; + } + else { + Status = (u32)XST_INVALID_PARAM; + goto END; + } + ConvertedLen += 2U; + } + Status = (u32)XST_SUCCESS; +END: + return Status; +} + +/******************************************************************************/ +/** + * Converts the string into the equivalent Hex buffer. + * Ex: "abc123" -> {0x23, 0xc1, 0xab} + * + * @param Str - Input String to be converted to hex number in little + * endian format. Valid characters of input strin are between + * 0-9, a-f and A-F + * @param Buf - Pointer to memory location where converted hex numbers are to + * be stored. + * @param Len - Expected number of output bits + * + * @return + * XST_SUCCESS - Input string is converted to hex number(s) + * XST_FAILURE - Invalid input character detected in input string + * + * @note + * + ******************************************************************************/ +u32 Xil_ConvertStringToHexLE(const char *Str, u8 *Buf, u32 Len) +{ + u32 ConvertedLen; + u8 LowerNibble = 0U; + u8 UpperNibble = 0U; + u32 StrIndex; + u32 Status = XST_FAILURE; + + if ((NULL == Str) || (NULL == Buf)) { + Status = XST_INVALID_PARAM; + goto END; + } + + if ((Len == 0U) || ((Len % XIL_SIZE_OF_BYTE_IN_BITS) != 0U)) { + Status = XST_INVALID_PARAM; + goto END; + } + + if(Len != (strlen(Str) * XIL_SIZE_OF_NIBBLE_IN_BITS)) { + Status = XST_INVALID_PARAM; + goto END; + } + + StrIndex = (Len / XIL_SIZE_OF_BYTE_IN_BITS) - 1U; + ConvertedLen = 0U; + while (ConvertedLen < (Len / XIL_SIZE_OF_NIBBLE_IN_BITS)) { + if ((Xil_ConvertCharToNibble(((u8)Str[ConvertedLen]), + &UpperNibble) == XST_SUCCESS) && + (Xil_ConvertCharToNibble(((u8)Str[ConvertedLen + 1U]), + &LowerNibble) == XST_SUCCESS)) { + Buf[StrIndex] = + (UpperNibble << XIL_SIZE_OF_NIBBLE_IN_BITS) | + LowerNibble; + StrIndex = StrIndex - 1U; + } + else { + Status = XST_INVALID_PARAM; + goto END; + } + ConvertedLen += 2U; + } + + Status = XST_SUCCESS; +END: + return Status; +} + +/******************************************************************************/ +/** + * Returns the length of input string. + * + * @param Str - Input string + * @param MaxLen - Maximum expected length of the input string + * + * @return + * Returns length of the input string if length is less than MaxLen. + * Returns MaxLen if the length of the input string is >= MaxLen. + * + * @note + * + ******************************************************************************/ +u32 Xil_Strnlen(const char *Str, u32 MaxLen) +{ + const char *InStr = Str; + u32 StrLen = 0U; + + if (NULL == Str) { + goto END; + } + + while(StrLen < MaxLen) { + if ('\0' == *InStr) { + break; + } + StrLen++; + InStr++; + } + +END: + return StrLen; +} + +/*****************************************************************************/ +/** + * @brief This function will Read, Modify and Write to an address. + * + * @param Addr denotes Address + * @param Mask denotes the bits to be modified + * @param Value is the value to be written to the address + * + * @return None + * + *****************************************************************************/ +void Xil_UtilRMW32(u32 Addr, u32 Mask, u32 Value) +{ + u32 Val; + + Val = Xil_In32(Addr); + Val = (Val & (~Mask)) | (Mask & Value); + Xil_Out32(Addr, Val); +} + +/*****************************************************************************/ +/** + * @brief This functions copies source string to destination string. This + * function is a safe version of strcpy + * + * @param DestPtr is pointer to destination string + * @param SrcPtr is pointer to source string + * @param Size is the maximum number of bytes of the source string + * to be copied + * + * @return XST_SUCCESS on success and error code on failure + * + ******************************************************************************/ +int Xil_Strcpy(char *DestPtr, const char *SrcPtr, const u32 Size) +{ + int Status = XST_FAILURE; + u32 Count; + + if ((SrcPtr == NULL) || (DestPtr == NULL) || (Size == 0U)) { + goto END; + } + + for (Count = 0U; (SrcPtr[Count] != '\0') && (Count < Size); ++Count) { + DestPtr[Count] = SrcPtr[Count]; + } + if (Count == Size) { + DestPtr[0U] = '\0'; + goto END; + } + DestPtr[Count] = '\0'; + Status = XST_SUCCESS; + +END: + return Status; +} + +/****************************************************************************/ +/** + * @brief Copies specified range from source string to destination string + * + * @param Src is a pointer to source string + * @param Dest is a pointer to destination string + * @param From is 0 based index from where string copy starts + * @param To is 0 based index till which string is copied + * @param MaxSrcLen is the maximum length of source string + * @param MaxDstLen is the maximum length of destination string + * + * @return XST_SUCCESS on success + * XST_FAILURE on failure + * + * @note None + * + ****************************************************************************/ +int Xil_StrCpyRange(const u8 *Src, u8 *Dest, u32 From, u32 To, u32 MaxSrcLen, + u32 MaxDstLen) +{ + int Status = XST_FAILURE; + u32 SrcLength; + u32 Index; + + if ((Src == NULL) || (Dest == NULL)) { + Status = XST_INVALID_PARAM; + goto END; + } + + if ((To >= MaxSrcLen) || (To < From)) { + Status = XST_INVALID_PARAM; + goto END; + } + + if ((To - From + 1U) >= MaxDstLen) { + Status = XST_INVALID_PARAM; + goto END; + } + + SrcLength = Xil_Strnlen((const char *)Src, MaxSrcLen); + if (To >= SrcLength) { + Status = XST_INVALID_PARAM; + goto END; + } + + for (Index = From; (Index <= To) && (Src[Index]!= (u8)'\0'); Index++) { + Dest[Index - From] = Src[Index]; + } + + Dest[Index - From] = (u8)'\0'; + Status = XST_SUCCESS; + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function appends string2 to string1. This function is a safe + * version of strcat + * + * @param Str1Ptr is pointer to string1 + * @param Str2Ptr is pointer to string2 + * @param Size is the maximum number of bytes Str1 can hold + * + * @return XST_SUCCESS on success and error code on failure + * + ******************************************************************************/ +int Xil_Strcat(char* Str1Ptr, const char* Str2Ptr, const u32 Size) +{ + int Status = XST_FAILURE; + u32 Count = 0U; + u32 CountTmp = 0U; + + if ((Str1Ptr == NULL) || (Str2Ptr == NULL) || (Size == 0U)) { + goto END; + } + + while ((Count < Size) && (Str1Ptr[Count] != '\0')) { + Count++; + } + + while ((Str2Ptr[CountTmp] != '\0') && (Count < Size)) { + Str1Ptr[Count] = Str2Ptr[CountTmp]; + Count++; + CountTmp++; + } + if (Count == Size) { + Str1Ptr[0U] = '\0'; + goto END; + } + Str1Ptr[Count] = '\0'; + Status = XST_SUCCESS; + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function copies Len bytes from source memory to destination + * memory. If Len is greater than DestPtrLen, then DestPtr is also + * filled with 0s till DestPtrLen bytes and is considered as a failure. + * This function is a secure implementation of memcpy + * + * @param DestPtr is pointer to destination address + * @param DestPtrLen is the memory alloted to the destination buffer + * @param SrcPtr is pointer to source address + * @param Len is number of bytes to be copied + * + * @return XST_SUCCESS on success and error code on failure + * + ******************************************************************************/ +int Xil_SecureMemCpy(void * DestPtr, u32 DestPtrLen, const void * SrcPtr, u32 Len) +{ + int Status = XST_FAILURE; + u8 *Dest = (u8 *)DestPtr; + const u8 *Src = (const u8 *)SrcPtr; + + if ((DestPtr == NULL) || (SrcPtr == NULL)) { + goto END; + } + + if (Len > DestPtrLen) { + while (DestPtrLen != 0U) { + *Dest = 0U; + Dest++; + DestPtrLen--; + } + goto END; + } + + /* Loop and copy. */ + while (Len != 0U) { + *Dest = *Src; + Dest++; + Src++; + Len--; + } + Status = XST_SUCCESS; + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function compares Len bytes from memory1 and memory2. This + * function is a secure implementation of memcmp + * + * @param Buf1Ptr is pointer to memory1 + * @param Buf2Ptr is pointer to memory2 + * @param Len is number of byets to be compared + * + * @return 0 if contents of both the memory regions are same, + * -1 if first non-matching character has lower value in Buf1Ptr + * 1 if first non-matching character is greater value in Buf1Ptr + * + ******************************************************************************/ +int Xil_MemCmp(const void * Buf1Ptr, const void * Buf2Ptr, u32 Len) +{ + volatile int RetVal = 1; + const u8 *Buf1 = Buf1Ptr; + const u8 *Buf2 = Buf2Ptr; + u32 Size = Len; + + /* Assert validates the input arguments */ + if ((Buf1 == NULL) || (Buf2 == NULL) || (Len == 0x0U)) { + goto END; + } + + /* Loop and compare */ + while (Size != 0U) { + if (*Buf1 > *Buf2) { + RetVal = 1; + goto END; + } else if (*Buf1 < *Buf2) { + RetVal = -1; + goto END; + } else { + Buf1++; + Buf2++; + Size--; + } + } + + /* Make sure size is zero to know the whole of data is compared */ + if (Size == 0U) { + RetVal = 0; + } + +END: + return RetVal; +} + +/*****************************************************************************/ +/** + * @brief This function is used to zeroize the memory + * + * @param DataPtr Pointer to the memory which need to be zeroized. + * @param Length Length of the data in bytes. + * + * @return + * - XST_SUCCESS: If Zeroization is successful. + * - XST_FAILURE: If Zeroization is not successful. + ********************************************************************************/ +int Xil_SecureZeroize(u8 *DataPtr, const u32 Length) +{ + u32 Index; + int Status = XST_FAILURE; + + /* Clear the data */ + (void)memset(DataPtr, 0, Length); + + /* Read it back to verify */ + for (Index = 0U; Index < Length; Index++) { + if (DataPtr[Index] != 0x00U) { + goto END; + } + } + if (Index == Length) { + Status = XST_SUCCESS; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function compares two memory regions for specified number + * of bytes. This function takes size of two memory regions to + * make sure not to read from or write to out of bound memory + * region. + * + * @param Src1 - Pointer to first memory range + * @param Src1Size - Maximum size of first memory range + * @param Src2 - Pointer to second memory range + * @param Src2Size - Maximum size of second memory range + * @param CmpLen - Number of bytes to be compared + * + * @return + * XST_SUCCESS - If specified number of bytes matches + * XST_FAILURE - If there is a mistmatch found during comparison + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SMemCmp(const void *Src1, const u32 Src1Size, + const void *Src2, const u32 Src2Size, const u32 CmpLen) +{ + int Status = XST_FAILURE; + + if ((Src1 == NULL) || (Src2 == NULL)) { + Status = XST_INVALID_PARAM; + } + else if ((CmpLen == 0U) || (Src1Size < CmpLen) || (Src2Size < CmpLen)) { + Status = XST_INVALID_PARAM; + } + else { + Status = memcmp (Src1, Src2, CmpLen); + if (Status != 0) { + Status = XST_FAILURE; + } + } + + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function compares two memory regions for specified number + * of bytes. This function takes size of two memory regions to + * make sure not to read from or write to out of bound memory + * region. + * Note that this function compares till end to make it execute + * in constant time irrespective of the content of input memory. + * + * @param Src1 - Pointer to first memory range + * @param Src1Size - Maximum size of first memory range + * @param Src2 - Pointer to second memory range + * @param Src2Size - Maximum size of second memory range + * @param CmpLen - Number of bytes to be compared + * + * @return + * XST_SUCCESS - If specified number of bytes matches + * XST_FAILURE - If mistmatch + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SMemCmp_CT(const void *Src1, const u32 Src1Size, + const void *Src2, const u32 Src2Size, const u32 CmpLen) +{ + volatile int Status = XST_FAILURE; + volatile int StatusRedundant = XST_FAILURE; + volatile u32 Data = 0U; + volatile u32 DataRedundant = 0xFFFFFFFFU; + u32 Cnt = CmpLen; + const u8 *Src_1 = (const u8 *)Src1; + const u8 *Src_2 = (const u8 *)Src2; + + + if ((Src1 == NULL) || (Src2 == NULL)) { + Status = XST_INVALID_PARAM; + } + else if ((CmpLen == 0U) || (Src1Size < CmpLen) || (Src2Size < CmpLen)) { + Status = XST_INVALID_PARAM; + } + else { + while (Cnt >= sizeof(u32)) { + Data |= (*(const u32 *)Src_1 ^ *(const u32 *)Src_2); + DataRedundant &= ~Data; + Src_1 += sizeof(u32); + Src_2 += sizeof(u32); + Cnt -= sizeof(u32); + } + + while (Cnt > 0U) { + Data |= (u32)(*Src_1 ^ *Src_2); + DataRedundant &= ~Data; + Src_1++; + Src_2++; + Cnt--; + } + + if ((Data == 0U) && (DataRedundant == 0xFFFFFFFFU)) { + Status = XST_SUCCESS; + StatusRedundant = XST_SUCCESS; + } + } + + return (Status | StatusRedundant); +} + +/*****************************************************************************/ +/** + * @brief This is wrapper function to memcpy function. This function + * takes size of two memory regions to make sure not read from + * or write to out of bound memory region. + * + * @param Dest - Pointer to destination memory + * @param DestSize - Memory available at destination + * @param Src - Pointer to source memory + * @param SrcSize - Maximum data that can be copied from source + * @param CopyLen - Number of bytes to be copied + * + * @return + * XST_SUCCESS - Copy is successful + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SMemCpy(void *Dest, const u32 DestSize, + const void *Src, const u32 SrcSize, const u32 CopyLen) +{ + int Status = XST_FAILURE; + const u8 *Src8 = (const u8 *) Src; + const u8 *Dst8 = (u8 *) Dest; + void * volatile DestTemp = Dest; + const void * volatile SrcTemp = Src; + + if ((Dest == NULL) || (Src == NULL)) { + Status = XST_INVALID_PARAM; + } + else if ((CopyLen == 0U) || (DestSize < CopyLen) || (SrcSize < CopyLen)) { + Status = XST_INVALID_PARAM; + } + /* Return error for overlap string */ + else if ((Src8 < Dst8) && (&Src8[CopyLen - 1U] >= Dst8)) { + Status = XST_INVALID_PARAM; + } + else if ((Dst8 < Src8) && (&Dst8[CopyLen - 1U] >= Src8)) { + Status = XST_INVALID_PARAM; + } + else { + (void)memcpy(DestTemp, SrcTemp, CopyLen); + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** + * @brief This is wrapper function to memset function. This function + * writes specified byte to destination specified number of times. + * This function also takes maximum string size that destination + * holds to make sure not to write out of bound area. + * + * @param Dest - Pointer to destination memory + * @param DestSize - Memory available at destination + * @param Data - Any value from 0 to 255 + * @param Len - Number of bytes to be copied + * + * @return + * XST_SUCCESS - Copy is successful + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SMemSet(void *Dest, const u32 DestSize, + const u8 Data, const u32 Len) +{ + int Status = XST_FAILURE; + + if ((Dest == NULL) || (DestSize < Len) || (Len == 0U)) { + Status = XST_INVALID_PARAM; + } + else { + (void)memset(Dest, (s32)Data, Len); + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function concatenates two strings. This function + * takes size of both strings to make sure not to read from / + * write to out of bound area. + * + * @param DestStr - Pointer to destination string + * @param DestSize - Maximum string size that detination can hold + * @param SrcStr - Pointer to source string + * @param SrcSize - Maximum string size that source can hold + * + * @return + * XST_SUCCESS - Copy is successful + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SStrCat (u8 *DestStr, const u32 DestSize, + const u8 *SrcStr, const u32 SrcSize) +{ + int Status = XST_FAILURE; + u32 SrcLen; + u32 DstLen; + + if ((DestStr == NULL) || (SrcStr == NULL)) { + Status = XST_INVALID_PARAM; + goto END; + } + + SrcLen = strnlen((const char*)SrcStr, SrcSize); + DstLen = strnlen((const char*)DestStr, DestSize); + + if ((DestSize <= DstLen) || (SrcSize <= SrcLen)) { + Status = XST_INVALID_PARAM; + } + else if (DestSize <= (SrcLen + DstLen)) { + Status = XST_INVALID_PARAM; + } + else { + (void)strcat((char*)DestStr, (const char*)SrcStr); + Status = XST_SUCCESS; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function compares two strings. It also takes maximum string + * size that Src1 and Src2 can hold to make sure not to read out of + * bound data for comparison. + * + * @param Str1 - Pointer to first string + * @param Str1Size - Maximum string size that Str1 can hold + * @param Str2 - Pointer to second string + * @param Str2Size - Maximum string size that Str2 can hold + * + * @return + * XST_SUCCESS - If both strings are same + * XST_FAILURE - If there is difference between two strings + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SStrCmp(const u8 *Str1, const u32 Str1Size, + const u8 *Str2, const u32 Str2Size) +{ + int Status = XST_FAILURE; + u32 Str1Len = 0U; + u32 Str2Len = 0U; + + if ((Str1 == NULL) || (Str2 == NULL)) { + Status = XST_INVALID_PARAM; + goto END; + } + + Str1Len = strnlen((const char*)Str1, Str1Size); + Str2Len = strnlen((const char*)Str2, Str2Size); + + if ((Str1Size <= Str1Len) || (Str2Size <= Str2Len)) { + Status = XST_INVALID_PARAM; + } + else if ((Str1Len < Str2Len) || (Str1Len > Str2Len)) { + Status = XST_FAILURE; + } + else { + Status = memcmp(Str1, Str2, Str1Len); + if (Status != 0) { + Status = XST_FAILURE; + } + } + +END: + return Status; +} + + +/*****************************************************************************/ +/** + * @brief This function compares two strings. It also takes maximum string + * size that Src1 and Src2 can hold to make sure not to read out of + * bound data for comparison. This function compares each character + * of the strings so that execution time of the function is not + * dependent on the content of two input strings. The execution + * time is constant when string size are same. + * + * @param Str1 - Pointer to first string + * @param Str1Size - Maximum string size that Str1 can hold + * @param Str2 - Pointer to second string + * @param Str2Size - Maximum string size that Str2 can hold + * + * @return + * XST_SUCCESS - If both strings are same + * XST_FAILURE - If there is difference between two strings + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SStrCmp_CT (const u8 *Str1, const u32 Str1Size, + const u8 *Str2, const u32 Str2Size) +{ + int Status = XST_FAILURE; + u32 Str1Len = 0U; + u32 Str2Len = 0U; + + if ((Str1 == NULL) || (Str2 == NULL)) { + Status = XST_INVALID_PARAM; + goto END; + } + + Str1Len = strnlen((const char*)Str1, Str1Size); + Str2Len = strnlen((const char*)Str2, Str2Size); + + if ((Str1Size <= Str1Len) || (Str2Size <= Str2Len)) { + Status = XST_INVALID_PARAM; + } + else if (Str1Len != Str2Len) { + Status = XST_FAILURE; + } + else { + Status = Xil_SMemCmp_CT (Str1, Str1Size, Str2, Str2Size, Str1Len); + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function copies one string to other. This function + * takes size of both strings to make sure not to read from / + * write to out of bound area. + * + * @param DestStr - Pointer to destination string + * @param DestSize - Maximum string size that detination can hold + * @param SrcStr - Pointer to source string + * @param SrcSize - Maximum string size that source can hold + * + * @return + * XST_SUCCESS - Copy is successful + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SStrCpy(u8 *DestStr, const u32 DestSize, + const u8 *SrcStr, const u32 SrcSize) +{ + int Status = XST_FAILURE; + u32 SrcLen = 0U; + + if ((DestStr == NULL) || (SrcStr == NULL)) { + Status = XST_INVALID_PARAM; + goto END; + } + + SrcLen = strnlen((const char*)SrcStr, SrcSize); + + if ((DestSize <= SrcLen) || (SrcSize <= SrcLen)) { + Status = XST_INVALID_PARAM; + } + else { + (void)memcpy(DestStr, SrcStr, SrcLen + 1U); + Status = XST_SUCCESS; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This is wrapper function to memmove function. This function + * takes size of two memory regions to avoid out of bound memory region. + * + * @param Dest - Pointer to destination memory + * @param DestSize - Memory available at destination + * @param Src - Pointer to source memory + * @param SrcSize - Maximum data that can be copied from source + * @param CopyLen - Number of bytes to be copied + * + * @return + * XST_SUCCESS - Copy is successful + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SMemMove(void *Dest, const u32 DestSize, + const void *Src, const u32 SrcSize, const u32 CopyLen) +{ + volatile int Status = XST_FAILURE; + const void *Output = NULL; + + if ((Dest == NULL) || (Src == NULL)) { + Status = XST_INVALID_PARAM; + } + else if ((CopyLen == 0U) || (DestSize < CopyLen) || (SrcSize < CopyLen)) { + Status = XST_INVALID_PARAM; + } + else { + Output = memmove(Dest, Src, CopyLen); + if (Output != NULL) { + Status = XST_SUCCESS; + } + } + + return Status; +} + +/****************************************************************************/ +/* + * Waits for the event to be set with in timeout and returns error incase + * event was not set in specified time out. + * + * @param Timeout - Max number of microseconds to wait for an event, + * It should be maximum timeout needed among the + * events specified. + * @param NumOfEvents - Number of event(s) to be checked. + * @param EventAddr - Pointer to address of event(s) to be set. + * + * @return + * XST_SUCCESS - On occurrence of the event(s). + * XST_FAILURE - Event(s) did not occur before counter reaches 0 + * + * @note None. + * + *****************************************************************************/ +u32 Xil_WaitForEventSet(u32 Timeout, u32 NumOfEvents, volatile u32 *EventAddr, ...) +{ + u32 PollCount = Timeout; + u32 Status = XST_FAILURE; + u32 LoopCnt = 0, i; + va_list Event; + + va_start(Event, EventAddr); + /* wait for all events to complete */ + for (i = 0; i < NumOfEvents; i++) { + while(PollCount > 0U) { + if (Xil_In32((UINTPTR)EventAddr)) { + LoopCnt++; + break; + } + PollCount--; +#ifdef VERSAL_PLM + Xil_PlmStubHandler(); +#endif + usleep(1U); + } + if (PollCount == 0U) { + goto END; + } + EventAddr = va_arg(Event, volatile u32 *); + PollCount = Timeout; + } + va_end(Event); + +END: + if (LoopCnt == NumOfEvents) { + Status = XST_SUCCESS; + } + + return Status; +} + +/****************************************************************************/ +/** + * @brief + * Performs a Read Modify Write operation for a memory location by writing the + * 32 bit value to the the specified address and then reading it back to + * verify the value written in the register. + * + * @param Addr contains the address to perform the output operation + * @param Mask indicates the bits to be modified + * @param Value contains 32 bit Value to be written at the specified address + * + * @return + * XST_SUCCESS on success + * XST_FAILURE on failure + * + *****************************************************************************/ +s32 Xil_SecureRMW32(UINTPTR Addr, u32 Mask, u32 Value) +{ + s32 Status = XST_FAILURE; + u32 ReadReg; + u32 Val; + + Val = Xil_In32(Addr); + Val = (Val & (~Mask)) | (Mask & Value); + Xil_Out32(Addr, Val); + + /* verify value written to specified address */ + ReadReg = Xil_In32(Addr) & Mask; + + if(ReadReg == (Mask & Value)) { + Status = XST_SUCCESS; + } + + return Status; +} diff --git a/bsp_z7/ps7_cortexa9_0/include/xil_util.h b/bsp_z7/ps7_cortexa9_0/include/xil_util.h new file mode 100644 index 0000000..d65854c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xil_util.h @@ -0,0 +1,318 @@ +/******************************************************************************/ +/** +* Copyright (c) 2019 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* @file xil_util.h +* @addtogroup common_utilities Common Utility APIs +* @{ +* @details +* +* xil_util.h file contains xil utility functions declarations +* Except few functions, most of these functions are wrappers to standard functions. +* The standard string functions do not validate the input and that results into +* buffer overflows. To avoid it, the wrapper function validates the input and +* then passed to standard function. There are few constant time functions +* ( xxx_CT() ) which are used to compare the data in constant time. +* The constant time functions should be used while comparing secure data +* like password, keys which prevent disclosing of the data using +* timing analysis. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+* 6.5   kal      02/29/20 Added Xil_ConvertStringToHexBE API
+* 7.3   kal      06/30/20 Converted Xil_Ceil macro to API
+*       rpo      08/19/20 Added function for read, modify and write
+*       bsv      08/21/20 Added XSECURE_TEMPORAL_CHECK macro to add
+*                         redundancy in security critical functions, to avoid
+*                         glitches from altering the return values of security
+*                         critical functions. The macro requires a label to be
+*                         passed to "go to" in case of error.
+*      kpt       09/03/20 Added XSECURE_TEMPORAL_IMPL macro for redundancy
+*      kal       09/22/20 Changed the param type from const char to const char*
+*                         to avoid copying key onto stack
+*      td        10/16/20 Added Xil_Strcpy, Xil_Strcat, Xil_SecureMemCpy and
+*                         Xil_MemCmp functions
+*      am        10/13/20 Resolved Coverity warning
+*      td        11/19/20 Updated XSECURE_TEMPORAL_CHECK and
+*                         XSECURE_TEMPORAL_IMPL to fix MISRA C Rule 15.3
+* 7.4  am        11/26/20 Added Xil_StrCpyRange function
+* 7.6  kpt       07/15/21 Added Xil_SecureZeroize function
+* 7.7  kpt       11/09/21 Added Xil_SMemCmp, Xil_SMemCmp_CT, Xil_SMemCpy,
+*                         Xil_SMemSet, Xil_SStrCat, Xil_SStrCmp, Xil_SStrCmp_CT
+*                         Xil_SStrCpy functions
+* 7.7	sk	 01/10/22 Update functions return type to fix misra_c_2012_
+* 			  directive_4_6 violations.
+*      mmd       02/28/22 Added Xil_SMemMove function prototype
+* 8.0  adk       04/18/22 Added Xil_WaitForEventSet function prototype.
+*      ssc       08/25/22 Added Xil_SecureRMW32 prototype
+* 8.1  sa        09/29/22 Change the type of first argument passed to Xil_WaitForEvent
+*			  API from u32 to UINTPTR for supporting 64 bit addressing.
+* 8.1  sa        10/20/22 Change the type of first argument passed to Xil_WaitForEvents
+*                         API from u32 to UINTPTR for supporting 64 bit addressing.
+* 8.1  akm       01/02/23 Added Xil_RegisterPlmHandler() & Xil_PlmStubHandler() APIs.
+*      bm        03/14/23 Added XSECURE_REDUNDANT_CALL and XSECURE_REDUNDANT_IMPL macros
+*      sk        03/14/23 Added Status Check Glitch detect Macro
+* 
+* +*****************************************************************************/ + +#ifndef XIL_UTIL_H_ +#define XIL_UTIL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_types.h" +#include "xil_io.h" +#include "xstatus.h" + +/*************************** Constant Definitions *****************************/ +#define XIL_SIZE_OF_NIBBLE_IN_BITS 4U +#define XIL_SIZE_OF_BYTE_IN_BITS 8U + +/* Maximum string length handled by Xil_ValidateHexStr function */ +#define XIL_MAX_HEX_STR_LEN 512U + + +/****************** Macros (Inline Functions) Definitions *********************/ +#ifdef __GNUC__ +/******************************************************************************/ +/** + * + * Updates the return value of the called function into Var and VarTmp variables + * for redundancy. This is to avoid glitches from altering the return values of + * security critical functions. + * + * @param Var is the variable which holds the return value of function + * executed + * @param VarTmp is the variable which holds the value stored in Var + * @param Function is the function to be executed + * @param Other params are arguments to the called function + * + * @return None + * + ******************************************************************************/ +#define XSECURE_TEMPORAL_IMPL(Var, VarTmp, Function, ...) \ + { \ + Var = XST_FAILURE; \ + VarTmp = XST_FAILURE; \ + Var = Function(__VA_ARGS__); \ + VarTmp = Var; \ + } + +/******************************************************************************/ +/** + * + * Adds redundancy while checking the status of the called function. + * This is to avoid glitches from altering the return values of security + * critical functions. The macro requires a label to be passed to "go to" + * in case of error. + * + * @param Label is the label defined in function and the control + * will jump to the label in case of XST_FAILURE + * @param Status is the variable which holds the return value of + * function executed + * @param Function is the function to be executed + * @param Other params are arguments to the called function + * + * @return None + * + ******************************************************************************/ +#define XSECURE_TEMPORAL_CHECK(Label, Status, Function, ...) \ + { \ + volatile int StatusTmp; \ + XSECURE_TEMPORAL_IMPL(Status, StatusTmp, Function, __VA_ARGS__); \ + if ((Status != XST_SUCCESS) || \ + (StatusTmp != XST_SUCCESS)) { \ + if (((Status) != (StatusTmp)) || \ + (Status == XST_SUCCESS)) { \ + Status = XST_GLITCH_ERROR; \ + }\ + goto Label; \ + } \ + } + +/******************************************************************************/ +/** + * + * Adds redundancy to the function call. This is to avoid glitches which can skip + * a function call and cause altering of the code flow in security critical + * functions. + * + * @param Status is the variable which holds the return value of + * function executed + * @param StatusTmp is the variable which holds the return value of + * redundant function call executed + * @param Function is the function to be executed + * @param Other params are arguments to the called function + * + * @return None + * + ******************************************************************************/ +#define XSECURE_REDUNDANT_CALL(Status, StatusTmp, Function, ...) \ + { \ + Status = Function(__VA_ARGS__); \ + StatusTmp = Function(__VA_ARGS__); \ + } + +/******************************************************************************/ +/** + * + * Adds redundancy to the function call. This is to avoid glitches which can skip + * a function call and cause altering of the code flow in security critical + * functions. + * + * @param Function is the function to be executed + * @param Other params are arguments to the called function + * + * @return None + * + ******************************************************************************/ +#define XSECURE_REDUNDANT_IMPL(Function, ...) \ + { \ + Function(__VA_ARGS__); \ + Function(__VA_ARGS__); \ + } + +/******************************************************************************/ +/** + * + * This Macro helps to detect glitches skipping the Status check + * in case of error. + * + * @param None + * + * @return None + * + ******************************************************************************/ +#define XSECURE_STATUS_CHK_GLITCH_DETECT(Status) \ + { \ + if (Status == XST_SUCCESS) { \ + Status = (int)XST_GLITCH_ERROR; \ + } \ + } + +#endif +/*************************** Function Prototypes ******************************/ +/* Ceils the provided float value */ +s32 Xil_Ceil(float Value); + +/* Converts input character to nibble */ +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num); + +/* Convert input hex string to array of 32-bits integers */ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len); + +#ifdef VERSAL_PLM +/* Register PLM handler */ +void Xil_RegisterPlmHandler(void (*PlmAlive) (void)); + +/* Call PLM handler */ +void Xil_PlmStubHandler(void); +#endif + +/* Waits for specified event */ +u32 Xil_WaitForEvent(UINTPTR RegAddr, u32 EventMask, u32 Event, u32 Timeout); + +/* Waits for specified events */ +u32 Xil_WaitForEvents(UINTPTR EventsRegAddr, u32 EventsMask, u32 WaitEvents, + u32 Timeout, u32* Events); + +/* Validate input hex character */ +u32 Xil_IsValidHexChar(const char *Ch); + +/* Validate the input string contains only hexadecimal characters */ +u32 Xil_ValidateHexStr(const char *HexStr); + +/* Convert string to hex numbers in little enidian format */ +u32 Xil_ConvertStringToHexLE(const char *Str, u8 *Buf, u32 Len); + +/* Returns length of the input string */ +u32 Xil_Strnlen(const char *Str, u32 MaxLen); + +/* Convert string to hex numbers in big endian format */ +u32 Xil_ConvertStringToHexBE(const char * Str, u8 * Buf, u32 Len); + +/*Read, Modify and Write to an address*/ +void Xil_UtilRMW32(u32 Addr, u32 Mask, u32 Value); + +/* Copies source string to destination string */ +int Xil_Strcpy(char *DestPtr, const char *SrcPtr, const u32 Size); + +/* Copies specified range from source string to destination string */ +int Xil_StrCpyRange(const u8 *Src, u8 *Dest, u32 From, u32 To, u32 MaxSrcLen, + u32 MaxDstLen); + +/* Appends string2 to string1 */ +int Xil_Strcat(char* Str1Ptr, const char* Str2Ptr, const u32 Size); + +/* Copies Len bytes from source memory to destination memory */ +int Xil_SecureMemCpy(void * DestPtr, u32 DestPtrLen, const void * SrcPtr, u32 Len); + +/* Compares Len bytes from memory1 and memory2 */ +int Xil_MemCmp(const void * Buf1Ptr, const void * Buf2Ptr, u32 Len); + +/* Zeroizes the memory of given length */ +int Xil_SecureZeroize(u8 *DataPtr, const u32 Length); + +/* Copies Len bytes from source memory to destination memory */ +int Xil_SMemCpy (void *Dest, const u32 DestSize, + const void *Src, const u32 SrcSize, const u32 CopyLen); + +/* Copies Len bytes from source memory to destination memory, allows + overlapped memory between source and destination */ +int Xil_SMemMove(void *Dest, const u32 DestSize, + const void *Src, const u32 SrcSize, const u32 CopyLen); + +/* Compares Len bytes between source and destination memory */ +int Xil_SMemCmp (const void *Src1, const u32 Src1Size, + const void *Src2, const u32 Src2Size, const u32 CmpLen); + +/* Compares Len bytes between source and destination memory with constant time */ +int Xil_SMemCmp_CT (const void *Src1, const u32 Src1Size, + const void *Src2, const u32 Src2Size, const u32 CmpLen); + +/* Sets the destination memory of given length with given data */ +int Xil_SMemSet (void *Dest, const u32 DestSize, + const u8 Data, const u32 Len); + +/* Copies source string to destination string */ +int Xil_SStrCpy (u8 *DestStr, const u32 DestSize, + const u8 *SrcStr, const u32 SrcSize); + +/* Compares source string with destination string */ +int Xil_SStrCmp (const u8 *Str1, const u32 Str1Size, + const u8 *Str2, const u32 Str2Size); + +/* Compares source string with destination string with constant time */ +int Xil_SStrCmp_CT (const u8 *Str1, const u32 Str1Size, + const u8 *Str2, const u32 Str2Size); + +/* Concatenates source string to destination string */ +int Xil_SStrCat (u8 *DestStr, const u32 DestSize, + const u8 *SrcStr, const u32 SrcSize); + +/* Waits for event timeout */ +u32 Xil_WaitForEventSet(u32 Timeout, u32 NumOfEvents, volatile u32 *EventAddr, ...); + +/* Implements Read Modify Writes securely */ +s32 Xil_SecureRMW32(UINTPTR Addr, u32 Mask, u32 Value); + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_UTIL_H_ */ +/** +* @} End of "addtogroup common_utilities". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xilrsa.h b/bsp_z7/ps7_cortexa9_0/include/xilrsa.h new file mode 100644 index 0000000..a8acdb1 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xilrsa.h @@ -0,0 +1,230 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xilrsa.h +* @addtogroup xilrsa_apis XilRSA APIs and Descriptions +* @{ +* @cond xilrsa_internal +* This file contains the RSA algorithm functions +* +*
+* MODIFICATION HISTORY:
+*
+* Ver	Who	Date		Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.0   hk   27/01/14 First release
+* 1.4   vns  07/06/17 Added dooxygen tags.
+*
+* 
+* +* @note +* +******************************************************************************/ +#ifndef ___XIL_RSA_H___ +#define ___XIL_RSA_H___ + +#ifdef __cplusplus +extern "C" { +#endif +/***************************** Include Files *********************************/ + +/* + * Digit size selection (32 or 16-bit). If supported by the CPU/compiler, + * 32-bit digits are approximately 4 times faster + */ + +//#define RSA_DIGIT_16 +#define RSA_DIGIT_32 + +/* + * RSA loop unrolling selection + * RSA main loop can be unrolled 2, 4 or 8 ways + */ +#define RSA_UNROLL 1 + +/* + * Select if ARM-optimized code is to be used. Only GCC for ARM is supported + */ +//#define RSA_ARM_OPTIMIZED + +/* + * Check the compatibility of the selection + */ +#if defined(RSA_DIGIT_16) && defined(RSA_DIGIT_32) + #error Please select a digit size +#endif +#if !defined(RSA_DIGIT_16) && !defined(RSA_DIGIT_32) + #error Please select just one digit size +#endif +#if (!defined(__GNUC__) || !defined(__arm__)) && defined(RSA_ARM_OPTIMIZED) + #error Assembly level code is only supported for the GCC/ARM combination +#endif +#if (RSA_UNROLL != 1) && (RSA_UNROLL != 2) && (RSA_UNROLL != 4) && (RSA_UNROLL != 8) + #error Only 1, 2, 4, and 8 unrolling are supported +#endif + +#ifdef RSA_DIGIT_16 +#define RSA_DIGIT unsigned short +#define RSA_SDIGIT short +#define RSA_DDIGIT unsigned long +#endif +#ifdef RSA_DIGIT_32 +#define RSA_DIGIT unsigned long +#define RSA_SDIGIT long +#define RSA_DDIGIT unsigned long long +#endif + +#define RSA_NUMBER RSA_DIGIT * +#define RSA_NBITS 2048 +#define RSA_NDIGITS (RSA_NBITS/(sizeof(RSA_DIGIT)*8)) +#define RSA_NBYTES (RSA_NDIGITS*sizeof(RSA_DIGIT)) + +/* + * Double-digit to single digit conversion + */ +#define RSA_MSB(x) (x >> (sizeof(RSA_DIGIT)*8)) +#define RSA_LSB(x) (x & (RSA_DIGIT)~0) + +#define SHA_BLKSIZE 512 +#define SHA_BLKBYTES (SHA_BLKSIZE/8) +#define SHA_BLKWORDS (SHA_BLKBYTES/4) + +#define SHA_VALSIZE 256 +#define SHA_VALBYTES (SHA_VALSIZE/8) +#define SHA_VALWORDS (SHA_VALBYTES/4) + +/* + * SHA-256 context structure + * Includes SHA-256 state, coalescing buffer to collect the processed strings, and + * total byte length counter (used both to manage the buffer and for padding) + */ + //! [sha2_context] +typedef struct +{ + unsigned int state[8]; + unsigned char buffer[SHA_BLKBYTES]; + unsigned long long bytes; +} sha2_context; +//! [sha2_context] +/** @} +@endcond */ + +/* + * RSA-2048 user interfaces + */ +/*****************************************************************************/ +/** + * @brief + * This function is used to encrypt the data using 2048 bit private key. + * + * @param modular A char pointer which contains the key modulus + * @param modular_ext A char pointer which contains the key modulus + * extension + * @param exponent A char pointer which contains the private key + * exponent + * @param result A char pointer which contains the encrypted data + * + * @return None + * + ******************************************************************************/ +void rsa2048_exp(const unsigned char *base, const unsigned char * modular, + const unsigned char *modular_ext, const unsigned char *exponent, + unsigned char *result); +/*****************************************************************************/ +/** + * @brief + * This function is used to decrypt the data using 2048 bit public key + * + * @param a RSA_NUMBER containing the decrypted data. + * @param x RSA_NUMBER containing the input data + * @param e Unsigned number containing the public key exponent + * @param m RSA_NUMBER containing the public key modulus + * @param rrm RSA_NUMBER containing the public key modulus extension. + * + * @return None + * + ******************************************************************************/ +void rsa2048_pubexp(RSA_NUMBER a, RSA_NUMBER x, + unsigned long e, RSA_NUMBER m, RSA_NUMBER rrm); + +/* + * SHA-256 user interfaces + */ +/*****************************************************************************/ +/** + * @brief + * This function calculates the hash for the input data using SHA-256 + * algorithm. This function internally calls the sha2_init, updates and + * finishes functions and updates the result. + * + * @param In Char pointer which contains the input data. + * @param Size Length of the input data + * @param Out Pointer to location where resulting hash will be + * written. + * + * @return None + * + ******************************************************************************/ +void sha_256(const unsigned char *in, const unsigned int size, unsigned char *out); +/*****************************************************************************/ +/** + * @brief + * This function initializes the SHA2 context. + * + * @param ctx Pointer to sha2_context structure that stores status and + * buffer. + * + * @return None + * + ******************************************************************************/ +void sha2_starts(sha2_context *ctx); +/*****************************************************************************/ +/** + * @brief + * This function adds the input data to SHA256 calculation. + * + * @param ctx Pointer to sha2_context structure that stores status and + * buffer. + * @param input Pointer to the data to add. + * @param Out Length of the input data. + * + * @return None + * + ******************************************************************************/ +void sha2_update(sha2_context *ctx, unsigned char* input, unsigned int ilen); +/*****************************************************************************/ +/** + * @brief + * This function finishes the SHA calculation. + * + * @param ctx Pointer to sha2_context structure that stores status and + * buffer. + * @param output Pointer to the calculated hash data. + * + * @return None + * + * + ******************************************************************************/ +void sha2_finish(sha2_context *ctx, unsigned char* output); + +/* + * Preprocessing interface (pre-computation of R*R mod M) + */ +/**@cond xilrsa_internal */ +void modular_ext(const unsigned char *modular, unsigned char *res); +/** @} +@endcond */ + +#ifdef __cplusplus +} +#endif + +#endif /* ___XIL_RSA_H___ */ +/** @} */ + + diff --git a/bsp_z7/ps7_cortexa9_0/include/xl2cc.h b/bsp_z7/ps7_cortexa9_0/include/xl2cc.h new file mode 100644 index 0000000..4df6d87 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xl2cc.h @@ -0,0 +1,155 @@ +/****************************************************************************** +* Copyright (c) 2011 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xl2cc.h +* +* This file contains the address definitions for the PL310 Level-2 Cache +* Controller. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  02/01/10 Initial version
+* 3.10a srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      'xil_errata.h' for errata description
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef _XL2CC_H_ +#define _XL2CC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ +/* L2CC Register Offsets */ +#define XPS_L2CC_ID_OFFSET 0x0000U +#define XPS_L2CC_TYPE_OFFSET 0x0004U +#define XPS_L2CC_CNTRL_OFFSET 0x0100U +#define XPS_L2CC_AUX_CNTRL_OFFSET 0x0104U +#define XPS_L2CC_TAG_RAM_CNTRL_OFFSET 0x0108U +#define XPS_L2CC_DATA_RAM_CNTRL_OFFSET 0x010CU + +#define XPS_L2CC_EVNT_CNTRL_OFFSET 0x0200U +#define XPS_L2CC_EVNT_CNT1_CTRL_OFFSET 0x0204U +#define XPS_L2CC_EVNT_CNT0_CTRL_OFFSET 0x0208U +#define XPS_L2CC_EVNT_CNT1_VAL_OFFSET 0x020CU +#define XPS_L2CC_EVNT_CNT0_VAL_OFFSET 0x0210U + +#define XPS_L2CC_IER_OFFSET 0x0214U /* Interrupt Mask */ +#define XPS_L2CC_IPR_OFFSET 0x0218U /* Masked interrupt status */ +#define XPS_L2CC_ISR_OFFSET 0x021CU /* Raw Interrupt Status */ +#define XPS_L2CC_IAR_OFFSET 0x0220U /* Interrupt Clear */ + +#define XPS_L2CC_CACHE_SYNC_OFFSET 0x0730U /* Cache Sync */ +#define XPS_L2CC_DUMMY_CACHE_SYNC_OFFSET 0x0740U /* Dummy Register for Cache Sync */ +#define XPS_L2CC_CACHE_INVLD_PA_OFFSET 0x0770U /* Cache Invalid by PA */ +#define XPS_L2CC_CACHE_INVLD_WAY_OFFSET 0x077CU /* Cache Invalid by Way */ +#define XPS_L2CC_CACHE_CLEAN_PA_OFFSET 0x07B0U /* Cache Clean by PA */ +#define XPS_L2CC_CACHE_CLEAN_INDX_OFFSET 0x07B8U /* Cache Clean by Index */ +#define XPS_L2CC_CACHE_CLEAN_WAY_OFFSET 0x07BCU /* Cache Clean by Way */ +#define XPS_L2CC_CACHE_INV_CLN_PA_OFFSET 0x07F0U /* Cache Invalidate and Clean by PA */ +#define XPS_L2CC_CACHE_INV_CLN_INDX_OFFSET 0x07F8U /* Cache Invalidate and Clean by Index */ +#define XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET 0x07FCU /* Cache Invalidate and Clean by Way */ + +#define XPS_L2CC_CACHE_DLCKDWN_0_WAY_OFFSET 0x0900U /* Cache Data Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_0_WAY_OFFSET 0x0904U /* Cache Instruction Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_1_WAY_OFFSET 0x0908U /* Cache Data Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_1_WAY_OFFSET 0x090CU /* Cache Instruction Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_2_WAY_OFFSET 0x0910U /* Cache Data Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_2_WAY_OFFSET 0x0914U /* Cache Instruction Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_3_WAY_OFFSET 0x0918U /* Cache Data Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_3_WAY_OFFSET 0x091CU /* Cache Instruction Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_4_WAY_OFFSET 0x0920U /* Cache Data Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_4_WAY_OFFSET 0x0924U /* Cache Instruction Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_5_WAY_OFFSET 0x0928U /* Cache Data Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_5_WAY_OFFSET 0x092CU /* Cache Instruction Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_6_WAY_OFFSET 0x0930U /* Cache Data Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_6_WAY_OFFSET 0x0934U /* Cache Instruction Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_7_WAY_OFFSET 0x0938U /* Cache Data Lockdown 7 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_7_WAY_OFFSET 0x093CU /* Cache Instruction Lockdown 7 by Way */ + +#define XPS_L2CC_CACHE_LCKDWN_LINE_ENABLE_OFFSET 0x0950U /* Cache Lockdown Line Enable */ +#define XPS_L2CC_CACHE_UUNLOCK_ALL_WAY_OFFSET 0x0954U /* Cache Unlock All Lines by Way */ + +#define XPS_L2CC_ADDR_FILTER_START_OFFSET 0x0C00U /* Start of address filtering */ +#define XPS_L2CC_ADDR_FILTER_END_OFFSET 0x0C04U /* Start of address filtering */ + +#define XPS_L2CC_DEBUG_CTRL_OFFSET 0x0F40U /* Debug Control Register */ + +/* XPS_L2CC_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_ENABLE_MASK 0x00000001U /* enables the L2CC */ + +/* XPS_L2CC_AUX_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_AUX_EBRESPE_MASK 0x40000000U /* Early BRESP Enable */ +#define XPS_L2CC_AUX_IPFE_MASK 0x20000000U /* Instruction Prefetch Enable */ +#define XPS_L2CC_AUX_DPFE_MASK 0x10000000U /* Data Prefetch Enable */ +#define XPS_L2CC_AUX_NSIC_MASK 0x08000000U /* Non-secure interrupt access control */ +#define XPS_L2CC_AUX_NSLE_MASK 0x04000000U /* Non-secure lockdown enable */ +#define XPS_L2CC_AUX_CRP_MASK 0x02000000U /* Cache replacement policy */ +#define XPS_L2CC_AUX_FWE_MASK 0x01800000U /* Force write allocate */ +#define XPS_L2CC_AUX_SAOE_MASK 0x00400000U /* Shared attribute override enable */ +#define XPS_L2CC_AUX_PE_MASK 0x00200000U /* Parity enable */ +#define XPS_L2CC_AUX_EMBE_MASK 0x00100000U /* Event monitor bus enable */ +#define XPS_L2CC_AUX_WAY_SIZE_MASK 0x000E0000U /* Way-size */ +#define XPS_L2CC_AUX_ASSOC_MASK 0x00010000U /* Associativity */ +#define XPS_L2CC_AUX_SAIE_MASK 0x00002000U /* Shared attribute invalidate enable */ +#define XPS_L2CC_AUX_EXCL_CACHE_MASK 0x00001000U /* Exclusive cache configuration */ +#define XPS_L2CC_AUX_SBDLE_MASK 0x00000800U /* Store buffer device limitation Enable */ +#define XPS_L2CC_AUX_HPSODRE_MASK 0x00000400U /* High Priority for SO and Dev Reads Enable */ +#define XPS_L2CC_AUX_FLZE_MASK 0x00000001U /* Full line of zero enable */ + +#define XPS_L2CC_AUX_REG_DEFAULT_MASK 0x72360000U /* Enable all prefetching, */ + /* Cache replacement policy, Parity enable, */ + /* Event monitor bus enable and Way Size (64 KB) */ +#define XPS_L2CC_AUX_REG_ZERO_MASK 0xFFF1FFFFU /* */ + +#define XPS_L2CC_TAG_RAM_DEFAULT_MASK 0x00000111U /* latency for TAG RAM */ +#define XPS_L2CC_DATA_RAM_DEFAULT_MASK 0x00000121U /* latency for DATA RAM */ + +/* Interrupt bit masks */ +#define XPS_L2CC_IXR_DECERR_MASK 0x00000100U /* DECERR from L3 */ +#define XPS_L2CC_IXR_SLVERR_MASK 0x00000080U /* SLVERR from L3 */ +#define XPS_L2CC_IXR_ERRRD_MASK 0x00000040U /* Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_ERRRT_MASK 0x00000020U /* Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ERRWD_MASK 0x00000010U /* Error on L2 data RAM (Write) */ +#define XPS_L2CC_IXR_ERRWT_MASK 0x00000008U /* Error on L2 tag RAM (Write) */ +#define XPS_L2CC_IXR_PARRD_MASK 0x00000004U /* Parity Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_PARRT_MASK 0x00000002U /* Parity Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ECNTR_MASK 0x00000001U /* Event Counter1/0 Overflow Increment */ + +/* Address filtering mask and enable bit */ +#define XPS_L2CC_ADDR_FILTER_VALID_MASK 0xFFF00000U /* Address filtering valid bits*/ +#define XPS_L2CC_ADDR_FILTER_ENABLE_MASK 0x00000001U /* Address filtering enable bit*/ + +/* Debug control bits */ +#define XPS_L2CC_DEBUG_SPIDEN_MASK 0x00000004U /* Debug SPIDEN bit */ +#define XPS_L2CC_DEBUG_DWB_MASK 0x00000002U /* Debug DWB bit, forces write through */ +#define XPS_L2CC_DEBUG_DCL_MASK 0x00000002U /* Debug DCL bit, disables cache line fill */ + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ + +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xl2cc_counter.h b/bsp_z7/ps7_cortexa9_0/include/xl2cc_counter.h new file mode 100644 index 0000000..31156ee --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xl2cc_counter.h @@ -0,0 +1,96 @@ +/****************************************************************************** +* Copyright (c) 2011 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xl2cc_counter.h +* +* @addtogroup l2_event_counter_apis PL310 L2 Event Counters Functions +* +* xl2cc_counter.h contains APIs for configuring and controlling the event +* counters in PL310 L2 cache controller. +* PL310 has two event counters which can be used to count variety of events +* like DRHIT, DRREQ, DWHIT, DWREQ, etc. xl2cc_counter.h contains definitions +* for different configurations which can be used for the event counters to +* count a set of events. +* +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 3.07a asa  08/30/12 Updated for CR 675636 to provide the L2 Base Address
+*		      inside the APIs
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef L2CCCOUNTER_H /* prevent circular inclusions */ +#define L2CCCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* + * The following constants define the event codes for the event counters. + */ +#define XL2CC_CO 0x1 +#define XL2CC_DRHIT 0x2 +#define XL2CC_DRREQ 0x3 +#define XL2CC_DWHIT 0x4 +#define XL2CC_DWREQ 0x5 +#define XL2CC_DWTREQ 0x6 +#define XL2CC_IRHIT 0x7 +#define XL2CC_IRREQ 0x8 +#define XL2CC_WA 0x9 +#define XL2CC_IPFALLOC 0xa +#define XL2CC_EPFHIT 0xb +#define XL2CC_EPFALLOC 0xc +#define XL2CC_SRRCVD 0xd +#define XL2CC_SRCONF 0xe +#define XL2CC_EPFRCVD 0xf + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/** +*@endcond +*/ + +/************************** Function Prototypes *****************************/ + +void XL2cc_EventCtrInit(s32 Event0, s32 Event1); +void XL2cc_EventCtrStart(void); +void XL2cc_EventCtrStop(u32 *EveCtr0, u32 *EveCtr1); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* L2CCCOUNTER_H */ +/** +* @} End of "addtogroup l2_event_counter_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xparameters.h b/bsp_z7/ps7_cortexa9_0/include/xparameters.h new file mode 100644 index 0000000..5d4b817 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xparameters.h @@ -0,0 +1,484 @@ +/****************************************************************************** +* Copyright (c) 2021 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +#ifndef XPARAMETERS_H /* prevent circular inclusions */ +#define XPARAMETERS_H /* by using protection macros */ + +/* Definition for CPU ID */ +#define XPAR_CPU_ID 0U + +/* Definitions for peripheral PS7_CORTEXA9_0 */ +#define XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ 666666687 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_CORTEXA9_0 */ +#define XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ 666666687 + + +/******************************************************************/ + +#include "xparameters_ps.h" + +#define STDIN_BASEADDRESS 0xE0000000 +#define STDOUT_BASEADDRESS 0xE0000000 + +/******************************************************************/ + +/* Platform specific definitions */ +#define PLATFORM_ZYNQ + +/* Definitions for sleep timer configuration */ +#define XSLEEP_TIMER_IS_DEFAULT_TIMER + + +/******************************************************************/ + +/* Definitions for peripheral PS7_DDR_0 */ +#define XPAR_PS7_DDR_0_S_AXI_BASEADDR 0x00100000 +#define XPAR_PS7_DDR_0_S_AXI_HIGHADDR 0x1FFFFFFF + + +/******************************************************************/ + +/* Definitions for driver DEVCFG */ +#define XPAR_XDCFG_NUM_INSTANCES 1U + +/* Definitions for peripheral PS7_DEV_CFG_0 */ +#define XPAR_PS7_DEV_CFG_0_DEVICE_ID 0U +#define XPAR_PS7_DEV_CFG_0_BASEADDR 0xF8007000U +#define XPAR_PS7_DEV_CFG_0_HIGHADDR 0xF80070FFU + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_DEV_CFG_0 */ +#define XPAR_XDCFG_0_DEVICE_ID XPAR_PS7_DEV_CFG_0_DEVICE_ID +#define XPAR_XDCFG_0_BASEADDR 0xF8007000U +#define XPAR_XDCFG_0_HIGHADDR 0xF80070FFU + + +/******************************************************************/ + +/* Definitions for driver DMAPS */ +#define XPAR_XDMAPS_NUM_INSTANCES 2 + +/* Definitions for peripheral PS7_DMA_NS */ +#define XPAR_PS7_DMA_NS_DEVICE_ID 0 +#define XPAR_PS7_DMA_NS_BASEADDR 0xF8004000 +#define XPAR_PS7_DMA_NS_HIGHADDR 0xF8004FFF + + +/* Definitions for peripheral PS7_DMA_S */ +#define XPAR_PS7_DMA_S_DEVICE_ID 1 +#define XPAR_PS7_DMA_S_BASEADDR 0xF8003000 +#define XPAR_PS7_DMA_S_HIGHADDR 0xF8003FFF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_DMA_NS */ +#define XPAR_XDMAPS_0_DEVICE_ID XPAR_PS7_DMA_NS_DEVICE_ID +#define XPAR_XDMAPS_0_BASEADDR 0xF8004000 +#define XPAR_XDMAPS_0_HIGHADDR 0xF8004FFF + +/* Canonical definitions for peripheral PS7_DMA_S */ +#define XPAR_XDMAPS_1_DEVICE_ID XPAR_PS7_DMA_S_DEVICE_ID +#define XPAR_XDMAPS_1_BASEADDR 0xF8003000 +#define XPAR_XDMAPS_1_HIGHADDR 0xF8003FFF + + +/******************************************************************/ + +/* Definitions for driver EMACPS */ +#define XPAR_XEMACPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_ETHERNET_0 */ +#define XPAR_PS7_ETHERNET_0_DEVICE_ID 0 +#define XPAR_PS7_ETHERNET_0_BASEADDR 0xE000B000 +#define XPAR_PS7_ETHERNET_0_HIGHADDR 0xE000BFFF +#define XPAR_PS7_ETHERNET_0_ENET_CLK_FREQ_HZ 125000000 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 8 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1 1 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 8 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1 5 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0 8 +#define XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1 50 +#define XPAR_PS7_ETHERNET_0_ENET_TSU_CLK_FREQ_HZ 0 + + +/******************************************************************/ + +#define XPAR_PS7_ETHERNET_0_IS_CACHE_COHERENT 0 +#define XPAR_XEMACPS_0_IS_CACHE_COHERENT 0 +/* Canonical definitions for peripheral PS7_ETHERNET_0 */ +#define XPAR_XEMACPS_0_DEVICE_ID XPAR_PS7_ETHERNET_0_DEVICE_ID +#define XPAR_XEMACPS_0_BASEADDR 0xE000B000 +#define XPAR_XEMACPS_0_HIGHADDR 0xE000BFFF +#define XPAR_XEMACPS_0_ENET_CLK_FREQ_HZ 125000000 +#define XPAR_XEMACPS_0_ENET_SLCR_1000Mbps_DIV0 8 +#define XPAR_XEMACPS_0_ENET_SLCR_1000Mbps_DIV1 1 +#define XPAR_XEMACPS_0_ENET_SLCR_100Mbps_DIV0 8 +#define XPAR_XEMACPS_0_ENET_SLCR_100Mbps_DIV1 5 +#define XPAR_XEMACPS_0_ENET_SLCR_10Mbps_DIV0 8 +#define XPAR_XEMACPS_0_ENET_SLCR_10Mbps_DIV1 50 +#define XPAR_XEMACPS_0_ENET_TSU_CLK_FREQ_HZ 0 + + +/******************************************************************/ + + +/* Definitions for peripheral PS7_AFI_0 */ +#define XPAR_PS7_AFI_0_S_AXI_BASEADDR 0xF8008000 +#define XPAR_PS7_AFI_0_S_AXI_HIGHADDR 0xF8008FFF + + +/* Definitions for peripheral PS7_AFI_1 */ +#define XPAR_PS7_AFI_1_S_AXI_BASEADDR 0xF8009000 +#define XPAR_PS7_AFI_1_S_AXI_HIGHADDR 0xF8009FFF + + +/* Definitions for peripheral PS7_AFI_2 */ +#define XPAR_PS7_AFI_2_S_AXI_BASEADDR 0xF800A000 +#define XPAR_PS7_AFI_2_S_AXI_HIGHADDR 0xF800AFFF + + +/* Definitions for peripheral PS7_AFI_3 */ +#define XPAR_PS7_AFI_3_S_AXI_BASEADDR 0xF800B000 +#define XPAR_PS7_AFI_3_S_AXI_HIGHADDR 0xF800BFFF + + +/* Definitions for peripheral PS7_DDRC_0 */ +#define XPAR_PS7_DDRC_0_S_AXI_BASEADDR 0xF8006000 +#define XPAR_PS7_DDRC_0_S_AXI_HIGHADDR 0xF8006FFF + + +/* Definitions for peripheral PS7_GLOBALTIMER_0 */ +#define XPAR_PS7_GLOBALTIMER_0_S_AXI_BASEADDR 0xF8F00200 +#define XPAR_PS7_GLOBALTIMER_0_S_AXI_HIGHADDR 0xF8F002FF + + +/* Definitions for peripheral PS7_GPV_0 */ +#define XPAR_PS7_GPV_0_S_AXI_BASEADDR 0xF8900000 +#define XPAR_PS7_GPV_0_S_AXI_HIGHADDR 0xF89FFFFF + + +/* Definitions for peripheral PS7_INTC_DIST_0 */ +#define XPAR_PS7_INTC_DIST_0_S_AXI_BASEADDR 0xF8F01000 +#define XPAR_PS7_INTC_DIST_0_S_AXI_HIGHADDR 0xF8F01FFF + + +/* Definitions for peripheral PS7_IOP_BUS_CONFIG_0 */ +#define XPAR_PS7_IOP_BUS_CONFIG_0_S_AXI_BASEADDR 0xE0200000 +#define XPAR_PS7_IOP_BUS_CONFIG_0_S_AXI_HIGHADDR 0xE0200FFF + + +/* Definitions for peripheral PS7_L2CACHEC_0 */ +#define XPAR_PS7_L2CACHEC_0_S_AXI_BASEADDR 0xF8F02000 +#define XPAR_PS7_L2CACHEC_0_S_AXI_HIGHADDR 0xF8F02FFF + + +/* Definitions for peripheral PS7_OCMC_0 */ +#define XPAR_PS7_OCMC_0_S_AXI_BASEADDR 0xF800C000 +#define XPAR_PS7_OCMC_0_S_AXI_HIGHADDR 0xF800CFFF + + +/* Definitions for peripheral PS7_PL310_0 */ +#define XPAR_PS7_PL310_0_S_AXI_BASEADDR 0xF8F02000 +#define XPAR_PS7_PL310_0_S_AXI_HIGHADDR 0xF8F02FFF + + +/* Definitions for peripheral PS7_PMU_0 */ +#define XPAR_PS7_PMU_0_S_AXI_BASEADDR 0xF8891000 +#define XPAR_PS7_PMU_0_S_AXI_HIGHADDR 0xF8891FFF +#define XPAR_PS7_PMU_0_PMU1_S_AXI_BASEADDR 0xF8893000 +#define XPAR_PS7_PMU_0_PMU1_S_AXI_HIGHADDR 0xF8893FFF + + +/* Definitions for peripheral PS7_QSPI_LINEAR_0 */ +#define XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR 0xFC000000 +#define XPAR_PS7_QSPI_LINEAR_0_S_AXI_HIGHADDR 0xFCFFFFFF + + +/* Definitions for peripheral PS7_RAM_0 */ +#define XPAR_PS7_RAM_0_S_AXI_BASEADDR 0x00000000 +#define XPAR_PS7_RAM_0_S_AXI_HIGHADDR 0x0003FFFF + + +/* Definitions for peripheral PS7_RAM_1 */ +#define XPAR_PS7_RAM_1_S_AXI_BASEADDR 0xFFFC0000 +#define XPAR_PS7_RAM_1_S_AXI_HIGHADDR 0xFFFFFFFF + + +/* Definitions for peripheral PS7_SCUC_0 */ +#define XPAR_PS7_SCUC_0_S_AXI_BASEADDR 0xF8F00000 +#define XPAR_PS7_SCUC_0_S_AXI_HIGHADDR 0xF8F000FC + + +/* Definitions for peripheral PS7_SLCR_0 */ +#define XPAR_PS7_SLCR_0_S_AXI_BASEADDR 0xF8000000 +#define XPAR_PS7_SLCR_0_S_AXI_HIGHADDR 0xF8000FFF + + +/******************************************************************/ + +/* Definitions for driver GPIOPS */ +#define XPAR_XGPIOPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_GPIO_0 */ +#define XPAR_PS7_GPIO_0_DEVICE_ID 0 +#define XPAR_PS7_GPIO_0_BASEADDR 0xE000A000 +#define XPAR_PS7_GPIO_0_HIGHADDR 0xE000AFFF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_GPIO_0 */ +#define XPAR_XGPIOPS_0_DEVICE_ID XPAR_PS7_GPIO_0_DEVICE_ID +#define XPAR_XGPIOPS_0_BASEADDR 0xE000A000 +#define XPAR_XGPIOPS_0_HIGHADDR 0xE000AFFF + + +/******************************************************************/ + +/* Definitions for driver QSPIPS */ +#define XPAR_XQSPIPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_QSPI_0 */ +#define XPAR_PS7_QSPI_0_DEVICE_ID 0 +#define XPAR_PS7_QSPI_0_BASEADDR 0xE000D000 +#define XPAR_PS7_QSPI_0_HIGHADDR 0xE000DFFF +#define XPAR_PS7_QSPI_0_QSPI_CLK_FREQ_HZ 200000000 +#define XPAR_PS7_QSPI_0_QSPI_MODE 0 +#define XPAR_PS7_QSPI_0_QSPI_BUS_WIDTH 2 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_QSPI_0 */ +#define XPAR_XQSPIPS_0_DEVICE_ID XPAR_PS7_QSPI_0_DEVICE_ID +#define XPAR_XQSPIPS_0_BASEADDR 0xE000D000 +#define XPAR_XQSPIPS_0_HIGHADDR 0xE000DFFF +#define XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ 200000000 +#define XPAR_XQSPIPS_0_QSPI_MODE 0 +#define XPAR_XQSPIPS_0_QSPI_BUS_WIDTH 2 + + +/******************************************************************/ + +/* Definitions for driver SCUGIC */ +#define XPAR_XSCUGIC_NUM_INSTANCES 1U + +/* Definitions for peripheral PS7_SCUGIC_0 */ +#define XPAR_PS7_SCUGIC_0_DEVICE_ID 0U +#define XPAR_PS7_SCUGIC_0_BASEADDR 0xF8F00100U +#define XPAR_PS7_SCUGIC_0_HIGHADDR 0xF8F001FFU +#define XPAR_PS7_SCUGIC_0_DIST_BASEADDR 0xF8F01000U + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUGIC_0 */ +#define XPAR_SCUGIC_0_DEVICE_ID 0U +#define XPAR_SCUGIC_0_CPU_BASEADDR 0xF8F00100U +#define XPAR_SCUGIC_0_CPU_HIGHADDR 0xF8F001FFU +#define XPAR_SCUGIC_0_DIST_BASEADDR 0xF8F01000U + + +/******************************************************************/ + +/* Definitions for driver SCUTIMER */ +#define XPAR_XSCUTIMER_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_SCUTIMER_0 */ +#define XPAR_PS7_SCUTIMER_0_DEVICE_ID 0 +#define XPAR_PS7_SCUTIMER_0_BASEADDR 0xF8F00600 +#define XPAR_PS7_SCUTIMER_0_HIGHADDR 0xF8F0061F + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUTIMER_0 */ +#define XPAR_XSCUTIMER_0_DEVICE_ID XPAR_PS7_SCUTIMER_0_DEVICE_ID +#define XPAR_XSCUTIMER_0_BASEADDR 0xF8F00600 +#define XPAR_XSCUTIMER_0_HIGHADDR 0xF8F0061F + + +/******************************************************************/ + +/* Definitions for driver SCUWDT */ +#define XPAR_XSCUWDT_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_SCUWDT_0 */ +#define XPAR_PS7_SCUWDT_0_DEVICE_ID 0 +#define XPAR_PS7_SCUWDT_0_BASEADDR 0xF8F00620 +#define XPAR_PS7_SCUWDT_0_HIGHADDR 0xF8F006FF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_SCUWDT_0 */ +#define XPAR_SCUWDT_0_DEVICE_ID XPAR_PS7_SCUWDT_0_DEVICE_ID +#define XPAR_SCUWDT_0_BASEADDR 0xF8F00620 +#define XPAR_SCUWDT_0_HIGHADDR 0xF8F006FF + + +/******************************************************************/ + +/* Definitions for driver SDPS */ +#define XPAR_XSDPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_SD_0 */ +#define XPAR_PS7_SD_0_DEVICE_ID 0 +#define XPAR_PS7_SD_0_BASEADDR 0xE0100000 +#define XPAR_PS7_SD_0_HIGHADDR 0xE0100FFF +#define XPAR_PS7_SD_0_SDIO_CLK_FREQ_HZ 50000000 +#define XPAR_PS7_SD_0_HAS_CD 1 +#define XPAR_PS7_SD_0_HAS_WP 1 +#define XPAR_PS7_SD_0_BUS_WIDTH 0 +#define XPAR_PS7_SD_0_MIO_BANK 0 +#define XPAR_PS7_SD_0_HAS_EMIO 0 +#define XPAR_PS7_SD_0_SLOT_TYPE 0 +#define XPAR_PS7_SD_0_CLK_50_SDR_ITAP_DLY 0 +#define XPAR_PS7_SD_0_CLK_50_SDR_OTAP_DLY 0 +#define XPAR_PS7_SD_0_CLK_50_DDR_ITAP_DLY 0 +#define XPAR_PS7_SD_0_CLK_50_DDR_OTAP_DLY 0 +#define XPAR_PS7_SD_0_CLK_100_SDR_OTAP_DLY 0 +#define XPAR_PS7_SD_0_CLK_200_SDR_OTAP_DLY 0 + + +/******************************************************************/ + +#define XPAR_PS7_SD_0_IS_CACHE_COHERENT 0 +/* Canonical definitions for peripheral PS7_SD_0 */ +#define XPAR_XSDPS_0_DEVICE_ID XPAR_PS7_SD_0_DEVICE_ID +#define XPAR_XSDPS_0_BASEADDR 0xE0100000 +#define XPAR_XSDPS_0_HIGHADDR 0xE0100FFF +#define XPAR_XSDPS_0_SDIO_CLK_FREQ_HZ 50000000 +#define XPAR_XSDPS_0_HAS_CD 1 +#define XPAR_XSDPS_0_HAS_WP 1 +#define XPAR_XSDPS_0_BUS_WIDTH 0 +#define XPAR_XSDPS_0_MIO_BANK 0 +#define XPAR_XSDPS_0_HAS_EMIO 0 +#define XPAR_XSDPS_0_SLOT_TYPE 0 +#define XPAR_XSDPS_0_IS_CACHE_COHERENT 0 +#define XPAR_XSDPS_0_CLK_50_SDR_ITAP_DLY 0 +#define XPAR_XSDPS_0_CLK_50_SDR_OTAP_DLY 0 +#define XPAR_XSDPS_0_CLK_50_DDR_ITAP_DLY 0 +#define XPAR_XSDPS_0_CLK_50_DDR_OTAP_DLY 0 +#define XPAR_XSDPS_0_CLK_100_SDR_OTAP_DLY 0 +#define XPAR_XSDPS_0_CLK_200_SDR_OTAP_DLY 0 + + +/******************************************************************/ + +/* Definitions for driver TTCPS */ +#define XPAR_XTTCPS_NUM_INSTANCES 3U + +/* Definitions for peripheral PS7_TTC_0 */ +#define XPAR_PS7_TTC_0_DEVICE_ID 0U +#define XPAR_PS7_TTC_0_BASEADDR 0XF8001000U +#define XPAR_PS7_TTC_0_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_PS7_TTC_0_TTC_CLK_CLKSRC 0U +#define XPAR_PS7_TTC_1_DEVICE_ID 1U +#define XPAR_PS7_TTC_1_BASEADDR 0XF8001004U +#define XPAR_PS7_TTC_1_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_PS7_TTC_1_TTC_CLK_CLKSRC 0U +#define XPAR_PS7_TTC_2_DEVICE_ID 2U +#define XPAR_PS7_TTC_2_BASEADDR 0XF8001008U +#define XPAR_PS7_TTC_2_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_PS7_TTC_2_TTC_CLK_CLKSRC 0U + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_TTC_0 */ +#define XPAR_XTTCPS_0_DEVICE_ID XPAR_PS7_TTC_0_DEVICE_ID +#define XPAR_XTTCPS_0_BASEADDR 0xF8001000U +#define XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_XTTCPS_0_TTC_CLK_CLKSRC 0U + +#define XPAR_XTTCPS_1_DEVICE_ID XPAR_PS7_TTC_1_DEVICE_ID +#define XPAR_XTTCPS_1_BASEADDR 0xF8001004U +#define XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_XTTCPS_1_TTC_CLK_CLKSRC 0U + +#define XPAR_XTTCPS_2_DEVICE_ID XPAR_PS7_TTC_2_DEVICE_ID +#define XPAR_XTTCPS_2_BASEADDR 0xF8001008U +#define XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ 111111115U +#define XPAR_XTTCPS_2_TTC_CLK_CLKSRC 0U + + +/******************************************************************/ + +/* Definitions for driver UARTPS */ +#define XPAR_XUARTPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_UART_1 */ +#define XPAR_PS7_UART_1_DEVICE_ID 0 +#define XPAR_PS7_UART_1_BASEADDR 0xE0001000 +#define XPAR_PS7_UART_1_HIGHADDR 0xE0001FFF +#define XPAR_PS7_UART_1_UART_CLK_FREQ_HZ 50000000 +#define XPAR_PS7_UART_1_HAS_MODEM 0 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_UART_1 */ +#define XPAR_XUARTPS_0_DEVICE_ID XPAR_PS7_UART_1_DEVICE_ID +#define XPAR_XUARTPS_0_BASEADDR 0xE0001000 +#define XPAR_XUARTPS_0_HIGHADDR 0xE0001FFF +#define XPAR_XUARTPS_0_UART_CLK_FREQ_HZ 50000000 +#define XPAR_XUARTPS_0_HAS_MODEM 0 + + +/******************************************************************/ + +/* Definitions for driver USBPS */ +#define XPAR_XUSBPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_USB_0 */ +#define XPAR_PS7_USB_0_DEVICE_ID 0 +#define XPAR_PS7_USB_0_BASEADDR 0xE0002000 +#define XPAR_PS7_USB_0_HIGHADDR 0xE0002FFF + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_USB_0 */ +#define XPAR_XUSBPS_0_DEVICE_ID XPAR_PS7_USB_0_DEVICE_ID +#define XPAR_XUSBPS_0_BASEADDR 0xE0002000 +#define XPAR_XUSBPS_0_HIGHADDR 0xE0002FFF + + +/******************************************************************/ + +/* Definitions for driver XADCPS */ +#define XPAR_XADCPS_NUM_INSTANCES 1 + +/* Definitions for peripheral PS7_XADC_0 */ +#define XPAR_PS7_XADC_0_DEVICE_ID 0 +#define XPAR_PS7_XADC_0_BASEADDR 0xF8007100 +#define XPAR_PS7_XADC_0_HIGHADDR 0xF8007120 + + +/******************************************************************/ + +/* Canonical definitions for peripheral PS7_XADC_0 */ +#define XPAR_XADCPS_0_DEVICE_ID XPAR_PS7_XADC_0_DEVICE_ID +#define XPAR_XADCPS_0_BASEADDR 0xF8007100 +#define XPAR_XADCPS_0_HIGHADDR 0xF8007120 + + +/******************************************************************/ + +/* Xilinx FAT File System Library (XilFFs) User Settings */ +#define FILE_SYSTEM_INTERFACE_SD +#define FILE_SYSTEM_USE_MKFS +#define FILE_SYSTEM_NUM_LOGIC_VOL 2 +#define FILE_SYSTEM_USE_STRFUNC 0 +#define FILE_SYSTEM_SET_FS_RPATH 0 +#define FILE_SYSTEM_WORD_ACCESS +#endif /* end of protection macro */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xparameters_ps.h b/bsp_z7/ps7_cortexa9_0/include/xparameters_ps.h new file mode 100644 index 0000000..f8b4e00 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xparameters_ps.h @@ -0,0 +1,334 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xparameters_ps.h +* +* This file contains the address definitions for the hard peripherals +* attached to the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 02/01/10 Initial version
+* 3.04a sdm     02/02/12 Removed some of the defines as they are being generated through
+*                        driver tcl
+* 5.0	pkp		01/16/15 Added interrupt ID definition of ttc for TEST APP
+* 6.6   srm     10/18/17 Added ARMA9 macro to identify CortexA9
+*
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef _XPARAMETERS_PS_H_ +#define _XPARAMETERS_PS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files *******************************/ + + +/************************** Constant Definitions *****************************/ + +/* + * This block contains constant declarations for the peripherals + * within the hardblock + */ + +/* Canonical definitions for DDR MEMORY */ +#define XPAR_DDR_MEM_BASEADDR 0x00000000U +#define XPAR_DDR_MEM_HIGHADDR 0x3FFFFFFFU + +/* Canonical definitions for Interrupts */ +#define XPAR_XUARTPS_0_INTR XPS_UART0_INT_ID +#define XPAR_XUARTPS_1_INTR XPS_UART1_INT_ID +#define XPAR_XUSBPS_0_INTR XPS_USB0_INT_ID +#define XPAR_XUSBPS_1_INTR XPS_USB1_INT_ID +#define XPAR_XIICPS_0_INTR XPS_I2C0_INT_ID +#define XPAR_XIICPS_1_INTR XPS_I2C1_INT_ID +#define XPAR_XSPIPS_0_INTR XPS_SPI0_INT_ID +#define XPAR_XSPIPS_1_INTR XPS_SPI1_INT_ID +#define XPAR_XCANPS_0_INTR XPS_CAN0_INT_ID +#define XPAR_XCANPS_1_INTR XPS_CAN1_INT_ID +#define XPAR_XGPIOPS_0_INTR XPS_GPIO_INT_ID +#define XPAR_XEMACPS_0_INTR XPS_GEM0_INT_ID +#define XPAR_XEMACPS_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_XEMACPS_1_INTR XPS_GEM1_INT_ID +#define XPAR_XEMACPS_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_XSDIOPS_0_INTR XPS_SDIO0_INT_ID +#define XPAR_XQSPIPS_0_INTR XPS_QSPI_INT_ID +#define XPAR_XSDIOPS_1_INTR XPS_SDIO1_INT_ID +#define XPAR_XWDTPS_0_INTR XPS_WDT_INT_ID +#define XPAR_XDCFG_0_INTR XPS_DVC_INT_ID +#define XPAR_SCUTIMER_INTR XPS_SCU_TMR_INT_ID +#define XPAR_SCUWDT_INTR XPS_SCU_WDT_INT_ID +#define XPAR_XTTCPS_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_XTTCPS_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_XTTCPS_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_XTTCPS_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_XTTCPS_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_XTTCPS_5_INTR XPS_TTC1_2_INT_ID +#define XPAR_XDMAPS_0_FAULT_INTR XPS_DMA0_ABORT_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_0 XPS_DMA0_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_1 XPS_DMA1_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_2 XPS_DMA2_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_3 XPS_DMA3_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_4 XPS_DMA4_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_5 XPS_DMA5_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_6 XPS_DMA6_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_7 XPS_DMA7_INT_ID + + +#define XPAR_XQSPIPS_0_LINEAR_BASEADDR XPS_QSPI_LINEAR_BASEADDR +#define XPAR_XPARPORTPS_CTRL_BASEADDR XPS_PARPORT_CRTL_BASEADDR + + + +/* Canonical definitions for DMAC */ + + +/* Canonical definitions for WDT */ + +/* Canonical definitions for SLCR */ +#define XPAR_XSLCR_NUM_INSTANCES 1U +#define XPAR_XSLCR_0_DEVICE_ID 0U +#define XPAR_XSLCR_0_BASEADDR XPS_SYS_CTRL_BASEADDR + +/* Canonical definitions for SCU GIC */ +#define XPAR_SCUGIC_NUM_INSTANCES 1U +#define XPAR_SCUGIC_SINGLE_DEVICE_ID 0U +#define XPAR_SCUGIC_CPU_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000100U) +#define XPAR_SCUGIC_DIST_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00001000U) +#define XPAR_SCUGIC_ACK_BEFORE 0U + +/* Canonical definitions for Global Timer */ +#define XPAR_GLOBAL_TMR_NUM_INSTANCES 1U +#define XPAR_GLOBAL_TMR_DEVICE_ID 0U +#define XPAR_GLOBAL_TMR_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000200U) +#define XPAR_GLOBAL_TMR_INTR XPS_GLOBAL_TMR_INT_ID + + +/* Xilinx Parallel Flash Library (XilFlash) User Settings */ +#define XPAR_AXI_EMC + + +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ + + +/* + * This block contains constant declarations for the peripherals + * within the hardblock. These have been put for bacwards compatibility + */ + +#define XPS_PERIPHERAL_BASEADDR 0xE0000000U +#define XPS_UART0_BASEADDR 0xE0000000U +#define XPS_UART1_BASEADDR 0xE0001000U +#define XPS_USB0_BASEADDR 0xE0002000U +#define XPS_USB1_BASEADDR 0xE0003000U +#define XPS_I2C0_BASEADDR 0xE0004000U +#define XPS_I2C1_BASEADDR 0xE0005000U +#define XPS_SPI0_BASEADDR 0xE0006000U +#define XPS_SPI1_BASEADDR 0xE0007000U +#define XPS_CAN0_BASEADDR 0xE0008000U +#define XPS_CAN1_BASEADDR 0xE0009000U +#define XPS_GPIO_BASEADDR 0xE000A000U +#define XPS_GEM0_BASEADDR 0xE000B000U +#define XPS_GEM1_BASEADDR 0xE000C000U +#define XPS_QSPI_BASEADDR 0xE000D000U +#define XPS_PARPORT_CRTL_BASEADDR 0xE000E000U +#define XPS_SDIO0_BASEADDR 0xE0100000U +#define XPS_SDIO1_BASEADDR 0xE0101000U +#define XPS_IOU_BUS_CFG_BASEADDR 0xE0200000U +#define XPS_NAND_BASEADDR 0xE1000000U +#define XPS_PARPORT0_BASEADDR 0xE2000000U +#define XPS_PARPORT1_BASEADDR 0xE4000000U +#define XPS_QSPI_LINEAR_BASEADDR 0xFC000000U +#define XPS_SYS_CTRL_BASEADDR 0xF8000000U /* AKA SLCR */ +#define XPS_TTC0_BASEADDR 0xF8001000U +#define XPS_TTC1_BASEADDR 0xF8002000U +#define XPS_DMAC0_SEC_BASEADDR 0xF8003000U +#define XPS_DMAC0_NON_SEC_BASEADDR 0xF8004000U +#define XPS_WDT_BASEADDR 0xF8005000U +#define XPS_DDR_CTRL_BASEADDR 0xF8006000U +#define XPS_DEV_CFG_APB_BASEADDR 0xF8007000U +#define XPS_AFI0_BASEADDR 0xF8008000U +#define XPS_AFI1_BASEADDR 0xF8009000U +#define XPS_AFI2_BASEADDR 0xF800A000U +#define XPS_AFI3_BASEADDR 0xF800B000U +#define XPS_OCM_BASEADDR 0xF800C000U +#define XPS_EFUSE_BASEADDR 0xF800D000U +#define XPS_CORESIGHT_BASEADDR 0xF8800000U +#define XPS_TOP_BUS_CFG_BASEADDR 0xF8900000U +#define XPS_SCU_PERIPH_BASE 0xF8F00000U +#define XPS_L2CC_BASEADDR 0xF8F02000U +#define XPS_SAM_RAM_BASEADDR 0xFFFC0000U +#define XPS_FPGA_AXI_S0_BASEADDR 0x40000000U +#define XPS_FPGA_AXI_S1_BASEADDR 0x80000000U +#define XPS_IOU_S_SWITCH_BASEADDR 0xE0000000U +#define XPS_PERIPH_APB_BASEADDR 0xF8000000U + +/* Shared Peripheral Interrupts (SPI) */ +#define XPS_CORE_PARITY0_INT_ID 32U +#define XPS_CORE_PARITY1_INT_ID 33U +#define XPS_L2CC_INT_ID 34U +#define XPS_OCMINTR_INT_ID 35U +#define XPS_ECC_INT_ID 36U +#define XPS_PMU0_INT_ID 37U +#define XPS_PMU1_INT_ID 38U +#define XPS_SYSMON_INT_ID 39U +#define XPS_DVC_INT_ID 40U +#define XPS_WDT_INT_ID 41U +#define XPS_TTC0_0_INT_ID 42U +#define XPS_TTC0_1_INT_ID 43U +#define XPS_TTC0_2_INT_ID 44U +#define XPS_DMA0_ABORT_INT_ID 45U +#define XPS_DMA0_INT_ID 46U +#define XPS_DMA1_INT_ID 47U +#define XPS_DMA2_INT_ID 48U +#define XPS_DMA3_INT_ID 49U +#define XPS_SMC_INT_ID 50U +#define XPS_QSPI_INT_ID 51U +#define XPS_GPIO_INT_ID 52U +#define XPS_USB0_INT_ID 53U +#define XPS_GEM0_INT_ID 54U +#define XPS_GEM0_WAKE_INT_ID 55U +#define XPS_SDIO0_INT_ID 56U +#define XPS_I2C0_INT_ID 57U +#define XPS_SPI0_INT_ID 58U +#define XPS_UART0_INT_ID 59U +#define XPS_CAN0_INT_ID 60U +#define XPS_FPGA0_INT_ID 61U +#define XPS_FPGA1_INT_ID 62U +#define XPS_FPGA2_INT_ID 63U +#define XPS_FPGA3_INT_ID 64U +#define XPS_FPGA4_INT_ID 65U +#define XPS_FPGA5_INT_ID 66U +#define XPS_FPGA6_INT_ID 67U +#define XPS_FPGA7_INT_ID 68U +#define XPS_TTC1_0_INT_ID 69U +#define XPS_TTC1_1_INT_ID 70U +#define XPS_TTC1_2_INT_ID 71U +#define XPS_DMA4_INT_ID 72U +#define XPS_DMA5_INT_ID 73U +#define XPS_DMA6_INT_ID 74U +#define XPS_DMA7_INT_ID 75U +#define XPS_USB1_INT_ID 76U +#define XPS_GEM1_INT_ID 77U +#define XPS_GEM1_WAKE_INT_ID 78U +#define XPS_SDIO1_INT_ID 79U +#define XPS_I2C1_INT_ID 80U +#define XPS_SPI1_INT_ID 81U +#define XPS_UART1_INT_ID 82U +#define XPS_CAN1_INT_ID 83U +#define XPS_FPGA8_INT_ID 84U +#define XPS_FPGA9_INT_ID 85U +#define XPS_FPGA10_INT_ID 86U +#define XPS_FPGA11_INT_ID 87U +#define XPS_FPGA12_INT_ID 88U +#define XPS_FPGA13_INT_ID 89U +#define XPS_FPGA14_INT_ID 90U +#define XPS_FPGA15_INT_ID 91U + +/* Private Peripheral Interrupts (PPI) */ +#define XPS_GLOBAL_TMR_INT_ID 27U /* SCU Global Timer interrupt */ +#define XPS_FIQ_INT_ID 28U /* FIQ from FPGA fabric */ +#define XPS_SCU_TMR_INT_ID 29U /* SCU Private Timer interrupt */ +#define XPS_SCU_WDT_INT_ID 30U /* SCU Private WDT interrupt */ +#define XPS_IRQ_INT_ID 31U /* IRQ from FPGA fabric */ + + +/* REDEFINES for TEST APP */ +/* Definitions for UART */ +#define XPAR_PS7_UART_0_INTR XPS_UART0_INT_ID +#define XPAR_PS7_UART_1_INTR XPS_UART1_INT_ID +#define XPAR_PS7_USB_0_INTR XPS_USB0_INT_ID +#define XPAR_PS7_USB_1_INTR XPS_USB1_INT_ID +#define XPAR_PS7_I2C_0_INTR XPS_I2C0_INT_ID +#define XPAR_PS7_I2C_1_INTR XPS_I2C1_INT_ID +#define XPAR_PS7_SPI_0_INTR XPS_SPI0_INT_ID +#define XPAR_PS7_SPI_1_INTR XPS_SPI1_INT_ID +#define XPAR_PS7_CAN_0_INTR XPS_CAN0_INT_ID +#define XPAR_PS7_CAN_1_INTR XPS_CAN1_INT_ID +#define XPAR_PS7_GPIO_0_INTR XPS_GPIO_INT_ID +#define XPAR_PS7_ETHERNET_0_INTR XPS_GEM0_INT_ID +#define XPAR_PS7_ETHERNET_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_PS7_ETHERNET_1_INTR XPS_GEM1_INT_ID +#define XPAR_PS7_ETHERNET_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_PS7_QSPI_0_INTR XPS_QSPI_INT_ID +#define XPAR_PS7_WDT_0_INTR XPS_WDT_INT_ID +#define XPAR_PS7_SCUWDT_0_INTR XPS_SCU_WDT_INT_ID +#define XPAR_PS7_SCUTIMER_0_INTR XPS_SCU_TMR_INT_ID +#define XPAR_PS7_XADC_0_INTR XPS_SYSMON_INT_ID +#define XPAR_PS7_TTC_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_PS7_TTC_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_PS7_TTC_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_PS7_TTC_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_PS7_TTC_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_PS7_TTC_5_INTR XPS_TTC1_2_INT_ID + +#define XPAR_XADCPS_INT_ID XPS_SYSMON_INT_ID + +/* For backwards compatibility */ +#define XPAR_XUARTPS_0_CLOCK_HZ XPAR_XUARTPS_0_UART_CLK_FREQ_HZ +#define XPAR_XUARTPS_1_CLOCK_HZ XPAR_XUARTPS_1_UART_CLK_FREQ_HZ +#define XPAR_XTTCPS_0_CLOCK_HZ XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_1_CLOCK_HZ XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_2_CLOCK_HZ XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_3_CLOCK_HZ XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_4_CLOCK_HZ XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_5_CLOCK_HZ XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ +#define XPAR_XIICPS_0_CLOCK_HZ XPAR_XIICPS_0_I2C_CLK_FREQ_HZ +#define XPAR_XIICPS_1_CLOCK_HZ XPAR_XIICPS_1_I2C_CLK_FREQ_HZ + +#define XPAR_XQSPIPS_0_CLOCK_HZ XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ + +#ifdef XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#endif + +#ifdef XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#endif + +#define XPAR_SCUTIMER_DEVICE_ID 0U +#define XPAR_SCUWDT_DEVICE_ID 0U + +/* + * Defines for interrupt wrapper API + * For more details about usage please refer xinterrupt_wrap.h + * Here Bits[11:0] represents interrupt id + * Bits[15:12] represents interrupt trigger type and level flags + */ +#define XPAR_PS7_SCUTIMER_0_INTERRUPT_ID 0x10000D +#define XPAR_PS7_TTC_0_INTERRUPT_ID 0x400A +#define XPAR_PS7_TTC_1_INTERRUPT_ID 0x400B +#define XPAR_PS7_TTC_2_INTERRUPT_ID 0x400C +#define XPAR_PS7_TTC_3_INTERRUPT_ID 0x4025 +#define XPAR_PS7_TTC_4_INTERRUPT_ID 0x4026 +#define XPAR_PS7_TTC_5_INTERRUPT_ID 0x4027 + + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ + +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xplatform_info.c b/bsp_z7/ps7_cortexa9_0/include/xplatform_info.c new file mode 100644 index 0000000..83692d8 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xplatform_info.c @@ -0,0 +1,206 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xplatform_info.c +* @addtogroup common_platform_info Hardware Platform Information +* @{ +* This file contains information about hardware for which the code is built +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 5.00  pkp  12/15/14 Initial release
+* 5.04  pkp  01/12/16 Added platform information support for Cortex-A53 32bit
+*					  mode
+* 6.00  mus  17/08/16 Removed unused variable from XGetPlatform_Info
+* 6.4   ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                     function for PMUFW.
+*       ms   06/13/17 Added PSU_PMU macro to provide support of
+*                     XGetPlatform_Info function for PMUFW.
+*       mus  08/17/17 Add EL1 NS mode support for
+*                     XGet_Zynq_UltraMp_Platform_info and XGetPSVersion_Info
+*                     APIs.
+* 7.0	aru 03/15/19  Check for versal before aarch64 and armr5
+*		      in XGetPlatform_Info()
+* 7.2   adk 08/01/20  Added versal support for the XGetPSVersion_Info function.
+* 7.6   mus 08/23/21  Updated prototypes for functions which are not taking any
+*                     arguments with void keyword. This has been done to fix
+*                     compilation warnings with "-Wstrict-prototypes" flag.
+*                     It fixes CR#1108601.
+* 7.6    mus 08/30/21 Updated flag checking to fix compilation warnings
+*                     reported with "-Wundef" flag. It fixes CR#1108601.
+
+* 7.7    mus 11/02/21 Updated XGet_Zynq_UltraMp_Platform_info and
+*                     XGetPSVersion_Info to fix compilation warning
+*                     reported with "-Wundef" flag CR#1111453
+* 8.1    mus 02/13/23 Added new API's XGetCoreId and XGetClusterId. As of now
+*                     they are supported only for VERSAL_NET APU and RPU.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" +#include "xplatform_info.h" +#if defined (__aarch64__) +#include "bspconfig.h" +#include "xil_smc.h" +#endif +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about platform +* +* @return The information about platform defined in xplatform_info.h +* +******************************************************************************/ +u32 XGetPlatform_Info(void) +{ +#if defined (versal) + return XPLAT_VERSAL; +#elif defined (ARMR5) || defined (__aarch64__) || defined (ARMA53_32) || defined (PSU_PMU) + return XPLAT_ZYNQ_ULTRA_MP; +#elif defined (__microblaze__) + return XPLAT_MICROBLAZE; +#else + return XPLAT_ZYNQ; +#endif +} + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about zynq ultrascale MP platform +* +* @return The information about zynq ultrascale MP platform defined in +* xplatform_info.h +* +******************************************************************************/ +#if defined (ARMR5) || defined (__aarch64__) || defined (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info(void) +{ +#if defined (__aarch64__) && (EL1_NONSECURE == 1) + XSmc_OutVar reg; + /* + * This SMC call will return, + * idcode - upper 32 bits of reg.Arg0 + * version - lower 32 bits of reg.Arg1 + */ + reg = Xil_Smc(GET_CHIPID_SMC_FID,0,0, 0, 0, 0, 0, 0); + return (u32)((reg.Arg1 >> XPLAT_INFO_SHIFT) & XPLAT_INFO_MASK); +#else + u32 reg; + reg = ((Xil_In32(XPLAT_PS_VERSION_ADDRESS) >> XPLAT_INFO_SHIFT ) + & XPLAT_INFO_MASK); + return reg; +#endif +} +#endif + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about PS Silicon version +* +* @return The information about PS Silicon version. +* +******************************************************************************/ +#if defined (ARMR5) || defined (__aarch64__) || defined (ARMA53_32) || defined (PSU_PMU) || defined (versal) +u32 XGetPSVersion_Info(void) +{ +#if defined (__aarch64__) && (EL1_NONSECURE == 1) + /* + * This SMC call will return, + * idcode - upper 32 bits of reg.Arg0 + * version - lower 32 bits of reg.Arg1 + */ + XSmc_OutVar reg; + reg = Xil_Smc(GET_CHIPID_SMC_FID,0,0, 0, 0, 0, 0, 0); + return (u32)((reg.Arg1 & XPS_VERSION_INFO_MASK) >> + XPS_VERSION_INFO_SHIFT); +#else + u32 reg; + reg = (Xil_In32(XPLAT_PS_VERSION_ADDRESS) + & XPS_VERSION_INFO_MASK); + return (reg >> XPS_VERSION_INFO_SHIFT); +#endif +} +#endif + +#if (defined (__aarch64__) && defined (VERSAL_NET)) || defined (ARMR52) +/*****************************************************************************/ +/** +* +* @brief This API is used to provide infomation about cluster id of the +* CPU core from which it is executed. +* +* @return Cluster id of the core on which API is executed. +* +******************************************************************************/ +u8 XGetClusterId(void) +{ + u64 ClusterId = 0; + +#if defined (ARMR52) + ClusterId = (mfcp(XREG_CP15_MULTI_PROC_AFFINITY) & XREG_MPIDR_MASK); + ClusterId = ((ClusterId & XREG_MPIDR_AFFINITY1_MASK) >> \ + XREG_MPIDR_AFFINITY1_SHIFT); +#else + ClusterId = (mfcp(MPIDR_EL1) & XREG_MPIDR_MASK); + ClusterId = ((ClusterId & XREG_MPIDR_AFFINITY2_MASK) >> \ + XREG_MPIDR_AFFINITY2_SHIFT); +#endif + + return (u8)ClusterId; +} + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide infomation about core id of the +* CPU core from which it is executed. +* +* @return Core id of the core on which API is executed. +* +******************************************************************************/ +u8 XGetCoreId(void) +{ + u64 CoreId; + +#if defined (ARMR52) + CoreId = (mfcp(XREG_CP15_MULTI_PROC_AFFINITY) & XREG_MPIDR_MASK); + CoreId = ((CoreId & XREG_MPIDR_AFFINITY0_MASK) >> \ + XREG_MPIDR_AFFINITY0_SHIFT); +#else + CoreId = (mfcp(MPIDR_EL1) & XREG_MPIDR_MASK); + CoreId = ((CoreId & XREG_MPIDR_AFFINITY1_MASK) >> \ + XREG_MPIDR_AFFINITY1_SHIFT); +#endif + + return (u8)CoreId; +} + +#endif + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xplatform_info.h b/bsp_z7/ps7_cortexa9_0/include/xplatform_info.h new file mode 100644 index 0000000..3e5df15 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xplatform_info.h @@ -0,0 +1,124 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xplatform_info.h +* +* +* @addtogroup common_platform_info APIs to Get Platform Information +* +* +* The xplatform_info.h file contains definitions for various available Xilinx® +* platforms. Also, it contains prototype of APIs, which can be used to get the +* platform information. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date    Changes
+* ----- ---- --------- -------------------------------------------------------
+* 6.4    ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                      function for PMUFW.
+* 7.2    adk  08/01/20 Added versal support for the XGetPSVersion_Info function.
+* 7.6    mus  08/23/21 Updated prototypes for functions which are not taking any
+*                      arguments with void keyword. This has been done to fix
+*                      compilation warnings with "-Wstrict-prototypes" flag.
+*                      It fixes CR#1108601.
+* 7.6    mus  08/30/21 Updated flag checking to fix compilation warnings
+*                      reported with "-Wundef" flag.
+* 7.7	 sk   01/10/22 Update XPLAT_INFO_MASK from signed to unsigned to fix
+*		       misra_c_2012_rule_10_4 violation.
+* 8.1    mus  02/13/23 Added new API's XGetCoreId and XGetClusterId. As of now
+*                      they are supported only for VERSAL_NET APU and RPU.
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XPLATFORM_INFO_H /* prevent circular inclusions */ +#define XPLATFORM_INFO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +#if defined (versal) +#define XPAR_PMC_TAP_BASEADDR 0xF11A0000U +#define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \ + XPAR_PMC_TAP_VERSION_OFFSET) +#else +#define XPAR_CSU_BASEADDR 0xFFCA0000U +#define XPAR_CSU_VER_OFFSET 0x00000044U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \ + XPAR_CSU_VER_OFFSET) +#endif +#define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0 +#define XPLAT_ZYNQ_ULTRA_MP 0x1 +#define XPLAT_ZYNQ_ULTRA_MPVEL 0x2 +#define XPLAT_ZYNQ_ULTRA_MPQEMU 0x3 +#define XPLAT_ZYNQ 0x4 +#define XPLAT_MICROBLAZE 0x5 +#define XPLAT_VERSAL 0x6U + +#define XPS_VERSION_1 0x0 +#define XPS_VERSION_2 0x1 +#define XPLAT_INFO_MASK (0xFU) + +#if defined (versal) +#define XPS_VERSION_INFO_MASK 0xFF00U +#define XPS_VERSION_INFO_SHIFT 0x8U +#define XPLAT_INFO_SHIFT 0x18U +#else +#define XPS_VERSION_INFO_MASK (0xF) +#define XPS_VERSION_INFO_SHIFT 0x0U +#define XPLAT_INFO_SHIFT 0xCU +#endif + +/**************************** Type Definitions *******************************/ +/** + *@endcond + */ +/***************** Macros (Inline Functions) Definitions *********************/ + + +u32 XGetPlatform_Info(void); + +#if defined (ARMR5) || defined (__aarch64__) || defined (ARMA53_32) || defined (PSU_PMU) || defined (versal) +u32 XGetPSVersion_Info(void); +#endif + +#if defined (ARMR5) || defined (__aarch64__) || defined (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info(void); +#endif + +#if (defined (__aarch64__) && defined (VERSAL_NET)) || defined (ARMR52) +u8 XGetClusterId(void); +u8 XGetCoreId(void); +#endif + +/************************** Function Prototypes ******************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_platform_info". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xpm_counter.h b/bsp_z7/ps7_cortexa9_0/include/xpm_counter.h new file mode 100644 index 0000000..8b09ef5 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xpm_counter.h @@ -0,0 +1,575 @@ +/****************************************************************************** +* Copyright (c) 2011 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xpm_counter.h +* +* @addtogroup a9_event_counter_apis Cortex A9 Event Counters Functions +* +* Cortex A9 event counter functions can be utilized to configure and control +* the Cortex-A9 performance monitor events. +* +* Cortex-A9 performance monitor has six event counters which can be used to +* count a variety of events described in Coretx-A9 TRM. xpm_counter.h defines +* configurations XPM_CNTRCFGx which can be used to program the event counters +* to count a set of events. +* +* @note +* It doesn't handle the Cortex-A9 cycle counter, as the cycle counter is +* being used for time keeping. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 8.0   mus  07/07/22 Added prototype for new APIs as per consolidated
+*                     xpm_counter.c.
+* 
+* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef XPMCOUNTER_H /* prevent circular inclusions */ +#define XPMCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* Number of performance counters */ +#define XPM_CTRCOUNT 6U + +/* The following constants define the Cortex-A9 Performance Monitor Events */ + +/* + * Software increment. The register is incremented only on writes to the + * Software Increment Register + */ +#define XPM_EVENT_SOFTINCR 0x00U + +/* + * Instruction fetch that causes a refill at (at least) the lowest level(s) of + * instruction or unified cache. Includes the speculative linefills in the + * count + */ +#define XPM_EVENT_INSRFETCH_CACHEREFILL 0x01U + +/* + * Instruction fetch that causes a TLB refill at (at least) the lowest level of + * TLB. Includes the speculative requests in the count + */ +#define XPM_EVENT_INSTRFECT_TLBREFILL 0x02U + +/* + * Data read or write operation that causes a refill at (at least) the lowest + * level(s)of data or unified cache. Counts the number of allocations performed + * in the Data Cache due to a read or a write + */ +#define XPM_EVENT_DATA_CACHEREFILL 0x03U + +/* + * Data read or write operation that causes a cache access at (at least) the + * lowest level(s) of data or unified cache. This includes speculative reads + */ +#define XPM_EVENT_DATA_CACHEACCESS 0x04U + +/* + * Data read or write operation that causes a TLB refill at (at least) the + * lowest level of TLB. This does not include micro TLB misses due to PLD, PLI, + * CP15 Cache operation by MVA and CP15 VA to PA operations + */ +#define XPM_EVENT_DATA_TLBREFILL 0x05U + +/* + * Data read architecturally executed. Counts the number of data read + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted LDR/LDM, as well as the reads due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_READS 0x06U + +/* + * Data write architecturally executed. Counts the number of data write + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted STR/STM, as well as the writes due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_WRITE 0x07U + +/* Exception taken. Counts the number of exceptions architecturally taken.*/ +#define XPM_EVENT_EXCEPTION 0x09U + +/* Exception return architecturally executed.*/ +#define XPM_EVENT_EXCEPRETURN 0x0AU + +/* + * Change to ContextID retired. Counts the number of instructions + * architecturally executed writing into the ContextID Register + */ +#define XPM_EVENT_CHANGECONTEXT 0x0BU + +/* + * Software change of PC, except by an exception, architecturally executed. + * Count the number of PC changes architecturally executed, excluding the PC + * changes due to taken exceptions + */ +#define XPM_EVENT_SW_CHANGEPC 0x0CU + +/* + * Immediate branch architecturally executed (taken or not taken). This includes + * the branches which are flushed due to a previous load/store which aborts + * late + */ +#define XPM_EVENT_IMMEDBRANCH 0x0DU + +/* + * Unaligned access architecturally executed. Counts the number of aborted + * unaligned accessed architecturally executed, and the number of not-aborted + * unaligned accesses, including the speculative ones + */ +#define XPM_EVENT_UNALIGNEDACCESS 0x0FU + +/* + * Branch mispredicted/not predicted. Counts the number of mispredicted or + * not-predicted branches executed. This includes the branches which are flushed + * due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHMISS 0x10U + +/* + * Counts clock cycles when the Cortex-A9 processor is not in WFE/WFI. This + * event is not exported on the PMUEVENT bus + */ +#define XPM_EVENT_CLOCKCYCLES 0x11U + +/* + * Branches or other change in program flow that could have been predicted by + * the branch prediction resources of the processor. This includes the branches + * which are flushed due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHPREDICT 0x12U + +/* + * Java bytecode execute. Counts the number of Java bytecodes being decoded, + * including speculative ones + */ +#define XPM_EVENT_JAVABYTECODE 0x40U + +/* + * Software Java bytecode executed. Counts the number of software java bytecodes + * being decoded, including speculative ones + */ +#define XPM_EVENT_SWJAVABYTECODE 0x41U + +/* + * Jazelle backward branches executed. Counts the number of Jazelle taken + * branches being executed. This includes the branches which are flushed due + * to a previous load/store which aborts late + */ +#define XPM_EVENT_JAVABACKBRANCH 0x42U + +/* + * Coherent linefill miss Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which also miss in all the other + * Cortex-A9 processors, meaning that the request is sent to the external + * memory + */ +#define XPM_EVENT_COHERLINEMISS 0x50U + +/* + * Coherent linefill hit. Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which hit in another Cortex-A9 + * processor, meaning that the linefill data is fetched directly from the + * relevant Cortex-A9 cache + */ +#define XPM_EVENT_COHERLINEHIT 0x51U + +/* + * Instruction cache dependent stall cycles. Counts the number of cycles where + * the processor is ready to accept new instructions, but does not receive any + * due to the instruction side not being able to provide any and the + * instruction cache is currently performing at least one linefill + */ +#define XPM_EVENT_INSTRSTALL 0x60U + +/* + * Data cache dependent stall cycles. Counts the number of cycles where the core + * has some instructions that it cannot issue to any pipeline, and the Load + * Store unit has at least one pending linefill request, and no pending + */ +#define XPM_EVENT_DATASTALL 0x61U + +/* + * Main TLB miss stall cycles. Counts the number of cycles where the processor + * is stalled waiting for the completion of translation table walks from the + * main TLB. The processor stalls can be due to the instruction side not being + * able to provide the instructions, or to the data side not being able to + * provide the necessary data, due to them waiting for the main TLB translation + * table walk to complete + */ +#define XPM_EVENT_MAINTLBSTALL 0x62U + +/* + * Counts the number of STREX instructions architecturally executed and + * passed + */ +#define XPM_EVENT_STREXPASS 0x63U + +/* + * Counts the number of STREX instructions architecturally executed and + * failed + */ +#define XPM_EVENT_STREXFAIL 0x64U + +/* + * Data eviction. Counts the number of eviction requests due to a linefill in + * the data cache + */ +#define XPM_EVENT_DATAEVICT 0x65U + +/* + * Counts the number of cycles where the issue stage does not dispatch any + * instruction because it is empty or cannot dispatch any instructions + */ +#define XPM_EVENT_NODISPATCH 0x66U + +/* + * Counts the number of cycles where the issue stage is empty + */ +#define XPM_EVENT_ISSUEEMPTY 0x67U + +/* + * Counts the number of instructions going through the Register Renaming stage. + * This number is an approximate number of the total number of instructions + * speculatively executed, and even more approximate of the total number of + * instructions architecturally executed. The approximation depends mainly on + * the branch misprediction rate. + * The renaming stage can handle two instructions in the same cycle so the event + * is two bits long: + * - b00 no instructions renamed + * - b01 one instruction renamed + * - b10 two instructions renamed + */ +#define XPM_EVENT_INSTRRENAME 0x68U + +/* + * Counts the number of procedure returns whose condition codes do not fail, + * excluding all returns from exception. This count includes procedure returns + * which are flushed due to a previous load/store which aborts late. + * Only the following instructions are reported: + * - BX R14 + * - MOV PC LR + * - POP {..,pc} + * - LDR pc,[sp],#offset + * The following instructions are not reported: + * - LDMIA R9!,{..,PC} (ThumbEE state only) + * - LDR PC,[R9],#offset (ThumbEE state only) + * - BX R0 (Rm != R14) + * - MOV PC,R0 (Rm != R14) + * - LDM SP,{...,PC} (writeback not specified) + * - LDR PC,[SP,#offset] (wrong addressing mode) + */ +#define XPM_EVENT_PREDICTFUNCRET 0x6EU + +/* + * Counts the number of instructions being executed in the main execution + * pipeline of the processor, the multiply pipeline and arithmetic logic unit + * pipeline. The counted instructions are still speculative + */ +#define XPM_EVENT_MAINEXEC 0x70U + +/* + * Counts the number of instructions being executed in the processor second + * execution pipeline (ALU). The counted instructions are still speculative + */ +#define XPM_EVENT_SECEXEC 0x71U + +/* + * Counts the number of instructions being executed in the Load/Store unit. The + * counted instructions are still speculative + */ +#define XPM_EVENT_LDRSTR 0x72U + +/* + * Counts the number of Floating-point instructions going through the Register + * Rename stage. Instructions are still speculative in this stage. + *Two floating-point instructions can be renamed in the same cycle so the event + * is two bitslong: + *0b00 no floating-point instruction renamed + *0b01 one floating-point instruction renamed + *0b10 two floating-point instructions renamed + */ +#define XPM_EVENT_FLOATRENAME 0x73U + +/* + * Counts the number of Neon instructions going through the Register Rename + * stage.Instructions are still speculative in this stage. + * Two NEON instructions can be renamed in the same cycle so the event is two + * bits long: + *0b00 no NEON instruction renamed + *0b01 one NEON instruction renamed + *0b10 two NEON instructions renamed + */ +#define XPM_EVENT_NEONRENAME 0x74U + +/* + * Counts the number of cycles where the processor is stalled because PLD slots + * are all full + */ +#define XPM_EVENT_PLDSTALL 0x80U + +/* + * Counts the number of cycles when the processor is stalled and the data side + * is stalled too because it is full and executing writes to the external + * memory + */ +#define XPM_EVENT_WRITESTALL 0x81U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the instruction side + */ +#define XPM_EVENT_INSTRTLBSTALL 0x82U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the data side + */ +#define XPM_EVENT_DATATLBSTALL 0x83U + +/* + * Counts the number of stall cycles due to micro TLB misses on the instruction + * side. This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_INSTR_uTLBSTALL 0x84U + +/* + * Counts the number of stall cycles due to micro TLB misses on the data side. + * This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_DATA_uTLBSTALL 0x85U + +/* + * Counts the number of stall cycles because of the execution of a DMB memory + * barrier. This includes all DMB instructions being executed, even + * speculatively + */ +#define XPM_EVENT_DMB_STALL 0x86U + +/* + * Counts the number of cycles during which the integer core clock is enabled + */ +#define XPM_EVENT_INT_CLKEN 0x8AU + +/* + * Counts the number of cycles during which the Data Engine clock is enabled + */ +#define XPM_EVENT_DE_CLKEN 0x8BU + +/* + * Counts the number of ISB instructions architecturally executed + */ +#define XPM_EVENT_INSTRISB 0x90U + +/* + * Counts the number of DSB instructions architecturally executed + */ +#define XPM_EVENT_INSTRDSB 0x91U + +/* + * Counts the number of DMB instructions speculatively executed + */ +#define XPM_EVENT_INSTRDMB 0x92U + +/* + * Counts the number of external interrupts executed by the processor + */ +#define XPM_EVENT_EXTINT 0x93U + +/* + * PLE cache line request completed + */ +#define XPM_EVENT_PLE_LRC 0xA0U + +/* + * PLE cache line request skipped + */ +#define XPM_EVENT_PLE_LRS 0xA1U + +/* + * PLE FIFO flush + */ +#define XPM_EVENT_PLE_FLUSH 0xA2U + +/* + * PLE request complete + */ +#define XPM_EVENT_PLE_CMPL 0xA3U + +/* + * PLE FIFO overflow + */ +#define XPM_EVENT_PLE_OVFL 0xA4U + +/* + * PLE request programmed + */ +#define XPM_EVENT_PLE_PROG 0xA5U + +/* + * The following constants define the configurations for Cortex-A9 Performance + * Monitor Events. Each configuration configures the event counters for a set + * of events. + * ----------------------------------------------- + * Config PmCtr0... PmCtr5 + * ----------------------------------------------- + * XPM_CNTRCFG1 { XPM_EVENT_SOFTINCR, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + * + * XPM_CNTRCFG2 { XPM_EVENT_DATA_READS, + * XPM_EVENT_DATA_WRITE, + * XPM_EVENT_EXCEPTION, + * XPM_EVENT_EXCEPRETURN, + * XPM_EVENT_CHANGECONTEXT, + * XPM_EVENT_SW_CHANGEPC } + * + * XPM_CNTRCFG3 { XPM_EVENT_IMMEDBRANCH, + * XPM_EVENT_UNALIGNEDACCESS, + * XPM_EVENT_BRANCHMISS, + * XPM_EVENT_CLOCKCYCLES, + * XPM_EVENT_BRANCHPREDICT, + * XPM_EVENT_JAVABYTECODE } + * + * XPM_CNTRCFG4 { XPM_EVENT_SWJAVABYTECODE, + * XPM_EVENT_JAVABACKBRANCH, + * XPM_EVENT_COHERLINEMISS, + * XPM_EVENT_COHERLINEHIT, + * XPM_EVENT_INSTRSTALL, + * XPM_EVENT_DATASTALL } + * + * XPM_CNTRCFG5 { XPM_EVENT_MAINTLBSTALL, + * XPM_EVENT_STREXPASS, + * XPM_EVENT_STREXFAIL, + * XPM_EVENT_DATAEVICT, + * XPM_EVENT_NODISPATCH, + * XPM_EVENT_ISSUEEMPTY } + * + * XPM_CNTRCFG6 { XPM_EVENT_INSTRRENAME, + * XPM_EVENT_PREDICTFUNCRET, + * XPM_EVENT_MAINEXEC, + * XPM_EVENT_SECEXEC, + * XPM_EVENT_LDRSTR, + * XPM_EVENT_FLOATRENAME } + * + * XPM_CNTRCFG7 { XPM_EVENT_NEONRENAME, + * XPM_EVENT_PLDSTALL, + * XPM_EVENT_WRITESTALL, + * XPM_EVENT_INSTRTLBSTALL, + * XPM_EVENT_DATATLBSTALL, + * XPM_EVENT_INSTR_uTLBSTALL } + * + * XPM_CNTRCFG8 { XPM_EVENT_DATA_uTLBSTALL, + * XPM_EVENT_DMB_STALL, + * XPM_EVENT_INT_CLKEN, + * XPM_EVENT_DE_CLKEN, + * XPM_EVENT_INSTRISB, + * XPM_EVENT_INSTRDSB } + * + * XPM_CNTRCFG9 { XPM_EVENT_INSTRDMB, + * XPM_EVENT_EXTINT, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG10 { XPM_EVENT_PLE_OVFL, + * XPM_EVENT_PLE_PROG, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG11 { XPM_EVENT_DATASTALL, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + */ +#define XPM_CNTRCFG1 0 +#define XPM_CNTRCFG2 1 +#define XPM_CNTRCFG3 2 +#define XPM_CNTRCFG4 3 +#define XPM_CNTRCFG5 4 +#define XPM_CNTRCFG6 5 +#define XPM_CNTRCFG7 6 +#define XPM_CNTRCFG8 7 +#define XPM_CNTRCFG9 8 +#define XPM_CNTRCFG10 9 +#define XPM_CNTRCFG11 10 + +#define XPM_NO_COUNTERS_AVAILABLE 0xFFU +#define XPM_MAX_EVENTHANDLER_ID 0x6U +#define XPM_EVENT_CNTRS_BIT_MASK 0x3FU +#define XPM_ALL_EVENT_CNTRS_IN_USE 0x3FU +#define XPM_EVENT_CNTRS_MASK 0x3FU +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ +#if defined(__GNUC__) +#define Xpm_ReadCycleCounterVal() mfcp(XREG_CP15_PERF_CYCLE_COUNTER) +#elif defined (__ICCARM__) +#define Xpm_ReadCycleCounterVal(val) mfcp(XREG_CP15_PERF_CYCLE_COUNTER,val) +#endif +/************************** Variable Definitions ****************************/ + +/** +*@endcond +*/ + +/************************** Function Prototypes *****************************/ + +/* Interface functions to access performance counters from abstraction layer */ +void Xpm_SetEvents(s32 PmcrCfg); +void Xpm_GetEventCounters(u32 *PmCtrValue); +u32 Xpm_DisableEvent(u32 EventCntrId); +void Xpm_DisableEventCounters(void); +void Xpm_EnableEventCounters (void); +void Xpm_ResetEventCounters (void); +u32 Xpm_SetUpAnEvent(u32 EventID); +u32 Xpm_GetEventCounter(u32 EventCntrId, u32 *CntVal); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_event_counter_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xpseudo_asm.h b/bsp_z7/ps7_cortexa9_0/include/xpseudo_asm.h new file mode 100644 index 0000000..6d07851 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xpseudo_asm.h @@ -0,0 +1,60 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xpseudo_asm.h +* +* @addtogroup a9_specific Cortex A9 Processor Specific Include Files +* +* The xpseudo_asm.h includes xreg_cortexa9.h and xpseudo_asm_gcc.h. +* +* The xreg_cortexa9.h file contains definitions for inline assembler code. +* It provides inline definitions for Cortex A9 GPRs, SPRs, MPE registers, +* co-processor registers and Debug registers. +* +* The xpseudo_asm_gcc.h contains the definitions for the most often used inline +* assembler instructions, available as macros. These can be very useful for +* tasks such as setting or getting special purpose registers, synchronization, +* or cache manipulation etc. These inline assembler instructions can be used +* from drivers and user applications written in C. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  10/18/09 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb in mcr instruction.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XPSEUDO_ASM_H +#define XPSEUDO_ASM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xreg_cortexa9.h" +#ifdef __GNUC__ + #include "xpseudo_asm_gcc.h" +#elif defined (__ICCARM__) + #include "xpseudo_asm_iccarm.h" +#else + #include "xpseudo_asm_rvct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XPSEUDO_ASM_H */ +/** +* @} End of "addtogroup a9_specific". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xpseudo_asm_gcc.h b/bsp_z7/ps7_cortexa9_0/include/xpseudo_asm_gcc.h new file mode 100644 index 0000000..b8517d3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xpseudo_asm_gcc.h @@ -0,0 +1,285 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xpseudo_asm_gcc.h +* +* This header file contains macros for using inline assembler code. It is +* written specifically for the GNU compiler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp		 05/21/14 First release
+* 6.0   mus      07/27/16 Consolidated file for a53,a9 and r5 processors
+* 7.2   asa      04/03/20 Renamed the str macro to strw.
+* 7.2   dp       04/30/20 Added clobber "cc" to mtcpsr for aarch32 processors
+* 8.0   mus      02/24/22 Added macro mfcpnotoken and mtcpnotoken.
+* 8.1   asa      02/13/23 Create macros to read ESR, FAR and ELR registers.
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XPSEUDO_ASM_GCC_H /* prevent circular inclusions */ +#define XPSEUDO_ASM_GCC_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "bspconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/* necessary for pre-processor */ +#define stringify(s) tostring(s) +#define tostring(s) #s + +#if defined (__aarch64__) +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + asm volatile("mrs %0, DAIF" : "=r" (rval));\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__ ("msr DAIF, %0" : : "r" (v)) + +#define cpsiei() //__asm__ __volatile__("cpsie i\n") +#define cpsidi() //__asm__ __volatile__("cpsid i\n") + +#define cpsief() //__asm__ __volatile__("cpsie f\n") +#define cpsidf() //__asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) /*__asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + )*/ + +#define mfgpr(rn) /*({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + })*/ + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb sy") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__("dsb sy") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__("dmb sy") + + +/* Memory Operations */ +#define ldr(adr) ({u64 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#if (EL3 == 1) +#define mfelrel3() ({u64 rval = 0U; \ + asm volatile("mrs %0, ELR_EL3" : "=r" (rval));\ + rval;\ + }) +#define mfesrel3() ({u64 rval = 0U; \ + asm volatile("mrs %0, ESR_EL3" : "=r" (rval));\ + rval;\ + }) + +#define mffarel3() ({u64 rval = 0U; \ + asm volatile("mrs %0, FAR_EL3" : "=r" (rval));\ + rval;\ + }) + +#else +#define mfelrel1() ({u64 rval = 0U; \ + asm volatile("mrs %0, ELR_EL1" : "=r" (rval));\ + rval;\ + }) + +#define mfesrel1() ({u64 rval = 0U; \ + asm volatile("mrs %0, ESR_EL1" : "=r" (rval));\ + rval;\ + }) + +#define mffarel1() ({u64 rval = 0U; \ + asm volatile("mrs %0, FAR_EL1" : "=r" (rval));\ + rval;\ + }) + + +#endif + +#define mtelrel3(v) __asm__ __volatile__ ("msr ELR_EL3, %0" : : "r" (v)) + +#else + +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrs %0, cpsr\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__(\ + "msr cpsr,%0\n"\ + : : "r" (v) : "cc" \ + ) + +#define cpsiei() __asm__ __volatile__("cpsie i\n") +#define cpsidi() __asm__ __volatile__("cpsid i\n") + +#define cpsief() __asm__ __volatile__("cpsie f\n") +#define cpsidf() __asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) __asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + ) + +#define mfgpr(rn) ({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb" : : : "memory") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__ ("dsb" : : : "memory") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__ ("dmb" : : : "memory") + + +/* Memory Operations */ +#define ldr(adr) ({u32 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#endif + +#define ldrb(adr) ({u8 rval; \ + __asm__ __volatile__(\ + "ldrb %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#define strw(adr, val) __asm__ __volatile__(\ + "str %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +#define strb(adr, val) __asm__ __volatile__(\ + "strb %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +/* Count leading zeroes (clz) */ +#define clz(arg) ({u8 rval; \ + __asm__ __volatile__(\ + "clz %0,%1"\ + : "=r" (rval) : "r" (arg)\ + );\ + rval;\ + }) + +#if defined (__aarch64__) +#define mtcpdc(reg,val) __asm__ __volatile__("dc " #reg ",%0" : : "r" (val)) +#define mtcpic(reg,val) __asm__ __volatile__("ic " #reg ",%0" : : "r" (val)) + +#define mtcpicall(reg) __asm__ __volatile__("ic " #reg) +#define mtcptlbi(reg) __asm__ __volatile__("tlbi " #reg) +#define mtcpat(reg,val) __asm__ __volatile__("at " #reg ",%0" : : "r" (val)) +/* CP15 operations */ +#define mfcp(reg) ({u64 rval = 0U;\ + __asm__ __volatile__("mrs %0, " #reg : "=r" (rval));\ + rval;\ + }) + +#define mfcpnotoken(reg) ({u64 rval = 0U;\ + __asm__ __volatile__("mrs %0, " reg : "=r" (rval));\ + rval;\ + }) + +#define mtcp(reg,val) __asm__ __volatile__("msr " #reg ",%0" : : "r" (val)) +#define mtcpnotoken(reg,val) __asm__ __volatile__("msr " reg ",%0" : : "r" (val)) + +#else +/* CP15 operations */ +#define mtcp(rn, v) __asm__ __volatile__(\ + "mcr " rn "\n"\ + : : "r" (v)\ + ); + +#define mfcp(rn) ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrc " rn "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +#define mtcp2(rn, v) __asm__ __volatile__(\ + "mcrr " rn "\n"\ + : : "r" (v), "r" (0)\ + ); + +#endif + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/** + *@endcond + */ + +#endif /* XPSEUDO_ASM_GCC_H */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xqspips.h b/bsp_z7/ps7_cortexa9_0/include/xqspips.h new file mode 100644 index 0000000..d7bae80 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xqspips.h @@ -0,0 +1,788 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xqspips.h +* @addtogroup qspips_v3_10 +* @{ +* @details +* +* This file contains the implementation of the XQspiPs driver. It supports only +* master mode. User documentation for the driver functions is contained in this +* file in the form of comment blocks at the front of each function. +* +* A QSPI device connects to an QSPI bus through a 4-wire serial interface. +* The QSPI bus is a full-duplex, synchronous bus that facilitates communication +* between one master and one slave. The device is always full-duplex, +* which means that for every byte sent, one is received, and vice-versa. +* The master controls the clock, so it can regulate when it wants to +* send or receive data. The slave is under control of the master, it must +* respond quickly since it has no control of the clock and must send/receive +* data as fast or as slow as the master does. +* +* Linear Mode +* The Linear Quad-SPI Controller extends the existing Quad-SPI Controller�s +* functionality by adding a linear addressing scheme that allows the SPI flash +* memory subsystem to behave like a typical ROM device. The new feature hides +* the normal SPI protocol from a master reading from the SPI flash memory. The +* feature improves both the user friendliness and the overall read memory +* throughput over that of the current Quad-SPI Controller by lessening the +* amount of software overheads required and by the use of the faster AXI +* interface. +* +* Initialization & Configuration +* +* The XQspiPs_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed by +* various operating systems, the driver instance can be initialized in the +* following way: +* - XQspiPs_LookupConfig(DeviceId) - Use the device identifier to find +* static configuration structure defined in xqspips_g.c. This is setup +* by the tools. For some operating systems the config structure will be +* initialized by the software and this call is not needed. +* - XQspiPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* Multiple Masters +* +* More than one master can exist, but arbitration is the responsibility of +* the higher layer software. The device driver does not perform any type of +* arbitration. +* +* Modes of Operation +* +* There are four modes to perform a data transfer and the selection of a mode +* is based on Chip Select(CS) and Start. These two options individually, can +* be controlled either by software(Manual) or hardware(Auto). +* - Auto CS: Chip select is automatically asserted as soon as the first word +* is written into the TXFIFO and de asserted when the TXFIFO becomes +* empty +* - Manual CS: Software must assert and de assert CS. +* - Auto Start: Data transmission starts as soon as there is data in the +* TXFIFO and stalls when the TXFIFO is empty +* - Manual Start: Software must start data transmission at the beginning of +* the transaction or whenever the TXFIFO has become empty +* +* The preferred combination is Manual CS and Auto Start. +* In this combination, the software asserts CS before loading any data into +* TXFIFO. In Auto Start mode, whenever data is in TXFIFO, controller sends it +* out until TXFIFO becomes empty. The software reads the RXFIFO whenever the +* data is available. If no further data, software disables CS. +* +* Risks/challenges of other combinations: +* - Manual CS and Manual Start: Manual Start bit should be set after each +* TXFIFO write otherwise there could be a race condition where the TXFIFO +* becomes empty before the new word is written. In that case the +* transmission stops. +* - Auto CS with Manual or Auto Start: It is very difficult for software to +* keep the TXFIFO filled. Whenever the TXFIFO runs empty, CS is de asserted. +* This results in a single transaction to be split into multiple pieces each +* with its own chip select. This will result in garbage data to be sent. +* +* Interrupts +* +* The user must connect the interrupt handler of the driver, +* XQspiPs_InterruptHandler, to an interrupt system such that it will be +* called when an interrupt occurs. This function does not save and restore +* the processor context such that the user must provide this processing. +* +* The driver handles the following interrupts: +* - Data Transmit Register/FIFO Underflow +* - Data Receive Register/FIFO Not Empty +* - Data Transmit Register/FIFO Overwater +* - Data Receive Register/FIFO Overrun +* +* The Data Transmit Register/FIFO Overwater interrupt -- indicates that the +* QSPI device has transmitted the data available to transmit, and now its data +* register and FIFO is ready to accept more data. The driver uses this +* interrupt to indicate progress while sending data. The driver may have +* more data to send, in which case the data transmit register and FIFO is +* filled for subsequent transmission. When this interrupt arrives and all +* the data has been sent, the driver invokes the status callback with a +* value of XST_SPI_TRANSFER_DONE to inform the upper layer software that +* all data has been sent. +* +* The Data Transmit Register/FIFO Underflow interrupt -- indicates that, +* as slave, the QSPI device was required to transmit but there was no data +* available to transmit in the transmit register (or FIFO). This may not +* be an error if the master is not expecting data. But in the case where +* the master is expecting data, this serves as a notification of such a +* condition. The driver reports this condition to the upper layer +* software through the status handler. +* +* The Data Receive Register/FIFO Overrun interrupt -- indicates that the QSPI +* device received data and subsequently dropped the data because the data +* receive register and FIFO was full. The driver reports this condition to the +* upper layer software through the status handler. This likely indicates a +* problem with the higher layer protocol, or a problem with the slave +* performance. +* +* +* Polled Operation +* +* Transfer in polled mode is supported through a separate interface function +* XQspiPs_PolledTransfer(). Unlike the transfer function in the interrupt mode, +* this function blocks until all data has been sent/received. +* +* Device Busy +* +* Some operations are disallowed when the device is busy. The driver tracks +* whether a device is busy. The device is considered busy when a data transfer +* request is outstanding, and is considered not busy only when that transfer +* completes (or is aborted with a mode fault error). +* +* Device Configuration +* +* The device can be configured in various ways during the FPGA implementation +* process. Configuration parameters are stored in the xqspips_g.c file or +* passed in via XQspiPs_CfgInitialize(). A table is defined where each entry +* contains configuration information for an QSPI device, including the base +* address for the device. +* +* RTOS Independence +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads or +* thread mutual exclusion, virtual memory, or cache control must be satisfied +* by the layer above this driver. +* +* NOTE: This driver was always tested with endianness set to little-endian. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00a sdm 11/25/10 First release, based on the PS SPI driver...
+* 1.01a sdm 11/22/11 Added TCL file for generating QSPI parameters
+*		     in xparameters.h
+* 2.00a kka 07/25/12 Added a few register defines for CR 670297
+* 		     Removed code related to mode fault for CR 671468
+*		     The XQspiPs_SetSlaveSelect has been modified to remove
+*		     the argument of the slave select as the QSPI controller
+*		     only supports one slave.
+* 		     XQspiPs_GetSlaveSelect API has been removed
+* 		     Added a flag ShiftReadData to the instance structure
+*.		     and is used in the XQspiPs_GetReadData API.
+*		     The ShiftReadData Flag indicates whether the data
+*		     read from the Rx FIFO needs to be shifted
+*		     in cases where the data is less than 4  bytes
+* 		     Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode and doesnot support
+*		     Slave mode or the legacy mode.
+*		     Modified the XQspiPs_PolledTransfer and XQspiPs_Transfer
+*		     APIs so that the last argument (IsInst) specifying whether
+*		     it is instruction or data has been removed. The first byte
+*		     in the SendBufPtr argument of these APIs specify the
+*		     instruction to be sent to the Flash Device.
+*		     This version of the driver fixes CRs 670197/663787/
+*		     670297/671468.
+* 		     Added the option for setting the Holdb_dr bit in the
+*		     configuration options, XQSPIPS_HOLD_B_DRIVE_OPTION
+*		     is the option to be used for setting this bit in the
+*		     configuration register.
+*		     The XQspiPs_PolledTransfer function has been updated
+*		     to fill the data to fifo depth.
+* 2.01a sg  02/03/13 Added flash opcodes for DUAL_IO_READ,QUAD_IO_READ.
+*		     Added macros for Set/Get Rx Watermark. Changed QSPI
+*		     Enable/Disable macro argument from BaseAddress to
+*		     Instance Pointer. Added DelayNss argument to SetDelays
+*		     and GetDelays API's.
+*		     Created macros XQspiPs_IsManualStart and
+*		     XQspiPs_IsManualChipSelect.
+*		     Changed QSPI transfer logic for polled and interrupt
+*		     modes to be based on filled tx fifo count and receive
+*		     based on it. RXNEMPTY interrupt is not used.
+*		     Added assertions to XQspiPs_LqspiRead function.
+*		     SetDelays and GetDelays API's include DelayNss parameter.
+*		     Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register. Renamed Fixed burst error to
+*		     data FSM error in  LQSPI Status register.
+*
+* 2.02a hk  05/07/13 Added ConnectionMode to config structure.
+*			 Corresponds to C_QSPI_MODE - 0:Single, 1:Stacked, 2:Parallel
+*			 Added enable and disable to the XQspiPs_LqspiRead() function
+*			 Removed XQspi_Reset() in Set_Options() function when
+*			 LQSPI_MODE_OPTION is set.
+*            Added instructions for bank selection, die erase and
+*            flag status register to the flash instruction table
+*            Handling for instructions not in flash instruction
+*			 table added. Checking for Tx FIFO empty when switching from
+*			 TXD1/2/3 to TXD0 added. If WRSR instruction is sent with
+*            byte count 3 (spansion), instruction size and TXD register
+*			 changed accordingly. CR# 712502 and 703869.
+*            Added prefix to constant definitions for ConnectionMode
+*            Added (\#ifdef linear base address) in the Linear read function.
+*            Changed  XPAR_XQSPIPS_0_LINEAR_BASEADDR to
+*            XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR in
+*            XQspiPs_LqspiRead function. Fix for CR#718141.
+*
+* 2.03a hk  09/17/13 Modified polled and interrupt transfers to make use of
+*                    thresholds. This is to improve performance.
+*                    Added API's for QSPI reset and
+*                    linear mode initialization for boot.
+*                    Added RX and TX threshold reset to one in XQspiPs_Abort.
+*                    Added RX threshold reset(1) after transfer in polled and
+*                    interrupt transfers. Made changes to make sure threshold
+*                    change is done only when no transfer is in progress.
+*                    Updated linear init API for parallel and stacked modes.
+*                    CR#737760.
+* 3.1   hk  08/13/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/05/17 Modified Comment lines in functions of qspips
+*                    examples to recognize it as documentation block
+*                    and modified filename tag in
+*                    xqspips_dual_flash_stack_lqspi_example.c to include it in
+*                    doxygen examples.
+* 3.4   nsk 31/07/17 Added QSPI_BUS_WIDTH parameter in xparameters.h file
+* 3.5	tjs 08/21/18 Fixed compilation warnings for the ARMCC.
+* 3.5	tjs 07/16/18 Added support for low density ISSI flash parts.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+* 3.6   akm 04/15/19 Modified FlashQuadEnable, FlashWrie and FlashErase APIs,
+*                    to wait for the on going operation to complete before
+*                    performing the next operation.
+* 3.6   akm 04/15/19 Modified the mask in XQspiPs_GetReadData() API to retrieve
+*                    configuration register values of both the Flashes in dual
+*                    parellel connection.
+* 3.7	akm 11/19/19 Fixed Coverity unused value warning in XQspiPs_PolledTransfer()
+* 			and XQspiPs_Transfer() APIs.
+* 3.7	akm 03/19/20 Modified XQspiPs_PolledTransfer(), XQspiPs_Transfer() and
+*			XQspiPs_InterruptHandler() APIs to fill TX FIFO with valid
+*			data when RX buffer is not NULL.
+* 3.8	akm 09/02/20 Updated the Makefile to support parallel make execution.
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_H /* prevent circular inclusions */ +#define XQSPIPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xqspips_hw.h" +#include + +/************************** Constant Definitions *****************************/ + +/** @name Configuration options + * + * The following options are supported to enable/disable certain features of + * an QSPI device. Each of the options is a bit mask, so more than one may be + * specified. + * + * + * The Active Low Clock option configures the device's clock polarity. + * Setting this option means the clock is active low and the SCK signal idles + * high. By default, the clock is active high and SCK idles low. + * + * The Clock Phase option configures the QSPI device for one of two + * transfer formats. A clock phase of 0, the default, means data is valid on + * the first SCK edge (rising or falling) after the slave select (SS) signal + * has been asserted. A clock phase of 1 means data is valid on the second SCK + * edge (rising or falling) after SS has been asserted. + * + * + * The QSPI Force Slave Select option is used to enable manual control of + * the slave select signal. + * 0: The SPI_SS signal is controlled by the QSPI controller during + * transfers. (Default) + * 1: The SPI_SS signal is forced active (driven low) regardless of any + * transfers in progress. + * + * NOTE: The driver will handle setting and clearing the Slave Select when + * the user sets the "FORCE_SSELECT_OPTION". Using this option will allow the + * QSPI clock to be set to a faster speed. If the QSPI clock is too fast, the + * processor cannot empty and refill the FIFOs before the TX FIFO is empty + * When the QSPI hardware is controlling the Slave Select signals, this + * will cause slave to be de-selected and terminate the transfer. + * + * The Manual Start option is used to enable manual control of + * the Start command to perform data transfer. + * 0: The Start command is controlled by the QSPI controller during + * transfers(Default). Data transmission starts as soon as there is data in + * the TXFIFO and stalls when the TXFIFO is empty + * 1: The Start command must be issued by software to perform data transfer. + * Bit 15 of Configuration register is used to issue Start command. This bit + * must be set whenever TXFIFO is filled with new data. + * + * NOTE: The driver will set the Manual Start Enable bit in Configuration + * Register, if Manual Start option is selected. Software will issue + * Manual Start command whenever TXFIFO is filled with data. When there is + * no further data, driver will clear the Manual Start Enable bit. + * + * @{ + */ +#define XQSPIPS_CLK_ACTIVE_LOW_OPTION 0x2 /**< Active Low Clock option */ +#define XQSPIPS_CLK_PHASE_1_OPTION 0x4 /**< Clock Phase one option */ +#define XQSPIPS_FORCE_SSELECT_OPTION 0x10 /**< Force Slave Select */ +#define XQSPIPS_MANUAL_START_OPTION 0x20 /**< Manual Start enable */ +#define XQSPIPS_LQSPI_MODE_OPTION 0x80 /**< Linear QPSI mode */ +#define XQSPIPS_HOLD_B_DRIVE_OPTION 0x100 /**< Drive HOLD_B Pin */ +/*@}*/ + + +/** @name QSPI Clock Prescaler options + * The QSPI Clock Prescaler Configuration bits are used to program master mode + * bit rate. The bit rate can be programmed in divide-by-two decrements from + * pclk/2 to pclk/256. + * + * @{ + */ +#define XQSPIPS_CLK_PRESCALE_2 0x00 /**< PCLK/2 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_4 0x01 /**< PCLK/4 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_8 0x02 /**< PCLK/8 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_16 0x03 /**< PCLK/16 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_32 0x04 /**< PCLK/32 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_64 0x05 /**< PCLK/64 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_128 0x06 /**< PCLK/128 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_256 0x07 /**< PCLK/256 Prescaler */ + +/*@}*/ + + +/** @name Callback events + * + * These constants specify the handler events that are passed to + * a handler from the driver. These constants are not bit masks such that + * only one will be passed at a time to the handler. + * + * @{ + */ +#define XQSPIPS_EVENT_TRANSFER_DONE 2 /**< Transfer done */ +#define XQSPIPS_EVENT_TRANSMIT_UNDERRUN 3 /**< TX FIFO empty */ +#define XQSPIPS_EVENT_RECEIVE_OVERRUN 4 /**< Receive data loss because + * RX FIFO full + */ +/*@}*/ + +/** @name Flash commands + * + * The following constants define most of the commands supported by flash + * devices. Users can add more commands supported by the flash devices + * + * @{ + */ +#define XQSPIPS_FLASH_OPCODE_WRSR 0x01 /* Write status register */ +#define XQSPIPS_FLASH_OPCODE_PP 0x02 /* Page program */ +#define XQSPIPS_FLASH_OPCODE_NORM_READ 0x03 /* Normal read data bytes */ +#define XQSPIPS_FLASH_OPCODE_WRDS 0x04 /* Write disable */ +#define XQSPIPS_FLASH_OPCODE_RDSR1 0x05 /* Read status register 1 */ +#define XQSPIPS_FLASH_OPCODE_WREN 0x06 /* Write enable */ +#define XQSPIPS_FLASH_OPCODE_FAST_READ 0x0B /* Fast read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_4K 0x20 /* Erase 4KiB block */ +#define XQSPIPS_FLASH_OPCODE_RDSR2 0x35 /* Read status register 2 */ +#define XQSPIPS_FLASH_OPCODE_DUAL_READ 0x3B /* Dual read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_32K 0x52 /* Erase 32KiB block */ +#define XQSPIPS_FLASH_OPCODE_QUAD_READ 0x6B /* Quad read data bytes */ +#define XQSPIPS_FLASH_OPCODE_ERASE_SUS 0x75 /* Erase suspend */ +#define XQSPIPS_FLASH_OPCODE_ERASE_RES 0x7A /* Erase resume */ +#define XQSPIPS_FLASH_OPCODE_RDID 0x9F /* Read JEDEC ID */ +#define XQSPIPS_FLASH_OPCODE_BE 0xC7 /* Erase whole flash block */ +#define XQSPIPS_FLASH_OPCODE_SE 0xD8 /* Sector erase (usually 64KB)*/ +#define XQSPIPS_FLASH_OPCODE_DUAL_IO_READ 0xBB /* Read data using Dual I/O */ +#define XQSPIPS_FLASH_OPCODE_QUAD_IO_READ 0xEB /* Read data using Quad I/O */ +#define XQSPIPS_FLASH_OPCODE_BRWR 0x17 /* Bank Register Write */ +#define XQSPIPS_FLASH_OPCODE_BRRD 0x16 /* Bank Register Read */ +/* Extende Address Register Write - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARWR 0xC5 +/* Extende Address Register Read - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARRD 0xC8 +#define XQSPIPS_FLASH_OPCODE_DIE_ERASE 0xC4 +#define XQSPIPS_FLASH_OPCODE_READ_FLAG_SR 0x70 +#define XQSPIPS_FLASH_OPCODE_CLEAR_FLAG_SR 0x50 +#define XQSPIPS_FLASH_OPCODE_READ_LOCK_REG 0xE8 /* Lock Reg Read */ +#define XQSPIPS_FLASH_OPCODE_WRITE_LOCK_REG 0xE5 /* Lock Reg Write */ + +/*@}*/ + +/** @name Instruction size + * + * The following constants define numbers 1 to 4. + * Used to identify whether TXD0,1,2 or 3 is to be used. + * + * @{ + */ +#define XQSPIPS_SIZE_ONE 1 +#define XQSPIPS_SIZE_TWO 2 +#define XQSPIPS_SIZE_THREE 3 +#define XQSPIPS_SIZE_FOUR 4 + +/*@}*/ + +/** @name ConnectionMode + * + * The following constants are the possible values of ConnectionMode in + * Config structure. + * + * @{ + */ +#define XQSPIPS_CONNECTION_MODE_SINGLE 0 +#define XQSPIPS_CONNECTION_MODE_STACKED 1 +#define XQSPIPS_CONNECTION_MODE_PARALLEL 2 + +/*@}*/ + +/** @name FIFO threshold value + * + * This is the Rx FIFO threshold (in words) that was found to be most + * optimal in terms of performance + * + * @{ + */ +#define XQSPIPS_RXFIFO_THRESHOLD_OPT 32 + +/*@}*/ + +/**************************** Type Definitions *******************************/ +/** + * The handler data type allows the user to define a callback function to + * handle the asynchronous processing for the QSPI device. The application + * using this driver is expected to define a handler of this type to support + * interrupt driven mode. The handler executes in an interrupt context, so + * only minimal processing should be performed. + * + * @param CallBackRef is the callback reference passed in by the upper + * layer when setting the callback functions, and passed back to + * the upper layer when the callback is invoked. Its type is + * not important to the driver, so it is a void pointer. + * @param StatusEvent holds one or more status events that have occurred. + * See the XQspiPs_SetStatusHandler() for details on the status + * events that can be passed in the callback. + * @param ByteCount indicates how many bytes of data were successfully + * transferred. This may be less than the number of bytes + * requested if the status event indicates an error. + */ +typedef void (*XQspiPs_StatusHandler) (void *CallBackRef, u32 StatusEvent, + unsigned ByteCount); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of the device */ + u32 InputClockHz; /**< Input clock frequency */ + u8 ConnectionMode; /**< Single, Stacked and Parallel mode */ +} XQspiPs_Config; + +/** + * The XQspiPs driver instance data. The user is required to allocate a + * variable of this type for every QSPI device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XQspiPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + + u8 *SendBufferPtr; /**< Buffer to send (state) */ + u8 *RecvBufferPtr; /**< Buffer to receive (state) */ + int RequestedBytes; /**< Number of bytes to transfer (state) */ + int RemainingBytes; /**< Number of bytes left to transfer(state) */ + u32 IsBusy; /**< A transfer is in progress (state) */ + XQspiPs_StatusHandler StatusHandler; + void *StatusRef; /**< Callback reference for status handler */ + u32 ShiftReadData; /**< Flag to indicate whether the data + * read from the Rx FIFO needs to be shifted + * in cases where the data is less than 4 + * bytes + */ +} XQspiPs; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Start Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualStart(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualStart(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_MANUAL_START_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Chip Select Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualChipSelect(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualChipSelect(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_FORCE_SSELECT_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/** +* +* Set the contents of the slave idle count register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are +* 0-255. +* +* @return None +* +* @note C-Style signature: +* void XQspiPs_SetSlaveIdle(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetSlaveIdle(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the slave idle count register. Use the XQSPIPS_SICR_* +* constants defined in xqspips_hw.h to interpret the bit-mask returned. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return An 8-bit value representing Slave Idle Count. +* +* @note C-Style signature: +* u32 XQspiPs_GetSlaveIdle(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetSlaveIdle(InstancePtr) \ + XQspiPs_In32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the transmit FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetTXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetTXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_TXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the transmit FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Tx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetTXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetTXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_TXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the receive FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetRXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetRXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_RXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the receive FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Rx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetRXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetRXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_RXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Enable the device and uninhibit master transactions. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Enable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Enable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, \ + XQSPIPS_ER_ENABLE_MASK) + +/****************************************************************************/ +/** +* +* Disable the device. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Disable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Disable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, 0) + +/****************************************************************************/ +/** +* +* Set the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written to the Linear QSPI +* configuration register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetLqspiConfigReg(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetLqspiConfigReg(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 32-bit value representing the contents of the LQSPI Config +* register. +* +* @note C-Style signature: +* u32 XQspiPs_GetLqspiConfigReg(u32 *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetLqspiConfigReg(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET) + +/************************** Function Prototypes ******************************/ + +/* + * Initialization function, implemented in xqspips_sinit.c + */ +XQspiPs_Config *XQspiPs_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xqspips.c + */ +int XQspiPs_CfgInitialize(XQspiPs *InstancePtr, XQspiPs_Config *Config, + u32 EffectiveAddr); +void XQspiPs_Reset(XQspiPs *InstancePtr); +void XQspiPs_Abort(XQspiPs *InstancePtr); + +s32 XQspiPs_Transfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, + u32 ByteCount); +s32 XQspiPs_PolledTransfer(XQspiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount); +int XQspiPs_LqspiRead(XQspiPs *InstancePtr, u8 *RecvBufPtr, + u32 Address, unsigned ByteCount); + +int XQspiPs_SetSlaveSelect(XQspiPs *InstancePtr); + +void XQspiPs_SetStatusHandler(XQspiPs *InstancePtr, void *CallBackRef, + XQspiPs_StatusHandler FuncPtr); +void XQspiPs_InterruptHandler(void *InstancePtr); + +/* + * Functions for selftest, in xqspips_selftest.c + */ +int XQspiPs_SelfTest(XQspiPs *InstancePtr); + +/* + * Functions for options, in xqspips_options.c + */ +s32 XQspiPs_SetOptions(XQspiPs *InstancePtr, u32 Options); +u32 XQspiPs_GetOptions(XQspiPs *InstancePtr); + +s32 XQspiPs_SetClkPrescaler(XQspiPs *InstancePtr, u8 Prescaler); +u8 XQspiPs_GetClkPrescaler(XQspiPs *InstancePtr); + +int XQspiPs_SetDelays(XQspiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit); +void XQspiPs_GetDelays(XQspiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xqspips_hw.h b/bsp_z7/ps7_cortexa9_0/include/xqspips_hw.h new file mode 100644 index 0000000..ab50675 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xqspips_hw.h @@ -0,0 +1,399 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xqspips_hw.h +* @addtogroup qspips_v3_10 +* @{ +* +* This header file contains the identifiers and basic HW access driver +* functions (or macros) that can be used to access the device. Other driver +* functions are defined in xqspips.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a ka  07/25/12 Added a few register defines for CR 670297
+*		     and removed some defines of reserved fields for
+*		     CR 671468
+*		     Added define XQSPIPS_CR_HOLD_B_MASK for Holdb_dr
+*		     bit in Configuration register.
+* 2.01a sg  02/03/13 Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register.
+* 2.03a hk  08/22/13 Added prototypes of API's for QSPI reset and
+*                    linear mode initialization for boot. Added related
+*                    constant definitions.
+* 3.1   hk  08/13/14 Changed definition of CR reset value masks to set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_HW_H /* prevent circular inclusions */ +#define XQSPIPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets from the base address of an QSPI device. + * @{ + */ +#define XQSPIPS_CR_OFFSET 0x00 /**< Configuration Register */ +#define XQSPIPS_SR_OFFSET 0x04 /**< Interrupt Status */ +#define XQSPIPS_IER_OFFSET 0x08 /**< Interrupt Enable */ +#define XQSPIPS_IDR_OFFSET 0x0c /**< Interrupt Disable */ +#define XQSPIPS_IMR_OFFSET 0x10 /**< Interrupt Enabled Mask */ +#define XQSPIPS_ER_OFFSET 0x14 /**< Enable/Disable Register */ +#define XQSPIPS_DR_OFFSET 0x18 /**< Delay Register */ +#define XQSPIPS_TXD_00_OFFSET 0x1C /**< Transmit 4-byte inst/data */ +#define XQSPIPS_RXD_OFFSET 0x20 /**< Data Receive Register */ +#define XQSPIPS_SICR_OFFSET 0x24 /**< Slave Idle Count */ +#define XQSPIPS_TXWR_OFFSET 0x28 /**< Transmit FIFO Watermark */ +#define XQSPIPS_RXWR_OFFSET 0x2C /**< Receive FIFO Watermark */ +#define XQSPIPS_GPIO_OFFSET 0x30 /**< GPIO Register */ +#define XQSPIPS_LPBK_DLY_ADJ_OFFSET 0x38 /**< Loopback Delay Adjust Reg */ +#define XQSPIPS_TXD_01_OFFSET 0x80 /**< Transmit 1-byte inst */ +#define XQSPIPS_TXD_10_OFFSET 0x84 /**< Transmit 2-byte inst */ +#define XQSPIPS_TXD_11_OFFSET 0x88 /**< Transmit 3-byte inst */ +#define XQSPIPS_LQSPI_CR_OFFSET 0xA0 /**< Linear QSPI config register */ +#define XQSPIPS_LQSPI_SR_OFFSET 0xA4 /**< Linear QSPI status register */ +#define XQSPIPS_MOD_ID_OFFSET 0xFC /**< Module ID register */ + +/* @} */ + +/** @name Configuration Register + * + * This register contains various control bits that + * affect the operation of the QSPI device. Read/Write. + * @{ + */ + +#define XQSPIPS_CR_IFMODE_MASK 0x80000000 /**< Flash mem interface mode */ +#define XQSPIPS_CR_ENDIAN_MASK 0x04000000 /**< Tx/Rx FIFO endianness */ +#define XQSPIPS_CR_MANSTRT_MASK 0x00010000 /**< Manual Transmission Start */ +#define XQSPIPS_CR_MANSTRTEN_MASK 0x00008000 /**< Manual Transmission Start + Enable */ +#define XQSPIPS_CR_SSFORCE_MASK 0x00004000 /**< Force Slave Select */ +#define XQSPIPS_CR_SSCTRL_MASK 0x00000400 /**< Slave Select Decode */ +#define XQSPIPS_CR_SSCTRL_SHIFT 10 /**< Slave Select Decode shift */ +#define XQSPIPS_CR_DATA_SZ_MASK 0x000000C0 /**< Size of word to be + transferred */ +#define XQSPIPS_CR_PRESC_MASK 0x00000038 /**< Prescaler Setting */ +#define XQSPIPS_CR_PRESC_SHIFT 3 /**< Prescaler shift */ +#define XQSPIPS_CR_PRESC_MAXIMUM 0x07 /**< Prescaler maximum value */ + +#define XQSPIPS_CR_CPHA_MASK 0x00000004 /**< Phase Configuration */ +#define XQSPIPS_CR_CPOL_MASK 0x00000002 /**< Polarity Configuration */ + +#define XQSPIPS_CR_MSTREN_MASK 0x00000001 /**< Master Mode Enable */ + +#define XQSPIPS_CR_HOLD_B_MASK 0x00080000 /**< HOLD_B Pin Drive Enable */ + +#define XQSPIPS_CR_REF_CLK_MASK 0x00000100 /**< Ref clk bit - should be 0 */ + +/* Deselect the Slave select line and set the transfer size to 32 at reset */ +#define XQSPIPS_CR_RESET_MASK_SET XQSPIPS_CR_IFMODE_MASK | \ + XQSPIPS_CR_SSCTRL_MASK | \ + XQSPIPS_CR_DATA_SZ_MASK | \ + XQSPIPS_CR_MSTREN_MASK | \ + XQSPIPS_CR_SSFORCE_MASK | \ + XQSPIPS_CR_HOLD_B_MASK +#define XQSPIPS_CR_RESET_MASK_CLR XQSPIPS_CR_CPOL_MASK | \ + XQSPIPS_CR_CPHA_MASK | \ + XQSPIPS_CR_PRESC_MASK | \ + XQSPIPS_CR_MANSTRTEN_MASK | \ + XQSPIPS_CR_MANSTRT_MASK | \ + XQSPIPS_CR_ENDIAN_MASK | \ + XQSPIPS_CR_REF_CLK_MASK +/* @} */ + + +/** @name QSPI Interrupt Registers + * + * QSPI Status Register + * + * This register holds the interrupt status flags for an QSPI device. Some + * of the flags are level triggered, which means that they are set as long + * as the interrupt condition exists. Other flags are edge triggered, + * which means they are set once the interrupt condition occurs and remain + * set until they are cleared by software. The interrupts are cleared by + * writing a '1' to the interrupt bit position in the Status Register. + * Read/Write. + * + * QSPI Interrupt Enable Register + * + * This register is used to enable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register sets the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Disable Register + * + * This register is used to disable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register clears the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Mask Register + * + * This register shows the enabled/disabled interrupts of an QSPI device. + * Read only. + * + * All four registers have the same bit definitions. They are only defined once + * for each of the Interrupt Enable Register, Interrupt Disable Register, + * Interrupt Mask Register, and Channel Interrupt Status Register + * @{ + */ + +#define XQSPIPS_IXR_TXUF_MASK 0x00000040 /**< QSPI Tx FIFO Underflow */ +#define XQSPIPS_IXR_RXFULL_MASK 0x00000020 /**< QSPI Rx FIFO Full */ +#define XQSPIPS_IXR_RXNEMPTY_MASK 0x00000010 /**< QSPI Rx FIFO Not Empty */ +#define XQSPIPS_IXR_TXFULL_MASK 0x00000008 /**< QSPI Tx FIFO Full */ +#define XQSPIPS_IXR_TXOW_MASK 0x00000004 /**< QSPI Tx FIFO Overwater */ +#define XQSPIPS_IXR_RXOVR_MASK 0x00000001 /**< QSPI Rx FIFO Overrun */ +#define XQSPIPS_IXR_DFLT_MASK 0x00000025 /**< QSPI default interrupts + mask */ +#define XQSPIPS_IXR_WR_TO_CLR_MASK 0x00000041 /**< Interrupts which + need write to clear */ +#define XQSPIPS_ISR_RESET_STATE 0x00000004 /**< Default to tx/rx empty */ +#define XQSPIPS_IXR_DISABLE_ALL 0x0000007D /**< Disable all interrupts */ +/* @} */ + + +/** @name Enable Register + * + * This register is used to enable or disable an QSPI device. + * Read/Write + * @{ + */ +#define XQSPIPS_ER_ENABLE_MASK 0x00000001 /**< QSPI Enable Bit Mask */ +/* @} */ + + +/** @name Delay Register + * + * This register is used to program timing delays in + * slave mode. Read/Write + * @{ + */ +#define XQSPIPS_DR_NSS_MASK 0xFF000000 /**< Delay to de-assert slave select + between two words mask */ +#define XQSPIPS_DR_NSS_SHIFT 24 /**< Delay to de-assert slave select + between two words shift */ +#define XQSPIPS_DR_BTWN_MASK 0x00FF0000 /**< Delay Between Transfers + mask */ +#define XQSPIPS_DR_BTWN_SHIFT 16 /**< Delay Between Transfers shift */ +#define XQSPIPS_DR_AFTER_MASK 0x0000FF00 /**< Delay After Transfers mask */ +#define XQSPIPS_DR_AFTER_SHIFT 8 /**< Delay After Transfers shift */ +#define XQSPIPS_DR_INIT_MASK 0x000000FF /**< Delay Initially mask */ +/* @} */ + +/** @name Slave Idle Count Registers + * + * This register defines the number of pclk cycles the slave waits for a the + * QSPI clock to become stable in quiescent state before it can detect the start + * of the next transfer in CPHA = 1 mode. + * Read/Write + * + * @{ + */ +#define XQSPIPS_SICR_MASK 0x000000FF /**< Slave Idle Count Mask */ +/* @} */ + + +/** @name Transmit FIFO Watermark Register + * + * This register defines the watermark setting for the Transmit FIFO. + * + * @{ + */ +#define XQSPIPS_TXWR_MASK 0x0000003F /**< Transmit Watermark Mask */ +#define XQSPIPS_TXWR_RESET_VALUE 0x00000001 /**< Transmit Watermark + * register reset value */ + +/* @} */ + +/** @name Receive FIFO Watermark Register + * + * This register defines the watermark setting for the Receive FIFO. + * + * @{ + */ +#define XQSPIPS_RXWR_MASK 0x0000003F /**< Receive Watermark Mask */ +#define XQSPIPS_RXWR_RESET_VALUE 0x00000001 /**< Receive Watermark + * register reset value */ + +/* @} */ + +/** @name FIFO Depth + * + * This macro provides the depth of transmit FIFO and receive FIFO. + * + * @{ + */ +#define XQSPIPS_FIFO_DEPTH 63 /**< FIFO depth (words) */ +/* @} */ + + +/** @name Linear QSPI Configuration Register + * + * This register contains various control bits that + * affect the operation of the Linear QSPI controller. Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_CR_LINEAR_MASK 0x80000000 /**< LQSPI mode enable */ +#define XQSPIPS_LQSPI_CR_TWO_MEM_MASK 0x40000000 /**< Both memories or one */ +#define XQSPIPS_LQSPI_CR_SEP_BUS_MASK 0x20000000 /**< Separate memory bus */ +#define XQSPIPS_LQSPI_CR_U_PAGE_MASK 0x10000000 /**< Upper memory page */ +#define XQSPIPS_LQSPI_CR_MODE_EN_MASK 0x02000000 /**< Enable mode bits */ +#define XQSPIPS_LQSPI_CR_MODE_ON_MASK 0x01000000 /**< Mode on */ +#define XQSPIPS_LQSPI_CR_MODE_BITS_MASK 0x00FF0000 /**< Mode value for dual I/O + or quad I/O */ +#define XQSPIPS_LQSPI_CR_DUMMY_MASK 0x00000700 /**< Number of dummy bytes + between addr and return + read data */ +#define XQSPIPS_LQSPI_CR_INST_MASK 0x000000FF /**< Read instr code */ +#define XQSPIPS_LQSPI_CR_RST_STATE 0x8000016B /**< Default CR value */ +/* @} */ + +/** @name Linear QSPI Status Register + * + * This register contains various status bits of the Linear QSPI controller. + * Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_SR_D_FSM_ERR_MASK 0x00000004 /**< AXI Data FSM Error + received */ +#define XQSPIPS_LQSPI_SR_WR_RECVD_MASK 0x00000002 /**< AXI write command + received */ +/* @} */ + + +/** @name Loopback Delay Adjust Register + * + * This register contains various bit masks of Loopback Delay Adjust Register. + * + * @{ + */ + +#define XQSPIPS_LPBK_DLY_ADJ_USE_LPBK_MASK 0x00000020 /**< Loopback Bit */ + +/* @} */ + + +/** @name SLCR Register + * + * Register offsets from SLCR base address. + * + * @{ + */ + +#define SLCR_LOCK 0x00000004 /**< SLCR Write Protection Lock */ +#define SLCR_UNLOCK 0x00000008 /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL 0x00000230 /**< Quad SPI Software Reset Control */ +#define SLCR_LOCKSTA 0x0000000C /**< SLCR Write Protection status */ + +/* @} */ + + +/** @name SLCR Register + * + * Bit Masks of above SLCR Registers . + * + * @{ + */ + +#ifndef XPAR_XSLCR_0_BASEADDR +#define XPAR_XSLCR_0_BASEADDR 0xF8000000 +#endif +#define SLCR_LOCK_MASK 0x767B /**< Write Protection Lock mask*/ +#define SLCR_UNLOCK_MASK 0xDF0D /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL_MASK 0x3 /**< Quad SPI Software Reset Control */ + +/* @} */ + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XQspiPs_In32 Xil_In32 +#define XQspiPs_Out32 Xil_Out32 +#define XQSPIPS_DUMMY_TX_DATA 0xFFFFFFFF + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XQspiPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +#define XQspiPs_ReadReg(BaseAddress, RegOffset) \ + XQspiPs_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +* +******************************************************************************/ +#define XQspiPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XQspiPs_Out32((BaseAddress) + (RegOffset), (RegisterValue)) + +/************************** Function Prototypes ******************************/ + +/* + * Functions implemented in xqspips_hw.c + */ +void XQspiPs_ResetHw(u32 BaseAddress); +void XQspiPs_LinearInit(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xreg_cortexa9.h b/bsp_z7/ps7_cortexa9_0/include/xreg_cortexa9.h new file mode 100644 index 0000000..2a4fff2 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xreg_cortexa9.h @@ -0,0 +1,573 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xreg_cortexa9.h +* +* This header file contains definitions for using inline assembler code. It is +* written specifically for the GNU, ARMCC compiler. +* +* All of the ARM Cortex A9 GPRs, SPRs, and Debug Registers are defined along +* with the positions of the bits within the registers. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  10/20/09 First release
+* 
+* +******************************************************************************/ +#ifndef XREG_CORTEXA9_H +#define XREG_CORTEXA9_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + *@cond nocomments + */ + +/* GPRs */ +#define XREG_GPR0 r0 +#define XREG_GPR1 r1 +#define XREG_GPR2 r2 +#define XREG_GPR3 r3 +#define XREG_GPR4 r4 +#define XREG_GPR5 r5 +#define XREG_GPR6 r6 +#define XREG_GPR7 r7 +#define XREG_GPR8 r8 +#define XREG_GPR9 r9 +#define XREG_GPR10 r10 +#define XREG_GPR11 r11 +#define XREG_GPR12 r12 +#define XREG_GPR13 r13 +#define XREG_GPR14 r14 +#define XREG_GPR15 r15 +#define XREG_CPSR cpsr + +/* Coprocessor number defines */ +#define XREG_CP0 0 +#define XREG_CP1 1 +#define XREG_CP2 2 +#define XREG_CP3 3 +#define XREG_CP4 4 +#define XREG_CP5 5 +#define XREG_CP6 6 +#define XREG_CP7 7 +#define XREG_CP8 8 +#define XREG_CP9 9 +#define XREG_CP10 10 +#define XREG_CP11 11 +#define XREG_CP12 12 +#define XREG_CP13 13 +#define XREG_CP14 14 +#define XREG_CP15 15 + +/* Coprocessor control register defines */ +#define XREG_CR0 cr0 +#define XREG_CR1 cr1 +#define XREG_CR2 cr2 +#define XREG_CR3 cr3 +#define XREG_CR4 cr4 +#define XREG_CR5 cr5 +#define XREG_CR6 cr6 +#define XREG_CR7 cr7 +#define XREG_CR8 cr8 +#define XREG_CR9 cr9 +#define XREG_CR10 cr10 +#define XREG_CR11 cr11 +#define XREG_CR12 cr12 +#define XREG_CR13 cr13 +#define XREG_CR14 cr14 +#define XREG_CR15 cr15 + +/* Current Processor Status Register (CPSR) Bits */ +#define XREG_CPSR_THUMB_MODE 0x20 +#define XREG_CPSR_MODE_BITS 0x1F +#define XREG_CPSR_SYSTEM_MODE 0x1F +#define XREG_CPSR_UNDEFINED_MODE 0x1B +#define XREG_CPSR_DATA_ABORT_MODE 0x17 +#define XREG_CPSR_SVC_MODE 0x13 +#define XREG_CPSR_IRQ_MODE 0x12 +#define XREG_CPSR_FIQ_MODE 0x11 +#define XREG_CPSR_USER_MODE 0x10 + +#define XREG_CPSR_IRQ_ENABLE 0x80 +#define XREG_CPSR_FIQ_ENABLE 0x40 + +#define XREG_CPSR_N_BIT 0x80000000 +#define XREG_CPSR_Z_BIT 0x40000000 +#define XREG_CPSR_C_BIT 0x20000000 +#define XREG_CPSR_V_BIT 0x10000000 + + +/* CP15 defines */ +#if defined (__GNUC__) || defined (__ICCARM__) +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "p15, 0, %0, c0, c0, 0" +#define XREG_CP15_CACHE_TYPE "p15, 0, %0, c0, c0, 1" +#define XREG_CP15_TCM_TYPE "p15, 0, %0, c0, c0, 2" +#define XREG_CP15_TLB_TYPE "p15, 0, %0, c0, c0, 3" +#define XREG_CP15_MULTI_PROC_AFFINITY "p15, 0, %0, c0, c0, 5" + +#define XREG_CP15_PROC_FEATURE_0 "p15, 0, %0, c0, c1, 0" +#define XREG_CP15_PROC_FEATURE_1 "p15, 0, %0, c0, c1, 1" +#define XREG_CP15_DEBUG_FEATURE_0 "p15, 0, %0, c0, c1, 2" +#define XREG_CP15_MEMORY_FEATURE_0 "p15, 0, %0, c0, c1, 4" +#define XREG_CP15_MEMORY_FEATURE_1 "p15, 0, %0, c0, c1, 5" +#define XREG_CP15_MEMORY_FEATURE_2 "p15, 0, %0, c0, c1, 6" +#define XREG_CP15_MEMORY_FEATURE_3 "p15, 0, %0, c0, c1, 7" + +#define XREG_CP15_INST_FEATURE_0 "p15, 0, %0, c0, c2, 0" +#define XREG_CP15_INST_FEATURE_1 "p15, 0, %0, c0, c2, 1" +#define XREG_CP15_INST_FEATURE_2 "p15, 0, %0, c0, c2, 2" +#define XREG_CP15_INST_FEATURE_3 "p15, 0, %0, c0, c2, 3" +#define XREG_CP15_INST_FEATURE_4 "p15, 0, %0, c0, c2, 4" + +#define XREG_CP15_CACHE_SIZE_ID "p15, 1, %0, c0, c0, 0" +#define XREG_CP15_CACHE_LEVEL_ID "p15, 1, %0, c0, c0, 1" +#define XREG_CP15_AUXILARY_ID "p15, 1, %0, c0, c0, 7" + +#define XREG_CP15_CACHE_SIZE_SEL "p15, 2, %0, c0, c0, 0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "p15, 0, %0, c1, c0, 0" +#define XREG_CP15_AUX_CONTROL "p15, 0, %0, c1, c0, 1" +#define XREG_CP15_CP_ACCESS_CONTROL "p15, 0, %0, c1, c0, 2" + +#define XREG_CP15_SECURE_CONFIG "p15, 0, %0, c1, c1, 0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "p15, 0, %0, c1, c1, 1" +#define XREG_CP15_NS_ACCESS_CONTROL "p15, 0, %0, c1, c1, 2" +#define XREG_CP15_VIRTUAL_CONTROL "p15, 0, %0, c1, c1, 3" + +#else /* RVCT */ +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "cp15:0:c0:c0:0" +#define XREG_CP15_CACHE_TYPE "cp15:0:c0:c0:1" +#define XREG_CP15_TCM_TYPE "cp15:0:c0:c0:2" +#define XREG_CP15_TLB_TYPE "cp15:0:c0:c0:3" +#define XREG_CP15_MULTI_PROC_AFFINITY "cp15:0:c0:c0:5" + +#define XREG_CP15_PROC_FEATURE_0 "cp15:0:c0:c1:0" +#define XREG_CP15_PROC_FEATURE_1 "cp15:0:c0:c1:1" +#define XREG_CP15_DEBUG_FEATURE_0 "cp15:0:c0:c1:2" +#define XREG_CP15_MEMORY_FEATURE_0 "cp15:0:c0:c1:4" +#define XREG_CP15_MEMORY_FEATURE_1 "cp15:0:c0:c1:5" +#define XREG_CP15_MEMORY_FEATURE_2 "cp15:0:c0:c1:6" +#define XREG_CP15_MEMORY_FEATURE_3 "cp15:0:c0:c1:7" + +#define XREG_CP15_INST_FEATURE_0 "cp15:0:c0:c2:0" +#define XREG_CP15_INST_FEATURE_1 "cp15:0:c0:c2:1" +#define XREG_CP15_INST_FEATURE_2 "cp15:0:c0:c2:2" +#define XREG_CP15_INST_FEATURE_3 "cp15:0:c0:c2:3" +#define XREG_CP15_INST_FEATURE_4 "cp15:0:c0:c2:4" + +#define XREG_CP15_CACHE_SIZE_ID "cp15:1:c0:c0:0" +#define XREG_CP15_CACHE_LEVEL_ID "cp15:1:c0:c0:1" +#define XREG_CP15_AUXILARY_ID "cp15:1:c0:c0:7" + +#define XREG_CP15_CACHE_SIZE_SEL "cp15:2:c0:c0:0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "cp15:0:c1:c0:0" +#define XREG_CP15_AUX_CONTROL "cp15:0:c1:c0:1" +#define XREG_CP15_CP_ACCESS_CONTROL "cp15:0:c1:c0:2" + +#define XREG_CP15_SECURE_CONFIG "cp15:0:c1:c1:0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "cp15:0:c1:c1:1" +#define XREG_CP15_NS_ACCESS_CONTROL "cp15:0:c1:c1:2" +#define XREG_CP15_VIRTUAL_CONTROL "cp15:0:c1:c1:3" +#endif + +/* XREG_CP15_CONTROL bit defines */ +#define XREG_CP15_CONTROL_TE_BIT 0x40000000U +#define XREG_CP15_CONTROL_AFE_BIT 0x20000000U +#define XREG_CP15_CONTROL_TRE_BIT 0x10000000U +#define XREG_CP15_CONTROL_NMFI_BIT 0x08000000U +#define XREG_CP15_CONTROL_EE_BIT 0x02000000U +#define XREG_CP15_CONTROL_HA_BIT 0x00020000U +#define XREG_CP15_CONTROL_RR_BIT 0x00004000U +#define XREG_CP15_CONTROL_V_BIT 0x00002000U +#define XREG_CP15_CONTROL_I_BIT 0x00001000U +#define XREG_CP15_CONTROL_Z_BIT 0x00000800U +#define XREG_CP15_CONTROL_SW_BIT 0x00000400U +#define XREG_CP15_CONTROL_B_BIT 0x00000080U +#define XREG_CP15_CONTROL_C_BIT 0x00000004U +#define XREG_CP15_CONTROL_A_BIT 0x00000002U +#define XREG_CP15_CONTROL_M_BIT 0x00000001U + +#if defined (__GNUC__) || defined (__ICCARM__) +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "p15, 0, %0, c2, c0, 0" +#define XREG_CP15_TTBR1 "p15, 0, %0, c2, c0, 1" +#define XREG_CP15_TTB_CONTROL "p15, 0, %0, c2, c0, 2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "p15, 0, %0, c3, c0, 0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "p15, 0, %0, c5, c0, 0" +#define XREG_CP15_INST_FAULT_STATUS "p15, 0, %0, c5, c0, 1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "p15, 0, %0, c5, c1, 0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "p15, 0, %0, c5, c1, 1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "p15, 0, %0, c6, c0, 0" +#define XREG_CP15_INST_FAULT_ADDRESS "p15, 0, %0, c6, c0, 2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "p15, 0, %0, c7, c0, 4" + +#define XREG_CP15_INVAL_IC_POU_IS "p15, 0, %0, c7, c1, 0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "p15, 0, %0, c7, c1, 6" + +#define XREG_CP15_PHYS_ADDR "p15, 0, %0, c7, c4, 0" + +#define XREG_CP15_INVAL_IC_POU "p15, 0, %0, c7, c5, 0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "p15, 0, %0, c7, c5, 1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "p15, 0, %0, c7, c5, 4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "p15, 0, %0, c7, c5, 6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c6, 1" +#define XREG_CP15_INVAL_DC_LINE_SW "p15, 0, %0, c7, c6, 2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "p15, 0, %0, c7, c8, 0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "p15, 0, %0, c7, c8, 1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "p15, 0, %0, c7, c8, 2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "p15, 0, %0, c7, c8, 3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "p15, 0, %0, c7, c8, 4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "p15, 0, %0, c7, c8, 5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "p15, 0, %0, c7, c8, 6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "p15, 0, %0, c7, c8, 7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "p15, 0, %0, c7, c10, 1" +#define XREG_CP15_CLEAN_DC_LINE_SW "p15, 0, %0, c7, c10, 2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "p15, 0, %0, c7, c10, 4" +#define XREG_CP15_DATA_MEMORY_BARRIER "p15, 0, %0, c7, c10, 5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "p15, 0, %0, c7, c11, 1" + +#define XREG_CP15_NOP2 "p15, 0, %0, c7, c13, 1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c14, 1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "p15, 0, %0, c7, c14, 2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "p15, 0, %0, c8, c3, 0" +#define XREG_CP15_INVAL_TLB_MVA_IS "p15, 0, %0, c8, c3, 1" +#define XREG_CP15_INVAL_TLB_ASID_IS "p15, 0, %0, c8, c3, 2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "p15, 0, %0, c8, c3, 3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "p15, 0, %0, c8, c5, 0" +#define XREG_CP15_INVAL_ITLB_MVA "p15, 0, %0, c8, c5, 1" +#define XREG_CP15_INVAL_ITLB_ASID "p15, 0, %0, c8, c5, 2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "p15, 0, %0, c8, c6, 0" +#define XREG_CP15_INVAL_DTLB_MVA "p15, 0, %0, c8, c6, 1" +#define XREG_CP15_INVAL_DTLB_ASID "p15, 0, %0, c8, c6, 2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "p15, 0, %0, c8, c7, 0" +#define XREG_CP15_INVAL_UTLB_MVA "p15, 0, %0, c8, c7, 1" +#define XREG_CP15_INVAL_UTLB_ASID "p15, 0, %0, c8, c7, 2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "p15, 0, %0, c8, c7, 3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "p15, 0, %0, c9, c12, 0" +#define XREG_CP15_COUNT_ENABLE_SET "p15, 0, %0, c9, c12, 1" +#define XREG_CP15_COUNT_ENABLE_CLR "p15, 0, %0, c9, c12, 2" +#define XREG_CP15_V_FLAG_STATUS "p15, 0, %0, c9, c12, 3" +#define XREG_CP15_SW_INC "p15, 0, %0, c9, c12, 4" +#define XREG_CP15_EVENT_CNTR_SEL "p15, 0, %0, c9, c12, 5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "p15, 0, %0, c9, c13, 0" +#define XREG_CP15_EVENT_TYPE_SEL "p15, 0, %0, c9, c13, 1" +#define XREG_CP15_PERF_MONITOR_COUNT "p15, 0, %0, c9, c13, 2" + +#define XREG_CP15_USER_ENABLE "p15, 0, %0, c9, c14, 0" +#define XREG_CP15_INTR_ENABLE_SET "p15, 0, %0, c9, c14, 1" +#define XREG_CP15_INTR_ENABLE_CLR "p15, 0, %0, c9, c14, 2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "p15, 0, %0, c10, c0, 0" + +#define XREG_CP15_PRI_MEM_REMAP "p15, 0, %0, c10, c2, 0" +#define XREG_CP15_NORM_MEM_REMAP "p15, 0, %0, c10, c2, 1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 1" + +#define XREG_CP15_INTERRUPT_STATUS "p15, 0, %0, c12, c1, 0" +#define XREG_CP15_VIRTUALIZATION_INTR "p15, 0, %0, c12, c1, 1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "p15, 0, %0, c13, c0, 1" +#define USER_RW_THREAD_PID "p15, 0, %0, c13, c0, 2" +#define USER_RO_THREAD_PID "p15, 0, %0, c13, c0, 3" +#define USER_PRIV_THREAD_PID "p15, 0, %0, c13, c0, 4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "p15, 0, %0, c15, c0, 0" +#define XREG_CP15_CONFIG_BASE_ADDR "p15, 4, %0, c15, c0, 0" + +#define XREG_CP15_READ_TLB_ENTRY "p15, 5, %0, c15, c4, 2" +#define XREG_CP15_WRITE_TLB_ENTRY "p15, 5, %0, c15, c4, 4" + +#define XREG_CP15_MAIN_TLB_VA "p15, 5, %0, c15, c5, 2" + +#define XREG_CP15_MAIN_TLB_PA "p15, 5, %0, c15, c6, 2" + +#define XREG_CP15_MAIN_TLB_ATTR "p15, 5, %0, c15, c7, 2" + +#else +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "cp15:0:c2:c0:0" +#define XREG_CP15_TTBR1 "cp15:0:c2:c0:1" +#define XREG_CP15_TTB_CONTROL "cp15:0:c2:c0:2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "cp15:0:c3:c0:0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "cp15:0:c5:c0:0" +#define XREG_CP15_INST_FAULT_STATUS "cp15:0:c5:c0:1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "cp15:0:c5:c1:0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "cp15:0:c5:c1:1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "cp15:0:c6:c0:0" +#define XREG_CP15_INST_FAULT_ADDRESS "cp15:0:c6:c0:2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "cp15:0:c7:c0:4" + +#define XREG_CP15_INVAL_IC_POU_IS "cp15:0:c7:c1:0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "cp15:0:c7:c1:6" + +#define XREG_CP15_PHYS_ADDR "cp15:0:c7:c4:0" + +#define XREG_CP15_INVAL_IC_POU "cp15:0:c7:c5:0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "cp15:0:c7:c5:1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "cp15:0:c7:c5:4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "cp15:0:c7:c5:6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c6:1" +#define XREG_CP15_INVAL_DC_LINE_SW "cp15:0:c7:c6:2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "cp15:0:c7:c8:0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "cp15:0:c7:c8:1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "cp15:0:c7:c8:2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "cp15:0:c7:c8:3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "cp15:0:c7:c8:4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "cp15:0:c7:c8:5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "cp15:0:c7:c8:6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "cp15:0:c7:c8:7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "cp15:0:c7:c10:1" +#define XREG_CP15_CLEAN_DC_LINE_SW "cp15:0:c7:c10:2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "cp15:0:c7:c10:4" +#define XREG_CP15_DATA_MEMORY_BARRIER "cp15:0:c7:c10:5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "cp15:0:c7:c11:1" + +#define XREG_CP15_NOP2 "cp15:0:c7:c13:1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c14:1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "cp15:0:c7:c14:2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "cp15:0:c8:c3:0" +#define XREG_CP15_INVAL_TLB_MVA_IS "cp15:0:c8:c3:1" +#define XREG_CP15_INVAL_TLB_ASID_IS "cp15:0:c8:c3:2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "cp15:0:c8:c3:3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "cp15:0:c8:c5:0" +#define XREG_CP15_INVAL_ITLB_MVA "cp15:0:c8:c5:1" +#define XREG_CP15_INVAL_ITLB_ASID "cp15:0:c8:c5:2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "cp15:0:c8:c6:0" +#define XREG_CP15_INVAL_DTLB_MVA "cp15:0:c8:c6:1" +#define XREG_CP15_INVAL_DTLB_ASID "cp15:0:c8:c6:2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "cp15:0:c8:c7:0" +#define XREG_CP15_INVAL_UTLB_MVA "cp15:0:c8:c7:1" +#define XREG_CP15_INVAL_UTLB_ASID "cp15:0:c8:c7:2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "cp15:0:c8:c7:3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "cp15:0:c9:c12:0" +#define XREG_CP15_COUNT_ENABLE_SET "cp15:0:c9:c12:1" +#define XREG_CP15_COUNT_ENABLE_CLR "cp15:0:c9:c12:2" +#define XREG_CP15_V_FLAG_STATUS "cp15:0:c9:c12:3" +#define XREG_CP15_SW_INC "cp15:0:c9:c12:4" +#define XREG_CP15_EVENT_CNTR_SEL "cp15:0:c9:c12:5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "cp15:0:c9:c13:0" +#define XREG_CP15_EVENT_TYPE_SEL "cp15:0:c9:c13:1" +#define XREG_CP15_PERF_MONITOR_COUNT "cp15:0:c9:c13:2" + +#define XREG_CP15_USER_ENABLE "cp15:0:c9:c14:0" +#define XREG_CP15_INTR_ENABLE_SET "cp15:0:c9:c14:1" +#define XREG_CP15_INTR_ENABLE_CLR "cp15:0:c9:c14:2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "cp15:0:c10:c0:0" + +#define XREG_CP15_PRI_MEM_REMAP "cp15:0:c10:c2:0" +#define XREG_CP15_NORM_MEM_REMAP "cp15:0:c10:c2:1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "cp15:0:c12:c0:0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "cp15:0:c12:c0:1" + +#define XREG_CP15_INTERRUPT_STATUS "cp15:0:c12:c1:0" +#define XREG_CP15_VIRTUALIZATION_INTR "cp15:0:c12:c1:1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "cp15:0:c13:c0:1" +#define USER_RW_THREAD_PID "cp15:0:c13:c0:2" +#define USER_RO_THREAD_PID "cp15:0:c13:c0:3" +#define USER_PRIV_THREAD_PID "cp15:0:c13:c0:4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "cp15:0:c15:c0:0" +#define XREG_CP15_CONFIG_BASE_ADDR "cp15:4:c15:c0:0" + +#define XREG_CP15_READ_TLB_ENTRY "cp15:5:c15:c4:2" +#define XREG_CP15_WRITE_TLB_ENTRY "cp15:5:c15:c4:4" + +#define XREG_CP15_MAIN_TLB_VA "cp15:5:c15:c5:2" + +#define XREG_CP15_MAIN_TLB_PA "cp15:5:c15:c6:2" + +#define XREG_CP15_MAIN_TLB_ATTR "cp15:5:c15:c7:2" +#endif + + +/* MPE register definitions */ +#define XREG_FPSID c0 +#define XREG_FPSCR c1 +#define XREG_MVFR1 c6 +#define XREG_MVFR0 c7 +#define XREG_FPEXC c8 +#define XREG_FPINST c9 +#define XREG_FPINST2 c10 + +/* FPSID bits */ +#define XREG_FPSID_IMPLEMENTER_BIT (24) +#define XREG_FPSID_IMPLEMENTER_MASK (0xFF << FPSID_IMPLEMENTER_BIT) +#define XREG_FPSID_SOFTWARE (1<<23) +#define XREG_FPSID_ARCH_BIT (16) +#define XREG_FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) +#define XREG_FPSID_PART_BIT (8) +#define XREG_FPSID_PART_MASK (0xFF << FPSID_PART_BIT) +#define XREG_FPSID_VARIANT_BIT (4) +#define XREG_FPSID_VARIANT_MASK (0xF << FPSID_VARIANT_BIT) +#define XREG_FPSID_REV_BIT (0) +#define XREG_FPSID_REV_MASK (0xF << FPSID_REV_BIT) + +/* FPSCR bits */ +#define XREG_FPSCR_N_BIT (1 << 31) +#define XREG_FPSCR_Z_BIT (1 << 30) +#define XREG_FPSCR_C_BIT (1 << 29) +#define XREG_FPSCR_V_BIT (1 << 28) +#define XREG_FPSCR_QC (1 << 27) +#define XREG_FPSCR_AHP (1 << 26) +#define XREG_FPSCR_DEFAULT_NAN (1 << 25) +#define XREG_FPSCR_FLUSHTOZERO (1 << 24) +#define XREG_FPSCR_ROUND_NEAREST (0 << 22) +#define XREG_FPSCR_ROUND_PLUSINF (1 << 22) +#define XREG_FPSCR_ROUND_MINUSINF (2 << 22) +#define XREG_FPSCR_ROUND_TOZERO (3 << 22) +#define XREG_FPSCR_RMODE_BIT (22) +#define XREG_FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT) +#define XREG_FPSCR_STRIDE_BIT (20) +#define XREG_FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT) +#define XREG_FPSCR_LENGTH_BIT (16) +#define XREG_FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT) +#define XREG_FPSCR_IDC (1 << 7) +#define XREG_FPSCR_IXC (1 << 4) +#define XREG_FPSCR_UFC (1 << 3) +#define XREG_FPSCR_OFC (1 << 2) +#define XREG_FPSCR_DZC (1 << 1) +#define XREG_FPSCR_IOC (1 << 0) + +/* MVFR0 bits */ +#define XREG_MVFR0_RMODE_BIT (28) +#define XREG_MVFR0_RMODE_MASK (0xF << XREG_MVFR0_RMODE_BIT) +#define XREG_MVFR0_SHORT_VEC_BIT (24) +#define XREG_MVFR0_SHORT_VEC_MASK (0xF << XREG_MVFR0_SHORT_VEC_BIT) +#define XREG_MVFR0_SQRT_BIT (20) +#define XREG_MVFR0_SQRT_MASK (0xF << XREG_MVFR0_SQRT_BIT) +#define XREG_MVFR0_DIVIDE_BIT (16) +#define XREG_MVFR0_DIVIDE_MASK (0xF << XREG_MVFR0_DIVIDE_BIT) +#define XREG_MVFR0_EXEC_TRAP_BIT (12) +#define XREG_MVFR0_EXEC_TRAP_MASK (0xF << XREG_MVFR0_EXEC_TRAP_BIT) +#define XREG_MVFR0_DP_BIT (8) +#define XREG_MVFR0_DP_MASK (0xF << XREG_MVFR0_DP_BIT) +#define XREG_MVFR0_SP_BIT (4) +#define XREG_MVFR0_SP_MASK (0xF << XREG_MVFR0_SP_BIT) +#define XREG_MVFR0_A_SIMD_BIT (0) +#define XREG_MVFR0_A_SIMD_MASK (0xF << MVFR0_A_SIMD_BIT) + +/* FPEXC bits */ +#define XREG_FPEXC_EX (1 << 31) +#define XREG_FPEXC_EN (1 << 30) +#define XREG_FPEXC_DEX (1 << 29) + + +/** + *@endcond + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XREG_CORTEXA9_H */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xscugic.h b/bsp_z7/ps7_cortexa9_0/include/xscugic.h new file mode 100644 index 0000000..0ee7342 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xscugic.h @@ -0,0 +1,689 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscugic.h +* @addtogroup scugic Overview +* @{ +* @details +* +* The generic interrupt controller driver component. +* +* The interrupt controller driver uses the idea of priority for the various +* handlers. Priority is an integer within the range of 1 and 31 inclusive with +* default of 1 being the highest priority interrupt source. The priorities +* of the various sources can be dynamically altered as needed through +* hardware configuration. +* +* The generic interrupt controller supports the following +* features: +* +* - specific individual interrupt enabling/disabling +* - specific individual interrupt acknowledging +* - attaching specific callback function to handle interrupt source +* - assigning desired priority to interrupt source if default is not +* acceptable. +* +* Details about connecting the interrupt handler of the driver are contained +* in the source file specific to interrupt processing, xscugic_intr.c. +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads +* or thread mutual exclusion, virtual memory, or cache control must be +* satisfied by the layer above this driver. +* +* Interrupt Vector Tables +* +* The device ID of the interrupt controller device is used by the driver as a +* direct index into the configuration data table. The user should populate the +* vector table with handlers and callbacks at run-time using the +* XScuGic_Connect() and XScuGic_Disconnect() functions. +* +* Each vector table entry corresponds to a device that can generate an +* interrupt. Each entry contains an interrupt handler function and an +* argument to be passed to the handler when an interrupt occurs. The +* user must use XScuGic_Connect() when the interrupt handler takes an +* argument other than the base address. +* +* Nested Interrupts Processing +* +* Nested interrupts are not supported by this driver. +* +* NOTE: +* The generic interrupt controller is not a part of the snoop control unit +* as indicated by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a drg  01/19/00 First release
+* 1.01a sdm  11/09/11 The XScuGic and XScuGic_Config structures have changed.
+*		      The HandlerTable (of type XScuGic_VectorTableEntry) is
+*		      moved to XScuGic_Config structure from XScuGic structure.
+*
+*		      The "Config" entry in XScuGic structure is made as
+*		      pointer for better efficiency.
+*
+*		      A new file named as xscugic_hw.c is now added. It is
+*		      to implement low level driver routines without using
+*		      any xscugic instance pointer. They are useful when the
+*		      user wants to use xscugic through device id or
+*		      base address. The driver routines provided are explained
+*		      below.
+*		      XScuGic_DeviceInitialize that takes device id as
+*		      argument and initializes the device (without calling
+*		      XScuGic_CfgInitialize).
+*		      XScuGic_DeviceInterruptHandler that takes device id
+*		      as argument and calls appropriate handlers from the
+*		      HandlerTable.
+*		      XScuGic_RegisterHandler that registers a new handler
+*		      by taking xscugic hardware base address as argument.
+*		      LookupConfigByBaseAddress is used to return the
+*		      corresponding config structure from XScuGic_ConfigTable
+*		      based on the scugic base address passed.
+* 1.02a sdm  12/20/11 Removed AckBeforeService from the XScuGic_Config
+*		      structure.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *.c and *_hw.c to
+*		      *_hw.h
+*		      Added APIs
+*			- XScuGic_SetPriTrigTypeByDistAddr()
+*			- XScuGic_GetPriTrigTypeByDistAddr()
+*		      (CR 702687)
+*			Added support to direct interrupts to the appropriate CPU. Earlier
+*			  interrupts were directed to CPU1 (hard coded). Now depending
+*			  upon the CPU selected by the user (xparameters.h), interrupts
+*			  will be directed to the relevant CPU. This fixes CR 699688.
+* 1.04a hk   05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
+*			  XScuGic_CfgInitialize. Fix for CR#704400 to remove warnings.
+*			  Moved functions XScuGic_SetPriTrigTypeByDistAddr and
+*             XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
+*			  This is fix for CR#705621.
+* 1.05a hk   06/26/13 Modified tcl to export external interrupts correctly to
+*                     xparameters.h. Fix for CR's 690505, 708928 & 719359.
+* 2.0   adk  12/10/13 Updated as per the New Tcl API's
+* 2.1   adk  25/04/14 Fixed the CR:789373 changes are made in the driver tcl file.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.2   asa  02/29/16 Modified DistributorInit function for Zynq AMP case. The
+*			  distributor is left uninitialized for Zynq AMP. It is assumed
+*             that the distributor will be initialized by Linux master. However
+*             for CortexR5 case, the earlier code is left unchanged where the
+*             the interrupt processor target registers in the distributor is
+*             initialized with the corresponding CPU ID on which the application
+*             built over the scugic driver runs.
+*             These changes fix CR#937243.
+*
+* 3.4   asa  04/07/16 Created a new static function DoDistributorInit to simplify
+*            the flow and avoid code duplication. Changes are made for
+*            USE_AMP use case for R5. In a scenario (in R5 split mode) when
+*            one R5 is operating with A53 in open amp config and other
+*            R5 running baremetal app, the existing code
+*            had the potential to stop the whole AMP solution to work (if
+*            for some reason the R5 running the baremetal app tasked to
+*            initialize the Distributor hangs or crashes before initializing).
+*            Changes are made so that the R5 under AMP first checks if
+*            the distributor is enabled or not and if not, it does the
+*            standard Distributor initialization.
+*            This fixes the CR#952962.
+* 3.6   ms   01/23/17 Modified xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 3.7   ms   04/11/17 Modified tcl file to add suffix U for all macro
+*                     definitions of scugic in xparameters.h
+* 3.8   mus  07/05/17 Updated scugic.tcl to add support for interrupts connected
+*                     through util_reduced_vector IP(OR gate)
+*       mus  07/05/17 Updated xdefine_zynq_canonical_xpars proc to initialize
+*                     the HandlerTable in XScuGic_ConfigTable to 0, it removes
+*                     the compilation warning in xscugic_g.c. Fix for CR#978736.
+*       mus  07/25/17 Updated xdefine_gic_params proc to export correct canonical
+*                     definitions for pl to ps interrupts.Fix for CR#980534
+* 3.9   mus  02/21/18 Added new API's XScuGic_UnmapAllInterruptsFromCpu and
+*                     XScuGic_InterruptUnmapFromCpu, These API's can be used
+*                     by applications to unmap specific/all interrupts from
+*                     target CPU.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+* 4.0   mus  11/22/18 Fixed bugs in software interrupt generation through
+*                      XScuGic_SoftwareIntr API
+* 4.1   asa  03/30/19 Made changes not to direct each interrupt to all
+*                     available CPUs by default. This was breaking AMP
+*                     behavior. Instead every time an interrupt enable
+*                     request is received, the interrupt was mapped to
+*                     the respective CPU. There were several other changes
+*                     made to implement this. This set of changes was to
+*                     fix CR-1024716.
+* 4.1   mus  06/19/19 Added API's XScuGic_MarkCoreAsleep and
+*                     XScuGic_MarkCoreAwake to mark processor core as
+*                     asleep or awake. Fix for CR#1027220.
+* 4.5   asa  03/07/21 Included a header file xil_spinlock.h to ensure that
+*                     GIC driver can use newly introduced spinlock
+*                     functionality.
+* 4.6	sk   08/05/21 Fix scugic misrac violations.
+* 4.7   dp   11/22/21 Added new API XScuGic_IsInitialized() to check and return
+*                     the GIC initialization status.
+* 5.0   mus  22/02/22 Add support for VERSAL NET
+* 	adk  04/18/22 Replace infinite while loops in the examples with
+* 		      Xil_WaitForEventSet() API.
+*       dp   04/25/22 Correct Trigger index calculation in macro
+*                     XScuGic_Get_Rdist_Int_Trigger_Index
+* 5.0   dp   11/07/22 Add macros for accessing the GIC Binary Point and
+*                     Running Priority registers of Cortex-R52.
+* 5.1   mus  02/13/23 Updated XScuGic_CfgInitialize, XScuGic_Enable and
+*                     XScuGic_Disable to support interrupts on each core
+*                     of all CortexA78/CortexR52 clusters in VERSAL NET SoC.
+*                     While at it, modified interrupt routing logic to make
+*                     use of CPU affinity register instead of XPAR_CPU_ID macro.
+*                     Also, XScuGic_CfgInitialize has been updated to find
+*                     redistributor base address of core on which API is
+*                     executed, redistributor address will be stored in newly
+*                     added member of XScuGic data structure "RedistBaseAddr".
+*                     It fixes CR#1150432.
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_H /* prevent circular inclusions */ +#define XSCUGIC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xil_io.h" +#include "xscugic_hw.h" +#include "xil_exception.h" +#include "xil_spinlock.h" + +/************************** Constant Definitions *****************************/ + +#define EFUSE_STATUS_OFFSET 0x10 +#define EFUSE_STATUS_CPU_MASK 0x80 + +#if !defined (ARMR5) && !defined (__aarch64__) && !defined (ARMA53_32) +#define ARMA9 +#endif + +#define XSCUGIC500_DCTLR_ARE_NS_ENABLE 0x20 +#define XSCUGIC500_DCTLR_ARE_S_ENABLE 0x10 + +#if defined (VERSAL_NET) +#define XSCUGIC_CLUSTERID_MASK 0xF0U +#define XSCUGIC_COREID_MASK 0xFU +#define XSCUGIC_CLUSTERID_SHIFT 4U +#define XSCUGIC_COREID_SHIFT 0U + +#define XSCUGIC_SGI1R_AFFINITY1_SHIFT 16U +#define XSCUGIC_SGI1R_AFFINITY2_SHIFT 32U + +#define XSCUGIC_IROUTER_AFFINITY1_SHIFT 8U +#define XSCUGIC_IROUTER_AFFINITY2_SHIFT 16U + +#define XSCUGIC_IROUTER_IRM_MASK 0x80000000U +#endif + +/**************************** Type Definitions *******************************/ + +/* The following data type defines each entry in an interrupt vector table. + * The callback reference is the base address of the interrupting device + * for the low level driver and an instance pointer for the high level driver. + */ +typedef struct +{ + Xil_InterruptHandler Handler; + void *CallBackRef; +} XScuGic_VectorTableEntry; + +/** + * This typedef contains configuration information for the device. + */ +typedef struct +{ + u16 DeviceId; /**< Unique ID of device */ + u32 CpuBaseAddress; /**< CPU Interface Register base address */ + u32 DistBaseAddress; /**< Distributor Register base address */ + XScuGic_VectorTableEntry HandlerTable[XSCUGIC_MAX_NUM_INTR_INPUTS];/**< + Vector table of interrupt handlers */ +} XScuGic_Config; + +/** + * The XScuGic driver instance data. The user is required to allocate a + * variable of this type for every intc device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct +{ + XScuGic_Config *Config; /**< Configuration table entry */ +#if defined (GICv3) + UINTPTR RedistBaseAddr; +#endif + u32 IsReady; /**< Device is initialized and ready */ + u32 UnhandledInterrupts; /**< Intc Statistics */ +} XScuGic; + +/************************** Variable Definitions *****************************/ + +extern XScuGic_Config XScuGic_ConfigTable[]; /**< Config table */ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_CPUWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_CPUWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_CPUReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_CPUReadReg(InstancePtr, RegOffset) \ + (XScuGic_ReadReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_DistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_DistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset))) + +#if defined (GICv3) +/****************************************************************************/ +/** +* +* Write the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(InstancePtr->RedistBaseAddr, RegOffset, (u32)Data)) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg(InstancePtr->RedistBaseAddr, RegOffset)) + +/****************************************************************************/ +/** +* +* Write the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(InstancePtr->RedistBaseAddr + \ + XSCUGIC_RDIST_SGI_PPI_OFFSET, (RegOffset), ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg(InstancePtr->RedistBaseAddr + XSCUGIC_RDIST_SGI_PPI_OFFSET, \ + RegOffset)) + +#if defined(ARMR52) +#define XREG_ICC_SRE_EL1 "p15, 0, %0, c12, c12, 5" +#define XREG_ICC_IGRPEN0_EL1 "p15, 0, %0, c12, c12, 6" +#define XREG_ICC_IGRPEN1_EL1 "p15, 0, %0, c12, c12, 7" +#define XREG_ICC_SGI0R_EL1 "p15, 2, %0, %1, c12" +#define XREG_ICC_SGI1R_EL1 "p15, 0, %0, %1, c12" +#define XREG_ICC_PMR_EL1 "p15, 0, %0, c4, c6, 0" +#define XREG_ICC_IAR0_EL1 "p15, 0, %0, c12, c8, 0" +#define XREG_ICC_EOIR0_EL1 "p15, 0, %0, c12, c8, 1" +#define XREG_IMP_CBAR "p15, 1, %0, c15, c3, 0" +#define XREG_ICC_BPR0_EL1 "p15, 0, %0, c12, c8, 3" +#define XREG_ICC_RPR_EL1 "p15, 0, %0, c12, c11, 3" +#else +#define XREG_ICC_SRE_EL1 "S3_0_C12_C12_5" +#define XREG_ICC_SRE_EL3 "S3_6_C12_C12_5" +#define XREG_ICC_IGRPEN0_EL1 "S3_0_C12_C12_6" +#define XREG_ICC_IGRPEN1_EL1 "S3_0_C12_C12_7" +#define XREG_ICC_IGRPEN1_EL3 "S3_6_C12_C12_7" +#define XREG_ICC_SGI0R_EL1 "S3_0_C12_C11_7" +#define XREG_ICC_SGI1R_EL1 "S3_0_C12_C11_5" +#define XREG_ICC_PMR_EL1 "S3_0_C4_C6_0" +#define XREG_ICC_IAR0_EL1 "S3_0_C12_C8_0" +#define XREG_ICC_IAR1_EL1 "S3_0_C12_C12_0" +#define XREG_ICC_EOIR0_EL1 "S3_0_C12_C8_1" +#define XREG_ICC_EOIR1_EL1 "S3_0_C12_C12_1" +#endif +/****************************************************************************/ +/** +* This function enables system register interface for GIC CPU Interface +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#define XScuGic_Enable_SystemReg_CPU_Interface_EL3() mtcpnotoken(XREG_ICC_SRE_EL3, 0xF); +#define XScuGic_Enable_SystemReg_CPU_Interface_EL1() mtcpnotoken(XREG_ICC_SRE_EL1, 0xF); +#elif defined (ARMR52) +#define XScuGic_Enable_SystemReg_CPU_Interface_EL1() mtcp(XREG_ICC_SRE_EL1, 0xF); +#endif +/****************************************************************************/ +/** +* This function enables Grou0 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined(ARMR52) +#define XScuGic_Enable_Group0_Interrupts() mtcp(XREG_ICC_IGRPEN0_EL1,0x1); +#else +#define XScuGic_Enable_Group0_Interrupts() mtcpnotoken(XREG_ICC_IGRPEN0_EL1,0x1); +#endif +/****************************************************************************/ +/** +* This function enables Group1 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (ARMR52) + +#define XScuGic_Enable_Group1_Interrupts() \ + mtcp (XREG_ICC_IGRPEN1_EL1, 0x1 | mfcp(XREG_ICC_IGRPEN1_EL1) ); +#elif EL1_NONSECURE +#define XScuGic_Enable_Group1_Interrupts() \ + mtcpnotoken(XREG_ICC_IGRPEN1_EL1, 0x1 | mfcpnotoken(XREG_ICC_IGRPEN1_EL1) ); +#else +#define XScuGic_Enable_Group1_Interrupts() \ + mtcpnotoken(XREG_ICC_IGRPEN1_EL3, 0x1 | mfcpnotoken(XREG_ICC_IGRPEN1_EL3) ); +#endif +/****************************************************************************/ +/** +* This function writes to ICC_SGI0R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined(ARMR52) +#define XScuGic_WriteICC_SGI0R_EL1(val) mtcp2(XREG_ICC_SGI0R_EL1,val) +#else +#define XScuGic_WriteICC_SGI0R_EL1(val) mtcpnotoken(XREG_ICC_SGI0R_EL1,val) +#endif + +/****************************************************************************/ +/** +* This function writes to ICC_SGI1R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined(ARMR52) +#define XScuGic_WriteICC_SGI1R_EL1(val) mtcp2(XREG_ICC_SGI1R_EL1,val) +#else +#define XScuGic_WriteICC_SGI1R_EL1(val) mtcpnotoken(XREG_ICC_SGI1R_EL1,val) +#endif + +/****************************************************************************/ +/** +* This function reads ICC_SGI1R_EL1 register +* +* @param None +* +* @return Value of ICC_SGI1R_EL1 register +* +* @note None. +* +*****************************************************************************/ +#if defined (ARMR52) +#define XScuGic_ReadICC_SGI1R_EL1() mfcp(XREG_ICC_SGI1R_EL1) +#else +#define XScuGic_ReadICC_SGI1R_EL1() mfcpnotoken(XREG_ICC_SGI1R_EL1) +#endif +/****************************************************************************/ +/** +* This function sets interrupt priority filter +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (ARMR52) +#define XScuGic_set_priority_filter(val) mtcp(XREG_ICC_PMR_EL1, val) +#else +#define XScuGic_set_priority_filter(val) mtcpnotoken(XREG_ICC_PMR_EL1, val) +#endif +/****************************************************************************/ +/** +* This function returns interrupt id of highest priority pending interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined(ARMR52) +#define XScuGic_get_IntID() mfcp(XREG_ICC_IAR0_EL1) +#elif EL3 +#define XScuGic_get_IntID() mfcpnotoken(XREG_ICC_IAR0_EL1) +#else +#define XScuGic_get_IntID() mfcpnotoken(XREG_ICC_IAR1_EL1) +#endif +/****************************************************************************/ +/** +* This function acks the interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined(ARMR52) +#define XScuGic_ack_Int(val) mtcp(XREG_ICC_EOIR0_EL1,val) +#elif EL3 +#define XScuGic_ack_Int(val) mtcpnotoken(XREG_ICC_EOIR0_EL1,val) +#else +#define XScuGic_ack_Int(val) mtcpnotoken(XREG_ICC_EOIR1_EL1,val) +#endif +/****************************************************************************/ +/** +* This macro returns bit position for the specific interrupt's trigger type +* configuration within GICR_ICFGR0/GICR_ICFGR1 register +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Get_Rdist_Int_Trigger_Index(IntrId) ((Int_Id%16) * 2U) +#endif +/************************** Function Prototypes ******************************/ + +/* + * Required functions in xscugic.c + */ + +s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id, + Xil_InterruptHandler Handler, void *CallBackRef); +void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id); + +void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id); +void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id); + +s32 XScuGic_CfgInitialize(XScuGic *InstancePtr, XScuGic_Config *ConfigPtr, + u32 EffectiveAddr); + +s32 XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Identifier); + +void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Identifier, u32 Int_Id); +void XScuGic_InterruptUnmapFromCpu(XScuGic *InstancePtr, u8 Cpu_Identifier, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpu(XScuGic *InstancePtr, u8 Cpu_Identifier); +void XScuGic_Stop(XScuGic *InstancePtr); +void XScuGic_SetCpuID(u32 CpuCoreId); +u32 XScuGic_GetCpuID(void); +u8 XScuGic_IsInitialized(u32 DeviceId); +/* + * Initialization functions in xscugic_sinit.c + */ +XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId); +XScuGic_Config *XScuGic_LookupConfigBaseAddr(UINTPTR BaseAddress); + +/* + * Interrupt functions in xscugic_intr.c + */ +void XScuGic_InterruptHandler(XScuGic *InstancePtr); + +/* + * Self-test functions in xscugic_selftest.c + */ +s32 XScuGic_SelfTest(XScuGic *InstancePtr); + +#if defined (GICv3) +void XScuGic_MarkCoreAsleep(XScuGic *InstancePtr); +void XScuGic_MarkCoreAwake(XScuGic *InstancePtr); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xscugic_hw.h b/bsp_z7/ps7_cortexa9_0/include/xscugic_hw.h new file mode 100644 index 0000000..0bbd0c4 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xscugic_hw.h @@ -0,0 +1,753 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscugic_hw.h +* @addtogroup scugic Overview +* @{ +* +* This header file contains identifiers and HW access functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* The driver functions/APIs are defined in xscugic.h. +* +* This GIC device has two parts, a distributor and CPU interface(s). Each part +* has separate register definition sections. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 "xil_exception.h" added as include.
+*		      Macros XScuGic_EnableIntr and XScuGic_DisableIntr are
+*		      added to enable or disable interrupts based on
+*		      Distributor Register base address. Normally users use
+*		      XScuGic instance and call XScuGic_Enable or
+*		      XScuGic_Disable to enable/disable interrupts. These
+*		      new macros are provided when user does not want to
+*		      use an instance pointer but still wants to enable or
+*		      disable interrupts.
+*		      Function prototypes for functions (present in newly
+*		      added file xscugic_hw.c) are added.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *_hw.c (CR
+*		      702687).
+* 1.04a hk   05/04/13 Fix for CR#705621. Moved function prototypes
+*		      XScuGic_SetPriTrigTypeByDistAddr and
+*         	      XScuGic_GetPriTrigTypeByDistAddr here from xscugic.h
+* 3.0	pkp  12/09/14 changed XSCUGIC_MAX_NUM_INTR_INPUTS for
+*		      Zynq Ultrascale Mp
+* 3.0   kvn  02/13/14 Modified code for MISRA-C:2012 compliance.
+* 3.2	pkp  11/09/15 Corrected the interrupt processsor target mask value
+*					  for CPU interface 2 i.e. XSCUGIC_SPI_CPU2_MASK
+* 3.9   mus  02/21/18 Added new API's XScuGic_InterruptUnmapFromCpuByDistAddr
+*					  and XScuGic_UnmapAllInterruptsFromCpuByDistAddr, These
+*					  API's can be used by applications to unmap specific/all
+*					  interrupts from target CPU. It fixes CR#992490.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+* 4.1   asa  03/30/19 Removed macros for XScuGic_EnableIntr, and
+*                     XScuGic_DisableIntr. These are now C functions. This
+*                     change was to fix CR-1024716.
+* 4.1   mus  06/12/19 Updated XSCUGIC_MAX_NUM_INTR_INPUTS for Versal.
+* 4.6	sk   06/07/21 Delete the commented macro code to fix the MISRA-C warning.
+* 4.6	sk   08/05/21 Fix Scugic Misrac violations.
+* 4.7	sk   12/10/21 Update XSCUGIC_SPI_INT_ID_START macro from signed to unsigned
+* 		      to fix misrac violation.
+* 4.7   mus  03/17/22 GICv3 coupled with A72 has different redistributor for
+*                     each core, and each redistributor has different address,
+*                     Updated #define for re-distributor address to have correct
+*                     value based on the cpu number. It fixes CR#1126156.
+* 5.0   mus  22/02/22 Added support for VERSAL NET
+* 5.1   mus  02/13/23 Added #defines required for logic to find redistributor
+*                     based address for specific CPU core. Also, added new macro
+*                     XScuGic_ReadReg64 to read 64 bit value from specific address.
+* 5.1   mus  02/15/23 Added support for VERSAL_NET APU and RPU GIC.
+*
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_HW_H /* prevent circular inclusions */ +#define XSCUGIC_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xil_exception.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ +#if (defined (versal) && !defined(ARMR5)) || defined (ARMR52) +#define GICv3 +#endif + +#if defined (VERSAL_NET) && ! defined (ARMR52) +#define GIC600 +#endif + +#if defined (VERSAL_NET) +#if defined (ARMR52) +#define XSCUGIC_NUM_OF_CORES_PER_CLUSTER 2U +#else +#define XSCUGIC_NUM_OF_CORES_PER_CLUSTER 4U +#endif +#endif + +/* + * The maximum number of interrupts supported by the hardware. + */ +#ifdef PLATFORM_ZYNQ +#define XSCUGIC_MAX_NUM_INTR_INPUTS 95U /* Maximum number of interrupt defined by Zynq */ +#elif defined (VERSAL_NET) +#define XSCUGIC_MAX_NUM_INTR_INPUTS 256U /* Maximum number of interrupt sources in VERSAL NET */ +#elif defined (versal) +#define XSCUGIC_MAX_NUM_INTR_INPUTS 192U +#else +#define XSCUGIC_MAX_NUM_INTR_INPUTS 195U /* Maximum number of interrupt defined by Zynq Ultrascale Mp */ +#endif + +/* + * First Interrupt Id for SPI interrupts. + */ +#define XSCUGIC_SPI_INT_ID_START 0x20U +/* + * The maximum priority value that can be used in the GIC. + */ +#define XSCUGIC_MAX_INTR_PRIO_VAL 248U +#define XSCUGIC_INTR_PRIO_MASK 0x000000F8U + +/** @name Distributor Interface Register Map + * + * Define the offsets from the base address for all Distributor registers of + * the interrupt controller, some registers may be reserved in the hardware + * device. + * @{ + */ +#define XSCUGIC_DIST_EN_OFFSET 0x00000000U /**< Distributor Enable + Register */ +#define XSCUGIC_IC_TYPE_OFFSET 0x00000004U /**< Interrupt Controller + Type Register */ +#define XSCUGIC_DIST_IDENT_OFFSET 0x00000008U /**< Implementor ID + Register */ +#define XSCUGIC_SECURITY_OFFSET 0x00000080U /**< Interrupt Security + Register */ +#define XSCUGIC_ENABLE_SET_OFFSET 0x00000100U /**< Enable Set + Register */ +#define XSCUGIC_DISABLE_OFFSET 0x00000180U /**< Enable Clear Register */ +#define XSCUGIC_PENDING_SET_OFFSET 0x00000200U /**< Pending Set + Register */ +#define XSCUGIC_PENDING_CLR_OFFSET 0x00000280U /**< Pending Clear + Register */ +#define XSCUGIC_ACTIVE_OFFSET 0x00000300U /**< Active Status Register */ +#define XSCUGIC_PRIORITY_OFFSET 0x00000400U /**< Priority Level Register */ +#define XSCUGIC_SPI_TARGET_OFFSET 0x00000800U /**< SPI Target + Register 0x800-0x8FB */ +#define XSCUGIC_INT_CFG_OFFSET 0x00000C00U /**< Interrupt Configuration + Register 0xC00-0xCFC */ +#define XSCUGIC_PPI_STAT_OFFSET 0x00000D00U /**< PPI Status Register */ +#define XSCUGIC_SPI_STAT_OFFSET 0x00000D04U /**< SPI Status Register + 0xd04-0xd7C */ +#define XSCUGIC_AHB_CONFIG_OFFSET 0x00000D80U /**< AHB Configuration + Register */ +#define XSCUGIC_SFI_TRIG_OFFSET 0x00000F00U /**< Software Triggered + Interrupt Register */ +#define XSCUGIC_PERPHID_OFFSET 0x00000FD0U /**< Peripheral ID Reg */ +#if defined (GICv3) +#define XSCUGIC_PCELLID_OFFSET 0x0000FFF0U /**< Pcell ID Register */ +#else +#define XSCUGIC_PCELLID_OFFSET 0x00000FF0U /**< Pcell ID Register */ +#endif +/* @} */ + +/** @name Distributor Enable Register + * Controls if the distributor response to external interrupt inputs. + * @{ + */ +#if defined (GICv3) +#define XSCUGIC_EN_INT_MASK 0x00000003U /**< Interrupt In Enable */ +#else +#define XSCUGIC_EN_INT_MASK 0x00000001U /**< Interrupt In Enable */ +#endif +/* @} */ + +/** @name Interrupt Controller Type Register + * @{ + */ +#define XSCUGIC_LSPI_MASK 0x0000F800U /**< Number of Lockable + Shared Peripheral + Interrupts*/ +#define XSCUGIC_DOMAIN_MASK 0x00000400U /**< Number os Security domains*/ +#define XSCUGIC_CPU_NUM_MASK 0x000000E0U /**< Number of CPU Interfaces */ +#define XSCUGIC_NUM_INT_MASK 0x0000001FU /**< Number of Interrupt IDs */ +/* @} */ + +/** @name Implementor ID Register + * Implementor and revision information. + * @{ + */ +#define XSCUGIC_REV_MASK 0x00FFF000U /**< Revision Number */ +#define XSCUGIC_IMPL_MASK 0x00000FFFU /**< Implementor */ +/* @} */ + +/** @name Interrupt Security Registers + * Each bit controls the security level of an interrupt, either secure or non + * secure. These registers can only be accessed using secure read and write. + * There are registers for each of the CPU interfaces at offset 0x080. A + * register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x084. + * @{ + */ +#define XSCUGIC_INT_NS_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Set Register + * Each bit controls the enabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Use the ENABLE_CLR register to set a + * bit to 0. + * There are registers for each of the CPU interfaces at offset 0x100. With up + * to 8 registers aliased to the same address. A register set for the SPI + * interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x104. + * @{ + */ +#define XSCUGIC_INT_EN_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Clear Register + * Each bit controls the disabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Writing a 1 disables an interrupt and + * sets the corresponding bit to 0. + * There are registers for each of the CPU interfaces at offset 0x180. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x184. + * @{ + */ +#define XSCUGIC_INT_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Set Register + * Each bit controls the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 sets + * an interrupt to the pending state. + * There are registers for each of the CPU interfaces at offset 0x200. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x204. + * @{ + */ +#define XSCUGIC_PEND_SET_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Clear Register + * Each bit can clear the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 + * clears the pending state of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x280. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x284. + * @{ + */ +#define XSCUGIC_PEND_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Active Status Register + * Each bit provides the Active status of an interrupt, a + * 0 is not Active, a 1 is Active. This is a read only register. + * There are registers for each of the CPU interfaces at offset 0x300. With up + * to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x380. + * @{ + */ +#define XSCUGIC_ACTIVE_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Priority Level Register + * Each byte in a Priority Level Register sets the priority level of an + * interrupt. Reading the register provides the priority level of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x400 through + * 0x41C. With up to 8 registers aliased to each address. + * 0 is highest priority, 0xFF is lowest. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x420. + * @{ + */ +#define XSCUGIC_PRIORITY_MASK 0x000000FFU /**< Each Byte corresponds to an + INT_ID */ +#define XSCUGIC_PRIORITY_MAX 0x000000FFU /**< Highest value of a priority + actually the lowest priority*/ +/* @} */ + +/** @name SPI Target Register 0x800-0x8FB + * Each byte references a separate SPI and programs which of the up to 8 CPU + * interfaces are sent a Pending interrupt. + * There are registers for each of the CPU interfaces at offset 0x800 through + * 0x81C. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x820. + * + * This driver does not support multiple CPU interfaces. These are included + * for complete documentation. + * @{ + */ +#define XSCUGIC_SPI_CPU7_MASK 0x00000080U /**< CPU 7 Mask*/ +#define XSCUGIC_SPI_CPU6_MASK 0x00000040U /**< CPU 6 Mask*/ +#define XSCUGIC_SPI_CPU5_MASK 0x00000020U /**< CPU 5 Mask*/ +#define XSCUGIC_SPI_CPU4_MASK 0x00000010U /**< CPU 4 Mask*/ +#define XSCUGIC_SPI_CPU3_MASK 0x00000008U /**< CPU 3 Mask*/ +#define XSCUGIC_SPI_CPU2_MASK 0x00000004U /**< CPU 2 Mask*/ +#define XSCUGIC_SPI_CPU1_MASK 0x00000002U /**< CPU 1 Mask*/ +#define XSCUGIC_SPI_CPU0_MASK 0x00000001U /**< CPU 0 Mask*/ +/* @} */ + +/** @name Interrupt Configuration Register 0xC00-0xCFC + * The interrupt configuration registers program an SFI to be active HIGH level + * sensitive or rising edge sensitive. + * Each bit pair describes the configuration for an INT_ID. + * SFI Read Only b10 always + * PPI Read Only depending on how the PPIs are configured. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive + * SPI LSB is read only. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive/ + * There are registers for each of the CPU interfaces at offset 0xC00 through + * 0xC04. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0xC08. + * @{ + */ +#define XSCUGIC_INT_CFG_MASK 0x00000003U /**< */ +/* @} */ + +/** @name PPI Status Register + * Enables an external AMBA master to access the status of the PPI inputs. + * A CPU can only read the status of its local PPI signals and cannot read the + * status for other CPUs. + * This register is aliased for each CPU interface. + * @{ + */ +#define XSCUGIC_PPI_C15_MASK 0x00008000U /**< PPI Status */ +#define XSCUGIC_PPI_C14_MASK 0x00004000U /**< PPI Status */ +#define XSCUGIC_PPI_C13_MASK 0x00002000U /**< PPI Status */ +#define XSCUGIC_PPI_C12_MASK 0x00001000U /**< PPI Status */ +#define XSCUGIC_PPI_C11_MASK 0x00000800U /**< PPI Status */ +#define XSCUGIC_PPI_C10_MASK 0x00000400U /**< PPI Status */ +#define XSCUGIC_PPI_C09_MASK 0x00000200U /**< PPI Status */ +#define XSCUGIC_PPI_C08_MASK 0x00000100U /**< PPI Status */ +#define XSCUGIC_PPI_C07_MASK 0x00000080U /**< PPI Status */ +#define XSCUGIC_PPI_C06_MASK 0x00000040U /**< PPI Status */ +#define XSCUGIC_PPI_C05_MASK 0x00000020U /**< PPI Status */ +#define XSCUGIC_PPI_C04_MASK 0x00000010U /**< PPI Status */ +#define XSCUGIC_PPI_C03_MASK 0x00000008U /**< PPI Status */ +#define XSCUGIC_PPI_C02_MASK 0x00000004U /**< PPI Status */ +#define XSCUGIC_PPI_C01_MASK 0x00000002U /**< PPI Status */ +#define XSCUGIC_PPI_C00_MASK 0x00000001U /**< PPI Status */ +/* @} */ + +/** @name SPI Status Register 0xd04-0xd7C + * Enables an external AMBA master to access the status of the SPI inputs. + * There are up to 63 registers if the maximum number of SPI inputs are + * configured. + * @{ + */ +#define XSCUGIC_SPI_N_MASK 0x00000001U /**< Each bit corresponds to an SPI + input */ +/* @} */ + +/** @name AHB Configuration Register + * Provides the status of the CFGBIGEND input signal and allows the endianness + * of the GIC to be set. + * @{ + */ +#define XSCUGIC_AHB_END_MASK 0x00000004U /**< 0-GIC uses little Endian, + 1-GIC uses Big Endian */ +#define XSCUGIC_AHB_ENDOVR_MASK 0x00000002U /**< 0-Uses CFGBIGEND control, + 1-use the AHB_END bit */ +#define XSCUGIC_AHB_TIE_OFF_MASK 0x00000001U /**< State of CFGBIGEND */ + +/* @} */ + +/** @name Software Triggered Interrupt Register + * Controls issuing of software interrupts. + * @{ + */ +#define XSCUGIC_SFI_SELFTRIG_MASK 0x02010000U +#define XSCUGIC_SFI_TRIG_TRGFILT_MASK 0x03000000U /**< Target List filter + b00-Use the target List + b01-All CPUs except requester + b10-To Requester + b11-reserved */ +#define XSCUGIC_SFI_TRIG_CPU_MASK 0x00FF0000U /**< CPU Target list */ +#define XSCUGIC_SFI_TRIG_SATT_MASK 0x00008000U /**< 0= Use a secure interrupt */ +#define XSCUGIC_SFI_TRIG_INTID_MASK 0x0000000FU /**< Set to the INTID + signaled to the CPU*/ +/* @} */ + +/** @name CPU Interface Register Map + * + * Define the offsets from the base address for all CPU registers of the + * interrupt controller, some registers may be reserved in the hardware device. + * @{ + */ +#define XSCUGIC_CONTROL_OFFSET 0x00000000U /**< CPU Interface Control + Register */ +#define XSCUGIC_CPU_PRIOR_OFFSET 0x00000004U /**< Priority Mask Reg */ +#define XSCUGIC_BIN_PT_OFFSET 0x00000008U /**< Binary Point Register */ +#define XSCUGIC_INT_ACK_OFFSET 0x0000000CU /**< Interrupt ACK Reg */ +#define XSCUGIC_EOI_OFFSET 0x00000010U /**< End of Interrupt Reg */ +#define XSCUGIC_RUN_PRIOR_OFFSET 0x00000014U /**< Running Priority Reg */ +#define XSCUGIC_HI_PEND_OFFSET 0x00000018U /**< Highest Pending Interrupt + Register */ +#define XSCUGIC_ALIAS_BIN_PT_OFFSET 0x0000001CU /**< Aliased non-Secure + Binary Point Register */ + +/**< 0x00000020 to 0x00000FBC are reserved and should not be read or written + * to. */ +/* @} */ + + +/** @name Control Register + * CPU Interface Control register definitions + * All bits are defined here although some are not available in the non-secure + * mode. + * @{ + */ +#define XSCUGIC_CNTR_SBPR_MASK 0x00000010U /**< Secure Binary Pointer, + 0=separate registers, + 1=both use bin_pt_s */ +#define XSCUGIC_CNTR_FIQEN_MASK 0x00000008U /**< Use nFIQ_C for secure + interrupts, + 0= use IRQ for both, + 1=Use FIQ for secure, IRQ for non*/ +#define XSCUGIC_CNTR_ACKCTL_MASK 0x00000004U /**< Ack control for secure or non secure */ +#define XSCUGIC_CNTR_EN_NS_MASK 0x00000002U /**< Non Secure enable */ +#define XSCUGIC_CNTR_EN_S_MASK 0x00000001U /**< Secure enable, 0=Disabled, 1=Enabled */ +/* @} */ + + +/** @name Binary Point Register + * Binary Point register definitions + * @{ + */ + +#define XSCUGIC_BIN_PT_MASK 0x00000007U /**< Binary point mask value + Value Secure Non-secure + b000 0xFE 0xFF + b001 0xFC 0xFE + b010 0xF8 0xFC + b011 0xF0 0xF8 + b100 0xE0 0xF0 + b101 0xC0 0xE0 + b110 0x80 0xC0 + b111 0x00 0x80 + */ +/*@}*/ + +/** @name Interrupt Acknowledge Register + * Interrupt Acknowledge register definitions + * Identifies the current Pending interrupt, and the CPU ID for software + * interrupts. + */ +#define XSCUGIC_ACK_INTID_MASK 0x000003FFU /**< Interrupt ID */ +#define XSCUGIC_CPUID_MASK 0x00000C00U /**< CPU ID */ +/* @} */ + +/** @name End of Interrupt Register + * End of Interrupt register definitions + * Allows the CPU to signal the GIC when it completes an interrupt service + * routine. + */ +#define XSCUGIC_EOI_INTID_MASK 0x000003FFU /**< Interrupt ID */ + +/* @} */ + +/** @name Running Priority Register + * Running Priority register definitions + * Identifies the interrupt priority level of the highest priority active + * interrupt. + */ +#define XSCUGIC_RUN_PRIORITY_MASK 0x000000FFU /**< Interrupt Priority */ +/* @} */ + +#if defined (GICv3) +#define XSCUGIC_IROUTER_BASE_OFFSET 0x6000U +#endif +/* + * Highest Pending Interrupt register definitions + * Identifies the interrupt priority of the highest priority pending interrupt + */ +#define XSCUGIC_PEND_INTID_MASK 0x000003FFU /**< Pending Interrupt ID */ +/* @} */ +#if defined (GICv3) +/** @name ReDistributor Interface Register Map + * + * @{ + */ +#if defined (VERSAL_NET) && ! defined (ARMR52) +#define XSCUGIC_RDIST_START_ADDR 0xE2060000U +#define XSCUGIC_RDIST_END_ADDR 0xE2260000U +#elif defined (ARMR52) +#define XSCUGIC_RDIST_START_ADDR 0xE2100000U +#define XSCUGIC_RDIST_END_ADDR 0xE2130000U +#else +#define XSCUGIC_RDIST_START_ADDR 0xF9080000U +#define XSCUGIC_RDIST_END_ADDR 0xF90B0000U +#endif +#define XSCUGIC_RDIST_OFFSET 0x20000U /* offset between consecutive redistributors */ +#define XSCUGIC_RDIST_SGI_PPI_OFFSET 0x10000U /* offset between control redistributor and SGI/PPI redistributor */ +#define XSCUGIC_GICR_TYPER_AFFINITY_SHIFT 32U +#define XSCUGIC_GICR_TYPER_AFFINITY_MASK 0xFFFFFFFF00000000UL + +#define XSCUGIC_RDIST_ISENABLE_OFFSET 0x100U +#define XSCUGIC_RDIST_IPRIORITYR_OFFSET 0x400U +#define XSCUGIC_RDIST_IGROUPR_OFFSET 0x80U +#define XSCUGIC_RDIST_GRPMODR_OFFSET 0xD00U +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET 0xC00U +#define XSCUGIC_RDIST_TYPER_OFFSET 0x8U +#define XSCUGIC_RDIST_WAKER_OFFSET 0x14U +#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U + +#if defined (GIC600) +#define XSCUGIC_RDIST_PWRR_OFFSET 0x24U +#endif +/* + * GICR_IGROUPR register definitions + */ +#if (defined(ARMR52) || EL3) +#define XSCUGIC_DEFAULT_SECURITY 0x0U +#else +#define XSCUGIC_DEFAULT_SECURITY 0xFFFFFFFFU +#endif +/* + * GICR_WAKER register definitions + */ +#define XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK 0x7 +#define XSCUGIC_RDIST_PWRR_RDPD_MASK 0x1U +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the Interrupt Configuration Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_INT_CFG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_INT_CFG_OFFSET + (((InterruptID)/16U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Priority Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_PRIORITY_OFFSET + (((InterruptID)/4U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Routing Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_IROUTER_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_IROUTER_BASE_OFFSET + (InterruptID * 8)) + +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SPI_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SPI_TARGET_OFFSET + (((InterruptID)/4U) * 4U)) +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SECURITY_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SECURITY_OFFSET + (((InterruptID)/32U)*4U)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt configuration register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_INT_CONFIG_OFFSET + ((InterruptID /16)*4)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt Priority register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_IPRIORITYR_OFFSET + (InterruptID * 4)) +/****************************************************************************/ +/** +* +* Read the Interrupt Clear-Enable Register offset for an interrupt ID +* +* @param Register is the register offset for the clear/enable bank. +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_EN_DIS_OFFSET_CALC(Register, InterruptID) \ + ((Register) + (((InterruptID)/32U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReadReg(BaseAddress, RegOffset) \ + (Xil_In32((BaseAddress) + (RegOffset))) + +/****************************************************************************/ +/** +* +* Read the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be read +* +* @return The 64-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_ReadReg64(UINTPTR BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReadReg64(BaseAddress, RegOffset) \ + (Xil_In64((BaseAddress) + (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_WriteReg(BaseAddress, RegOffset, Data) \ + (Xil_Out32(((BaseAddress) + (RegOffset)), ((u32)(Data)))) + + +/************************** Function Prototypes ******************************/ + +void XScuGic_DeviceInterruptHandler(void *DeviceId); +s32 XScuGic_DeviceInitialize(u32 DeviceId); +void XScuGic_RegisterHandler(u32 BaseAddress, s32 InterruptID, + Xil_InterruptHandler IntrHandler, void *CallBackRef); +void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_GetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_InterruptMapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id); +void XScuGic_InterruptUnmapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id); +void XScuGic_EnableIntr (u32 DistBaseAddress, u32 Int_Id); +void XScuGic_DisableIntr (u32 DistBaseAddress, u32 Int_Id); +#if defined(GICv3) +UINTPTR XScuGic_GetRedistBaseAddr(void); +#endif +/************************** Variable Definitions *****************************/ +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xscutimer.h b/bsp_z7/ps7_cortexa9_0/include/xscutimer.h new file mode 100644 index 0000000..bdce1c6 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xscutimer.h @@ -0,0 +1,350 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscutimer.h +* @addtogroup scutimer_v2_4 +* @{ +* @details +* +* The timer driver supports the Cortex A9 private timer. +* +* The timer driver supports the following features: +* - Normal mode and Auto reload mode +* - Interrupts (Interrupt handler is not provided in this driver. Application +* has to register it's own handler) +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Timer. +* +* XScuTimer_CfgInitialize() API is used to initialize the Timer. The +* user needs to first call the XScuTimer_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuTimer_CfgInitialize() API. +* +* Interrupts +* +* The Timer hardware supports interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuTimer driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The timer is not a part of the snoop control unit as indicated by the +* prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.02a sg  07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 2.3   mus 08/31/20 Updated makefile to support parallel make and
+*                    incremental builds, it would help to reduce compilation
+*                    time.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_H /* prevent circular inclusions */ +#define XSCUTIMER_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscutimer_hw.h" +#include "bspconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +#ifdef XIL_INTERRUPT + u32 IntrId; + UINTPTR IntrParent; /** Bit[0] Interrupt parent type Bit[64/32:1] Parent base address */ +#endif +} XScuTimer_Config; + +/** + * The XScuTimer driver instance data. The user is required to allocate a + * variable of this type for every timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuTimer_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device timer is running */ +} XScuTimer; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Check if the timer has expired. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return +* - TRUE if the timer has expired. +* - FALSE if the timer has not expired. +* +* @note C-style signature: +* int XScuTimer_IsExpired(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_IsExpired(InstancePtr) \ + ((XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) & \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) == \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the timer. This macro will read the timer load register +* and writes the same value to load register to update the counter register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_RestartTimer(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_RestartTimer(InstancePtr) \ + XScuTimer_LoadTimer((InstancePtr), \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET)) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_LoadTimer(XScuTimer *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_LoadTimer(InstancePtr, Value) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. It can be called at any +* time. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterValue(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetCounterValue(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_AUTO_RELOAD_MASK)) + +/****************************************************************************/ +/** +* +* Disable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_AUTO_RELOAD_MASK))) + +/****************************************************************************/ +/** +* +* Enable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_IRQ_ENABLE_MASK)) + +/****************************************************************************/ +/** +* +* Disable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_IRQ_ENABLE_MASK))) + +/*****************************************************************************/ +/** +* +* This function reads the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_GetInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetInterruptStatus(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) + +/*****************************************************************************/ +/** +* +* This function clears the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_ClearInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_ClearInterruptStatus(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET, XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscutimer_sinit.c + */ +XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscutimer_selftest.c + */ +s32 XScuTimer_SelfTest(XScuTimer *InstancePtr); + +/* + * Interface functions in xscutimer.c + */ +s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr, + XScuTimer_Config *ConfigPtr, u32 EffectiveAddress); +void XScuTimer_Start(XScuTimer *InstancePtr); +void XScuTimer_Stop(XScuTimer *InstancePtr); +void XScuTimer_SetPrescaler(XScuTimer *InstancePtr, u8 PrescalerValue); +u8 XScuTimer_GetPrescaler(XScuTimer *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xscutimer_hw.h b/bsp_z7/ps7_cortexa9_0/include/xscutimer_hw.h new file mode 100644 index 0000000..c34acd1 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xscutimer_hw.h @@ -0,0 +1,261 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscutimer_hw.h +* @addtogroup scutimer_v2_4 +* @{ +* +* This file contains the hardware interface to the Timer. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.01a sdm 02/02/12 Added low level macros to read/write load, counter, control
+*		     and interrupt registers
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_HW_H /* prevent circular inclusions */ +#define XSCUTIMER_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XSCUTIMER_LOAD_OFFSET 0x00U /**< Timer Load Register */ +#define XSCUTIMER_COUNTER_OFFSET 0x04U /**< Timer Counter Register */ +#define XSCUTIMER_CONTROL_OFFSET 0x08U /**< Timer Control Register */ +#define XSCUTIMER_ISR_OFFSET 0x0CU /**< Timer Interrupt + Status Register */ +/* @} */ + +/** @name Timer Control register + * This register bits control the prescaler, Intr enable, + * auto-reload and timer enable. + * @{ + */ + +#define XSCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUTIMER_CONTROL_PRESCALER_SHIFT 8U +#define XSCUTIMER_CONTROL_IRQ_ENABLE_MASK 0x00000004U /**< Intr enable */ +#define XSCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload */ +#define XSCUTIMER_CONTROL_ENABLE_MASK 0x00000001U /**< Timer enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Timer counter register has reached zero. + * @{ + */ + +#define XSCUTIMER_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetLoadReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetLoadReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: +* u32 XScuTimer_GetLoadReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetLoadReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_LOAD_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetCounterReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetCounterReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetCounterReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetControlReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetControlReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: + u32 XScuTimer_GetControlReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetControlReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetIntrReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetIntrReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_ISR_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetIntrReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetIntrReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_ISR_OFFSET) + +/****************************************************************************/ +/** +* +* Read from the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuTimer_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuTimer_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuTimer_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xscuwdt.h b/bsp_z7/ps7_cortexa9_0/include/xscuwdt.h new file mode 100644 index 0000000..8d11ff8 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xscuwdt.h @@ -0,0 +1,365 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscuwdt.h +* @addtogroup scuwdt_v2_4 +* @{ +* @details +* +* The Xilinx SCU watchdog timer driver (XScuWdt) supports the Xilinx SCU private +* watchdog timer hardware. +* +* The XScuWdt driver supports the following features: +* - Watchdog mode +* - Timer mode +* - Auto reload (timer mode only) +* +* The watchdog counter register is a down counter and starts decrementing when +* the watchdog is started. +* In watchdog mode, when the counter reaches 0, the Reset flag is set in the +* Reset status register and the WDRESETREQ pin is asserted, causing a system +* reset. The Reset flag is not reset by normal processor reset and is cleared +* when written with a value of 1. This enables the user to differentiate a +* normal reset and a reset caused by watchdog time-out. The user needs to call +* XScuWdt_RestartWdt() periodically, to avoid the watchdog from being timed-out. +* +* The IsWdtExpired function can be used to check if the watchdog was the cause +* of the last reset. In this situation, call Initialize then call IsWdtExpired. +* If the result is true, watchdog timeout caused the last system reset. The +* application then needs to clear the Reset flag. +* +* In timer mode, when the counter reaches 0, the Event flag is set in the +* Interrupt status register and if interrupts are enabled, interrupt ID 30 is +* set as pending in the interrupt distributor. The IsTimerExpired function +* is used to check if the watchdog counter has decremented to 0 in timer mode. +* If auto-reload mode is enabled, the Counter register is automatically reloaded +* from the Load register. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Watchdog Timer. +* +* XScuWdt_CfgInitialize() API is used to initialize the Watchdog Timer. The +* user needs to first call the XScuWdt_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuWdt_CfgInitialize() API. +* +* Interrupts +* +* The SCU Watchdog Timer supports interrupts in Timer mode. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuWdt driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The watchdog timer is not a part of the snoop control unit as indicated +* by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 2.3   mus 08/31/20 Updated makefile to support parallel make and
+*                    incremental builds. It would help to reduce compilaton
+*                    time.
+* 2.3	sne 09/16/20 Fixed MISRA-C violations.
+* 2.4	sne 02/04/21 Fixed Doxygen warnings.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_H /**< prevent circular inclusions */ +#define XSCUWDT_H /**< by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscuwdt_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XScuWdt_Config; + +/** + * The XScuWdt driver instance data. The user is required to allocate a + * variable of this type for every watchdog/timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuWdt_Config Config;/**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device watchdog timer is running */ +} XScuWdt; + +/************************** Variable Definitions *****************************/ +extern XScuWdt_Config XScuWdt_ConfigTable[]; + +/***************** Macros (Inline Functions) Definitions *********************/ +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog has timed-out and the last +* reset was caused by the watchdog reset. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsWdtExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsWdtExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_RST_STS_OFFSET) & \ + XSCUWDT_RST_STS_RESET_FLAG_MASK) == XSCUWDT_RST_STS_RESET_FLAG_MASK) + +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog counter has reached 0 in timer +* mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsTimerExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsTimerExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_ISR_OFFSET) & \ + XSCUWDT_ISR_EVENT_FLAG_MASK) == XSCUWDT_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the watchdog timer. This macro will read the watchdog load register +* and write the same value to load register to update the counter register. +* An application needs to call this function periodically to keep the watchdog +* from asserting the WDRESETREQ reset request output pin. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_RestartWdt(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_RestartWdt(InstancePtr) \ + XScuWdt_LoadWdt((InstancePtr), \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET))) + +/****************************************************************************/ +/** +* +* Write to the watchdog timer load register. This will also update the +* watchdog counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param Value is the value to be written to the Watchdog Load register. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_LoadWdt(XScuWdt *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuWdt_LoadWdt(InstancePtr, Value) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Watchdog mode by setting the WD mode bit of the +* Watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetWdMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetWdMode(InstancePtr) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) | \ + (XSCUWDT_CONTROL_WD_MODE_MASK))) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Timer mode by writing 0x12345678 and 0x87654321 +* successively to the Watchdog Disable Register. +* The software must write 0x12345678 and 0x87654321 successively to the +* Watchdog Disable Register so that the watchdog mode bit in the Watchdog +* Control Register is set to zero. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetTimerMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetTimerMode(InstancePtr) \ +{ \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE1); \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE2); \ +} + +/****************************************************************************/ +/** +* +* Get the contents of the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return Contents of the watchdog control register. +* +* @note C-style signature: + u32 XScuWdt_GetControlReg(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_GetControlReg(InstancePtr) \ + XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param ControlReg is the value to be written to the watchdog control +* register. +* +* @return None. +* +* @note C-style signature: + void XScuWdt_SetControlReg(XScuWdt *InstancePtr, u32 ControlReg) +* +******************************************************************************/ +#define XScuWdt_SetControlReg(InstancePtr, ControlReg) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, (ControlReg)) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_EnableAutoReload(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_EnableAutoReload(InstancePtr) \ + XScuWdt_SetControlReg((InstancePtr), \ + (XScuWdt_GetControlReg(InstancePtr) | \ + XSCUWDT_CONTROL_AUTO_RELOAD_MASK)) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscuwdt_sinit.c. + */ +XScuWdt_Config *XScuWdt_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscuwdt_selftest.c + */ +s32 XScuWdt_SelfTest(XScuWdt *InstancePtr); + +/* + * Interface functions in xscuwdt.c + */ +s32 XScuWdt_CfgInitialize(XScuWdt *InstancePtr, + XScuWdt_Config *ConfigPtr, u32 EffectiveAddress); + +void XScuWdt_Start(XScuWdt *InstancePtr); + +void XScuWdt_Stop(XScuWdt *InstancePtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xscuwdt_hw.h b/bsp_z7/ps7_cortexa9_0/include/xscuwdt_hw.h new file mode 100644 index 0000000..0cdfc1e --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xscuwdt_hw.h @@ -0,0 +1,156 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscuwdt_hw.h +* @addtogroup scuwdt_v2_4 +* @{ +* +* This file contains the hardware interface to the Xilinx SCU private Watch Dog +* Timer (XSCUWDT). +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.01a bss 02/27/12 Updated the register offsets to start at 0x0 instead
+*                    of 0x20 as the base address obtained from the tools
+*		     starts at 0x20.
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_HW_H /**< prevent circular inclusions */ +#define XSCUWDT_HW_H /**< by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device. The WDT registers start at + * an offset 0x20 + * @{ + */ + +#define XSCUWDT_LOAD_OFFSET 0x00U /**< Watchdog Load Register */ +#define XSCUWDT_COUNTER_OFFSET 0x04U /**< Watchdog Counter Register */ +#define XSCUWDT_CONTROL_OFFSET 0x08U /**< Watchdog Control Register */ +#define XSCUWDT_ISR_OFFSET 0x0CU /**< Watchdog Interrupt Status Register */ +#define XSCUWDT_RST_STS_OFFSET 0x10U /**< Watchdog Reset Status Register */ +#define XSCUWDT_DISABLE_OFFSET 0x14U /**< Watchdog Disable Register */ +/* @} */ + +/** @name Watchdog Control register + * This register bits control the prescaler, WD/Timer mode, Intr enable, + * auto-reload, watchdog enable. + * @{ + */ + +#define XSCUWDT_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUWDT_CONTROL_PRESCALER_SHIFT 8U +#define XSCUWDT_CONTROL_WD_MODE_MASK 0x00000008U /**< Watchdog/Timer mode */ +#define XSCUWDT_CONTROL_IT_ENABLE_MASK 0x00000004U /**< Intr enable (in + timer mode) */ +#define XSCUWDT_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload (in + timer mode) */ +#define XSCUWDT_CONTROL_WD_ENABLE_MASK 0x00000001U /**< Watchdog enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Counter register has reached zero in Counter + * mode. + * @{ + */ + +#define XSCUWDT_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/** @name Reset Status register + * This register indicates the Counter register has reached zero in Watchdog + * mode and a reset request is sent. + * @{ + */ + +#define XSCUWDT_RST_STS_RESET_FLAG_MASK 0x00000001U /**< Time out occurred */ +/*@}*/ + +/** @name Disable register + * This register is used to switch from watchdog mode to timer mode. + * The software must write 0x12345678 and 0x87654321 successively to the + * Watchdog Disable Register so that the watchdog mode bit in the Watchdog + * Control Register is set to zero. + * @{ + */ +#define XSCUWDT_DISABLE_VALUE1 0x12345678U /**< Watchdog mode disable + value 1 */ +#define XSCUWDT_DISABLE_VALUE2 0x87654321U /**< Watchdog mode disable + value 2 */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuWdt_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuWdt_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + ((u32)RegOffset)) + +/****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuWdt_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + ((u32)RegOffset), ((u32)Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xsdps.h b/bsp_z7/ps7_cortexa9_0/include/xsdps.h new file mode 100644 index 0000000..77aa9c6 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xsdps.h @@ -0,0 +1,389 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps.h +* @addtogroup sdps Overview +* @{ +* @details +* +* This section explains the implementation of the XSdPs driver. +* See xsdps.h for a detailed description of the device and driver. +* +* This driver is used initialize read from and write to the SD card. +* Features such as switching bus width to 4-bit and switching to high speed, +* changing clock frequency, block size etc. are supported. +* SD 2.0 uses 1/4 bus width and speeds of 25/50KHz. Initialization, however +* is done using 1-bit bus width and 400KHz clock frequency. +* SD commands are classified as broadcast and addressed. Commands can be +* those with response only (using only command line) or +* response + data (using command and data lines). +* Only one command can be sent at a time. During a data transfer however, +* when dsta lines are in use, certain commands (which use only the command +* line) can be sent, most often to obtain status. +* This driver does not support multi card slots at present. +* +* Initialization & Configuration +* +* This includes initialization on the host controller side to select +* clock frequency, bus power and default transfer related parameters. +* The default voltage is 3.3V. +* On the SD card side, the initialization and identification state diagram is +* implemented. This resets the card, gives it a unique address/ID and +* identifies key card related specifications. +* +* Data transfer +* +* The SD card is put in transfer state to read from or write to it. +* The default block size is 512 bytes and if supported, +* default bus width is 4-bit and bus speed is High speed. +* The read and write functions are implemented in polled mode using ADMA2. +* +* At any point, when key parameters such as block size or +* clock/speed or bus width are modified, this driver takes care of +* maintaining the same selection on host and card. +* All error bits in host controller are monitored by the driver and in the +* event one of them is set, driver will clear the interrupt status and +* communicate failure to the upper layer. +* +* File system use +* +* This driver can be used with xilffs library to read and write files to SD. +* (Please refer to procedure in diskio.c). The file system read/write example +* in polled mode can used for reference. +* +* There is no example for using SD driver without file system at present. +* However, the driver can be used without the file system. The glue layer +* in filesystem can be used as reference for the same. The block count +* passed to the read/write function in one call is limited by the ADMA2 +* descriptor table and hence care will have to be taken to call read/write +* API's in a loop for large file sizes. +* +* Interrupt mode is not supported because it offers no improvement when used +* with file system. +* +* eMMC support +* +* SD driver supports SD and eMMC based on the "enable MMC" parameter in SDK. +* The features of eMMC supported by the driver will depend on those supported +* by the host controller. The current driver supports read/write on eMMC card +* using 4-bit and high speed mode currently. +* +* Features not supported include - card write protect, password setting, +* lock/unlock, interrupts, SDMA mode, programmed I/O mode and +* 64-bit addressed ADMA2, erase/pre-erase commands. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 1.00a hk/sg  10/17/13 Initial release
+* 2.0   hk      03/07/14 Version number revised.
+* 2.1   hk     04/18/14 Increase sleep for eMMC switch command.
+*                       Add sleep for microblaze designs. CR# 781117.
+* 2.2   hk     07/28/14 Make changes to enable use of data cache.
+* 2.3   sk     09/23/14 Send command for relative card address
+*                       when re-initialization is done.CR# 819614.
+*						Use XSdPs_Change_ClkFreq API whenever changing
+*						clock.CR# 816586.
+* 2.4	sk	   12/04/14 Added support for micro SD without
+* 						WP/CD. CR# 810655.
+*						Checked for DAT Inhibit mask instead of CMD
+* 						Inhibit mask in Cmd Transfer API.
+*						Added Support for SD Card v1.0
+* 2.5 	sg		07/09/15 Added SD 3.0 features
+*       kvn     07/15/15 Modified the code according to MISRAC-2012.
+* 2.6   sk     10/12/15 Added support for SD card v1.0 CR# 840601.
+* 2.7   sk     11/24/15 Considered the slot type befoe checking CD/WP pins.
+*       sk     12/10/15 Added support for MMC cards.
+*              01/08/16 Added workaround for issue in auto tuning mode
+*                       of SDR50, SDR104 and HS200.
+*       sk     02/16/16 Corrected the Tuning logic.
+*       sk     03/01/16 Removed Bus Width check for eMMC. CR# 938311.
+* 2.8   sk     04/20/16 Added new workaround for auto tuning.
+*              05/03/16 Standard Speed for SD to 19MHz in ZynqMPSoC. CR#951024
+* 3.0   sk     06/09/16 Added support for mkfs to calculate sector count.
+*       sk     07/16/16 Added support for UHS modes.
+*       sk     07/07/16 Used usleep API for both arm and microblaze.
+*       sk     07/16/16 Added Tap delays accordingly to different SD/eMMC
+*                       operating modes.
+*       sk     08/13/16 Removed sleep.h from xsdps.h as a temporary fix for
+*                       CR#956899.
+* 3.1   mi     09/07/16 Removed compilation warnings with extra compiler flags.
+*       sk     10/13/16 Reduced the delay during power cycle to 1ms as per spec
+*       sk     10/19/16 Used emmc_hwreset pin to reset eMMC.
+*       sk     11/07/16 Enable Rst_n bit in ext_csd reg if not enabled.
+*       sk     11/16/16 Issue DLL reset at 31 iteration to load new zero value.
+* 3.2   sk     11/30/16 Modified the voltage switching sequence as per spec.
+*       sk     02/01/17 Added HSD and DDR mode support for eMMC.
+*       sk     02/01/17 Consider bus width parameter from design for switching
+*       vns    02/09/17 Added ARMA53_32 support for ZynqMP CR#968397
+*       sk     03/20/17 Add support for EL1 non-secure mode.
+* 3.3   mn     05/17/17 Add support for 64bit DMA addressing
+* 	mn     08/07/17 Modify driver to support 64-bit DMA in arm64 only
+*       mn     08/17/17 Enabled CCI support for A53 by adding cache coherency
+*                       information.
+*       mn     09/06/17 Resolved compilation errors with IAR toolchain
+* 3.6   mn     08/01/18 Add support for using 64Bit DMA with 32-Bit Processor
+* 3.7   mn     02/01/19 Add support for idling of SDIO
+* 3.8   mn     04/12/19 Modified TapDelay code for supporting ZynqMP and Versal
+*       mn     09/17/19 Modified ADMA handling API for 32bit and 64bit addresses
+* 3.9   mn     03/03/20 Restructured the code for more readability and modularity
+*       mn     03/16/20 Move XSdPs_Select_Card API to User APIs
+* 3.10  mn     06/05/20 Check Transfer completion separately from XSdPs_Read and
+*                       XSdPs_Write APIs
+*       mn     06/05/20 Modified code for SD Non-Blocking Read support
+* 3.11  sk     12/01/20 Tap programming sequence updates like disable OTAPEN
+*                       always, write zero to tap register for zero tap value.
+*       sk     12/07/20 Fix eMMC DDR52 mode write/read issue.
+*       sk     12/17/20 Removed checking platform specific SD macros and used
+*                       Baseaddress instead.
+* 3.12  sk     01/28/21 Added support for non-blocking write.
+*       sk     02/12/21 Fix the issue in reading CID and CSD.
+*       sk     04/08/21 Fixed doxygen warnings in all source files.
+*       sk     05/25/21 Fix the compilation issue in Cortex-A72 + EL1_NS by
+*                       removing the DLL reset logic (Dead code for Versal).
+* 3.13  sk     08/10/21 Limit the SD operating frequency to 19MHz for Versal.
+* 3.14  sk     10/22/21 Add support for Erase feature.
+*       sk     11/29/21 Fix compilation warnings reported with "-Wundef" flag.
+*       sk     01/10/22 Add support to read slot_type parameter.
+* 4.0   sk     02/25/22 Add support for eMMC5.1.
+*       sk     04/07/22 Add support to read custom tap delay values from design
+*                       for SD/eMMC.
+*       sk     06/03/22 Fix issue in internal clock divider calculation logic.
+* 4.1   sk     11/10/22 Add SD/eMMC Tap delay support for Versal Net.
+* 4.1   sa     01/03/23 Report error if Transfer size is greater than 2MB.
+* 4.1	sa     12/19/22 Enable eMMC HS400 mode for Versal Net.
+* 	sa     01/25/23	Use instance structure to store DMA descriptor tables.
+*
+* 
+* +******************************************************************************/ + + +#ifndef SDPS_H_ +#define SDPS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_printf.h" +#include "xil_cache.h" +#include "xstatus.h" +#include "xsdps_hw.h" +#include "xplatform_info.h" +#include "sleep.h" +#include +#if defined (XCLOCKING) +#include "xil_clocking.h" +#endif + +/************************** Constant Definitions *****************************/ + +#define XSDPS_CT_ERROR 0x2L /**< Command timeout flag */ +#define MAX_TUNING_COUNT 40U /**< Maximum Tuning count */ +#define MAX_TIMEOUT 0x1FFFFFFFU /**< Maximum Timeout */ +#define XSDPS_CMD8_VOL_PATTERN 0x1AAU /**< CMD8 voltage pattern */ +#define XSDPS_RESPOCR_READY 0x80000000U /**< Ready response */ +#define XSDPS_ACMD41_HCS 0x40000000U /**< High Capacity Support */ +#define XSDPS_ACMD41_3V3 0x00300000U /**< 3.3 voltage support */ +#define XSDPS_CMD1_HIGH_VOL 0x00FF8000U /**< CMD1 for High voltage */ +#define XSDPS_CMD1_DUAL_VOL 0x00FF8010U /**< CMD1 for Dual voltage */ +#define HIGH_SPEED_SUPPORT 0x2U /**< High Speed support */ +#define UHS_SDR12_SUPPORT 0x1U /**< SDR12 support */ +#define UHS_SDR25_SUPPORT 0x2U /**< SDR25 support */ +#define UHS_SDR50_SUPPORT 0x4U /**< SDR50 support */ +#define UHS_SDR104_SUPPORT 0x8U /**< SDR104 support */ +#define UHS_DDR50_SUPPORT 0x10U /**< DDR50 support */ +#define WIDTH_4_BIT_SUPPORT 0x4U /**< 4-bit width support */ +#define SD_CLK_25_MHZ 25000000U /**< 25MHz clock */ +#define SD_CLK_19_MHZ 19000000U /**< 19MHz clock */ +#define SD_CLK_26_MHZ 26000000U /**< 26MHz clock */ +#define EXT_CSD_DEVICE_TYPE_BYTE 196U /**< CSD Device Type byte number */ +#define EXT_CSD_SEC_COUNT_BYTE1 212U /**< CSD Sector count byte 1 */ +#define EXT_CSD_SEC_COUNT_BYTE2 213U /**< CSD Sector count byte 2 */ +#define EXT_CSD_SEC_COUNT_BYTE3 214U /**< CSD Sector count byte 3 */ +#define EXT_CSD_SEC_COUNT_BYTE4 215U /**< CSD Sector count byte 4 */ +#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED 0x2U /**< CSD Device type HS */ +#define EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED 0x4U /**< CSD Dev type DDR 1.8v speed */ +#define EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED 0x8U /**< CSD Dev type DDR 1.2v speed */ +#define EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 0x10U /**< CSD SDR 1.8v HS200 */ +#define EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200 0x20U /**< CSD SDR 1.2v HS200 */ +#define EXT_CSD_DEVICE_TYPE_DDR_1V8_HS400 0x40U /**< CSD SDR 1.8v HS400 */ +#define EXT_CSD_DEVICE_TYPE_DDR_1V2_HS400 0x80U /**< CSD SDR 1.2v HS400 */ +#define CSD_SPEC_VER_3 0x3U /**< CSD card spec ver 3 */ +#define SCR_SPEC_VER_3 0x80U /**< SCR spec ver 3 */ +#define ADDRESS_BEYOND_32BIT 0x100000000U /**< Macro used for beyond 32-bit addr */ + +#define XSDPS_ZYNQMP_SD0_BASE 0xFF160000U /**< ZynqMP SD0 Baseaddress */ +#define XSDPS_ZYNQMP_SD1_BASE 0xFF170000U /**< ZynqMP SD1 Baseaddress */ +#define XSDPS_VERSAL_SD0_BASE 0xF1040000U /**< Versal SD0 Baseaddress */ +#define XSDPS_VERSAL_SD1_BASE 0xF1050000U /**< Versal SD1 Baseaddress */ + +/** @name Block size mask for 512 bytes + * + * Block size mask for 512 bytes - This is the default block size. + * @{ + */ + +#define XSDPS_BLK_SIZE_512_MASK 0x200U /**< Blk Size 512 */ + +/** @} */ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of the device */ + u32 InputClockHz; /**< Input clock frequency */ + u32 CardDetect; /**< Card Detect */ + u32 WriteProtect; /**< Write Protect */ + u32 BusWidth; /**< Bus Width */ + u32 BankNumber; /**< MIO Bank selection for SD */ + u32 HasEMIO; /**< If SD is connected to EMIO */ + u8 SlotType; /**< Slot type */ + u8 IsCacheCoherent; /**< If SD is Cache Coherent or not */ +#if defined (XCLOCKING) + u32 RefClk; /**< Input clocks */ +#endif + u32 ITapDly_SDR_Clk50; /**< Input Tap delay for HSD/SDR25 modes */ + u32 OTapDly_SDR_Clk50; /**< Output Tap delay for HSD/SDR25 modes */ + u32 ITapDly_DDR_Clk50; /**< Input Tap delay for DDR50 modes */ + u32 OTapDly_DDR_Clk50; /**< Output Tap delay for DDR50 modes */ + u32 OTapDly_SDR_Clk100; /**< Input Tap delay for SDR50 modes */ + u32 OTapDly_SDR_Clk200; /**< Input Tap delay for SDR104/HS200 modes */ +} XSdPs_Config; + +/** + * ADMA2 32-Bit descriptor table + */ +typedef struct { + u16 Attribute; /**< Attributes of descriptor */ + u16 Length; /**< Length of current dma transfer */ + u32 Address; /**< Address of current dma transfer */ +#ifdef __ICCARM__ +#pragma data_alignment = 32 +} XSdPs_Adma2Descriptor32; +#else +} __attribute__((__packed__))XSdPs_Adma2Descriptor32; +#endif + +/** + * ADMA2 64-Bit descriptor table + */ +typedef struct { + u16 Attribute; /**< Attributes of descriptor */ + u16 Length; /**< Length of current dma transfer */ + u64 Address; /**< Address of current dma transfer */ +#ifdef __ICCARM__ +#pragma data_alignment = 32 +} XSdPs_Adma2Descriptor64; +#else +} __attribute__((__packed__))XSdPs_Adma2Descriptor64; +#endif + +/** + * The XSdPs driver instance data. The user is required to allocate a + * variable of this type for every SD device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XSdPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + u32 Host_Caps; /**< Capabilities of host controller */ + u32 Host_CapsExt; /**< Extended Capabilities */ + u32 HCS; /**< High capacity support in card */ + u8 CardType; /**< Type of card - SD/MMC/eMMC */ + u8 Card_Version; /**< Card version */ + u8 HC_Version; /**< Host controller version */ + u8 BusWidth; /**< Current operating bus width */ + u32 BusSpeed; /**< Current operating bus speed */ + u8 Switch1v8; /**< 1.8V Switch support */ + u32 CardID[4]; /**< Card ID Register */ + u32 RelCardAddr; /**< Relative Card Address */ + u32 CardSpecData[4]; /**< Card Specific Data Register */ + u32 SectorCount; /**< Sector Count */ + u32 SdCardConfig; /**< Sd Card Configuration Register */ + u32 Mode; /**< Bus Speed Mode */ + u32 OTapDelay; /**< Output Tap Delay */ + u32 ITapDelay; /**< Input Tap Delay */ + u64 Dma64BitAddr; /**< 64 Bit DMA Address */ + u16 TransferMode; /**< Transfer Mode */ + u32 SlcrBaseAddr; /**< SLCR base address*/ + u8 IsBusy; /**< Busy Flag*/ + u32 BlkSize; /**< Block Size*/ + u8 IsTuningDone; /**< Flag to indicate HS200 tuning complete */ +#ifdef __ICCARM__ +#pragma data_alignment = 32 + XSdPs_Adma2Descriptor32 Adma2_DescrTbl32[32]; + XSdPs_Adma2Descriptor64 Adma2_DescrTbl64[32]; +#else + XSdPs_Adma2Descriptor32 Adma2_DescrTbl32[32] __attribute__ ((aligned(32))); + XSdPs_Adma2Descriptor64 Adma2_DescrTbl64[32] __attribute__ ((aligned(32))); +#endif +} XSdPs; + +/***************** Macros (Inline Functions) Definitions *********************/ +/** + * @name SD High Speed mode configuration options + * @{ + */ +/** + * User configuration option to enable or disable SD HS mode. + * By default SD HS mode is disabled for Versal and enabled for + * other platforms. + */ +#ifdef versal +#define SD_HS_MODE_ENABLE 0 +#else +#define SD_HS_MODE_ENABLE 1 +#endif +/** @} */ + +/** + * Enable eMMC HS400 mode for Versal Net platform + */ +#define ENABLE_HS400_MODE + +/************************** Function Prototypes ******************************/ +XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId); +s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr, + u32 EffectiveAddr); +s32 XSdPs_CardInitialize(XSdPs *InstancePtr); +s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff); +s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff); +s32 XSdPs_Idle(XSdPs *InstancePtr); + +s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr); +s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq); +s32 XSdPs_Pullup(XSdPs *InstancePtr); +s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff); +s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr); +s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff); +s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff); +s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg); +s32 XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize); +s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg); +s32 XSdPs_Select_Card(XSdPs *InstancePtr); +s32 XSdPs_StartReadTransfer(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff); +s32 XSdPs_CheckReadTransfer(XSdPs *InstancePtr); +s32 XSdPs_StartWriteTransfer(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff); +s32 XSdPs_CheckWriteTransfer(XSdPs *InstancePtr); +s32 XSdPs_Erase(XSdPs *InstancePtr, u32 StartAddr, u32 EndAddr); + +#ifdef __cplusplus +} +#endif + +#endif /* SD_H_ */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xsdps_core.h b/bsp_z7/ps7_cortexa9_0/include/xsdps_core.h new file mode 100644 index 0000000..239c2f1 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xsdps_core.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps_core.h +* @addtogroup sdps Overview +* @{ +* +* The xsdps_core.h header file contains the identifiers and basic HW access driver +* functions (or macros) that can be used to access the device. Other driver +* functions are defined in xsdps.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 3.9   mn     03/03/20 Restructured the code for more readability and modularity
+*       mn     03/16/20 Move XSdPs_Select_Card API to User APIs
+* 3.12  sk     01/28/21 Added support for non-blocking write.
+* 3.14  sk     10/22/21 Add support for Erase feature.
+*       mn     11/28/21 Fix MISRA-C violations.
+* 4.0   sk     02/25/22 Add support for eMMC5.1.
+* 4.1   sa     01/06/23 Include xil_util.h in this file.
+* 
+* +******************************************************************************/ + +/** @cond INTERNAL */ +#ifndef SDPS_INCLUDE_H_ +#define SDPS_INCLUDE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xsdps.h" +#if defined (__aarch64__) +#include "xil_smc.h" +#endif + +#include "xil_util.h" + +s32 XSdPs_SdCardInitialize(XSdPs *InstancePtr); +s32 XSdPs_MmcCardInitialize(XSdPs *InstancePtr); +s32 XSdPs_IdentifyCard(XSdPs *InstancePtr); +s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt); +s32 XSdPs_SetupTransfer(XSdPs *InstancePtr); +s32 XSdPs_Read(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff); +s32 XSdPs_Write(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff); +s32 XSdPs_CheckTransferComplete(XSdPs *InstancePtr); +void XSdPs_Identify_UhsMode(XSdPs *InstancePtr, u8 *ReadBuff); +s32 XSdPs_DllReset(XSdPs *InstancePtr); +s32 XSdPs_Switch_Voltage(XSdPs *InstancePtr); +void XSdPs_SetupADMA2DescTbl64Bit(XSdPs *InstancePtr, u32 BlkCnt); +void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff); +void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst); +void XSdPs_ConfigTapDelay(XSdPs *InstancePtr); +s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr); +void XSdPs_Setup32ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff); +void XSdPs_Setup64ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff); +u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd); +void XSdPs_SetTapDelay(XSdPs *InstancePtr); +s32 XSdPs_CheckResetDone(XSdPs *InstancePtr, u8 Value); +s32 XSdPs_CheckVoltage18(XSdPs *InstancePtr); +s32 XSdPs_SetupCmd(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt); +void XSdPs_SetExecTuning(XSdPs *InstancePtr); +s32 XSdPs_CheckCardDetect(XSdPs *InstancePtr); +s32 XSdPs_CardReset(XSdPs *InstancePtr); +s32 XSdPs_CardIfCond(XSdPs *InstancePtr); +s32 XSdPs_CardOpCond(XSdPs *InstancePtr); +s32 XSdPs_GetCardId(XSdPs *InstancePtr); +s32 XSdPs_GetCsd(XSdPs *InstancePtr); +s32 XSdPs_CardSetVoltage18(XSdPs *InstancePtr); +s32 XSdPs_SdModeInit(XSdPs *InstancePtr); +s32 XSdPs_SdCardEnum(XSdPs *InstancePtr); +s32 XSdPs_MmcCardEnum(XSdPs *InstancePtr); +s32 XSdPs_MmcModeInit(XSdPs *InstancePtr); +s32 XSdPs_EmmcModeInit(XSdPs *InstancePtr); +s32 XSdPs_ResetConfig(XSdPs *InstancePtr); +void XSdPs_HostConfig(XSdPs *InstancePtr); +s32 XSdPs_Reset(XSdPs *InstancePtr, u8 Value); +void XSdPs_DisableBusPower(XSdPs *InstancePtr); +void XSdPs_EnableBusPower(XSdPs *InstancePtr); +s32 XSdPs_CheckBusIdle(XSdPs *InstancePtr, u32 Value); +s32 XSdPs_CheckBusHigh(XSdPs *InstancePtr); +s32 XSdPs_SetupVoltageSwitch(XSdPs *InstancePtr); +s32 XSdPs_AutoTuning(XSdPs *InstancePtr); +s32 XSdPs_SetClock(XSdPs *InstancePtr, u32 SelFreq); +u32 XSdPs_CalcClock(XSdPs *InstancePtr, u32 SelFreq); +s32 XSdPs_EnableClock(XSdPs *InstancePtr, u16 ClockReg); +s32 XSdps_CheckTransferDone(XSdPs *InstancePtr); +s32 XSdPs_Change_SdBusSpeed(XSdPs *InstancePtr); +s32 XSdPs_Change_MmcBusSpeed(XSdPs *InstancePtr); +s32 XSdPs_CalcBusSpeed(XSdPs *InstancePtr, u32 *Arg); +void XSdPs_SetupReadDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, u8 *Buff); +void XSdPs_SetupWriteDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, const u8 *Buff); +s32 XSdPs_SetVoltage18(XSdPs *InstancePtr); +s32 XSdPs_SendCmd(XSdPs *InstancePtr, u32 Cmd); +void XSdPs_IdentifyEmmcMode(XSdPs *InstancePtr, const u8 *ExtCsd); +s32 XSdPs_CheckEmmcTiming(XSdPs *InstancePtr, u8 *ExtCsd); +void XSdPs_ConfigPower(XSdPs *InstancePtr); +void XSdPs_ConfigDma(XSdPs *InstancePtr); +void XSdPs_ConfigInterrupt(XSdPs *InstancePtr); +s32 XSdPs_SendErase(XSdPs *InstancePtr); +s32 XSdPs_SetEndAddr(XSdPs *InstancePtr, u32 EndAddr); +s32 XSdPs_SetStartAddr(XSdPs *InstancePtr, u32 StartAddr); +#ifdef VERSAL_NET +u32 XSdPs_Select_HS400(XSdPs *InstancePtr); +#endif + +#if defined (__aarch64__) && (EL1_NONSECURE == 1) +void XSdps_Smc(XSdPs *InstancePtr, u32 RegOffset, u32 Mask, u32 Val); +#endif + +#ifdef __cplusplus +} +#endif + +#endif +/** @endcond */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xsdps_hw.h b/bsp_z7/ps7_cortexa9_0/include/xsdps_hw.h new file mode 100644 index 0000000..7ee7774 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xsdps_hw.h @@ -0,0 +1,1507 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps_hw.h +* @addtogroup sdps Overview +* @{{ +* +* The xsdps_hw.h header file contains the identifiers and basic HW access driver +* functions (or macros) that can be used to access the device. Other driver +* functions are defined in xsdps.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 1.00a hk/sg  10/17/13 Initial release
+* 2.5 	sg	   07/09/15 Added SD 3.0 features
+*       kvn    07/15/15 Modified the code according to MISRAC-2012.
+* 2.7   sk     12/10/15 Added support for MMC cards.
+*       sk     03/02/16 Configured the Tap Delay values for eMMC HS200 mode.
+* 2.8   sk     04/20/16 Added new workaround for auto tuning.
+* 3.0   sk     06/09/16 Added support for mkfs to calculate sector count.
+*       sk     07/16/16 Added support for UHS modes.
+*       sk     07/16/16 Added Tap delays accordingly to different SD/eMMC
+*                       operating modes.
+* 3.1   sk     11/07/16 Enable Rst_n bit in ext_csd reg if not enabled.
+* 3.2   sk     03/20/17 Add support for EL1 non-secure mode.
+* 3.3   mn     08/22/17 Updated for Word Access System support
+*       mn     09/06/17 Added support for ARMCC toolchain
+* 3.4   mn     01/22/18 Separated out SDR104 and HS200 clock defines
+* 3.6   mn     07/06/18 Fix Doxygen warnings for sdps driver
+* 3.8   mn     04/12/19 Modified TapDelay code for supporting ZynqMP and Versal
+*       mn     05/21/19 Set correct tap delays for Versal
+*       mn     05/21/19 Disable DLL Reset code for Versal
+*       mn     07/03/19 Update Input Tap Delays for Versal
+* 3.9   mn     03/03/20 Restructured the code for more readability and modularity
+* 3.14  mn     11/28/21 Fix MISRA-C violations.
+* 4.0   sk     02/25/22 Add support for eMMC5.1.
+*       sk     04/07/22 Fix typo in 'XSDPS_MMC_1_BIT_BUS_ARG' macro definition.
+* 4.1   sk     11/10/22 Add SD/eMMC Tap delay support for Versal Net.
+*
+* 
+* +******************************************************************************/ + +/** @cond INTERNAL */ +#ifndef SD_HW_H_ +#define SD_HW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets from the base address of an SD device. + * @{ + */ + +#define XSDPS_SDMA_SYS_ADDR_OFFSET 0x00U /**< SDMA System Address + Register */ +#define XSDPS_SDMA_SYS_ADDR_LO_OFFSET XSDPS_SDMA_SYS_ADDR_OFFSET + /**< SDMA System Address + Low Register */ +#define XSDPS_ARGMT2_LO_OFFSET 0x00U /**< Argument2 Low Register */ +#define XSDPS_SDMA_SYS_ADDR_HI_OFFSET 0x02U /**< SDMA System Address + High Register */ +#define XSDPS_ARGMT2_HI_OFFSET 0x02U /**< Argument2 High Register */ + +#define XSDPS_BLK_SIZE_OFFSET 0x04U /**< Block Size Register */ +#define XSDPS_BLK_CNT_OFFSET 0x06U /**< Block Count Register */ +#define XSDPS_ARGMT_OFFSET 0x08U /**< Argument Register */ +#define XSDPS_ARGMT1_LO_OFFSET XSDPS_ARGMT_OFFSET + /**< Argument1 Register */ +#define XSDPS_ARGMT1_HI_OFFSET 0x0AU /**< Argument1 Register */ + +#define XSDPS_XFER_MODE_OFFSET 0x0CU /**< Transfer Mode Register */ +#define XSDPS_CMD_OFFSET 0x0EU /**< Command Register */ +#define XSDPS_RESP0_OFFSET 0x10U /**< Response0 Register */ +#define XSDPS_RESP1_OFFSET 0x14U /**< Response1 Register */ +#define XSDPS_RESP2_OFFSET 0x18U /**< Response2 Register */ +#define XSDPS_RESP3_OFFSET 0x1CU /**< Response3 Register */ +#define XSDPS_BUF_DAT_PORT_OFFSET 0x20U /**< Buffer Data Port */ +#define XSDPS_PRES_STATE_OFFSET 0x24U /**< Present State */ +#define XSDPS_HOST_CTRL1_OFFSET 0x28U /**< Host Control 1 */ +#define XSDPS_POWER_CTRL_OFFSET 0x29U /**< Power Control */ +#define XSDPS_BLK_GAP_CTRL_OFFSET 0x2AU /**< Block Gap Control */ +#define XSDPS_WAKE_UP_CTRL_OFFSET 0x2BU /**< Wake Up Control */ +#define XSDPS_CLK_CTRL_OFFSET 0x2CU /**< Clock Control */ +#define XSDPS_TIMEOUT_CTRL_OFFSET 0x2EU /**< Timeout Control */ +#define XSDPS_SW_RST_OFFSET 0x2FU /**< Software Reset */ +#define XSDPS_NORM_INTR_STS_OFFSET 0x30U /**< Normal Interrupt + Status Register */ +#define XSDPS_ERR_INTR_STS_OFFSET 0x32U /**< Error Interrupt + Status Register */ +#define XSDPS_NORM_INTR_STS_EN_OFFSET 0x34U /**< Normal Interrupt + Status Enable Register */ +#define XSDPS_ERR_INTR_STS_EN_OFFSET 0x36U /**< Error Interrupt + Status Enable Register */ +#define XSDPS_NORM_INTR_SIG_EN_OFFSET 0x38U /**< Normal Interrupt + Signal Enable Register */ +#define XSDPS_ERR_INTR_SIG_EN_OFFSET 0x3AU /**< Error Interrupt + Signal Enable Register */ + +#define XSDPS_AUTO_CMD12_ERR_STS_OFFSET 0x3CU /**< Auto CMD12 Error Status + Register */ +#define XSDPS_HOST_CTRL2_OFFSET 0x3EU /**< Host Control2 Register */ +#define XSDPS_CAPS_OFFSET 0x40U /**< Capabilities Register */ +#define XSDPS_CAPS_EXT_OFFSET 0x44U /**< Capabilities Extended */ +#define XSDPS_MAX_CURR_CAPS_OFFSET 0x48U /**< Maximum Current + Capabilities Register */ +#define XSDPS_MAX_CURR_CAPS_EXT_OFFSET 0x4CU /**< Maximum Current + Capabilities Ext Register */ +#define XSDPS_FE_ERR_INT_STS_OFFSET 0x52U /**< Force Event for + Error Interrupt Status */ +#define XSDPS_FE_AUTO_CMD12_EIS_OFFSET 0x50U /**< Auto CM12 Error Interrupt + Status Register */ +#define XSDPS_ADMA_ERR_STS_OFFSET 0x54U /**< ADMA Error Status + Register */ +#define XSDPS_ADMA_SAR_OFFSET 0x58U /**< ADMA System Address + Register */ +#define XSDPS_ADMA_SAR_EXT_OFFSET 0x5CU /**< ADMA System Address + Extended Register */ +#define XSDPS_PRE_VAL_1_OFFSET 0x60U /**< Preset Value Register */ +#define XSDPS_PRE_VAL_2_OFFSET 0x64U /**< Preset Value Register */ +#define XSDPS_PRE_VAL_3_OFFSET 0x68U /**< Preset Value Register */ +#define XSDPS_PRE_VAL_4_OFFSET 0x6CU /**< Preset Value Register */ +#define XSDPS_BOOT_TOUT_CTRL_OFFSET 0x70U /**< Boot timeout control + register */ + +#define XSDPS_SHARED_BUS_CTRL_OFFSET 0xE0U /**< Shared Bus Control + Register */ +#define XSDPS_SLOT_INTR_STS_OFFSET 0xFCU /**< Slot Interrupt Status + Register */ +#define XSDPS_HOST_CTRL_VER_OFFSET 0xFEU /**< Host Controller Version + Register */ +#ifdef VERSAL_NET +#define XSDPS_PHYCTRLREG1_OFFSET 0x270U /**< PHY Control register2 */ +#define XSDPS_PHYCTRLREG2_OFFSET 0x274U /**< PHY Control register2 */ +#endif + +/** @} */ + +/** @name Control Register - Host control, Power control, + * Block Gap control and Wakeup control + * + * This register contains bits for various configuration options of + * the SD host controller. Read/Write apart from the reserved bits. + * @{ + */ + +#define XSDPS_HC_LED_MASK 0x00000001U /**< LED Control */ +#define XSDPS_HC_WIDTH_MASK 0x00000002U /**< Bus width */ +#define XSDPS_HC_BUS_WIDTH_4 0x00000002U +#define XSDPS_HC_SPEED_MASK 0x00000004U /**< High Speed */ +#define XSDPS_HC_DMA_MASK 0x00000018U /**< DMA Mode Select */ +#define XSDPS_HC_DMA_SDMA_MASK 0x00000000U /**< SDMA Mode */ +#define XSDPS_HC_DMA_ADMA1_MASK 0x00000008U /**< ADMA1 Mode */ +#define XSDPS_HC_DMA_ADMA2_32_MASK 0x00000010U /**< ADMA2 Mode - 32 bit */ +#define XSDPS_HC_DMA_ADMA2_64_MASK 0x00000018U /**< ADMA2 Mode - 64 bit */ +#define XSDPS_HC_EXT_BUS_WIDTH 0x00000020U /**< Bus width - 8 bit */ +#define XSDPS_HC_CARD_DET_TL_MASK 0x00000040U /**< Card Detect Tst Lvl */ +#define XSDPS_HC_CARD_DET_SD_MASK 0x00000080U /**< Card Detect Sig Det */ + +#define XSDPS_PC_BUS_PWR_MASK 0x00000001U /**< Bus Power Control */ +#define XSDPS_PC_BUS_VSEL_MASK 0x0000000EU /**< Bus Voltage Select */ +#define XSDPS_PC_BUS_VSEL_3V3_MASK 0x0000000EU /**< Bus Voltage 3.3V */ +#define XSDPS_PC_BUS_VSEL_3V0_MASK 0x0000000CU /**< Bus Voltage 3.0V */ +#define XSDPS_PC_BUS_VSEL_1V8_MASK 0x0000000AU /**< Bus Voltage 1.8V */ +#define XSDPS_PC_EMMC_HW_RST_MASK 0x00000010U /**< HW reset for eMMC */ + +#define XSDPS_BGC_STP_REQ_MASK 0x00000001U /**< Block Gap Stop Req */ +#define XSDPS_BGC_CNT_REQ_MASK 0x00000002U /**< Block Gap Cont Req */ +#define XSDPS_BGC_RWC_MASK 0x00000004U /**< Block Gap Rd Wait */ +#define XSDPS_BGC_INTR_MASK 0x00000008U /**< Block Gap Intr */ +#define XSDPS_BGC_SPI_MODE_MASK 0x00000010U /**< Block Gap SPI Mode */ +#define XSDPS_BGC_BOOT_EN_MASK 0x00000020U /**< Block Gap Boot Enb */ +#define XSDPS_BGC_ALT_BOOT_EN_MASK 0x00000040U /**< Block Gap Alt BootEn */ +#define XSDPS_BGC_BOOT_ACK_MASK 0x00000080U /**< Block Gap Boot Ack */ + +#define XSDPS_WC_WUP_ON_INTR_MASK 0x00000001U /**< Wakeup Card Intr */ +#define XSDPS_WC_WUP_ON_INSRT_MASK 0x00000002U /**< Wakeup Card Insert */ +#define XSDPS_WC_WUP_ON_REM_MASK 0x00000004U /**< Wakeup Card Removal */ + +/** @} */ + +/** @name Control Register - Clock control, Timeout control & Software reset + * + * This register contains bits for configuration options of clock, timeout and + * software reset. + * Read/Write except for Inter_Clock_Stable bit (read only) and reserved bits. + * @{ + */ + +#define XSDPS_CC_INT_CLK_EN_MASK 0x00000001U /**< INT clk enable */ +#define XSDPS_CC_INT_CLK_STABLE_MASK 0x00000002U /**< INT clk stable */ +#define XSDPS_CC_SD_CLK_EN_MASK 0x00000004U /**< SD clk enable */ +#define XSDPS_CC_SD_CLK_GEN_SEL_MASK 0x00000020U /**< SD clk gen selection */ +#define XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK 0x00000003U /**< SD clk freq sel upper */ +#define XSDPS_CC_SDCLK_FREQ_SEL_MASK 0x000000FFU /**< SD clk freq sel */ +#define XSDPS_CC_SDCLK_FREQ_D256_MASK 0x00008000U /**< Divider 256 */ +#define XSDPS_CC_SDCLK_FREQ_D128_MASK 0x00004000U /**< Divider 128 */ +#define XSDPS_CC_SDCLK_FREQ_D64_MASK 0x00002000U /**< Divider 64 */ +#define XSDPS_CC_SDCLK_FREQ_D32_MASK 0x00001000U /**< Divider 32 */ +#define XSDPS_CC_SDCLK_FREQ_D16_MASK 0x00000800U /**< Divider 16 */ +#define XSDPS_CC_SDCLK_FREQ_D8_MASK 0x00000400U /**< Divider 8 */ +#define XSDPS_CC_SDCLK_FREQ_D4_MASK 0x00000200U /**< Divider 4 */ +#define XSDPS_CC_SDCLK_FREQ_D2_MASK 0x00000100U /**< Divider 2 */ +#define XSDPS_CC_SDCLK_FREQ_BASE_MASK 0x00000000U /**< Base clock */ +#define XSDPS_CC_MAX_DIV_CNT 256U /**< Max divider count */ +#define XSDPS_CC_EXT_MAX_DIV_CNT 2046U /**< Max extended divider count */ +#define XSDPS_CC_EXT_DIV_SHIFT 6U /**< Ext divider shift */ + +#define XSDPS_TC_CNTR_VAL_MASK 0x0000000FU /**< Data timeout counter */ + +#define XSDPS_SWRST_ALL_MASK 0x00000001U /**< Software Reset All */ +#define XSDPS_SWRST_CMD_LINE_MASK 0x00000002U /**< Software reset for CMD line */ +#define XSDPS_SWRST_DAT_LINE_MASK 0x00000004U /**< Software reset for DAT line */ + +#define XSDPS_CC_MAX_NUM_OF_DIV 9U /**< Max number of Clock dividers */ +#define XSDPS_CC_DIV_SHIFT 8U /**< Clock Divider shift */ + +/** @} */ + +/** @name SD Interrupt Registers + * + * Normal and Error Interrupt Status Register + * This register shows the normal and error interrupt status. + * Status enable register affects reads of this register. + * If Signal enable register is set and the corresponding status bit is set, + * interrupt is generated. + * Write to clear except + * Error_interrupt and Card_Interrupt bits - Read only + * + * Normal and Error Interrupt Status Enable Register + * Setting this register bits enables Interrupt status. + * Read/Write except Fixed_to_0 bit (Read only) + * + * Normal and Error Interrupt Signal Enable Register + * This register is used to select which interrupt status is + * indicated to the Host System as the interrupt. + * Read/Write except Fixed_to_0 bit (Read only) + * + * All three registers have same bit definitions + * @{ + */ + +#define XSDPS_INTR_CC_MASK 0x00000001U /**< Command Complete */ +#define XSDPS_INTR_TC_MASK 0x00000002U /**< Transfer Complete */ +#define XSDPS_INTR_BGE_MASK 0x00000004U /**< Block Gap Event */ +#define XSDPS_INTR_DMA_MASK 0x00000008U /**< DMA Interrupt */ +#define XSDPS_INTR_BWR_MASK 0x00000010U /**< Buffer Write Ready */ +#define XSDPS_INTR_BRR_MASK 0x00000020U /**< Buffer Read Ready */ +#define XSDPS_INTR_CARD_INSRT_MASK 0x00000040U /**< Card Insert */ +#define XSDPS_INTR_CARD_REM_MASK 0x00000080U /**< Card Remove */ +#define XSDPS_INTR_CARD_MASK 0x00000100U /**< Card Interrupt */ +#define XSDPS_INTR_INT_A_MASK 0x00000200U /**< INT A Interrupt */ +#define XSDPS_INTR_INT_B_MASK 0x00000400U /**< INT B Interrupt */ +#define XSDPS_INTR_INT_C_MASK 0x00000800U /**< INT C Interrupt */ +#define XSDPS_INTR_RE_TUNING_MASK 0x00001000U /**< Re-Tuning Interrupt */ +#define XSDPS_INTR_BOOT_ACK_RECV_MASK 0x00002000U /**< Boot Ack Recv + Interrupt */ +#define XSDPS_INTR_BOOT_TERM_MASK 0x00004000U /**< Boot Terminate + Interrupt */ +#define XSDPS_INTR_ERR_MASK 0x00008000U /**< Error Interrupt */ +#define XSDPS_NORM_INTR_ALL_MASK 0x0000FFFFU + +#define XSDPS_INTR_ERR_CT_MASK 0x00000001U /**< Command Timeout + Error */ +#define XSDPS_INTR_ERR_CCRC_MASK 0x00000002U /**< Command CRC Error */ +#define XSDPS_INTR_ERR_CEB_MASK 0x00000004U /**< Command End Bit + Error */ +#define XSDPS_INTR_ERR_CI_MASK 0x00000008U /**< Command Index Error */ +#define XSDPS_INTR_ERR_DT_MASK 0x00000010U /**< Data Timeout Error */ +#define XSDPS_INTR_ERR_DCRC_MASK 0x00000020U /**< Data CRC Error */ +#define XSDPS_INTR_ERR_DEB_MASK 0x00000040U /**< Data End Bit Error */ +#define XSDPS_INTR_ERR_CUR_LMT_MASK 0x00000080U /**< Current Limit Error */ +#define XSDPS_INTR_ERR_AUTO_CMD12_MASK 0x00000100U /**< Auto CMD12 Error */ +#define XSDPS_INTR_ERR_ADMA_MASK 0x00000200U /**< ADMA Error */ +#define XSDPS_INTR_ERR_TR_MASK 0x00001000U /**< Tuning Error */ +#define XSDPS_INTR_VEND_SPF_ERR_MASK 0x0000E000U /**< Vendor Specific + Error */ +#define XSDPS_ERROR_INTR_ALL_MASK 0x0000F3FFU /**< Mask for error bits */ +/** @} */ + +/** @name Block Size and Block Count Register + * + * This register contains the block count for current transfer, + * block size and SDMA buffer size. + * Read/Write except for reserved bits. + * @{ + */ + +#define XSDPS_BLK_SIZE_MASK 0x00000FFFU /**< Transfer Block Size */ +#define XSDPS_SDMA_BUFF_SIZE_MASK 0x00007000U /**< Host SDMA Buffer Size */ +#define XSDPS_BLK_SIZE_1024 0x400U +#define XSDPS_BLK_SIZE_2048 0x800U +#define XSDPS_BLK_CNT_MASK 0x0000FFFFU /**< Block Count for + Current Transfer */ + +/** @} */ + +/** @name Transfer Mode and Command Register + * + * The Transfer Mode register is used to control the data transfers and + * Command register is used for command generation + * Read/Write except for reserved bits. + * @{ + */ + +#define XSDPS_TM_DMA_EN_MASK 0x00000001U /**< DMA Enable */ +#define XSDPS_TM_BLK_CNT_EN_MASK 0x00000002U /**< Block Count Enable */ +#define XSDPS_TM_AUTO_CMD12_EN_MASK 0x00000004U /**< Auto CMD12 Enable */ +#define XSDPS_TM_DAT_DIR_SEL_MASK 0x00000010U /**< Data Transfer + Direction Select */ +#define XSDPS_TM_MUL_SIN_BLK_SEL_MASK 0x00000020U /**< Multi/Single + Block Select */ + +#define XSDPS_CMD_RESP_SEL_MASK 0x00000003U /**< Response Type + Select */ +#define XSDPS_CMD_RESP_NONE_MASK 0x00000000U /**< No Response */ +#define XSDPS_CMD_RESP_L136_MASK 0x00000001U /**< Response length 138 */ +#define XSDPS_CMD_RESP_L48_MASK 0x00000002U /**< Response length 48 */ +#define XSDPS_CMD_RESP_L48_BSY_CHK_MASK 0x00000003U /**< Response length 48 & + check busy after + response */ +#define XSDPS_CMD_CRC_CHK_EN_MASK 0x00000008U /**< Command CRC Check + Enable */ +#define XSDPS_CMD_INX_CHK_EN_MASK 0x00000010U /**< Command Index Check + Enable */ +#define XSDPS_DAT_PRESENT_SEL_MASK 0x00000020U /**< Data Present Select */ +#define XSDPS_CMD_TYPE_MASK 0x000000C0U /**< Command Type */ +#define XSDPS_CMD_TYPE_NORM_MASK 0x00000000U /**< CMD Type - Normal */ +#define XSDPS_CMD_TYPE_SUSPEND_MASK 0x00000040U /**< CMD Type - Suspend */ +#define XSDPS_CMD_TYPE_RESUME_MASK 0x00000080U /**< CMD Type - Resume */ +#define XSDPS_CMD_TYPE_ABORT_MASK 0x000000C0U /**< CMD Type - Abort */ +#define XSDPS_CMD_MASK 0x00003F00U /**< Command Index Mask - + Set to CMD0-63, + AMCD0-63 */ + +/** @} */ + +/** @name Auto CMD Error Status Register + * + * This register is read only register which contains + * information about the error status of Auto CMD 12 and 23. + * Read Only + * @{ + */ +#define XSDPS_AUTO_CMD12_NT_EX_MASK 0x0001U /**< Auto CMD12 Not + executed */ +#define XSDPS_AUTO_CMD_TOUT_MASK 0x0002U /**< Auto CMD Timeout + Error */ +#define XSDPS_AUTO_CMD_CRC_MASK 0x0004U /**< Auto CMD CRC Error */ +#define XSDPS_AUTO_CMD_EB_MASK 0x0008U /**< Auto CMD End Bit + Error */ +#define XSDPS_AUTO_CMD_IND_MASK 0x0010U /**< Auto CMD Index Error */ +#define XSDPS_AUTO_CMD_CNI_ERR_MASK 0x0080U /**< Command not issued by + Auto CMD12 Error */ +/** @} */ + +/** @name Host Control2 Register + * + * This register contains extended configuration bits. + * Read Write + * @{ + */ +#define XSDPS_HC2_UHS_MODE_MASK 0x0007U /**< UHS Mode select bits */ +#define XSDPS_HC2_UHS_MODE_SDR12_MASK 0x0000U /**< SDR12 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_SDR25_MASK 0x0001U /**< SDR25 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_SDR50_MASK 0x0002U /**< SDR50 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_SDR104_MASK 0x0003U /**< SDR104 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_DDR50_MASK 0x0004U /**< DDR50 UHS Mode */ +#define XSDPS_HC2_HS400_MASK 0x0005U /**< HS400 Mode */ +#define XSDPS_HC2_1V8_EN_MASK 0x0008U /**< 1.8V Signal Enable */ +#define XSDPS_HC2_DRV_STR_SEL_MASK 0x0030U /**< Driver Strength + Selection */ +#define XSDPS_HC2_DRV_STR_B_MASK 0x0000U /**< Driver Strength B */ +#define XSDPS_HC2_DRV_STR_A_MASK 0x0010U /**< Driver Strength A */ +#define XSDPS_HC2_DRV_STR_C_MASK 0x0020U /**< Driver Strength C */ +#define XSDPS_HC2_DRV_STR_D_MASK 0x0030U /**< Driver Strength D */ +#define XSDPS_HC2_EXEC_TNG_MASK 0x0040U /**< Execute Tuning */ +#define XSDPS_HC2_SAMP_CLK_SEL_MASK 0x0080U /**< Sampling Clock + Selection */ +#define XSDPS_HC2_ASYNC_INTR_EN_MASK 0x4000U /**< Asynchronous Interrupt + Enable */ +#define XSDPS_HC2_PRE_VAL_EN_MASK 0x8000U /**< Preset Value Enable */ + +/** @} */ + +/** @name Capabilities Register + * + * Capabilities register is a read only register which contains + * information about the host controller. + * Sufficient if read once after power on. + * Read Only + * @{ + */ +#define XSDPS_CAP_TOUT_CLK_FREQ_MASK 0x0000003FU /**< Timeout clock freq + select */ +#define XSDPS_CAP_TOUT_CLK_UNIT_MASK 0x00000080U /**< Timeout clock unit - + MHz/KHz */ +#define XSDPS_CAP_MAX_BLK_LEN_MASK 0x00030000U /**< Max block length */ +#define XSDPS_CAP_MAX_BLK_LEN_512B_MASK 0x00000000U /**< Max block 512 bytes */ +#define XSDPS_CAP_MAX_BL_LN_1024_MASK 0x00010000U /**< Max block 1024 bytes */ +#define XSDPS_CAP_MAX_BL_LN_2048_MASK 0x00020000U /**< Max block 2048 bytes */ +#define XSDPS_CAP_MAX_BL_LN_4096_MASK 0x00030000U /**< Max block 4096 bytes */ + +#define XSDPS_CAP_EXT_MEDIA_BUS_MASK 0x00040000U /**< Extended media bus */ +#define XSDPS_CAP_ADMA2_MASK 0x00080000U /**< ADMA2 support */ +#define XSDPS_CAP_HIGH_SPEED_MASK 0x00200000U /**< High speed support */ +#define XSDPS_CAP_SDMA_MASK 0x00400000U /**< SDMA support */ +#define XSDPS_CAP_SUSP_RESUME_MASK 0x00800000U /**< Suspend/Resume + support */ +#define XSDPS_CAP_VOLT_3V3_MASK 0x01000000U /**< 3.3V support */ +#define XSDPS_CAP_VOLT_3V0_MASK 0x02000000U /**< 3.0V support */ +#define XSDPS_CAP_VOLT_1V8_MASK 0x04000000U /**< 1.8V support */ + +#define XSDPS_CAP_SYS_BUS_64_MASK 0x10000000U /**< 64 bit system bus + support */ +/* Spec 2.0 */ +#define XSDPS_CAP_INTR_MODE_MASK 0x08000000U /**< Interrupt mode + support */ +#define XSDPS_CAP_SPI_MODE_MASK 0x20000000U /**< SPI mode */ +#define XSDPS_CAP_SPI_BLOCK_MODE_MASK 0x40000000U /**< SPI block mode */ + + +/* Spec 3.0 */ +#define XSDPS_CAPS_ASYNC_INTR_MASK 0x20000000U /**< Async Interrupt + support */ +#define XSDPS_CAPS_SLOT_TYPE_MASK 0xC0000000U /**< Slot Type */ +#define XSDPS_CAPS_REM_CARD 0x00000000U /**< Removable Slot */ +#define XSDPS_CAPS_EMB_SLOT 0x40000000U /**< Embedded Slot */ +#define XSDPS_CAPS_SHR_BUS 0x80000000U /**< Shared Bus Slot */ + +#define XSDPS_ECAPS_SDR50_MASK 0x00000001U /**< SDR50 Mode support */ +#define XSDPS_ECAPS_SDR104_MASK 0x00000002U /**< SDR104 Mode support */ +#define XSDPS_ECAPS_DDR50_MASK 0x00000004U /**< DDR50 Mode support */ +#define XSDPS_ECAPS_DRV_TYPE_A_MASK 0x00000010U /**< DriverType A support */ +#define XSDPS_ECAPS_DRV_TYPE_C_MASK 0x00000020U /**< DriverType C support */ +#define XSDPS_ECAPS_DRV_TYPE_D_MASK 0x00000040U /**< DriverType D support */ +#define XSDPS_ECAPS_TMR_CNT_MASK 0x00000F00U /**< Timer Count for + Re-tuning */ +#define XSDPS_ECAPS_USE_TNG_SDR50_MASK 0x00002000U /**< SDR50 Mode needs + tuning */ +#define XSDPS_ECAPS_RE_TNG_MODES_MASK 0x0000C000U /**< Re-tuning modes + support */ +#define XSDPS_ECAPS_RE_TNG_MODE1_MASK 0x00000000U /**< Re-tuning mode 1 */ +#define XSDPS_ECAPS_RE_TNG_MODE2_MASK 0x00004000U /**< Re-tuning mode 2 */ +#define XSDPS_ECAPS_RE_TNG_MODE3_MASK 0x00008000U /**< Re-tuning mode 3 */ +#define XSDPS_ECAPS_CLK_MULT_MASK 0x00FF0000U /**< Clock Multiplier value + for Programmable clock + mode */ +#define XSDPS_ECAPS_SPI_MODE_MASK 0x01000000U /**< SPI mode */ +#define XSDPS_ECAPS_SPI_BLK_MODE_MASK 0x02000000U /**< SPI block mode */ + +/** @} */ + +/** @name Present State Register + * + * Gives the current status of the host controller + * Read Only + * @{ + */ + +#define XSDPS_PSR_INHIBIT_CMD_MASK 0x00000001U /**< Command inhibit - CMD */ +#define XSDPS_PSR_INHIBIT_DAT_MASK 0x00000002U /**< Command Inhibit - DAT */ +#define XSDPS_PSR_DAT_ACTIVE_MASK 0x00000004U /**< DAT line active */ +#define XSDPS_PSR_RE_TUNING_REQ_MASK 0x00000008U /**< Re-tuning request */ +#define XSDPS_PSR_WR_ACTIVE_MASK 0x00000100U /**< Write transfer active */ +#define XSDPS_PSR_RD_ACTIVE_MASK 0x00000200U /**< Read transfer active */ +#define XSDPS_PSR_BUFF_WR_EN_MASK 0x00000400U /**< Buffer write enable */ +#define XSDPS_PSR_BUFF_RD_EN_MASK 0x00000800U /**< Buffer read enable */ +#define XSDPS_PSR_CARD_INSRT_MASK 0x00010000U /**< Card inserted */ +#define XSDPS_PSR_CARD_STABLE_MASK 0x00020000U /**< Card state stable */ +#define XSDPS_PSR_CARD_DPL_MASK 0x00040000U /**< Card detect pin level */ +#define XSDPS_PSR_WPS_PL_MASK 0x00080000U /**< Write protect switch + pin level */ +#define XSDPS_PSR_DAT30_SG_LVL_MASK 0x00F00000U /**< Data 3:0 signal lvl */ +#define XSDPS_PSR_CMD_SG_LVL_MASK 0x01000000U /**< Cmd Line signal lvl */ +#define XSDPS_PSR_DAT74_SG_LVL_MASK 0x1E000000U /**< Data 7:4 signal lvl */ + +/** @} */ + +/** @name Maximum Current Capabilities Register + * + * This register is read only register which contains + * information about current capabilities at each voltage levels. + * Read Only + * @{ + */ +#define XSDPS_MAX_CUR_CAPS_1V8_MASK 0x00000F00U /**< Maximum Current + Capability at 1.8V */ +#define XSDPS_MAX_CUR_CAPS_3V0_MASK 0x000000F0U /**< Maximum Current + Capability at 3.0V */ +#define XSDPS_MAX_CUR_CAPS_3V3_MASK 0x0000000FU /**< Maximum Current + Capability at 3.3V */ +/** @} */ + + +/** @name Force Event for Auto CMD Error Status Register + * + * This register is write only register which contains + * control bits to generate events for Auto CMD error status. + * Write Only + * @{ + */ +#define XSDPS_FE_AUTO_CMD12_NT_EX_MASK 0x0001U /**< Auto CMD12 Not + executed */ +#define XSDPS_FE_AUTO_CMD_TOUT_MASK 0x0002U /**< Auto CMD Timeout + Error */ +#define XSDPS_FE_AUTO_CMD_CRC_MASK 0x0004U /**< Auto CMD CRC Error */ +#define XSDPS_FE_AUTO_CMD_EB_MASK 0x0008U /**< Auto CMD End Bit + Error */ +#define XSDPS_FE_AUTO_CMD_IND_MASK 0x0010U /**< Auto CMD Index Error */ +#define XSDPS_FE_AUTO_CMD_CNI_ERR_MASK 0x0080U /**< Command not issued by + Auto CMD12 Error */ +/** @} */ + + + +/** @name Force Event for Error Interrupt Status Register + * + * This register is write only register which contains + * control bits to generate events of error interrupt status register. + * Write Only + * @{ + */ +#define XSDPS_FE_INTR_ERR_CT_MASK 0x0001U /**< Command Timeout + Error */ +#define XSDPS_FE_INTR_ERR_CCRC_MASK 0x0002U /**< Command CRC Error */ +#define XSDPS_FE_INTR_ERR_CEB_MASK 0x0004U /**< Command End Bit + Error */ +#define XSDPS_FE_INTR_ERR_CI_MASK 0x0008U /**< Command Index Error */ +#define XSDPS_FE_INTR_ERR_DT_MASK 0x0010U /**< Data Timeout Error */ +#define XSDPS_FE_INTR_ERR_DCRC_MASK 0x0020U /**< Data CRC Error */ +#define XSDPS_FE_INTR_ERR_DEB_MASK 0x0040U /**< Data End Bit Error */ +#define XSDPS_FE_INTR_ERR_CUR_LMT_MASK 0x0080U /**< Current Limit Error */ +#define XSDPS_FE_INTR_ERR_AUTO_CMD_MASK 0x0100U /**< Auto CMD Error */ +#define XSDPS_FE_INTR_ERR_ADMA_MASK 0x0200U /**< ADMA Error */ +#define XSDPS_FE_INTR_ERR_TR_MASK 0x1000U /**< Target Response */ +#define XSDPS_FE_INTR_VEND_SPF_ERR_MASK 0xE000U /**< Vendor Specific + Error */ + +/** @} */ + +/** @name ADMA Error Status Register + * + * This register is read only register which contains + * status information about ADMA errors. + * Read Only + * @{ + */ +#define XSDPS_ADMA_ERR_MM_LEN_MASK 0x04U /**< ADMA Length Mismatch + Error */ +#define XSDPS_ADMA_ERR_STATE_MASK 0x03U /**< ADMA Error State */ +#define XSDPS_ADMA_ERR_STATE_STOP_MASK 0x00U /**< ADMA Error State + STOP */ +#define XSDPS_ADMA_ERR_STATE_FDS_MASK 0x01U /**< ADMA Error State + FDS */ +#define XSDPS_ADMA_ERR_STATE_TFR_MASK 0x03U /**< ADMA Error State + TFR */ +/** @} */ + +/** @name Preset Values Register + * + * This register is read only register which contains + * preset values for each of speed modes. + * Read Only + * @{ + */ +#define XSDPS_PRE_VAL_SDCLK_FSEL_MASK 0x03FFU /**< SDCLK Frequency + Select Value */ +#define XSDPS_PRE_VAL_CLK_GEN_SEL_MASK 0x0400U /**< Clock Generator + Mode Select */ +#define XSDPS_PRE_VAL_DRV_STR_SEL_MASK 0xC000U /**< Driver Strength + Select Value */ + +/** @} */ + +/** @name Slot Interrupt Status Register + * + * This register is read only register which contains + * interrupt slot signal for each slot. + * Read Only + * @{ + */ +#define XSDPS_SLOT_INTR_STS_INT_MASK 0x0007U /**< Interrupt Signal + mask */ + +/** @} */ + +/** @name Host Controller Version Register + * + * This register is read only register which contains + * Host Controller and Vendor Specific version. + * Read Only + * @{ + */ +#define XSDPS_HC_VENDOR_VER 0xFF00U /**< Vendor + Specification + version mask */ +#define XSDPS_HC_SPEC_VER_MASK 0x00FFU /**< Host + Specification + version mask */ +#define XSDPS_HC_SPEC_V3 0x0002U /**< HC spec version 3 */ +#define XSDPS_HC_SPEC_V2 0x0001U /**< HC spec version 2 */ +#define XSDPS_HC_SPEC_V1 0x0000U /**< HC spec version 1 */ +/** @} */ + +/** @name PHYCTRL Register1 - OTAP, ITAP and SROBE SEL + * + * This register contains bits for input tap, output tap and strobe sel. + * @{ + */ + +#define XSDPS_PHYREG1_STROBE_SEL_MASK 0xFF0000U /**< STROBE Sel Mask */ +#define XSDPS_PHYREG1_STROBE_SEL_SHIFT 16U /**< STROBE Sel Shift */ +#define XSDPS_PHYREG1_ITAP_CHGWIN_MASK 0x40U /**< Input Tap Change Window */ +#define XSDPS_PHYREG1_ITAP_EN_MASK 0x1U /**< Input Tap Enable Mask */ +#define XSDPS_PHYREG1_ITAP_DLY_MASK 0x2EU /**< Input Tap Delay Mask */ +#define XSDPS_PHYREG1_ITAP_DLY_SHIFT 1U /**< Input Tap Delay Shift */ +#define XSDPS_PHYREG1_OTAP_EN_MASK 0x100U /**< Output Tap Enable Mask */ +#define XSDPS_PHYREG1_OTAP_DLY_MASK 0xF000U /**< Output Tap Delay Mask */ +#define XSDPS_PHYREG1_OTAP_DLY_SHIFT 12U /**< Output Tap Delay Shift */ + +/** @} */ + +/** @name PHYCTRL Register2 - DLL enable, FREQ_SEL, Tx and Rx Dly Chain Sel + * + * This register contains bits for cDLL enable, FREQ_SEL, Tx and Rx Dly Chain Sel + * and DLL Ready. + * @{ + */ + +#define XSDPS_PHYREG2_DLL_EN_MASK 0x00000001U /**< DLL enable */ +#define XSDPS_PHYREG2_DLL_RDY_MASK 0x00000002U /**< DLL Ready */ +#define XSDPS_PHYREG2_FREQ_SEL_MASK 0x00000070U /**< Freq selection */ +#define XSDPS_PHYREG2_FREQ_SEL_SHIFT 4U /**< Freq selection shift */ +#define XSDPS_FREQ_SEL_170MHZ_200MHz 0U /**< Macro to select between 170MHz to 200MHz */ +#define XSDPS_FREQ_SEL_140MHZ_169MHz 1U /**< Macro to select between 140MHz to 169MHz */ +#define XSDPS_FREQ_SEL_110MHZ_139MHz 2U /**< Macro to select between 110MHz to 139MHz */ +#define XSDPS_FREQ_SEL_80MHZ_109MHz 3U /**< Macro to select between 80MHz to 109MHz */ +#define XSDPS_FREQ_SEL_50MHZ_79MHz 4U /**< Macro to select between 50MHz to 79MHz */ +#define XSDPS_PHYREG2_TRIM_ICP_MASK 0x00000F00U /**< DLL TRIM ICP */ +#define XSDPS_PHYREG2_TRIM_ICP_DEF_VAL 8U /**< DLL TRIM ICP default value */ +#define XSDPS_PHYREG2_TRIM_ICP_SHIFT 8U /**< DLL TRIM ICP shift */ +#define XSDPS_PHYREG2_DLYTX_SEL_MASK 0x00010000U /**< Delay Chain based Tx Clk */ +#define XSDPS_PHYREG2_DLYRX_SEL_MASK 0x00020000U /**< Delay Chain based Rx Clk */ +/** @} */ + +/** @name Commands + * + * Constant definitions for commands and response related to SD + * @{ + */ +/** + * Command/Response related to SD/eMMC + */ + +#define XSDPS_APP_CMD_PREFIX 0x8000U +#define CMD0 0x0000U +#define CMD1 0x0100U +#define CMD2 0x0200U +#define CMD3 0x0300U +#define CMD4 0x0400U +#define CMD5 0x0500U +#define CMD6 0x0600U +#define ACMD6 (XSDPS_APP_CMD_PREFIX + 0x0600U) +#define CMD7 0x0700U +#define CMD8 0x0800U +#define CMD9 0x0900U +#define CMD10 0x0A00U +#define CMD11 0x0B00U +#define CMD12 0x0C00U +#define ACMD13 (XSDPS_APP_CMD_PREFIX + 0x0D00U) +#define CMD16 0x1000U +#define CMD17 0x1100U +#define CMD18 0x1200U +#define CMD19 0x1300U +#define CMD21 0x1500U +#define CMD23 0x1700U +#define ACMD23 (XSDPS_APP_CMD_PREFIX + 0x1700U) +#define CMD24 0x1800U +#define CMD25 0x1900U +#define CMD32 0x2000U +#define CMD33 0x2100U +#define CMD35 0x2300U +#define CMD36 0x2400U +#define CMD38 0x2600U +#define CMD41 0x2900U +#define ACMD41 (XSDPS_APP_CMD_PREFIX + 0x2900U) +#define ACMD42 (XSDPS_APP_CMD_PREFIX + 0x2A00U) +#define ACMD51 (XSDPS_APP_CMD_PREFIX + 0x3300U) +#define CMD52 0x3400U +#define CMD55 0x3700U +#define CMD58 0x3A00U + +#define RESP_NONE (u32)XSDPS_CMD_RESP_NONE_MASK +#define RESP_R1 (u32)XSDPS_CMD_RESP_L48_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK | \ + (u32)XSDPS_CMD_INX_CHK_EN_MASK + +#define RESP_R1B (u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \ + (u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK + +#define RESP_R2 (u32)XSDPS_CMD_RESP_L136_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK +#define RESP_R3 (u32)XSDPS_CMD_RESP_L48_MASK + +#define RESP_R6 (u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \ + (u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK + +/** @} */ + +/** + * @name Card Interface + * @{ + */ +/** + * Card Interface Conditions Definitions + */ +#define XSDPS_CIC_CHK_PATTERN 0xAAU +#define XSDPS_CIC_VOLT_MASK (0xFU<<8) +#define XSDPS_CIC_VOLT_2V7_3V6 (1U<<8) +#define XSDPS_CIC_VOLT_LOW (1U<<9) +/** @} */ + +/** + * @name OCR + * @{ + */ +/** + * Operation Conditions Register Definitions + */ +#define XSDPS_OCR_PWRUP_STS (0x00000001U << 31) +#define XSDPS_OCR_CC_STS (0x00000001U << 30) +#define XSDPS_OCR_S18 (0x00000001U << 24) +#define XSDPS_OCR_3V5_3V6 (0x00000001U << 23) +#define XSDPS_OCR_3V4_3V5 (0x00000001U << 22) +#define XSDPS_OCR_3V3_3V4 (0x00000001U << 21) +#define XSDPS_OCR_3V2_3V3 (0x00000001U << 20) +#define XSDPS_OCR_3V1_3V2 (0x00000001U << 19) +#define XSDPS_OCR_3V0_3V1 (0x00000001U << 18) +#define XSDPS_OCR_2V9_3V0 (0x00000001U << 17) +#define XSDPS_OCR_2V8_2V9 (0x00000001U << 16) +#define XSDPS_OCR_2V7_2V8 (0x00000001U << 15) +#define XSDPS_OCR_1V7_1V95 (0x00000001U << 7) +#define XSDPS_OCR_HIGH_VOL 0x00FF8000U +#define XSDPS_OCR_LOW_VOL 0x00000080U +/** @} */ + +/** + * @name Card Configuration + * @{ + */ +/** + * SD Card Configuration Register Definitions + */ +#define XSDPS_SCR_REG_LEN 8U +#define XSDPS_SCR_STRUCT_MASK (0xFU<<28) +#define XSDPS_SCR_SPEC_MASK (0xFU<<24) +#define XSDPS_SCR_SPEC_1V0 0U +#define XSDPS_SCR_SPEC_1V1 (1U<<24) +#define XSDPS_SCR_SPEC_2V0_3V0 (2U<<24) +#define XSDPS_SCR_MEM_VAL_AF_ERASE (1U<<23) +#define XSDPS_SCR_SEC_SUPP_MASK (7U<<20) +#define XSDPS_SCR_SEC_SUPP_NONE 0U +#define XSDPS_SCR_SEC_SUPP_1V1 (2U<<20) +#define XSDPS_SCR_SEC_SUPP_2V0 (3U<<20) +#define XSDPS_SCR_SEC_SUPP_3V0 (4U<<20) +#define XSDPS_SCR_BUS_WIDTH_MASK (0xFU<<16) +#define XSDPS_SCR_BUS_WIDTH_1 (1U<<16) +#define XSDPS_SCR_BUS_WIDTH_4 (4U<<16) +#define XSDPS_SCR_SPEC3_MASK (1U<<12) +#define XSDPS_SCR_SPEC3_2V0 0U +#define XSDPS_SCR_SPEC3_3V0 (1U<<12) +#define XSDPS_SCR_CMD_SUPP_MASK 0x3U +#define XSDPS_SCR_CMD23_SUPP (1U<<1) +#define XSDPS_SCR_CMD20_SUPP (1U<<0) +/** @} */ + +/** + * @name Card Status + * @{ + */ +/** + * Card Status Register Definitions + */ +#define XSDPS_CD_STS_OUT_OF_RANGE (1U<<31) +#define XSDPS_CD_STS_ADDR_ERR (1U<<30) +#define XSDPS_CD_STS_BLK_LEN_ERR (1U<<29) +#define XSDPS_CD_STS_ER_SEQ_ERR (1U<<28) +#define XSDPS_CD_STS_ER_PRM_ERR (1U<<27) +#define XSDPS_CD_STS_WP_VIO (1U<<26) +#define XSDPS_CD_STS_IS_LOCKED (1U<<25) +#define XSDPS_CD_STS_LOCK_UNLOCK_FAIL (1U<<24) +#define XSDPS_CD_STS_CMD_CRC_ERR (1U<<23) +#define XSDPS_CD_STS_ILGL_CMD (1U<<22) +#define XSDPS_CD_STS_CARD_ECC_FAIL (1U<<21) +#define XSDPS_CD_STS_CC_ERR (1U<<20) +#define XSDPS_CD_STS_ERR (1U<<19) +#define XSDPS_CD_STS_CSD_OVRWR (1U<<16) +#define XSDPS_CD_STS_WP_ER_SKIP (1U<<15) +#define XSDPS_CD_STS_CARD_ECC_DIS (1U<<14) +#define XSDPS_CD_STS_ER_RST (1U<<13) +#define XSDPS_CD_STS_CUR_STATE (0xFU<<9) +#define XSDPS_CD_STS_RDY_FOR_DATA (1U<<8) +#define XSDPS_CD_STS_APP_CMD (1U<<5) +#define XSDPS_CD_STS_AKE_SEQ_ERR (1U<<2) +/** @} */ + +/** + * @name Switch function + * @{ + */ +/** + * Switch Function Definitions CMD6 + */ +#define XSDPS_SWITCH_SD_RESP_LEN 64U + +#define XSDPS_SWITCH_FUNC_SWITCH (1U<<31) +#define XSDPS_SWITCH_FUNC_CHECK 0U +/** @} */ + +/** + * @name Mode Function + * @{ + */ +/** + * Mode function groups definitions. + */ +#define XSDPS_MODE_FUNC_GRP1 1U +#define XSDPS_MODE_FUNC_GRP2 2U +#define XSDPS_MODE_FUNC_GRP3 3U +#define XSDPS_MODE_FUNC_GRP4 4U +#define XSDPS_MODE_FUNC_GRP5 5U +#define XSDPS_MODE_FUNC_GRP6 6U + +#define XSDPS_FUNC_GRP_DEF_VAL 0xFU +#define XSDPS_FUNC_ALL_GRP_DEF_VAL 0xFFFFFFU +/** @} */ + +/** + * @name Operating modes + * @{ + */ +/** + * SD operating modes in UHS. + */ +#define XSDPS_ACC_MODE_DEF_SDR12 0U +#define XSDPS_ACC_MODE_HS_SDR25 1U +#define XSDPS_ACC_MODE_SDR50 2U +#define XSDPS_ACC_MODE_SDR104 3U +#define XSDPS_ACC_MODE_DDR50 4U +/** @} */ + +/** + * @name General definitions + * @{ + */ +/** + * Definitions related to Driver strength, Current limit and + * CSD specific data. + */ +#define XSDPS_CMD_SYS_ARG_SHIFT 4U +#define XSDPS_CMD_SYS_DEF 0U +#define XSDPS_CMD_SYS_eC 1U +#define XSDPS_CMD_SYS_OTP 3U +#define XSDPS_CMD_SYS_ASSD 4U +#define XSDPS_CMD_SYS_VEND 5U + +#define XSDPS_DRV_TYPE_ARG_SHIFT 8U +#define XSDPS_DRV_TYPE_B 0U +#define XSDPS_DRV_TYPE_A 1U +#define XSDPS_DRV_TYPE_C 2U +#define XSDPS_DRV_TYPE_D 3U + +#define XSDPS_CUR_LIM_ARG_SHIFT 12U +#define XSDPS_CUR_LIM_200 0U +#define XSDPS_CUR_LIM_400 1U +#define XSDPS_CUR_LIM_600 2U +#define XSDPS_CUR_LIM_800 3U + +#define CSD_SPEC_VER_MASK 0x3C0000U +#define READ_BLK_LEN_MASK 0x00000F00U +#define C_SIZE_MULT_MASK 0x00000380U +#define C_SIZE_LOWER_MASK 0xFFC00000U +#define C_SIZE_UPPER_MASK 0x00000003U +#define CSD_STRUCT_MASK 0x00C00000U +#define CSD_V2_C_SIZE_MASK 0x3FFFFF00U +#define CSD_CCC_MASK 0xFFF00000U +#define CSD_CCC_SHIFT 20U +#define CSD_CCC_CLASS5_MASK 0x20U +/** @} */ + +/** + * @name Extended Card Specific Data + * @{ + */ +/** + * EXT_CSD field definitions + */ +#define XSDPS_EXT_CSD_SIZE 512U + +#define EXT_CSD_WR_REL_PARAM_EN (1U<<2) + +#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40U) +#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10U) +#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04U) +#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01U) + +#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7U) +#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1U) +#define EXT_CSD_PART_CONFIG_ACC_BOOT1 (0x2U) +#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3U) +#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4U) +#define EXT_CSD_PART_CONFIG_BYTE (179U) +#define XSDPS_MMC_PART_CFG_0_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24U) \ + | ((u32)EXT_CSD_PART_CONFIG_BYTE << 16U) \ + | ((u32)(0U) << 8U)) + +#define XSDPS_MMC_PART_CFG_1_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24U) \ + | ((u32)EXT_CSD_PART_CONFIG_BYTE << 16U) \ + | ((u32)EXT_CSD_PART_CONFIG_ACC_BOOT0 << 8U)) + +#define XSDPS_MMC_PART_CFG_2_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24U) \ + | ((u32)EXT_CSD_PART_CONFIG_BYTE << 16U) \ + | ((u32)EXT_CSD_PART_CONFIG_ACC_BOOT1 << 8U)) + +#define EXT_CSD_PART_SUPPORT_PART_EN (0x1U) + +#define EXT_CSD_CMD_SET_NORMAL (1U<<0) +#define EXT_CSD_CMD_SET_SECURE (1U<<1) +#define EXT_CSD_CMD_SET_CPSECURE (1U<<2) + +#define EXT_CSD_CARD_TYPE_26 (1U<<0) /* Card can run at 26MHz */ +#define EXT_CSD_CARD_TYPE_52 (1U<<1) /* Card can run at 52MHz */ +#define EXT_CSD_CARD_TYPE_MASK 0x3FU /* Mask out reserved bits */ +#define EXT_CSD_CARD_TYPE_DDR_1_8V (1U<<2) /* Card can run at 52MHz */ + /* DDR mode @1.8V or 3V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_1_2V (1U<<3) /* Card can run at 52MHz */ + /* DDR mode @1.2V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ + | EXT_CSD_CARD_TYPE_DDR_1_2V) +#define EXT_CSD_CARD_TYPE_SDR_1_8V (1U<<4) /* Card can run at 200MHz */ +#define EXT_CSD_CARD_TYPE_SDR_1_2V (1U<<5) /* Card can run at 200MHz */ + /* SDR mode @1.2V I/O */ +#define EXT_CSD_BUS_WIDTH_BYTE 183U +#define EXT_CSD_BUS_WIDTH_1_BIT 0U /* Card is in 1 bit mode */ +#define EXT_CSD_BUS_WIDTH_4_BIT 1U /* Card is in 4 bit mode */ +#define EXT_CSD_BUS_WIDTH_8_BIT 2U /* Card is in 8 bit mode */ +#define EXT_CSD_BUS_WIDTH_DDR_4_BIT 5U /* Card is in 4 bit DDR mode */ +#define EXT_CSD_BUS_WIDTH_DDR_8_BIT 6U /* Card is in 8 bit DDR mode */ + +#define EXT_CSD_HS_TIMING_BYTE 185U +#define EXT_CSD_HS_TIMING_DEF 0U +#define EXT_CSD_HS_TIMING_HIGH 1U /* Card is in high speed mode */ +#define EXT_CSD_HS_TIMING_HS200 2U /* Card is in HS200 mode */ +#define EXT_CSD_HS_TIMING_HS400 3U /* Card is in HS200 mode */ + +#define EXT_CSD_RST_N_FUN_BYTE 162U +#define EXT_CSD_RST_N_FUN_TEMP_DIS 0U /* RST_n signal is temporarily disabled */ +#define EXT_CSD_RST_N_FUN_PERM_EN 1U /* RST_n signal is permanently enabled */ +#define EXT_CSD_RST_N_FUN_PERM_DIS 2U /* RST_n signal is permanently disabled */ + +#define XSDPS_EXT_CSD_CMD_SET 0U +#define XSDPS_EXT_CSD_SET_BITS 1U +#define XSDPS_EXT_CSD_CLR_BITS 2U +#define XSDPS_EXT_CSD_WRITE_BYTE 3U +/** @} */ + +/** + * @name SD/eMMC Bus Speed and Bus Width Arguments + * @{ + */ +/** + * SD/MMC Arguments for Bus Speed and Bus Width. + */ +#define XSDPS_MMC_DEF_SPEED_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \ + | ((u32)EXT_CSD_HS_TIMING_DEF << 8)) + +#define XSDPS_MMC_HIGH_SPEED_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \ + | ((u32)EXT_CSD_HS_TIMING_HIGH << 8)) + +#define XSDPS_MMC_HS200_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \ + | ((u32)EXT_CSD_HS_TIMING_HS200 << 8)) + +#define XSDPS_MMC_HS400_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \ + | ((u32)EXT_CSD_HS_TIMING_HS400 << 8)) + +#define XSDPS_MMC_1_BIT_BUS_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | ((u32)EXT_CSD_BUS_WIDTH_1_BIT << 8)) + +#define XSDPS_MMC_4_BIT_BUS_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | ((u32)EXT_CSD_BUS_WIDTH_4_BIT << 8)) + +#define XSDPS_MMC_8_BIT_BUS_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | ((u32)EXT_CSD_BUS_WIDTH_8_BIT << 8)) + +#define XSDPS_MMC_DDR_4_BIT_BUS_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | ((u32)EXT_CSD_BUS_WIDTH_DDR_4_BIT << 8)) + +#define XSDPS_MMC_DDR_8_BIT_BUS_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | ((u32)EXT_CSD_BUS_WIDTH_DDR_8_BIT << 8)) + +#define XSDPS_MMC_RST_FUN_EN_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_RST_N_FUN_BYTE << 16) \ + | ((u32)EXT_CSD_RST_N_FUN_PERM_EN << 8)) + +#define XSDPS_MMC_DELAY_FOR_SWITCH 1000U + +/** @} */ + +/** + * @name General Delay definitions + * @{ + */ +/** + * @400KHz, in usec + */ +#define XSDPS_74CLK_DELAY 2960U +#define XSDPS_100CLK_DELAY 4000U +#define XSDPS_INIT_DELAY 10000U +/** @} */ + +#define XSDPS_DEF_VOLT_LVL XSDPS_PC_BUS_VSEL_3V0_MASK /**< Default voltage level */ +#define XSDPS_CARD_DEF_ADDR 0x1234U /**< Card Default address */ + +#define XSDPS_CARD_SD 1U /**< SD card */ +#define XSDPS_CARD_MMC 2U /**< MMC card */ +#define XSDPS_CARD_SDIO 3U /**< SDIO card */ +#define XSDPS_CARD_SDCOMBO 4U /**< SDCOMBO card */ +#define XSDPS_CHIP_EMMC 5U /**< EMMC chip */ + + +/** + *@name ADMA2 Descriptor related definitions + * @{ + */ +/** + * ADMA2 Descriptor related definitions + */ +#define XSDPS_DESC_MAX_LENGTH 65536U + +#define XSDPS_DESC_VALID (0x1U << 0) +#define XSDPS_DESC_END (0x1U << 1) +#define XSDPS_DESC_INT (0x1U << 2) +#define XSDPS_DESC_TRAN (0x2U << 4) + +/** @} */ + +/* For changing clock frequencies */ +#define XSDPS_CLK_400_KHZ 400000U /**< 400 KHZ */ +#define XSDPS_CLK_50_MHZ 50000000U /**< 50 MHZ */ +#define XSDPS_CLK_52_MHZ 52000000U /**< 52 MHZ */ +#define XSDPS_SD_VER_1_0 0x1U /**< SD ver 1 */ +#define XSDPS_SD_VER_2_0 0x2U /**< SD ver 2 */ +#define XSDPS_SCR_BLKCNT 1U /**< SCR Block Count */ +#define XSDPS_SCR_BLKSIZE 8U /**< SCR Block Size */ +#define XSDPS_1_BIT_WIDTH 0x1U /**< Bus Width 1 */ +#define XSDPS_4_BIT_WIDTH 0x2U /**< Bus Width 4 */ +#define XSDPS_8_BIT_WIDTH 0x3U /**< Bus Width 8 */ +#define XSDPS_UHS_SPEED_MODE_SDR12 0x0U /**< SDR12 mode */ +#define XSDPS_UHS_SPEED_MODE_SDR25 0x1U /**< SDR25 mode */ +#define XSDPS_UHS_SPEED_MODE_SDR50 0x2U /**< SDR50 mode */ +#define XSDPS_UHS_SPEED_MODE_SDR104 0x3U /**< SDR104 mode */ +#define XSDPS_UHS_SPEED_MODE_DDR50 0x4U /**< DDR50 mode */ +#define XSDPS_HIGH_SPEED_MODE 0x5U /**< High Speed mode */ +#define XSDPS_DEFAULT_SPEED_MODE 0x6U /**< Default speed mode */ +#define XSDPS_HS200_MODE 0x7U /**< eMMC HS200 mode */ +#define XSDPS_HS400_MODE 0x8U /**< eMMC HS400 mode */ +#define XSDPS_DDR52_MODE 0x4U /**< eMMC DDR52 mode */ +#define XSDPS_SWITCH_CMD_BLKCNT 1U /**< Blk cnt for SWITCH cmd */ +#define XSDPS_SWITCH_CMD_BLKSIZE 64U /**< Blk sz for SWITCH cmd */ +#define XSDPS_SWITCH_CMD_HS_GET 0x00FFFFF0U /**< SWITCH cmd to Get HS */ +#define XSDPS_SWITCH_CMD_HS_SET 0x80FFFFF1U /**< SWITCH cmd to Set HS */ +#define XSDPS_SWITCH_CMD_SDR12_SET 0x80FFFFF0U /**< SWITCH cmd to Set SDR12 */ +#define XSDPS_SWITCH_CMD_SDR25_SET 0x80FFFFF1U /**< SWITCH cmd to Set SDR25 */ +#define XSDPS_SWITCH_CMD_SDR50_SET 0x80FFFFF2U /**< SWITCH cmd to Set SDR50 */ +#define XSDPS_SWITCH_CMD_SDR104_SET 0x80FFFFF3U /**< SWITCH cmd to Set SDR104 */ +#define XSDPS_SWITCH_CMD_DDR50_SET 0x80FFFFF4U /**< SWITCH cmd to Set DDR50 */ +#define XSDPS_EXT_CSD_CMD_BLKCNT 1U /**< Blk Cnt for EXT CSD */ +#define XSDPS_EXT_CSD_CMD_BLKSIZE 512U /**< Blk Sz for EXT CSD */ +#define XSDPS_TUNING_CMD_BLKCNT 1U /**< Blk Cnt for Tuning cmd */ +#define XSDPS_TUNING_CMD_BLKSIZE 64U /**< Blk Sz for Tuning cmd */ +#define XSDPS_SD_STATUS_BLKCNT 1U /**< Blk Cnt for SD status */ +#define XSDPS_SD_STATUS_BLKSIZE 64U /**< Blk Sz for SD status */ + +#define XSDPS_HIGH_SPEED_MAX_CLK 50000000U /**< Max clk for HS mode */ +#define XSDPS_UHS_SDR104_MAX_CLK 208000000U /**< Max clk for SDR104 mode */ +#define XSDPS_UHS_SDR50_MAX_CLK 100000000U /**< Max clk for SDR50 mode */ +#define XSDPS_UHS_DDR50_MAX_CLK 50000000U /**< Max clk for DDR50 mode */ +#define XSDPS_UHS_SDR25_MAX_CLK 50000000U /**< Max clk for SDR25 mode */ +#define XSDPS_UHS_SDR12_MAX_CLK 25000000U /**< Max clk for SDR12 mode */ + +#define SD_DRIVER_TYPE_B 0x01U /**< Driver Type B */ +#define SD_DRIVER_TYPE_A 0x02U /**< Driver Type A */ +#define SD_DRIVER_TYPE_C 0x04U /**< Driver Type C */ +#define SD_DRIVER_TYPE_D 0x08U /**< Driver Type D */ +#define SD_SET_CURRENT_LIMIT_200 0U /**< Current limit 200mA */ +#define SD_SET_CURRENT_LIMIT_400 1U /**< Current limit 400mA */ +#define SD_SET_CURRENT_LIMIT_600 2U /**< Current limit 600mA */ +#define SD_SET_CURRENT_LIMIT_800 3U /**< Current limit 800mA */ + +#define SD_MAX_CURRENT_200 (1U << SD_SET_CURRENT_LIMIT_200) /**< Current limit 200mA Arg */ +#define SD_MAX_CURRENT_400 (1U << SD_SET_CURRENT_LIMIT_400) /**< Current limit 400mA Arg */ +#define SD_MAX_CURRENT_600 (1U << SD_SET_CURRENT_LIMIT_600) /**< Current limit 600mA Arg */ +#define SD_MAX_CURRENT_800 (1U << SD_SET_CURRENT_LIMIT_800) /**< Current limit 800mA Arg */ + +#define XSDPS_SD_SDR12_MAX_CLK 25000000U /**< Max clk for SDR12 mode */ +#define XSDPS_SD_SDR25_MAX_CLK 50000000U /**< Max clk for SDR25 mode */ +#define XSDPS_SD_SDR50_MAX_CLK 100000000U /**< Max clk for SDR50 mode */ +#define XSDPS_SD_DDR50_MAX_CLK 50000000U /**< Max clk for DDR50 mode */ +#define XSDPS_SD_SDR104_MAX_CLK 208000000U /**< Max clk for SDR104 mode */ +/** + * XSDPS_SD_INPUT_MAX_CLK is set to 175000000 in order to keep it smaller + * than the clock value coming from the core. This value is kept to safely + * switch to SDR104 mode if the SD card supports it. + */ +#define XSDPS_SD_INPUT_MAX_CLK 175000000U + +#define XSDPS_MMC_HS200_MAX_CLK 200000000U /**< Max clk for MMC HS200 mode */ +#define XSDPS_MMC_HSD_MAX_CLK 52000000U /**< Max clk for MMC HSD mode */ +#define XSDPS_MMC_DDR_MAX_CLK 52000000U /**< Max clk for MMC DDR52 mode */ + +#define XSDPD_MIN_DLL_MODE_CLK 50000000U /**< Min clk for DLL mode */ + +/** + * @name Card states + * @{ + */ +/** + * Definition for Card state. + */ +#define XSDPS_CARD_STATE_IDLE 0U +#define XSDPS_CARD_STATE_RDY 1U +#define XSDPS_CARD_STATE_IDEN 2U +#define XSDPS_CARD_STATE_STBY 3U +#define XSDPS_CARD_STATE_TRAN 4U +#define XSDPS_CARD_STATE_DATA 5U +#define XSDPS_CARD_STATE_RCV 6U +#define XSDPS_CARD_STATE_PROG 7U +#define XSDPS_CARD_STATE_DIS 8U +#define XSDPS_CARD_STATE_BTST 9U +#define XSDPS_CARD_STATE_SLP 10U +/** @} */ + +#define XSDPS_SLOT_REM 0U /**< Removable slot */ +#define XSDPS_SLOT_EMB 1U /**< Embedded slot */ + +#define XSDPS_WIDTH_8 8U /**< Bus width 8 */ +#define XSDPS_WIDTH_4 4U /**< Bus width 4 */ + +#define XSDPS_SLOTTYPE_SDADIR 4U /**< SD3.0 Auto Direction */ + +/** + * @name Tap delays + * @{ + */ +/** + * SD/eMMC ITAP and OTAP delays for different operating modes + * for both Versal and ZynqMP platforms. + */ +#ifdef VERSAL_NET +#define SD_ITAPDLY_SEL_MASK 0x000000FFU +#define SD_OTAPDLY_SEL_MASK 0x0000003FU +#define SD_ITAPDLY 0x0000F0F8U +#define SD_OTAPDLY 0x0000F0FCU +#define SD0_DLL_CTRL 0x00000448U +#define SD1_DLL_CTRL 0x000004C8U +#define SD_DLL_RST 0x00000004U +#define SD_ITAPCHGWIN 0x00000200U +#define SD_ITAPDLYENA 0x00000100U +#define SD_OTAPDLYENA 0x00000040U +#define SD_OTAPDLYSEL_HS200_B0 0x00000007U +#define SD_OTAPDLYSEL_HS200_B2 0x00000007U +#define SD_OTAPDLYSEL_HS400 0x00000004U +#define SD_ITAPDLYSEL_SD50 0x0000000EU +#define SD_OTAPDLYSEL_SD50 0x00000003U +#define SD_ITAPDLYSEL_SD_DDR50 0x00000036U +#define SD_ITAPDLYSEL_EMMC_DDR50 0x00000003U +#define SD_OTAPDLYSEL_SD_DDR50 0x00000003U +#define SD_OTAPDLYSEL_EMMC_DDR50 0x00000005U +#define SD_ITAPDLYSEL_HSD 0x0000002CU +#define SD_ITAPDLYSEL_EMMC_HSD 0x00000000U +#define SD_OTAPDLYSEL_SD_HSD 0x00000004U +#define SD_OTAPDLYSEL_EMMC_HSD 0x00000005U +#define SD_AUTODIR_ITAPDLYSEL_HSD 0x00000025U +#define SD_AUTODIR_ITAPDLYSEL_SDR25 0x00000026U +#define SD_AUTODIR_ITAPDLYSEL_DDR50 0x0000002AU +#define PHY_STRB_SEL_SIG 0x00000077U +#elif defined (versal) +#define SD_ITAPDLY_SEL_MASK 0x000000FFU +#define SD_OTAPDLY_SEL_MASK 0x0000003FU +#define SD_ITAPDLY 0x0000F0F8U +#define SD_OTAPDLY 0x0000F0FCU +#define SD0_DLL_CTRL 0x00000448U +#define SD1_DLL_CTRL 0x000004C8U +#define SD_DLL_RST 0x00000004U +#define SD_ITAPCHGWIN 0x00000200U +#define SD_ITAPDLYENA 0x00000100U +#define SD_OTAPDLYENA 0x00000040U +#define SD_OTAPDLYSEL_HS200_B0 0x00000002U +#define SD_OTAPDLYSEL_HS200_B2 0x00000002U +#define SD_ITAPDLYSEL_SD50 0x0000000EU +#define SD_OTAPDLYSEL_SD50 0x00000003U +#define SD_ITAPDLYSEL_SD_DDR50 0x00000036U +#define SD_ITAPDLYSEL_EMMC_DDR50 0x0000001EU +#define SD_OTAPDLYSEL_SD_DDR50 0x00000003U +#define SD_OTAPDLYSEL_EMMC_DDR50 0x00000005U +#define SD_ITAPDLYSEL_HSD 0x0000002CU +#define SD_ITAPDLYSEL_EMMC_HSD 0x0000002CU +#define SD_OTAPDLYSEL_SD_HSD 0x00000004U +#define SD_OTAPDLYSEL_EMMC_HSD 0x00000005U +#define SD_AUTODIR_ITAPDLYSEL_HSD 0x00000025U +#define SD_AUTODIR_ITAPDLYSEL_SDR25 0x00000026U +#define SD_AUTODIR_ITAPDLYSEL_DDR50 0x0000002AU +#else +#define SD0_ITAPDLY_SEL_MASK 0x000000FFU +#define SD0_OTAPDLY_SEL_MASK 0x0000003FU +#define SD1_ITAPDLY_SEL_MASK 0x00FF0000U +#define SD1_OTAPDLY_SEL_MASK 0x003F0000U +#define SD_DLL_CTRL 0x00000358U +#define SD_ITAPDLY 0x00000314U +#define SD_OTAPDLY 0x00000318U +#define SD0_DLL_RST 0x00000004U +#define SD1_DLL_RST 0x00040000U +#define SD0_ITAPCHGWIN 0x00000200U +#define SD0_ITAPDLYENA 0x00000100U +#define SD0_OTAPDLYENA 0x00000040U +#define SD1_ITAPCHGWIN 0x02000000U +#define SD1_ITAPDLYENA 0x01000000U +#define SD1_OTAPDLYENA 0x00400000U +#define SD_OTAPDLYSEL_HS200_B0 0x00000003U +#define SD_OTAPDLYSEL_HS200_B2 0x00000002U +#define SD_ITAPDLYSEL_SD50 0x00000014U +#define SD_OTAPDLYSEL_SD50 0x00000003U +#define SD_ITAPDLYSEL_SD_DDR50 0x0000003DU +#define SD_ITAPDLYSEL_EMMC_DDR50 0x00000012U +#define SD_OTAPDLYSEL_SD_DDR50 0x00000004U +#define SD_OTAPDLYSEL_EMMC_DDR50 0x00000006U +#define SD_ITAPDLYSEL_HSD 0x00000015U +#define SD_ITAPDLYSEL_EMMC_HSD 0x00000015U +#define SD_OTAPDLYSEL_SD_HSD 0x00000005U +#define SD_OTAPDLYSEL_EMMC_HSD 0x00000006U +#define SD_AUTODIR_ITAPDLYSEL_HSD 0x00000028U +#define SD_AUTODIR_ITAPDLYSEL_SDR25 0x0000002CU +#define SD_AUTODIR_ITAPDLYSEL_DDR50 0x00000033U +#endif +/** @} */ + +#ifdef __MICROBLAZE__ +#define XPS_SYS_CTRL_BASEADDR 0xFF180000U /**< System controller Baseaddress */ +#endif + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +#define XSdPs_In64 Xil_In64 /**< Low level 64-bit data read */ +#define XSdPs_Out64 Xil_Out64 /**< Low level 64-bit data write */ + +#define XSdPs_In32 Xil_In32 /**< Low level 32-bit data read */ +#define XSdPs_Out32 Xil_Out32 /**< Low level 32-bit data write */ + +#define XSdPs_In16 Xil_In16 /**< Low level 16-bit data read */ +#define XSdPs_Out16 Xil_Out16 /**< Low level 16-bit data write */ + +#define XSdPs_In8 Xil_In8 /**< Low level 8-bit data read */ +#define XSdPs_Out8 Xil_Out8 /**< Low level 8-bit data write */ + +/****************************************************************************/ +/** +* Read a register. +* +* @param InstancePtr is the pointer to the sdps instance. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XSdPs_ReadReg(XSdPs *InstancePtr. s32 RegOffset) +* +******************************************************************************/ +#define XSdPs_ReadReg64(InstancePtr, RegOffset) \ + XSdPs_In64((InstancePtr->Config.BaseAddress) + RegOffset) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param InstancePtr is the pointer to the sdps instance. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XSdPs_WriteReg(XSdPs *InstancePtr, s32 RegOffset, +* u64 RegisterValue) +* +******************************************************************************/ +#define XSdPs_WriteReg64(InstancePtr, RegOffset, RegisterValue) \ + XSdPs_Out64((InstancePtr->Config.BaseAddress) + (RegOffset), \ + (RegisterValue)) + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XSdPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +#define XSdPs_ReadReg(BaseAddress, RegOffset) \ + XSdPs_In32((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset)) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XSdPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +* +******************************************************************************/ +#define XSdPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XSdPs_Out32((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset), (RegisterValue)) + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u16 XSdPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +static INLINE u16 XSdPs_ReadReg16(u32 BaseAddress, u8 RegOffset) +{ +#if defined (__MICROBLAZE__) + u32 Reg; + BaseAddress += RegOffset & 0xFC; + Reg = XSdPs_In32(BaseAddress); + Reg >>= ((RegOffset & 0x3)*8); + return (u16)Reg; +#else + return XSdPs_In16((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset)); +#endif +} + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XSdPs_WriteReg(u32 BaseAddress, int RegOffset, +* u16 RegisterValue) +* +******************************************************************************/ + +static INLINE void XSdPs_WriteReg16(u32 BaseAddress, u8 RegOffset, u16 RegisterValue) +{ +#if defined (__MICROBLAZE__) + u32 Reg; + BaseAddress += RegOffset & 0xFC; + Reg = XSdPs_In32(BaseAddress); + Reg &= ~(0xFFFFU<<((RegOffset & 0x3)*8)); + Reg |= RegisterValue <<((RegOffset & 0x3)*8); + XSdPs_Out32(BaseAddress, Reg); +#else + XSdPs_Out16((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset), (RegisterValue)); +#endif +} + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u8 XSdPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +static INLINE u8 XSdPs_ReadReg8(u32 BaseAddress, u8 RegOffset) +{ +#if defined (__MICROBLAZE__) + u32 Reg; + BaseAddress += RegOffset & 0xFC; + Reg = XSdPs_In32(BaseAddress); + Reg >>= ((RegOffset & 0x3)*8); + return (u8)Reg; +#else + return XSdPs_In8((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset)); +#endif +} +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XSdPs_WriteReg(u32 BaseAddress, int RegOffset, +* u8 RegisterValue) +* +******************************************************************************/ +static INLINE void XSdPs_WriteReg8(u32 BaseAddress, u8 RegOffset, u8 RegisterValue) +{ +#if defined (__MICROBLAZE__) + u32 Reg; + BaseAddress += RegOffset & 0xFC; + Reg = XSdPs_In32(BaseAddress); + Reg &= ~(0xFFU<<((RegOffset & 0x3)*8)); + Reg |= RegisterValue <<((RegOffset & 0x3)*8); + XSdPs_Out32(BaseAddress, Reg); +#else + XSdPs_Out8((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset), (RegisterValue)); +#endif +} +/***************************************************************************/ +/** +* Macro to get present status register +* +* @param BaseAddress contains the base address of the device. +* +* @return None. +* +* @note C-Style signature: +* void XSdPs_WriteReg(u32 BaseAddress, int RegOffset, +* u8 RegisterValue) +* +******************************************************************************/ +#define XSdPs_GetPresentStatusReg(BaseAddress) \ + XSdPs_In32((BaseAddress) + (XSDPS_PRES_STATE_OFFSET)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* SD_HW_H_ */ +/** @endcond */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xstatus.h b/bsp_z7/ps7_cortexa9_0/include/xstatus.h new file mode 100644 index 0000000..85d1e73 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xstatus.h @@ -0,0 +1,524 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All Rights Reserved. * +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xstatus.h +* +* @addtogroup common_status_codes Xilinx software status codes +* +* The xstatus.h file contains the Xilinx software status codes.These codes are +* used throughout the Xilinx device drivers. +* +* @{ +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XSTATUS_H /* prevent circular inclusions */ +#define XSTATUS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/*********************** Common statuses 0 - 500 *****************************/ +/** +@name Common Status Codes for All Device Drivers +@{ +*/ +#define XST_SUCCESS 0L +#define XST_FAILURE 1L +#define XST_DEVICE_NOT_FOUND 2L +#define XST_DEVICE_BLOCK_NOT_FOUND 3L +#define XST_INVALID_VERSION 4L +#define XST_DEVICE_IS_STARTED 5L +#define XST_DEVICE_IS_STOPPED 6L +#define XST_FIFO_ERROR 7L /*!< An error occurred during an + operation with a FIFO such as + an underrun or overrun, this + error requires the device to + be reset */ +#define XST_RESET_ERROR 8L /*!< An error occurred which requires + the device to be reset */ +#define XST_DMA_ERROR 9L /*!< A DMA error occurred, this error + typically requires the device + using the DMA to be reset */ +#define XST_NOT_POLLED 10L /*!< The device is not configured for + polled mode operation */ +#define XST_FIFO_NO_ROOM 11L /*!< A FIFO did not have room to put + the specified data into */ +#define XST_BUFFER_TOO_SMALL 12L /*!< The buffer is not large enough + to hold the expected data */ +#define XST_NO_DATA 13L /*!< There was no data available */ +#define XST_REGISTER_ERROR 14L /*!< A register did not contain the + expected value */ +#define XST_INVALID_PARAM 15L /*!< An invalid parameter was passed + into the function */ +#define XST_NOT_SGDMA 16L /*!< The device is not configured for + scatter-gather DMA operation */ +#define XST_LOOPBACK_ERROR 17L /*!< A loopback test failed */ +#define XST_NO_CALLBACK 18L /*!< A callback has not yet been + registered */ +#define XST_NO_FEATURE 19L /*!< Device is not configured with + the requested feature */ +#define XST_NOT_INTERRUPT 20L /*!< Device is not configured for + interrupt mode operation */ +#define XST_DEVICE_BUSY 21L /*!< Device is busy */ +#define XST_ERROR_COUNT_MAX 22L /*!< The error counters of a device + have maxed out */ +#define XST_IS_STARTED 23L /*!< Used when part of device is + already started i.e. + sub channel */ +#define XST_IS_STOPPED 24L /*!< Used when part of device is + already stopped i.e. + sub channel */ +#define XST_DATA_LOST 26L /*!< Driver defined error */ +#define XST_RECV_ERROR 27L /*!< Generic receive error */ +#define XST_SEND_ERROR 28L /*!< Generic transmit error */ +#define XST_NOT_ENABLED 29L /*!< A requested service is not + available because it has not + been enabled */ +#define XST_NO_ACCESS 30L /* Generic access error */ +#define XST_TIMEOUT 31L /*!< Event timeout occurred */ +#define XST_GLITCH_ERROR 32L /*!< Used when a glitch occurs*/ + +/** @} */ +/***************** Utility Component statuses 401 - 500 *********************/ +/** +@name Utility Component Status Codes 401 - 500 +@{ +*/ +#define XST_MEMTEST_FAILED 401L /*!< Memory test failed */ + +/** @} */ +/***************** Common Components statuses 501 - 1000 *********************/ +/** +@name Packet Fifo Status Codes 501 - 510 +@{ +*/ +/********************* Packet Fifo statuses 501 - 510 ************************/ + +#define XST_PFIFO_LACK_OF_DATA 501L /*!< Not enough data in FIFO */ +#define XST_PFIFO_NO_ROOM 502L /*!< Not enough room in FIFO */ +#define XST_PFIFO_BAD_REG_VALUE 503L /*!< Self test, a register value + was invalid after reset */ +#define XST_PFIFO_ERROR 504L /*!< Generic packet FIFO error */ +#define XST_PFIFO_DEADLOCK 505L /*!< Packet FIFO is reporting + * empty and full simultaneously + */ +/** @} */ +/** +@name DMA Status Codes 511 - 530 +@{ +*/ +/************************** DMA statuses 511 - 530 ***************************/ + +#define XST_DMA_TRANSFER_ERROR 511L /*!< Self test, DMA transfer + failed */ +#define XST_DMA_RESET_REGISTER_ERROR 512L /*!< Self test, a register value + was invalid after reset */ +#define XST_DMA_SG_LIST_EMPTY 513L /*!< Scatter gather list contains + no buffer descriptors ready + to be processed */ +#define XST_DMA_SG_IS_STARTED 514L /*!< Scatter gather not stopped */ +#define XST_DMA_SG_IS_STOPPED 515L /*!< Scatter gather not running */ +#define XST_DMA_SG_LIST_FULL 517L /*!< All the buffer descriptors of + the scatter gather list are + being used */ +#define XST_DMA_SG_BD_LOCKED 518L /*!< The scatter gather buffer + descriptor which is to be + copied over in the scatter + list is locked */ +#define XST_DMA_SG_NOTHING_TO_COMMIT 519L /*!< No buffer descriptors have been + put into the scatter gather + list to be committed */ +#define XST_DMA_SG_COUNT_EXCEEDED 521L /*!< The packet count threshold + specified was larger than the + total # of buffer descriptors + in the scatter gather list */ +#define XST_DMA_SG_LIST_EXISTS 522L /*!< The scatter gather list has + already been created */ +#define XST_DMA_SG_NO_LIST 523L /*!< No scatter gather list has + been created */ +#define XST_DMA_SG_BD_NOT_COMMITTED 524L /*!< The buffer descriptor which was + being started was not committed + to the list */ +#define XST_DMA_SG_NO_DATA 525L /*!< The buffer descriptor to start + has already been used by the + hardware so it can't be reused + */ +#define XST_DMA_SG_LIST_ERROR 526L /*!< General purpose list access + error */ +#define XST_DMA_BD_ERROR 527L /*!< General buffer descriptor + error */ +/** @} */ +/** +@name IPIF Status Codes Codes 531 - 550 +@{ +*/ +/************************** IPIF statuses 531 - 550 ***************************/ + +#define XST_IPIF_REG_WIDTH_ERROR 531L /*!< An invalid register width + was passed into the function */ +#define XST_IPIF_RESET_REGISTER_ERROR 532L /*!< The value of a register at + reset was not valid */ +#define XST_IPIF_DEVICE_STATUS_ERROR 533L /*!< A write to the device interrupt + status register did not read + back correctly */ +#define XST_IPIF_DEVICE_ACK_ERROR 534L /*!< The device interrupt status + register did not reset when + acked */ +#define XST_IPIF_DEVICE_ENABLE_ERROR 535L /*!< The device interrupt enable + register was not updated when + other registers changed */ +#define XST_IPIF_IP_STATUS_ERROR 536L /*!< A write to the IP interrupt + status register did not read + back correctly */ +#define XST_IPIF_IP_ACK_ERROR 537L /*!< The IP interrupt status register + did not reset when acked */ +#define XST_IPIF_IP_ENABLE_ERROR 538L /*!< IP interrupt enable register was + not updated correctly when other + registers changed */ +#define XST_IPIF_DEVICE_PENDING_ERROR 539L /*!< The device interrupt pending + register did not indicate the + expected value */ +#define XST_IPIF_DEVICE_ID_ERROR 540L /*!< The device interrupt ID register + did not indicate the expected + value */ +#define XST_IPIF_ERROR 541L /*!< Generic ipif error */ +/** @} */ + +/****************** Device specific statuses 1001 - 4095 *********************/ +/** +@name Ethernet Status Codes 1001 - 1050 +@{ +*/ +/********************* Ethernet statuses 1001 - 1050 *************************/ + +#define XST_EMAC_MEMORY_SIZE_ERROR 1001L /*!< Memory space is not big enough + * to hold the minimum number of + * buffers or descriptors */ +#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L /*!< Memory allocation failed */ +#define XST_EMAC_MII_READ_ERROR 1003L /*!< MII read error */ +#define XST_EMAC_MII_BUSY 1004L /*!< An MII operation is in progress */ +#define XST_EMAC_OUT_OF_BUFFERS 1005L /*!< Driver is out of buffers */ +#define XST_EMAC_PARSE_ERROR 1006L /*!< Invalid driver init string */ +#define XST_EMAC_COLLISION_ERROR 1007L /*!< Excess deferral or late + * collision on polled send */ +/** @} */ +/** +@name UART Status Codes 1051 - 1075 +@{ +*/ +/*********************** UART statuses 1051 - 1075 ***************************/ +#define XST_UART + +#define XST_UART_INIT_ERROR 1051L +#define XST_UART_START_ERROR 1052L +#define XST_UART_CONFIG_ERROR 1053L +#define XST_UART_TEST_FAIL 1054L +#define XST_UART_BAUD_ERROR 1055L +#define XST_UART_BAUD_RANGE 1056L + +/** @} */ +/** +@name IIC Status Codes 1076 - 1100 +@{ +*/ +/************************ IIC statuses 1076 - 1100 ***************************/ + +#define XST_IIC_SELFTEST_FAILED 1076 /*!< self test failed */ +#define XST_IIC_BUS_BUSY 1077 /*!< bus found busy */ +#define XST_IIC_GENERAL_CALL_ADDRESS 1078 /*!< mastersend attempted with */ + /* general call address */ +#define XST_IIC_STAND_REG_RESET_ERROR 1079 /*!< A non parameterizable reg */ + /* value after reset not valid */ +#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080 /*!< Tx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081 /*!< Rx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_TBA_REG_RESET_ERROR 1082 /*!< 10 bit addr incl in design */ + /* value after reset not valid */ +#define XST_IIC_CR_READBACK_ERROR 1083 /*!< Read of the control register */ + /* didn't return value written */ +#define XST_IIC_DTR_READBACK_ERROR 1084 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_DRR_READBACK_ERROR 1085 /*!< Read of the data Receive reg */ + /* didn't return value written */ +#define XST_IIC_ADR_READBACK_ERROR 1086 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_TBA_READBACK_ERROR 1087 /*!< Read of the 10 bit addr reg */ + /* didn't return written value */ +#define XST_IIC_NOT_SLAVE 1088 /*!< The device isn't a slave */ +#define XST_IIC_ARB_LOST 1089 /*!< Arbitration lost for master */ +/** @} */ +/** +@name ATMC Status Codes 1101 - 1125 +@{ +*/ +/*********************** ATMC statuses 1101 - 1125 ***************************/ + +#define XST_ATMC_ERROR_COUNT_MAX 1101L /*!< the error counters in the ATM + controller hit the max value + which requires the statistics + to be cleared */ +/** @} */ +/** +@name Flash Status Codes 1126 - 1150 +@{ +*/ +/*********************** Flash statuses 1126 - 1150 **************************/ + +#define XST_FLASH_BUSY 1126L /*!< Flash is erasing or programming + */ +#define XST_FLASH_READY 1127L /*!< Flash is ready for commands */ +#define XST_FLASH_ERROR 1128L /*!< Flash had detected an internal + error. Use XFlash_DeviceControl + to retrieve device specific codes + */ +#define XST_FLASH_ERASE_SUSPENDED 1129L /*!< Flash is in suspended erase state + */ +#define XST_FLASH_WRITE_SUSPENDED 1130L /*!< Flash is in suspended write state + */ +#define XST_FLASH_PART_NOT_SUPPORTED 1131L /*!< Flash type not supported by + driver */ +#define XST_FLASH_NOT_SUPPORTED 1132L /*!< Operation not supported */ +#define XST_FLASH_TOO_MANY_REGIONS 1133L /*!< Too many erase regions */ +#define XST_FLASH_TIMEOUT_ERROR 1134L /*!< Programming or erase operation + aborted due to a timeout */ +#define XST_FLASH_ADDRESS_ERROR 1135L /*!< Accessed flash outside its + addressible range */ +#define XST_FLASH_ALIGNMENT_ERROR 1136L /*!< Write alignment error */ +#define XST_FLASH_BLOCKING_CALL_ERROR 1137L /*!< Couldn't return immediately from + write/erase function with + XFL_NON_BLOCKING_WRITE/ERASE + option cleared */ +#define XST_FLASH_CFI_QUERY_ERROR 1138L /*!< Failed to query the device */ +/** @} */ +/** +@name SPI Status Codes 1151 - 1175 +@{ +*/ +/*********************** SPI statuses 1151 - 1175 ****************************/ + +#define XST_SPI_MODE_FAULT 1151 /*!< master was selected as slave */ +#define XST_SPI_TRANSFER_DONE 1152 /*!< data transfer is complete */ +#define XST_SPI_TRANSMIT_UNDERRUN 1153 /*!< slave underruns transmit register */ +#define XST_SPI_RECEIVE_OVERRUN 1154 /*!< device overruns receive register */ +#define XST_SPI_NO_SLAVE 1155 /*!< no slave has been selected yet */ +#define XST_SPI_TOO_MANY_SLAVES 1156 /*!< more than one slave is being + * selected */ +#define XST_SPI_NOT_MASTER 1157 /*!< operation is valid only as master */ +#define XST_SPI_SLAVE_ONLY 1158 /*!< device is configured as slave-only + */ +#define XST_SPI_SLAVE_MODE_FAULT 1159 /*!< slave was selected while disabled */ +#define XST_SPI_SLAVE_MODE 1160 /*!< device has been addressed as slave */ +#define XST_SPI_RECEIVE_NOT_EMPTY 1161 /*!< device received data in slave mode */ + +#define XST_SPI_COMMAND_ERROR 1162 /*!< unrecognised command - qspi only */ +#define XST_SPI_POLL_DONE 1163 /*!< controller completed polling the + device for status */ +/** @} */ +/** +@name OPB Arbiter Status Codes 1176 - 1200 +@{ +*/ +/********************** OPB Arbiter statuses 1176 - 1200 *********************/ + +#define XST_OPBARB_INVALID_PRIORITY 1176 /*!< the priority registers have either + * one master assigned to two or more + * priorities, or one master not + * assigned to any priority + */ +#define XST_OPBARB_NOT_SUSPENDED 1177 /*!< an attempt was made to modify the + * priority levels without first + * suspending the use of priority + * levels + */ +#define XST_OPBARB_PARK_NOT_ENABLED 1178 /*!< bus parking by id was enabled but + * bus parking was not enabled + */ +#define XST_OPBARB_NOT_FIXED_PRIORITY 1179 /*!< the arbiter must be in fixed + * priority mode to allow the + * priorities to be changed + */ +/** @} */ +/** +@name INTC Status Codes 1201 - 1225 +@{ +*/ +/************************ Intc statuses 1201 - 1225 **************************/ + +#define XST_INTC_FAIL_SELFTEST 1201 /*!< self test failed */ +#define XST_INTC_CONNECT_ERROR 1202 /*!< interrupt already in use */ +/** @} */ +/** +@name TmrCtr Status Codes 1226 - 1250 +@{ +*/ +/********************** TmrCtr statuses 1226 - 1250 **************************/ + +#define XST_TMRCTR_TIMER_FAILED 1226 /*!< self test failed */ +/** @} */ +/** +@name WdtTb Status Codes 1251 - 1275 +@{ +*/ +/********************** WdtTb statuses 1251 - 1275 ***************************/ + +#define XST_WDTTB_TIMER_FAILED 1251L +/** @} */ +/** +@name PlbArb status Codes 1276 - 1300 +@{ +*/ +/********************** PlbArb statuses 1276 - 1300 **************************/ + +#define XST_PLBARB_FAIL_SELFTEST 1276L +/** @} */ +/** +@name Plb2Opb Status Codes 1301 - 1325 +@{ +*/ +/********************** Plb2Opb statuses 1301 - 1325 *************************/ + +#define XST_PLB2OPB_FAIL_SELFTEST 1301L +/** @} */ +/** +@name Opb2Plb Status 1326 - 1350 +@{ +*/ +/********************** Opb2Plb statuses 1326 - 1350 *************************/ + +#define XST_OPB2PLB_FAIL_SELFTEST 1326L +/** @} */ +/** +@name SysAce Status Codes 1351 - 1360 +@{ +*/ +/********************** SysAce statuses 1351 - 1360 **************************/ + +#define XST_SYSACE_NO_LOCK 1351L /*!< No MPU lock has been granted */ +/** @} */ +/** +@name PCI Bridge Status Codes 1361 - 1375 +@{ +*/ +/********************** PCI Bridge statuses 1361 - 1375 **********************/ + +#define XST_PCI_INVALID_ADDRESS 1361L +/** @} */ +/** +@name FlexRay Constants 1400 - 1409 +@{ +*/ +/********************** FlexRay constants 1400 - 1409 *************************/ + +#define XST_FR_TX_ERROR 1400 +#define XST_FR_TX_BUSY 1401 +#define XST_FR_BUF_LOCKED 1402 +#define XST_FR_NO_BUF 1403 +/** @} */ +/** +@name USB constants 1410 - 1420 +@{ +*/ +/****************** USB constants 1410 - 1420 *******************************/ + +#define XST_USB_ALREADY_CONFIGURED 1410 +#define XST_USB_BUF_ALIGN_ERROR 1411 +#define XST_USB_NO_DESC_AVAILABLE 1412 +#define XST_USB_BUF_TOO_BIG 1413 +#define XST_USB_NO_BUF 1414 +/** @} */ +/** +@name HWICAP constants 1421 - 1429 +@{ +*/ +/****************** HWICAP constants 1421 - 1429 *****************************/ + +#define XST_HWICAP_WRITE_DONE 1421 + +/** @} */ +/** +@name AXI VDMA constants 1430 - 1440 +@{ +*/ +/****************** AXI VDMA constants 1430 - 1440 *****************************/ + +#define XST_VDMA_MISMATCH_ERROR 1430 +/** @} */ +/** +@name NAND Flash Status Codes 1441 - 1459 +@{ +*/ +/*********************** NAND Flash statuses 1441 - 1459 *********************/ + +#define XST_NAND_BUSY 1441L /*!< Flash is erasing or + * programming + */ +#define XST_NAND_READY 1442L /*!< Flash is ready for commands + */ +#define XST_NAND_ERROR 1443L /*!< Flash had detected an + * internal error. + */ +#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by + * driver + */ +#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported + */ +#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase + * operation aborted due to a + * timeout + */ +#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its + * addressible range + */ +#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error + */ +#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter + * page of the device + */ +#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error + */ + +#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected + */ +/** @} */ + +/**************************** Type Definitions *******************************/ + +typedef s32 XStatus; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ + +/** + *@endcond + */ + +/** +* @} End of "addtogroup common_status_codes". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xtime_l.h b/bsp_z7/ps7_cortexa9_0/include/xtime_l.h new file mode 100644 index 0000000..9d17f5c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xtime_l.h @@ -0,0 +1,86 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xtime_l.h +* @addtogroup a9_time_apis Cortex A9 Time Functions +* +* xtime_l.h provides access to the 64-bit Global Counter in the PMU. This +* counter increases by one at every two processor cycles. These functions can +* be used to get/set time in the global timer. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------------
+* 1.00a rp/sdm 11/03/09 Initial release.
+* 3.06a sgd    05/15/12 Updated get/set time functions to make use Global Timer
+* 3.06a asa    06/17/12 Reverted back the changes to make use Global Timer.
+* 3.07a sgd    07/05/12 Updated get/set time functions to make use Global Timer
+* 6.6   srm    10/23/17 Updated the macros to support user configurable sleep
+*						implementation
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 7.5   mus    04/30/21  Moved pragma message from xtime_l.h to xtime_l.c, to avoid
+*                        displaying same warnings multiple times. It fixes CR#1090562.
+* 
+* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef XTIME_H /* prevent circular inclusions */ +#define XTIME_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xparameters.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +typedef u64 XTime; + +/************************** Constant Definitions *****************************/ +#define GLOBAL_TMR_BASEADDR XPAR_GLOBAL_TMR_BASEADDR +#define GTIMER_COUNTER_LOWER_OFFSET 0x00U +#define GTIMER_COUNTER_UPPER_OFFSET 0x04U +#define GTIMER_CONTROL_OFFSET 0x08U + +#if defined (SLEEP_TIMER_BASEADDR) +#define COUNTS_PER_SECOND (SLEEP_TIMER_FREQUENCY) +#else +/* Global Timer is always clocked at half of the CPU frequency */ +#define COUNTS_PER_SECOND (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ /2) +#endif +/************************** Variable Definitions *****************************/ + +/** +*@endcond +*/ + +/************************** Function Prototypes ******************************/ + +void XTime_SetTime(XTime Xtime_Global); +void XTime_GetTime(XTime *Xtime_Global); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XTIME_H */ +/** +* @} End of "addtogroup a9_time_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/include/xttcps.h b/bsp_z7/ps7_cortexa9_0/include/xttcps.h new file mode 100644 index 0000000..643e73e --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xttcps.h @@ -0,0 +1,526 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xttcps.h +* @addtogroup ttcps Overview +* @{ +* @details +* +* This is the driver for one 16-bit timer counter in the Triple Timer Counter +* (TTC) module in the Ps block. +* +* The TTC module provides three independent timer/counter modules that can each +* be clocked using either the system clock (pclk) or an externally driven +* clock (ext_clk). In addition, each counter can independently prescale its +* selected clock input (divided by 2 to 65536). Counters can be set to +* decrement or increment. +* +* Each of the counters can be programmed to generate interrupt pulses: +* . At a regular, predefined period, that is on a timed interval +* . When the counter registers overflow +* . When the count matches any one of the three 'match' registers +* +* Therefore, up to six different events can trigger a timer interrupt: three +* match interrupts, an overflow interrupt, an interval interrupt and an event +* timer interrupt. Note that the overflow interrupt and the interval interrupt +* are mutually exclusive. +* +* Initialization & Configuration +* +* An XTtcPs_Config structure is used to configure a driver instance. +* Information in the XTtcPs_Config structure is the hardware properties +* about the device. +* +* A driver instance is initialized through +* XTtcPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr). Where CfgPtr +* is a pointer to the XTtcPs_Config structure, it can be looked up statically +* through XTtcPs_LookupConfig(DeviceID), or passed in by the caller. The +* EffectiveAddr can be the static base address of the device or virtual +* mapped address if address translation is supported. +* +* Interrupts +* +* Interrupt handler is not provided by the driver, as handling of interrupt +* is application specific. +* +* stack usage(in bytes) +* +* XTtcPs_LookupConfig : 32 +* XTtcPs_CfgInitialize : 80 +* XTtcPs_SetMatchValue : 32 +* XTtcPs_GetMatchValue : 48 +* XTtcPs_SetPrescaler : 48 +* XTtcPs_GetPrescaler : 48 +* XTtcPs_CalcIntervalFromFreq : 48 +* XTtcPs_SetOptions : 48 +* XTtcPs_GetOptions : 48 +* XTtcPs_SelfTest : 48 +* XTtcPs_InterruptHandler : 48 +* XTtcPs_SetStatusHandler : 48 +* +* Memory foot-print(in bytes) +* +* XTtcPs_LookupConfig : 72 +* XTtcPs_CfgInitialize : 304 +* XTtcPs_SetMatchValue : 168 +* XTtcPs_GetMatchValue : 176 +* XTtcPs_SetPrescaler : 172 +* XTtcPs_GetPrescaler : 152 +* XTtcPs_CalcIntervalFromFreq : 228 +* XTtcPs_SetOptions : 424 +* XTtcPs_GetOptions : 200 +* XTtcPs_SelfTest : 148 +* XTtcPs_InterruptHandler : 88 +* XTtcPs_SetStatusHandler : 140 +* +* Execution Time(in usec) +* +* XTtcPs_LookupConfig : 8.31 +* TtcPs_CfgInitialize : 1.30 +* XTtcPs_SetMatchValue : 1.10 +* XTtcPs_GetMatchValue : 1.00 +* XTtcPs_SetPrescaler : 1.09 +* XTtcPs_GetPrescaler : 1.00 +* XTtcPs_CalcIntervalFromFreq : 1.29 +* XTtcPs_SetOptions: 1.91 +* XTtcPs_GetOptions: 2.55 +* XTtcPs_SelfTest: .85 +* +* Assumptions of Use + +* 1.The default setting for a timer/counter is: +* - Overflow Mode +* - Internal clock (pclk) selected +* - Counter disabled +* - All Interrupts disabled +* - Output waveforms disabled +* +* Compiler Name +* +* gcc +* +* Compiler version +* +* 8.2.0 +* +* Compiler options +* +* -DARMR5 -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-r5 -mfloat-abi=hard -mfpu=vfpv3-d16 -I +* -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a72 -I +* -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -I +* +* User Defined data types +* +* u8 1 byte +* u16 2 bytes +* u32 4 bytes / 1 word +* u64 8 bytes / double word +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------------
+* 1.00a drg/jz 01/20/10 First release..
+* 2.0   adk    12/10/13 Updated as per the New Tcl API's
+* 3.0	pkp    12/09/14 Added support for Zynq Ultrascale Mp.Also code
+*			modified for MISRA-C:2012 compliance.
+* 3.2   mus    10/28/16 Modified XTtcPs_GetCounterValue and XTtcPs_SetInterval
+*                       macros to return 32 bit values for zynq ultrascale+mpsoc
+*       ms   01/23/17 Modified xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 3.4   ms   04/18/17 Modified tcl file to add suffix U for all macros
+*                     definitions of ttcps in xparameters.h
+* 3.5   srm  10/06/17 Added new typedef XMatchRegValue for match register width
+* 3.8   aru  12/19/18 Modified in XTtcPs_ClearInterruptStatus function to clear
+*                     Interrupt status register by reading instead of writing it.
+* 3.14   mus 02/22/21 Updated XTtcPs_ClearInterruptStatus to fix compiler warning.
+*                     It fixes CR#1084697.
+* 3.16  adk  04/19/22 Fix infinite loop in the examples by adding polled
+* 		      timeout loop.
+* 
+* +******************************************************************************/ + +#ifndef XTTCPS_H /* prevent circular inclusions */ +#define XTTCPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xttcps_hw.h" +#include "xstatus.h" + +/*****************************************************************************/ +typedef void (*XTtcPs_StatusHandler) (const void *CallBackRef, u32 StatusEvent); + + +/************************** Constant Definitions *****************************/ + + +/* + * Maximum Value for interval counter + */ + #if defined(ARMA9) + #define XTTCPS_MAX_INTERVAL_COUNT 0xFFFFU + #else + #define XTTCPS_MAX_INTERVAL_COUNT 0xFFFFFFFFU + #endif + +/** @name Configuration options + * + * Options for the device. Each of the options is bit field, so more than one + * options can be specified. + * + * @{ + */ +#define XTTCPS_OPTION_EXTERNAL_CLK 0x00000001U /**< External clock source */ +#define XTTCPS_OPTION_CLK_EDGE_NEG 0x00000002U /**< Clock on trailing edge for + external clock*/ +#define XTTCPS_OPTION_INTERVAL_MODE 0x00000004U /**< Interval mode */ +#define XTTCPS_OPTION_DECREMENT 0x00000008U /**< Decrement the counter */ +#define XTTCPS_OPTION_MATCH_MODE 0x00000010U /**< Match mode */ +#define XTTCPS_OPTION_WAVE_DISABLE 0x00000020U /**< No waveform output */ +#define XTTCPS_OPTION_WAVE_POLARITY 0x00000040U /**< Waveform polarity */ +/*@}*/ +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID for device */ + u32 BaseAddress; /**< Base address for device */ + u32 InputClockHz; /**< Input clock frequency */ +#ifdef XIL_INTERRUPT + u16 IntrId; + UINTPTR IntrParent; /** Bit[0] Interrupt parent type Bit[64/32:1] Parent base address */ +#endif +} XTtcPs_Config; + +/** + * The XTtcPs driver instance data. The user is required to allocate a + * variable of this type for each PS timer/counter device in the system. A + * pointer to a variable of this type is then passed to various driver API + * functions. + */ +typedef struct { + XTtcPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + XTtcPs_StatusHandler StatusHandler; + void *StatusRef; /**< Callback reference for status handler */ +} XTtcPs; + +/** + * This typedef contains interval count and Match register value + */ +#if defined(ARMA9) +typedef u16 XInterval; +typedef u16 XMatchRegValue; +#else +typedef u32 XInterval; +typedef u32 XMatchRegValue; +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/* + * Internal helper macros + */ +#define InstReadReg(InstancePtr, RegOffset) \ + (Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)(RegOffset))) + +#define InstWriteReg(InstancePtr, RegOffset, Data) \ + (Xil_Out32(((InstancePtr)->Config.BaseAddress) + (u32)(RegOffset), (u32)(Data))) + +/*****************************************************************************/ +/** +* +* This function starts the counter/timer without resetting the counter value. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return None +* +* @note C-style signature: +* void XTtcPs_Start(XTtcPs *InstancePtr) +* +****************************************************************************/ +#define XTtcPs_Start(InstancePtr) \ + InstWriteReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET, \ + (InstReadReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET) & \ + ~XTTCPS_CNT_CNTRL_DIS_MASK)) + +/*****************************************************************************/ +/** +* +* This function stops the counter/timer. This macro may be called at any time +* to stop the counter. The counter holds the last value until it is reset, +* restarted or enabled. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return None +* +* @note C-style signature: +* void XTtcPs_Stop(XTtcPs *InstancePtr) +* +****************************************************************************/ +#define XTtcPs_Stop(InstancePtr) \ + InstWriteReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET, \ + (InstReadReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET) | \ + XTTCPS_CNT_CNTRL_DIS_MASK)) + +/*****************************************************************************/ +/** +* +* This function checks whether the timer counter has already started. +* +* @param InstancePtr is a pointer to the XTtcPs instance +* +* @return Non-zero if the device has started, '0' otherwise. +* +* @note C-style signature: +* int XTtcPs_IsStarted(XTtcPs *InstancePtr) +* +****************************************************************************/ +#define XTtcPs_IsStarted(InstancePtr) \ + ((InstReadReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET) & \ + XTTCPS_CNT_CNTRL_DIS_MASK) == 0U) + +/*****************************************************************************/ +/** +* +* This function returns the current 16-bit counter value. It may be called at +* any time. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return zynq:16 bit counter value. +* zynq ultrascale+mpsoc:32 bit counter value. +* +* @note C-style signature: +* zynq: u16 XTtcPs_GetCounterValue(XTtcPs *InstancePtr) +* zynq ultrascale+mpsoc: u32 XTtcPs_GetCounterValue(XTtcPs *InstancePtr) +* +****************************************************************************/ +#if defined(ARMA9) +/* + * ttc supports 16 bit counter for zynq + */ +#define XTtcPs_GetCounterValue(InstancePtr) \ + (u16)InstReadReg((InstancePtr), XTTCPS_COUNT_VALUE_OFFSET) +#else +/* + * ttc supports 32 bit counter for zynq ultrascale+mpsoc + */ +#define XTtcPs_GetCounterValue(InstancePtr) \ + InstReadReg((InstancePtr), XTTCPS_COUNT_VALUE_OFFSET) +#endif + +/*****************************************************************************/ +/** +* +* This function sets the interval value to be used in interval mode. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param Value is the 16-bit value to be set in the interval register. +* +* @return None +* +* @note C-style signature: +* void XTtcPs_SetInterval(XTtcPs *InstancePtr, XInterval Value) +* +****************************************************************************/ +#define XTtcPs_SetInterval(InstancePtr, Value) \ + InstWriteReg((InstancePtr), XTTCPS_INTERVAL_VAL_OFFSET, (Value)) + +/*****************************************************************************/ +/** +* +* This function gets the interval value from the interval register. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return zynq:16 bit interval value. +* zynq ultrascale+mpsoc:32 bit interval value. +* +* @note C-style signature: +* zynq: u16 XTtcPs_GetInterval(XTtcPs *InstancePtr) +* zynq ultrascale+mpsoc: u32 XTtcPs_GetInterval(XTtcPs *InstancePtr) +* +****************************************************************************/ +#if defined(ARMA9) +/* + * ttc supports 16 bit interval counter for zynq + */ +#define XTtcPs_GetInterval(InstancePtr) \ + (u16)InstReadReg((InstancePtr), XTTCPS_INTERVAL_VAL_OFFSET) +#else +/* + * ttc supports 32 bit interval counter for zynq ultrascale+mpsoc + */ +#define XTtcPs_GetInterval(InstancePtr) \ + InstReadReg((InstancePtr), XTTCPS_INTERVAL_VAL_OFFSET) +#endif +/*****************************************************************************/ +/** +* +* This macro resets the count register. It may be called at any time. The +* counter is reset to either 0 or 0xFFFF, or the interval value, depending on +* the increment/decrement mode. The state of the counter, as started or +* stopped, is not affected by calling reset. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return None +* +* @note C-style signature: +* void XTtcPs_ResetCounterValue(XTtcPs *InstancePtr) +* +****************************************************************************/ +#define XTtcPs_ResetCounterValue(InstancePtr) \ + InstWriteReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET, \ + (InstReadReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET) | \ + (u32)XTTCPS_CNT_CNTRL_RST_MASK)) + +/*****************************************************************************/ +/** +* +* This function enables the interrupts. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param InterruptMask defines which interrupt should be enabled. +* Constants are defined in xttcps_hw.h as XTTCPS_IXR_*. +* This is a bit mask, all set bits will be enabled, cleared bits +* will not be disabled. +* +* @return None. +* +* @note +* C-style signature: +* void XTtcPs_EnableInterrupts(XTtcPs *InstancePtr, u32 InterruptMask) +* +******************************************************************************/ +#define XTtcPs_EnableInterrupts(InstancePtr, InterruptMask) \ + InstWriteReg((InstancePtr), XTTCPS_IER_OFFSET, \ + (InstReadReg((InstancePtr), XTTCPS_IER_OFFSET) | \ + (InterruptMask))) + +/*****************************************************************************/ +/** +* +* This function disables the interrupts. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param InterruptMask defines which interrupt should be disabled. +* Constants are defined in xttcps_hw.h as XTTCPS_IXR_*. +* This is a bit mask, all set bits will be disabled, cleared bits +* will not be disabled. +* +* @return None. +* +* @note +* C-style signature: +* void XTtcPs_DisableInterrupts(XTtcPs *InstancePtr, u32 InterruptMask) +* +******************************************************************************/ +#define XTtcPs_DisableInterrupts(InstancePtr, InterruptMask) \ + InstWriteReg((InstancePtr), XTTCPS_IER_OFFSET, \ + (InstReadReg((InstancePtr), XTTCPS_IER_OFFSET) & \ + ~(InterruptMask))) + +/*****************************************************************************/ +/** +* +* This function reads the interrupt status. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return None. +* +* @note C-style signature: +* u32 XTtcPs_GetInterruptStatus(XTtcPs *InstancePtr) +* +******************************************************************************/ +#define XTtcPs_GetInterruptStatus(InstancePtr) \ + InstReadReg((InstancePtr), XTTCPS_ISR_OFFSET) + +/*****************************************************************************/ +/** +* +* This function clears the interrupt status. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param InterruptMask defines which interrupt should be cleared. +* Constants are defined in xttcps_hw.h as XTTCPS_IXR_*. +* This is a bit mask, all set bits will be cleared, cleared bits +* will not be cleared. +* +* @return None. +* +* @note +* C-style signature: +* void XTtcPs_ClearInterruptStatus(XTtcPs *InstancePtr, u32 InterruptMask) +* +******************************************************************************/ +#define XTtcPs_ClearInterruptStatus(InstancePtr, InterruptMask) \ + (void) InterruptMask; \ + InstReadReg((InstancePtr), XTTCPS_ISR_OFFSET) + + +/************************** Function Prototypes ******************************/ + +/* + * Initialization functions in xttcps_sinit.c + */ +XTtcPs_Config *XTtcPs_LookupConfig(u16 DeviceId); + +/* + * Required functions, in xttcps.c + */ +s32 XTtcPs_CfgInitialize(XTtcPs *InstancePtr, + XTtcPs_Config * ConfigPtr, u32 EffectiveAddr); + +void XTtcPs_SetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex, XMatchRegValue Value); +XMatchRegValue XTtcPs_GetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex); + +void XTtcPs_SetPrescaler(XTtcPs *InstancePtr, u8 PrescalerValue); +u8 XTtcPs_GetPrescaler(XTtcPs *InstancePtr); + +void XTtcPs_CalcIntervalFromFreq(XTtcPs *InstancePtr, u32 Freq, + XInterval *Interval, u8 *Prescaler); + +/* + * Functions for options, in file xttcps_options.c + */ +s32 XTtcPs_SetOptions(XTtcPs *InstancePtr, u32 Options); +u32 XTtcPs_GetOptions(XTtcPs *InstancePtr); + +/* + * Function for self-test, in file xttcps_selftest.c + */ +s32 XTtcPs_SelfTest(XTtcPs *InstancePtr); +u32 XTtcPs_InterruptHandler(XTtcPs *InstancePtr); +void XTtcPs_SetStatusHandler(XTtcPs *InstancePtr, void *CallBackRef, + XTtcPs_StatusHandler FuncPointer); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xttcps_hw.h b/bsp_z7/ps7_cortexa9_0/include/xttcps_hw.h new file mode 100644 index 0000000..64354a3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xttcps_hw.h @@ -0,0 +1,208 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xttcps_hw.h +* @addtogroup ttcps Overview +* @{ +* +* This file defines the hardware interface to one of the three timer counters +* in the Ps block. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -------------------------------------------------
+* 1.00a drg/jz 01/21/10 First release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.5   srm    10/06/17 Updated XTTCPS_COUNT_VALUE_MASK,
+*                       XTTCPS_INTERVAL_VAL_MASK, XTTCPS_MATCH_MASK macros to
+*                       mask 16 bit values for zynq and 32 bit values for
+*                       zynq ultrascale+mpsoc "
+* 
+* +******************************************************************************/ + +#ifndef XTTCPS_HW_H /* prevent circular inclusions */ +#define XTTCPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ +/* + * Flag for a9 processor + */ + #if !defined (ARMR5) && !defined (__aarch64__) && !defined (ARMA53_32) + #define ARMA9 + #endif + +/** @name Register Map + * + * Register offsets from the base address of the device. + * + * @{ + */ +#define XTTCPS_CLK_CNTRL_OFFSET 0x00000000U /**< Clock Control Register */ +#define XTTCPS_CNT_CNTRL_OFFSET 0x0000000CU /**< Counter Control Register*/ +#define XTTCPS_COUNT_VALUE_OFFSET 0x00000018U /**< Current Counter Value */ +#define XTTCPS_INTERVAL_VAL_OFFSET 0x00000024U /**< Interval Count Value */ +#define XTTCPS_MATCH_0_OFFSET 0x00000030U /**< Match 1 value */ +#define XTTCPS_MATCH_1_OFFSET 0x0000003CU /**< Match 2 value */ +#define XTTCPS_MATCH_2_OFFSET 0x00000048U /**< Match 3 value */ +#define XTTCPS_ISR_OFFSET 0x00000054U /**< Interrupt Status Register */ +#define XTTCPS_IER_OFFSET 0x00000060U /**< Interrupt Enable Register */ +/* @} */ + +/** @name Clock Control Register + * Clock Control Register definitions + * @{ + */ +#define XTTCPS_CLK_CNTRL_PS_EN_MASK 0x00000001U /**< Prescale enable */ +#define XTTCPS_CLK_CNTRL_PS_VAL_MASK 0x0000001EU /**< Prescale value */ +#define XTTCPS_CLK_CNTRL_PS_VAL_SHIFT 1U /**< Prescale shift */ +#define XTTCPS_CLK_CNTRL_PS_DISABLE 16U /**< Prescale disable */ +#define XTTCPS_CLK_CNTRL_SRC_MASK 0x00000020U /**< Clock source */ +#define XTTCPS_CLK_CNTRL_EXT_EDGE_MASK 0x00000040U /**< External Clock edge */ +/* @} */ + +/** @name Counter Control Register + * Counter Control Register definitions + * @{ + */ +#define XTTCPS_CNT_CNTRL_DIS_MASK 0x00000001U /**< Disable the counter */ +#define XTTCPS_CNT_CNTRL_INT_MASK 0x00000002U /**< Interval mode */ +#define XTTCPS_CNT_CNTRL_DECR_MASK 0x00000004U /**< Decrement mode */ +#define XTTCPS_CNT_CNTRL_MATCH_MASK 0x00000008U /**< Match mode */ +#define XTTCPS_CNT_CNTRL_RST_MASK 0x00000010U /**< Reset counter */ +#define XTTCPS_CNT_CNTRL_EN_WAVE_MASK 0x00000020U /**< Enable waveform */ +#define XTTCPS_CNT_CNTRL_POL_WAVE_MASK 0x00000040U /**< Waveform polarity */ +#define XTTCPS_CNT_CNTRL_RESET_VALUE 0x00000021U /**< Reset value */ +/* @} */ + +/** @name Current Counter Value Register + * Current Counter Value Register definitions + * @{ + */ +#if defined(ARMA9) +#define XTTCPS_COUNT_VALUE_MASK 0x0000FFFFU /**< 16-bit counter value */ +#else +#define XTTCPS_COUNT_VALUE_MASK 0xFFFFFFFFU /**< 32-bit counter value */ +#endif +/* @} */ + +/** @name Interval Value Register + * Interval Value Register is the maximum value the counter will count up or + * down to. + * @{ + */ +#if defined(ARMA9) +#define XTTCPS_INTERVAL_VAL_MASK 0x0000FFFFU /**< 16-bit Interval value*/ +#else +#define XTTCPS_INTERVAL_VAL_MASK 0xFFFFFFFFU /**< 32-bit Interval value*/ +#endif +/* @} */ + +/** @name Match Registers + * Definitions for Match registers, each timer counter has three match + * registers. + * @{ + */ +#if defined(ARMA9) +#define XTTCPS_MATCH_MASK 0x0000FFFFU /**< 16-bit Match value */ +#else +#define XTTCPS_MATCH_MASK 0xFFFFFFFFU /**< 32-bit Match value */ +#endif +#define XTTCPS_NUM_MATCH_REG 3U /**< Num of Match reg */ +/* @} */ + +/** @name Interrupt Registers + * Following register bit mask is for all interrupt registers. + * + * @{ + */ +#define XTTCPS_IXR_INTERVAL_MASK 0x00000001U /**< Interval Interrupt */ +#define XTTCPS_IXR_MATCH_0_MASK 0x00000002U /**< Match 1 Interrupt */ +#define XTTCPS_IXR_MATCH_1_MASK 0x00000004U /**< Match 2 Interrupt */ +#define XTTCPS_IXR_MATCH_2_MASK 0x00000008U /**< Match 3 Interrupt */ +#define XTTCPS_IXR_CNT_OVR_MASK 0x00000010U /**< Counter Overflow */ +#define XTTCPS_IXR_ALL_MASK 0x0000001FU /**< All valid Interrupts */ +/* @} */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given Timer Counter register. +* +* @param BaseAddress is the base address of the timer counter device. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XTtcPs_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XTtcPs_ReadReg(BaseAddress, RegOffset) \ + (Xil_In32((BaseAddress) + (u32)(RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given Timer Counter register. +* +* @param BaseAddress is the base address of the timer counter device. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XTtcPs_WriteReg(XTtcPs BaseAddress, u32 RegOffset, +* u32 Data) +* +*****************************************************************************/ +#define XTtcPs_WriteReg(BaseAddress, RegOffset, Data) \ + (Xil_Out32((BaseAddress) + (u32)(RegOffset), (u32)(Data))) + +/****************************************************************************/ +/** +* +* Calculate a match register offset using the Match Register index. +* +* @param MatchIndex is the 0-2 value of the match register +* +* @return MATCH_N_OFFSET. +* +* @note C-style signature: +* u32 XTtcPs_Match_N_Offset(u8 MatchIndex) +* +*****************************************************************************/ +#define XTtcPs_Match_N_Offset(MatchIndex) \ + ((u32)XTTCPS_MATCH_0_OFFSET + ((u32)(12U) * (u32)(MatchIndex))) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +#ifdef __cplusplus +} +#endif +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xuartps.h b/bsp_z7/ps7_cortexa9_0/include/xuartps.h new file mode 100644 index 0000000..20dd99f --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xuartps.h @@ -0,0 +1,508 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xuartps.h +* @addtogroup uartps Overview +* @{ +* @details +* +* This driver supports the following features: +* +* - Dynamic data format (baud rate, data bits, stop bits, parity) +* - Polled mode +* - Interrupt driven mode +* - Transmit and receive FIFOs (32 byte FIFO depth) +* - Access to the external modem control lines +* +* Initialization & Configuration +* +* The XUartPs_Config structure is used by the driver to configure itself. +* Fields inside this structure are properties of XUartPs based on its hardware +* build. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized in the +* following way: +* +* - XUartPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the parameter EffectiveAddr should be the +* virtual address. +* +* Baud Rate +* +* The UART has an internal baud rate generator, which furnishes the baud rate +* clock for both the receiver and the transmitter. The input clock frequency +* can be either the master clock or the master clock divided by 8, configured +* through the mode register. +* +* Accompanied with the baud rate divider register, the baud rate is determined +* by: +*
+*	baud_rate = input_clock / (bgen * (bdiv + 1)
+* 
+* where bgen is the value of the baud rate generator, and bdiv is the value of +* baud rate divider. +* +* Interrupts +* +* The FIFOs are not flushed when the driver is initialized, but a function is +* provided to allow the user to reset the FIFOs if desired. +* +* The driver defaults to no interrupts at initialization such that interrupts +* must be enabled if desired. An interrupt is generated for one of the +* following conditions. +* +* - A change in the modem signals +* - Data in the receive FIFO for a configuable time without receiver activity +* - A parity error +* - A framing error +* - An overrun error +* - Transmit FIFO is full +* - Transmit FIFO is empty +* - Receive FIFO is full +* - Receive FIFO is empty +* - Data in the receive FIFO equal to the receive threshold +* +* The application can control which interrupts are enabled using the +* XUartPs_SetInterruptMask() function. +* +* In order to use interrupts, it is necessary for the user to connect the +* driver interrupt handler, XUartPs_InterruptHandler(), to the interrupt +* system of the application. A separate handler should be provided by the +* application to communicate with the interrupt system, and conduct +* application specific interrupt handling. An application registers its own +* handler through the XUartPs_SetHandler() function. +* +* Data Transfer +* +* The functions, XUartPs_Send() and XUartPs_Recv(), are provided in the +* driver to allow data to be sent and received. They can be used in either +* polled or interrupt mode. +* +* @note +* +* The default configuration for the UART after initialization is: +* +* - 9,600 bps or XPAR_DFT_BAUDRATE if defined +* - 8 data bits +* - 1 stop bit +* - no parity +* - FIFO's are enabled with a receive threshold of 8 bytes +* - The RX timeout is enabled with a timeout of 1 (4 char times) +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00a	drg/jz 01/12/10 First Release
+* 1.00a sdm    09/27/11 Fixed compiler warnings and also a bug
+*		        in XUartPs_SetFlowDelay where the value was not
+*			being written to the register.
+* 1.01a sdm    12/20/11 Removed the InputClockHz parameter from the XUartPs
+*			instance structure and the driver is updated to use
+*			InputClockHz parameter from the XUartPs_Config config
+*			structure.
+*			Added a parameter to XUartPs_Config structure which
+*			specifies whether the user has selected Modem pins
+*			to be connected to MIO or FMIO.
+*			Added the tcl file to generate the xparameters.h
+* 1.02a sg     05/16/12	Changed XUARTPS_RXWM_MASK to 0x3F for CR 652540 fix.
+* 1.03a sg     07/16/12 Updated XUARTPS_FORMAT_7_BITS and XUARTPS_FORMAT_6_BITS
+*			with the correct values for CR 666724
+* 			Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the name of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added API for uart reset and related
+*			constant definitions.
+* 2.0   hk      03/07/14 Version number revised.
+* 2.1   hk     04/16/14 Change XUARTPS_MAX_RATE to 921600. CR# 780625.
+* 2.2   hk     06/23/14 SW reset of RX and TX should be done when changing
+*                       baud rate. CR# 804281.
+* 3.0   vm     12/09/14 Modified source code according to misrac guideline.
+*			Support for Zynq Ultrascale Mp added.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes. Also added
+*						platform variable in driver instance structure.
+* 3.1   adk   14/03/16  Include interrupt examples in the peripheral test when
+*			uart is connected to a valid interrupt controller CR#946803.
+* 3.2   rk     07/20/16 Modified the logic for transmission break bit set
+* 3.4   ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 3.6   ms     02/16/18 Updates the flow control mode offset value in modem
+*                       control register.
+* 3.7   aru    08/17/18 Resolved MISRA-C:2012 compliance mandatory violations.
+* 3.9   rna    12/03/19 Modified the XUARTPS_MAX_RATE macro.
+* 3.9   sd     02/06/20 Added clock support
+* 3.12	gm     11/04/22 Added timeout support using Xil_WaitForEvent
+*
+* 
+* +*****************************************************************************/ + +#ifndef XUARTPS_H /* prevent circular inclusions */ +#define XUARTPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xuartps_hw.h" +#include "xplatform_info.h" +#if defined (XCLOCKING) +#include "xil_clocking.h" +#endif +#include "xil_util.h" + +/************************** Constant Definitions ****************************/ + +/* + * The following constants indicate the max and min baud rates and these + * numbers are based only on the testing that has been done. The hardware + * is capable of other baud rates. + */ +#define XUARTPS_MAX_RATE 6240000U +#define XUARTPS_MIN_RATE 110U + +#define XUARTPS_DFT_BAUDRATE 115200U /* Default baud rate */ + +/** @name Configuration options + * @{ + */ +/** + * These constants specify the options that may be set or retrieved + * with the driver, each is a unique bit mask such that multiple options + * may be specified. These constants indicate the available options + * in active state. + * + */ + +#define XUARTPS_OPTION_SET_BREAK 0x0080U /**< Starts break transmission */ +#define XUARTPS_OPTION_STOP_BREAK 0x0040U /**< Stops break transmission */ +#define XUARTPS_OPTION_RESET_TMOUT 0x0020U /**< Reset the receive timeout */ +#define XUARTPS_OPTION_RESET_TX 0x0010U /**< Reset the transmitter */ +#define XUARTPS_OPTION_RESET_RX 0x0008U /**< Reset the receiver */ +#define XUARTPS_OPTION_ASSERT_RTS 0x0004U /**< Assert the RTS bit */ +#define XUARTPS_OPTION_ASSERT_DTR 0x0002U /**< Assert the DTR bit */ +#define XUARTPS_OPTION_SET_FCM 0x0001U /**< Turn on flow control mode */ +/*@}*/ + + +/** @name Channel Operational Mode + * + * The UART can operate in one of four modes: Normal, Local Loopback, Remote + * Loopback, or automatic echo. + * + * @{ + */ + +#define XUARTPS_OPER_MODE_NORMAL (u8)0x00U /**< Normal Mode */ +#define XUARTPS_OPER_MODE_AUTO_ECHO (u8)0x01U /**< Auto Echo Mode */ +#define XUARTPS_OPER_MODE_LOCAL_LOOP (u8)0x02U /**< Local Loopback Mode */ +#define XUARTPS_OPER_MODE_REMOTE_LOOP (u8)0x03U /**< Remote Loopback Mode */ + +/* @} */ + +/** @name Data format values + * + * These constants specify the data format that the driver supports. + * The data format includes the number of data bits, the number of stop + * bits and parity. + * + * @{ + */ +#define XUARTPS_FORMAT_8_BITS 0U /**< 8 data bits */ +#define XUARTPS_FORMAT_7_BITS 2U /**< 7 data bits */ +#define XUARTPS_FORMAT_6_BITS 3U /**< 6 data bits */ + +#define XUARTPS_FORMAT_NO_PARITY 4U /**< No parity */ +#define XUARTPS_FORMAT_MARK_PARITY 3U /**< Mark parity */ +#define XUARTPS_FORMAT_SPACE_PARITY 2U /**< parity */ +#define XUARTPS_FORMAT_ODD_PARITY 1U /**< Odd parity */ +#define XUARTPS_FORMAT_EVEN_PARITY 0U /**< Even parity */ + +#define XUARTPS_FORMAT_2_STOP_BIT 2U /**< 2 stop bits */ +#define XUARTPS_FORMAT_1_5_STOP_BIT 1U /**< 1.5 stop bits */ +#define XUARTPS_FORMAT_1_STOP_BIT 0U /**< 1 stop bit */ +/*@}*/ + +/** @name Callback events + * + * These constants specify the handler events that an application can handle + * using its specific handler function. Note that these constants are not bit + * mask, so only one event can be passed to an application at a time. + * + * @{ + */ +#define XUARTPS_EVENT_RECV_DATA 1U /**< Data receiving done */ +#define XUARTPS_EVENT_RECV_TOUT 2U /**< A receive timeout occurred */ +#define XUARTPS_EVENT_SENT_DATA 3U /**< Data transmission done */ +#define XUARTPS_EVENT_RECV_ERROR 4U /**< A receive error detected */ +#define XUARTPS_EVENT_MODEM 5U /**< Modem status changed */ +#define XUARTPS_EVENT_PARE_FRAME_BRKE 6U /**< A receive parity, frame, break + * error detected */ +#define XUARTPS_EVENT_RECV_ORERR 7U /**< A receive overrun error detected */ + +/*@}*/ + +#define TIMEOUT_VAL 1000000U /**< Wait for 1 sec in worst case */ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ + u32 InputClockHz;/**< Input clock frequency */ + s32 ModemPinsConnected; /** Specifies whether modem pins are connected + * to MIO or FMIO */ +#if defined (XCLOCKING) + u32 RefClk; /**< Input clock frequency */ +#endif +} XUartPs_Config; + +/* Keep track of state information about a data buffer in the interrupt mode. */ +typedef struct { + u8 *NextBytePtr; + u32 RequestedBytes; + u32 RemainingBytes; +} XUartPsBuffer; + +/** + * Keep track of data format setting of a device. + */ +typedef struct { + u32 BaudRate; /**< In bps, ie 1200 */ + u32 DataBits; /**< Number of data bits */ + u32 Parity; /**< Parity */ + u8 StopBits; /**< Number of stop bits */ +} XUartPsFormat; + +/******************************************************************************/ +/** + * This data type defines a handler that an application defines to communicate + * with interrupt system to retrieve state information about an application. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the handler, and is passed back to the upper layer + * when the handler is called. It is used to find the device driver + * instance. + * @param Event contains one of the event constants indicating events that + * have occurred. + * @param EventData contains the number of bytes sent or received at the + * time of the call for send and receive events and contains the + * modem status for modem events. + * + ******************************************************************************/ +typedef void (*XUartPs_Handler) (void *CallBackRef, u32 Event, + u32 EventData); + +/** + * The XUartPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XUartPs_Config Config; /* Configuration data structure */ + u32 InputClockHz; /* Input clock frequency */ + u32 IsReady; /* Device is initialized and ready */ + u32 BaudRate; /* Current baud rate */ + + XUartPsBuffer SendBuffer; + XUartPsBuffer ReceiveBuffer; + + XUartPs_Handler Handler; + void *CallBackRef; /* Callback reference for event handler */ + u32 Platform; + u8 is_rxbs_error; +} XUartPs; + + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* Get the UART Channel Status Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u16 XUartPs_GetChannelStatus(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetChannelStatus(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) + +/****************************************************************************/ +/** +* Get the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_GetControl(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetModeControl(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET) + +/****************************************************************************/ +/** +* Set the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_SetModeControl(XUartPs *InstancePtr, u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_SetModeControl(InstancePtr, RegisterValue) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET, \ + (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Enable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_EnableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_EnableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + ((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_EN | (u32)XUARTPS_CR_TX_EN))) + +/****************************************************************************/ +/** +* Disable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_DisableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_DisableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + (((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET)) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS))) + +/****************************************************************************/ +/** +* Determine if the transmitter FIFO is empty. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* - TRUE if a byte can be sent +* - FALSE if the Transmitter Fifo is not empty +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitEmpty(XUartPs InstancePtr) +* +******************************************************************************/ +#define XUartPs_IsTransmitEmpty(InstancePtr) \ + ((Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXEMPTY) == (u32)XUARTPS_SR_TXEMPTY) + + +/************************** Function Prototypes *****************************/ + +/* Static lookup function implemented in xuartps_sinit.c */ +XUartPs_Config *XUartPs_LookupConfig(u16 DeviceId); + +/* Interface functions implemented in xuartps.c */ +s32 XUartPs_CfgInitialize(XUartPs *InstancePtr, + XUartPs_Config * Config, u32 EffectiveAddr); + +u32 XUartPs_Send(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +u32 XUartPs_Recv(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate); + +/* Options functions in xuartps_options.c */ +void XUartPs_SetOptions(XUartPs *InstancePtr, u16 Options); + +u16 XUartPs_GetOptions(XUartPs *InstancePtr); + +void XUartPs_SetFifoThreshold(XUartPs *InstancePtr, u8 TriggerLevel); + +u8 XUartPs_GetFifoThreshold(XUartPs *InstancePtr); + +u16 XUartPs_GetModemStatus(XUartPs *InstancePtr); + +u32 XUartPs_IsSending(XUartPs *InstancePtr); + +u8 XUartPs_GetOperMode(XUartPs *InstancePtr); + +void XUartPs_SetOperMode(XUartPs *InstancePtr, u8 OperationMode); + +u8 XUartPs_GetFlowDelay(XUartPs *InstancePtr); + +void XUartPs_SetFlowDelay(XUartPs *InstancePtr, u8 FlowDelayValue); + +u8 XUartPs_GetRecvTimeout(XUartPs *InstancePtr); + +void XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout); + +s32 XUartPs_SetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +void XUartPs_GetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +/* interrupt functions in xuartps_intr.c */ +u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr); + +void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask); + +void XUartPs_InterruptHandler(XUartPs *InstancePtr); + +void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr, + void *CallBackRef); + +/* self-test functions in xuartps_selftest.c */ +s32 XUartPs_SelfTest(XUartPs *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xuartps_hw.h b/bsp_z7/ps7_cortexa9_0/include/xuartps_hw.h new file mode 100644 index 0000000..59d4ccf --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xuartps_hw.h @@ -0,0 +1,426 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xuartps_hw.h +* @addtogroup uartps Overview +* @{ +* +* This header file contains the hardware interface of an XUartPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/12/10 First Release
+* 1.03a sg     09/04/12 Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the names of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added prototype for uart reset and related
+*			constant definitions.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.6   ms     02/16/18 Updates flow control mode offset value in
+*			modem control register.
+*
+* 
+* +******************************************************************************/ +#ifndef XUARTPS_HW_H /* prevent circular inclusions */ +#define XUARTPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the UART. + * @{ + */ +#define XUARTPS_CR_OFFSET 0x0000U /**< Control Register [8:0] */ +#define XUARTPS_MR_OFFSET 0x0004U /**< Mode Register [9:0] */ +#define XUARTPS_IER_OFFSET 0x0008U /**< Interrupt Enable [12:0] */ +#define XUARTPS_IDR_OFFSET 0x000CU /**< Interrupt Disable [12:0] */ +#define XUARTPS_IMR_OFFSET 0x0010U /**< Interrupt Mask [12:0] */ +#define XUARTPS_ISR_OFFSET 0x0014U /**< Interrupt Status [12:0]*/ +#define XUARTPS_BAUDGEN_OFFSET 0x0018U /**< Baud Rate Generator [15:0] */ +#define XUARTPS_RXTOUT_OFFSET 0x001CU /**< RX Timeout [7:0] */ +#define XUARTPS_RXWM_OFFSET 0x0020U /**< RX FIFO Trigger Level [5:0] */ +#define XUARTPS_MODEMCR_OFFSET 0x0024U /**< Modem Control [5:0] */ +#define XUARTPS_MODEMSR_OFFSET 0x0028U /**< Modem Status [8:0] */ +#define XUARTPS_SR_OFFSET 0x002CU /**< Channel Status [14:0] */ +#define XUARTPS_FIFO_OFFSET 0x0030U /**< FIFO [7:0] */ +#define XUARTPS_BAUDDIV_OFFSET 0x0034U /**< Baud Rate Divider [7:0] */ +#define XUARTPS_FLOWDEL_OFFSET 0x0038U /**< Flow Delay [5:0] */ +#define XUARTPS_TXWM_OFFSET 0x0044U /**< TX FIFO Trigger Level [5:0] */ +#define XUARTPS_RXBS_OFFSET 0x0048U /**< RX FIFO Byte Status [11:0] */ +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +#define XUARTPS_CR_STOPBRK 0x00000100U /**< Stop transmission of break */ +#define XUARTPS_CR_STARTBRK 0x00000080U /**< Set break */ +#define XUARTPS_CR_TORST 0x00000040U /**< RX timeout counter restart */ +#define XUARTPS_CR_TX_DIS 0x00000020U /**< TX disabled. */ +#define XUARTPS_CR_TX_EN 0x00000010U /**< TX enabled */ +#define XUARTPS_CR_RX_DIS 0x00000008U /**< RX disabled. */ +#define XUARTPS_CR_RX_EN 0x00000004U /**< RX enabled */ +#define XUARTPS_CR_EN_DIS_MASK 0x0000003CU /**< Enable/disable Mask */ +#define XUARTPS_CR_TXRST 0x00000002U /**< TX logic reset */ +#define XUARTPS_CR_RXRST 0x00000001U /**< RX logic reset */ +/* @}*/ + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ +#define XUARTPS_MR_CCLK 0x00000400U /**< Input clock selection */ +#define XUARTPS_MR_CHMODE_R_LOOP 0x00000300U /**< Remote loopback mode */ +#define XUARTPS_MR_CHMODE_L_LOOP 0x00000200U /**< Local loopback mode */ +#define XUARTPS_MR_CHMODE_ECHO 0x00000100U /**< Auto echo mode */ +#define XUARTPS_MR_CHMODE_NORM 0x00000000U /**< Normal mode */ +#define XUARTPS_MR_CHMODE_SHIFT 8U /**< Mode shift */ +#define XUARTPS_MR_CHMODE_MASK 0x00000300U /**< Mode mask */ +#define XUARTPS_MR_STOPMODE_2_BIT 0x00000080U /**< 2 stop bits */ +#define XUARTPS_MR_STOPMODE_1_5_BIT 0x00000040U /**< 1.5 stop bits */ +#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000U /**< 1 stop bit */ +#define XUARTPS_MR_STOPMODE_SHIFT 6U /**< Stop bits shift */ +#define XUARTPS_MR_STOPMODE_MASK 0x000000A0U /**< Stop bits mask */ +#define XUARTPS_MR_PARITY_NONE 0x00000020U /**< No parity mode */ +#define XUARTPS_MR_PARITY_MARK 0x00000018U /**< Mark parity mode */ +#define XUARTPS_MR_PARITY_SPACE 0x00000010U /**< Space parity mode */ +#define XUARTPS_MR_PARITY_ODD 0x00000008U /**< Odd parity mode */ +#define XUARTPS_MR_PARITY_EVEN 0x00000000U /**< Even parity mode */ +#define XUARTPS_MR_PARITY_SHIFT 3U /**< Parity setting shift */ +#define XUARTPS_MR_PARITY_MASK 0x00000038U /**< Parity mask */ +#define XUARTPS_MR_CHARLEN_6_BIT 0x00000006U /**< 6 bits data */ +#define XUARTPS_MR_CHARLEN_7_BIT 0x00000004U /**< 7 bits data */ +#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000U /**< 8 bits data */ +#define XUARTPS_MR_CHARLEN_SHIFT 1U /**< Data Length shift */ +#define XUARTPS_MR_CHARLEN_MASK 0x00000006U /**< Data length mask */ +#define XUARTPS_MR_CLKSEL 0x00000001U /**< Input clock selection */ +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ +#define XUARTPS_IXR_RBRK 0x00002000U /**< Rx FIFO break detect interrupt */ +#define XUARTPS_IXR_TOVR 0x00001000U /**< Tx FIFO Overflow interrupt */ +#define XUARTPS_IXR_TNFUL 0x00000800U /**< Tx FIFO Nearly Full interrupt */ +#define XUARTPS_IXR_TTRIG 0x00000400U /**< Tx Trig interrupt */ +#define XUARTPS_IXR_DMS 0x00000200U /**< Modem status change interrupt */ +#define XUARTPS_IXR_TOUT 0x00000100U /**< Timeout error interrupt */ +#define XUARTPS_IXR_PARITY 0x00000080U /**< Parity error interrupt */ +#define XUARTPS_IXR_FRAMING 0x00000040U /**< Framing error interrupt */ +#define XUARTPS_IXR_OVER 0x00000020U /**< Overrun error interrupt */ +#define XUARTPS_IXR_TXFULL 0x00000010U /**< TX FIFO full interrupt. */ +#define XUARTPS_IXR_TXEMPTY 0x00000008U /**< TX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXFULL 0x00000004U /**< RX FIFO full interrupt. */ +#define XUARTPS_IXR_RXEMPTY 0x00000002U /**< RX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXOVR 0x00000001U /**< RX FIFO trigger interrupt. */ +#define XUARTPS_IXR_MASK 0x00003FFFU /**< Valid bit mask */ +/* @} */ + + +/** @name Baud Rate Generator Register + * + * The baud rate generator control register (BRGR) is a 16 bit register that + * controls the receiver bit sample clock and baud rate. + * Valid values are 1 - 65535. + * + * Bit Sample Rate = CCLK / BRGR, where the CCLK is selected by the MR_CCLK bit + * in the MR register. + * @{ + */ +#define XUARTPS_BAUDGEN_DISABLE 0x00000000U /**< Disable clock */ +#define XUARTPS_BAUDGEN_MASK 0x0000FFFFU /**< Valid bits mask */ +#define XUARTPS_BAUDGEN_RESET_VAL 0x0000028BU /**< Reset value */ + +/** @name Baud Divisor Rate register + * + * The baud rate divider register (BDIV) controls how much the bit sample + * rate is divided by. It sets the baud rate. + * Valid values are 0x04 to 0xFF. Writing a value less than 4 will be ignored. + * + * Baud rate = CCLK / ((BAUDDIV + 1) x BRGR), where the CCLK is selected by + * the MR_CCLK bit in the MR register. + * @{ + */ +#define XUARTPS_BAUDDIV_MASK 0x000000FFU /**< 8 bit baud divider mask */ +#define XUARTPS_BAUDDIV_RESET_VAL 0x0000000FU /**< Reset value */ +/* @} */ + + +/** @name Receiver Timeout Register + * + * Use the receiver timeout register (RTR) to detect an idle condition on + * the receiver data line. + * + * @{ + */ +#define XUARTPS_RXTOUT_DISABLE 0x00000000U /**< Disable time out */ +#define XUARTPS_RXTOUT_MASK 0x000000FFU /**< Valid bits mask */ + +/** @name Receiver FIFO Trigger Level Register + * + * Use the Receiver FIFO Trigger Level Register (RTRIG) to set the value at + * which the RX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_RXWM_DISABLE 0x00000000U /**< Disable RX trigger interrupt */ +#define XUARTPS_RXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_RXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Transmit FIFO Trigger Level Register + * + * Use the Transmit FIFO Trigger Level Register (TTRIG) to set the value at + * which the TX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_TXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_TXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Modem Control Register + * + * This register (MODEMCR) controls the interface with the modem or data set, + * or a peripheral device emulating a modem. + * + * @{ + */ +#define XUARTPS_MODEMCR_FCM 0x00000020U /**< Flow control mode */ +#define XUARTPS_MODEMCR_RTS 0x00000002U /**< Request to send */ +#define XUARTPS_MODEMCR_DTR 0x00000001U /**< Data terminal ready */ +/* @} */ + +/** @name Modem Status Register + * + * This register (MODEMSR) indicates the current state of the control lines + * from a modem, or another peripheral device, to the CPU. In addition, four + * bits of the modem status register provide change information. These bits + * are set to a logic 1 whenever a control input from the modem changes state. + * + * Note: Whenever the DCTS, DDSR, TERI, or DDCD bit is set to logic 1, a modem + * status interrupt is generated and this is reflected in the modem status + * register. + * + * @{ + */ +#define XUARTPS_MODEMSR_FCMS 0x00000100U /**< Flow control mode (FCMS) */ +#define XUARTPS_MODEMSR_DCD 0x00000080U /**< Complement of DCD input */ +#define XUARTPS_MODEMSR_RI 0x00000040U /**< Complement of RI input */ +#define XUARTPS_MODEMSR_DSR 0x00000020U /**< Complement of DSR input */ +#define XUARTPS_MODEMSR_CTS 0x00000010U /**< Complement of CTS input */ +#define XUARTPS_MODEMSR_DDCD 0x00000008U /**< Delta DCD indicator */ +#define XUARTPS_MODEMSR_TERI 0x00000004U /**< Trailing Edge Ring Indicator */ +#define XUARTPS_MODEMSR_DDSR 0x00000002U /**< Change of DSR */ +#define XUARTPS_MODEMSR_DCTS 0x00000001U /**< Change of CTS */ +/* @} */ + +/** @name Channel Status Register + * + * The channel status register (CSR) is provided to enable the control logic + * to monitor the status of bits in the channel interrupt status register, + * even if these are masked out by the interrupt mask register. + * + * @{ + */ +#define XUARTPS_SR_TNFUL 0x00004000U /**< TX FIFO Nearly Full Status */ +#define XUARTPS_SR_TTRIG 0x00002000U /**< TX FIFO Trigger Status */ +#define XUARTPS_SR_FLOWDEL 0x00001000U /**< RX FIFO fill over flow delay */ +#define XUARTPS_SR_TACTIVE 0x00000800U /**< TX active */ +#define XUARTPS_SR_RACTIVE 0x00000400U /**< RX active */ +#define XUARTPS_SR_TXFULL 0x00000010U /**< TX FIFO full */ +#define XUARTPS_SR_TXEMPTY 0x00000008U /**< TX FIFO empty */ +#define XUARTPS_SR_RXFULL 0x00000004U /**< RX FIFO full */ +#define XUARTPS_SR_RXEMPTY 0x00000002U /**< RX FIFO empty */ +#define XUARTPS_SR_RXOVR 0x00000001U /**< RX FIFO fill over trigger */ +/* @} */ + +/** @name Flow Delay Register + * + * Operation of the flow delay register (FLOWDEL) is very similar to the + * receive FIFO trigger register. An internal trigger signal activates when the + * FIFO is filled to the level set by this register. This trigger will not + * cause an interrupt, although it can be read through the channel status + * register. In hardware flow control mode, RTS is deactivated when the trigger + * becomes active. RTS only resets when the FIFO level is four less than the + * level of the flow delay trigger and the flow delay trigger is not activated. + * A value less than 4 disables the flow delay. + * @{ + */ +#define XUARTPS_FLOWDEL_MASK XUARTPS_RXWM_MASK /**< Valid bit mask */ +/* @} */ + +/** @name Receiver FIFO Byte Status Register + * + * The Receiver FIFO Status register is used to have a continuous + * monitoring of the raw unmasked byte status information. The register + * contains frame, parity and break status information for the top + * four bytes in the RX FIFO. + * + * Receiver FIFO Byte Status Register Bit Definition + * @{ + */ +#define XUARTPS_RXBS_BYTE3_BRKE 0x00000800U /**< Byte3 Break Error */ +#define XUARTPS_RXBS_BYTE3_FRME 0x00000400U /**< Byte3 Frame Error */ +#define XUARTPS_RXBS_BYTE3_PARE 0x00000200U /**< Byte3 Parity Error */ +#define XUARTPS_RXBS_BYTE2_BRKE 0x00000100U /**< Byte2 Break Error */ +#define XUARTPS_RXBS_BYTE2_FRME 0x00000080U /**< Byte2 Frame Error */ +#define XUARTPS_RXBS_BYTE2_PARE 0x00000040U /**< Byte2 Parity Error */ +#define XUARTPS_RXBS_BYTE1_BRKE 0x00000020U /**< Byte1 Break Error */ +#define XUARTPS_RXBS_BYTE1_FRME 0x00000010U /**< Byte1 Frame Error */ +#define XUARTPS_RXBS_BYTE1_PARE 0x00000008U /**< Byte1 Parity Error */ +#define XUARTPS_RXBS_BYTE0_BRKE 0x00000004U /**< Byte0 Break Error */ +#define XUARTPS_RXBS_BYTE0_FRME 0x00000002U /**< Byte0 Frame Error */ +#define XUARTPS_RXBS_BYTE0_PARE 0x00000001U /**< Byte0 Parity Error */ +#define XUARTPS_RXBS_MASK 0x00000007U /**< 3 bit RX byte status mask */ +/* @} */ + + +/* + * Defines for backwards compatibility, will be removed + * in the next version of the driver + */ +#define XUARTPS_MEDEMSR_DCDX XUARTPS_MODEMSR_DDCD +#define XUARTPS_MEDEMSR_RIX XUARTPS_MODEMSR_TERI +#define XUARTPS_MEDEMSR_DSRX XUARTPS_MODEMSR_DDSR +#define XUARTPS_MEDEMSR_CTSX XUARTPS_MODEMSR_DCTS + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* Read a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_ReadReg(u32 BaseAddress, int RegOffset) +* +******************************************************************************/ +#define XUartPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (u32)(RegOffset)) + +/***************************************************************************/ +/** +* Write a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_WriteReg(u32 BaseAddress, int RegOffset, +* u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (u32)(RegOffset), (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Determine if there is receive data in the receiver and/or FIFO. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if there is receive data, FALSE otherwise. +* +* @note C-Style signature: +* u32 XUartPs_IsReceiveData(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsReceiveData(BaseAddress) \ + !((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_RXEMPTY) == (u32)XUARTPS_SR_RXEMPTY) + +/****************************************************************************/ +/** +* Determine if a byte of data can be sent with the transmitter. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if the TX FIFO is full, FALSE if a byte can be put in the +* FIFO. +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitFull(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsTransmitFull(BaseAddress) \ + ((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXFULL) == (u32)XUARTPS_SR_TXFULL) + +/************************** Function Prototypes ******************************/ + +void XUartPs_SendByte(u32 BaseAddress, u8 Data); + +u8 XUartPs_RecvByte(u32 BaseAddress); + +void XUartPs_ResetHw(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xusbps.h b/bsp_z7/ps7_cortexa9_0/include/xusbps.h new file mode 100644 index 0000000..5c01051 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xusbps.h @@ -0,0 +1,1132 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xusbps.h +* @addtogroup usbps_v2_7 +* @{ +* @details + * + * This file contains the implementation of the XUsbPs driver. It is the + * driver for an USB controller in DEVICE or HOST mode. + * + *

Introduction

+ * + * The Spartan-3AF Embedded Peripheral Block contains a USB controller for + * communication with serial peripherals or hosts. The USB controller supports + * Host, Device and On the Go (OTG) applications. + * + *

USB Controller Features

+ * + * - Supports Low Speed USB 1.1 (1.5Mbps), Full Speed USB 1.1 (12Mbps), and + * High Speed USB 2.0 (480Mbps) data speeds + * - Supports Device, Host and OTG operational modes + * - ULPI transceiver interface for USB 2.0 operation + * - Integrated USB Full and Low speed serial transceiver interfaces for lowest + * cost connections + * + *

Initialization & Configuration

+ * + * The configuration of the USB driver happens in multiple stages: + * + * - (a) Configuration of the basic parameters: + * In this stage the basic parameters for the driver are configured, + * including the base address and the controller ID. + * + * - (b) Configuration of the DEVICE endpoints (if applicable): + * If DEVICE mode is desired, the endpoints of the controller need to be + * configured using the XUsbPs_DeviceConfig data structure. Once the + * endpoint configuration is set up in the data structure, The user then + * needs to allocate the required amount of DMAable memory and + * finalize the configuration of the XUsbPs_DeviceConfig data structure, + * e.g. setting the DMAMemVirt and DMAMemPhys members. + * + * - (c) Configuration of the DEVICE modes: + * In the second stage the parameters for DEVICE are configured. + * The caller only needs to configure the modes that are + * actually used. Configuration is done with the: + * XUsbPs_ConfigureDevice() + * Configuration parameters are defined and passed + * into these functions using the: + * XUsbPs_DeviceConfig data structures. + * + * + *

USB Device Endpoints

+ * + * The USB core supports up to 4 endpoints. Each endpoint has two directions, + * an OUT (RX) and an IN (TX) direction. Note that the direction is viewed from + * the host's perspective. Endpoint 0 defaults to be the control endpoint and + * does not need to be set up. Other endpoints need to be configured and set up + * depending on the application. Only endpoints that are actuelly used by the + * application need to be initialized. + * See the example code (xusbps_intr_example.c) for more information. + * + * + *

Interrupt Handling

+ * + * The USB core uses one interrupt line to report interrupts to the CPU. + * Interrupts are handled by the driver's interrupt handler function + * XUsbPs_IntrHandler(). + * It has to be registered with the OS's interrupt subsystem. The driver's + * interrupt handler divides incoming interrupts into two categories: + * + * - General device interrupts + * - Endopint related interrupts + * + * The user (typically the adapter layer) can register general interrupt + * handler functions and endpoint specific interrupt handler functions with the + * driver to receive those interrupts by calling the + * XUsbPs_IntrSetHandler() + * and + * XUsbPs_EpSetHandler() + * functions respectively. Calling these functions with a NULL pointer as the + * argument for the function pointer will "clear" the handler function. + * + * The user can register one handler function for the generic interrupts and + * two handler functions for each endpoint, one for the RX (OUT) and one for + * the TX (IN) direction. For some applications it may be useful to register a + * single endpoint handler function for muliple endpoints/directions. + * + * When a callback function is called by the driver, parameters identifying the + * type of the interrupt will be passed into the handler functions. For general + * interrupts the interrupt mask will be passed into the handler function. For + * endpoint interrupts the parameters include the number of the endpoint, the + * direction (OUT/IN) and the type of the interrupt. + * + * + *

Data buffer handling

+ * + * Data buffers are sent to and received from endpoint using the + * XUsbPs_EpBufferSend(), XUsbPs_EpBufferSendWithZLT() + * and + * XUsbPs_EpBufferReceive() + * functions. + * + * User data buffer size is limited to 16 Kbytes. If the user wants to send a + * data buffer that is bigger than this limit it needs to break down the data + * buffer into multiple fragments and send the fragments individually. + * + * From the controller perspective Data buffers can be aligned at any boundary. + * if the buffers are from cache region then the buffer and buffer size should + * be aligned to cache line aligned + * + * + *

Zero copy

+ * + * The driver uses a zero copy mechanism which imposes certain restrictions to + * the way the user can handle the data buffers. + * + * One restriction is that the user needs to release a buffer after it is done + * processing the data in the buffer. + * + * Similarly, when the user sends a data buffer it MUST not re-use the buffer + * until it is notified by the driver that the buffer has been transmitted. The + * driver will notify the user via the registered endpoint interrupt handling + * function by sending a XUSBPS_EP_EVENT_DATA_TX event. + * + * + *

DMA

+ * + * The driver uses DMA internally to move data from/to memory. This behaviour + * is transparent to the user. Keeping the DMA handling hidden from the user + * has the advantage that the same API can be used with USB cores that do not + * support DMA. + * + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- ----------------------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 1.02a wgr  05/16/12 Removed comments as they are showing up in SDK
+ *		       Tabs for CR 657898
+ * 1.03a nm   09/21/12 Fixed CR#678977. Added proper sequence for setup packet
+ *                    handling.
+ * 1.04a nm   10/23/12 Fixed CR# 679106.
+ *	      11/02/12 Fixed CR# 683931. Mult bits are set properly in dQH.
+ * 2.00a kpc 04/03/14 Fixed CR#777763. Corrected the setup tripwire macro val.
+ * 2.1   kpc 04/28/14 Removed unused function prototypes
+ * 2.2   kpc 08/23/14 Exported XUsbPs_DeviceReset API as global for calling in
+ *                    code coverage tests.
+ * 2.3   kpc 02/19/14 Fixed CR#873972, CR#873974. Corrected the logic for proper
+ *                    moving of dTD Head/Tail Pointers. Invalidate the cache
+ *                    after buffer receive in Endpoint Buffer Handler.
+ * 2.4   sg  04/26/16 Fixed CR#949693, Corrected the logic for EP flush
+ *       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+ *                    generation.
+ *       ms  04/10/17 Modified filename tag to include the file in doxygen
+ *                    examples.
+ * 2.5   pm  02/20/20 Added ISO support for usb 2.0 and ch9 common framework
+ * 			calls.
+ * 
+ * + ******************************************************************************/ + +#ifndef XUSBPS_H +#define XUSBPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xusbps_hw.h" +#include "xil_types.h" +#include "xstatus.h" + +/************************** Constant Definitions *****************************/ + +/** + * @name System hang prevention Timeout counter value. + * + * This value is used throughout the code to initialize a Timeout counter that + * is used when hard polling a register. The ides is to initialize the Timeout + * counter to a value that is longer than any expected Timeout but short enough + * so the system will continue to work and report an error while the user is + * still paying attention. A reasonable Timeout time would be about 10 seconds. + * The XUSBPS_TIMEOUT_COUNTER value should be chosen so a polling loop would + * run about 10 seconds before a Timeout is detected. For example: + * + * int Timeout = XUSBPS_TIMEOUT_COUNTER; + * while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + * XUSBPS_CMD_OFFSET) & + * XUSBPS_CMD_RST_MASK) && --Timeout) { + * ; + * } + * if (0 == Timeout) { + * return XST_FAILURE; + * } + * + */ +#define XUSBPS_TIMEOUT_COUNTER 1000000 + + +/** + * @name Endpoint Direction (bitmask) + * Definitions to be used with Endpoint related function that require a + * 'Direction' parameter. + * + * NOTE: + * The direction is always defined from the perspective of the HOST! This + * means that an IN endpoint on the controller is used for sending data while + * the OUT endpoint on the controller is used for receiving data. + * @{ + */ +#define XUSBPS_EP_DIRECTION_IN 0x01 /**< Endpoint direction IN. */ +#define XUSBPS_EP_DIRECTION_OUT 0x02 /**< Endpoint direction OUT. */ +/* @} */ + + +/** + * @name Endpoint Type + * Definitions to be used with Endpoint related functions that require a 'Type' + * parameter. + * @{ + */ +#define XUSBPS_EP_TYPE_NONE 0 /**< Endpoint is not used. */ +#define XUSBPS_EP_TYPE_CONTROL 1 /**< Endpoint for Control Transfers */ +#define XUSBPS_EP_TYPE_ISOCHRONOUS 2 /**< Endpoint for isochronous data */ +#define XUSBPS_EP_TYPE_BULK 3 /**< Endpoint for BULK Transfers. */ +#define XUSBPS_EP_TYPE_INTERRUPT 4 /**< Endpoint for interrupt Transfers */ +/* @} */ + +/** + * Endpoint Max Packet Length in DeviceConfig is a coded value, ch9.6.6. + * + * @{ + */ +#define ENDPOINT_MAXP_LENGTH 0x400 +#define ENDPOINT_MAXP_MULT_MASK 0xC00 +#define ENDPOINT_MAXP_MULT_SHIFT 10 +/* @} */ + +/** + * @name Field names for status retrieval + * Definitions for the XUsbPs_GetStatus() function call 'StatusType' + * parameter. + * @{ + */ +#define XUSBPS_EP_STS_ADDRESS 1 /**< Address of controller. */ +#define XUSBPS_EP_STS_CONTROLLER_STATE 2 /**< Current controller state. */ +/* @} */ + + /* + * Device Speeds + */ + #define XUSBPS_SPEED_UNKNOWN 0U + #define XUSBPS_SPEED_LOW 1U + #define XUSBPS_SPEED_FULL 2U + #define XUSBPS_SPEED_HIGH 3U + +/** + * @name USB Default alternate setting + * + * @{ + */ +#define XUSBPS_DEFAULT_ALT_SETTING 0 /**< The default alternate setting is 0 */ +/* @} */ + + /* + * Device States + */ + #define XUSBPS_STATE_ATTACHED 0U + #define XUSBPS_STATE_POWERED 1U + #define XUSBPS_STATE_DEFAULT 2U + #define XUSBPS_STATE_ADDRESS 3U + #define XUSBPS_STATE_CONFIGURED 4U + #define XUSBPS_STATE_SUSPENDED 5U + +/** + * @name Endpoint event types + * Definitions that are used to identify events that occur on endpoints. Passed + * to the endpoint event handler functions registered with + * XUsbPs_EpSetHandler(). + * @{ + */ +#define XUSBPS_EP_EVENT_SETUP_DATA_RECEIVED 0x01 + /**< Setup data has been received on the endpoint. */ +#define XUSBPS_EP_EVENT_DATA_RX 0x02 + /**< Data frame has been received on the endpoint. */ +#define XUSBPS_EP_EVENT_DATA_TX 0x03 + /**< Data frame has been sent on the endpoint. */ +/* @} */ + + +/* + * Maximum packet size for endpoint, 1024 + * @{ + */ +#define XUSBPS_MAX_PACKET_SIZE 1024 + /**< Maximum value can be put into the queue head */ +/* @} */ +/**************************** Type Definitions *******************************/ + +/****************************************************************************** + * This data type defines the callback function to be used for Endpoint + * handlers. + * + * @param CallBackRef is the Callback reference passed in by the upper + * layer when setting the handler, and is passed back to the upper + * layer when the handler is called. + * @param EpNum is the Number of the endpoint that caused the event. + * @param EventType is the type of the event that occurred on the endpoint. + * @param Data is a pointer to user data pointer specified when callback + * was registered. + */ +typedef void (*XUsbPs_EpHandlerFunc)(void *CallBackRef, + u8 EpNum, u8 EventType, void *Data); + +/****************************************************************************** + * This data type defines the callback function to be used for Endpoint + * handlers. + * + * @param CallBackRef is the Callback reference passed in by the upper + * layer when setting the handler, and is passed back to the upper + * layer when the handler is called. + * @param RequestedBytes is the number of bytes requested to transfer. + * @param BytesTxed is the actual number of bytes to be transfer. + */ +typedef void (*XUsbPs_EpIsoHandlerFunc)(void *CallBackRef, + u32 RequestedBytes, u32 BytesTxed); + +/****************************************************************************** + * This data type defines the callback function to be used for the general + * interrupt handler. + * + * @param CallBackRef is the Callback reference passed in by the upper + * layer when setting the handler, and is passed back to the upper + * layer when the handler is called. + * @param IrqMask is the Content of the interrupt status register. This + * value can be used by the callback function to distinguish the + * individual interrupt types. + */ +typedef void (*XUsbPs_IntrHandlerFunc)(void *CallBackRef, u32 IrqMask); + + +/******************************************************************************/ + +/* The following type definitions are used for referencing Queue Heads and + * Transfer Descriptors. The structures themselves are not used, however, the + * types are used in the API to avoid using (void *) pointers. + */ +typedef u8 XUsbPs_dQH[XUSBPS_dQH_ALIGN]; +typedef u8 XUsbPs_dTD[XUSBPS_dTD_ALIGN]; + + +/** + * The following data structures are used internally by the L0/L1 driver. + * Their contents MUST NOT be changed by the upper layers. + */ + +/** + * The following data structure represents OUT endpoint. + */ +typedef struct { + XUsbPs_dQH *dQH; + /**< Pointer to the Queue Head structure of the endpoint. */ + + XUsbPs_dTD *dTDs; + /**< Pointer to the first dTD of the dTD list for this + * endpoint. */ + + XUsbPs_dTD *dTDCurr; + /**< Buffer to the currently processed descriptor. */ + + u8 *dTDBufs; + /**< Pointer to the first buffer of the buffer list for this + * endpoint. */ + + XUsbPs_EpHandlerFunc HandlerFunc; + XUsbPs_EpIsoHandlerFunc HandlerIsoFunc; + /**< Handler function for this endpoint. */ + void *HandlerRef; + /**< User data reference for the handler. */ + u32 RequestedBytes; /**< RequestedBytes for transfer */ + u32 BytesTxed; /**< Actual Bytes transferred */ + u8 *BufferPtr; /**< Buffer location */ + u8 MemAlloted; /**< Mem alloted and data is not received */ + u32 Interval; /**< Data transfer service interval */ +} XUsbPs_EpOut; + + +/** + * The following data structure represents IN endpoint. + */ +typedef struct { + XUsbPs_dQH *dQH; + /**< Pointer to the Queue Head structure of the endpoint. */ + + XUsbPs_dTD *dTDs; + /**< List of pointers to the Transfer Descriptors of the + * endpoint. */ + + XUsbPs_dTD *dTDHead; + /**< Buffer to the next available descriptor in the list. */ + + XUsbPs_dTD *dTDTail; + /**< Buffer to the last unsent descriptor in the list*/ + + XUsbPs_EpHandlerFunc HandlerFunc; + XUsbPs_EpIsoHandlerFunc HandlerIsoFunc; + /**< Handler function for this endpoint. */ + void *HandlerRef; + /**< User data reference for the handler. */ + u32 RequestedBytes; /**< RequestedBytes for transfer */ + u32 BytesTxed; /**< Actual Bytes transferred */ + u8 *BufferPtr; /**< Buffer location */ + u32 Interval; /**< Data transfer service interval */ +} XUsbPs_EpIn; + + +/** + * The following data structure represents an endpoint used internally + * by the L0/L1 driver. + */ +typedef struct { + /* Each endpoint has an OUT and an IN component. + */ + XUsbPs_EpOut Out; /**< OUT endpoint structure */ + XUsbPs_EpIn In; /**< IN endpoint structure */ +} XUsbPs_Endpoint; + + + +/** + * The following structure is used by the user to receive Setup Data from an + * endpoint. Using this structure simplifies the process of interpreting the + * setup data in the core's data fields. + * + * The naming scheme for the members of this structure is different from the + * naming scheme found elsewhere in the code. The members of this structure are + * defined in the Chapter 9 USB reference guide. Using this naming scheme makes + * it easier for people familiar with the standard to read the code. + */ +typedef struct { + u8 bmRequestType; /**< bmRequestType in setup data */ + u8 bRequest; /**< bRequest in setup data */ + u16 wValue; /**< wValue in setup data */ + u16 wIndex; /**< wIndex in setup data */ + u16 wLength; /**< wLength in setup data */ +} +XUsbPs_SetupData; + + +/** + * Data structures used to configure endpoints. + */ +typedef struct { + u32 Type; + /**< Endpoint type: + - XUSBPS_EP_TYPE_CONTROL + - XUSBPS_EP_TYPE_ISOCHRONOUS + - XUSBPS_EP_TYPE_BULK + - XUSBPS_EP_TYPE_INTERRUPT */ + + u32 NumBufs; + /**< Number of buffers to be handled by this endpoint. */ + u32 BufSize; + /**< Buffer size. Only relevant for OUT (receive) Endpoints. */ + + u16 MaxPacketSize; + /**< Maximum packet size for this endpoint. This number will + * define the maximum number of bytes sent on the wire per + * transaction. Range: 0..1024 */ +} XUsbPs_EpSetup; + + +/** + * Endpoint configuration structure. + */ +typedef struct { + XUsbPs_EpSetup Out; /**< OUT component of endpoint. */ + XUsbPs_EpSetup In; /**< IN component of endpoint. */ +} XUsbPs_EpConfig; + + +/** + * The XUsbPs_DeviceConfig structure contains the configuration information to + * configure the USB controller for DEVICE mode. This data structure is used + * with the XUsbPs_ConfigureDevice() function call. + */ +typedef struct { + u8 NumEndpoints; /**< Number of Endpoints for the controller. + This number depends on the runtime + configuration of driver. The driver may + configure fewer endpoints than are available + in the core. */ + + XUsbPs_EpConfig EpCfg[XUSBPS_MAX_ENDPOINTS]; + /**< List of endpoint configurations. */ + + + u32 DMAMemPhys; /**< Physical base address of DMAable memory + allocated for the driver. */ + + /* The following members are used internally by the L0/L1 driver. They + * MUST NOT be accesses and/or modified in any way by the upper layers. + * + * The reason for having these members is that we generally try to + * avoid allocating memory in the L0/L1 driver as we want to be OS + * independent. In order to avoid allocating memory for this data + * structure wihin L0/L1 we put it into the XUsbPs_DeviceConfig + * structure which is allocated by the caller. + */ + XUsbPs_Endpoint Ep[XUSBPS_MAX_ENDPOINTS]; + /**< List of endpoint metadata structures. */ + + u32 PhysAligned; /**< 64 byte aligned base address of the DMA + memory block. Will be computed and set by + the L0/L1 driver. */ +} XUsbPs_DeviceConfig; + + +/** + * The XUsbPs_Config structure contains configuration information for the USB + * controller. + * + * This structure only contains the basic configuration for the controller. The + * caller also needs to initialize the controller for the DEVICE mode + * using the XUsbPs_DeviceConfig data structures with the + * XUsbPs_ConfigureDevice() function call + */ +typedef struct { + u16 DeviceID; /**< Unique ID of controller. */ + u32 BaseAddress; /**< Core register base address. */ +} XUsbPs_Config; + +typedef XUsbPs_Config Usb_Config; + +struct Usb_DevData { + u8 Speed; + u8 State; + + void *PrivateData; +}; + +/** + * The XUsbPs driver instance data. The user is required to allocate a + * variable of this type for every USB controller in the system. A pointer to a + * variable of this type is then passed to the driver API functions. + */ +typedef struct { + XUsbPs_SetupData SetupData; + /**< Setup Packet buffer */ + XUsbPs_Config Config; /**< Configuration structure */ + + int CurrentAltSetting; /**< Current alternative setting of interface */ + + void *UserDataPtr; /**< Data pointer to be used by upper layers to + store application dependent data structures. + The upper layers are responsible to allocated + and free the memory. The driver will not + mofidy this data pointer. */ + + /** + * The following structures hold the configuration for DEVICE mode + * of the controller. They are initialized using the + * XUsbPs_ConfigureDevice() function call. + */ + XUsbPs_DeviceConfig DeviceConfig; + /**< Configuration for the DEVICE mode. */ + + XUsbPs_IntrHandlerFunc HandlerFunc; + /**< Handler function for the controller. */ + void *HandlerRef; + /**< User data reference for the handler. */ + u32 HandlerMask; + /**< User interrupt mask. Defines which interrupts will cause + * the callback to be called. */ + struct Usb_DevData *AppData; + u8 IsConfigDone; + void *data_ptr; /* pointer for storing applications data */ +} XUsbPs; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************** + * + * USB CONTROLLER RELATED MACROS + * + ******************************************************************************/ +/*****************************************************************************/ +/** + * This macro returns the current frame number. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @return The current frame number. + * + * @note C-style signature: + * u32 XUsbPs_GetFrameNum(const XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_GetFrameNum(InstancePtr) \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, XUSBPS_FRAME_OFFSET) + + +/*****************************************************************************/ +/** + * This macro starts the USB engine. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @note C-style signature: + * void XUsbPs_Start(XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_Start(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_CMD_OFFSET, XUSBPS_CMD_RS_MASK) + + +/*****************************************************************************/ +/** + * This macro stops the USB engine. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @note C-style signature: + * void XUsbPs_Stop(XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_Stop(InstancePtr) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_CMD_OFFSET, XUSBPS_CMD_RS_MASK) + + +/*****************************************************************************/ +/** + * This macro forces the USB engine to be in Full Speed (FS) mode. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @note C-style signature: + * void XUsbPs_ForceFS(XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_ForceFS(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_PORTSCR1_OFFSET, \ + XUSBPS_PORTSCR_PFSC_MASK) + + +/*****************************************************************************/ +/** + * This macro starts the USB Timer 0, with repeat option for period of + * one second. + * + * @param InstancePtr is a pointer to XUsbPs instance of the controller. + * @param Interval is the interval for Timer0 to generate an interrupt + * + * @note C-style signature: + * void XUsbPs_StartTimer0(XUsbPs *InstancePtr, u32 Interval) + * + ******************************************************************************/ +#define XUsbPs_StartTimer0(InstancePtr, Interval) \ +{ \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_TIMER0_LD_OFFSET, (Interval)); \ + XUsbPs_SetBits(InstancePtr, XUSBPS_TIMER0_CTL_OFFSET, \ + XUSBPS_TIMER_RUN_MASK | \ + XUSBPS_TIMER_RESET_MASK | \ + XUSBPS_TIMER_REPEAT_MASK); \ +} \ + + +/*****************************************************************************/ +/** +* This macro stops Timer 0. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_StopTimer0(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_StopTimer0(InstancePtr) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_TIMER0_CTL_OFFSET, \ + XUSBPS_TIMER_RUN_MASK) + + +/*****************************************************************************/ +/** +* This macro reads Timer 0. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_ReadTimer0(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_ReadTimer0(InstancePtr) \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_TIMER0_CTL_OFFSET) & \ + XUSBPS_TIMER_COUNTER_MASK + + +/*****************************************************************************/ +/** +* This macro force remote wakeup on host +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_RemoteWakeup(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_RemoteWakeup(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_PORTSCR1_OFFSET, \ + XUSBPS_PORTSCR_FPR_MASK) + + +/****************************************************************************** + * + * ENDPOINT RELATED MACROS + * + ******************************************************************************/ +/*****************************************************************************/ +/** +* This macro enables the given endpoint for the given direction. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is number of the endpoint to enable. +* @param Dir is direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpEnable(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpEnable(InstancePtr, EpNum, Dir) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXE_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXE_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro disables the given endpoint for the given direction. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is the number of the endpoint to disable. +* @param Dir is the direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpDisable(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpDisable(InstancePtr, EpNum, Dir) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXE_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXE_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro stalls the given endpoint for the given direction, and flush +* the buffers. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is number of the endpoint to stall. +* @param Dir is the direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpStall(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpStall(InstancePtr, EpNum, Dir) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXS_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXS_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro unstalls the given endpoint for the given direction. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is the Number of the endpoint to unstall. +* @param Dir is the Direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpUnStall(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpUnStall(InstancePtr, EpNum, Dir) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXS_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXS_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro flush an endpoint upon interface disable +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is the number of the endpoint to flush. +* @param Dir is the direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpFlush(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpFlush(InstancePtr, EpNum, Dir) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPFLUSH_OFFSET, \ + 1 << (EpNum + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? \ + XUSBPS_EPFLUSH_RX_SHIFT:XUSBPS_EPFLUSH_TX_SHIFT))) \ + +/*****************************************************************************/ +/** +* This macro enables the interrupts defined by the bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param IntrMask is the Bit mask of interrupts to be enabled. +* +* @note C-style signature: +* void XUsbPs_IntrEnable(XUsbPs *InstancePtr, u32 IntrMask) +* +******************************************************************************/ +#define XUsbPs_IntrEnable(InstancePtr, IntrMask) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_IER_OFFSET, IntrMask) + + +/*****************************************************************************/ +/** +* This function disables the interrupts defined by the bit mask. +* +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param IntrMask is a Bit mask of interrupts to be disabled. +* +* @note C-style signature: +* void XUsbPs_IntrDisable(XUsbPs *InstancePtr, u32 IntrMask) +* +******************************************************************************/ +#define XUsbPs_IntrDisable(InstancePtr, IntrMask) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_IER_OFFSET, IntrMask) + + +/*****************************************************************************/ +/** +* This macro enables the endpoint NAK interrupts defined by the bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param NakIntrMask is the Bit mask of endpoint NAK interrupts to be +* enabled. +* @note C-style signature: +* void XUsbPs_NakIntrEnable(XUsbPs *InstancePtr, u32 NakIntrMask) +* +******************************************************************************/ +#define XUsbPs_NakIntrEnable(InstancePtr, NakIntrMask) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPNAKIER_OFFSET, NakIntrMask) + + +/*****************************************************************************/ +/** +* This macro disables the endpoint NAK interrupts defined by the bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param NakIntrMask is a Bit mask of endpoint NAK interrupts to be +* disabled. +* +* @note +* C-style signature: +* void XUsbPs_NakIntrDisable(XUsbPs *InstancePtr, u32 NakIntrMask) +* +******************************************************************************/ +#define XUsbPs_NakIntrDisable(InstancePtr, NakIntrMask) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_EPNAKIER_OFFSET, NakIntrMask) + + +/*****************************************************************************/ +/** +* This function clears the endpoint NAK interrupts status defined by the +* bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param NakIntrMask is the Bit mask of endpoint NAK interrupts to be cleared. +* +* @note C-style signature: +* void XUsbPs_NakIntrClear(XUsbPs *InstancePtr, u32 NakIntrMask) +* +******************************************************************************/ +#define XUsbPs_NakIntrClear(InstancePtr, NakIntrMask) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_EPNAKISR_OFFSET, NakIntrMask) + + + +/*****************************************************************************/ +/** +* This macro sets the Interrupt Threshold value in the control register +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param Threshold is the Interrupt threshold to be set. +* Allowed values: +* - XUSBPS_CMD_ITHRESHOLD_0 - Immediate interrupt +* - XUSBPS_CMD_ITHRESHOLD_1 - 1 Frame +* - XUSBPS_CMD_ITHRESHOLD_2 - 2 Frames +* - XUSBPS_CMD_ITHRESHOLD_4 - 4 Frames +* - XUSBPS_CMD_ITHRESHOLD_8 - 8 Frames +* - XUSBPS_CMD_ITHRESHOLD_16 - 16 Frames +* - XUSBPS_CMD_ITHRESHOLD_32 - 32 Frames +* - XUSBPS_CMD_ITHRESHOLD_64 - 64 Frames +* +* @note +* C-style signature: +* void XUsbPs_SetIntrThreshold(XUsbPs *InstancePtr, u8 Threshold) +* +******************************************************************************/ +#define XUsbPs_SetIntrThreshold(InstancePtr, Threshold) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_CMD_OFFSET, (Threshold))\ + + +/*****************************************************************************/ +/** +* This macro sets the Tripwire bit in the USB command register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_SetTripwire(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_SetSetupTripwire(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_CMD_OFFSET, \ + XUSBPS_CMD_SUTW_MASK) + + +/*****************************************************************************/ +/** +* This macro clears the Tripwire bit in the USB command register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_ClrTripwire(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_ClrSetupTripwire(InstancePtr) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_CMD_OFFSET, \ + XUSBPS_CMD_SUTW_MASK) + + +/*****************************************************************************/ +/** +* This macro checks if the Tripwire bit in the USB command register is set. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @return +* - TRUE: The tripwire bit is still set. +* - FALSE: The tripwire bit has been cleared. +* +* @note C-style signature: +* int XUsbPs_TripwireIsSet(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_SetupTripwireIsSet(InstancePtr) \ + (XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_CMD_OFFSET) & \ + XUSBPS_CMD_SUTW_MASK ? TRUE : FALSE) + + +/****************************************************************************** +* +* GENERAL REGISTER / BIT MANIPULATION MACROS +* +******************************************************************************/ +/****************************************************************************/ +/** +* This macro sets the given bit mask in the register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param RegOffset is the register offset to be written. +* @param Bits is the Bits to be set in the register +* +* @return None. +* +* @note C-style signature: +* void XUsbPs_SetBits(u32 BaseAddress, u32 RegOffset, u32 Bits) +* +*****************************************************************************/ +#define XUsbPs_SetBits(InstancePtr, RegOffset, Bits) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, RegOffset, \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + RegOffset) | (Bits)); + + +/****************************************************************************/ +/** +* +* This macro clears the given bits in the register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param RegOffset is the register offset to be written. +* @param Bits are the bits to be cleared in the register +* +* @return None. +* +* @note +* C-style signature: +* void XUsbPs_ClrBits(u32 BaseAddress, u32 RegOffset, u32 Bits) +* +*****************************************************************************/ +#define XUsbPs_ClrBits(InstancePtr, RegOffset, Bits) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, RegOffset, \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + RegOffset) & ~(Bits)); + + +/************************** Function Prototypes ******************************/ + +/** + * Setup / Initialize functions. + * + * Implemented in file xusbps.c + */ +int XUsbPs_CfgInitialize(XUsbPs *InstancePtr, + const XUsbPs_Config *ConfigPtr, u32 BaseAddress); + +int XUsbPs_ConfigureDevice(XUsbPs *InstancePtr, + const XUsbPs_DeviceConfig *CfgPtr); + +/** + * Common functions used for DEVICE/HOST mode. + */ +int XUsbPs_Reset(XUsbPs *InstancePtr); + +void XUsbPs_DeviceReset(XUsbPs *InstancePtr); + +/** + * DEVICE mode specific functions. + */ +int XUsbPs_BusReset(XUsbPs *InstancePtr); +int XUsbPs_SetDeviceAddress(XUsbPs *InstancePtr, u8 Address); + + +/** + * Handling Suspend and Resume. + * + * Implemented in xusbps.c + */ +int XUsbPs_Suspend(const XUsbPs *InstancePtr); +int XUsbPs_Resume(const XUsbPs *InstancePtr); +int XUsbPs_RequestHostResume(const XUsbPs *InstancePtr); + + +/* + * Functions for managing Endpoints / Transfers + * + * Implemented in file xusbps_endpoint.c + */ +int XUsbPs_EpBufferSend(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen); +int XUsbPs_EpBufferSendWithZLT(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen); +int XUsbPs_EpBufferReceive(XUsbPs *InstancePtr, u8 EpNum, + u8 **BufferPtr, u32 *BufferLenPtr, u32 *Handle); +void XUsbPs_EpBufferRelease(u32 Handle); + +int XUsbPs_EpSetHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction, + XUsbPs_EpHandlerFunc CallBackFunc, + void *CallBackRef); +s32 XUsbPs_EpSetIsoHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction, + XUsbPs_EpIsoHandlerFunc CallBackFunc); +int XUsbPs_EpGetSetupData(XUsbPs *InstancePtr, int EpNum, + XUsbPs_SetupData *SetupDataPtr); + +int XUsbPs_EpPrime(XUsbPs *InstancePtr, u8 EpNum, u8 Direction); + +int XUsbPs_ReconfigureEp(XUsbPs *InstancePtr, XUsbPs_DeviceConfig *CfgPtr, + int EpNum, unsigned short NewDirection, int DirectionChanged); + +/* + * Interrupt handling functions + * + * Implemented in file xusbps_intr.c + */ +void XUsbPs_IntrHandler(void *InstancePtr); + +int XUsbPs_IntrSetHandler(XUsbPs *InstancePtr, + XUsbPs_IntrHandlerFunc CallBackFunc, + void *CallBackRef, u32 Mask); +void XUsbPs_EpGetData(XUsbPs *InstancePtr, u8 EpNum, u32 BufferLen); + +s32 XUsbPs_EpDataBufferReceive(XUsbPs *InstancePtr, u8 EpNum, + u8 *BufferPtr, u32 BufferLen); +/* + * Helper functions for static configuration. + * Implemented in xusbps_sinit.c + */ +XUsbPs_Config *XUsbPs_LookupConfig(u16 DeviceId); + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_H */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xusbps_endpoint.h b/bsp_z7/ps7_cortexa9_0/include/xusbps_endpoint.h new file mode 100644 index 0000000..b924726 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xusbps_endpoint.h @@ -0,0 +1,507 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xusbps_endpoint.h +* @addtogroup usbps_v2_7 +* @{ + * + * This is an internal file containung the definitions for endpoints. It is + * included by the xusbps_endpoint.c which is implementing the endpoint + * functions and by xusbps_intr.c. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- --------------------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 2.5   pm   02/20/20 Added multiplier bit for ISO frame handling.
+ * 
+ * + ******************************************************************************/ +#ifndef XUSBPS_ENDPOINT_H +#define XUSBPS_ENDPOINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_cache.h" +#include "xusbps.h" +#include "xil_types.h" + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + + +/** + * Endpoint Device Transfer Descriptor + * + * The dTD describes to the device controller the location and quantity of data + * to be sent/received for given transfer. The driver does not attempt to + * modify any field in an active dTD except the Next Link Pointer. + */ +#define XUSBPS_dTDNLP 0x00 /**< Pointer to the next descriptor */ +#define XUSBPS_dTDTOKEN 0x04 /**< Descriptor Token */ +#define XUSBPS_dTDBPTR0 0x08 /**< Buffer Pointer 0 */ +#define XUSBPS_dTDBPTR1 0x0C /**< Buffer Pointer 1 */ +#define XUSBPS_dTDBPTR2 0x10 /**< Buffer Pointer 2 */ +#define XUSBPS_dTDBPTR3 0x14 /**< Buffer Pointer 3 */ +#define XUSBPS_dTDBPTR4 0x18 /**< Buffer Pointer 4 */ +#define XUSBPS_dTDBPTR(n) (XUSBPS_dTDBPTR0 + (n) * 0x04) +#define XUSBPS_dTDRSRVD 0x1C /**< Reserved field */ + +/* We use the reserved field in the dTD to store user data. */ +#define XUSBPS_dTDUSERDATA XUSBPS_dTDRSRVD /**< Reserved field */ + + +/** @name dTD Next Link Pointer (dTDNLP) bit positions. + * @{ + */ +#define XUSBPS_dTDNLP_T_MASK 0x00000001 + /**< USB dTD Next Link Pointer Terminate Bit */ +#define XUSBPS_dTDNLP_ADDR_MASK 0xFFFFFFE0 + /**< USB dTD Next Link Pointer Address [31:5] */ +/* @} */ + + +/** @name dTD Token (dTDTOKEN) bit positions. + * @{ + */ +#define XUSBPS_dTDTOKEN_XERR_MASK 0x00000008 /**< dTD Transaction Error */ +#define XUSBPS_dTDTOKEN_BUFERR_MASK 0x00000020 /**< dTD Data Buffer Error */ +#define XUSBPS_dTDTOKEN_HALT_MASK 0x00000040 /**< dTD Halted Flag */ +#define XUSBPS_dTDTOKEN_ACTIVE_MASK 0x00000080 /**< dTD Active Bit */ +#define XUSBPS_dTDTOKEN_MULTO_MASK 0x00000C00 /**< Multiplier Override Field [1:0] */ +#define XUSBPS_dTDTOKEN_IOC_MASK 0x00008000 /**< Interrupt on Complete Bit */ +#define XUSBPS_dTDTOKEN_LEN_MASK 0x7FFF0000 /**< Transfer Length Field */ +/* @} */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * + * IMPORTANT NOTE: + * =============== + * + * Many of the following macros modify Device Queue Head (dQH) data structures + * and Device Transfer Descriptor (dTD) data structures. Those structures can + * potentially reside in CACHED memory. Therefore, it's the callers + * responsibility to ensure cache coherency by using provided + * + * XUsbPs_dQHInvalidateCache() + * XUsbPs_dQHFlushCache() + * XUsbPs_dTDInvalidateCache() + * XUsbPs_dTDFlushCache() + * + * function calls. + * + ******************************************************************************/ +#define XUsbPs_dTDInvalidateCache(dTDPtr) \ + Xil_DCacheInvalidateRange((unsigned int)dTDPtr, sizeof(XUsbPs_dTD)) + +#define XUsbPs_dTDFlushCache(dTDPtr) \ + Xil_DCacheFlushRange((unsigned int)dTDPtr, sizeof(XUsbPs_dTD)) + +#define XUsbPs_dQHInvalidateCache(dQHPtr) \ + Xil_DCacheInvalidateRange((unsigned int)dQHPtr, sizeof(XUsbPs_dQH)) + +#define XUsbPs_dQHFlushCache(dQHPtr) \ + Xil_DCacheFlushRange((unsigned int)dQHPtr, sizeof(XUsbPs_dQH)) + +/*****************************************************************************/ +/** + * + * This macro sets the Transfer Length for the given Transfer Descriptor. + * + * @param dTDPtr is pointer to the dTD element. + * @param Len is the length to be set. Range: 0..16384 + * + * @note C-style signature: + * void XUsbPs_dTDSetTransferLen(u32 dTDPtr, u32 Len) + * + ******************************************************************************/ +#define XUsbPs_dTDSetTransferLen(dTDPtr, Len) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDTOKEN, \ + (XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) & \ + ~XUSBPS_dTDTOKEN_LEN_MASK) | ((Len) << 16)) + + +/*****************************************************************************/ +/** + * + * This macro gets the Next Link pointer of the given Transfer Descriptor. + * + * @param dTDPtr is pointer to the dTD element. + * + * @return TransferLength field of the descriptor. + * + * @note C-style signature: + * u32 XUsbPs_dTDGetTransferLen(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDGetNLP(dTDPtr) \ + (XUsbPs_dTD *) ((XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP)\ + & XUSBPS_dTDNLP_ADDR_MASK)) + + +/*****************************************************************************/ +/** + * + * This macro sets the Next Link pointer of the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * @param NLP is the Next Link Pointer + * + * @note C-style signature: + * void XUsbPs_dTDSetTransferLen(u32 dTDPtr, u32 Len) + * + ******************************************************************************/ +#define XUsbPs_dTDSetNLP(dTDPtr, NLP) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDNLP, \ + (XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP) & \ + ~XUSBPS_dTDNLP_ADDR_MASK) | \ + ((NLP) & XUSBPS_dTDNLP_ADDR_MASK)) + + +/*****************************************************************************/ +/** + * + * This macro gets the Transfer Length for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @return TransferLength field of the descriptor. + * + * @note C-style signature: + * u32 XUsbPs_dTDGetTransferLen(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDGetTransferLen(dTDPtr) \ + (u32) ((XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) \ + & XUSBPS_dTDTOKEN_LEN_MASK) >> 16) + + +/*****************************************************************************/ +/** + * + * This macro sets the Interrupt On Complete (IOC) bit for the given Transfer + * Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDSetIOC(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDSetIOC(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDTOKEN, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) | \ + XUSBPS_dTDTOKEN_IOC_MASK) + + +/*****************************************************************************/ +/** + * + * This macro sets the Terminate bit for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDSetTerminate(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDSetTerminate(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDNLP, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP) | \ + XUSBPS_dTDNLP_T_MASK) + + +/*****************************************************************************/ +/** + * + * This macro clears the Terminate bit for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDClrTerminate(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDClrTerminate(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDNLP, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP) & \ + ~XUSBPS_dTDNLP_T_MASK) + + +/*****************************************************************************/ +/** + * + * This macro checks if the given descriptor is active. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @return + * - TRUE: The buffer is active. + * - FALSE: The buffer is not active. + * + * @note C-style signature: + * int XUsbPs_dTDIsActive(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDIsActive(dTDPtr) \ + ((XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) & \ + XUSBPS_dTDTOKEN_ACTIVE_MASK) ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * + * This macro sets the Active bit for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDSetActive(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDSetActive(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDTOKEN, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) | \ + XUSBPS_dTDTOKEN_ACTIVE_MASK) + +/*****************************************************************************/ +/** + * + * This macro sets the multiplier bit for the Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * @param val is the multiplier value. + * + * @note C-style signature: + * void XUsbPs_dTDSetMultO(u32 dTDPtr, u32 val) + * + ******************************************************************************/ +#define XUsbPs_dTDSetMultO(dTDPtr, val) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDTOKEN, \ + (XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) & \ + (~XUSBPS_dTDTOKEN_MULTO_MASK)) | val) + + +/*****************************************************************************/ +/** + * + * This macro reads the content of a field in a Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * @param Id is the field ID inside the dTD element to read. + * + * @note C-style signature: + * u32 XUsbPs_ReaddTD(u32 dTDPtr, u32 Id) + * + ******************************************************************************/ +#define XUsbPs_ReaddTD(dTDPtr, Id) (*(u32 *)((u32)(dTDPtr) + (u32)(Id))) + +/*****************************************************************************/ +/** + * + * This macro writes a value to a field in a Transfer Descriptor. + * + * @param dTDPtr is pointer to the dTD element. + * @param Id is the field ID inside the dTD element to read. + * @param Val is the value to write to the field. + * + * @note C-style signature: + * u32 XUsbPs_WritedTD(u32 dTDPtr, u32 Id, u32 Val) + * + ******************************************************************************/ +#define XUsbPs_WritedTD(dTDPtr, Id, Val) \ + (*(u32 *) ((u32)(dTDPtr) + (u32)(Id)) = (u32)(Val)) + + +/******************************************************************************/ +/** + * Endpoint Device Queue Head + * + * Device queue heads are arranged in an array in a continuous area of memory + * pointed to by the ENDPOINTLISTADDR pointer. The device controller will index + * into this array based upon the endpoint number received from the USB bus. + * All information necessary to respond to transactions for all primed + * transfers is contained in this list so the Device Controller can readily + * respond to incoming requests without having to traverse a linked list. + * + * The device Endpoint Queue Head (dQH) is where all transfers are managed. The + * dQH is a 48-byte data structure, but must be aligned on a 64-byte boundary. + * During priming of an endpoint, the dTD (device transfer descriptor) is + * copied into the overlay area of the dQH, which starts at the nextTD pointer + * DWord and continues through the end of the buffer pointers DWords. After a + * transfer is complete, the dTD status DWord is updated in the dTD pointed to + * by the currentTD pointer. While a packet is in progress, the overlay area of + * the dQH is used as a staging area for the dTD so that the Device Controller + * can access needed information with little minimal latency. + * + * @note + * Software must ensure that no interface data structure reachable by the + * Device Controller spans a 4K-page boundary. The first element of the + * Endpoint Queue Head List must be aligned on a 4K boundary. + */ +#define XUSBPS_dQHCFG 0x00 /**< dQH Configuration */ +#define XUSBPS_dQHCPTR 0x04 /**< dQH Current dTD Pointer */ +#define XUSBPS_dQHdTDNLP 0x08 /**< dTD Next Link Ptr in dQH + overlay */ +#define XUSBPS_dQHdTDTOKEN 0x0C /**< dTD Token in dQH overlay */ +#define XUSBPS_dQHSUB0 0x28 /**< USB dQH Setup Buffer 0 */ +#define XUSBPS_dQHSUB1 0x2C /**< USB dQH Setup Buffer 1 */ + + +/** @name dQH Configuration (dQHCFG) bit positions. + * @{ + */ +#define XUSBPS_dQHCFG_IOS_MASK 0x00008000 + /**< USB dQH Interrupt on Setup Bit */ +#define XUSBPS_dQHCFG_MPL_MASK 0x07FF0000 + /**< USB dQH Maximum Packet Length + * Field [10:0] */ +#define XUSBPS_dQHCFG_MPL_SHIFT 16 +#define XUSBPS_dQHCFG_ZLT_MASK 0x20000000 + /**< USB dQH Zero Length Termination + * Select Bit */ +#define XUSBPS_dQHCFG_MULT_MASK 0xC0000000 + /* USB dQH Number of Transactions Field + * [1:0] */ +#define XUSBPS_dQHCFG_MULT_SHIFT 30 +/* @} */ + + +/*****************************************************************************/ +/** + * + * This macro sets the Maximum Packet Length field of the give Queue Head. + * + * @param dQHPtr is a pointer to the dQH element. + * @param Len is the length to be set. + * + * @note C-style signature: + * void XUsbPs_dQHSetMaxPacketLen(u32 dQHPtr, u32 Len) + * + ******************************************************************************/ +#define XUsbPs_dQHSetMaxPacketLen(dQHPtr, Len) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & \ + ~XUSBPS_dQHCFG_MPL_MASK) | ((Len) << 16)) + +/*****************************************************************************/ +/** + * + * This macro sets the Interrupt On Setup (IOS) bit for an endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHSetIOS(u32 dQHPtr) + * + ******************************************************************************/ +#define XUsbPs_dQHSetIOS(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) | \ + XUSBPS_dQHCFG_IOS_MASK) + +/*****************************************************************************/ +/** + * + * This macro clears the Interrupt On Setup (IOS) bit for an endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHClrIOS(u32 dQHPtr) + * + ******************************************************************************/ +#define XUsbPs_dQHClrIOS(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & \ + ~XUSBPS_dQHCFG_IOS_MASK) + +/*****************************************************************************/ +/** + * + * This macro enables Zero Length Termination for the endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHEnableZLT(u32 dQHPtr) + * + * + ******************************************************************************/ +#define XUsbPs_dQHEnableZLT(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & \ + ~XUSBPS_dQHCFG_ZLT_MASK) + + +/*****************************************************************************/ +/** + * + * This macro disables Zero Length Termination for the endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHDisableZLT(u32 dQHPtr) + * + * + ******************************************************************************/ +#define XUsbPs_dQHDisableZLT(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) | \ + XUSBPS_dQHCFG_ZLT_MASK) + +/*****************************************************************************/ +/** + * + * This macro reads the content of a field in a Queue Head. + * + * @param dQHPtr is a pointer to the dQH element. + * @param Id is the Field ID inside the dQH element to read. + * + * @note C-style signature: + * u32 XUsbPs_ReaddQH(u32 dQHPtr, u32 Id) + * + ******************************************************************************/ +#define XUsbPs_ReaddQH(dQHPtr, Id) (*(u32 *)((u32)(dQHPtr) + (u32) (Id))) + +/*****************************************************************************/ +/** + * + * This macro writes a value to a field in a Queue Head. + * + * @param dQHPtr is a pointer to the dQH element. + * @param Id is the Field ID inside the dQH element to read. + * @param Val is the Value to write to the field. + * + * @note C-style signature: + * u32 XUsbPs_WritedQH(u32 dQHPtr, u32 Id, u32 Val) + * + ******************************************************************************/ +#define XUsbPs_WritedQH(dQHPtr, Id, Val) \ + (*(u32 *) ((u32)(dQHPtr) + (u32)(Id)) = (u32)(Val)) + + + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_ENDPOINT_H */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/include/xusbps_hw.h b/bsp_z7/ps7_cortexa9_0/include/xusbps_hw.h new file mode 100644 index 0000000..4f985dc --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/include/xusbps_hw.h @@ -0,0 +1,505 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xusbps_hw.h +* @addtogroup usbps_v2_7 +* @{ + * + * This header file contains identifiers and low-level driver functions (or + * macros) that can be used to access the device. High-level driver functions + * are defined in xusbps.h. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 1.04a nm   10/23/12 Fixed CR# 679106.
+ * 1.05a kpc  07/03/13 Added XUsbPs_ResetHw function prototype
+ * 2.00a kpc  04/03/14 Fixed CR#777764. Corrected max endpoint vale and masks 
+ * 2.5   pm   02/20/20 Added Endpoint Control Register bit positions for Rx & Tx
+ * 
+ * + ******************************************************************************/ +#ifndef XUSBPS_HW_H +#define XUSBPS_HW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + + +#define XUSBPS_REG_SPACING 4 + +/** @name Timer 0 Register offsets + * + * @{ + */ +#define XUSBPS_TIMER0_LD_OFFSET 0x00000080 +#define XUSBPS_TIMER0_CTL_OFFSET 0x00000084 +/* @} */ + +/** @name Timer Control Register bit mask + * + * @{ + */ +#define XUSBPS_TIMER_RUN_MASK 0x80000000 +#define XUSBPS_TIMER_STOP_MASK 0x80000000 +#define XUSBPS_TIMER_RESET_MASK 0x40000000 +#define XUSBPS_TIMER_REPEAT_MASK 0x01000000 +/* @} */ + +/** @name Timer Control Register bit mask + * + * @{ + */ +#define XUSBPS_TIMER_COUNTER_MASK 0x00FFFFFF +/* @} */ + +/** @name Device Hardware Parameters + * + * @{ + */ +#define XUSBPS_HWDEVICE_OFFSET 0x0000000C + +#define XUSBPS_EP_NUM_MASK 0x3E +#define XUSBPS_EP_NUM_SHIFT 1 +/* @} */ + +/** @name Capability Register offsets + */ +#define XUSBPS_HCSPARAMS_OFFSET 0x00000104 + +/** @name Operational Register offsets. + * Register comments are tagged with "H:" and "D:" for Host and Device modes, + * respectively. + * Tags are only present for registers that have a different meaning DEVICE and + * HOST modes. Most registers are only valid for either DEVICE or HOST mode. + * Those registers don't have tags. + * @{ + */ +#define XUSBPS_CMD_OFFSET 0x00000140 /**< Configuration */ +#define XUSBPS_ISR_OFFSET 0x00000144 /**< Interrupt Status */ +#define XUSBPS_IER_OFFSET 0x00000148 /**< Interrupt Enable */ +#define XUSBPS_FRAME_OFFSET 0x0000014C /**< USB Frame Index */ +#define XUSBPS_LISTBASE_OFFSET 0x00000154 /**< H: Periodic List Base Address */ +#define XUSBPS_DEVICEADDR_OFFSET 0x00000154 /**< D: Device Address */ +#define XUSBPS_ASYNCLISTADDR_OFFSET 0x00000158 /**< H: Async List Address */ +#define XUSBPS_EPLISTADDR_OFFSET 0x00000158 /**< D: Endpoint List Addr */ +#define XUSBPS_TTCTRL_OFFSET 0x0000015C /**< TT Control */ +#define XUSBPS_BURSTSIZE_OFFSET 0x00000160 /**< Burst Size */ +#define XUSBPS_TXFILL_OFFSET 0x00000164 /**< Tx Fill Tuning */ +#define XUSBPS_ULPIVIEW_OFFSET 0x00000170 /**< ULPI Viewport */ +#define XUSBPS_EPNAKISR_OFFSET 0x00000178 /**< Endpoint NAK IRQ Status */ +#define XUSBPS_EPNAKIER_OFFSET 0x0000017C /**< Endpoint NAK IRQ Enable */ +#define XUSBPS_PORTSCR1_OFFSET 0x00000184 /**< Port Control/Status 1 */ + +/* NOTE: The Port Control / Status Register index is 1-based. */ +#define XUSBPS_PORTSCRn_OFFSET(n) \ + (XUSBPS_PORTSCR1_OFFSET + (((n)-1) * XUSBPS_REG_SPACING)) + + +#define XUSBPS_OTGCSR_OFFSET 0x000001A4 /**< OTG Status and Control */ +#define XUSBPS_MODE_OFFSET 0x000001A8 /**< USB Mode */ +#define XUSBPS_EPSTAT_OFFSET 0x000001AC /**< Endpoint Setup Status */ +#define XUSBPS_EPPRIME_OFFSET 0x000001B0 /**< Endpoint Prime */ +#define XUSBPS_EPFLUSH_OFFSET 0x000001B4 /**< Endpoint Flush */ +#define XUSBPS_EPRDY_OFFSET 0x000001B8 /**< Endpoint Ready */ +#define XUSBPS_EPCOMPL_OFFSET 0x000001BC /**< Endpoint Complete */ +#define XUSBPS_EPCR0_OFFSET 0x000001C0 /**< Endpoint Control 0 */ +#define XUSBPS_EPCR1_OFFSET 0x000001C4 /**< Endpoint Control 1 */ +#define XUSBPS_EPCR2_OFFSET 0x000001C8 /**< Endpoint Control 2 */ +#define XUSBPS_EPCR3_OFFSET 0x000001CC /**< Endpoint Control 3 */ +#define XUSBPS_EPCR4_OFFSET 0x000001D0 /**< Endpoint Control 4 */ + +#define XUSBPS_MAX_ENDPOINTS 12 /**< Number of supported Endpoints in + * this core. */ +#define XUSBPS_EP_OUT_MASK 0x00000FFF /**< OUR (RX) endpoint mask */ +#define XUSBPS_EP_IN_MASK 0x0FFF0000 /**< IN (TX) endpoint mask */ +#define XUSBPS_EP_ALL_MASK 0x0FFF0FFF /**< Mask used for endpoint control + * registers */ +#define XUSBPS_EPCRn_OFFSET(n) \ + (XUSBPS_EPCR0_OFFSET + ((n) * XUSBPS_REG_SPACING)) + +#define XUSBPS_EPFLUSH_RX_SHIFT 0 +#define XUSBPS_EPFLUSH_TX_SHIFT 16 + +/* @} */ + + + +/** @name Endpoint Control Register (EPCR) bit positions. + * @{ + */ + +/* Definitions for TX Endpoint bits */ +#define XUSBPS_EPCR_TXT_TYPE_SHIFT 18 /* < Endpoint Type - TX bit shift*/ +#define XUSBPS_EPCR_TXT_TYPE_MASK 0x000C0000 /* < Endpoint Type - TX read only*/ +#define XUSBPS_EPCR_TXT_CONTROL_MASK 0x00000000 /**< Control Endpoint - TX */ +#define XUSBPS_EPCR_TXT_ISO_MASK 0x00040000 /**< Isochronous. Endpoint */ +#define XUSBPS_EPCR_TXT_BULK_MASK 0x00080000 /**< Bulk Endpoint - TX */ +#define XUSBPS_EPCR_TXT_INTR_MASK 0x000C0000 /**< Interrupt Endpoint */ +#define XUSBPS_EPCR_TXS_MASK 0x00010000 /**< Stall TX endpoint */ +#define XUSBPS_EPCR_TXE_MASK 0x00800000 /**< Transmit enable - TX */ +#define XUSBPS_EPCR_TXR_MASK 0x00400000 /**< Data Toggle Reset Bit */ + + +/* Definitions for RX Endpoint bits */ +#define XUSBPS_EPCR_RXT_TYPE_SHIFT 2 /* < Endpoint Type - RX bit shift*/ +#define XUSBPS_EPCR_RXT_TYPE_MASK 0x0000000C /**< Endpoint Type - RX read only*/ +#define XUSBPS_EPCR_RXT_CONTROL_MASK 0x00000000 /**< Control Endpoint - RX */ +#define XUSBPS_EPCR_RXT_ISO_MASK 0x00000004 /**< Isochronous Endpoint */ +#define XUSBPS_EPCR_RXT_BULK_MASK 0x00000008 /**< Bulk Endpoint - RX */ +#define XUSBPS_EPCR_RXT_INTR_MASK 0x0000000C /**< Interrupt Endpoint */ +#define XUSBPS_EPCR_RXS_MASK 0x00000001 /**< Stall RX endpoint. */ +#define XUSBPS_EPCR_RXE_MASK 0x00000080 /**< Transmit enable. - RX */ +#define XUSBPS_EPCR_RXR_MASK 0x00000040 /**< Data Toggle Reset Bit */ +/* @} */ + + +/** @name USB Command Register (CR) bit positions. + * @{ + */ +#define XUSBPS_CMD_RS_MASK 0x00000001 /**< Run/Stop */ +#define XUSBPS_CMD_RST_MASK 0x00000002 /**< Controller RESET */ +#define XUSBPS_CMD_FS01_MASK 0x0000000C /**< Frame List Size bit 0,1 */ +#define XUSBPS_CMD_PSE_MASK 0x00000010 /**< Periodic Sched Enable */ +#define XUSBPS_CMD_ASE_MASK 0x00000020 /**< Async Sched Enable */ +#define XUSBPS_CMD_IAA_MASK 0x00000040 /**< IRQ Async Advance Doorbell */ +#define XUSBPS_CMD_ASP_MASK 0x00000300 /**< Async Sched Park Mode Cnt */ +#define XUSBPS_CMD_ASPE_MASK 0x00000800 /**< Async Sched Park Mode Enbl */ +#define XUSBPS_CMD_SUTW_MASK 0x00002000 /**< Setup TripWire */ +#define XUSBPS_CMD_ATDTW_MASK 0x00004000 /**< Add dTD TripWire */ +#define XUSBPS_CMD_FS2_MASK 0x00008000 /**< Frame List Size bit 2 */ +#define XUSBPS_CMD_ITC_MASK 0x00FF0000 /**< IRQ Threshold Control */ +/* @} */ + + +/** + * @name Interrupt Threshold + * These definitions are used by software to set the maximum rate at which the + * USB controller will generate interrupt requests. The interrupt interval is + * given in number of micro-frames. + * + * USB defines a full-speed 1 ms frame time indicated by a Start Of Frame (SOF) + * packet each and every 1ms. USB also defines a high-speed micro-frame with a + * 125us frame time. For each micro-frame a SOF (Start Of Frame) packet is + * generated. Data is sent in between the SOF packets. The interrupt threshold + * defines how many micro-frames the controller waits before issuing an + * interrupt after data has been received. + * + * For a threshold of 0 the controller will issue an interrupt immediately + * after the last byte of the data has been received. For a threshold n>0 the + * controller will wait for n micro-frames before issuing an interrupt. + * + * Therefore, a setting of 8 micro-frames (default) means that the controller + * will issue at most 1 interrupt per millisecond. + * + * @{ + */ +#define XUSBPS_CMD_ITHRESHOLD_0 0x00 /**< Immediate interrupt. */ +#define XUSBPS_CMD_ITHRESHOLD_1 0x01 /**< 1 micro-frame */ +#define XUSBPS_CMD_ITHRESHOLD_2 0x02 /**< 2 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_4 0x04 /**< 4 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_8 0x08 /**< 8 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_16 0x10 /**< 16 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_32 0x20 /**< 32 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_64 0x40 /**< 64 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_MAX XUSBPS_CMD_ITHRESHOLD_64 +#define XUSBPS_CMD_ITHRESHOLD_DEFAULT XUSBPS_CMD_ITHRESHOLD_8 +/* @} */ + + + +/** @name USB Interrupt Status Register (ISR) / Interrupt Enable Register (IER) + * bit positions. + * @{ + */ +#define XUSBPS_IXR_UI_MASK 0x00000001 /**< USB Transaction Complete */ +#define XUSBPS_IXR_UE_MASK 0x00000002 /**< Transaction Error */ +#define XUSBPS_IXR_PC_MASK 0x00000004 /**< Port Change Detect */ +#define XUSBPS_IXR_FRE_MASK 0x00000008 /**< Frame List Rollover */ +#define XUSBPS_IXR_AA_MASK 0x00000020 /**< Async Advance */ +#define XUSBPS_IXR_UR_MASK 0x00000040 /**< RESET Received */ +#define XUSBPS_IXR_SR_MASK 0x00000080 /**< Start of Frame */ +#define XUSBPS_IXR_SLE_MASK 0x00000100 /**< Device Controller Suspend */ +#define XUSBPS_IXR_ULPI_MASK 0x00000400 /**< ULPI IRQ */ +#define XUSBPS_IXR_HCH_MASK 0x00001000 /**< Host Controller Halted + * Read Only */ +#define XUSBPS_IXR_RCL_MASK 0x00002000 /**< USB Reclamation Read Only */ +#define XUSBPS_IXR_PS_MASK 0x00004000 /**< Periodic Sched Status + * Read Only */ +#define XUSBPS_IXR_AS_MASK 0x00008000 /**< Async Sched Status Read only */ +#define XUSBPS_IXR_NAK_MASK 0x00010000 /**< NAK IRQ */ +#define XUSBPS_IXR_UA_MASK 0x00040000 /**< USB Host Async IRQ */ +#define XUSBPS_IXR_UP_MASK 0x00080000 /**< USB Host Periodic IRQ */ +#define XUSBPS_IXR_TI0_MASK 0x01000000 /**< Timer 0 Interrupt */ +#define XUSBPS_IXR_TI1_MASK 0x02000000 /**< Timer 1 Interrupt */ + +#define XUSBPS_IXR_ALL (XUSBPS_IXR_UI_MASK | \ + XUSBPS_IXR_UE_MASK | \ + XUSBPS_IXR_PC_MASK | \ + XUSBPS_IXR_FRE_MASK | \ + XUSBPS_IXR_AA_MASK | \ + XUSBPS_IXR_UR_MASK | \ + XUSBPS_IXR_SR_MASK | \ + XUSBPS_IXR_SLE_MASK | \ + XUSBPS_IXR_ULPI_MASK | \ + XUSBPS_IXR_HCH_MASK | \ + XUSBPS_IXR_RCL_MASK | \ + XUSBPS_IXR_PS_MASK | \ + XUSBPS_IXR_AS_MASK | \ + XUSBPS_IXR_NAK_MASK | \ + XUSBPS_IXR_UA_MASK | \ + XUSBPS_IXR_UP_MASK | \ + XUSBPS_IXR_TI0_MASK | \ + XUSBPS_IXR_TI1_MASK) + /**< Mask for ALL IRQ types */ +/* @} */ + + +/** @name USB Mode Register (MODE) bit positions. + * @{ + */ +#define XUSBPS_MODE_CM_MASK 0x00000003 /**< Controller Mode Select */ +#define XUSBPS_MODE_CM_IDLE_MASK 0x00000000 +#define XUSBPS_MODE_CM_DEVICE_MASK 0x00000002 +#define XUSBPS_MODE_CM_HOST_MASK 0x00000003 +#define XUSBPS_MODE_ES_MASK 0x00000004 /**< USB Endian Select */ +#define XUSBPS_MODE_SLOM_MASK 0x00000008 /**< USB Setup Lockout Mode Disable */ +#define XUSBPS_MODE_SDIS_MASK 0x00000010 +#define XUSBPS_MODE_VALID_MASK 0x0000001F + +/* @} */ + + +/** @name USB Device Address Register (DEVICEADDR) bit positions. + * @{ + */ +#define XUSBPS_DEVICEADDR_DEVICEAADV_MASK 0x01000000 + /**< Device Addr Auto Advance */ +#define XUSBPS_DEVICEADDR_ADDR_MASK 0xFE000000 + /**< Device Address */ +#define XUSBPS_DEVICEADDR_ADDR_SHIFT 25 + /**< Address shift */ +#define XUSBPS_DEVICEADDR_MAX 127 + /**< Biggest allowed address */ +/* @} */ + +/** @name USB TT Control Register (TTCTRL) bit positions. + * @{ + */ +#define XUSBPS_TTCTRL_HUBADDR_MASK 0x7F000000 /**< TT Hub Address */ +/* @} */ + + +/** @name USB Burst Size Register (BURSTSIZE) bit posisions. + * @{ + */ +#define XUSBPS_BURSTSIZE_RX_MASK 0x000000FF /**< RX Burst Length */ +#define XUSBPS_BURSTSIZE_TX_MASK 0x0000FF00 /**< TX Burst Length */ +/* @} */ + + +/** @name USB Tx Fill Tuning Register (TXFILL) bit positions. + * @{ + */ +#define XUSBPS_TXFILL_OVERHEAD_MASK 0x000000FF + /**< Scheduler Overhead */ +#define XUSBPS_TXFILL_HEALTH_MASK 0x00001F00 + /**< Scheduler Health Cntr */ +#define XUSBPS_TXFILL_BURST_MASK 0x003F0000 + /**< FIFO Burst Threshold */ +/* @} */ + + +/** @name USB ULPI Viewport Register (ULPIVIEW) bit positions. + * @{ + */ +#define XUSBPS_ULPIVIEW_DATWR_MASK 0x000000FF /**< ULPI Data Write */ +#define XUSBPS_ULPIVIEW_DATRD_MASK 0x0000FF00 /**< ULPI Data Read */ +#define XUSBPS_ULPIVIEW_ADDR_MASK 0x00FF0000 /**< ULPI Data Address */ +#define XUSBPS_ULPIVIEW_PORT_MASK 0x07000000 /**< ULPI Port Number */ +#define XUSBPS_ULPIVIEW_SS_MASK 0x08000000 /**< ULPI Synchronous State */ +#define XUSBPS_ULPIVIEW_RW_MASK 0x20000000 /**< ULPI Read/Write Control */ +#define XUSBPS_ULPIVIEW_RUN_MASK 0x40000000 /**< ULPI Run */ +#define XUSBPS_ULPIVIEW_WU_MASK 0x80000000 /**< ULPI Wakeup */ +/* @} */ + + +/** @name Port Status Control Register bit positions. + * @{ + */ +#define XUSBPS_PORTSCR_CCS_MASK 0x00000001 /**< Current Connect Status */ +#define XUSBPS_PORTSCR_CSC_MASK 0x00000002 /**< Connect Status Change */ +#define XUSBPS_PORTSCR_PE_MASK 0x00000004 /**< Port Enable/Disable */ +#define XUSBPS_PORTSCR_PEC_MASK 0x00000008 /**< Port Enable/Disable Change */ +#define XUSBPS_PORTSCR_OCA_MASK 0x00000010 /**< Over-current Active */ +#define XUSBPS_PORTSCR_OCC_MASK 0x00000020 /**< Over-current Change */ +#define XUSBPS_PORTSCR_FPR_MASK 0x00000040 /**< Force Port Resume */ +#define XUSBPS_PORTSCR_SUSP_MASK 0x00000080 /**< Suspend */ +#define XUSBPS_PORTSCR_PR_MASK 0x00000100 /**< Port Reset */ +#define XUSBPS_PORTSCR_HSP_MASK 0x00000200 /**< High Speed Port */ +#define XUSBPS_PORTSCR_LS_MASK 0x00000C00 /**< Line Status */ +#define XUSBPS_PORTSCR_PP_MASK 0x00001000 /**< Port Power */ +#define XUSBPS_PORTSCR_PO_MASK 0x00002000 /**< Port Owner */ +#define XUSBPS_PORTSCR_PIC_MASK 0x0000C000 /**< Port Indicator Control */ +#define XUSBPS_PORTSCR_PTC_MASK 0x000F0000 /**< Port Test Control */ +#define XUSBPS_PORTSCR_WKCN_MASK 0x00100000 /**< Wake on Connect Enable */ +#define XUSBPS_PORTSCR_WKDS_MASK 0x00200000 /**< Wake on Disconnect Enable */ +#define XUSBPS_PORTSCR_WKOC_MASK 0x00400000 /**< Wake on Over-current Enable */ +#define XUSBPS_PORTSCR_PHCD_MASK 0x00800000 /**< PHY Low Power Suspend - + * Clock Disable */ +#define XUSBPS_PORTSCR_PFSC_MASK 0x01000000 /**< Port Force Full Speed + * Connect */ +#define XUSBPS_PORTSCR_PSPD_MASK 0x0C000000 /**< Port Speed */ +/* @} */ + + +/** @name On-The-Go Status Control Register (OTGCSR) bit positions. + * @{ + */ +#define XUSBPS_OTGSC_VD_MASK 0x00000001 /**< VBus Discharge Bit */ +#define XUSBPS_OTGSC_VC_MASK 0x00000002 /**< VBus Charge Bit */ +#define XUSBPS_OTGSC_HAAR_MASK 0x00000004 /**< HW Assist Auto Reset + * Enable Bit */ +#define XUSBPS_OTGSC_OT_MASK 0x00000008 /**< OTG Termination Bit */ +#define XUSBPS_OTGSC_DP_MASK 0x00000010 /**< Data Pulsing Pull-up + * Enable Bit */ +#define XUSBPS_OTGSC_IDPU_MASK 0x00000020 /**< ID Pull-up Enable Bit */ +#define XUSBPS_OTGSC_HADP_MASK 0x00000040 /**< HW Assist Data Pulse + * Enable Bit */ +#define XUSBPS_OTGSC_HABA_MASK 0x00000080 /**< USB Hardware Assist + * B Disconnect to A + * Connect Enable Bit */ +#define XUSBPS_OTGSC_ID_MASK 0x00000100 /**< ID Status Flag */ +#define XUSBPS_OTGSC_AVV_MASK 0x00000200 /**< USB A VBus Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_ASV_MASK 0x00000400 /**< USB A Session Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_BSV_MASK 0x00000800 /**< USB B Session Valid Status Flag */ +#define XUSBPS_OTGSC_BSE_MASK 0x00001000 /**< USB B Session End Status Flag */ +#define XUSBPS_OTGSC_1MST_MASK 0x00002000 /**< USB 1 Millisecond Timer Status Flag */ +#define XUSBPS_OTGSC_DPS_MASK 0x00004000 /**< Data Pulse Status Flag */ +#define XUSBPS_OTGSC_IDIS_MASK 0x00010000 /**< USB ID Interrupt Status Flag */ +#define XUSBPS_OTGSC_AVVIS_MASK 0x00020000 /**< USB A VBus Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_ASVIS_MASK 0x00040000 /**< USB A Session Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_BSVIS_MASK 0x00080000 /**< USB B Session Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_BSEIS_MASK 0x00100000 /**< USB B Session End Interrupt Status Flag */ +#define XUSBPS_OTGSC_1MSS_MASK 0x00200000 /**< 1 Millisecond Timer Interrupt Status Flag */ +#define XUSBPS_OTGSC_DPIS_MASK 0x00400000 /**< Data Pulse Interrupt Status Flag */ +#define XUSBPS_OTGSC_IDIE_MASK 0x01000000 /**< ID Interrupt Enable Bit */ +#define XUSBPS_OTGSC_AVVIE_MASK 0x02000000 /**< USB A VBus Valid Interrupt Enable Bit */ +#define XUSBPS_OTGSC_ASVIE_MASK 0x04000000 /**< USB A Session Valid Interrupt Enable Bit */ +#define XUSBPS_OTGSC_BSVIE_MASK 0x08000000 /**< USB B Session Valid Interrupt Enable Bit */ +#define XUSBPS_OTGSC_BSEE_MASK 0x10000000 /**< USB B Session End Interrupt Enable Bit */ +#define XUSBPS_OTGSC_1MSE_MASK 0x20000000 /**< 1 Millisecond Timer + * Interrupt Enable Bit */ +#define XUSBPS_OTGSC_DPIE_MASK 0x40000000 /**< Data Pulse Interrupt + * Enable Bit */ + +#define XUSBPS_OTG_ISB_ALL (XUSBPS_OTGSC_IDIS_MASK |\ + XUSBPS_OTGSC_AVVIS_MASK | \ + XUSBPS_OTGSC_ASVIS_MASK | \ + XUSBPS_OTGSC_BSVIS_MASK | \ + XUSBPS_OTGSC_BSEIS_MASK | \ + XUSBPS_OTGSC_1MSS_MASK | \ + XUSBPS_OTGSC_DPIS_MASK) + /** Mask for All IRQ status masks */ + +#define XUSBPS_OTG_IEB_ALL (XUSBPS_OTGSC_IDIE_MASK |\ + XUSBPS_OTGSC_AVVIE_MASK | \ + XUSBPS_OTGSC_ASVIE_MASK | \ + XUSBPS_OTGSC_BSVIE_MASK | \ + XUSBPS_OTGSC_BSEE_IEB_MASK | \ + XUSBPS_OTGSC_1MSE_MASK | \ + XUSBPS_OTGSC_DPIE_MASK) + /** Mask for All IRQ Enable masks */ +/* @} */ + + +/**< Alignment of the Device Queue Head List BASE. */ +#define XUSBPS_dQH_BASE_ALIGN 2048 + +/**< Alignment of a Device Queue Head structure. */ +#define XUSBPS_dQH_ALIGN 64 + +/**< Alignment of a Device Transfer Descriptor structure. */ +#define XUSBPS_dTD_ALIGN 32 + +/**< Size of one RX buffer for a OUT Transfer Descriptor. */ +#define XUSBPS_dTD_BUF_SIZE 4096 + +/**< Maximum size of one RX/TX buffer. */ +#define XUSBPS_dTD_BUF_MAX_SIZE 16*1024 + +/**< Alignment requirement for Transfer Descriptor buffers. */ +#define XUSBPS_dTD_BUF_ALIGN 4096 + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* This macro reads the given register. +* +* @param BaseAddress is the base address for the USB registers. +* @param RegOffset is the register offset to be read. +* +* @return The 32-bit value of the register. +* +* @note C-style signature: +* u32 XUsbPs_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XUsbPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32(BaseAddress + (RegOffset)) + + +/****************************************************************************/ +/** +* +* This macro writes the given register. +* +* @param BaseAddress is the the base address for the USB registers. +* @param RegOffset is the register offset to be written. +* @param Data is the the 32-bit value to write to the register. +* +* @return None. +* +* @note C-style signature: +* void XUsbPs_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* + *****************************************************************************/ +#define XUsbPs_WriteReg(BaseAddress, RegOffset, Data) \ + Xil_Out32(BaseAddress + (RegOffset), (Data)) + + +/************************** Function Prototypes ******************************/ +/* + * Perform reset operation to the USB PS interface + */ +void XUsbPs_ResetHw(u32 BaseAddress); +/************************** Variable Definitions ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_L_H */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/lib/librsa.a b/bsp_z7/ps7_cortexa9_0/lib/librsa.a new file mode 100644 index 0000000000000000000000000000000000000000..acef5d8ad74d115f18fb1a1375fa432efeb2afe5 GIT binary patch literal 12530 zcmdU#0dQ2udB^wNN#ZQY_5TxD?YPYWAY44<-4R#tsO{a;Q zTK)g`?RPvK$H?`hL&5bNl)=>({JX z>o~5y<^Oh^S{FC;)mEyMnupI*-sk$el$!k+7;Ind*2Q)u?%Ulplu(kSKG@y9de>mG zeIPmL>Gvf%+ml_MzNcqj&tNz8U8~ouRZU85@86T$wtZtwziF<&m9=&2*Vdt3Y$v|g z*3~)A?X_!T(#i+Eu;q6x%R(c)%Tm?qN=m8D>vVo`ofg%q6rCzMwKA(tJv>!$?(QjD zm1P5NYC7bWWo@@AYq`Oxa_H#(J0YY)PE~dy7);Cka+3}?9kBE6(Vn*G$@Ha}nZ?Xk zZpTzmr84T=LsKgB?D-`#t1=hwS$V-hy*vK(?x{AbEZaH1EZe=bEZbXKmi@|xCePkZ zO>bP4n*MNR=3Rw$Rm1o9(U#8Is;mpW7qSkr8&bJPv-L(Va!04Sjh`6uT-}DFS=|Qs ztVcQ+M|+x6)5okp`bcpw9dt+1M~V)nEq62>v{RWF%S;~4mOHRR-O8E3y%Xunk){m& zu@1I@cGOu<1N277IAm}b<&J=5B9&>RjdL9AO4D`Fm3=g88Na2{j-X0U6kBO)ayUJq z+cB=&(KuOEunqLXdfES3^}4A{5`AZz6OhUFs_X{nQP|};m^w8Fg?8Gh=_AE~^fAlh za7(NR!=FwGbFgJ4b7WsG}pJTLB<_4IIoB9qzj${6|;$F3`b99RHocadTxoKwRo2--d zmngMZ)<*CAs_gYjab0A1FQ`pTF)aY|dM6 z?Q{LI?_B59gSDxQ4PIO$$~l_LtFW1OFwM0WRNFFW!(!UAJ^wy4^D@HBI|^g_fAN9- z9JSok=%D-FTlq1=4XwNoLd*ywRyl}O5ww|e*EW)Uh@egf?Nat5St|}U&8g`K)02;6 z%gsDf@s_mJ{G+tZwIz89dG?Rezp|P#v@fy`PSJl@Rb{n5bx=#@JIJqujjZ9IJ%TaV zI*qmjEjzVvzy01@Y!mrduxGodZ-C7|VLU?^1J}es)wuFP5&HBX;$UR}^(`pNI?K?H z)!rKB7zAol(~PTM@Wn+LPq3P8%d&rr zvSNql&*BQ$u^*J28+eqK`r9VurS7kxJnKAxxy^o4XSttZ{pGir^-8%Olq&*Tb@J!-hkdn=JI6kZG;QOsp+C7F!Tbv2KKsD?G2Caowo&gY@F!!gKL_RY`a@leNirum zMp4|8G2$~x*mI1kQJ!POdN{8muw^|

E}s=J%WJ5q}^2k8kWYZ`yQ+Q@#01U%t($t65jGT5Y@&v827LeRq$txO*wy z)IX5y8d|w=y(%f4w=ra07bp!bD5|h-vOXKEv=&*5t*T(yT2ivi`n=U(shYvB_a)nR zLna42*)7^YS8okmB~=Z!W$mhF_u!za>FDq4>)MCBjoa?7X-_5xdUoHJ>>5PPANBei z48c`l4D`iT9}AfTM3GUeAiZswmk}>l%7IE#mZu%{n@t)qR$pg*zL-HdRrjtMk%`0csen2i+pYS#`Ubm@)z#OL_(u|ql7mm^kQyyZ+LKkm1oOe@Olw9B$>P8s%BRoQd5JfFe) zO=g36uVMU(@cRHjHZP37vtewppXJ5p|Mcq5qo zn0r+8t=Vmw3ZSptZ*IdF373G|k#0kOcfv+<0u%0qId*)$uLB3_WO9oz!84Ec-ZL+c z1?nfyYcj~cpWpZV`yZpvuNCO?P3$xH#PRIY{na|!ihePl`}r4UW*(He#(mJW<_g(y zuE@N;*tGIO82iK_%>1-NNRcrduZ2f z((kA_yZx!myaeppQ<+;ssZ0ZWaSt7bzXoSVb^v8o<(IMW4hy?R#WiwJ>m!&OTTrGE z?OYZ~Wm>StIEKyWYm3^EO~6l00Y6-moX7M-oqo7RIe!A!19cidzMFn3E#g0cxT5uZAB`xtQ_yfuuGaU)R%`-nFPutO~0cB>KTIFkSRl* z^&IfmGtXB~CF%jwG1!fnGSrtNe;8%POg$?K)N>eihfNvktY_R`Psmpf+P$nOl{p5x zW2OxC<>==TlsRVV`Mj?lj_YV`D#Q1x+kE*F54q2cV2-ZC9L4kbLFzHYMm%QTp*{q? z8a6T3XDhtx#HYE3{ej^i|I{Fch|q;VA3h#YWO5Mn5_h;{5?~dJSXq(zMp=J-rfjI+J(@iF@w_K{tYDOF2Fc zet+UK24n5Ur)}7&+M{nXPxkbmMf^%2KStkYz29l3*Te5*G|jx_tPlDY=)uYHbT92T zVVy#D&@LX)c_%P8yn6AQmphzJp#2G!!Q43j$@i;V9-e!gLws-JyA0ncndbaue_i^< z+M%3Y3%}^E&iidokD|Tqr1$#{+ZK&i>EBvr_1jlRC46%JlOd%r)Vg8F-v}b`>A+VQ zHnV&gUX~i25|)KH_QD5$%OXcD4M*z2v5~&Pv72__NGTkt=X2}@6S5YLMc|mrGkxTH zFV}G;?ZA<1oP8!&a-;j@}P!I4rpYTa;j;IkS& zBk;vJT8Lv{4vu^#aPE+!mWCsB;n+am;Mhq!aHJHD)blxZg9-Tx#}GK?@=PE3y8++B zz40GO^BtXiCRcK#6plL2aI8RkD<{o72FHrHVOoGA>)`JIQThZ&O5vz=!;$amQTVKe zuLx`kaSYDEu@gQxcgRso!;!jhjMFzbw$Tn8DTO2Te2$%HKluvBa&XM$8IFv-t|Q|= zg0<`QnOw<{QaI{7!;x_;JZa`JI9A3bHu&P1uMWlz9T&inQaEbeaIA(;9V_6A^Ry7h zqB%IW!3XCKIcjM*QWuW(^bL+XX$Ov!!jXDDNA8WtS2)_>n9DPLlz8Zk|CM;@&^I_z z3P+u1IO^X!C(S$t$AZrVUmc7cIxc{tjuqw^qjkfPF;~Zmc!3yUd(V^NIXLcw56&HO z)Y5RIE*xXf$+4Ao;7BPPspoU#zMOo8V+A!ioQqSke|1QW^I97sVF3_h92v{>GlAv6vEZ}8R|jK9 zm_EUgQaEbeaAeHYu_9g|Mi`Fs=HS=@ADlbnsHNdZT{!ZYLypa~14l~XNIjop3pkRm za14WEF3Y~n+dQuKk>t1qY2ipcpJOvPlCN-dz%iF+`uJ(vKVCNn$1UKf*DE+`X*g0B zj@@K}`Pc|aj+DZYdOpW3;7Gp0F#?XcJi}4qVI}Q81^dU+IXE_gBj*n1qn3svb>YZo z4mmc^4jd_kBlUcajo?VW!m%10b9siN#6!j@a+G*Uu3XoYvaWTWS=XP`{;_Nhjt$_* zxkHXx8jjS3BcD0s7^fXLQVK`v`5YU-k$i6F3)iMwCx|SpMzsP zIO_EZj#?Uy)P-X!nSf&qk{l_8BlUca_25Xp!m$ncQW6q+#9upZxda(~tl3=?goa`^x%D^Dlk% z8x(-#b0<;a~mB@OMhyJf6IC{LGo2*Zg2C+|2px@ z)BiEF|3&qQpVt`Z_YQCT|D4-s3}2Z$JdeRE|J+8=GNrolX9>?OKq%VbA8d8ANn=gw z>i~SkjZPu{^3QENKS_)9 z=YO2@9de$-^JgiZTS=EFh5xDac@Cc6D90bO^*HFk^Bwq)-ggC6tx3fpEt2zHJl`?f zzF421p^1Z!Rp9&w@5vR!dF;(5!Sg~q@39?{`s;wo^e%Isf*kkYQ;ueg;luj_NFPCe znjx9~14suSsOW3)tV107$cT5KW7ik=^(2+iTL#+q4ese5=u?qSm1ytm?Af;$M@xE= zJ?*_b$}XqZ3!G{<$4vC0_p1)K^GrpBTu0pVN9AA zD3SjvB_{D@$Q3w`@(ai)B(Q0}u90JqEAW6h3>k$yhlR-WtB_1rVlpxvhGe=8hklsu zgk<^&_+9gn?)2~1>Z7=lF6_8A~;=}tp t@nJfJxyJNKNT$z!#!LSUl4-ZnOV>d%J+#P6AAn?f5{Hmj{sl;;{}(@F8!rF= literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/lib/libxil.a b/bsp_z7/ps7_cortexa9_0/lib/libxil.a new file mode 100644 index 0000000000000000000000000000000000000000..721365e846f8c110612a161da888774c95a84009 GIT binary patch literal 1267772 zcmeEv3!Gd2qc-AJV=5>m}Dl9;Dk&v2}Bp|^z`&(#>}JB z-IE6o2?~NMazRm1qltnpi>TMa3-a;x)Uv=KlZnI9+|Z z=MjVuuhy^6`KrG9>Z>~S{Jwg1!-_;E*?VbaQ>@T5TTW%S-?7-j#fz3Mk~CW@g>Www z;-cRQ(ei{4SESXmSVA>Qc;@m{z;GD(Ps9~a_FLOtJHA;jZt>iO4a zgy8dkzM-C9O%jgNCY+kB!kIQlICG-HSu|fgEk6;?RgVbg+FOLvH$ym?+lBMjPYUPY zGs5`?;7UC|-Xa`6KYvs>FFaKAxKo#lGx-U<;h+empAexN9~Gh7?h&DVkB|I(dx;3W zM31+6iSV}EFT7M*cth>NyA|%2@d;n`kO+52MR>=Y@jai}B*MSvQ+8#GDBGM9Wp8>? zJ@0E5Wu=~Ho)cxi-XhAKM@9L(y}#dcU$rQIkx!)TArU#}poq*nQT$x;q==khPet`z zqT;M4M}OuY5EZX};rD;u{fMZrpHF}pMi%7*F+-4pH)1_oS%q?iSTM9v9Vn+sF4j5f#-x zi@fNkW_v``>|L&&yV^y~2Vf6AUwKH>{ODd$b9Aq$`Q;t{Q(JY1sGYN1)GnNK<~&dB z7PY_l#%X`*KJu6-`5cLex)=FGJJKQ=zd=2jH6nV$*3qAXo`~}K-;apsb9ag8?^;BC z5uU+Q@;@Gs_h_Jo*F-7O|e`^l+2U%f|6`1`$L!c&{%GjaL~G2-*u z?nKv6CMV)MQ_0*=CZ0=l^`}HUok?YL3F5nkhVV}I4`qSQ^$n!5A~%o~@pv*l9PbXX~Wx^xT` zrqa2-p+V7kO`f(bkxQ&({^d~}nN&|Im+TFocV+tUxp4)ytn5y9WaF(vgFSuQRGKsj zd@`#CWhyO98?uMRVxg``g=s}%yIO}*Jw1KN zKGY}6YhB;qy2S2vsYG@-lNzx6kd~D@w^@{yi+=ry%z(;3KduEsNb*6 zrZ9>;RDw5WQ5$Ihc zk&3OOb!CSRrPE|#zz3g-al-01WLTMo(q8zE(jH*ej_y9+14&LGFM(ANqZ2NsR(T)5 zgI?uR01xgZ@u1&0G|<_bK(#3mWT+>%E0Ia9?GE@MnCvY}<_Y2&*>i2SZ6L8~IJ?I$ zT=w<36tEhzDU%q?_E<$|DxS=yK)oAC1cxaw0xDng6h+~nV$rNi3?{b8$nxP@dlQ3$ zseYtK;x11N_vhAjZZvLueB01qDqpcA6|j;pfL=S8&1K?k>sD@Dx5_Z^ao6N=n}%9j zH(s6SA4YeiqDA>4=x|bZzxZ%;Bmu9h&>~aaw$~M@LDFP~(4cklGb!e-jY3s`+S2eLMYl`EB^xc(Wleh=oDKq99^%5V0hPxG0EN8bmBJhz`n6@nFjRZb*GxVRcwN zkf7MIs(T~4%T`ERkZ86PBKz@m0o=-dNM8Zm=D||fO+)O=3K(9V85&r#Yt!zM=#9nb zR513|-V{W?LZ%(Lj21d{Tx@TNgi*Od59o!zAvQV1p|tckLf2PK{M{R6BG9)h@)<)|Y{zOFhmM z1kzQE1m*hS9Hd>9={E65_*IF)?e>Q;9kyF0#YWhvvGI0-Yx{VIMTulYhS4Hq2Qy6bJ39HKU60>n2Uaq z6^F2rvZ$z-+7&9mzhpTCqf{wT;jPao`Yy%Hq9}?ppZH*Eiqf7h7R@D428w}17KP21 zKs>92LsTVyN{JIP@{@dw(Fg2?hc-T{zvVeFw9}WLi)XMX=ZJ!7Dv9yuvZQMZ*u}4w zbAo!@MvB*^23j$dx23H+lUD)OCkNmdNMO+I97yKzo&Cv7d|ls=?Dym_Ddlg7Hqxh~ zzkdWDUEkYNJ5&9gy?s5Hk1~M}m*k{*r~%x@Y|eIdWNpNTY`U)y(-}mpT?DDt4zn5J zL?Na%F<6Memlh(VylgX3y{*O|@6f4k>hD^a%VqkyhI5!jW$&q~CMG7OOMkd=BDdEe zS9gPMr=0EVk#=pBlb3o9Q-;QO4N}GR9h(Oscq?aq%CCTGBV^Y^HdTOIn>9|AILLcQ z0Ouywu3v817ecl0Jr+Y((GH}#&}9+APqAoC^+Eqb2uOyQ#mPY>%xoIEs;^7Va^~@! z$gRO`&tscRnU3q|X zupg7qOvdJ1U;oB+*XZwrPm-+y9eVAAjPsmzd^ zlqJUYRrYx6CPi%VAQ>u_!ZUIc8SRF-virg5G|5Hqb?7T(csp->o-$$TQ+v|PyY@xN zWL)Myrg>GzRe*vdKv^PyqeNbS((M9$T1S5(*E5tEh_4;&84_F4199C9R3t;goR~+^ z!b4TaV!UKljJEm6@c63D>6L?$QX<%;ayGD4#iEF~DA1A0^b{a9p-M*}7?7%$DV(Cy zIGH%=wc5=QC!uprqvTS7PoT5Luq>Qf(b)VXjz)A0_4lW`i_q;mvgtl05Nkr@L1%wr zX9{8=I(I)(qUFMYKjLV5NcVx6zdR#f2h}L#OArOVn8LNNA4b|fm#hA=(8hZ%>-L8VX@W4E^ zuo_XaKHJDu7_|L*#x<5qQFYhYqJ%2E?xhi*aqF+sPF7pL$@)~XHW#Dw?a`;S6Dz;- zn(kat5+$xEfyCyMr(8O5(&5igA~GTZQFY7NY0gr0(yH};X_s?tri*MH!m1A@?lj%n zZVUr`J$qUc856X#n~r>eY07m2$&z@yq^HFeYCtBHbyXbmWSrj!X5c0iV70G;Ir9nf%h6Nqe6iPvjMuLL1LDAXyq%is9DYrii8U6#7kk;9q#wHLpOjEvA z+mv`@`&z8G>cE#{e?Tf<=>pTAs_L@qu;m-mA1VP+Gm<%3fU#mJsH3XQLR7mvliHy} zBRf|0Z|{_KqGr=Y0HSke0x zca2%`_fw$?u^8{m{(g)BOkPk>6oomZW?c%U1dU^7yNcVzwrIr0RB~qkk;M`lv@A`4 z&-K4xT_THF5TDh^9{wk3TAxGEL#AiAN3Np#d^v(^2a=bRwK^d(|40mso z%VauOph0UaKE=;RKe8ees4nm88M3y^rm4y36~Ac4=84PgsmZ)XWUFf}vrI*m>F!(43pZyw3oqH}bKSz~-x%CJWRtP7mrT zhS?aU4}zscuTHB1CRegob{}zQlY2VgccB+KvkBrEG{VUX7knk*e`YiysOl#R}PoWR$4>`Q=wdK~!6^p-#zjHW?J)M3=gK#+i9UHlYE}NqiTj+tv6=MokaQ3!UVpmon4%&Hu z3=`uF+SSd8Oc_vPP$b;&BvIS2z8nmQNx%W9)bVr{--+Qbk?xbUz{{!M7 zhnkR)n6#Nx>%*j)#O%OC5TY1T+Y4+|!53tc!`m=<62wW)BVqd>Z%Bp+ybBsxLEv1D zpKnL2Fa<=z7?T538dXS^?E)1lO?s$rP(~^DE+cMJs-_(2woiL4U9v=yELyg3siNIl zdDH6l%N@tT`7LD}F<0bWLU`p8A6_ECTrovVhW~-1(Ut{2``yWtzxV|3Vd3CB7*3Dj zMa9>M<}mTIE3alGO#|OT63(WjLND!o-WRB!Yxim(kAHoqgp5*Wrmc9nM0c=7_4QORGXi zja%=WTRRcf>9w1u)H~5B2&;V~;NIw5HZ4^9>Z(hsF0ML%+HKCX71NxFh$$@A0+bbb z*EUxOl)wl$a?^!`Vy|cJ3}1gc7?TmFVhg>Kjb<4|k`UvY0a**;@!zRg&N;plfDx z-Hp90ZdkCn7TY^cTwhbD%dvIXH#lj|Z0*x0l!CSNSa;lXU*HtY(I(IK(L zm}2x5S8a~9E?kC_hmDIGn_~+GlIh{sB(ZxuwR=J0Vz_(Y-r1AhxtR9;p+s&0zVJ0z z#^?qDpDo|X-q*mobJ>E#yn*z*Y$`cV2iX=|uzr!=h3_XP$wd(P@)O_GJ2a4L8W`%$ zG<9PLYFfLov+25~ZGE|>)Ie9NyF1mL-PMFlY0Beo{f;Y)I%b60I>P&Oac4j!|xU-!LoibjA z9V+NKSbbHUH#8w&Y!gC_udoqT>mWKLWK;GjLIMrbGNC}|kf^eJ8NMdqW;@H9kf_f) zU<-+8z&+7#rOeCONZ$mDLQalwS)2`6iKHX%;l&L%|i zFVOg98sb2%q+hLJyM~<_zFxzGhP@gNX}D9v>ot6*hW8Mn8{V%WbJ|7M!*3#9rWf!g z?Pk4lfn;w+f6Ca_8J>na!xd|Rf)zfY$a^Wr1~3)Y~-1f?Wz7f3e}zJ z8s3J}Gg$FzRQ5zyS0=U7_Qh!csJEJjBFf;P0J^RMTtD~MXeLO8Xry4k9qux26|RR9 z2ci+1WE*kZ#w0>`23h?p8b|t*}aZj=jbhzsrEI`E3Qi2Y@3#rp54E54#BitN3?3 zyJ*qI_$A;rc6#-|5u-&L@rtj4^Q$BI&+~ zfk6z&vw&f_kRKuA1PkA^puVubFvjp>8f?1dNZ+>&5ul+~_k$T9pKR;K9pU=Z{37$oG#B;HuNYc;i_;f7zS+r`wFJn~$zl@&! z{BbY3;8^tR6B1Gu_M#tpI(qgqa1$Or9;^DFXQNeLezvaT%g=bvz46FP5k4pOAM>JD z9TCyJ#~3Gh*FN{~Ve*cN=+V!LH`br5J~+`6=Y&ss2SYZ^`sZ%?73r3MMIteCk6LcX;`z!1>P9#Z z5hsl&*uTY;18+}UiT75^y&3i!EI0cl)_Y}C1u`zmDqD>MFbaNy1#ThOUm3&pa;!5EPSkY+1*y~;QM4QoPs zY`O)A19->-eYWI>A}t!5=74#vVFG_+4USE>AVF*4Z;YX1WwxeV^gN52RVg*+vSjfh zJ$#KlHa$Zj0$nQekR$v=Xblg~iXN|vI_QHp97P%`U5rcrgYoKFcmFXFz3bTCX#Ek4 zzmq5C*+bV^<1_*r%3$A5?i?co>Ey87deICwN#=Nv~4AD$IGbQBHX(1h4qj=IlX zaCq-O?LX$u{~GK=hi(6f+P`}Q|0&vk%?SSW+JF8C{?oO8bOird+W&>`??3j!4t$?@ z-!Vt*Ju1X)$DVQaANw=dqjfI6=@4M(_>;i#8#yKp;c3Qqw}6IWnt^{5{vvun=IiIA z{jOsVH{jc&Hy>tRKLFeV^{O21hy8wSKLGm{(23aIWB0<&vSXS4_T(g<+$guh9kc3>*G<0pXvZw)IAs*4{^p~UO;~t(4ws`&x=26T%@?DeZaL1pip~Ok%sJx4-g4xzmi@;*vU1X)N%5h>2h*_coN~y! z>%ie@fBol&r+oGuhp+zI^5f23uRHSJCr>`;q^~*hYe4tFpC73dorjN|Joz2QMZTsS z&N?Hb)lQ#*m5;UB#yAW(#CpbgrIJ4kS zpIL65o1#^|%*5LJ9H*(Nskvz(-gug&qbYP&qjWE7YQj(YgzAW*Aq~ywkPH#l=iIbd zhd?m>%g5*AWK=pKBQ4A2Pb>#PSJoeFca0XY*;9FaoCY#Pd}iu*Qpm# z%mq)VVYvjhSTyjoIPFH8C%r2WZ`L%!DUv(RGSf)@0+APTDBp& zIfo%mp5#yq^ZdzXyy5trbiz%2l5NSjDRZ-38TT4mWE-UA`I8&)R&7$bDRZ-J(nbI6 zc(aX4C)}LeXZtkn+hAdvHSTx8!v4XyKMV`|4�Z7Pf8U{vs^wQ;hpDSlHhf_YYu^ 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%0DU=HfY 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

kzeb$bylz>Sb6>K|3j)cJOGZ7zPyoMf!0L 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 Ekm$#o+)2nda)CeJ} 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 Bx4-}Z literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/lib/libxilffs.a b/bsp_z7/ps7_cortexa9_0/lib/libxilffs.a new file mode 100644 index 0000000000000000000000000000000000000000..91e939c9d7865c0882acadb5bde140e3978fe6dd GIT binary patch literal 122322 zcmc${dwi7DwLZSz+stGV!Xz^!LyYnUf*^!s!bK1f1_%m@G9*DzX-ObKr~x7gh?Yu# zAQ#1kn<9leZM9-+TdLGU@lq;STd|c2R;smUF207+i?(X3t(D*N>~~KRXwUhc^ErR~ z=94{Z@3q%nd+oK?Ui7cX7hy12e+@m-B>dU<1ggUVU9ptVWd+Sod8VSQ`s z;w6gUj^&G68^ywTOO~xz+6uU=xp66gEVpo8Cb#9zr3-*v(6p?D#7!-YjkhV{hQ-S> zIc}6i-53Q!9_n1UypiQvm#I_7X&RL8el#&ybf<*)&2WjgMoKUkT~r|6zh>C)M4d>B zx@fxBRq^zWx&aB%hICsrEn@Mc8QtNC=F^=*)TS>L!Y{VPlUepXiMGqPJG(F4?pzi) z>6AuxIGV^yYt0)CO{-3aKu4NQ$QPnIorARI3#Pv`BW`5H?-4rEULnqE(c087!~->1pVe_sqT|wsBoCA+`b2nBmiTGs`x~D-qkDtte+sW|iZ&XR`^v2+1=nvo92f~+}qhZ7JT&h!0FCT|bC_pUBxrn3Uz>sjlxUB1@Ybm>~h z1Nz-pul<*{yb8XrfN#{^;TR=)YBy+KKw1+U)0Dvw@${QWH%FmE=!*60B9Io*c(NGs zYKRwscSgTfC3OOQLMImRZHSlJ>rx`J-SLhwQeIz8`X8v%5-u+hh^2g>W51a8HfKlU zr3n#NWrT@PqweBhRAa z1sZ5097OyWLK}1-(0=NP{Mfc$y@-oKHxHcY7!A45=d=al*M{QSy3)8tyhq&QV}0k9 z9p;uLZu{r~iPdZq_)D2%@$@^;m4NIeIg`_uoU2Iw|E0GcLtBpE3%~kepjkpQi7)*& zzAnBS+WJ7bfG40qek`AN7EqSy9nF;Hxf`~qKZ;W3(C{@9<@+5{mTnCJ(6@uwyrOSC zb9C=M63<55yguAYlxa;M)!$ftM&FGR<$a0eeO3Tf>I)%*xwtQ!hZtyDi{Wkc4}dq% z6k+TO{jbQj!oe#UKMTB78k)s;k}S%Cix>}3-bm<+j4vmCTxb{L&oN%zXFuYW&-^V) z2Ud&`)p-YjC^Aqeu%hyEQImfJ>A;E+!$ocWY0_%GU!vAP3ou{GdqrkmK2og7e+N;0 zHkf)g2H$6V9^+pwWUDSU^+QN`hZjh(m!dN7h(hYC=r+`(&%l>=RFM4jktD3`y&9-2 znRyMg<_qRBKFF)Fkgp*3HKg)pAxGqW2642!uY;$aw-^{B??J>(q4x(TU$OBhNC%J0 z`Y7wWAoOg+*IzyPzzNSKp!=KWV#H0)kAVMJ#(kdgz=?+F8`3(MWr1ZrijskP~ndy7mK5 z=ecD~QQ${~1zNwuD05Lxv34nn$+8#sEPF}Mvi&sASnxyHUf@)!^`qfk7B%dwGA-*7 zu+#Pjao;$Ikj2~5@R$EWt*cVQRWJlY?1ad zDj4hLG-*vpTu38H?H>U?o3L=!iGx8u)f8qyVFO5O4(Dp2IG-j5aIO%dxC`>F)x-VqOy7 z7m?8QT;>lz8k4*5z6WUx-M0x@W0B_i)H@9cQ}@mTXh6CSA>4wM9=rZdB(O*pxmEbe z(mm8FXM!&i*9v|4bsxR%_mTb%LhtF2>kn8{T#8yvEvBy!BEJJT4nd@IRtSI8palrg z-_&O6D}k-nTk&0^-vMOS9pDzZ4lymIdC7V(h}j-(Z{e>X{U(jgZ$*rgj<&Y~?m;$x zvnHE=4A>(Gl?#?M2yKgtd;^G+2vR5aYQE2b1y&g1U4-!R#ujnE)E!eJQvA)?z*C6!X1Tom!5RhywT9E%Sa7R^Z@95E5w2jRv+=9GWvbs-^ zbo;OnJY*wobmjd5auy;;d1q_Borr%4;ZEY%hjTR9hs57U9Q*JlP4?mQh#p2jAI{a- zhbIw!jv)K+^P23#_mKV_aqPo+n(V`D@bx0}4&jTfI;&d6KAZy_$H)Jq4=-K^&VOXp zRNf&dRNG5_m(WW8L>s*Xks^eCE#l9l8-e&RgdolA11aH5B&QKo57dVN4ulpYmmv&) zHCu>w6w~;Ht`eGG^FE9kd~Y)cBEhvhvN5qqmlGIgfA}3zJTD{io|+E)*#phs7P&GjIYNnUjXTS$an|=%vd{H zq2XLY9PB+4$r4uV=G=#fLGSdV;B8$w`NU3j`@`@D2Elzyh1_u~pT3v6=|is)w+7O! z_W1&+tShZ6vZn>dfTLbOO!k%8M4*%<2+V0h z58oZeY*;F?v&Ux}xme9*%1Tm}^;(jf=5o^u|6@`ilx~U2po(Yp7TF~x8Tw1Ww*qCd zHEmi@114vrDlFOQsH<1GHlc5qc!T;*3y$kc%G?a46k4(FJyrXXwnlOapb5UQC7w(h z@&2= zcz0#l|E97_G97?SUsq-QG9m!mErNYsbM>37*(LBSCG0JjW4T7f%SN+Bc8Ni82DoU7 zT@vhpFU`{i<_2LE7v-|;0d)I7WhijZm!j99{XwQSK06y$V7jNLrh; zY!IMpi5UVL^SMdaJcml7lljwvAf?%rU5LX_8m7!xnh5B)Zik^EMz$47jk4xJeOJ!rwK3@-P-hW^1zwS?8z=>6Lw5J{7a( z8W4<@%2gsk<&atY00Y;Oz7Gj}%!8ie9xY}b_dMa%X7xbLbWyV!M9p+jZj~;o+C|+cbWPJmCJ1CcYq7>> zEx^db<}vGInf{m%={C<^5A*jDA|3baXWA91-9r6coarjf^HC%-KQ(q>8Z~#Iu8d|S zYNm_op;?Kp2Ks~v&7LsdF?(wE9Wqdwm6SCugD%bPH21Tjcg!;ce=y$%$Y}Oc6(O%V%cvU;5D`}|f?vFWmjyBt@+pFPwul9uIxkF_Av*=;-fOd%G4r#A+ zpY#c=KSXdyf0oUBRtMwR0yCa42d`!~zoI>>1IjAQ6WSTFImj|Gp?l1ByG$c3WRU*u#>+e~GAu)q zw6L;))Gh^N&f18WkB}MIsMd^DNzVAf>g!(-Ra4Da%6CFLf8J0+Y19qo))58wDR%__iypi1x+g&8b!s5 zmgN=o%a;sWx@>9Vu*UlNiz`%C#gh63ixw~aZ%JD2Z0WkDSilCZYH4V0nYZYU@} zTbddho82f*n{XP*+KmoPv-BWNpYp6rMq2(aS=uzqgUDr;?ui5~BV>6znl;D>Uu*Sl zvJ8)LSGlQUo%ZJ}lryq4(?H^x6-b0UnhDeJ7{>*%SsvpDYc!*OIglQqo0>7GJOT!l z$O{_PT?N2$7${Il{&gsQt>r~@q~|&-=&80w8mr2!tm}ZAVR@!l-f&QszJ{g2H|Q}& z%estd<*a9<$Ebh^M$WZC3*uPba&TNKnH!!FRxVHw0F4a-XEc{v-XP@6vpi*1R^>3u z@)$MOhO7X{EKh~y^JwLWjIc_8C@i<^3M*W}mKn2Hna`*ww+fBBuC>AutFTNKDR7I1 zprWAhLbr;7#yu;$T8wHSCAdR~;Z`3&2={+bDwSL2F;-nGbu*9kpj8@WyvVRMtIsgD zcEz=-$_lF&8DLP}yRyp}ZOh-QQ{{Nx?7OqT=NrYeLASk4A9+J|T^i!E{6$!4-bw_(>S7_$n= zJm&_haEO&N+_J7l*IZ}ic=}kq*p5m>$^JUhmzP_9qouqY_GA>5dyH&WL^aBKZVO67 zwx|pcLR!YC)!{JE?7vv0;ADEPqhLm*95>b1T77}+waDsQM$@%WkJ-oa1D7|n!tzI~ zyfS{9o(frNuq-w8TI)(sXvUa@)|JN8a;yKfT@;toN^dD=6(iWqh=e^x@xuRFBN?s! zpEYt(xz2UTq^8?yc&$8jSxf7@$@R@GQ&zQ#>Gks)o5Zx*`sS*pJLlC@RnME;bla$i zsF7FF)s44`6-!$d-@3H1!RCdBi$3oXdfq%_j2J!-nGKVdEnT?yR)JzO7A|aQY!%a5 zYF8{>y!6&8_-9emv|#z9`j*Ct4GqiPD{Xc0J+Wa){qT8JjV%k7*UoRkUB)#x%(5p} zjwWxl10}z-H zQcyL@UCiXZCubQ z7Ra0Ss@XHDt3=bXrMKGh>wGwL^tKyT zEScZ9Tqq^Z=DmJw`7&AM9853Mmf{L%{)&YQ1!bveZd_1R-&!xGH!i)kb&*&h=M>qw zlb5zGZ(4pMSXC@qwxqFQ$+AVuD;hvsF|E3$;;xEY7q?b4qN;|5#)g(VDw-D0uV}er zUVU?OOT}GxF1>x;!j}0>6-ySkEU0L189mQcd;JyjBBX3tzMukg9eTF{Q8A~cA=Wa_ z6?IutQ)7d0+jRLzw5e)I{pBMkEpF}VZ_I=XL{;O;#S0pzH6Q|=xGHklOkQ~Fv~J~0 zYnhBGym9ifMUBfFVS3Y+Hm_)%+_Y@LZBy?OlH~&Qch5&7TqVJLnj4m{6zFesf$Zfm z5T<%c&Achq)ibKa)cTew*H4?#qw8qd8N+OBX;H13zHHfTE1Fer)HE$?t;O80@}?|@ z9gCVf7Pl@~RJn3Ym%Vfkph-8?PLUlotxA<)uk~o3D=jYhAXsc-HDr^~+10V?S~0P; zb@}4?EAXI2#u63h;V{nH<@HNj7B()wei@cP(^{(WxW=7sYZ{iVnBUYW+bpfh?TqHu z_e zB)1*^I@qQ!TQG^k0<}p$)HM>Nfw($Q4rbQd{$^oAL=)m1kMh*sm;p>m?#HY*>{K_h1`Zou$$ zRo*2z^-NzY4V@-g)3~%jHd5My^d{$fO~_u|*hJ;avC*w@bQ1gqGo<~BYbH+~YY(1? zC!_4@#^z-$i_!OYUZz|vmZ3O@6X)>JguXgArRgLRL&(b&{8KXdbNVLs*ICv#nq z;g`9nxsZP1?`x^ zn)%%yLzJonNi@`de!eL#Q~A6J#I{R}M4E9NZpm~Mke7m)^mRz{PB4?6gEX%MGifBd zJ_h!IJwJxPtyGVXAxm{5j0?13NGt1^f4+7M(YrenF+ONp+T zOil=D1*TRHuGctk;*(T89!hjc&Y!9k4i)y8-(*4Q4(YyHvtyoisTi-OZW@}ARI>nAj>TRWVzkMBcHbr#WtQR zBrFl)3?TWv4@iCi3^JB41!Va$K$fp1et>&3#(a)nthL1>3hr0%2?Y-*$Y;OEhc_YQ z^C4jIKnRPI1lcY?;(6;tzI;T5_y&c)kNCmv*wk?h%hAKzhkOMK6vTsXQl9>Va5(e{ zq>CsxTETG&UaR0t1$ksg`UV9TD|m;3s}#+a+%M5C;U)B9`i7r zqhMG;+5zzq1;;5kRYBSX^Xn8`qTpQ$^0_DG?^KXCoJ{i>CBmZ$o>1^@1@Ta(%s;1K z4(x#ReHG+=CesrX`GgwtSEw`}Az*r!g2xnmN5Nc-LFSh#I8DJ@6ue!*FA}1Uwy5+j zLO7|16#S~fKd#c>QSeEHe@>-;tl&=+{+BBKx`HVM-&OGUgplvAD*bl_&nY|~R;C=e z3I+)w=O6{g5<-tR5rR*n!Z)k*T`Ijd?qOT4Jv&TA>{m=g7X!AiAvwD;7WyG ztI``3+@kQiRQe$Wzp3E26#O0`>OZW~&ntLT;eVmhuPOKjA=>eK1wSK1JHlBmAKq>< zKcdoC5TYGdDL75R>lLgfME!GBx=z7Hg6pSnUK?Q%R;BOTC zBO&Vht4iaTQKoYVA!ojVmnhg@!9j#5H(bGS3LjN)io#DPgnTmzF{$0G@C}6EzevH` z2|>4#5Of<9ezStx6?{O!hY3Od2qEadr|?fH_`J$Ls^A+6|CWMDg?~@M4++7?!2KuX z@+ufmFr?tcgs8VaA?SxGe5HcpRQ^Pjf1^s@qS8$&eK#TWcfW#r6nsp<|4{I#f+rOG zt%7G2{8&K~n=JCnQ}D}>k#@*+2I2Pf{GV)gaqcwNUm&B1-s|M=4nlvsuc>YSgE2v49NG9Pq{ z{P0<33_lT-DIx5^SQnyT2x*ol9o&i-sL~l03HB*)nNNn_P#{R3p(BHMMhM_-1b!$F z`FDLlcQNcI^U36Kt=Ut)!Iud!2Nh60Osie;MG?=GK~!7}Ba3$l(VbU)0o`+0|Nijb z(A@yKp7pj>y7tL>*}jZk7GA(_CDzF{aG6g=rujhhVTtsc?cQ#4kM0kY6g&> zaiv%nW)gszx(IvPWh>}9fan7}wnCC0_0BrMuj^wD!V~lvCctK*l%XeGV7NGM@1CK< zm2KC%YBoOq&-c|LBO{}Slk)%lzFK^{tflLHwZ7b`9*HN>G6zrWrQuTj!p3_Qdi!RzyLR2S7 zCqzQN-=pCjF_!uJxpOZI`#y(dz0)zpF~^8ZOz5J9j}HzpBBvb0rEKKu z%HTrXUYpRwDJR31??rvo^Sv$W(2*XQoHEeX z!;#l32iNTywQa$r5$Hc%R<}XQ2t4`=^+)4;R@0AmQ155)z8cEaCb2Xf!umDwy5q6i z6W;Fk$I>i|_tgBLgPiWWWPtJ=vIume+0m3givCN))8#SnJwhG*#ql1Q4tZlY zu~Uq92}NYB^K|8jk_CU}Xvc=cQAFFW#A62A@K4~q!IkgJ! zpMI+}p1i5!OlLIKo+?B6tjOz~ridqd!`8In>yufL7dvf?XS4a3qXpI_zDGXrbt7m? zb@3$oj_;nzx`JyHkEwe24y-j3dbFWO^zoW`7Ph%@^xyW*aOAB{E3&TB3>sSUQCV0o6++m3eXk@bl=rJbFcebmX6&kDRKW$r2G1|{d~;B|BS zOy``^bf+I}^T#$MdPk0?!6&Ijni*!wjNFrmiXBdG{fI0>+EVbHu4tvcDn+_IVk8XE9xzYJ_fYM? z1C9pYI4gFhQ|dkjKC#!G$58evRTl3H7tL-y)2WG2+S`o$$QzDfZb;gCJTE4G@1=}B z)Wfqd`SqHl)1!H=OIcA?%FY!14|SbqR*&_r_@J|u~G z0(PzD5d}jw<_9q`rQ4HII?AC910csh$TJZ1Lk1(iW59p}Y()08`yOqFgLcTeH1sw4 zlXJoz&ZnXoHi)_`5$9vI=<90C9W{CV<-G0oXCI|k6J?>h@QIQaQD!oH$vTAUq-DQ8 zDj+tDg5Mfp*)NVV!5@AC{2!D)te)j*XEtmT?;X>hpgzig`fB;^FJNmLGWuP8+?Y(B zJ2&>XXan`i{t|W~%`$)a%pI$pD3h@@Lg`03W~M|l`n4^d90XnG)II0~><7^oH>R-{ zfvHx@`63i~(19M(o*3m|U$kQWsHK1Ld&I0H)^m^pH0W0YX`OEZf`=Z%+=V=xD#>|d zsBBj(^(Wa+v(hu6GmNJ+eGPp8d3c};_&cfV6zHIbu6)kzMY6wRY3c{IvWI zmiz!~EVm8SY1)z&+YDPn{m6qnJ2;@Vioe`ZU9iCkM*5&%!(D@w}nn zZKBUkQ6}irM0v`w7kUj$ScY}PP3dn8M_9qZ=J} zO@hA1*wXAt+XME-U0P&4=B1aU|I@(d86}4yZb}}4ZJLlJOV!tg`p%$#*+6quq(t-2)ql zr+szzBm(d`#dYmc=Z7Hkqk2v9udtctrM}#@>q-acXQ_+#XTa~H4I=VOC+EcVDRF>f zv%{GS{ZwFm5B(Ksk-vAP@p}nai=)2Cz3`cDI{iTRJlb!!>F`q`Z8zVWvfCyh9>tut z^^DoJ5o2(p<0Xu~>DU72?w(613we;VjP`qLp}_6 z&%=PQv6reCrmTM~<9-)v49h#Tlb%|7|gT*y%&s)Mv`?5_EH z8Gh=6y1?4fup`GU_M43~`fB;-q6T#N5sD3jHO@2-U~XxI(9><4D*tO z{BXxt9FAYk4d4B=iv~WVHa!$|U=51jk_e_@Z_wNMdfIrOY`~iT zD^9kJJr453k&~zgP|Rgt`?EVvIunj$r94NDJK52bjxQR*d?$+J`WIu+0*wg37EtC> zCHpVY?$glO(7;<5dwJ=HAX7l}O#=se*yjWSUvcnmq!YzhpBcdV0P8Nyz3IbwCzA&& zPijVZt>z2d>)ZeyB9efOx$P;7Y`{2i`_=^RN624;{EYr&-i+tY{O+IF51_r!xAS?> zuz&Ud$~ia+T{gofAfIau`U&cpI;KyizOmlr8q8lyJx5{~`)DKd6UO?Vx^d?_SEpY4 ze4Un1r_InQ_7v0$eUFH|2H#qfp?1!MzP-r>vA4J{d#G-9ykXyn#0Q&~JZ%o?(M$Ij^wa%j^x#FOX)N zxfa#L?e2ODX;GJubDkMF;*{03Inz;J)IQ~mA1=~Q#dapck#(sSoFV)k@$I^?D;n89!d;)Cf8;)FmfxSo z7{r<(ZU7hL-i$udhkm4g+%DQv85>5PuV*{BuVp(#pql%Opq_*A3dlJLGIX^8I`xCU zd(IG}58#>(`zPo%8tCSaJ)HG8Z6CB{m?NYtprQZgUb`5+pZh|+Ii6hm5A-$00&Myz z_~65$PN0vXX)*Bu%$2oiI7*x=;Jl&Po8sP^`#99(&hJ8S04sv1d8l-4~(V(uQvbZ>)3EH%XqcbTc65V8AWZU0KIYhk9y4 znWs0LO0qvWw>Pxyv}hk(&l;#N+}7?aK$+{YU#E{e96OerM_%?6jKTcmT$KO*qo z3-;Sv9bs>E_v$w07x*6fd5q-|=&J!g(y_j`afSxIa1A{6cKf||>C4uLL^^={90W@obGTLz80TE~v_#Imdnob~oVy%LZpSz+7{1f- z#kQs{&Bu9H^VXE7|4x+K>Rb+dAh6Z(p=}|g(a&eSuyxq2-wf<}hhu=YigQ8QTvC^I z5lipH{6;$NXH4`R$`xs#U4^=O0cPyO-y@!bcr)^GvzBHXGi_&E{|x@?uy5Dkzo3i6 z*KEXLFVBOXbcZiLl_VW?WkmKQSswFv(K+lV^~&`L>ZS?fnfm%I_8C$?@L3uC92k8H zdm88l_Dx$h?0EV~@YVvGQ*75a)L8i#JjeGJY5Jun?VU;L)j&VP55kx2bgGA2>H5kl z_^j&WAAu`{9+wZt8BgWa5;wU2POEJAPAg!yTj&>yYYn*{#hB!JcGiXSE%l80IgZ(0 z`s1s(cEr5hA36;Oc45DP^(5s34reDt#h6z_glDHXqk|uPA97^qZdY{NYZr@Mj*WI^ z)9E^3!P^?e1z-#a5=u<6_cKCZ*^gWc#jQm9U8LkgFPk5s) zo-zk;o*017F~wFVM{G^$QM42Gl!H+J_iq0KKYSRM1@IH_KP5Zhe=tYU4+dW7V`4ms zy!CMDE>06K^dVl95QpEi!akPv6@bqP(D%wVZB4<>l0U+HmceuHFotVi$Y7#=ojQk3 z%Ro=r=%2_Bdk+I^BL9SDE9DDpg)Tsk{3kd!*2T~k_(il`z?P`{F{qb&KVREE*+w$} z*tXRvQEPmzFW(sPc9Q)u5$!C-xmAATZSK$gd00omA7G61N!KCmtBa?x&pk^T+9Aiz zSk_k;=l=L?0Q4h4ud93w>2jn8ckFY@BD*n<#M7m){b<}hm&Eu=+K^L3PCJKZ{u*aK zHR*$uzt)U78?>h*r?IxiUZUe6=OFxmfWOQ^*#OSS@^GeA9B|J&q+TL7rL;&q_}K6u z&*1!rn@=Z0pxxNYbNku!r9*tEi~i8tF)dLKJCpk+=omgp?wdfzz3330dEi{=tOsp< z0?-TiEkF}+KOpBG(I?rFpCK=vK3w@T_`1^^ zn`zp^!OEXOowMW`rP$sK|NK*@1bT~t?*Y^q7T9~C{!NJcpj*}nnf%l__k7If+To@M z_mMT}Hspn%Z#^~z>vpb5W^qkFKM;hQvZ+MOfN zugj3Hq0ZY>o2k39_-<#b@-=JGc9x}H*Q>Fjp}w5hCg(2Xy-K;!f4>Ig{BCq$UrYN& zU0NIV?66%Cfv#fk%Tf5SPu%e~8|}`+I-PTWE#iR#SYIBvDCNcaC5ASJ;8Sv%cR5<~ zH3<`aYc|KBs@dsjv_p*JnMw!Iz=r%%l+TIoa}L{Fn@vi6tu#L|5p-ermJs}{E}}|5 zv1Aqc{xI%w1_Qq>5=lfsr{~O0i}+9qQ3< zyW`g#uQB+qeGcYh?4x%%#qkYJ4dgR$5224+fHu`6jcB|QKB)xv9qAiji>6(Lv&iY_ zvlr6+lkfrJz6924@Ci@BUSfdj-l2ap>=4hAi|8NO2ktm{2xrK%6K30{go(8P^()V> z0_}-VV1x4?D962Eh(1B?3umTb^F==BgX6(aV*v_58JQTO>ASkJrT$Pc`|M1`QnKZ-UU^s2SPvhRK=6>958Z!%D{flIC5XYh-^w| zuuk-pPTEGd}z!)K8sa4R~JtoGkC$l!wvux(k6el#Ns z_T)tYoT0Km*5KSdfc8-KZJ?EXYfnmeP&ecovaWPfVjTKbe`Ou|;`oB*>O;Yba z2feiCwjTD}oU!LkIA4H0$8dJ`vFnfFH;eM>Xd^eKKZkfA0)4?R!mk)yLx$jQEYY0A zJqOf2ORneEbR^QT1jq8{)6oO%`Rt>d1F+-xTS*OPF!4u<5;?$ejNAk00}saQ!H@lj za|XcX^qqh{*faeD{en-lTPG^r{lp^l2k#C;*z?M>Tj?jNlcVK0cnjm;E6%pz!xJOG zL(iF&*6l5c%Q+6fk20&fMt=^{;GMh;>qE$zqTKW)xm-W~VQI<|pHEr|+V|(vSl{k3 z12?41BiE#i_>a>idGVw_zA=%FJ~QoSF+bf5xL(=!B`MS`^@TMk&cTmi&9~FZ6>SLt zAC}v^F~NG_Pbza`vl6-XI^Z{f2J-^i`(4@Jr?|JqI_j953p4gBZMu#&bw2*lk-T@< zqU`!D#~+#4#_4zhzTTnbyswof{? zy)K=Ndn_OHC_r0nc6JsaeUUgSZ9)Wo3BNis-G6Xg3)x4l{`k$%K7a!Aat`R9EIFFQ z9w}WATaPuzdib25ICrBSj^ilqxM*9Hxx1f!^Ez~}@g&E)7K^6jd84>mt~(hQarchImGx$xH)Ef& zIA!5JEF9bE7d6wr-X508lt=reF1bJE z+K6K;OX-06$)C_BVV}HPkYlvj^*fxeGUZxOKm9i8Fb5Y&|D@=Su^fCk?^;+l ze7N-Ik0^dU&oOzwO}ljGH|`ftJG_^;(Z<~**8`Y`sUOT8{t$eqTp!ANyIEYn4>@dO zeHg&{Fn@RgXKem&)~-vyx143YTL5*)$2DjKw#)q-*K-)N2IpBXc)DYTcDpsTNv#vn zp051}{ci-eofCuaguXZz3-rZjYVFqtZGUUHJ3qm19QL3s+*9DWB=C4$o+WaRaJcfd z0pjr&mY<38aD=$rczlVt$WF8^;KGjZ^LMHa>%{V>NL+wi~jPaK;) zpXZ@}!q{|(&-gr4+~xCJy>P!nQ&=`0sy20`!4l zJTKsc(I*@yI`WEPXSAiu=>r1p{`MB=lx-I1AC!S?&z))f*zLP<=(oY}Y25cxmH_&T z<>c4~o@;aVVWHZOvkuBJPW7MMLn6O}{RSQ49=~f3>50al`rzET!<3!pBBhukv!X9b zS#jpzA1rY81X;5oE5?YtGt2D3wKjJzAom8Ye5t>3{)At z+*c0(1h2GdZ%9D?q64L`C3Qv5zRS=vPjqZ@EYuaioq;Cr7+;kBhHKAVKM?)7_3%Ne^Ip~689Cu48p4Dj0an8ST4FP*i4rRZxY8{Bz{}gdPr?2_1=1-ob_w;F)L(g(e z!})%h(i{B)^~|xx`%1{d`=LFs>7@I7Ts--opym2Uwgv4DL4K|cbFfzB9G(|D<~*bF zFU-?G4?W1T7v|BA({KL?@O}7{CX6kPE4{}!nxfW#9P3TA5$K!yQjR;0r9gD6^Bm_1 zw1N75OP$A{jZZ<}hYN5X!?P6FXpzADU50VMvx9>ruWN_vUr*|b?$PKcF`pF$n)f+_ z!ISgfzQ4LW;RB0`aOUdHk=XY{F!pgT4!z-QC!V|(bf+QzILI>&vQ*V=b#7KR2YnY2 zf4lP0t}lr3{-g-cq2atWp2mE87QSEJsj*G%s_aqFU`{&w{^Vi5o8Ch&Jh!5MIj8(b z#=lIbZq`3{#xM5C-_|b%O>tzavy!@jpYcWG2F_;Si)wkdQ{;=dzJzBoJP-aF>%}~d z@m_?n-{sHfZ^-NO$mf|R=XUJLVKXb}KZ`U)i?J>Lp8)Aa9rxAyoI@YEb#wp7`c^c* z_ij1bJgdF4Qv`5#XRlA)ShwD}x%nviWMQ;E9G#CF^vZg-*`JDi*&+nt8QdZ(^qy|XB~-f23r-YG>NhLIoW*zSZtTMU|2 z$h!+XW`;UD>%qSn^sOkj8uVWTp6gV$)3lE|9ke;XPzrGaze+CZ#*L$RY4*T1xpG4?(uJMaSbIY*oyOFhJsJE0@`H_jE0AwCLwxM*~T zQ;YgbLhz@a|fS|^C$T7-r~Dw0>JS+DhwRYr-_>j`rhK% zGmK}TSM0@WTKAusi+Tm>eL>YZk#>MFkNe6Z<_%DO;v~|mBKw?+q5sQ3-^*U_lpx+W zu->T%yzS&6JrL=B>~r*MAEck_|90{@>{TwZ--chwPh;O>aNon{_qY!tj?WV{)a`TF zuRQArAuR%@oWmt2vF@Ci<})Jl-g)pkP3Qfjjpw@HOZ)Ro0B2}}k-sCqGQs(keq#e| z0`kKS@I1jO2Y0z?tdso_)G-xu(?_pXG+zZxk-CQ!Hl7DW9?#~7BL6}3X9HxSU2@OB z{=%77nrAajz(*CHYpsL8>B!@Hl)muBk)54))g5!b2p>+Lc?PWS`j%W z?bt+K<{Xm#dAit&``xYXUE=}R4tz%=Y=>>ZS<_PovG(jb@2})}KkhwkocG&D`!wSY z*pRZjXG`3pA{~58`qDu9CxDzczfB#%CRnx>{J(`X@Bj3y>h#y3Pu>$hOyAS|y5noZ z`CH_gRBk8D#YhN_iG`08Tbb5tq$*>Z^PWGkHeV+?nC&DR9iGYKnMLe&}%U(1!1KQ zUd2x{&`$(l3v>GawX+ty%({4TD)g`6xso}8w#d11ZDJ%K^&=t+Qqh3Ck8w(Yv%!<| z)-~YeiE__?vo@3?-;X8;`K$)dMcZO+9eS*7-G*3vtK^~lI-2GrpdL+jK(p;b7J^Z4NCiI5hV;q-zsGEPFPuro_DB@3H zT{%wj!X6v6ZNT9UVNWi`j9h#0+&7B(AM`C4L-g~s&$)=##%K!y`_L%%2K$^^*oXle zp*-xn8$iS7j(!h*6L4NQ!FKJ3cCiY1><`M7jkZxPt~)3fW!Q=`Sm)uFrMu5i+a(xMH|`r}!! znvrID#)v8D-Y8=tJ!-t3J`_2QzQMUX%EK$7s_uie0XQU|y`?nZny;x)Q z0i1w(!hpQTEdneX7f;UpX=mpl^y8qwam*Q5quI!}MS2M7>}Z;EdVx6Z6e53U_Y!z*xfYA5h-S6H<9WUqk0$VKIez}iv;AOtDewKCtn~^r*!#S@n+Maj@ zdgODlJY%)m;+3AZc!>!adG_yBv}})jJ{9&Bh260&J^c`UH2siS7tj0O_@cKy<9;9a zx+sS;Uq5{j$1wSy!*dho#zj+q#n||)B8s&oo@*YC@x(iRoGsHQ6!ZC6=*`BuQAj)C zvkUv22L}vH7)aAsNuPvw3Zzf!$Vynav($0UWOr;%!N)jg%-PHs_hCIuzsS8!PQdNY zxdR_|4B$!%l(v7X<8 z=bF#b?zLz<9T@en^xI#@I?X_zJX!aF;&)^EdDO3C4j?~Khr3P4F&TEM!)C9J9Cv2J zF4?{^;5gq@DZ7s#jkBwCDWBnl{SQa_8fEuWVCzw&Y4?)=FSPmg(ubWJL3>jVn@8K^ zc$oDC*!)`9{IVHo-;sM0w0qh(ZJl<1sP5im@ey?|)DcUqgpV@gE)8i(!+T8HoCoi{ zuwQxpNjuE=CO$_&K75vfW$1e{&rz`aJC*lJU-O4b_yq7^{p5FM=Dl)GiDv3ic-Fyr zoAvY@d;OrxAndn;{RAD#{=oAOw5uVIn|{b_=GfflaGZr>TtDFqqYe0&eD2_^i7|uc zr{s9?+88gmZ-l*+m=V;4`gnI}HgA-34%a_e_xdYQZ^oBH_8nL|?1EkHTJqVsEju9# z$8tF4j$^Eq{9Gf*XVLKNKgRb!*vJr_XC}ClM?LV(*i(Xr_V+dTm+*|&pC$sMbh;f=u0n~cW>(VB~#LY16!Sk`marJeNYGaCZMjb z;n{PJNz4h3aUjlTtIksIJ2Wk^3iX+F+i+imc8mB3o)2rH4Q^CD9~PLF$byWe#}Itj z<6v&#x!ugR$9$aklD>&Jq*n!>j+ZGe^AWl%PyWG5Qzs7-EWC zGwXpV&IIU;va|oB&f+N3_L6)*CzCfsgKn_KqFvEHOb|!XTHV#yf2@^vC3)?yc9OPe z(;J=n_x-2z^KzQ;Veln?>V>?0&6Y#nd{->5;nmJC z+8JK-Mkm)#!6vk)&T_&5+UHEp^XuUYcF>O^ZkW&;;0`UIt>apY=hGbX4TygOex;|5 zv*2r>Kybpd;PMCOmIUsA|JGyv+QA8Qh@fPCB$DJ!mdLUoJ3XTuL^O415Rc=axUlpXR~Va_Y$S~{tWs1pCsuj zkXoDa_ai>qEO-!gd))uQR`3)A@Qf(Ll34Wrgrq+qVq~y`2+VAvAdN52s33Xb#WKWe zdh=!H0*zd1WxW3gBKXf|JYUFVh5f4#AG%>Ys?BZ2*F9eH7P(AwrjNoG=dOX6kIA^5I|%gqWxO=^H|Vyl@j;O7gkxC790$l(77w1)+r{}%EF;6Ic8D2p+{ zrW}zXo4MBm@nhLSPwrmCUyyNcE`KlPs1(ze>wyTz{DasmQOJ45#^uY!X&KMU{Rf)+Ysn{+%irO7Q>o!f;NOzXD$acY zwY)9kb}j~m_^prZOUv-phw@2!8A6%-FxxK#YZOD?vn&#$st>N8thSv9R%cy!I+k4u$@ zecDGPV@GCbvN^&Y4zckMgJ>S6eFERvZo*@4fgCxS)PN7a-OYc1=VSRS(T_%Ifs3pr zM+_Maod>mVvywnx?H1&WTezfEc#7QO!rp+ai`;}}7lOK2^ZpScnl^vF?P5296D^Qk zqRIAxD~^suKaIan)t@Y{@@gDxo`G8K2S^6~2>C?dHxNt<^no(Fq+H!a$pMw$O*!yQ_UI*E z3bL0(-Cwfq!mj~2Y2f9c@(#%Q41ylYuo43)kGE7}f6;{v-wXlA7SgUZn zw}P;MucPWK3wtxp$rc%+_p;_zF|II}0Im#a8zJxW;B{4@k6KubFc+bB6aKmL_(Ey# zm!Q@hgwTQ({7!6P=p&T13>#E~o&b7M2E#fAJp;_-!oCY3jobUac4(!lP!37_N-NIX z(EjbHv8qs-;17^~9Kpl?l2BC`qI&;^^arHl3{q9tm$(2l;-~H=BT-c-y>L0wLl8Xl zS5pe5Z}}Y36A--3t&QSp7w5rG^;}aZ{RNJJ1b^ku$4PZ+q3aW&r(A?VBdNo}0M)E- ztMUz!$uN^kk$p3Qr@4LwNNnQXLi#@td~47FQwwG9G@}UH?pX><8L3`CivI}Gv$BP_ z3gTv8<7mqT2>>c3Bk7?>YG+rNZhZHK1v+cY`|SY++-A) zfZ(I2z1C&55NR4{sA+yZaJhd+hw0m5zKv-2b#9Z7BK!L+_IHVsP3}kYMeyAZ_SY54 zc5g!Z9^#&rbh6!#BE5|`I>_m+jd(Du`QvFmy2j~+xf~UD1J{h;Sqw}8F+V}-05L0< zHHqsBJsbr5$+2<-PeY5iq0mo@AB*G|1TX)w-;6>(P1`ztjSwH=?gz_PB%ci%{LL@z zPryzE=_CX#g~S3x>Y4Zz63Y>3M#yFnf$=Gn<#V(Nk zC~RB_?nT!EtBuFkFF^G&DXrc}eK?Bl@KF%{JZv^mj7x$29rBY1S`iZb0kR?l(Tkj? zO3wWD0rgzi_! z4x8U39W8S)BDXR@%WOqtITN(Z4T!8okVd%|kq4NdQNDo4K?GNrG2p6;ArR)Ru<-`a zQW&cj{`D{u6lN?E_%C0oneWR26Hws8u;l|<_P{1Y+L&Mue1gb(2(DgEN$D4$!24nA z3evD|hv7DSAc8FLc|>kR5WQ&qERZ9=ff0WRTT3&AHiKqurqJ_<9Au%cA(Jasp_X5S z&4)7u-bel)G6nGe?}UcnHk@NDEHZOg^u`C1N)UoCup5 znX{NQwzOCM)vtQ8hv~CphC;U?NDBA{ezuEJCCKp<*5q z`nKuDZGdZlxPugTAn^zydzn~|#BoH9GVx_3K1SqEOne22p+QW!2*x*&s6u2c6Hg+s z6pib1wvkgR7_`WKO`CZigyk}@qS7b1-kx8zAeW81+s!rTkw*HLo0i*yAA zZG|iU&YtLQ`J*D|2q?H1&k0AAe5(|-SqQ?l0@Yxm z_t6X~eGfI54I|tpmb>{~8g-j#Zu|Id>_OR5b2TW*>4qMhs(ste-0jI0pA`wyH`2{t ztn#UFSJ&o9WKoY_R#|r-Yo_cG{>xz%DP~IXKHe32_MYRe7xf-g0hD45?G1BIYZ7zasvhRE9MVhw;>nM!Dr5ADq z-md^LZdK&I)Fb*ki1*`?nf^*`R{IRZvi92r0j@A#2HMYm=<-B?+^m%JgIM1w$d!0* zPQL5n{oHJPuRv}#yo<$?1#*+*U2rF&{y$=1Tzm%7JyjrA^%sY{m<9{vHsj*csO4Zm zK6d~YbA~=x(2sGsQ~7~nxTrxq?bdVg29P{mko^f*dRrDCn#btHZCG_bUC@VdQ8)qR z!z;kIHpDiBFqMr&leE2u!tkpfA$L|tZUApZ>lPs7;VfL-=;H1|dKH3)>+G9Ca-F>g z>2(Mp9AMoXk|$Wkwh!+PHGE;2xFzJ_IgPPx_Zp;^BAv}N+)s!)nH%!5R)c28v!1!3 z2sgj~1h)?miH1@ULUXtHIN_?Trd0M2V8&>*zg z*p|3knB#zabR@=E2Kmn2a8w57VNQy}g;@uJ+u@oPX9zkl37t|%{}iZjz6fZPoQ z@92r#tCakhi=^+%N&uIq6pyrfQu$#Py;d^RzBOwsdbk2x%f%?6+5jz{W%r%m#+M(IVAd7a_Y4L3UR;B14#AoPLm9Q6Lq-WnPLF85h*Gl#dMNG7!wv3hBi@ePwrj_hMgo>Bd zK8(mdgo|h;aaoZ6{XAnK-$54pL)P+3M2;iiBNv7gOcPr`UK;Y=&Q@_@_z@`n$Rb>T zUkY(AL2%vNDHPBJPm3=Nd0%A#dZQZT&tS9Ym6{M)$OQe$W<)k1WV49$D_=+Is|eDs zJcr1CASfl5LV8Oa1?k|BcLRSPjjfffd=pf^LXgV+0Fn0)q;grvD>x%Sxx-k9%9YK{ zg@8JOtJEBrtS z%8=)22q2aCWl(HHkVnPGky{X?=UIe;*udaB2QXt-i;>+(de*cKk<|$Jn7_d&rjz+0WRmV;=Njo`b^}N! zW5R~$WPXt$cmn>U49IsU3GurOaxY8iD^Te;WN~F_PDkXWDl`(_L2`aV(U5TjTL49v z)0`>MhDZmvj*%rKJ97*gLeF)5Hy4q!2}pXWoZX19G7-KNp6KgAE=cwdMiRb3+uNs~ z@=M?X6zL}s=$9S~s>R2B(l6}~s{MFp}aA;`J*21KSKWRptHwR4cV z5dl0nb(VpLCPpFmOfdV47oh;dDLu^bQ3!BC5K`)~_ z(58D4WS_OVefBca2Z%$Tt#JEn1k9rX!Gr&vELOT5Lz9_|VBLnsvjR)>f$r`M`hEt( z&^7|Q0@=4C{C~XtdthBhb@vaSbM~C0`^~a^w`0eb*s(2Nlh|<*%ZU@;o%n7i27GrM zUt(J_xi}CN1PBmR0ksICViiQuLj?#>ivUsd5EaCO`cy4~3MyIyqEU-z)S?zqRPy_L z*X$!5h0y2y>s2ymuQjvQnl)?IteHJ~_IC6-$R7f{pOhu4;Dh9R3G54`>Z8j@_zyUC*`dpuMmeN zFQ7+$MV^^(iZ|gF^462&_EWtHV=o*{|C#Fc)_W(V&ymvaL#b(n_89)l;7!WYgXC$2 zMVf*~!2ex&dKxgj(AL_Mus|+}ZTK05cCWGoY#u31kCA5<+613-Xe&cw5!Sa~*dvDu zbGD&z^eiRYA>T?0NpOv}QhN*g>IBj-16X_&{ke%4Pn!;$^=Wh*d{;!iPgbbm>ASv(6r6(h=Ov+Mu zd@htEv+uu8vam82e6kX8;}?@Gj&RSCbL)L97!e+|U&`sE++)ayuA^i(89PbQ!dgy)V|r z3FX?h@OI0nlUQN^ytbLa^F<6X?LBeUFJ_a*1#EgzQ?xD%DDTwe$RAEh6IhCpCrM_K z4|$V(4gAkYW|EJ1le`N4AIih!UYul+b{UcVkle`T5kO5xRxq2T3+U zj{@u`W$8JejnKD%JwwVKg4>T!Gjcx7;iNym#ED4br1)P-pp0A%_4`R?P+i%4}+6Wf)^MGilmB#M@k12k}QpHdi(R zG?21HWpm}1!CFZ)vlZRs(^p|Nmp`hZ{=%tbB%oLx{m!tsjKQ;#D%BZb=Y?}uWZK`* z;1>$i8~IqLoXVng3yBw+h(1tY6Vd;r(yx>9o}?uoEU;rC8C3Br@~pvsSYRW64|xxe z)Zh;ln42rI;(3wU0$VUNQd&VuoH$uZUalh03KUyPvIn~#F0d%N75qNs>7PLRh_CS} z@N1+T-IVV~2*-f=m6I1v%6*4|scy{Q21z-|Zp^Cy-b0GG#WYS{asxVV0<+luNOn0T zwnMAoVf%sUwChlUM;k`FhdB$oGSB%bE&CM3S^>It00rFt2jzFdDy&Drc?Y7J~cSs4AYpYE=FIxUaa23ObS%pZ692 z0{owqN5vO>#dGks86@4AUd*@tUI|*PEbUNT%C}v-yTKJQEb^(&MC9Eu{53!Q^kOPk zM*#MavP5MA_gSzvld?zP_5(Nm$r7eaT1~qltItntWZ`A^3-5#Sy(GI| z_z=J!2+^&|#{q7T?Cwm=vB+m&<~HR!(nPl@U!?d8qSwtsH^BcP`P&rDQnARFU`XDk z{3~UHBK{V_M*#j)$X7vPc!*|if13g$lQ_Srw<)<4XOgU@+W_W~__I5=GKgc54(j^j z{KRFoOt-(gpm;zmy8Zoq01X1)nkpE0YzV{0^Amq82DRpElz&wWYE2hFr!nXWml$G^ zei%NMpZMEk4KGvvk77^_({QGIQY3p8#CD^z3_uHuS74A|v9xtHtSx}ERs!yq>yBhYze?^B)_}SVNB0pl7sod zr^TS%jXNk`C59h^YzNpZM7tZhqd7*(5{vC_l!NJ>#&$P82XKRgO4`J&Vp#cK?ZB+h zPh?3=QuLD>uL>s+_0UjYSYthMy!SfN95`}g~T;&|^ z9}il|o|vB8@MNh(Pd9=Wu)1r9LP7UU6L?w1x_q>iZ$0CA$NkG`2`!%YjqyY>E|aI& zuIOuz*uq-$kZr0uY+4qb_cn9Nc6M&MF<7*2-wN-PZ}(35ZkqEBk~w8Xo}K0TD0nRi zr@R_@hxd_hfq&KVuJVZ6obtaxe?>BeKaeZB&U4OM5lbOcgkW)Zzq{kR(Yq~ z0)DUZYT`68&t~Okz)O`kJB_8DSK<@kFOuY_@Ar=SebB!anH=@~-cbuNlKMHFe;Ok4 z`*{|s9{}G-@>A{%ED_nyucq8j=Vgs7Cqq;2en|F`%u(M6aFpa7wcnV|VZ^`73l6d; zY;N=f@CKjr_@9|;^roc;k@88TZa5$7T+*<&RkqlL}6G(n4rdnos}$XYCv zkedvgR+nEb{0QrO)y}x~vyI+oKKe&%ypR4xt_997(ULzS*(&vGxpoWJ1>UK=pVG?q zTzl~L3iuC6=8!MtT9kYPty@FVEnG)#xE0j$y!`Vob1i5FFEl@&V87v;xfV2YP&$od z>$-2|W@}xy9DE_kg6lVP3zYXL_;%5;MEGW|-GF`=^beH9L$}Uc3%AXnjifZKH@}r@ zo}KgEl1Stxd*FfnPNo4{@}^X-q*s4R$v;8fPqL-+5Wv5ZY}Nd0fM1a!cF(PUjxB2c zC>x$1*_t=?tCFC5?l?f8qTboK#1nYZh&u) zJW~_ov50=fl%1EjjR<2*MF2TM#IzOQK2pRQ*lbMtRReSKvd)Q44SW~CJA~+&)e8W> zPqGHq0eplMu{BT^ywS)yJR&bI@xW@3Z^7^$2aQtpUm{l333PDMwk$(0jmMvV?y-s?lS;Qq=-w$Ikb`REieXe@PcjIhC2z%xQC!zcU?bA zmN)pFghuToFlR;FVJLLt6=5uf5+ZIcic9QVpZVG&B2JH2H1gM4x!?P(Ay0e1+foE& z%L8rMb(uCPmYfecba=qRPc;SFQG4e&n*m2B3S*NMUulrk}6b> z)+zMmG4$T%$NHCP?w^w^lDs{PB;fytWG9>}d?fh+cn>LY65e-t-v0*wmGX23wKCVv zpiV})NhCi7`iLXj%py&`dO7kQUq$SNGWRq(>EYnRXryq;9ZNZL=mFAeNH-hgZSxhap2#2{{;MF%1fuo*K=%-@+;tfro6|E z&cf>t!N03K?UY{6u_F+Z?;s$N()*2Wks@;m_?^o8Od6Y?Id*#cDe!Bggx=J6OOCCx z-wpmeDLxZ>R7}zc<9kez|CN*et~){QB)5fPJHxsZbl*V@4679!JgCoR4!Sqs2nQkDvQRbZz{VO=_d!MdGa)m5CE{szi? zT>!l#Ul+hnNnXLj#-v{{t;kLP07br4SU{HbRRNqPc?B;(9*fLIk2`XUzLjM70p-1< zEEV{wzW7mw22cL*6YFyrkH?75_x)aaV@j;zP%if8-w40K#fQpiV z$GRu>3>`RC?@1ID5Pde}*v*qP%Vccadbx!icLA` z)+F<5^|w8&4#s7I6EitesZJx$z8z2FpCu3 z2C@ZU6Ddnn!7*}9gS~+?Qxcjmbu98j${u(5#{GVZ-bpg<&jEazlqCw|{yJDYDWe0< z@CL`<3XShvVYJYrp<$HqYYvmM`X%Y8LH1XO_%_M9{w6>#DUxvt(l6|>UJuGXprerS zfHvXTDEl5v*K5AKI zk>`EZ+d-ePtdo)Q?DWkv@Drdnly#0%+!jo~2KGheXj*xj&+7yK9x1XYO5e}Vwpe~M zi^psh%bV||@7cs%kZoJ{zkzayWC||yRd2foPbJyJv^d+A!XE~IxAHEPMwVn-bpJ=t z?<)&Wx;@(>`KzG6B*j%rNjCPgf2?^|cBZ!SqTeQW0cj2?+Ro3zq-~_EboJlg0hN+Y zlLGyV6`vt}O32Und5QE@A;08DrQa74V{tH@^s0~?fcKN0BL!3W`620VNIA{;QWyF} z?RPHLNy|=apxx1SO7b>BLW<=40oddm(dl;9Nzf1BX?Oh!gb;xxd%Me$1{8zTIxQ;~lpWr@m$$RwmVl1bQV z5{^;E02@*#Nx}|_RhdaR25^*=B`T9p3ic!^<0#zWAPaYgb+ps&%_14ID7=U;O+D8l z{J9ZYuf6x#XsX=nV~<2!J;WMWcUn=n^AX(;$2xH^MswQ9NMDwXhqO~bnZH7ES}AXu{xHiQ*1U9%7es8$kX9-%>*t~n zlxNW8$UkP~ZpC3DOTK{EE19Rm%C2TwWtn=;Sej|i871M(nO@i_fnM0j$XhZkLNJpc z=YdR9TI*&hz1hpL#om@o8_j79*{zv2WFw0_ zq%2VdD}X9US4qJJemY6t5b_{De@FTolB+_lyyzq%y>BJ^%r#RaXL)X{NDi}#*?@xN zG)KV-%WRA7BbDCxdrN$Oz1y4I`m4&DTK)AtZ({uI z{Tb$Ok)jf&t-C$*Cqw29o;gz!!aW%_NtmFG=g?QeD$^IN7D*$mo1DtHA&v(n5UFN6O*DWQFpT(8!m2k=~y?b76?+0nwy;Kd|4c%HBH z!=N7|*@;-aRL1%oqpeNL|BbvwH`QOD_;Vz?ss1X!S4a^z3u4{f&Y)s>ZOQ=<_XuU$ zpe+u|%4k;^dDUaI@|tH6Q*?l4d_Q5vQ>l#igM^P0YR%s#tY6YjmOdN#2M^CC3;k z{~@cBl<_#yCe~^%Sa1`F-z`HW`P~PoM_!bCILq49T@K4WV`Y!9b>nwjDa&XH%U;71 zS+okNe-$?m?8F%dL8EnQnsxC1javu*J$ikIWF7q1adXN-XriQoR>vlx&wC7fAIW;| zJ8|o|4}iZ%d6%9pi}ZN9FM)qfdGzLYha&CUA6Tc_M=s}pE76XA_n7`%aLdmz8ki; zldQrffR71Lg+Bo3CS`T}c7=(pYyeP}Jvpq9x+P!TCi63WM2gx2EbPtxLF8$)=6gff zXf5z|%6#+j3z114PCIcjQWW>Y^>SoN+%HEoM5cN}M~c2q2>9R52CGgJ*gnzMo%Nte zeaZQ7^3=)5H=LJ*&~G@u>`-0b3@K2j(}jWMjyM}1E_V$>Uk^Z~>gRl!3H`ihi4<*4 zW7s(JB+bpDd!MJXDXZFDqB|GLQ*e61`QW6MT}<-q#D0%>9=Tg zp5QyNSwABuv-Ijo;N^NYn|bn*^6#=G-l@oUW8V6uk?+N9MvN@kK+S&^(;4v0%RDOk zv)F9Cw_+XmXR*cFi;67S#?NPC+6yw8&&Fnr(R?yn=bnlMcnxuPg%=Wq>bF}NJ8`oo`Xx+~swc`iH0NQA_ zg9*Ck585KaIbC1rQQVaE{WsGEAhs!YZfnh|{qS#N{tSyE65@_B$plG9fn^lWDp zWIo#XTZoKfVL@tUWR9l2Q7eNYN($8P%=llHR zNWgP4o&8pDWfnXpIbxlI7Bi%z0XIg%|A zR1a@IQpZ;l8S_+!mIzN#TuQPfLM6aENfFl!v6hINpwkk;W)RzUw|6Krv~?Ih1hcZe z@v_L9Be#Y(Tp48)%kX|pOiOgvk{)AyiSTIMzae$Aj=yo}PX`L?sI!_B=wRV50e&V# z2Mm`$d7E_AA;dKRt4NFGg=I+NUpnWPaTocw%sksHxu4<^l5Ljk2iQrXehvO=XcwSZ zwC;cJMn3FZu9~X>(?WTZ81$IyUjS~7F;p7EUKn0< zZex;R4!{&4V%P_;gXC*?+8EA)e#E)UqEQVM0M7{#!)x(`Q(u$2JgkZt{>=#?i1KH4_Jw zdIMI8eitAwxo7xeB=nI?-C#EWsZg7Z86%KR+`$-kmpNM1T%fYc=D?bcZ7!b*cb24R zk+>h=ej!>ueih)eq`=mP&<9FdCsqJFD@5zXZvuRgWIN=`=psTRXVKN#+U*>ExLt@6KgbPc7*3xN8!FBKRfB zpCFk#zYE~^#Ne7}wd~mro#F{gNjDtk^`zuYMyT06B~RawQr_rzUPfJ*7s`sv(Hce{ zq|(M;v`)A4(a)0gS!$PW244Xg0{9mp-vF7zFquRO{s!b2z+NFg1o48&%Wx-_-tGe{drv)@$j+PC@PeRmYEjI6#&4=JtD z2fDO&TYUxwr8Pf@F*RbxNHiW>4#K_w?w1ctcT_% z&0$?3bIhC2VBTb2WNn=fA$^u&w*~VkSOLevP6Ui2Cxq}G4i1O;WX#bZrM z=`a>x<3i@;+%`QlByUa2S_vFzULXT5EsSQ(Yj>5=d2_vv^D<<(W#dZEOWRhcVl{C& z)LE%?#mNlh8RH7`XVh9LhkILex_oMtj6Z80V_l-QN7krD><+?TWr8=58g>&fZ~nBrMRt-LHKi>M|+P(A91}$Up^YU?DHZ~BAG9H z`Dk>Hd--Vp8>0tY_lbcMTn0`IpGdGW;d!4MK2dd&tge&2T$J@c{!th5_!kq8cAnt# zlAR~IPh|3ZI%dzOZy>+@EZOa6JI+GXaklO8=%cRf@s7t+i8>yyxCBwfrQu7I4qvK% z60G{k>MLN?S9;6ztp(RxHe8mtqmDjAi@>)Ik>*(q=+-DjFe9vS|$6!py zjFvOp?YLG_dM*HQ{tjbr`3H}t#d`={@=X=MMGOGP8D`aD3ax+tfo+%0s;;>#rGPec)SQ zs;B7_HtQGOaH1VUdQWzo9YfU5V~F}TiHsY<#zrW$_So<-M%U=^juTuOWf#WU$st{a zPL7^o@HC!ld;+YG-r~}He)s~J!xu&`2G^pDFnRbRk=U5fm~~7v5`@?BdR_Uk@?+8c zuId<-?e~@Kr?UF9VD$_q^ZlxG4Nri#J<z4C*46;Zk+J`n(FO&)1&^ ztv^3{k&8UrM3_$d8Fhn~Jq?r^yt~D$7xW_;|%8muI*C$rNp&JS!C7? z*Kuj!5?KR?4YQJb|Kk+`!_pzR1?pnojH(bxLKA_(N8anptW5kYMAFE|}jK0;? z9{=od@X@n1k4F!?2I+9vRXkDkMD&QOdZOlu;F)7LFh$=JM7gT-&F7)5xYTk9qP9yN zmuPd3;*6SFeVL2Jk^RoXht{Kb+6W^vT?cJ1M{d30D$doN8^iqI4P&XAeBqvmAe$sm2>4eK;3={;FVpn;_0@$zx2n{mfnfjFJ?c!c*JYdoF? zM`Av1(|EiI3)DXE+VMOC!c`F}EX=Adjw6ylP+_Uz0<8ejBMvbl`-r*fa~=#@7)) zo{s!Z2Sax2ai)sa<88-@ifv{+9LZY`z*`TX>s-${D0&#Z=4#$(6nLWnR9vdQVnuQr z1LQaYh&%8TrHQCE*;=gkN~w1VMon*w9^}&Sruds9ibxIk8Fp(sK~oRnH;pI5f_BA} zgEkRR-p@E@=WP`n;aDEM$b^ZrPWW@9#Py69DxR;2roS4_JSnKcUkciLviD31+VObL zg%ng3q@W58)qwhBp931ODP}_+;a$*an>MRO_kOT{m2-uFSU4C`Fy867{;5Rqq-a zeT?~>zqGW>%pg!+<0)oHF$dS3=MJu?CxHwB?G$Aap-*)JWZj6kn6V`#2l05C>ps;@ zVJ`EW0eMiRrDbGfWo5hJ^TX%8`vIikb%}L&g>nrkNkz6UgfWpwPtVK@8Luz!w88a| zF1WrZnRDBXNRZ%tpH4LMGioQbGZG`xDa{v1WupkLXA6*?IXCzRZn9&cvIWw5knBk} zB5@*_8$2~~ifAx$s{C~PD(@eXotCCKWYEZ1+K3{!KAC=nCb(X7BN9`M85t2*e!BcL z%({5yB&dd#pRQD{ni+FpLp@7yoe&|W;QG8IKp^)y^F3#PG1Tob{V~3q&%5g{vHER3 z-vZPD)N;NX=r4h~v9G)SjfizbwrfA#e%ivg01fvsD_hBRra=$PP6Bh1z%BBnDD|Cg zJ#BMCD}Y2u6LOnTc^XQn`1*7ti?~(wrN8QBg!L&`G>mgAzCJUhHC?B>D7x*2>pI;H zu$UH{?gdzK!}Xr7JQG~M-CC0FD$jsvP8E<2P!m%RsXe~z`ji_XFctX;S9PZ9OzZ)` z2w>}(gkIdhEKzxm${2;p53Vo8Z!8Rg*C@M&OHj&mUUQ}aTy?Os!T4A5%%L7-}z^AatnXWTIIzZEfrVBo+=|cAfWqDT# zf2r4)uKy+w6YSStHK+@yoDppNR_Y;@HeG1D;7i*i^SM~)uX6UGvqNVmW%Eztvd{ZM zHGw!>y(@q6Z{=&~4xJr-oe~?zXGdPAB*oh`h$NVqO_$(VY~lfy$dVg8i@L*z37&QI zksl)&uIFse*&t(tB^E#;`&G2{u*-ZEC$nO_O)hEU&~m863RH;)sKf)o4c@ZJD<~)| zj989|%=4v!^Tx$n?$FuTMp$xl^YbT7nmpMv1wC{6+^ZbYWdoH@&LvfM~Ym^NdE&kU|JvsjqDzUoF~ z&b)cIdYU`OY3IzH>obGvp$@@yO%e%LexdwAI6TU6y+oh`oho5?sEl!-e0Tku&?ob>eDlRY{D#W4jQF)<8c-@6Mf2k*%ZmOpy#z)xiOw$*u zFDA10?mfPV+0nztH_?Rz6bEI>WgqO-$l|j zL$zIOyXc3UARBTv0U5^P#0b&=w4@!6^bH6}WM93y={U+%sX$T&je~Yy|2dFZ;QGIgL9eJ<{6K$h;5EA%uid_|U^wuk_B>MW>r?ngxIf#< zWO$p zAeZYdv-WPh+^I|FMD)yk{Uqjq5}uK=$cKt*&&H4)0A+OM=<39h9v*;|WQCaQIIT2QTz%M}Vw9Jv_mVB23=YS$W%G-PW}o?h)(F!^66a9PT+H|LZx@ ze*|>!NbO@>>K<#>rSGwukE!tHV-an!Dl3kJKKCzR}el>GT<)2fZFeQ%Dhb$#z$bvQ>|UGsMV|x<}m$|4q-} zmO_G3*3wXm#$ftOuqTQ|UEia_k1|#;ui&uN!;jKN<@BqRcrW#b9~}X9Bac=+#$1B@ zVL`A)UGrmok2w}6HUV)4C|M1fqTA6{ z32%im6wV-#@Mbt%*)SqS;>!L5NK~%uKM}4!*S@cJAO6z2@9+0%3p^SAB$uY?cfud^ zH}}a7H~01LW4I3OtJu$_Vt@61q*U*364tc8WxqVLWq;d#-5z%DziIf*{e%0(JGj66 zfXd4c)Et1T=0M*8xLOZ(9R%w-SbYer`cT~=O(k`Q8bBxLAcQ);q8h)lzk9#-!}h-{ z>}4td8{GejuvhjE90aRA^r1swA39WXIP_FEx}Q1@BAcv(e2o-&T?cv&KwNjI`4Cj& zS*#b7wKpY;J7{I?;~!hf7h{(gyAE_8h+ngw&Cx2)7X(+i@eoCDb*6xBfLZ3qp$KXY zt4u;X05_|<`a_L}h`^19nhwRUNU&?7TIx_F3_G~~Q2n9cD))pU4z3n)OAbwNbqaMP z*RiJHLDRx}M-o(URUx@yaP{k0<+;-D;VT~cyD_MD4EjF)6XQSEbD-g%Z8bF?syu8_ zAr{4nqE^7rYChDD^;|!tuC!fTyq#r*u2jKCYzDEt&VLg3+Jd-F$oZnz6Bv&Xl^YH= zhJ2NWYeIoz1zI+eOOM(1K==!f>eA5jkPSVP!_b36imB8?Dy=+RMP4{Cs}5I7BsLHf zwn6&{$`GB#org5;Jduq%f5Q-Q9S1uO;)c3}JrjcJnT~_q$_+c)ccy0vO1awDbdJ>VZ9@x>W6L+N-eAySLA-{d))Ys&wy&p(A@M z6zMAW)#=i(uVtUbsD16A@-RQ@8uxVVQGU;!2IFc#D19`r7cPQ*)Ya^5*sFjPLfAIy z>Xm1uO?!Lyx)&<_tPyohd)xL((KfREtkEp!kTupC+_1ZMH|q56?%z$+>)$;fY+!fe z9_nBmX~7fznGLiy3l>~osV=qLUz|9{f{Wd4n9(D=B(UPZ*8yNL-ja_DjMD`NfGyzhsopl zss2m}gmp+r$0Of-gfJypU=qbelDt&|Q#Db4;1(E7-4M1xO`Zrs6ZB0m!7x~aGalO7 zvF5H1o6B`r%?_70u5ZWa4(c4;@#>D`Q(W?fcc9hqj)vVSD{wUE+cC03GyaaYo!Gl= zXY;Pqho#NCT6U4$va4ZtO14=-4flV@DBmgLm+$P@DGTgu*d?nr?`qox+O}(W7aRH` zyQ-{5>UP)fro+cQ*fqi?dhu}sAU2_GyJ~lX*6l{+BU-rglq<>QT6XsC#0_umtlY(= zZCCfMpo}$p_pU+dJGg7a<0HH3c2h1HDo0;i|F`Yxm1g~raj_b-tBW~WcUJG>PQ~~h zMM=eU%l0bv?i`SrDtAG}gAAn0>d|y`@7S5HXIZz-FS!wMEZ`GqX+As0XFm{buZwb4 zYSy|19=qQN=E)8nJ7*{JVr;I=NRn(yC0X`Akt8`vLJr@$uI>HX)$Z*-+iw3Ji8Z-v z`@nWwV_RoRUh$^;g;7dt{m8qxUY-^M>wFrWGYfJsM29w4FWMG+TsM19JBMT;I z_&a3Qk7;N!(Xf6SvXjxJdQ1Hl>aO3?vz5C2pR3-|yoH`<-qNy#FG#wUEnnP{I$c?{ z)mvJ($l9%2+9jZSORp~dTk5w;+}7r;>VoF2U7(s*straA09fnq zNB{c!8y_HCG(FIwOa11~2f6eQ@p zYFX`rwDSP%{Mv(*eeJ;xVI2?B0w&W32ZaqjI3$dUAL3H|Q0+spvUJ+j_Yj4B4~;$) zTw{N(d<*SltdF&`YK!lNh#ORMj?fM?*JIOUtZ*$4bUlEKhRyApWt*Xgh9AnfHg=~x zjA(jq^r3P|!p$2tH*b!WO%~Ym&=9qcL4I?{^=$gdCUp48rt16U-)0Lk`!~t9{hLNr zSbjf+K5DDnwQL;NNcOi^+3$>-68{*?K;%9NL& zOu7cYslm`HFF_p}TCTHXpoIG>n$lS^ToO7raE~d`Q*yIJ8zx#!Di4G9l=PN_&&I+< zYG+Aji7iq^VT)AJBp0c@p$Lu#_^OBzycOOUcAA}HlC zm}CW|JO=Z?Edr`G1*LP@OU-vxNRjbuD@#aFI*A(#0}7Gs9|vYy4(_P}zxqysQY*|& zRmJk`uENXWuEGP{Rd|3$Z2EK6>%X`jxB24wmW^RpvCPKxjKRkB!|NI6!<3~=OJWO` zF`j!b+?DsBUgbRv_i*;*tvU|Va8IkUy6-`*{LQ4+ujj_CUR5O@gZTNKdq?eZU+;aU8=oXQO?8|WjQau~R0^qvqLRi*pFN;gw!#m2CtVxubF zoUE0rtG>JD?)1xucs9cATFu=p8(7eF-$Oeeb))yv&PNe|5&fAz*RVe9EwcQw)b-xo ze|M~Gn(M!N*wDX0jY!p=%+U>WwzZ6l%KS}@>$$i0-o*8Y*|7KC zzIzeFpSghR-!Qa6TaaAr8P1TT>_bX7&GqN&xcB7G|FY;%-5izKFt8zbjt7kc5^xj& zqaN>~0xRghw_g_Pzjxr?pp?fi12Q?1lZv^jjWrwnxi`(P8yhy}l+8-;0nb_M7d%CG zn~p|=C)ZHy%51Yjnv1?}Bl&e)f-7tq*FivVvV~QQ?FEl|Ws|yp%!Vy6@<{Lj$Q)w7qxq-=TiJgXZjaU3ZP%#iemw%R0hO z%HUJo@uzGURo~TcR|qypm4m2qb6uEoQ(A?0vA!od*LJNelN8ziyGbqI!Drm%po6{~VRkg+Iyprhj>PF}0T$*A_Fm)D|}v<8~dz^(!=3RZ9CVbZVcw|$QYcT0vC8GM$f6UJ)6>WOY^FZRa(<|DD0qC zW!jxl*Q)+i-cOx@bReNbpn6qMkCof88=+lZ8O84;tfwuIS*8AgOP}Xg#17>rLF8-u zI?T0Z3hndU>{XA!Y*&jcY`VDmR}GmiDaPqfQZRju!L04aV3zk|Fe`kCFo`VkX=lso zZidMi6y72BE*n@zCk-t7wdYcYq{ph<^9XGcHr%jwT;Ob zUA?@1Inl6wdBgIw%aPR!SfPn?WLf!g#+>s~`j#t%^}!#GL)SO|m-DIlm-9z&m&o7V zmQwxt^OSp_>{`G$?^@8iAZ7jHdKWYl$*x>HG9i0pan%yCtCsj$ zlbcz-ris74UfQmDS&J^{UXbJ4&X*t4e}h+8)r5SieoaaF;_AilR8#wFN=6n}ETN=g zN!5}ROPWFxDb@0k`Q;0e_Nu0Sx}bN#=wXn^B5A1~t_7 z7*SUR1tV{|JyV_XW8bOeWMggvV)u%M%iF%!D3MZLG7Q`M5{+qu-%Oh$Hdm^54hENuEa8@X^#Zo_5MV68wMq5`H`pVfB_oUMHXu2By4r;} z1C!&Tp+%a|h89)crnhz~Z>zaYQ(52QfyLNUw*szWVeLZElrQdEoSeNZ6C*2c+{o2X zBD8#Q6U?q_agSs~5{ZI>S+lelDPLSC39e38yxgvO#Jsq1v1)IGF}9XL=+g5FXUth> z46f{*EJ{S`%KmT+`jau}&sm}n!aFd&E9=)-OHL`BWM!1S%==At%v|W?B+4A{PriT^ zhf0csC#RC1PAHoDdPNB6Pg1G=8hj=^yOFHFmaL4jpCs!SIys5L{^KM&-BY`$NO-dT zA5AEl`+7wPxS6Di@I0V*N$(O@Hc0!&o&_i?qwJMr{X!=vQP}@A$!@$w!jtv?d_vLO z*DFH6V3LaOskn~YJ8t*4Y)t0%G{Ukn%3ey=FN(=Y6!xzt*^RJBc(VTgJ)vms>lGoO zJxQhddvEWh{sx?3tbS!>lzq~L{V#NK5{3Owd;$Hhk|N>B`adzDXzuG3A)p~i6^UiI z!P^I^zlr+&lbCd$l~MNDWc{L;oJ3*&Op@Jri-afZ|MY~Sxvy7*fTkps0)+j!-nk=l z8G0jgo8~h*o94G_=4hSY2bQGa>d82}23hJ<&@{h&J}dh6`7g~U$h;&rzZV2ctFlXJ!5NE`#>9RdiE@>xL@Gc-7xQy`~CyR4gI5T+OXDxB4MJ=5oqP8S+A3 zf5@xkcMN$I{lAC24B^|u z+h&4wN}djyNoD>xP^dpQjB4_gmKiNGVjQ6!n%OW*KGQI(brvJ3b5_k9p*3^r=7_9r zPJ`hMsB7MUQ}OCalc@K(_SxlgV%L{?>g!9b2CHR62H0x`;NND%0e$O#7(qX7AH_4vlQ!CBR_ z*$MO>f7#@4Fv3-f?+APYx|n|9dyT$yqHu_k!Wk&`N1(=T5>z+KMwA5dTwqq0E?tt# z)B3PI6?3X^%JKGa{w1|)3)fgN%p9wVe&+n?m<(?Wc9REZkIvSB<4?%QY@B?Ay!`9@ zOIE*Lkn!t`|}0v~uZ0_9US>ohJx2s#_|J zsD(?Yi0zPji_1$rd6lVAwX{an*C3wi8unx)M?1U6Y;f`h9Xo@u7 z6n3(3C@&Hj9Ih2P$LVAP_IP>K5YMh$Rq^O1dR7P9M>C9cg%%-3B3v<9cM6x5_=6Q8MJ zHA#=)+5)c#1G-^Z<1(8E8&P3w613`B^%Qj!$qq$5MOdY$sCEii?UdH3V69U-r-F4( zy$R;&!(Y#~$JkQWS3O0;MZ~A!qWY;s(E6#ZQ&US@B}k77Tw4*4AAb|%8sZwJbV-Y@ zDcw^DCf!qpgbhvk#S}#UVoKFiGOMQ6Pvvz&#stWVXAJs)T- zYM81XoZ2)scykF)_f$&6rVFOli7pAH?%ktmOTj<^!UhUDC+XIAQr{$ro-`nAVA7zl z!AXrpwo^ae7SF~JAh8ie#J0z?5zZ&QBJ35hr9Sjevb&*zO37`S)TYbGq=rH+4TbH6 zbV_^Su&}|&Lt5qxO)f8@Rpmt$MX{%{T}4qfy(u~2M1=1Oxk)4B-zJ!?kV#dOw8E*H zR5yu{RIhpniiP!sBC0RESqM5fxwc4sG&anU(^b%0Ky|$m$9T799dy-VI08cj?Qzvb z@Ey?vKE{hR+9r91n|2+TG*T#hq_AGC=$PEEi)su5M0)|Y37;Ldpq{O`)H;iVYL!zq zYFd-EnU&09M@3dRlpMOEQ)5R8M`Sn^f~vbaCJ#>blaoQ3L4BTh4H9AU&voXF%CXd9j*I&>q ztXWO4&WXBF^ssJ}24mgG{G$TeHP(*$3GJX`LlVAn0Vm>!$;nK0thI=1y-KwmV;hat z7+BuigI>ByBd%gK0@^XLD|#mMfi=L4KY?1!rQ;4DHnr8hxms)|_}-BuQ@Ky&c zfSL}eF7Vpe9l|=IyDFkBV=nE{Zo76<7`Dsv z^hO6HW*|BkP4&;gXl0D-%2ERkhb%aabdNs`eZg+yA6#zq5^=^6r{gBCwrbI=*6 z^E!iJM58r1qk;5cs0w7nsVT5msP2lOAz;WrHyQ)-p66pAM3t`2Nm?EMrC*I)j?Ch% zG2n(I#)`YaHM;cYtPHHtwI?y&g>84$@i9I{98J6y9#cfOI!-dQx(*k-72zHH2j1bj zJ>Kp5!KHD7yXovc4c_W_;=lC4Romwqb|WshociQwgq-xt$;U>*CWY9#1((Mj7%9IH zG~8mjJocza1+#y<0N$}DL}5?jxbcQKJ=_rQiet{Mc%QJocuSi1nQ$&JGC4_CyfL9` zW1=Y`%QmGorwMOPgCh(s*vZv;v19TY6G#_v(iM|L6NMstT&U@o)T}AdBwpQbxvoT4 z!oNt@l^9Cci*)t?D=aDd3)W0VQ}#83h7xS!v5htMcxni?k_<~uJ!;<;{o1;G_E&~*Ocih(<;+qW%+hZl;zujF69Zxv0lSEN@;U0iY?4Jfs}$R14p(+t%8(~QbYYOc)u zU?$iHGdqNJWd60Vzs~H-dJUVe66X303{s!bm4UgskdbPx%FL=vN~<#KGbyb{W@>3i zW~WL!Gb^$vt;ph^sTq&W$u8leBKq@M?)6$8_FC>m%cjgIhlMiRGK;Q8u0?K5lx$sa z3(tJ?y@I?M>@Hga_WA}KmZ9|*UXWUs5vt!H^&2wUGFT4Wmql4!R-3Rc2_oX9VW_6egc&Mjr(T&kmO0-) zAtP3jH7hl1-2#ur!sqrzF*}(ThINldQ%P?BpGZQXAwB=3m3{4jjXY}q9o?y-sV4I^ zJ#8-t{;ooMl#h?RE~nxdU(Lx0-&<4-p@~cpCRO}OU9FN3Ba)_Igj0E7SVpwddrNLO zb6CDPoH?2qe_96`G$(6Lu!4PdvBP?z2uk@t$izR_msOX|@Tkjf&1NLFW_Jne%DyS= zX7+G)%3yKB*&`|)$?ne?8>g-%r#A=xvgdETIej^}LSIgQPI_rX?~BaSLS_8V)n6W-iWVPR@v^8FnZEdK2R z9ss3C8he*V)JrCoB%dm!kdM9BBl7$Hej9Co8_2<;*VuSkJ_FVd~J@=-t zo4Iv)V0C#7xjVqATu*L)ZoD+IegSLEyymA}U&oSs`~V$Ut_)dRTq&TW|s)-tzUSo_>wFvcFc zwycR6ncZ^+=kTQ4wcXNoizd;kxiunenAk?4bOS|EzrIF zmWH_+6C!6LMB=?xZcz2_^%eW03$E*y{#y{*e@n$&7S5aokOm|-IH&3shEyFoaH*Y( zO!oEXc5z9L%K(FmaAM`KF)qc%O{dt{Bp2HO+nScz(IBSH-N88(w`der+yV=O?Us67 z>ThX~LdmwPVi9#A!dk6e+fXTqwc&|EVdhv}ta&)U6dF*3V%B$T{N3C5fUei0l<+T~ z+y3MiXzjMhRdZA1m*BQukJuX8X$7qna!hr73-#*308*)>gK%@^g!8&TPpH!Bzq{i;K*mOpDYU z<6%s?{_MeQIb2hoYsFu=Wn&+}Zsz^{v)w#%>)ey?dh`48-A#5T+$eX_5mzy(a+2-; zxSMS1xJtHkV4qSx)s;`Jm}(n(>}*bJpT@JC<{5g5GSdz6Si>G_@K(mm!I}2_!JZ1R zw_i2KRr4gl9sxvL`K*dru3}czEPDoE+wjm-dYZ6Uj|EaQduI2}c73yN&bF<0s=)nm z4*MCJgI8DGVm*#G)y%~c>*nH69dlhLy&6)>AyPAY=l0EYdQ{9K+V1(ThlkbJ(}TT$ zI@NOk z?=Fs`xtp9U^C#0@54^d`j+MDV&XeI5oHgb!@9152Hkb`Fj?8mBe)wKH6VF`%FA}&` zUfbc-q4E+}T~bq`7i~IAToC z_Ob|V-&8pUZmryEZ?@sQTYI*;Uf#>2^LdZYHSxY6??aA&H}JZuYve6pdq3FKK3w-O zr=a#$v+cx-)!21!=U&&vi__#DsAkX~s3ZCuXkxXOutTG~F(iZ{f7+&P(qZi!= z=~>>ecm2E%&v?<7R4R@%9l>>uRPfCpKBU61)~8VFA8mRR+D8W-b%T7$1h;u~kgq}W z;SzRT9_!)L!+e;8kfINZ)bS+|?5*#KH1XXJ`s(EHNmqNS{*-Gt)qKje@D)QUr z`Bcj(`#2#@I8}YhwV&@e@A}U7pSSON5l2q-opLw%7$L#p)X*t6e5(9(#0{MqKIO{! zgrKY7GlM)xJY9F1uljYK_8$mrJ>P!bb)D}y?}qpUS;Wp0(;Y)$9+uJf+vd~Xu(J>PfU z^`9R|;?);xF1p%_br)SdU)G{s7i%xt7pw5ri%l0@Gas}65b7GS|j;gCckEBru39W2%cqf6YG# zpi?9fyJL#3xK?^~#qp~bmtT7F(&^==kDoZV;@qW^7p|Q;z2f5WlaHUfbUN}skd!`C z>WeR&JF(*I$&;^f)72fsx|k75@LQhW|k_{|LjG;*;nYdDE%WXO3UHQ1+&> zXD**EEq+`R_nS(~PMy0{2Et4T3<)rE{?q3!jL|VYBI9wb22PzTJ%8>=50{o*J$LCW zFuTb2oVa%GLfP_jm)Lvr%qMB{X-~*UGb3@EX@k*e(Ri#-f79a81dq<+nL$=@JeF9& zhHrEmz{+?~$g!wsd^TG|QSxK;DvDGx{lxXP%7Ts@!05aXbyc`6fgYh0^eu;&_I{Cn(|K5=Dkgm~Q#(xWN`=MdP`_FRs%$Q{yvXPg|}& zDU4?&0`{EavEum5;Fs68$K%EEX)EGWimj@5(LaUKN8J|$*~Rg~sCv(Oj-E|y_aOEv zjP9pdijn5AL zgMU;6%e7YD+EMqVr)dB_TnCko<| zS8R`GCzixxd*TIjr8HR;pASQxTD}5f{qd8SWwI(MB4-&MO=*s4`FHsgB~~PH^Nn#N zx*`$0SW2e%y5cx}unBZZk^KCO&^s_=kl{7NpK{K4hnMiT>E{f(27gYQ=O8w%_>6ay z?dEC!4@U_d<4ipECkeb^RWyE!B+?|8cpOtQJc<)I>?NEgk~;Gk$Zd5NHax`S*6F#1+7MnvXHi*C_npp0FWNmdwv zQe;7@C=kr@n$aKEw)+s9T3Ng>zMlGTCx)$x-@7!Pn+SgJEIlxJvL*!6EU1sGuYdjQ zxbwZnpQ6D#A&CdyhciQJ1~=lx!K=@DcdVc+*Cef=7pI_da31B<8L67w0tuG71x=un zJ7fj_hCmmL63PiEZ@VtN!m4Kw5VBTC0>!EF)&Ca$gX7+ESZ6FiPcV;6S45@T(Kv>M zbs-M>PBDzaT>3?p_PJp*mKvY(qeL<*5-Bm{c~qQQNEFdDk|%=g#HBYEdpO8cl-NDl z#x$eBCEDZ*>Epg2r!~3TAKaqOTjx73E!YAOthe?aEtYTlNe=O{VQ$c@d19>7ZVfsy z3KLU2_##$Imm=jP&LE?hV1Nl2- z+jx+xNkzdqp^=mgp`yJQj8hpIE903Gv{IA22Ie_yBM@s9-x)#Td|1d#5ls-jSH%mk z3#$m1C}&dDAY^RGuR<3fYrZTe(^GS1aMHp@k-D_?wevDlv<0l}pw$&at^pqpI_0w{ zF-7qvnqbMLe_A+rF^2MtFIq7J;n%RqD(LRCR&h>BjwtUzx%e&$&QPGb>5AYpZ-sZ7 ze9Y|SNi<m5eTXQCDb3BS`6Wgka{ zmGK3|@dEScf|cF|L};ok+HPx$V@OmymxXttJc9FskB_NCp#Lj``q{ns%!+VQ51QX9 zb)s)0`16q7B>mA_&zO|p<1jGi7kkIqYd+58iqT}9C=*Y7Z9HQsCRhc=LP@x4&}viH z^n^{ya@oadG|QKma^xN~f64Z^nKKdWj>Z)-u}XTdrZ~vhe%4B&!6)8g>eS;X)7zlI!Pqsqe%PwR(ssl%wppPJC!(3skpY;t%!9bTR%UDc(6a_KzeP*y=trgQ!eaQS z>dQ1r3dIs%3u{L*^+oT97X(jxA6-Z}3f^utC=3+F?-H!$;1rbpf9<^od{tE%_PbA3 z&IzdmLI*VpC^ZR1z&ezK5~?98wuvE)KuBT|KoAuX#eySPu#BQ(Z`j6BWYn>t;wU;Q z_AaBSqmE*mv3<|;u4gAF5k}{J-~H})fA=2c{P(-|>g8SUT5F%3$P9KtjOk2wVSLs3 zE^Y0xks(+|?ypFaMGISlqc&oGe8W*R>ua~d=s@_R85?mMQIY5|&$7c=SHcVpOF(_e z7r|>0n!6G7n`4bE+GO7~5LW`+Ep65}dI7V+LRO*Bro1o`tUeN9zf%MBHdRP_0eZ=l zXBy21cGQ*<@HXdG%lvo4Offd`DNFH_`v&ot}>jc=~sGlF8>U+lA zsnAI6A<&J+@b{dryV^jJhV2lp6EduZ7%m|;6dA>!&WpkxhvK8MVktviie@Uonhq|| z@O>Dr*7q0utw3gjqbo83{WmKo<~~klFG;c3Vd_Mn16gmmsDH0DTr$)sZ^KLm5-KIp z$rM~ww4){Nvi$H!aF?A-6A|`Ff;$Xtfh)8Beq(wKl|c35PQxGMqee`JkW~f!4mW&3 zTX{Xe^#+Eqt1pap$l-DBTby*VE_>7h(uIEL9sRTjpZ%D?tgy?vDcYleH})j;Nmwmt=|`8K2f`4=C3jm=y+MZog$S+d zP(khPZbjLV+Vjad?xuxoDzwj56fV*?3vGklQ3|kf-4>)BTY_<9j^H1AR4|dLB*p`y`u}X`8#}Z42oJDAu%L z(cN&nKQB7K<8FwM<2lp)6@D~QEgQFSnUBRJY-4S1!K;g1Asssx;|!~c_HaZrQJ6k? z=!V@{JL^oJpbsQcg6^w|?ghbg-DEmp{)oBv=3+a>ucwg34rX3Q+*(wif~C3zl``zG z|Acj50v0R1yyDU(sH?Y~A@xsN`u#jxK2saROxb)&;}DH(UBDH^TG?aD%x>_BGjLz zoKbg-Y6$9pEm0*-vp8rYP`!j9QlKWijYs_$_O5V^FMXLh7204!#P3!zKlHt;^a3f_h1J=V6l#L%FlGz2(X7{v8{SKA)4DY03)2AGg}M`>;Gmy*>(4+q*ND zuo7J@Lm8QKS5zalwtI?*eQ^ zhad^eovc#;iFzMq%C`7IEX`UrRP&~T(T6kKnqB1N!!A%1OgqIjS-*jOg9czS;rO2H zbtk56*pIw1873Kn_*Fo=Y#KL|yY7qe2(8#{#K0)FT3ce6i<{pCO*uwnUsf`RSdHN`ySLNnBMl}goc}Y4u&ztAf`81_5^CXRH#es zUsDUA$uWheBi|5E?`zp*+#Pe9TLojnZ}C2X!5MWM=CZ?T@0XcFn8&#KWg{a7L>`8Q z$w({wf1M|vkH?XkkFz37)mCE|r3tZ#%mLLB2W$d#5>GNPckCH6-4oM{ha$7fvNv}% z5BxF}#l5jVpmEdOV<*x2*obR?$ns~%DD2sY&9_y1TCJIRYAzaba1uGlre5{*i|Gxti`4~S;^t^1@{*Jyj|8|Xxd_!llIGu*#m%e3r5^>iz{ zVjy6`aNn}YSq8VPD-{;HMt6;up(s0=C%!+Jibb-S%zB>JxabvDW$r%PPQcDclG_wP zS@`Yi-w@Sar;OFeidF4Sqd^ z9`i=4g4vjKzsDUY&g&N;2Gl|%2ICCtC^X#@P%xS9N?ND38A!`9RBgD8L5PNB<86gi zgK7DC7$+F9+`i_aO(P0rr(v8}hhtlR*_J%u^cF9o+F+1ZalICry{p|{#&gDL88{J_H|1Z0I_TVb%j zigBxn(>QYe99CJ38^=2t{rQdJ-Ha*8%Gb`UK5pg4+?IC8JqH}>DFf>`E*Y_1fMRh8 z8ec)|edyCR?|A){fKw2T1m>QJWkN{}L8F+hwr|S@UoHj~mwg$ofo0;xp*p<<3#Sts zP?kVsC{mxO)K5juvJlAf$=1YLd`=EVC|VAi;ax2YHqw;2A=WT#SD*b;&4-M@tI?YN z6bF?vmAQHCq)J=TVfn!sqa&L-To>oD3H`X>V1jS#6jL9!r=5z)nKjBwzXq9VE#HR~ zWkVioO?u``t944c!(kcPCk0(CT)FsAW?;ZprHzpYlZ88cX>M z_U^9kSZJ6o?2mMZp`X~f7jnS;UFIZ|J%{8q@6kkYHl|5~NpMhrSy5A$&_7icbTo37 zFgTjdF2!x)4xFC3oUJ;MSU_$T+MeZ4m~c{DmqM4vT6U9o2+975E||y(5Dmuq z>Ox|o*UzF-91aB&07%I18bI!w8|gz|8tL4n}N-t~aL>*D<3PI6aRoR;smEZ^7eBH#4t zUWON(9VEN!s(hGN>0o*B?Svi*HEgpZjw@K>ezzdUw@SgkDU=>Co15+9cJ2=%{LuiOTBP=EyHc084-WF9`54PAf-C&;`4nArgZeH z95nV2JNrq^i)K!QlxHn%24rD0p9QeV_h#fNo##&2HcnzUKvbleW$kbQHO36GGxETy zr>nEoHwHdTB93JY_fdt-C62g#pogeF@qun~i_yKPBO+9S(77po<&E)7eFP5+Xz!-7 zQEfK_&kC^r<7og7mX9kVRf?1?kKh=9qa%v?u?E4mNR@9iDyXXH0C*bem4kKt3?`l! z+ZWY&>aVFzwD~uvP7BK|du*O@qDjKQOE&u>G${BW2P({tb}<7`_2IZF+0Exd1;>L? zY`t@^+ricH=nRXiGMd;qx)FMG3o9%k7$k^S5>Y-}QY zFz&2Gc?Ozp+|iu}+ZZZ7+lMJ59EWfnNLSam(a(zvFgdhV)*_CuMX-I!Ngk73tConk z%X(l*-ZBJWU10&jApk2ELjda_iSrix!0UD1Qxbv;Z!;LNId z=&p+%YCQutyv45Jw@42dK@B|2;!vwpGIbb~?x6}~WDxSS+m<_C*JnF+BrBmLV7scwly6VFC5xC zc`9!?ddmgyj8XF~o>a3bR3;*gRqWkkL(H8@AKny3W|OA)$MW325I_3vN|>X*)8ix< z*-CYLVx7fPDZAn<<`t_AJIbaq+QY3WM+BIC5l@1t zMD{E9A}pbFPO~tAF!b>z36%J~`Dow)oX%kuu|6$jg$$oaK@BqEbaz2HhsMt>Kct=P z7Df2%7On0b@SN<!EP_T z6!IyD%sugx10F_@!tTz_)I^hqgN5gU{wh?>e&7~HyD>KwmCd_M?EtJ*;DYBPuq|f; z0tWare>DL8W4N89CZWv-bF6Zuz}~V47K2bImG-S2l1Uh>Q|$RXJQIcIsIZ{LMiXj+ z`|MaJGaORfoejZa!Ct0P@lQg~gyUwRH2*%#X`xq?Om(V-&c=+4-pUZuP1V~bL};5p zEBHr$uug90Hed`>r6RGcC=Q8vHqLY-wm*pm%g5;`WGXJs8qwGxNP`<_?YV)*hgCAO zu(^^k0?uKVFNzLF#&|}b6&;H!j4WIw$M7r->lnKxnXVSkzVIXush)OZhWRFq8cyd2Ftb?!e!B|$4jg8K%*;*3X!8pz4py_t zV{QEoU{)BrAM}=Glmucg98@BdJBG>;n@(14*Dp>koto-Or~1|WVs;oK?a4n+;1D?i7{hg<2mUV^5qIe?>WW}kZl8Ey6kY>>5dY_4b79k|8ESmO}0&7~>p9s806nRBXrkMH96uc5HFF3+2q786Mka z#>zq`ZOx+^xPbH%#fytr-!@TP-p+2JEX zUC^EHZb|MwOYYJCoE+-iKQc~j^f052xhL_Q_AU~?gFbxualV0WmW5XJ+jFQks19lk zKG2cwHrKJ>-H|D)EYqDEvAc&ykNpf)r;UNKbAp1Z9c0RaVM=R0J_3?GLU0Xk&#w%%m%8%1~d!E&L zri@!2s(fzeYsfoCAv%D1tl3cKcW5@et;a7kMV?Ygbr5QBYAt4$N6kS0 zI1yq#P=kmo>7-84_T0`#+}J=(Qd+TTmMshC=LmQ;iD^Pz5Aza-ujzEeYFj_JZLwn8 zfw5A*at*8V%tU+~@|;gRm8^u z-RoHOYvirPj$IUI&i`@baVXG4y9}NqF58xd&*GSR7enD}c(ZK;WTw?Vf`6Ka#xQc9 z$M3z^Fz$0C57XgXY!I-UhBF*zR`!)dbYIpj1|WP`+YO0k*>Qzcw8N^OddHL|HDKH$ zs8sn=t&&hD$1PWURpH)&@9YfWXCSs(6>G7Qh2&~3%b#4a-Lr;q-H+y^MZ*^6p@W6< zt!P=b2Zp*>K=}N*e{LMQSivqmpkJZ2x|x>D%ED8hEd~)r7ZOGdp|N7_AvUNV%BYz8 zY$wUj3~hIfbGxy6TBe4UvCVnYjG<}hVz#H}ZpKF4Zf+|cD8V#wbrsU^(?qy)Yd=1* zhjC5aX<+${TtxCb><$i7Tz01s@mdYKTJxhf-2LY2|6w{vG=7p$}UrpCK* z03^hw`G{8Frzs3&8}cw7{c=ZJ518N3R_S;?wj&P;XyWi#H3|N9wwuQEZJ0D)U_c$s zO?2*r`(b+;Q?q8k(`8Vr_?SLhWcn-_&rn2pjPE;Z#2swoVI0k7m~G{)ckI3CYdeup zXI3~I93zA5b4(7pCCxu^>ASjS3Ov|FqsKQ|)a~P^2K3>>*4a$L;G9wX!K|$#y`_LH zcK#j&i*xD=>_1|&4By9Kqx|e9SnqzlP5HSp-?novHxk-0xj-fW*=|Tpr^zmL??7UtHKRel1Mty5FW&Ioe z*I|<=-L1Dc{T>_!V_|e}w`H%5IElCu8BTSx)kIv#L;I2%} zACq%607v8>eIv#r8?)lPjc&&zZX2?LRqFs>Aiq$>bs8R*vZ`&)T)1LIqkL(N*rrih zwaEZ?d-6Iq#w?1}Y@5ZoouOvfhK8=ps zX6)iANZy9o$17BnS4CzUnM!@Sl}f!GD)kqPZOu5`(8rQV5+9C^x?WhG_?msvx=M2w z&e_NZrC)=W^=LUiAk9?wOBv>gJD%)$r1cDHHTope-GfJSoHa)nO}-Wt45J|V5b8g7 zS8qJ$VTUB_&FBN}5#%6wU+iJr)f;;-xwiI0O?Bp>1G>5*rvBj}7q*M+$dDQmhJ}0C z)(^DD4d_B-IJX-`0mD&Z8$yFH%a(e!S@3VQsW1FvbV1$PFSs=GSI;?rcQIZwu{Y zL?fNg&@Z@`k%*Oi#9fSP^&Q#oX*W+t^KCl9v>EY79a+uxfgkIrH5S?ToM@$Ab)sn4 zy|Uhc=1ZD9bO62J$ql3z+UT}eYYt6|Ec^`tw~IL>F#o}J4gHgR<`T)-gCdwTW7E+{ z^ohNt1F__W364V~&YG3cxpsD!n8Vt|o?RGcX-;%JtGfA7RjkqNp;b$$Gv{DVpk`|Q zDH_ENHxIiyaPr2|p7CJs2^&w`7%+A1+l|lQbH2q}H(^?H@VBEjgzw?7LvaIU1}vE# z=E)-GVkmq{dZjrd9FEQt9PAJt_N8FQ3Oa32wEOUAe>?+)AIo4VV~%#lY6t>U&h82FILe0TR48O*W?t@C;i~u{bvmbQW zzV>UY4$&U?l@@-u!rvL;-K0<^h#3iB;g79NZ2I)zt{i;y@MlTrs#r*L;6W9B$JB`Z z3(PdgJ%4M9p!|sglbReI0S9;*VdKMpb0|8E4AVuYK-)8hFrQ|675YqR%f{hXF&LR!oCWwC8Kh=M z1$D!AUXNHM(#8*Ui;;_#r*E)v^ua*Hie_}5&E(9Pg9k9q9fXwzMzQ-EPTk$gLFhYJ znYfFKVTran`@&+LJtx&2!5DaG<3DNZ(q_i@Pmc< zXEX6A3!b|`+9(oMw(0Ke_(-X#5ugWc9n9X%bp`vr2lojuK)DI$u15q}gQA@-xgDWPj&hH*C!!pg{Pory+3<=u=7CB=A#!3fxYr(#R}R6LDG8KuSVxDZD&e5ANP z!E-X?oI$o<-KP4W3@-4Lkydwd6d zWY?aO+fNy^oC@K7tH_6b?$h@UwiSmG3K?||4vIj3@k{_&v2!&HyZ&5$QOBYA^hkZv_#-Utd+mim5;wo#hwHu{@qhrAW@>ez zamV%kM06;uUNUH9YF`K|ca+2*3fRVw+!6c$ln=IoxkB8RVxfuD>xd_t%Ws_{=!rV( zZ!`Q9+YTz;W)c1}0^ae|8k6mk8~!{;$(rG--|QeAo_Zl!bA`B{PnIH+MKiq`EJrW< z(02=Fpn32mcNj9kEh&s2x7eSU0VfREt1x6cV;9hEZ!=!KV%z@nZf1Sgr+I;OMJcDa zKJ68a_j957kvfSByUyI-ii_X-zXI-DuFx>x_6cY0bhoVa^z^?@Ei5;^z`?zB=JI&G z5H28~7N}~tBuPA-CKR41;+rj=kIQ+yVnyS($5b&KO5=9aZL)io`UVYjixv2}{}9ZA zK$|uPS#Lr9wu>OXzNp615yGZJ-|n0s;{Y?1d7~)GQEjF<{pZuQa(NG`>k!1S?EH>wLF?OomGxH^~V*k zvu)em@0#LV4r75?!SjG=P+68fOofb7H0wOqq+LP3xl{P61p)M$4uar`cs?KWBm zc@Y*F(|}2X<3DDK<>D|*Uv9Ev5n*kO0}`Q$%n#!27w4?sq3WQ~KU;+$^olp5*#07{ zAO!YXjZ7^swwx*Yhoxw3CM=KkEcY^=8(U^i^CfVDZL)u`4~pCl26Lk&jP^y=Wga@q zC5KyQ!IBTQ+~DQW9#hJrsrVfuUI*oujo4J(Ne6nbAA8!xKJYF^`?h|OPFBCE?$X0i z9QS^|ocoaOU{)klRi7v+%C1{Be9=*7%wQjdO}hYpW^(f3Ku$PHA;*P*&5} z6jaxjHZXGN>s6uK;62lcpUuX3C`elKi4chZO|1C6%R3 zjX@=X)HPNFix5R6eNCM_erCy-vD1r+3-W_S)wPWkWlcd%dBeg0DOLotOUg@|N|6;r ziVUL6^DE|;l+`b0*y8EaOQw#Qc0|ea83ofy#!s43Fw@>ChWC(_HZ5RcO$`fb%SxLn zf=Wb#@6x8q#$dv0gO)vbep&s3gUad}nktSTT)H3RO2`W<>lY5=bxmDq z(_mD?L32tQ%He>Qve|dpoP%(=aOB|9f%EGJBHIHMq$+#x^r685WO&$6k(O9eMN12FPc8KuwWd#EwNygbu~40i%_V;vfTQ{ktM!AlKrbjLuuSpoE18 z8tZ1ywZ;kyX^m?IuCA%5uC1&K>KFLZW0023L&7L;O=CsHJaqh$avPA=*tHdlg4)W4 zii!XOw?UP{I_8V>N~-J1nrh&PW-bq!tTWYf+!PheWG9$jgdAFrDzkg2x!E=I0=s5w zTQF4rwCR5295J)FU}{|7;wY{xwGyH8qFhX=wiL~nKfA1Wc1?grwO)WY!l6E6OwpLB z1;qtL!6NJIEzt*Kk0>q(>McK&C5sxWF&eFhV>mZfaFj5K+T)u_O3|`q7%`1YW?TI> zR+n3m5I4KFH885lYRQ_wIv<)p>}4$f;YBlwirJ|xhn1FXrad&Q3XTd(grV5a@(ZR- zLL;&lqdjbNmDeqpT~iS>Yo6wD;gwWv$((XkKidQ|2X@nKW~Mib%1jkBR4nidC#LO(!%*xMVcYfHkW^?JzK;OAPavZQfwZ5cA+ z>jAHUESu8+wa;d02q%f@lY`mTa?)vj9>X}ZUgI^5uPd}^0}Ixy8Excvoo4D7n#qqa zCd;9RzT_id{WO+WvrdX9O)Z#yXmOA~vv^GLp)+kD*Ob>Tfc9vx&WH?EHd2pkK4Vps z&n_z&in*Bm4^3Qz8FaR(h*~O1&5f2F8@@LFe9Jax)|v?#%X+QNjOg`Kp-meqn#$(1 zu3D-|yyuhCB~u=PCWl(LMl%(RVjNyHskoqIM$zV z;f(gaE_T&MvoeEV1@e?1SLRVZE5Yj>g5XNzC4Xmm$5o%&SNuX%}vS39-A8G z^TF;x@T~dWNuA|qj7oUavUa3>pJd-b7 zQZmxe8(r?CQtd8I>lKFNYYZx;Efo!Qak}llWHZ#O6P#;BQ2NWcfHA z#2;A*Fmz16A1fK%Gn_k|qlYRX4L4)rtTa>$`hrd$s>)Weidh8*f# z%D;mg>Qc&AK@RmN<=Y^K`jYZ}kVD-_IsW7D+UZU44v?Q{BjZoS2ch0%_*Wo@dXMs_ zkfG-Ei3U4x73w|S{~mIv>nJC;%0gn01v%7byq^uZR~Q}g(-(3$runxd2DAzvv;41a z{)-c>ZlXQ?{pRQ(50@9_IRg10$h^*wTmU&cPHtU4iNR!rZ)g4!gF_(m8bbo{CE~l~ zLZOIB_2rU=oS@xF9P|V)%}2Tt>jKn`^@oQ+-2SJ+7-88%lHXypfE>Li}EX7V!!dF80F^T1~`9 z)@B#ZFN^$AhQ4iW)~7tknKCXfh~MDgO|BMN#RXqOuq~kdgI3!tIa9_=8#i%!QC@39 zA0dV^@?rS$9)@T)DrczQrOH8!ji>=_IF0Ah+tw=DPqS;kqSe|iZX+UYQRCNe@WM4p z>y@Jq(6R>=E@-vkqirGEG11P(PWLmzEd;F|!(GL28^y%u^{h1NaB7XRO7&&$Uis;%mZ1Ta`FJg4^`TW^9m+>=5qx||7U>opV-yA_d?vf ze+`Mh+)x91nepG%!?O?k_8J`ox07%`5R)6rw_I<4NQ@5!YlMiGTSd(!GX6y3gX?z}*lY90V34Zu(m)t|D>oDamh( zU&_54bw~f(Nx0>W0uk>l65%?b&roLHVfpgJa=F(?UL{VUU&L2VB0kzC2`JYEB--p^ z@iG$mHQNDokM0~Kpia^Kj9tVYB*qS!Ily6K08`!Wqk4_Vwh>igED#IDSz?J;E;fjZ z#goJ};^pFv;-ADv#23Z4#ZSe5i>VQxpI%}=k@gqMNjrEQ=re7UKequSR&37 zY5UXPL*f?kHF3MhKm1L9`-sEEG2%4wXz>K`6mg|^j(EO!iFk#0t$4F|hj@>8zxar_ zS$sy^D!wMZBYq%$B7Q0UBzBMb^6eq^6$gq##8KjJ#d##+sF!@A6f5nz^s+dWl{d!8?L(CP2i3Q}IK~PA- z|KXC4mRv2lR`OyJ>6|Dom-{)A*NA@*uN7}15&xeg-zz>K_sx=@7T*xx5x*Cyz?eQB zeX{s6C3h0L%e|jCOztDa3F2gN28nzfCAmbLFCHhJBAzCmMIziK;x%%=L0m8Q4U+E@ zACmi1lAjf~%KdH0+r)3>?yxbyawmytB+~CHxu=*d_kogg#o==QjpT9SM7htDe7JbD z+^Zzd6Bmmoisy)H#4E*X#Cu8f+rN;5gWwstKQF#6zAb(zejU55+IUuf-tM#}^|JUl$VP?IHFS_YsGXNPi>=|5M~XLp)OVkJbHpxi^U? zil>NYlZbDPc&*%T6z>%879S+x|1t4ZxxXoXAbu=PrCK3M~B=Yl++&76^#OK7< zN%()4g#Rz({oMEu{8@SoWpL_Rx-yOX%zM;s;h1H}Syk~ouu|077mS1tGX z;zDtWc&fNkTrFN8UP2AJs4_b-$CmEw)!dhw4W z;@c{|DgG!Xb@2By#qQ!>;so(%u~EEGTqj;H-Y(uNJ}mxS#Lv4dKe^&`ajv*pyhOZ8 zd`kRE?2_f<`Hfg9t`ct%|0F&jrglQOT&xqsW5pWrcyWbzz4(CmtoSO4di_xHmn6o= zx8e_SZ`awor-{A9Y_V2s5Eqfi-*U;Pi|3L^??Mv&;##@iDBdaFE&fG(M0|ooxW7r> zD!wVcD}F-4UosZhVD9|8Gddm(&$R`BKG967Jn4?#l_-@;^`#fSw$k<%jABgc%!&pyoZGU`$_oUEcd6y7sXe_ z_rwpxf079QwHU)b9m}60W{F+JJxKT;E*>h*6;Bo~5N{ASljzsaOMX}KCnVDQT#R)0 zGG0Yx?)^xF8z*^!I9sd~>qz8l0f~AzP3~uk=ZR~@E5xhCTS$bzlSKH3<^GuXjQG6x z1_}S~k?{YS+;@oIivc#MSiWR2UF|yrDVC9lubM=BOXPl%c$V(3*8MBxevPe3rc~6mh=8R{k?vIuGcyY4aizUwz zOT`LtE{S-SikFLbijRr!ia&~7u&2-RWs?ZMABp@QBu*6%5swwi#U}B1@e~sAtRzw1 zi{$=$@fz_4aXkrtcT3(V{)I$5Pm0^bAH^Qo{(c^b{O>P$lH_6%<(MTNBlkIyYsBN^ zzEtuuakY4Xcs+@9?v#AD_-DC4CizM68M(hI`AzXXxqmA83o*c+A@iFkb|+E(J;Y&h zA1RI&^Tk3E{;S1P#cN39`&P;KOMZexdQXY3i*Jkn6u%Tx_ww;~5c`q{-(MUmjt~pU z1UwQXE))MCZXl7bhb6y8BEGl8&%_;~>+SC+iCx4VVsA15`61Dt_LKWT;&`!8oKC{u zEXhZUr6l617Z-|W>HhD;i^SiHw~+|p>#D0VK+mBaRdg5J!{nH%anTv6w`@8pW036(sU`qvVH4#Q&K1qWG%#k@%??+1rOt zBM~lB%oh8I{Yj)VT=FRKAh}PJJViW|M1GGF>*U@jE)|!Fr<3r1rFf%wr}#JVRq<;v za~~gWZxZ>-lRSw;d8UfTh^1l^iS*78uOL~Ek{>2nkK&8stKx^^C*t=aA3C&p6g!E# zkw~vMiS`{P_mSdgF<+cS!e5c(!^ERV#4}f{C*g0I?ynHf5!Z;9itEJdNyM|BMELvV z{*d^jxJ7)Kg#R~5`2R@mpNijz--(I+;ScrKPV7J;d{=QFxepYFi=)JR68;NGq<5s; ze=Amr^TY)t{GUL=|JiasSG-ufOuUYS|654-zfbObR*CuEEIuthPs0D};y=a20p7hQ ziT=}9^1&qH87ofE{UXVSiIw79aj|%!c#gP6yoN+Nw@Ln^xIylZNPb*=O71U7eog#H z{8ZdQBHkY*Gw=MDM8dtJ*C5TBC!v*Ih_8{+%oN8%3g8!;G!_;8&lrjUrgk2qdDR$L0K}RX7P5p|5@^1#3xA9+ZOR%xxX)dChib_AmJZBx3+fA zB2oUXVz$^v94rnIN05l)HqS_gl$}NR;~oaT$q!XG=a;yg=?(NWNP9qj->=(h_9hW7NAgf{q}<0!9xqOo z`(cug6iehjS8}b`DEE^jFBezJ{XEHQ#ox>QI>|SQx5<5@+VLjw zkK#SzLnQn^F1{xBx5Vw@Kg6#|`2U_nzS2he_%p@MB;0qGyq7qbM7Uw%1i4QZi^W;u zY!d$Gh)dDB@ymr zG7HbKlPLdZa{p0s^8Ro~eWr_iMwoK8m@5tw$BN^{VsVx@N30PWNThoriTtdU`=#O) zx_^`8Tg3;&hsD2%Tg7eScJXr(@qa_29+M6LQI1rxlh{q%jfB6wB@YmXi6h0)V!k+4 zJVZQF{H<6e&J&x&LFBiC8B#ip#~*#dArde<6wTUn}<;#XH5j#lMJ;h)<9R_nPFl#BC(vjpci$ ziP`8yyQyn9qkArY># zL~ zs5nI|(fu;9MywalArbC;@p`%6EZ!w<5FZjZiCe_y#Mi{P#O>lg#IH!C_Z^9LOf3Xa zFYU!{VlQzo68^`ErQ$+yHHq*Sh?k3h5N{H174H%MEIvvi{wKv(<^HDlf%vibH3|R8 zlYP4BVi&Q8*qemE{v^t|pWF`;$I5-OWW4Lg%27-r+;7NG7sQvvcS-o)P9olK<^H`Go#N9;7PCnB?@q#hf4L79M~M52`6T=olJI|| z+bOFBAvBzzf`&k@g)`|l-RAznu! z+(vPW_^$Ykm@>oXKSS&)_7wYw{lp>SzT!9%=}aP#za!*+j94ko73)d(KS^98_Y1{! z;#K0!;%(vv@jh{rxLJIOMEq}%$j>Ko|6KgH_@n3!@&3|Cv}2~&okTo)=zgx;hlvM@ zqs0Oe=}nVdBpyy8o+j~R@e(o@`#s`S;&tN9;%(wx;sz1ZtNs3OZZg;(?;{dVNP~?1 zh|S`q?Y;b=xO6w~{|s^3o?f=+a1hVrzFr>4^%!JZ_krUi$CxhUOcLcfAmVvziYI>; zPWKn{JUh`JuDi*9AIbeBkCqJc(83)p`B=$IB`=eFvE<7n-z9m2qe|;$ODpK9UcVJX-Scl9x)pK=Q?s zH%R9D5E$P!$=fAoJD(okkHGs!OFmZe@sgKH=6e&Ezbhp_EBOVEjbrk4(NY3z31mU;5V)lY6yc@T&4k7HiboT6qiiPoa z@jA^Kyy}k;HHRo|;A?^5uTO{sIQD4%glUms-{Z|rRQgD_E3Sv( zAJb*MGtIEi<1*+p73~`rFpRH58-Mq$i3IO3fIgu=ybyUY-Xc0br!F^}pFI2aU;f&E zj~G7O9EXe=E-%NXoLn$vd?XUa#Cq%3s_t(0m4&|z$4@`xzkN`Lt7s6hI|+9}*exAj z;UJGh_?s5IAH7{yL>o!K-!CDO3MeH;`x=sRh<4FghNR!ai%X31&8v|_4lUeE>_bG_ zjfR&X(kDnwJvh~6poTj{`etO|vS$W=EaY^D{iPHB`FixZhG?IC@a=*<@tqL)E+ZYW zT8Wu9-dCl{D>JXH-U1tUFaFK3@$V&Wc`NY$?eDv`WPkqd-v2!>QV(A%Z?Dd^Ot7(j zo*TQrlNai?WS-%E;cd2KMxZVJ=U=|ajuU=<`Q3|g0}z3B_AbUSE|Tx^i~s!h@77C= z503btiR1bkyK@4P;K)jV!ssYcH&O0E!jpAs$o=G=E3yXZ59YKnU*z0J_agCFu}Z8J zS-J%3%>Q5~{oF=sHf{d1G1SKJ*|m}Lf8C~`t-|&XTgmG$IOr4h4b~s8Lw&p}e^eoC zlV9>@$`1a*595nB#=>+5!5z&IjK)8HE=I)5K(;rP7ymImm>ZTqz&_XGdv9G6VSLyw zXuhWV)A&a<9DYK7*q&>ZZZ{;vbeL`u{)OotgX=I1E`z`0AMLg96W*(a1FuG!qq8_l%h4A-l=Gv#=??HsX1kr5MWa6529JU!QgH;eP z(waYER@=_C*{Fzfntl1aQ>?69P+MJwKZ>Er_E*fcqq6Pu%X94pRz9Xy-v@Ux*KWey z-LAsd82ZBpbFCTgk#>9!Ddt*M73SLUloF$(3`uNT%(X{QYL|2?q@T^TY+B5 +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- --- -------- --------------------------------------------- +* 1.00a hvm 02/07/11 First release +* 2.00a nm 05/31/12 Updated the driver for CR 660835 so that input length for +* source/destination to the XDcfg_InitiateDma, XDcfg_Transfer +* APIs is words (32 bit) and not bytes. +* Updated the notes for XDcfg_InitiateDma/XDcfg_Transfer APIs +* to add information that 2 LSBs of the Source/Destination +* address when equal to 2�b01 indicate the last DMA command +* of an overall transfer. +* Updated the XDcfg_Transfer function to use the +* Destination Address passed to this API for secure transfers +* instead of using 0xFFFFFFFF for CR 662197. This issue was +* resulting in the failure of secure transfers of +* non-bitstream images. +* 2.01a nm 08/27/12 Updated the XDcfg_Transfer API to clear the +* QUARTER_PCAP_RATE_EN bit in the control register for +* non secure writes for CR 675543. +* 2.02a nm 01/31/13 Fixed CR# 679335. +* Added Setting and Clearing the internal PCAP loopback. +* Removed code for enabling/disabling AES engine as BootROM +* locks down this setting. +* Fixed CR# 681976. +* Skip Checking the PCFG_INIT in case of non-secure DMA +* loopback. +* Fixed CR# 699558. +* XDcfg_Transfer fails to transfer data in loopback mode. +* 2.03a nm 04/19/13 Fixed CR# 703728. +* Updated the register definitions as per the latest TRM +* version UG585 (v1.4) November 16, 2012. +* 3.0 kpc 21/02/14 Implemented new function XDcfg_ClearControlRegister +* 3.2 sb 08/25/14 Fixed XDcfg_PcapReadback() function +* updated driver code with != instead of ==, +* while checking for Interrupt Status with DMA and +* PCAP Done Mask +* ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr, +* XDCFG_INT_STS_OFFSET) & +* XDCFG_IXR_D_P_DONE_MASK) != +* XDCFG_IXR_D_P_DONE_MASK); +* +* +* +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Initialize the Device Config Interface driver. This function +* must be called before other functions of the driver are called. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param ConfigPtr is the config structure. +* @param EffectiveAddress is the base address for the device. It could be +* a virtual address if address translation is supported in the +* system, otherwise it is the physical address. +* +* @return +* - XST_SUCCESS if initialization was successful. +* - XST_DEVICE_IS_STARTED if the device has already been started. +* +* @note The very first APB access to the Device Configuration Interface +* block needs to be a write to the UNLOCK register with the value +* of 0x757BDF0D. This step is to be done once after reset, any +* other APB access has to come after this. The APB access is +* considered illegal if the step is not done or if it is done +* incorrectly. Furthermore, if any of efuse_sec_cfg[5:0] is high, +* the following additional actions would be carried out. +* In other words, if all bits are low, the following steps are not +* done. +* 1. AES is disabled +* 2. All APB writes disabled +* 3. SoC debug fully enabled +* +******************************************************************************/ +int XDcfg_CfgInitialize(XDcfg *InstancePtr, + XDcfg_Config *ConfigPtr, u32 EffectiveAddress) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * If the device is started, disallow the initialize and return a + * status indicating it is started. This allows the user to stop the + * device and reinitialize, but prevents a user from inadvertently + * initializing. + */ + if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { + return XST_DEVICE_IS_STARTED; + } + + /* + * Copy configuration into instance. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + + /* + * Save the base address pointer such that the registers of the block + * can be accessed and indicate it has not been started yet. + */ + InstancePtr->Config.BaseAddr = EffectiveAddress; + InstancePtr->IsStarted = 0; + + + /* Unlock the Device Configuration Interface */ + XDcfg_Unlock(InstancePtr); + + /* + * Indicate the instance is ready to use, successfully initialized. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* The functions enables the PCAP interface by setting the PCAP mode bit in the +* control register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return None. +* +* @note Enable FPGA programming from PCAP interface. Enabling this bit +* disables all the external interfaces from programming of FPGA +* except for ICAP. The user needs to ensure that the FPGA is +* programmed through either PCAP or ICAP. +* +*****************************************************************************/ +void XDcfg_EnablePCAP(XDcfg *InstancePtr) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg | XDCFG_CTRL_PCAP_MODE_MASK)); + +} + +/****************************************************************************/ +/** +* +* The functions disables the PCAP interface by clearing the PCAP mode bit in +* the control register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_DisablePCAP(XDcfg *InstancePtr) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg & ( ~XDCFG_CTRL_PCAP_MODE_MASK))); + +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the 32 bit mask data to be written to the Register. +* The mask definitions are defined in the xdevcfg_hw.h file. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetControlRegister(XDcfg *InstancePtr, u32 Mask) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg | Mask)); + +} + +/****************************************************************************/ +/** +* +* The function Clears the specified bit positions of the Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the 32 bit value which holds the bit positions to be cleared. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_ClearControlRegister(XDcfg *InstancePtr, u32 Mask) +{ + u32 CtrlReg; + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET, + (CtrlReg & ~Mask)); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Control +* Register. +* Use the XDCFG_CTRL_*_MASK constants defined in xdevcfg_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetControlRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Control Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Lock Register. These bits +* can only be set to a 1. They will be cleared after a Power On Reset. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetLockRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_LOCK_OFFSET, Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Lock Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Lock +* Register. +* Use the XDCFG_CR_*_MASK constants defined in xdevcfg_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetLockRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Lock Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_LOCK_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Configuration Register with the +* given value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetConfigRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CFG_OFFSET, Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Configuration Register with the +* given value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Config +* Register. +* Use the XDCFG_CFG_*_MASK constants defined in xdevcfg_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetConfigRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_CFG_OFFSET); + +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the Status Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_SetStatusRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET, Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Status Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Status +* Register. +* Use the XDCFG_STATUS_*_MASK constants defined in +* xdevcfg_hw.h to interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_GetStatusRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Status Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the contents of the ROM Shadow Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note This register is can only be written and is used to control the +* RAM shadow of 32 bit 4K page ROM pages in user mode +* +*****************************************************************************/ +void XDcfg_SetRomShadowRegister(XDcfg *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_ROM_SHADOW_OFFSET, + Data); + +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Software ID Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return 32 Bit boot software ID. +* +* @note This register is locked for write once the system enters +* usermode. Hence API for reading the register only is provided. +* +*****************************************************************************/ +u32 XDcfg_GetSoftwareIdRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Software ID Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_SW_ID_OFFSET); +} + +/****************************************************************************/ +/** +* +* The function sets the bit mask for the feature in Miscellaneous Control +* Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the feature to be set. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XDcfg_SetMiscControlRegister(XDcfg *InstancePtr, u32 Mask) +{ + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + RegData = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_MCTRL_OFFSET, + (RegData | Mask)); +} + +/****************************************************************************/ +/** +* +* The function reads the contents of the Miscellaneous Control Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return 32 Bit boot software ID. +* +* @note This register is locked for write once the system enters +* usermode. Hence API to reading the register only is provided. +* +*****************************************************************************/ +u32 XDcfg_GetMiscControlRegister(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Miscellaneous Control Register and return the value. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_MCTRL_OFFSET); +} + +/******************************************************************************/ +/** +* +* This function checks if DMA command queue is full. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return XST_SUCCESS is the DMA is busy +* XST_FAILURE if the DMA is idle +* +* @note The DMA queue has a depth of two. +* +****************************************************************************/ +u32 XDcfg_IsDmaBusy(XDcfg *InstancePtr) +{ + + u32 RegData; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the PCAP status register for DMA status */ + RegData = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_STATUS_OFFSET); + + if ((RegData & XDCFG_STATUS_DMA_CMD_Q_F_MASK) == + XDCFG_STATUS_DMA_CMD_Q_F_MASK){ + return XST_SUCCESS; + } + + return XST_FAILURE; +} + +/******************************************************************************/ +/** +* +* This function initiates the DMA transfer. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param SourcePtr contains a pointer to the source memory where the data +* is to be transferred from. +* @param SrcWordLength is the number of words (32 bit) to be transferred +* for the source transfer. +* @param DestPtr contains a pointer to the destination memory +* where the data is to be transferred to. +* @param DestWordLength is the number of words (32 bit) to be transferred +* for the Destination transfer. +* +* @return None. +* +* @note It is the responsibility of the caller function to ensure that +* correct values are passed to this function. +* +* The 2 LSBs of the SourcePtr (Source)/ DestPtr (Destination) +* address when equal to 2�b01 indicates the last DMA command of +* an overall transfer. +* +****************************************************************************/ +void XDcfg_InitiateDma(XDcfg *InstancePtr, u32 SourcePtr, u32 DestPtr, + u32 SrcWordLength, u32 DestWordLength) +{ + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_SRC_ADDR_OFFSET, + SourcePtr); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_DEST_ADDR_OFFSET, + DestPtr); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_SRC_LEN_OFFSET, + SrcWordLength); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_DMA_DEST_LEN_OFFSET, + DestWordLength); +} + +/******************************************************************************/ +/** +* +* This function Implements the DMA Read Command. This command is used to +* transfer the image data from FPGA to the external memory. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param SourcePtr contains a pointer to the source memory where the data +* is to be transferred from. +* @param SrcWordLength is the number of words (32 bit) to be transferred +* for the source transfer. +* @param DestPtr contains a pointer to the destination memory +* where the data is to be transferred to. +* @param DestWordLength is the number of words (32 bit) to be transferred +* for the Destination transfer. +* +* @return - XST_INVALID_PARAM if source address/length is invalid. +* - XST_SUCCESS if DMA transfer initiated properly. +* +* @note None. +* +****************************************************************************/ +static u32 XDcfg_PcapReadback(XDcfg *InstancePtr, u32 SourcePtr, + u32 SrcWordLength, u32 DestPtr, + u32 DestWordLength) +{ + u32 IntrReg; + + /* + * Send READ Frame command to FPGA + */ + XDcfg_InitiateDma(InstancePtr, SourcePtr, XDCFG_DMA_INVALID_ADDRESS, + SrcWordLength, 0); + + /* + * Store the enabled interrupts to enable before the actual read + * transfer is initiated and Disable all the interrupts temporarily. + */ + IntrReg = XDcfg_IntrGetEnabled(InstancePtr); + XDcfg_IntrDisable(InstancePtr, XDCFG_IXR_ALL_MASK); + + /* + * Wait till you get the DMA done for the read command sent + */ + while ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET) & + XDCFG_IXR_D_P_DONE_MASK) != + XDCFG_IXR_D_P_DONE_MASK); + /* + * Enable the previously stored Interrupts . + */ + XDcfg_IntrEnable(InstancePtr, IntrReg); + + /* + * Initiate the DMA write command. + */ + XDcfg_InitiateDma(InstancePtr, XDCFG_DMA_INVALID_ADDRESS, (u32)DestPtr, + 0, DestWordLength); + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** +* +* This function starts the DMA transfer. This function only starts the +* operation and returns before the operation may be completed. +* If the interrupt is enabled, an interrupt will be generated when the +* operation is completed, otherwise it is necessary to poll the Status register +* to determine when it is completed. It is the responsibility of the caller to +* determine when the operation is completed by handling the generated interrupt +* or polling the Status Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param SourcePtr contains a pointer to the source memory where the data +* is to be transferred from. +* @param SrcWordLength is the number of words (32 bit) to be transferred +* for the source transfer. +* @param DestPtr contains a pointer to the destination memory +* where the data is to be transferred to. +* @param DestWordLength is the number of words (32 bit) to be transferred +* for the Destination transfer. +* @param TransferType contains the type of PCAP transfer being requested. +* The definitions can be found in the xdevcfg.h file. +* @return +* - XST_SUCCESS.if DMA transfer initiated successfully +* - XST_DEVICE_BUSY if DMA is busy +* - XST_INVALID_PARAM if invalid Source / Destination address +* is sent or an invalid Source / Destination length is +* sent +* +* @note It is the responsibility of the caller to ensure that the cache +* is flushed and invalidated both before the DMA operation is +* started and after the DMA operation completes if the memory +* pointed to is cached. The caller must also ensure that the +* pointers contain physical address rather than a virtual address +* if address translation is being used. +* +* The 2 LSBs of the SourcePtr (Source)/ DestPtr (Destination) +* address when equal to 2�b01 indicates the last DMA command of +* an overall transfer. +* +*****************************************************************************/ +u32 XDcfg_Transfer(XDcfg *InstancePtr, + void *SourcePtr, u32 SrcWordLength, + void *DestPtr, u32 DestWordLength, + u32 TransferType) +{ + + u32 CtrlReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + if (XDcfg_IsDmaBusy(InstancePtr) == XST_SUCCESS) { + return XST_DEVICE_BUSY; + } + + /* + * Check whether the fabric is in initialized state + */ + if ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET) + & XDCFG_STATUS_PCFG_INIT_MASK) == 0) { + /* + * We don't need to check PCFG_INIT to be high for + * non-encrypted loopback transfers. + */ + if (TransferType != XDCFG_CONCURRENT_NONSEC_READ_WRITE) { + return XST_FAILURE; + } + } + + if ((TransferType == XDCFG_SECURE_PCAP_WRITE) || + (TransferType == XDCFG_NON_SECURE_PCAP_WRITE)) { + + /* Check for valid source pointer and length */ + if ((!SourcePtr) || (SrcWordLength == 0)) { + return XST_INVALID_PARAM; + } + + /* Clear internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg & + ~(XDCFG_MCTRL_PCAP_LPBK_MASK))); + + if (TransferType == XDCFG_NON_SECURE_PCAP_WRITE) { + /* + * Clear QUARTER_PCAP_RATE_EN bit + * so that the PCAP data is transmitted every clock + */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET, (CtrlReg & + ~XDCFG_CTRL_PCAP_RATE_EN_MASK)); + + } + if (TransferType == XDCFG_SECURE_PCAP_WRITE) { + /* + * AES engine handles only 8 bit data every clock cycle. + * Hence, Encrypted PCAP data which is 32 bit data can + * only be sent in every 4 clock cycles. Set the control + * register QUARTER_PCAP_RATE_EN bit to achieve this + * operation. + */ + XDcfg_SetControlRegister(InstancePtr, + XDCFG_CTRL_PCAP_RATE_EN_MASK); + } + + XDcfg_InitiateDma(InstancePtr, (u32)SourcePtr, + (u32)DestPtr, SrcWordLength, DestWordLength); + + } + + if (TransferType == XDCFG_PCAP_READBACK) { + + if ((!DestPtr) || (DestWordLength == 0)) { + + return XST_INVALID_PARAM; + } + + /* Clear internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg & + ~(XDCFG_MCTRL_PCAP_LPBK_MASK))); + + /* + * For PCAP readback of FPGA configuration register or memory, + * the read command is first sent (written) to the FPGA fabric + * which responds by returning the required read data. Read data + * from the FPGA is captured if pcap_radata_v is active.A DMA + * read transfer is required to obtain the readback command, + * which is then sent to the FPGA, followed by a DMA write + * transfer to support this mode of operation. + */ + return XDcfg_PcapReadback(InstancePtr, + (u32)SourcePtr, SrcWordLength, + (u32)DestPtr, DestWordLength); + } + + + if ((TransferType == XDCFG_CONCURRENT_SECURE_READ_WRITE) || + (TransferType == XDCFG_CONCURRENT_NONSEC_READ_WRITE)) { + + if ((!SourcePtr) || (SrcWordLength == 0) || + (!DestPtr) || (DestWordLength == 0)) { + return XST_INVALID_PARAM; + } + + if (TransferType == XDCFG_CONCURRENT_NONSEC_READ_WRITE) { + /* Enable internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg | + XDCFG_MCTRL_PCAP_LPBK_MASK)); + + /* + * Clear QUARTER_PCAP_RATE_EN bit + * so that the PCAP data is transmitted every clock + */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_CTRL_OFFSET, (CtrlReg & + ~XDCFG_CTRL_PCAP_RATE_EN_MASK)); + + } + if (TransferType == XDCFG_CONCURRENT_SECURE_READ_WRITE) { + /* Clear internal PCAP loopback */ + CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_MCTRL_OFFSET, (CtrlReg & + ~(XDCFG_MCTRL_PCAP_LPBK_MASK))); + + /* + * Set the QUARTER_PCAP_RATE_EN bit + * so that the PCAP data is transmitted every 4 clock + * cycles, this is required for encrypted data. + */ + XDcfg_SetControlRegister(InstancePtr, + XDCFG_CTRL_PCAP_RATE_EN_MASK); + } + + XDcfg_InitiateDma(InstancePtr, (u32)SourcePtr, + (u32)DestPtr, SrcWordLength, DestWordLength); + } + + return XST_SUCCESS; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg.h b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg.h new file mode 100644 index 0000000..e567699 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg.h @@ -0,0 +1,377 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdevcfg.h +* @addtogroup devcfg_v3_7 +* @{ +* @details +* +* The is the main header file for the Device Configuration Interface of the Zynq +* device. The device configuration interface has three main functionality. +* 1. AXI-PCAP +* 2. Security Policy +* 3. XADC +* This current version of the driver supports only the AXI-PCAP and Security +* Policy blocks. There is a separate driver for XADC. +* +* AXI-PCAP is used for download/upload an encrypted or decrypted bitstream. +* DMA embedded in the AXI PCAP provides the master interface to +* the Device configuration block for any DMA transfers. The data transfer can +* take place between the Tx/RxFIFOs of AXI-PCAP and memory (on chip +* RAM/DDR/peripheral memory). +* +* The current driver only supports the downloading the FPGA bitstream and +* readback of the decrypted image (sort of loopback). +* The driver does not know what information needs to be written to the FPGA to +* readback FPGA configuration register or memory data. The application above the +* driver should take care of creating the data that needs to be downloaded to +* the FPGA so that the bitstream can be readback. +* This driver also does not support the reading of the internal registers of the +* PCAP. The driver has no knowledge of the PCAP internals. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Device Configuration device. +* +* XDcfg_CfgInitialize() API is used to initialize the Device Configuration +* Interface. The user needs to first call the XDcfg_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XDcfg_CfgInitialize() API. +* +* Interrupts +* The Driver implements an interrupt handler to support the interrupts provided +* by this interface. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XDcfg driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +*

+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.00a nm  05/31/12 Updated the driver for CR 660835 so that input length for
+*		     source/destination to the XDcfg_InitiateDma, XDcfg_Transfer
+*		     APIs is words (32 bit) and not bytes.
+* 		     Updated the notes for XDcfg_InitiateDma/XDcfg_Transfer APIs
+*		     to add information that 2 LSBs of the Source/Destination
+*		     address when equal to 2�b01 indicate the last DMA command
+*		     of an overall transfer.
+*		     Destination Address passed to this API for secure transfers
+*		     instead of using 0xFFFFFFFF for CR 662197. This issue was
+*		     resulting in the failure of secure transfers of
+*		     non-bitstream images.
+* 2.01a nm  07/07/12 Updated the XDcfg_IntrClear function to directly
+*		     set the mask instead of oring it with the
+*		     value read from the interrupt status register
+* 		     Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg.
+*		     Added XDcfg_GetPsVersion, XDcfg_SelectIcapInterface
+*		     and XDcfg_SelectPcapInterface APIs for CR 643295
+*		     The user has to call the XDcfg_SelectIcapInterface API
+*		     for the PL reconfiguration using AXI HwIcap.
+*		     Updated the XDcfg_Transfer API to clear the
+*		     QUARTER_PCAP_RATE_EN bit in the control register for
+*		     non secure writes for CR 675543.
+* 2.02a nm  01/31/13 Fixed CR# 679335.
+* 		     Added Setting and Clearing the internal PCAP loopback.
+*		     Removed code for enabling/disabling AES engine as BootROM
+*		     locks down this setting.
+*		     Fixed CR# 681976.
+*		     Skip Checking the PCFG_INIT in case of non-secure DMA
+*		     loopback.
+*		     Fixed CR# 699558.
+*		     XDcfg_Transfer fails to transfer data in loopback mode.
+*		     Fixed CR# 701348.
+*                    Peripheral test fails with  Running
+* 		     DcfgSelfTestExample() in SECURE bootmode.
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 3.0   adk 10/12/13 Updated as per the New Tcl API's
+* 3.0   kpc 21/02/14 Added function prototype for XDcfg_ClearControlRegister
+* 3.2   sb  08/25/14 Fixed XDcfg_PcapReadback() function
+*		     updated driver code with != instead of ==,
+*		     while checking for Interrupt Status with DMA and
+*		     PCAP Done Mask
+*		     ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
+*			XDCFG_INT_STS_OFFSET) &
+*			XDCFG_IXR_D_P_DONE_MASK) !=
+*			XDCFG_IXR_D_P_DONE_MASK);
+*		     A new example has been added to read back the
+*		     configuration registers from the PL region.
+*		     xdevcfg_reg_readback_example.c
+* 3.3   sk  04/06/15 Modified XDcfg_ReadMultiBootConfig Macro CR# 851335.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/10/17 Modified filename tag in interrupt and polled examples
+*                    to include them in doxygen examples.
+* 3.5   ms  04/18/17 Modified tcl file to add suffix U for all macros
+*                    definitions of devcfg in xparameters.h
+*       ms  08/07/17 Fixed compilation warnings in xdevcfg_sinit.c
+* 
+* +******************************************************************************/ +#ifndef XDCFG_H /* prevent circular inclusions */ +#define XDCFG_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xdevcfg_hw.h" +#include "xstatus.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/* Types of PCAP transfers */ + +#define XDCFG_NON_SECURE_PCAP_WRITE 1 +#define XDCFG_SECURE_PCAP_WRITE 2 +#define XDCFG_PCAP_READBACK 3 +#define XDCFG_CONCURRENT_SECURE_READ_WRITE 4 +#define XDCFG_CONCURRENT_NONSEC_READ_WRITE 5 + + +/**************************** Type Definitions *******************************/ +/** +* The handler data type allows the user to define a callback function to +* respond to interrupt events in the system. This function is executed +* in interrupt context, so amount of processing should be minimized. +* +* @param CallBackRef is the callback reference passed in by the upper +* layer when setting the callback functions, and passed back to +* the upper layer when the callback is invoked. Its type is +* unimportant to the driver component, so it is a void pointer. +* @param Status is the Interrupt status of the XDcfg device. +*/ +typedef void (*XDcfg_IntrHandler) (void *CallBackRef, u32 Status); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XDcfg_Config; + +/** + * The XDcfg driver instance data. + */ +typedef struct { + XDcfg_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device Configuration Interface + * is running + */ + XDcfg_IntrHandler StatusHandler; /* Event handler function */ + void *CallBackRef; /* Callback reference for event handler */ +} XDcfg; + +/****************************************************************************/ +/** +* +* Unlock the Device Config Interface block. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_Unlock(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_Unlock(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_UNLOCK_OFFSET, XDCFG_UNLOCK_DATA) + + + +/****************************************************************************/ +/** +* +* Get the version number of the PS from the Miscellaneous Control Register. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return Version of the PS. +* +* @note C-style signature: +* void XDcfg_GetPsVersion(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_GetPsVersion(InstancePtr) \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MCTRL_OFFSET)) & \ + XDCFG_MCTRL_PCAP_PS_VERSION_MASK) >> \ + XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT + + + +/****************************************************************************/ +/** +* +* Read the multiboot config register value. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* u32 XDcfg_ReadMultiBootConfig(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_ReadMultiBootConfig(InstancePtr) \ + XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, \ + XDCFG_MULTIBOOT_ADDR_OFFSET) + + +/****************************************************************************/ +/** +* +* Selects ICAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectIcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectIcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + & ( ~XDCFG_CTRL_PCAP_PR_MASK))) + +/****************************************************************************/ +/** +* +* Selects PCAP interface for reconfiguration after the initial configuration +* of the PL. +* +* @param InstancePtr is a pointer to the instance of XDcfg driver. +* +* @return None. +* +* @note C-style signature: +* void XDcfg_SelectPcapInterface(XDcfg* InstancePtr) +* +*****************************************************************************/ +#define XDcfg_SelectPcapInterface(InstancePtr) \ + XDcfg_WriteReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET, \ + ((XDcfg_ReadReg((InstancePtr)->Config.BaseAddr, XDCFG_CTRL_OFFSET)) \ + | XDCFG_CTRL_PCAP_PR_MASK)) + + + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xdevcfg_sinit.c. + */ +XDcfg_Config *XDcfg_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xdevcfg_selftest.c + */ +int XDcfg_SelfTest(XDcfg *InstancePtr); + +/* + * Interface functions in xdevcfg.c + */ +int XDcfg_CfgInitialize(XDcfg *InstancePtr, + XDcfg_Config *ConfigPtr, u32 EffectiveAddress); + +void XDcfg_EnablePCAP(XDcfg *InstancePtr); + +void XDcfg_DisablePCAP(XDcfg *InstancePtr); + +void XDcfg_SetControlRegister(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_ClearControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetControlRegister(XDcfg *InstancePtr); + +void XDcfg_SetLockRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetLockRegister(XDcfg *InstancePtr); + +void XDcfg_SetConfigRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetConfigRegister(XDcfg *InstancePtr); + +void XDcfg_SetStatusRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetStatusRegister(XDcfg *InstancePtr); + +void XDcfg_SetRomShadowRegister(XDcfg *InstancePtr, u32 Data); + +u32 XDcfg_GetSoftwareIdRegister(XDcfg *InstancePtr); + +void XDcfg_SetMiscControlRegister(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_GetMiscControlRegister(XDcfg *InstancePtr); + +u32 XDcfg_IsDmaBusy(XDcfg *InstancePtr); + +void XDcfg_InitiateDma(XDcfg *InstancePtr, u32 SourcePtr, u32 DestPtr, + u32 SrcWordLength, u32 DestWordLength); + +u32 XDcfg_Transfer(XDcfg *InstancePtr, + void *SourcePtr, u32 SrcWordLength, + void *DestPtr, u32 DestWordLength, + u32 TransferType); + +/* + * Interrupt related function prototypes implemented in xdevcfg_intr.c + */ +void XDcfg_IntrEnable(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_IntrDisable(XDcfg *InstancePtr, u32 Mask); + +u32 XDcfg_IntrGetEnabled(XDcfg *InstancePtr); + +u32 XDcfg_IntrGetStatus(XDcfg *InstancePtr); + +void XDcfg_IntrClear(XDcfg *InstancePtr, u32 Mask); + +void XDcfg_InterruptHandler(XDcfg *InstancePtr); + +void XDcfg_SetHandler(XDcfg *InstancePtr, void *CallBackFunc, + void *CallBackRef); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_g.c new file mode 100644 index 0000000..28d1efd --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_g.c @@ -0,0 +1,52 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdevcfg_g.c +* @addtogroup devcfg_v3_7 +* @{ +* +* This file contains a table that specifies the configuration of the Device +* Configuration Interface device in the system. Each device should have an entry +* in the table. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Prototypes ******************************/ + +/** + * This table contains configuration information for each Device Config + * Interface instance in the system. + */ +XDcfg_Config XDcfg_ConfigTable[1] = { + { + XPAR_XDCFG_0_DEVICE_ID, + XPAR_XDCFG_0_BASEADDR, + } +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_hw.c b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_hw.c new file mode 100644 index 0000000..1feacd9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_hw.c @@ -0,0 +1,87 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdevcfg_hw.c +* @addtogroup devcfg_v3_7 +* @{ +* +* This file contains the implementation of the interface reset functionality +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 2.04a kpc 10/07/13 First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg_hw.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* This function perform the reset sequence to the given devcfg interface by +* configuring the appropriate control bits in the devcfg specifc registers +* the devcfg reset squence involves the following steps +* Disable all the interuupts +* Clear the status +* Update relevant config registers with reset values +* Disbale the looopback mode and pcap rate enable +* +* @param BaseAddress of the interface +* +* @return N/A +* +* @note +* This function will not modify the slcr registers that are relavant for +* devcfg controller +******************************************************************************/ +void XDcfg_ResetHw(u32 BaseAddr) +{ + u32 Regval = 0; + + /* Mask the interrupts */ + XDcfg_WriteReg(BaseAddr, XDCFG_INT_MASK_OFFSET, + XDCFG_IXR_ALL_MASK); + /* Clear the interuupt status */ + Regval = XDcfg_ReadReg(BaseAddr, XDCFG_INT_STS_OFFSET); + XDcfg_WriteReg(BaseAddr, XDCFG_INT_STS_OFFSET, Regval); + /* Clear the source address register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_SRC_ADDR_OFFSET, 0x0); + /* Clear the destination address register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_DEST_ADDR_OFFSET, 0x0); + /* Clear the source length register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_SRC_LEN_OFFSET, 0x0); + /* Clear the destination length register */ + XDcfg_WriteReg(BaseAddr, XDCFG_DMA_DEST_LEN_OFFSET, 0x0); + /* Clear the loopback enable bit */ + Regval = XDcfg_ReadReg(BaseAddr, XDCFG_MCTRL_OFFSET); + Regval = Regval & ~XDCFG_MCTRL_PCAP_LPBK_MASK; + XDcfg_WriteReg(BaseAddr, XDCFG_MCTRL_OFFSET, Regval); + /*Reset the configuration register to reset value */ + XDcfg_WriteReg(BaseAddr, XDCFG_CFG_OFFSET, + XDCFG_CONFIG_RESET_VALUE); + /*Disable the PCAP rate enable bit */ + Regval = XDcfg_ReadReg(BaseAddr, XDCFG_CTRL_OFFSET); + Regval = Regval & ~XDCFG_CTRL_PCAP_RATE_EN_MASK; + XDcfg_WriteReg(BaseAddr, XDCFG_CTRL_OFFSET, Regval); + +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_hw.h new file mode 100644 index 0000000..1b7d881 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_hw.h @@ -0,0 +1,369 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdevcfg_hw.h +* @addtogroup devcfg_v3_7 +* @{ +* +* This file contains the hardware interface to the Device Config Interface. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.01a nm  08/01/12 Added defines for the PS Version bits,
+*	             removed the FIFO Flush bits from the
+*		     Miscellaneous Control Reg
+* 2.03a nm  04/19/13 Fixed CR# 703728.
+*		     Updated the register definitions as per the latest TRM
+*		     version UG585 (v1.4) November 16, 2012.
+* 2.04a	kpc	10/07/13 Added function prototype.
+* 3.00a	kpc	25/02/14 Corrected the XDCFG_BASE_ADDRESS macro value.
+* 
+* +******************************************************************************/ +#ifndef XDCFG_HW_H /* prevent circular inclusions */ +#define XDCFG_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XDCFG_CTRL_OFFSET 0x00 /**< Control Register */ +#define XDCFG_LOCK_OFFSET 0x04 /**< Lock Register */ +#define XDCFG_CFG_OFFSET 0x08 /**< Configuration Register */ +#define XDCFG_INT_STS_OFFSET 0x0C /**< Interrupt Status Register */ +#define XDCFG_INT_MASK_OFFSET 0x10 /**< Interrupt Mask Register */ +#define XDCFG_STATUS_OFFSET 0x14 /**< Status Register */ +#define XDCFG_DMA_SRC_ADDR_OFFSET 0x18 /**< DMA Source Address Register */ +#define XDCFG_DMA_DEST_ADDR_OFFSET 0x1C /**< DMA Destination Address Reg */ +#define XDCFG_DMA_SRC_LEN_OFFSET 0x20 /**< DMA Source Transfer Length */ +#define XDCFG_DMA_DEST_LEN_OFFSET 0x24 /**< DMA Destination Transfer */ +#define XDCFG_ROM_SHADOW_OFFSET 0x28 /**< DMA ROM Shadow Register */ +#define XDCFG_MULTIBOOT_ADDR_OFFSET 0x2C /**< Multi BootAddress Pointer */ +#define XDCFG_SW_ID_OFFSET 0x30 /**< Software ID Register */ +#define XDCFG_UNLOCK_OFFSET 0x34 /**< Unlock Register */ +#define XDCFG_MCTRL_OFFSET 0x80 /**< Miscellaneous Control Reg */ + +/* @} */ + +/** @name Control Register Bit definitions + * @{ + */ + +#define XDCFG_CTRL_FORCE_RST_MASK 0x80000000 /**< Force into + * Secure Reset + */ +#define XDCFG_CTRL_PCFG_PROG_B_MASK 0x40000000 /**< Program signal to + * Reset FPGA + */ +#define XDCFG_CTRL_PCFG_POR_CNT_4K_MASK 0x20000000 /**< Control PL POR timer */ +#define XDCFG_CTRL_PCAP_PR_MASK 0x08000000 /**< Enable PCAP for PR */ +#define XDCFG_CTRL_PCAP_MODE_MASK 0x04000000 /**< Enable PCAP */ +#define XDCFG_CTRL_PCAP_RATE_EN_MASK 0x02000000 /**< Enable PCAP send data + * to FPGA every 4 PCAP + * cycles + */ +#define XDCFG_CTRL_MULTIBOOT_EN_MASK 0x01000000 /**< Multiboot Enable */ +#define XDCFG_CTRL_JTAG_CHAIN_DIS_MASK 0x00800000 /**< JTAG Chain Disable */ +#define XDCFG_CTRL_USER_MODE_MASK 0x00008000 /**< User Mode Mask */ +#define XDCFG_CTRL_PCFG_AES_FUSE_MASK 0x00001000 /**< AES key source */ +#define XDCFG_CTRL_PCFG_AES_EN_MASK 0x00000E00 /**< AES Enable Mask */ +#define XDCFG_CTRL_SEU_EN_MASK 0x00000100 /**< SEU Enable Mask */ +#define XDCFG_CTRL_SEC_EN_MASK 0x00000080 /**< Secure/Non Secure + * Status mask + */ +#define XDCFG_CTRL_SPNIDEN_MASK 0x00000040 /**< Secure Non Invasive + * Debug Enable + */ +#define XDCFG_CTRL_SPIDEN_MASK 0x00000020 /**< Secure Invasive + * Debug Enable + */ +#define XDCFG_CTRL_NIDEN_MASK 0x00000010 /**< Non-Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DBGEN_MASK 0x00000008 /**< Invasive Debug + * Enable + */ +#define XDCFG_CTRL_DAP_EN_MASK 0x00000007 /**< DAP Enable Mask */ + +/* @} */ + +/** @name Lock register bit definitions + * @{ + */ + +#define XDCFG_LOCK_AES_EFUSE_MASK 0x00000010 /**< Lock AES Efuse bit */ +#define XDCFG_LOCK_AES_EN_MASK 0x00000008 /**< Lock AES_EN update */ +#define XDCFG_LOCK_SEU_MASK 0x00000004 /**< Lock SEU_En update */ +#define XDCFG_LOCK_SEC_MASK 0x00000002 /**< Lock SEC_EN and + * USER_MODE + */ +#define XDCFG_LOCK_DBG_MASK 0x00000001 /**< This bit locks + * security config + * including: DAP_En, + * DBGEN,, + * NIDEN, SPNIEN + */ +/*@}*/ + + + +/** @name Config Register Bit definitions + * @{ + */ +#define XDCFG_CFG_RFIFO_TH_MASK 0x00000C00 /**< Read FIFO + * Threshold Mask + */ +#define XDCFG_CFG_WFIFO_TH_MASK 0x00000300 /**< Write FIFO Threshold + * Mask + */ +#define XDCFG_CFG_RCLK_EDGE_MASK 0x00000080 /**< Read data active + * clock edge + */ +#define XDCFG_CFG_WCLK_EDGE_MASK 0x00000040 /**< Write data active + * clock edge + */ +#define XDCFG_CFG_DISABLE_SRC_INC_MASK 0x00000020 /**< Disable Source address + * increment mask + */ +#define XDCFG_CFG_DISABLE_DST_INC_MASK 0x00000010 /**< Disable Destination + * address increment + * mask + */ +/* @} */ + + +/** @name Interrupt Status/Mask Register Bit definitions + * @{ + */ +#define XDCFG_IXR_PSS_GTS_USR_B_MASK 0x80000000 /**< Tri-state IO during + * HIZ + */ +#define XDCFG_IXR_PSS_FST_CFG_B_MASK 0x40000000 /**< First configuration + * done + */ +#define XDCFG_IXR_PSS_GPWRDWN_B_MASK 0x20000000 /**< Global power down */ +#define XDCFG_IXR_PSS_GTS_CFG_B_MASK 0x10000000 /**< Tri-state IO during + * configuration + */ +#define XDCFG_IXR_PSS_CFG_RESET_B_MASK 0x08000000 /**< PL configuration + * reset + */ +#define XDCFG_IXR_AXI_WTO_MASK 0x00800000 /**< AXI Write Address + * or Data or response + * timeout + */ +#define XDCFG_IXR_AXI_WERR_MASK 0x00400000 /**< AXI Write response + * error + */ +#define XDCFG_IXR_AXI_RTO_MASK 0x00200000 /**< AXI Read Address or + * response timeout + */ +#define XDCFG_IXR_AXI_RERR_MASK 0x00100000 /**< AXI Read response + * error + */ +#define XDCFG_IXR_RX_FIFO_OV_MASK 0x00040000 /**< Rx FIFO Overflow */ +#define XDCFG_IXR_WR_FIFO_LVL_MASK 0x00020000 /**< Tx FIFO less than + * threshold */ +#define XDCFG_IXR_RD_FIFO_LVL_MASK 0x00010000 /**< Rx FIFO greater than + * threshold */ +#define XDCFG_IXR_DMA_CMD_ERR_MASK 0x00008000 /**< Illegal DMA command */ +#define XDCFG_IXR_DMA_Q_OV_MASK 0x00004000 /**< DMA command queue + * overflow + */ +#define XDCFG_IXR_DMA_DONE_MASK 0x00002000 /**< DMA Command Done */ +#define XDCFG_IXR_D_P_DONE_MASK 0x00001000 /**< DMA and PCAP + * transfers Done + */ +#define XDCFG_IXR_P2D_LEN_ERR_MASK 0x00000800 /**< PCAP to DMA transfer + * length error + */ +#define XDCFG_IXR_PCFG_HMAC_ERR_MASK 0x00000040 /**< HMAC error mask */ +#define XDCFG_IXR_PCFG_SEU_ERR_MASK 0x00000020 /**< SEU Error mask */ +#define XDCFG_IXR_PCFG_POR_B_MASK 0x00000010 /**< FPGA POR mask */ +#define XDCFG_IXR_PCFG_CFG_RST_MASK 0x00000008 /**< FPGA Reset mask */ +#define XDCFG_IXR_PCFG_DONE_MASK 0x00000004 /**< Done Signal Mask */ +#define XDCFG_IXR_PCFG_INIT_PE_MASK 0x00000002 /**< Detect Positive edge + * of Init Signal + */ +#define XDCFG_IXR_PCFG_INIT_NE_MASK 0x00000001 /**< Detect Negative edge + * of Init Signal + */ +#define XDCFG_IXR_ERROR_FLAGS_MASK (XDCFG_IXR_AXI_WTO_MASK | \ + XDCFG_IXR_AXI_WERR_MASK | \ + XDCFG_IXR_AXI_RTO_MASK | \ + XDCFG_IXR_AXI_RERR_MASK | \ + XDCFG_IXR_RX_FIFO_OV_MASK | \ + XDCFG_IXR_DMA_CMD_ERR_MASK |\ + XDCFG_IXR_DMA_Q_OV_MASK | \ + XDCFG_IXR_P2D_LEN_ERR_MASK |\ + XDCFG_IXR_PCFG_HMAC_ERR_MASK) + + +#define XDCFG_IXR_ALL_MASK 0x00F7F8EF + + + +/* @} */ + + +/** @name Status Register Bit definitions + * @{ + */ +#define XDCFG_STATUS_DMA_CMD_Q_F_MASK 0x80000000 /**< DMA command + * Queue full + */ +#define XDCFG_STATUS_DMA_CMD_Q_E_MASK 0x40000000 /**< DMA command + * Queue empty + */ +#define XDCFG_STATUS_DMA_DONE_CNT_MASK 0x30000000 /**< Number of + * completed DMA + * transfers + */ +#define XDCFG_STATUS_RX_FIFO_LVL_MASK 0x01F000000 /**< Rx FIFO level */ +#define XDCFG_STATUS_TX_FIFO_LVL_MASK 0x0007F000 /**< Tx FIFO level */ + +#define XDCFG_STATUS_PSS_GTS_USR_B 0x00000800 /**< Tri-state IO + * during HIZ + */ +#define XDCFG_STATUS_PSS_FST_CFG_B 0x00000400 /**< First PL config + * done + */ +#define XDCFG_STATUS_PSS_GPWRDWN_B 0x00000200 /**< Global power down */ +#define XDCFG_STATUS_PSS_GTS_CFG_B 0x00000100 /**< Tri-state IO during + * config + */ +#define XDCFG_STATUS_SECURE_RST_MASK 0x00000080 /**< Secure Reset + * POR Status + */ +#define XDCFG_STATUS_ILLEGAL_APB_ACCESS_MASK 0x00000040 /**< Illegal APB + * access + */ +#define XDCFG_STATUS_PSS_CFG_RESET_B 0x00000020 /**< PL config + * reset status + */ +#define XDCFG_STATUS_PCFG_INIT_MASK 0x00000010 /**< FPGA Init + * Status + */ +#define XDCFG_STATUS_EFUSE_BBRAM_KEY_DISABLE_MASK 0x00000008 + /**< BBRAM key + * disable + */ +#define XDCFG_STATUS_EFUSE_SEC_EN_MASK 0x00000004 /**< Efuse Security + * Enable Status + */ +#define XDCFG_STATUS_EFUSE_JTAG_DIS_MASK 0x00000002 /**< EFuse JTAG + * Disable + * status + */ +/* @} */ + + +/** @name DMA Source/Destination Transfer Length Register Bit definitions + * @{ + */ +#define XDCFG_DMA_LEN_MASK 0x7FFFFFF /**< Length Mask */ +/*@}*/ + + + + +/** @name Miscellaneous Control Register Bit definitions + * @{ + */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_MASK 0xF0000000 /**< PS Version Mask */ +#define XDCFG_MCTRL_PCAP_PS_VERSION_SHIFT 28 /**< PS Version Shift */ +#define XDCFG_MCTRL_PCAP_LPBK_MASK 0x00000010 /**< PCAP loopback mask */ +/* @} */ + +/** @name FIFO Threshold Bit definitions + * @{ + */ + +#define XDCFG_CFG_FIFO_QUARTER 0x0 /**< Quarter empty */ +#define XDCFG_CFG_FIFO_HALF 0x1 /**< Half empty */ +#define XDCFG_CFG_FIFO_3QUARTER 0x2 /**< 3/4 empty */ +#define XDCFG_CFG_FIFO_EMPTY 0x4 /**< Empty */ +/* @}*/ + + +/* Miscellaneous constant values */ +#define XDCFG_DMA_INVALID_ADDRESS 0xFFFFFFFF /**< Invalid DMA address */ +#define XDCFG_UNLOCK_DATA 0x757BDF0D /**< First APB access data*/ +#define XDCFG_BASE_ADDRESS 0xF8007000 /**< Device Config base + * address + */ +#define XDCFG_CONFIG_RESET_VALUE 0x508 /**< Config reg reset value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XDcfg_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XDcfg_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XDcfg_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XDcfg_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ +/* + * Perform reset operation to the devcfg interface + */ +void XDcfg_ResetHw(u32 BaseAddr); +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_intr.c b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_intr.c new file mode 100644 index 0000000..9e7a741 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_intr.c @@ -0,0 +1,284 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdevcfg_intr.c +* @addtogroup devcfg_v3_7 +* @{ +* +* Contains the implementation of interrupt related functions of the XDcfg +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.01a nm  07/07/12 Updated the XDcfg_IntrClear function to directly
+*		     set the mask instead of oring it with the
+*		     value read from the interrupt status register
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* This function enables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the interrupts to be enabled. +* Bit positions of 1 will be enabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XDCFG_INT_* bits defined in xdevcfg_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_IntrEnable(XDcfg *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Enable the specified interrupts in the Interrupt Mask Register. + */ + RegValue = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET); + RegValue &= ~(Mask & XDCFG_IXR_ALL_MASK); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function disables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the interrupts to be disabled. +* Bit positions of 1 will be disabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XDCFG_INT_* bits defined in xdevcfg_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_IntrDisable(XDcfg *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable the specified interrupts in the Interrupt Mask Register. + */ + RegValue = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET); + RegValue |= (Mask & XDCFG_IXR_ALL_MASK); + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET, + RegValue); +} +/****************************************************************************/ +/** +* +* This function returns the enabled interrupts read from the Interrupt Mask +* Register. Use the XDCFG_INT_* constants defined in xdevcfg_hw.h +* to interpret the returned value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the IMR. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_IntrGetEnabled(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Mask Register. + */ + return (~ XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_MASK_OFFSET)); +} + +/****************************************************************************/ +/** +* +* This function returns the interrupt status read from Interrupt Status +* Register. Use the XDCFG_INT_* constants defined in xdevcfg_hw.h +* to interpret the returned value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return A 32-bit value representing the contents of the Interrupt +* Status register. +* +* @note None. +* +*****************************************************************************/ +u32 XDcfg_IntrGetStatus(XDcfg *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Status register. + */ + return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET); +} + +/****************************************************************************/ +/** +* +* This function clears the specified interrupts in the Interrupt Status +* Register. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* @param Mask is the bit-mask of the interrupts to be cleared. +* Bit positions of 1 will be cleared. Bit positions of 0 will not +* change the previous interrupt status. This mask is formed by +* OR'ing XDCFG_INT_* bits which are defined in xdevcfg_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XDcfg_IntrClear(XDcfg *InstancePtr, u32 Mask) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET, + Mask); + +} + +/*****************************************************************************/ +/** +* The interrupt handler for the Device Config Interface. +* +* Events are signaled to upper layer for proper handling. +* +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XDcfg_InterruptHandler(XDcfg *InstancePtr) +{ + u32 IntrStatusReg; + + /* + * Assert validates the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Interrupt status register. + */ + IntrStatusReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET); + + /* + * Write the status back to clear the interrupts so that no + * subsequent interrupts are missed while processing this interrupt. + * This also does the DMA acknowledgment automatically. + */ + XDcfg_WriteReg(InstancePtr->Config.BaseAddr, + XDCFG_INT_STS_OFFSET, IntrStatusReg); + + /* + * Signal application that there are events to handle. + */ + InstancePtr->StatusHandler(InstancePtr->CallBackRef, + IntrStatusReg); + +} + +/****************************************************************************/ +/** +* +* This function sets the handler that will be called when an event (interrupt) +* occurs that needs application's attention. +* +* @param InstancePtr is a pointer to the XDcfg instance +* @param CallBackFunc is the address of the callback function. +* @param CallBackRef is a user data item that will be passed to the +* callback function when it is invoked. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XDcfg_SetHandler(XDcfg *InstancePtr, void *CallBackFunc, + void *CallBackRef) +{ + /* + * Asserts validate the input arguments + * CallBackRef not checked, no way to know what is valid + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(CallBackFunc != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->StatusHandler = (XDcfg_IntrHandler) CallBackFunc; + InstancePtr->CallBackRef = CallBackRef; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_selftest.c b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_selftest.c new file mode 100644 index 0000000..f1fa391 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_selftest.c @@ -0,0 +1,88 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdevcfg_selftest.c +* @addtogroup devcfg_v3_7 +* @{ +* +* Contains diagnostic self-test functions for the XDcfg driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 2.02a nm  02/27/13 Fixed CR# 701348.
+*                    Peripheral test fails with  Running
+* 		     DcfgSelfTestExample() in SECURE bootmode.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Run a self-test on the Device Configuration Interface. This test does a +* control register write and reads back the same value. +* +* @param InstancePtr is a pointer to the XDcfg instance. +* +* @return +* - XST_SUCCESS if self-test was successful. +* - XST_FAILURE if fails. +* +* @note None. +* +******************************************************************************/ +int XDcfg_SelfTest(XDcfg *InstancePtr) +{ + u32 OldCfgReg; + u32 CfgReg; + int Status = XST_SUCCESS; + + /* + * Assert to ensure the inputs are valid and the instance has been + * initialized. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + OldCfgReg = XDcfg_GetControlRegister(InstancePtr); + + XDcfg_SetControlRegister(InstancePtr, XDCFG_CTRL_NIDEN_MASK); + + CfgReg = XDcfg_GetControlRegister(InstancePtr); + + if ((CfgReg & XDCFG_CTRL_NIDEN_MASK) != XDCFG_CTRL_NIDEN_MASK) { + + Status = XST_FAILURE; + } + + /* + * Restore the original values of the register + */ + XDcfg_SetControlRegister(InstancePtr, OldCfgReg); + + return Status; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_sinit.c new file mode 100644 index 0000000..b42d32b --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/devcfg/src/xdevcfg_sinit.c @@ -0,0 +1,68 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xdevcfg_sinit.c +* @addtogroup devcfg_v3_7 +* @{ +* +* This file contains method for static initialization (compile-time) of the +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a hvm 02/07/11 First release
+* 3.5   ms  08/07/17 Fixed compilation warnings.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdevcfg.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XDcfg_Config *XDcfg_LookupConfig(u16 DeviceId) +{ + extern XDcfg_Config XDcfg_ConfigTable[]; + XDcfg_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_XDCFG_NUM_INSTANCES; Index++) { + if (XDcfg_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XDcfg_ConfigTable[Index]; + break; + } + } + + return (CfgPtr); +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/Makefile new file mode 100644 index 0000000..be5fccb --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/Makefile @@ -0,0 +1,41 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +INCLUDEFILES:=*.h + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf $(DEPFILES) diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps.c b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps.c new file mode 100644 index 0000000..27dffb9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps.c @@ -0,0 +1,1961 @@ +/****************************************************************************** +* Copyright (C) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdmaps.c +* @addtogroup dmaps_v2_8 +* @{ +* +* This file contains the implementation of the interface functions for XDmaPs +* driver. Refer to the header file xdmaps.h for more detailed information. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	hbm    08/19/2010 First Release
+* 1.00  nm     05/25/2011 Updated for minor doxygen corrections
+* 1.02a sg     05/16/2012 Made changes for doxygen and moved some function
+*			  header from the xdmaps.h file to xdmaps.c file
+*			  Other cleanup for coding guidelines and CR 657109
+*			  and CR 657898
+* 1.03a sg     07/16/2012 changed inline to __inline for CR665681
+* 1.04a nm     10/22/2012 Fixed CR# 681671.
+* 1.05a nm     04/15/2013 Fixed CR# 704396. Removed warnings when compiled
+*			  with -Wall and -Wextra option in bsp.
+*	       05/01/2013 Fixed CR# 700189. Changed XDmaPs_BuildDmaProg()
+*			  function description.
+*			  Fixed CR# 704396. Removed unused variables
+*			  UseM2MByte & MemBurstLen from XDmaPs_BuildDmaProg()
+*			  function.
+* 1.07a asa    11/02/13. Made changes to fix compilation issues for iarcc.
+*			   Removed the PDBG prints. By default they were always
+*			   defined out and never used. The PDBG is non-standard for
+*			   Xilinx drivers and no other driver does something similar.
+*			   Since there is no easy way to fix compilation issues with
+*			   the IARCC compiler around PDBG, it is better to remove it.
+*			   Users can always use xil_printfs if they want to debug.
+* 2.01 kpc    08/23/14   Fixed the IAR compiler reported errors
+* 2.2  mus    12/08/16   Remove definition of INLINE macro to avoid re-definition,
+*                         since it is being defined in xil_io.h
+* 2.3 kpc     14/10/16   Fixed the compiler error when optimization O0 is used.
+* 2.5 hk      08/16/19   Add a memory barrier before DMASEV as per specification.
+* 2.6 hk      02/14/20   Correct boundary check for Channel.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include + +#include "xstatus.h" +#include "xdmaps.h" +#include "xil_io.h" +#include "xil_cache.h" + +#include "xil_printf.h" + + +/************************** Constant Definitions ****************************/ + +/* The following constant defines the amount of error that is allowed for + * a specified baud rate. This error is the difference between the actual + * baud rate that will be generated using the specified clock and the + * desired baud rate. + */ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ +static int XDmaPs_Exec_DMAKILL(u32 BaseAddr, + unsigned int Channel, + unsigned int Thread); + +static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf); + +static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg); + +static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel); +static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool); +static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd, + unsigned CacheLength); + +static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length); + + + +/************************** Variable Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Initializes a specific XDmaPs instance such that it is ready to be used. +* The data format of the device is setup for 8 data bits, 1 stop bit, and no +* parity by default. The baud rate is set to a default value specified by +* Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The +* receive FIFO threshold is set for 8 bytes. The default operating mode of the +* driver is polled mode. +* +* @param InstPtr is a pointer to the XDmaPs instance. +* @param Config is a reference to a structure containing information +* about a specific XDmaPs driver. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the +* address mapping from EffectiveAddr to the device physical base +* address unchanged once this function is invoked. Unexpected +* errors may occur if the address mapping changes after this +* function is called. If address translation is not used, pass in +* the physical address instead. +* +* @return +* +* - XST_SUCCESS on initialization completion +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_CfgInitialize(XDmaPs *InstPtr, + XDmaPs_Config *Config, + u32 EffectiveAddr) +{ + int Status = XST_SUCCESS; + unsigned int CacheLength = 0; + u32 CfgReg; + unsigned Channel; + XDmaPs_ChannelData *ChanData; + + /* + * Assert validates the input arguments + */ + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Config != NULL); + + /* + * Setup the driver instance using passed in parameters + */ + InstPtr->Config.DeviceId = Config->DeviceId; + InstPtr->Config.BaseAddress = EffectiveAddr; + + CfgReg = XDmaPs_ReadReg(EffectiveAddr, XDMAPS_CR1_OFFSET); + CacheLength = CfgReg & XDMAPS_CR1_I_CACHE_LEN_MASK; + if (CacheLength < 2 || CacheLength > 5) + CacheLength = 0; + else + CacheLength = 1 << CacheLength; + + InstPtr->CacheLength = CacheLength; + + memset(InstPtr->Chans, 0, + sizeof(XDmaPs_ChannelData[XDMAPS_CHANNELS_PER_DEV])); + + for (Channel = 0; Channel < XDMAPS_CHANNELS_PER_DEV; Channel++) { + ChanData = InstPtr->Chans + Channel; + ChanData->ChanId = Channel; + ChanData->DevId = Config->DeviceId; + } + + InstPtr->IsReady = 1; + + return Status; +} + +/****************************************************************************/ +/** +* +* Reset the DMA Manager. +* +* @param InstPtr is the DMA instance. +* +* @return 0 on success, -1 on time out +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ResetManager(XDmaPs *InstPtr) +{ + int Status; + Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress, + 0, 0); + + return Status; +} + +/****************************************************************************/ +/** +* +* Reset the specified DMA Channel. +* +* @param InstPtr is the DMA instance. +* @param Channel is the channel to be reset. +* +* @return 0 on success, -1 on time out +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel) +{ + int Status; + Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress, + Channel, 1); + + return Status; + +} + +/*****************************************************************************/ +/** +* +* Driver fault interrupt service routine +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_FaultISR(XDmaPs *InstPtr) +{ + + void *DmaProgBuf; + u32 Fsm; /* Fault status DMA manager register value */ + u32 Fsc; /* Fault status DMA channel register value */ + u32 FaultType; /* Fault type DMA manager register value */ + + u32 BaseAddr = InstPtr->Config.BaseAddress; + + u32 Pc; /* DMA Pc or channel Pc */ + XDmaPs_ChannelData *ChanData; + + unsigned Chan; + unsigned DevId; + + XDmaPs_Cmd *DmaCmd; + + Fsm = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSM_OFFSET) & 0x01; + Fsc = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSC_OFFSET) & 0xFF; + + + DevId = InstPtr->Config.DeviceId; + + if (Fsm) { + /* + * if DMA manager is fault + */ + FaultType = XDmaPs_ReadReg(BaseAddr, XDMAPS_FTM_OFFSET); + Pc = XDmaPs_ReadReg(BaseAddr, XDMAPS_DPC_OFFSET); + + xil_printf("PL330 device %d fault with type: %x at Pc %x\n", + DevId, + FaultType, Pc); + + /* kill the DMA manager thread */ + /* Should we disable interrupt?*/ + XDmaPs_Exec_DMAKILL(BaseAddr, 0, 0); + } + + /* + * check which channel faults and kill the channel thread + */ + for (Chan = 0; + Chan < XDMAPS_CHANNELS_PER_DEV; + Chan++) { + if (Fsc & (0x01 << Chan)) { + FaultType = + XDmaPs_ReadReg(BaseAddr, + XDmaPs_FTCn_OFFSET(Chan)); + Pc = XDmaPs_ReadReg(BaseAddr, + XDmaPs_CPCn_OFFSET(Chan)); + + /* kill the channel thread */ + /* Should we disable interrupt? */ + XDmaPs_Exec_DMAKILL(BaseAddr, Chan, 1); + + /* + * get the fault type and fault Pc and invoke the + * fault callback. + */ + ChanData = InstPtr->Chans + Chan; + + DmaCmd = ChanData->DmaCmdToHw; + + /* Should we check DmaCmd is not null */ + DmaCmd->DmaStatus = -1; + DmaCmd->ChanFaultType = FaultType; + DmaCmd->ChanFaultPCAddr = Pc; + ChanData->DmaCmdFromHw = DmaCmd; + ChanData->DmaCmdToHw = NULL; + + if (!ChanData->HoldDmaProg) { + DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg; + if (DmaProgBuf) + XDmaPs_BufPool_Free(ChanData->ProgBufPool, + DmaProgBuf); + DmaCmd->GeneratedDmaProg = NULL; + } + + if (InstPtr->FaultHandler) + InstPtr->FaultHandler(Chan, + DmaCmd, + InstPtr->FaultRef); + + } + } + +} + +/*****************************************************************************/ +/** +* +* Set the done handler for a channel. +* +* @param InstPtr is the DMA instance. +* @param Channel is the channel number. +* @param DoneHandler is the done interrupt handler. +* @param CallbackRef is the callback reference data. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int XDmaPs_SetDoneHandler(XDmaPs *InstPtr, + unsigned Channel, + XDmaPsDoneHandler DoneHandler, + void *CallbackRef) +{ + XDmaPs_ChannelData *ChanData; + + Xil_AssertNonvoid(InstPtr != NULL); + + if (Channel >= XDMAPS_CHANNELS_PER_DEV) + return XST_FAILURE; + + + ChanData = InstPtr->Chans + Channel; + + ChanData->DoneHandler = DoneHandler; + ChanData->DoneRef = CallbackRef; + + return 0; +} + +/*****************************************************************************/ +/** +* +* Set the fault handler for a channel. +* +* @param InstPtr is the DMA instance. +* @param FaultHandler is the fault interrupt handler. +* @param CallbackRef is the callback reference data. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int XDmaPs_SetFaultHandler(XDmaPs *InstPtr, + XDmaPsFaultHandler FaultHandler, + void *CallbackRef) +{ + Xil_AssertNonvoid(InstPtr != NULL); + + InstPtr->FaultHandler = FaultHandler; + InstPtr->FaultRef = CallbackRef; + + return XST_SUCCESS; +} + + + +/****************************************************************************/ +/** +* Construction function for DMAEND instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg the DMA program buffer, it's the starting address for +* the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAEND(char *DmaProg) +{ + /* + * DMAEND encoding: + * 7 6 5 4 3 2 1 0 + * 0 0 0 0 0 0 0 0 + */ + *DmaProg = 0x0; + + return 1; +} + +static INLINE void XDmaPs_Memcpy4(char *Dst, char *Src) +{ + *Dst = *Src; + *(Dst + 1) = *(Src + 1); + *(Dst + 2) = *(Src + 2); + *(Dst + 3) = *(Src + 3); +} + +/****************************************************************************/ +/** +* +* Construction function for DMAGO instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param Cn is the Channel number, 0 - 7 +* @param Imm is 32-bit immediate number written to the Channel Program +* Counter. +* @param Ns is Non-secure flag. If Ns is 1, the DMA channel operates in +* the Non-secure state. If Ns is 0, the execution depends on the +* security state of the DMA manager: +* DMA manager is in the Secure state, DMA channel operates in the +* Secure state. +* DMA manager is in the Non-secure state, DMAC aborts. +* +* @return The number of bytes for this instruction which is 6. +* +* @note None +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn, + u32 Imm, unsigned int Ns) +{ + /* + * DMAGO encoding: + * 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + * 0 0 0 0 0 |cn[2:0]| 1 0 1 0 0 0 ns 0 + * + * 47 ... 16 + * imm[32:0] + */ + *DmaProg = 0xA0 | ((Ns << 1) & 0x02); + + *(DmaProg + 1) = (u8)(Cn & 0x07); + + // *((u32 *)(DmaProg + 2)) = Imm; + XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm); + + /* success */ + return 6; +} + +/****************************************************************************/ +/** +* +* Construction function for DMALD instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg the DMA program buffer, it's the starting address for the +* instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMALD(char *DmaProg) +{ + /* + * DMALD encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 0 0 1 bs x + * + * Note: this driver doesn't support conditional load or store, + * so the bs bit is 0 and x bit is 0. + */ + *DmaProg = 0x04; + return 1; +} + +/****************************************************************************/ +/** +* +* Construction function for DMALP instruction. This function fills the program +* buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param Lc is the Loop counter register, can either be 0 or 1. +* @param LoopIterations: the number of interations, LoopInterations - 1 +* will be encoded in the DMALP instruction. +* +* @return The number of bytes for this instruction which is 2. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc, + unsigned LoopIterations) +{ + /* + * DMALP encoding + * 15 ... 8 7 6 5 4 3 2 1 0 + * | iter[7:0] |0 0 1 0 0 0 lc 0 + */ + *DmaProg = (u8)(0x20 | ((Lc & 1) << 1)); + *(DmaProg + 1) = (u8)(LoopIterations - 1); + return 2; +} + +/****************************************************************************/ +/** +* +* Construction function for DMALPEND instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param BodyStart is the starting address of the loop body. It is used +* to calculate the bytes of backward jump. +* @param Lc is the Loop counter register, can either be 0 or 1. +* +* @return The number of bytes for this instruction which is 2. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc) +{ + /* + * DMALPEND encoding + * 15 ... 8 7 6 5 4 3 2 1 0 + * | backward_jump[7:0] |0 0 1 nf 1 lc bs x + * + * lc: loop counter + * nf is for loop forever. The driver does not support loop forever, + * so nf is 1. + * The driver does not support conditional LPEND, so bs is 0, x is 0. + */ + *DmaProg = 0x38 | ((Lc & 1) << 2); + *(DmaProg + 1) = (u8)(DmaProg - BodyStart); + + return 2; +} + +/* + * Register number for the DMAMOV instruction + */ +#define XDMAPS_MOV_SAR 0x0 +#define XDMAPS_MOV_CCR 0x1 +#define XDMAPS_MOV_DAR 0x2 + +/****************************************************************************/ +/** +* +* Construction function for DMAMOV instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param Rd is the register id, 0 for SAR, 1 for CCR, and 2 for DAR +* @param Imm is the 32-bit immediate number +* +* @return The number of bytes for this instruction which is 6. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm) +{ + /* + * DMAMOV encoding + * 15 4 3 2 1 10 ... 8 7 6 5 4 3 2 1 0 + * 0 0 0 0 0 |rd[2:0]|1 0 1 1 1 1 0 0 + * + * 47 ... 16 + * imm[32:0] + * + * rd: b000 for SAR, b001 CCR, b010 DAR + */ + *DmaProg = 0xBC; + *(DmaProg + 1) = Rd & 0x7; + // *((u32 *)(DmaProg + 2)) = Imm; + XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm); + + return 6; +} + +/****************************************************************************/ +/** +* +* Construction function for DMANOP instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMANOP(char *DmaProg) +{ + /* + * DMANOP encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 1 1 0 0 0 + */ + *DmaProg = 0x18; + return 1; +} + +/****************************************************************************/ +/** +* +* Construction function for DMARMB instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_Instr_DMARMB(char *DmaProg) +{ + /* + * DMARMB encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 1 0 0 1 0 + */ + *DmaProg = 0x12; + return 1; +} + +/****************************************************************************/ +/** +* +* Construction function for DMASEV instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* @param EventNumber is the Event number to signal. +* +* @return The number of bytes for this instruction which is 2. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber) +{ + /* + * DMASEV encoding + * 15 4 3 2 1 10 9 8 7 6 5 4 3 2 1 0 + * |event[4:0]| 0 0 0 0 0 1 1 0 1 0 0 + */ + *DmaProg = 0x34; + *(DmaProg + 1) = (u8)(EventNumber << 3); + + return 2; +} + + +/****************************************************************************/ +/** +* +* Construction function for DMAST instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +static INLINE int XDmaPs_Instr_DMAST(char *DmaProg) +{ + /* + * DMAST encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 0 1 0 bs x + * + * Note: this driver doesn't support conditional load or store, + * so the bs bit is 0 and x bit is 0. + */ + *DmaProg = 0x08; + return 1; +} + + +/****************************************************************************/ +/** +* +* Construction function for DMAWMB instruction. This function fills the +* program buffer with the constructed instruction. +* +* @param DmaProg is the DMA program buffer, it's the starting address +* for the instruction being constructed +* +* @return The number of bytes for this instruction which is 1. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_Instr_DMAWMB(char *DmaProg) +{ + /* + * DMAWMB encoding + * 7 6 5 4 3 2 1 0 + * 0 0 0 1 0 0 1 0 + */ + *DmaProg = 0x13; + return 1; +} + +/****************************************************************************/ +/** +* +* Conversion function from the endian swap size to the bit encoding of the CCR +* +* @param EndianSwapSize is the endian swap size, in terms of bits, it +* could be 8, 16, 32, 64, or 128(We are using DMA assembly syntax) +* +* @return The endian swap size bit encoding for the CCR. +* +* @note None. +* +*****************************************************************************/ +static INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize) +{ + switch (EndianSwapSize) { + case 0: + case 8: + return 0; + case 16: + return 1; + case 32: + return 2; + case 64: + return 3; + case 128: + return 4; + default: + return 0; + } + +} + +/****************************************************************************/ +/** +* +* Conversion function from the burst size to the bit encoding of the CCR +* +* @param BurstSize is the burst size. It's the data width. +* In terms of bytes, it could be 1, 2, 4, 8, 16, 32, 64, or 128. +* It must be no larger than the bus width. +* (We are using DMA assembly syntax.) +* +* @note None. +* +*****************************************************************************/ +static INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize) +{ + switch (BurstSize) { + case 1: + return 0; + case 2: + return 1; + case 4: + return 2; + case 8: + return 3; + case 16: + return 4; + case 32: + return 5; + case 64: + return 6; + case 128: + return 7; + default: + return 0; + } +} + + +/****************************************************************************/ +/** +* +* Conversion function from PL330 bus transfer descriptors to CCR value. All the +* values passed to the functions are in terms of assembly languages, not in +* terms of the register bit encoding. +* +* @param ChanCtrl is the Instance of XDmaPs_ChanCtrl. +* +* @return The 32-bit CCR value. +* +* @note None. +* +*****************************************************************************/ +u32 XDmaPs_ToCCRValue(XDmaPs_ChanCtrl *ChanCtrl) +{ + /* + * Channel Control Register encoding + * [31:28] - endian_swap_size + * [27:25] - dst_cache_ctrl + * [24:22] - dst_prot_ctrl + * [21:18] - dst_burst_len + * [17:15] - dst_burst_size + * [14] - dst_inc + * [13:11] - src_cache_ctrl + * [10:8] - src_prot_ctrl + * [7:4] - src_burst_len + * [3:1] - src_burst_size + * [0] - src_inc + */ + + unsigned es = + XDmaPs_ToEndianSwapSizeBits(ChanCtrl->EndianSwapSize); + + unsigned dst_burst_size = + XDmaPs_ToBurstSizeBits(ChanCtrl->DstBurstSize); + unsigned dst_burst_len = (ChanCtrl->DstBurstLen - 1) & 0x0F; + unsigned dst_cache_ctrl = (ChanCtrl->DstCacheCtrl & 0x03) + | ((ChanCtrl->DstCacheCtrl & 0x08) >> 1); + unsigned dst_prot_ctrl = ChanCtrl->DstProtCtrl & 0x07; + unsigned dst_inc_bit = ChanCtrl->DstInc & 1; + + unsigned src_burst_size = + XDmaPs_ToBurstSizeBits(ChanCtrl->SrcBurstSize); + unsigned src_burst_len = (ChanCtrl->SrcBurstLen - 1) & 0x0F; + unsigned src_cache_ctrl = (ChanCtrl->SrcCacheCtrl & 0x03) + | ((ChanCtrl->SrcCacheCtrl & 0x08) >> 1); + unsigned src_prot_ctrl = ChanCtrl->SrcProtCtrl & 0x07; + unsigned src_inc_bit = ChanCtrl->SrcInc & 1; + + u32 ccr_value = (es << 28) + | (dst_cache_ctrl << 25) + | (dst_prot_ctrl << 22) + | (dst_burst_len << 18) + | (dst_burst_size << 15) + | (dst_inc_bit << 14) + | (src_cache_ctrl << 11) + | (src_prot_ctrl << 8) + | (src_burst_len << 4) + | (src_burst_size << 1) + | (src_inc_bit); + + return ccr_value; +} + +/****************************************************************************/ +/** +* Construct a loop with only DMALD and DMAST as the body using loop counter 0. +* The function also makes sure the loop body and the lpend is in the same +* cache line. +* +* @param DmaProgStart is the very start address of the DMA program. +* This is used to calculate whether the loop is in a cache line. +* @param CacheLength is the icache line length, in terms of bytes. +* If it's zero, the performance enhancement feature will be +* turned off. +* @param DmaProgLoopStart The starting address of the loop (DMALP). +* @param LoopCount The inner loop count. Loop count - 1 will be used to +* initialize the loop counter. +* +* @return The number of bytes the loop has. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ConstructSingleLoop(char *DmaProgStart, + int CacheLength, + char *DmaProgLoopStart, + int LoopCount) +{ + int CacheStartOffset; + int CacheEndOffset; + int NumNops; + char *DmaProgBuf = DmaProgLoopStart; + + DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCount); + + if (CacheLength > 0) { + /* + * the CacheLength > 0 switch is ued to turn on/off nop + * insertion + */ + CacheStartOffset = DmaProgBuf - DmaProgStart; + CacheEndOffset = CacheStartOffset + 3; + + /* + * check whether the body and lpend fit in one cache line + */ + if (CacheStartOffset / CacheLength + != CacheEndOffset / CacheLength) { + /* insert the nops */ + NumNops = CacheLength + - CacheStartOffset % CacheLength; + while (NumNops--) { + DmaProgBuf += + XDmaPs_Instr_DMANOP(DmaProgBuf); + } + } + } + + DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf, + DmaProgBuf - 2, 0); + + return DmaProgBuf - DmaProgLoopStart; +} + +/****************************************************************************/ +/** +* Construct a nested loop with only DMALD and DMAST in the inner loop body. +* It uses loop counter 1 for the outer loop and loop counter 0 for the +* inner loop. +* +* @param DmaProgStart is the very start address of the DMA program. +* This is used to calculate whether the loop is in a cache line. +* @param CacheLength is the icache line length, in terms of bytes. +* If it's zero, the performance enhancement feature will be +* turned off. +* @param DmaProgLoopStart The starting address of the loop (DMALP). +* @param LoopCountOuter The outer loop count. Loop count - 1 will be +* used to initialize the loop counter. +* @param LoopCountInner The inner loop count. Loop count - 1 will be +* used to initialize the loop counter. +* +* @return The number byes the nested loop program has. +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_ConstructNestedLoop(char *DmaProgStart, + int CacheLength, + char *DmaProgLoopStart, + unsigned int LoopCountOuter, + unsigned int LoopCountInner) +{ + int CacheStartOffset; + int CacheEndOffset; + int NumNops; + char *InnerLoopStart; + char *DmaProgBuf = DmaProgLoopStart; + + DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 1, LoopCountOuter); + InnerLoopStart = DmaProgBuf; + + if (CacheLength > 0) { + /* + * the CacheLength > 0 switch is ued to turn on/off nop + * insertion + */ + if (CacheLength < 8) { + /* + * if the cache line is too small to fit both loops + * just align the inner loop + */ + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + LoopCountInner); + /* outer loop end */ + DmaProgBuf += + XDmaPs_Instr_DMALPEND(DmaProgBuf, + InnerLoopStart, + 1); + + /* + * the nested loop is constructed for + * smaller cache line + */ + return DmaProgBuf - DmaProgLoopStart; + } + + /* + * Now let's handle the case where a cache line can + * fit the nested loops. + */ + CacheStartOffset = DmaProgBuf - DmaProgStart; + CacheEndOffset = CacheStartOffset + 7; + + /* + * check whether the body and lpend fit in one cache line + */ + if (CacheStartOffset / CacheLength + != CacheEndOffset / CacheLength) { + /* insert the nops */ + NumNops = CacheLength + - CacheStartOffset % CacheLength; + while (NumNops--) { + DmaProgBuf += + XDmaPs_Instr_DMANOP(DmaProgBuf); + } + } + } + + /* insert the inner DMALP */ + DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCountInner); + + /* DMALD and DMAST instructions */ + DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf); + + /* inner DMALPEND */ + DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf, + DmaProgBuf - 2, 0); + /* outer DMALPEND */ + DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf, + InnerLoopStart, 1); + + /* return the number of bytes */ + return DmaProgBuf - DmaProgLoopStart; +} + +/* + * [31:28] endian_swap_size b0000 + * [27:25] dst_cache_ctrl b000 + * [24:22] dst_prot_ctrl b000 + * [21:18] dst_burst_len b0000 + * [17:15] dst_burst_size b000 + * [14] dst_inc b0 + * [27:25] src_cache_ctrl b000 + * [24:22] src_prot_ctrl b000 + * [21:18] src_burst_len b0000 + * [17:15] src_burst_size b000 + * [14] src_inc b0 + */ +#define XDMAPS_CCR_SINGLE_BYTE (0x0) +#define XDMAPS_CCR_M2M_SINGLE_BYTE ((0x1 << 14) | 0x1) + + +/****************************************************************************/ +/** +* +* Construct the DMA program based on the descriptions of the DMA transfer. +* The function handles memory to memory DMA transfers. +* It also handles unalgined head and small amount of residue tail. +* +* @param Channel DMA channel number +* @param Cmd is the DMA command. +* @param CacheLength is the icache line length, in terms of bytes. +* If it's zero, the performance enhancement feature will be +* turned off. +* +* @returns The number of bytes for the program. +* +* @note None. +* +*****************************************************************************/ +static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd, + unsigned CacheLength) +{ + /* + * unpack arguments + */ + char *DmaProgBuf = (char *)Cmd->GeneratedDmaProg; + unsigned DevChan = Channel; + unsigned long DmaLength = Cmd->BD.Length; + u32 SrcAddr = Cmd->BD.SrcAddr; + + unsigned SrcInc = Cmd->ChanCtrl.SrcInc; + u32 DstAddr = Cmd->BD.DstAddr; + unsigned DstInc = Cmd->ChanCtrl.DstInc; + + char *DmaProgStart = DmaProgBuf; + + unsigned int BurstBytes; + unsigned int LoopCount; + unsigned int LoopCount1 = 0; + unsigned int LoopResidue = 0; + unsigned int TailBytes; + unsigned int TailWords; + int DmaProgBytes; + u32 CCRValue; + unsigned int Unaligned; + unsigned int UnalignedCount; + unsigned int MemBurstSize = 1; + u32 MemAddr = 0; + unsigned int Index; + unsigned int SrcUnaligned = 0; + unsigned int DstUnaligned = 0; + + XDmaPs_ChanCtrl *ChanCtrl; + XDmaPs_ChanCtrl WordChanCtrl; + static XDmaPs_ChanCtrl Mem2MemByteCC; + + Mem2MemByteCC.EndianSwapSize = 0; + Mem2MemByteCC.DstCacheCtrl = 0; + Mem2MemByteCC.DstProtCtrl = 0; + Mem2MemByteCC.DstBurstLen = 1; + Mem2MemByteCC.DstBurstSize = 1; + Mem2MemByteCC.DstInc = 1; + Mem2MemByteCC.SrcCacheCtrl = 0; + Mem2MemByteCC.SrcProtCtrl = 0; + Mem2MemByteCC.SrcBurstLen = 1; + Mem2MemByteCC.SrcBurstSize = 1; + Mem2MemByteCC.SrcInc = 1; + + ChanCtrl = &Cmd->ChanCtrl; + + /* insert DMAMOV for SAR and DAR */ + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_SAR, + SrcAddr); + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_DAR, + DstAddr); + + + if (ChanCtrl->SrcInc) + SrcUnaligned = SrcAddr % ChanCtrl->SrcBurstSize; + + if (ChanCtrl->DstInc) + DstUnaligned = DstAddr % ChanCtrl->DstBurstSize; + + if ((SrcUnaligned && DstInc) || (DstUnaligned && SrcInc)) { + ChanCtrl = &Mem2MemByteCC; + } + + if (ChanCtrl->SrcInc) { + MemBurstSize = ChanCtrl->SrcBurstSize; + MemAddr = SrcAddr; + + } else if (ChanCtrl->DstInc) { + MemBurstSize = ChanCtrl->DstBurstSize; + MemAddr = DstAddr; + } + + /* check whether the head is aligned or not */ + Unaligned = MemAddr % MemBurstSize; + + if (Unaligned) { + /* if head is unaligned, transfer head in bytes */ + UnalignedCount = MemBurstSize - Unaligned; + CCRValue = XDMAPS_CCR_SINGLE_BYTE + | (SrcInc & 1) + | ((DstInc & 1) << 14); + + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + + for (Index = 0; Index < UnalignedCount; Index++) { + DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf); + } + + DmaLength -= UnalignedCount; + } + + /* now the burst transfer part */ + CCRValue = XDmaPs_ToCCRValue(ChanCtrl); + DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + + BurstBytes = ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen; + + LoopCount = DmaLength / BurstBytes; + TailBytes = DmaLength % BurstBytes; + + /* + * the loop count register is 8-bit wide, so if we need + * a larger loop, we need to have nested loops + */ + if (LoopCount > 256) { + LoopCount1 = LoopCount / 256; + if (LoopCount1 > 256) { + xil_printf("DMA operation cannot fit in a 2-level " + "loop for channel %d, please reduce the " + "DMA length or increase the burst size or " + "length", + Channel); + return 0; + } + LoopResidue = LoopCount % 256; + + if (LoopCount1 > 1) + DmaProgBuf += + XDmaPs_ConstructNestedLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + LoopCount1, + 256); + else + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + 256); + + /* there will be some that cannot be covered by + * nested loops + */ + LoopCount = LoopResidue; + } + + if (LoopCount > 0) { + DmaProgBuf += XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + LoopCount); + } + + if (TailBytes) { + /* handle the tail */ + TailWords = TailBytes / MemBurstSize; + TailBytes = TailBytes % MemBurstSize; + + if (TailWords) { + WordChanCtrl = *ChanCtrl; + /* + * if we can transfer the tail in words, we will + * transfer words as much as possible + */ + WordChanCtrl.SrcBurstSize = MemBurstSize; + WordChanCtrl.SrcBurstLen = 1; + WordChanCtrl.DstBurstSize = MemBurstSize; + WordChanCtrl.DstBurstLen = 1; + + + /* + * the burst length is 1 + */ + CCRValue = XDmaPs_ToCCRValue(&WordChanCtrl); + + DmaProgBuf += + XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + TailWords); + + } + + if (TailBytes) { + /* + * for the rest, we'll tranfer in bytes + */ + /* + * So far just to be safe, the tail bytes + * are transfered in a loop. We can optimize a little + * to perform a burst. + */ + CCRValue = XDMAPS_CCR_SINGLE_BYTE + | (SrcInc & 1) + | ((DstInc & 1) << 14); + + DmaProgBuf += + XDmaPs_Instr_DMAMOV(DmaProgBuf, + XDMAPS_MOV_CCR, + CCRValue); + + DmaProgBuf += + XDmaPs_ConstructSingleLoop(DmaProgStart, + CacheLength, + DmaProgBuf, + TailBytes); + + } + } + + /* Add a memory barrier before DMASSEV as recommended by spec */ + DmaProgBuf += XDmaPs_Instr_DMAWMB(DmaProgBuf); + DmaProgBuf += XDmaPs_Instr_DMASEV(DmaProgBuf, DevChan); + DmaProgBuf += XDmaPs_Instr_DMAEND(DmaProgBuf); + + DmaProgBytes = DmaProgBuf - DmaProgStart; + + Xil_DCacheFlushRange((u32)DmaProgStart, DmaProgBytes); + + return DmaProgBytes; + +} + + +/****************************************************************************/ +/** +* +* Generate a DMA program based for the DMA command, the buffer will be pointed +* by the GeneratedDmaProg field of the command. +* +* @param InstPtr is then DMA instance. +* @param Channel is the DMA channel number. +* @param Cmd is the DMA command. +* +* @return - XST_SUCCESS on success. +* - XST_FAILURE if it fails +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd) +{ + void *Buf; + int ProgLen; + XDmaPs_ChannelData *ChanData; + XDmaPs_ChanCtrl *ChanCtrl; + + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Cmd != NULL); + + + if (Channel > XDMAPS_CHANNELS_PER_DEV) + return XST_FAILURE; + + ChanData = InstPtr->Chans + Channel; + ChanCtrl = &Cmd->ChanCtrl; + + if (ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen + != ChanCtrl->DstBurstSize * ChanCtrl->DstBurstLen) { + return XST_FAILURE; + } + + + /* + * unaligned fixed address is not supported + */ + if (!ChanCtrl->SrcInc && Cmd->BD.SrcAddr % ChanCtrl->SrcBurstSize) { + return XST_FAILURE; + } + + if (!ChanCtrl->DstInc && Cmd->BD.DstAddr % ChanCtrl->DstBurstSize) { + return XST_FAILURE; + } + + Buf = XDmaPs_BufPool_Allocate(ChanData->ProgBufPool); + if (Buf == NULL) { + return XST_FAILURE; + } + + Cmd->GeneratedDmaProg = Buf; + ProgLen = XDmaPs_BuildDmaProg(Channel, Cmd, + InstPtr->CacheLength); + Cmd->GeneratedDmaProgLength = ProgLen; + + +#ifdef XDMAPS_DEBUG + XDmaPs_Print_DmaProg(Cmd); +#endif + + if (ProgLen <= 0) { + /* something wrong, release the buffer */ + XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf); + Cmd->GeneratedDmaProgLength = 0; + Cmd->GeneratedDmaProg = NULL; + return XST_FAILURE; + } + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** + * Free the DMA program buffer that is pointed by the GeneratedDmaProg field + * of the command. + * + * @param InstPtr is then DMA instance. + * @param Channel is the DMA channel number. + * @param Cmd is the DMA command. + * + * @return XST_SUCCESS on success. + * XST_FAILURE if there is any error. + * + * @note None. + * + ****************************************************************************/ +int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd) +{ + + void *Buf; + XDmaPs_ChannelData *ChanData; + + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Cmd != NULL); + + if (Channel > XDMAPS_CHANNELS_PER_DEV) + return XST_FAILURE; + + Buf = (void *)Cmd->GeneratedDmaProg; + ChanData = InstPtr->Chans + Channel; + + if (Buf) { + XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf); + Cmd->GeneratedDmaProg = 0; + Cmd->GeneratedDmaProgLength = 0; + } + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** +* +* Start a DMA command. The command can only be invoked when the channel +* is idle. The driver takes the command, generates DMA program if needed, +* then pass the program to DMAC to execute. +* +* @param InstPtr is then DMA instance. +* @param Channel is the DMA channel number. +* @param Cmd is the DMA command. +* @param HoldDmaProg is tag indicating whether the driver can release +* the allocated DMA buffer or not. If a user wants to examine the +* generated DMA program, the flag should be set to 1. After the +* DMA program is finished, a user needs to explicity free the +* buffer. +* +* @return +* - XST_SUCCESS on success +* - XST_DEVICE_BUSY if DMA is busy +* - XST_FAILURE on other failures +* +* @note None. +* +****************************************************************************/ +int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd, + int HoldDmaProg) +{ + int Status; + u32 DmaProg = 0; + u32 Inten; + + Xil_AssertNonvoid(InstPtr != NULL); + Xil_AssertNonvoid(Cmd != NULL); + + + Cmd->DmaStatus = XST_FAILURE; + + if (XDmaPs_IsActive(InstPtr, Channel)) + return XST_DEVICE_BUSY; + + if (!Cmd->UserDmaProg && !Cmd->GeneratedDmaProg) { + Status = XDmaPs_GenDmaProg(InstPtr, Channel, Cmd); + if (Status) + return XST_FAILURE; + } + + InstPtr->Chans[Channel].HoldDmaProg = HoldDmaProg; + + if (Cmd->UserDmaProg) + DmaProg = (u32)Cmd->UserDmaProg; + else if (Cmd->GeneratedDmaProg) + DmaProg = (u32)Cmd->GeneratedDmaProg; + + if (DmaProg) { + /* enable the interrupt */ + Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTEN_OFFSET); + Inten |= 0x01 << Channel; /* set the correpsonding bit */ + XDmaPs_WriteReg(InstPtr->Config.BaseAddress, + XDMAPS_INTEN_OFFSET, + Inten); + Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTEN_OFFSET); + + InstPtr->Chans[Channel].DmaCmdToHw = Cmd; + + if (Cmd->ChanCtrl.SrcInc) { + Xil_DCacheFlushRange(Cmd->BD.SrcAddr, Cmd->BD.Length); + } + if (Cmd->ChanCtrl.DstInc) { + Xil_DCacheInvalidateRange(Cmd->BD.DstAddr, + Cmd->BD.Length); + } + + Status = XDmaPs_Exec_DMAGO(InstPtr->Config.BaseAddress, + Channel, DmaProg); + } + else { + InstPtr->Chans[Channel].DmaCmdToHw = NULL; + Status = XST_FAILURE; + } + + return Status; +} + +/****************************************************************************/ +/** +* +* Checks whether the DMA channel is active or idle. +* +* @param InstPtr is the DMA instance. +* @param Channel is the DMA channel number. +* +* @return 0: if the channel is idle +* 1: otherwise +* +* @note None. +* +*****************************************************************************/ +int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel) +{ + Xil_AssertNonvoid(InstPtr != NULL); + + /* Need to assert Channel is in range */ + if (Channel >= XDMAPS_CHANNELS_PER_DEV) + return XST_FAILURE; + + return InstPtr->Chans[Channel].DmaCmdToHw != NULL; +} + + + +/****************************************************************************/ +/** +* +* Allocate a buffer of the DMA program buffer from the pool. +* +* @param Pool the DMA program pool. +* +* @return The allocated buffer, NULL if there is any error. +* +* @note None. +* +*****************************************************************************/ +static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool) +{ + int Index; + + Xil_AssertNonvoid(Pool != NULL); + + for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) { + if (!Pool[Index].Allocated) { + Pool[Index].Allocated = 1; + return Pool[Index].Buf; + } + } + + return NULL; + +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 0. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_0(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 0); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 1. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_1(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 1); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 2. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_2(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 2); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 3. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_3(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 3); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 4. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_4(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 4); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 5. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_5(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 5); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 6. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_6(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 6); +} + +/*****************************************************************************/ +/** +* +* Driver done interrupt service routine for channel 7. We need this done ISR +* mainly because the driver needs to release the DMA program buffer. +* This is the one that connects the GIC +* +* @param InstPtr is the DMA instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XDmaPs_DoneISR_7(XDmaPs *InstPtr) +{ + XDmaPs_DoneISR_n(InstPtr, 7); +} + +#ifndef XDMAPS_MAX_WAIT +#define XDMAPS_MAX_WAIT 4000 +#endif + +/****************************************************************************/ +/** +* Use the debug registers to kill the DMA thread. +* +* @param BaseAddr is DMA device base address. +* @param Channel is the DMA channel number. +* @param Thread is Debug thread encoding. +* 0: DMA manager thread, 1: DMA channel. +* +* @return 0 on success, -1 on time out +* +* @note None. +* +*****************************************************************************/ +static int XDmaPs_Exec_DMAKILL(u32 BaseAddr, + unsigned int Channel, + unsigned int Thread) +{ + u32 DbgInst0; + int WaitCount; + + DbgInst0 = XDmaPs_DBGINST0(0, 0x01, Channel, Thread); + + /* wait while debug status is busy */ + WaitCount = 0; + while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + && (WaitCount < XDMAPS_MAX_WAIT)) + WaitCount++; + + if (WaitCount >= XDMAPS_MAX_WAIT) { + /* wait time out */ + xil_printf("PL330 device at %x debug status busy time out\n", + BaseAddr); + + return -1; + } + + /* write debug instruction 0 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0); + + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, 0); + + + /* run the command in DbgInst0 and DbgInst1 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0); + + return 0; +} + +/****************************************************************************/ +/** +* +* +* Free a buffer of the DMA program buffer. +* @param Pool the DMA program pool. +* @param Buf the DMA program buffer to be release. +* +* @return None +* +* @note None. +* +*****************************************************************************/ +static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf) +{ + int Index; + Xil_AssertVoid(Pool != NULL); + + for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) { + if (Pool[Index].Buf == Buf) { + if (Pool[Index].Allocated) { + Pool[Index].Allocated = 0; + } + } + } +} + +/*****************************************************************************/ +/** +* XDmaPs_Exec_DMAGO - Execute the DMAGO to start a channel. +* +* @param BaseAddr PL330 device base address +* @param Channel Channel number for the device +* @param DmaProg DMA program starting address, this should be DMA address +* +* @return 0 on success, -1 on time out +* +* @note None. +* +****************************************************************************/ +static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg) +{ + char DmaGoProg[8]; + u32 DbgInst0; + u32 DbgInst1; + + int WaitCount; + + XDmaPs_Instr_DMAGO(DmaGoProg, Channel, DmaProg, 0); + + DbgInst0 = XDmaPs_DBGINST0(*(DmaGoProg + 1), *DmaGoProg, 0, 0); + DbgInst1 = (u32)DmaProg; + + /* wait while debug status is busy */ + WaitCount = 0; + while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + && (WaitCount < XDMAPS_MAX_WAIT)) { + + WaitCount++; + } + + if (WaitCount >= XDMAPS_MAX_WAIT) { + xil_printf("PL330 device at %x debug status busy time out\r\n", + BaseAddr); + return -1; + } + + /* write debug instruction 0 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0); + /* write debug instruction 1 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, DbgInst1); + + + /* wait while the DMA Manager is busy */ + WaitCount = 0; + while ((XDmaPs_ReadReg(BaseAddr, + XDMAPS_DS_OFFSET) & XDMAPS_DS_DMA_STATUS) + != XDMAPS_DS_DMA_STATUS_STOPPED + && WaitCount <= XDMAPS_MAX_WAIT) { + WaitCount++; + } + + if (WaitCount >= XDMAPS_MAX_WAIT) { + xil_printf("PL330 device at %x debug status busy time out\r\n", + BaseAddr); + return -1; + } + + /* run the command in DbgInst0 and DbgInst1 */ + XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0); + + return 0; +} + + +/****************************************************************************/ +/** +* +* It's the generic Done ISR. +* @param InstPtr is the DMA instance. +* @param Channel is the DMA channel numer. +* +* @return None.* +* +* @note None. +* +*****************************************************************************/ +static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel) +{ + + void *DmaProgBuf; + XDmaPs_ChannelData *ChanData; + XDmaPs_Cmd *DmaCmd; + //u32 Value; + + ChanData = InstPtr->Chans + Channel; + + /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTSTATUS_OFFSET);*/ + + /* clear the interrupt status */ + XDmaPs_WriteReg(InstPtr->Config.BaseAddress, + XDMAPS_INTCLR_OFFSET, + 1 << ChanData->ChanId); + + /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress, + XDMAPS_INTSTATUS_OFFSET);*/ + + + DmaCmd = ChanData->DmaCmdToHw; + if (DmaCmd) { + if (!ChanData->HoldDmaProg) { + DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg; + if (DmaProgBuf) + XDmaPs_BufPool_Free(ChanData->ProgBufPool, + DmaProgBuf); + DmaCmd->GeneratedDmaProg = NULL; + } + + DmaCmd->DmaStatus = 0; + ChanData->DmaCmdToHw = NULL; + ChanData->DmaCmdFromHw = DmaCmd; + + if (ChanData->DoneHandler) + ChanData->DoneHandler(Channel, DmaCmd, + ChanData->DoneRef); + } + +} + + +/****************************************************************************/ +/** +* Prints the content of the buffer in bytes +* @param Buf is the buffer. +* @param Length is the length of the DMA program. +* +* @return None. +* +* @note None. +****************************************************************************/ +static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length) +{ + int Index; + for (Index = 0; Index < Length; Index++) + xil_printf("[%x] %x\r\n", Index, Buf[Index]); + +} +/****************************************************************************/ +/** +* Print the Dma Prog Contents. +* +* @param Cmd is the command buffer. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ + void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd) +{ + if (Cmd->GeneratedDmaProg && Cmd->GeneratedDmaProgLength) { + xil_printf("Generated DMA program (%d):\r\n", + Cmd->GeneratedDmaProgLength); + XDmaPs_Print_DmaProgBuf((char *)Cmd->GeneratedDmaProg, + Cmd->GeneratedDmaProgLength); + } + + if (Cmd->UserDmaProg && Cmd->UserDmaProgLength) { + xil_printf("User defined DMA program (%d):\r\n", + Cmd->UserDmaProgLength); + XDmaPs_Print_DmaProgBuf((char *)Cmd->UserDmaProg, + Cmd->UserDmaProgLength); + } +} + + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps.h b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps.h new file mode 100644 index 0000000..179c840 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps.h @@ -0,0 +1,329 @@ +/****************************************************************************** +* Copyright (C) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdmaps.h +* @addtogroup dmaps_v2_8 +* @{ +* @details +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	hbm    08/19/10 First Release
+* 1.01a nm     12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		        the maximum number of channels.
+*		        Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                       with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h.
+*			Added the tcl file to automatically generate the
+*			xparameters.h
+* 1.02a sg     05/16/12 Made changes for doxygen and moved some function
+*			header from the xdmaps.h file to xdmaps.c file
+*			Other cleanup for coding guidelines and CR 657109
+*			and CR 657898
+*			The xdmaps_example_no_intr.c example is removed
+*			as it is using interrupts  and is similar to
+*			the interrupt example - CR 652477
+* 1.03a sg     07/16/2012 changed inline to __inline for CR665681
+* 1.04a nm     10/22/2012 Fixed CR# 681671.
+* 1.05a nm     04/15/2013 Fixed CR# 704396. Removed warnings when compiled
+*			  with -Wall and -Wextra option in bsp.
+*	       05/01/2013 Fixed CR# 700189. Changed XDmaPs_BuildDmaProg()
+*			  function description.
+*			  Fixed CR# 704396. Removed unused variables
+*			  UseM2MByte & MemBurstLen from XDmaPs_BuildDmaProg()
+*			  function.
+* 1.07a asa    11/02/13. Made changes to fix compilation issues for iarcc.
+*			   Removed the PDBG prints. By default they were always
+*			   defined out and never used. The PDBG is non-standard for
+*			   Xilinx drivers and no other driver does something similar.
+*			   Since there is no easy way to fix compilation issues with
+*			   the IARCC compiler around PDBG, it is better to remove it.
+*			   Users can always use xil_printfs if they want to debug.
+* 2.0   adk    10/12/13  Updated as per the New Tcl API's
+* 2.01  kpc    08/23/14  Fixed the IAR compiler reported errors
+* 2.2   mus    08/12/16  Declared all inline functions in xdmaps.c as extern, to avoid
+*                        linker error for IAR compiler
+* 2.3   ms     01/23/17 Modified xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 2.4   adk    13/08/18 Fixed armcc compiler warnings in the driver CR-1008310.
+* 2.8	sk     05/18/21 Modify all inline functions declarations from extern inline
+*			to static inline to avoid the linkage conflict for IAR compiler.
+* 
+* +*****************************************************************************/ + +#ifndef XDMAPS_H /* prevent circular inclusions */ +#define XDMAPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xparameters.h" +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" + +#include "xdmaps_hw.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ +} XDmaPs_Config; + + +/** DMA channle control structure. It's for AXI bus transaction. + * This struct will be translated into a 32-bit channel control register value. + */ +typedef struct { + unsigned int EndianSwapSize; /**< Endian swap size. */ + unsigned int DstCacheCtrl; /**< Destination cache control */ + unsigned int DstProtCtrl; /**< Destination protection control */ + unsigned int DstBurstLen; /**< Destination burst length */ + unsigned int DstBurstSize; /**< Destination burst size */ + unsigned int DstInc; /**< Destination incrementing or fixed + * address */ + unsigned int SrcCacheCtrl; /**< Source cache control */ + unsigned int SrcProtCtrl; /**< Source protection control */ + unsigned int SrcBurstLen; /**< Source burst length */ + unsigned int SrcBurstSize; /**< Source burst size */ + unsigned int SrcInc; /**< Source incrementing or fixed + * address */ +} XDmaPs_ChanCtrl; + +/** DMA block descriptor stucture. + */ +typedef struct { + u32 SrcAddr; /**< Source starting address */ + u32 DstAddr; /**< Destination starting address */ + unsigned int Length; /**< Number of bytes for the block */ +} XDmaPs_BD; + +/** + * A DMA command consisits of a channel control struct, a block descriptor, + * a user defined program, a pointer pointing to generated DMA program, and + * execution result. + * + */ +typedef struct { + XDmaPs_ChanCtrl ChanCtrl; /**< Channel Control Struct */ + XDmaPs_BD BD; /**< Together with SgLength field, + * it's a scatter-gather list. + */ + void *UserDmaProg; /**< If user wants the driver to + * execute their own DMA program, + * this field points to the DMA + * program. + */ + int UserDmaProgLength; /**< The length of user defined + * DMA program. + */ + + void *GeneratedDmaProg; /**< The DMA program genreated + * by the driver. This field will be + * set if a user invokes the DMA + * program generation function. Or + * the DMA command is finished and + * a user informs the driver not to + * release the program buffer. + * This field has two purposes, one + * is to ask the driver to generate + * a DMA program while the DMAC is + * performaning DMA transactions. The + * other purpose is to debug the + * driver. + */ + int GeneratedDmaProgLength; /**< The length of the DMA program + * generated by the driver + */ + int DmaStatus; /**< 0 on success, otherwise error code + */ + u32 ChanFaultType; /**< Channel fault type in case of fault + */ + u32 ChanFaultPCAddr; /**< Channel fault PC address + */ +} XDmaPs_Cmd; + +/** + * It's the done handler a user can set for a channel + */ +typedef void (*XDmaPsDoneHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +/** + * It's the fault handler a user can set for a channel + */ +typedef void (*XDmaPsFaultHandler) (unsigned int Channel, + XDmaPs_Cmd *DmaCmd, + void *CallbackRef); + +#define XDMAPS_MAX_CHAN_BUFS 2 +#define XDMAPS_CHAN_BUF_LEN 128 + +/** + * The XDmaPs_ProgBuf is the struct for a DMA program buffer. + */ +typedef struct { + char Buf[XDMAPS_CHAN_BUF_LEN]; /**< The actual buffer the holds the + * content */ + unsigned Len; /**< The actual length of the DMA + * program in bytes. */ + int Allocated; /**< A tag indicating whether the + * buffer is allocated or not */ +} XDmaPs_ProgBuf; + +/** + * The XDmaPs_ChannelData is a struct to book keep individual channel of + * the DMAC. + */ +typedef struct { + unsigned DevId; /**< Device id indicating which DMAC */ + unsigned ChanId; /**< Channel number of the DMAC */ + XDmaPs_ProgBuf ProgBufPool[XDMAPS_MAX_CHAN_BUFS]; /**< A pool of + program buffers*/ + XDmaPsDoneHandler DoneHandler; /**< Done interrupt handler */ + void *DoneRef; /**< Done interrupt callback data */ + XDmaPs_Cmd *DmaCmdToHw; /**< DMA command being executed */ + XDmaPs_Cmd *DmaCmdFromHw; /**< DMA command that is finished. + * This field is for debugging purpose + */ + int HoldDmaProg; /**< A tag indicating whether to hold the + * DMA program after the DMA is done. + */ + +} XDmaPs_ChannelData; + +/** + * The XDmaPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XDmaPs_Config Config; /**< Configuration data structure */ + int IsReady; /**< Device is Ready */ + int CacheLength; /**< icache length */ + XDmaPsFaultHandler FaultHandler; /**< fault interrupt handler */ + void *FaultRef; /**< fault call back data */ + XDmaPs_ChannelData Chans[XDMAPS_CHANNELS_PER_DEV]; + /**< + * channel data + */ +} XDmaPs; + +/* + * Functions implemented in xdmaps.c + */ +int XDmaPs_CfgInitialize(XDmaPs *InstPtr, + XDmaPs_Config *Config, + u32 EffectiveAddr); + +int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd, + int HoldDmaProg); + +int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel); +int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, + XDmaPs_Cmd *Cmd); +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); + + +int XDmaPs_ResetManager(XDmaPs *InstPtr); +int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel); + + +int XDmaPs_SetDoneHandler(XDmaPs *InstPtr, + unsigned Channel, + XDmaPsDoneHandler DoneHandler, + void *CallbackRef); + +int XDmaPs_SetFaultHandler(XDmaPs *InstPtr, + XDmaPsFaultHandler FaultHandler, + void *CallbackRef); + +void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd); +int XDmaPs_Instr_DMARMB(char *DmaProg); +int XDmaPs_Instr_DMAWMB(char *DmaProg); + +/** + * To avoid linkage error,modify all inline functions from extern + * inline to static inline for IAR compiler + */ +#ifdef __ICCARM__ +static INLINE int XDmaPs_Instr_DMAEND(char *DmaProg); +static INLINE void XDmaPs_Memcpy4(char *Dst, char *Src); +static INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn, + u32 Imm, unsigned int Ns); +static INLINE int XDmaPs_Instr_DMALD(char *DmaProg); +static INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc, + unsigned LoopIterations); +static INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc); +static INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm); +static INLINE int XDmaPs_Instr_DMANOP(char *DmaProg); +static INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber); +static INLINE int XDmaPs_Instr_DMAST(char *DmaProg); +static INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize); +static INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize); +#endif + +/** + * Driver done interrupt service routines for the channels. + * We need this done ISR mainly because the driver needs to release the + * DMA program buffer. This is the one that connects the GIC + */ +void XDmaPs_DoneISR_0(XDmaPs *InstPtr); +void XDmaPs_DoneISR_1(XDmaPs *InstPtr); +void XDmaPs_DoneISR_2(XDmaPs *InstPtr); +void XDmaPs_DoneISR_3(XDmaPs *InstPtr); +void XDmaPs_DoneISR_4(XDmaPs *InstPtr); +void XDmaPs_DoneISR_5(XDmaPs *InstPtr); +void XDmaPs_DoneISR_6(XDmaPs *InstPtr); +void XDmaPs_DoneISR_7(XDmaPs *InstPtr); + +/** + * Driver fault interrupt service routine + */ +void XDmaPs_FaultISR(XDmaPs *InstPtr); + + +/* + * Static loopup function implemented in xdmaps_sinit.c + */ +XDmaPs_Config *XDmaPs_LookupConfig(u16 DeviceId); + + +/* + * self-test functions in xdmaps_selftest.c + */ +int XDmaPs_SelfTest(XDmaPs *InstPtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_g.c new file mode 100644 index 0000000..30facf1 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_g.c @@ -0,0 +1,54 @@ +/****************************************************************************** +* Copyright (C) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdmaps_g.c +* @addtogroup dmaps_v2_8 +* @{ +* +* This file contains a configuration table where each entry is a configuration +* structure for an XDmaPs device in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  hbm    08/19/2010 First Release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xdmaps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Prototypes ******************************/ + +/** + * Each XDmaPs device in the system has an entry in this table. + */ +XDmaPs_Config XDmaPs_ConfigTable[] = { + { + XPAR_XDMAPS_0_DEVICE_ID, + XPAR_XDMAPS_0_BASEADDR, + }, +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_hw.c b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_hw.c new file mode 100644 index 0000000..cb45d29 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_hw.c @@ -0,0 +1,90 @@ +/****************************************************************************** +* Copyright (C) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdmaps_hw.c +* @addtogroup dmaps_v2_8 +* @{ +* +* This file contains the implementation of the interface reset functionality +* for XDmaPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.06a kpc 10/07/13 First release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xdmaps_hw.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ +#ifndef XDMAPS_MAX_WAIT +#define XDMAPS_MAX_WAIT 4000 +#endif +/************************** Function Prototypes *****************************/ + +/************************** Variable Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function perform the reset sequence to the given dmaps interface by +* configuring the appropriate control bits in the dmaps specifc registers +* the dmaps reset squence involves the following steps +* Disable all the interuupts +* Clear the pending interrupts +* Kill all the active channel threads +* Kill the manager thread +* +* @param BaseAddress of the interface +* +* @return N/A +* +* @note +* This function will not modify the slcr registers that are relavant for +* dmaps controller +******************************************************************************/ +void XDmaPs_ResetHw(u32 BaseAddress) +{ + u32 DbgInst; + u32 WaitCount = 0; + u32 ChanIndex; + + /* Disable all the interrupts */ + XDmaPs_WriteReg(BaseAddress, XDMAPS_INTEN_OFFSET, 0x00); + /* Clear the interrupts */ + XDmaPs_WriteReg(BaseAddress, XDMAPS_INTCLR_OFFSET, XDMAPS_INTCLR_ALL_MASK); + /* Kill the dma channel threads */ + for (ChanIndex=0; ChanIndex < XDMAPS_CHANNELS_PER_DEV; ChanIndex++) { + while ((XDmaPs_ReadReg(BaseAddress, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + && (WaitCount < XDMAPS_MAX_WAIT)) + WaitCount++; + + DbgInst = XDmaPs_DBGINST0(0, 0x01, ChanIndex, 1); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST0_OFFSET, DbgInst); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST1_OFFSET, 0x0); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGCMD_OFFSET, 0x0); + } + /* Kill the manager thread */ + DbgInst = XDmaPs_DBGINST0(0, 0x01, 0, 0); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST0_OFFSET, DbgInst); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGINST1_OFFSET, 0x0); + XDmaPs_WriteReg(BaseAddress, XDMAPS_DBGCMD_OFFSET, 0x0); +} + + + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_hw.h new file mode 100644 index 0000000..d039278 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_hw.h @@ -0,0 +1,267 @@ +/****************************************************************************** +* Copyright (C) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xdmaps_hw.h +* @addtogroup dmaps_v2_8 +* @{ +* +* This header file contains the hardware interface of an XDmaPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who   Date     Changes
+* ----- ----  -------- ----------------------------------------------
+* 1.00a	hbm   08/18/10 First Release
+* 1.01a nm    12/20/12 Added definition XDMAPS_CHANNELS_PER_DEV which specifies
+*		       the maximum number of channels.
+*		       Replaced the usage of XPAR_XDMAPS_CHANNELS_PER_DEV
+*                      with XDMAPS_CHANNELS_PER_DEV defined in xdmaps_hw.h
+* 1.02a sg    05/16/12 Made changes for doxygen
+* 1.06a kpc   07/10/13 Added function prototype
+* 
+* +******************************************************************************/ + +#ifndef XDMAPS_HW_H /* prevent circular inclusions */ +#define XDMAPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the DMAC. + * @{ + */ + +#define XDMAPS_DS_OFFSET 0x000 /* DMA Status Register */ +#define XDMAPS_DPC_OFFSET 0x004 /* DMA Program Counter Rregister */ +#define XDMAPS_INTEN_OFFSET 0X020 /* DMA Interrupt Enable Register */ +#define XDMAPS_ES_OFFSET 0x024 /* DMA Event Status Register */ +#define XDMAPS_INTSTATUS_OFFSET 0x028 /* DMA Interrupt Status Register + */ +#define XDMAPS_INTCLR_OFFSET 0x02c /* DMA Interrupt Clear Register */ +#define XDMAPS_FSM_OFFSET 0x030 /* DMA Fault Status DMA Manager + * Register + */ +#define XDMAPS_FSC_OFFSET 0x034 /* DMA Fault Status DMA Chanel Register + */ +#define XDMAPS_FTM_OFFSET 0x038 /* DMA Fault Type DMA Manager Register */ + +#define XDMAPS_FTC0_OFFSET 0x040 /* DMA Fault Type for DMA Channel 0 */ +/* + * The offset for the rest of the FTC registers is calculated as + * FTC0 + dev_chan_num * 4 + */ +#define XDmaPs_FTCn_OFFSET(ch) (XDMAPS_FTC0_OFFSET + (ch) * 4) + +#define XDMAPS_CS0_OFFSET 0x100 /* Channel Status for DMA Channel 0 */ +/* + * The offset for the rest of the CS registers is calculated as + * CS0 + * dev_chan_num * 0x08 + */ +#define XDmaPs_CSn_OFFSET(ch) (XDMAPS_CS0_OFFSET + (ch) * 8) + +#define XDMAPS_CPC0_OFFSET 0x104 /* Channel Program Counter for DMA + * Channel 0 + */ +/* + * The offset for the rest of the CPC registers is calculated as + * CPC0 + dev_chan_num * 0x08 + */ +#define XDmaPs_CPCn_OFFSET(ch) (XDMAPS_CPC0_OFFSET + (ch) * 8) + +#define XDMAPS_SA_0_OFFSET 0x400 /* Source Address Register for DMA + * Channel 0 + */ +/* The offset for the rest of the SA registers is calculated as + * SA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_SA_n_OFFSET(ch) (XDMAPS_SA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DA_0_OFFSET 0x404 /* Destination Address Register for + * DMA Channel 0 + */ +/* The offset for the rest of the DA registers is calculated as + * DA_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_DA_n_OFFSET(ch) (XDMAPS_DA_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_CC_0_OFFSET 0x408 /* Channel Control Register for + * DMA Channel 0 + */ +/* + * The offset for the rest of the CC registers is calculated as + * CC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_CC_n_OFFSET(ch) (XDMAPS_CC_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_LC0_0_OFFSET 0x40C /* Loop Counter 0 for DMA Channel 0 */ +/* + * The offset for the rest of the LC0 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC0_n_OFFSET(ch) (XDMAPS_LC0_0_OFFSET + (ch) * 0x20) +#define XDMAPS_LC1_0_OFFSET 0x410 /* Loop Counter 1 for DMA Channel 0 */ +/* + * The offset for the rest of the LC1 registers is calculated as + * LC_0 + dev_chan_num * 0x20 + */ +#define XDmaPs_LC1_n_OFFSET(ch) (XDMAPS_LC1_0_OFFSET + (ch) * 0x20) + +#define XDMAPS_DBGSTATUS_OFFSET 0xD00 /* Debug Status Register */ +#define XDMAPS_DBGCMD_OFFSET 0xD04 /* Debug Command Register */ +#define XDMAPS_DBGINST0_OFFSET 0xD08 /* Debug Instruction 0 Register */ +#define XDMAPS_DBGINST1_OFFSET 0xD0C /* Debug Instruction 1 Register */ + +#define XDMAPS_CR0_OFFSET 0xE00 /* Configuration Register 0 */ +#define XDMAPS_CR1_OFFSET 0xE04 /* Configuration Register 1 */ +#define XDMAPS_CR2_OFFSET 0xE08 /* Configuration Register 2 */ +#define XDMAPS_CR3_OFFSET 0xE0C /* Configuration Register 3 */ +#define XDMAPS_CR4_OFFSET 0xE10 /* Configuration Register 4 */ +#define XDMAPS_CRDN_OFFSET 0xE14 /* Configuration Register Dn */ + +#define XDMAPS_PERIPH_ID_0_OFFSET 0xFE0 /* Peripheral Identification + * Register 0 + */ +#define XDMAPS_PERIPH_ID_1_OFFSET 0xFE4 /* Peripheral Identification + * Register 1 + */ +#define XDMAPS_PERIPH_ID_2_OFFSET 0xFE8 /* Peripheral Identification + * Register 2 + */ +#define XDMAPS_PERIPH_ID_3_OFFSET 0xFEC /* Peripheral Identification + * Register 3 + */ +#define XDMAPS_PCELL_ID_0_OFFSET 0xFF0 /* PrimeCell Identification + * Register 0 + */ +#define XDMAPS_PCELL_ID_1_OFFSET 0xFF4 /* PrimeCell Identification + * Register 1 + */ +#define XDMAPS_PCELL_ID_2_OFFSET 0xFF8 /* PrimeCell Identification + * Register 2 + */ +#define XDMAPS_PCELL_ID_3_OFFSET 0xFFC /* PrimeCell Identification + * Register 3 + */ + +/* + * Some useful register masks + */ +#define XDMAPS_DS_DMA_STATUS 0x0F /* DMA status mask */ +#define XDMAPS_DS_DMA_STATUS_STOPPED 0x00 /* debug status busy mask */ + +#define XDMAPS_DBGSTATUS_BUSY 0x01 /* debug status busy mask */ + +#define XDMAPS_CS_ACTIVE_MASK 0x07 /* channel status active mask, + * llast 3 bits of CS register + */ + +#define XDMAPS_CR1_I_CACHE_LEN_MASK 0x07 /* i_cache_len mask */ + + +/* + * XDMAPS_DBGINST0 - constructs the word for the Debug Instruction-0 Register. + * @b1: Instruction byte 1 + * @b0: Instruction byte 0 + * @ch: Channel number + * @dbg_th: Debug thread encoding: 0 = DMA manager thread, 1 = DMA channel + */ +#define XDmaPs_DBGINST0(b1, b0, ch, dbg_th) \ + (((b1) << 24) | ((b0) << 16) | (((ch) & 0x7) << 8) | ((dbg_th & 0x1))) + +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +/* @}*/ + + +#define XDMAPS_CHANNELS_PER_DEV 8 + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ + +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ + +/* @} */ +#define XDMAPS_INTCLR_ALL_MASK 0xFF + +#define XDmaPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write a DMAC register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note +* C-Style signature: +* void XDmaPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +******************************************************************************/ +#define XDmaPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (RegOffset), (RegisterValue)) +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes *****************************/ +/* + * Perform reset operation to the dmaps interface + */ +void XDmaPs_ResetHw(u32 BaseAddr); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_selftest.c b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_selftest.c new file mode 100644 index 0000000..dd2d4d3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_selftest.c @@ -0,0 +1,84 @@ +/****************************************************************************** +* Copyright (C) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdmaps_selftest.c +* @addtogroup dmaps_v2_8 +* @{ +* +* This file contains the self-test functions for the XDmaPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00	hbm 	03/29/2010 First Release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xdmaps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + + +/****************************************************************************/ +/** +* +* This function runs a self-test on the driver and hardware device. This self +* test performs a local loopback and verifies data can be sent and received. +* +* The time for this test is proportional to the baud rate that has been set +* prior to calling this function. +* +* The mode and control registers are restored before return. +* +* @param InstPtr is a pointer to the XDmaPs instance +* +* @return +* +* - XST_SUCCESS if the test was successful +* - XST_FAILURE if the test failed +* +* @note +* +* This function can hang if the hardware is not functioning properly. +* +******************************************************************************/ +int XDmaPs_SelfTest(XDmaPs *InstPtr) +{ + u32 BaseAddr = InstPtr->Config.BaseAddress; + int i; + + if (XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET) + & XDMAPS_DBGSTATUS_BUSY) + return XST_FAILURE; + + for (i = 0; i < XDMAPS_CHANNELS_PER_DEV; i++) { + if (XDmaPs_ReadReg(BaseAddr, + XDmaPs_CSn_OFFSET(i))) + return XST_FAILURE; + } + return XST_SUCCESS; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_sinit.c new file mode 100644 index 0000000..751df21 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/dmaps/src/xdmaps_sinit.c @@ -0,0 +1,78 @@ +/****************************************************************************** +* Copyright (C) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xdmaps_sinit.c +* @addtogroup dmaps_v2_8 +* @{ +* +* The implementation of the XDmaPs driver's static initialzation +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00  hbm  08/13/10 First Release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xdmaps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Variable Definitions ****************************/ +extern XDmaPs_Config XDmaPs_ConfigTable[]; + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the ID of the device +* +* @return +* +* A pointer to the configuration structure or NULL if the specified device +* is not in the system. +* +* @note +* +* None. +* +******************************************************************************/ +XDmaPs_Config *XDmaPs_LookupConfig(u16 DeviceId) +{ + XDmaPs_Config *CfgPtr = NULL; + + int i; + + for (i = 0; i < XPAR_XDMAPS_NUM_INSTANCES; i++) { + if (XDmaPs_ConfigTable[i].DeviceId == DeviceId) { + CfgPtr = &XDmaPs_ConfigTable[i]; + break; + } + } + + return CfgPtr; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/Makefile new file mode 100644 index 0000000..be5fccb --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/Makefile @@ -0,0 +1,41 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +INCLUDEFILES:=*.h + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf $(DEPFILES) diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps.c b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps.c new file mode 100644 index 0000000..88a35cb --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps.c @@ -0,0 +1,487 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps.c +* @addtogroup emacps_v3_16 +* @{ +* +* The XEmacPs driver. Functions in this file are the minimum required functions +* for this driver. See xemacps.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 2.1  srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification and
+*		      64-bit changes.
+* 3.00 kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.0  hk   02/20/15 Added support for jumbo frames. Increase AHB burst.
+*                    Disable extended mode. Perform all 64 bit changes under
+*                    check for arch64.
+* 3.1  hk   08/10/15 Update upper 32 bit tx and rx queue ptr registers
+* 3.5  hk   08/14/17 Update cache coherency information of the interface in
+*                    its config structure.
+* 3.8  hk   09/17/18 Cleanup stale comments.
+* 3.8  mus  11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
+* 3.10 hk   05/16/19 Clear status registers properly in reset
+* 3.11 sd   02/14/20 Add clock support
+*
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xemacps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +void XEmacPs_StubHandler(void); /* Default handler routine */ + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* Initialize a specific XEmacPs instance/driver. The initialization entails: +* - Initialize fields of the XEmacPs instance structure +* - Reset hardware and apply default options +* - Configure the DMA channels +* +* The PHY is setup independently from the device. Use the MII or whatever other +* interface may be present for setup. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param CfgPtr is the device configuration structure containing required +* hardware build data. +* @param EffectiveAddress is the base address of the device. If address +* translation is not utilized, this parameter can be passed in using +* CfgPtr->Config.BaseAddress to specify the physical base address. +* +* @return +* - XST_SUCCESS if initialization was successful +* +******************************************************************************/ +LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr, + UINTPTR EffectiveAddress) +{ + /* Verify arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + + /* Set device base address and ID */ + InstancePtr->Config.DeviceId = CfgPtr->DeviceId; + InstancePtr->Config.BaseAddress = EffectiveAddress; + InstancePtr->Config.IsCacheCoherent = CfgPtr->IsCacheCoherent; +#if defined (XCLOCKING) + InstancePtr->Config.RefClk = CfgPtr->RefClk; +#endif + + InstancePtr->Config.S1GDiv0 = CfgPtr->S1GDiv0; + InstancePtr->Config.S1GDiv1 = CfgPtr->S1GDiv1; + InstancePtr->Config.S100MDiv0 = CfgPtr->S100MDiv0; + InstancePtr->Config.S100MDiv1 = CfgPtr->S100MDiv1; + InstancePtr->Config.S10MDiv0 = CfgPtr->S10MDiv0; + InstancePtr->Config.S10MDiv1 = CfgPtr->S10MDiv1; + + /* Set callbacks to an initial stub routine */ + InstancePtr->SendHandler = ((XEmacPs_Handler)((void*)XEmacPs_StubHandler)); + InstancePtr->RecvHandler = ((XEmacPs_Handler)(void*)XEmacPs_StubHandler); + InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void*)XEmacPs_StubHandler); + + /* Reset the hardware and set default options */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + XEmacPs_Reset(InstancePtr); + + return (LONG)(XST_SUCCESS); +} + + +/*****************************************************************************/ +/** +* Start the Ethernet controller as follows: +* - Enable transmitter if XTE_TRANSMIT_ENABLE_OPTION is set +* - Enable receiver if XTE_RECEIVER_ENABLE_OPTION is set +* - Start the SG DMA send and receive channels and enable the device +* interrupt +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return N/A +* +* @note +* Hardware is configured with scatter-gather DMA, the driver expects to start +* the scatter-gather channels and expects that the user has previously set up +* the buffer descriptor lists. +* +* This function makes use of internal resources that are shared between the +* Start, Stop, and Set/ClearOptions functions. So if one task might be setting +* device options while another is trying to start the device, the user is +* required to provide protection of this shared data (typically using a +* semaphore). +* +* This function must not be preempted by an interrupt that may service the +* device. +* +******************************************************************************/ +void XEmacPs_Start(XEmacPs *InstancePtr) +{ + u32 Reg; + + /* Assert bad arguments and conditions */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + +#if defined (XCLOCKING) + if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) { + Xil_ClockEnable(InstancePtr->Config.RefClk); + } +#endif + + /* Start DMA */ + /* When starting the DMA channels, both transmit and receive sides + * need an initialized BD list. + */ + if (InstancePtr->Version == 2) { + Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0); + Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXQBASE_OFFSET, + InstancePtr->RxBdRing.BaseBdAddr); + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXQBASE_OFFSET, + InstancePtr->TxBdRing.BaseBdAddr); + } + + /* clear any existed int status */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, + XEMACPS_IXR_ALL_MASK); + + /* Enable transmitter if not already enabled */ + if ((InstancePtr->Options & (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION)!=0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + if ((!(Reg & XEMACPS_NWCTRL_TXEN_MASK))==TRUE) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, + Reg | (u32)XEMACPS_NWCTRL_TXEN_MASK); + } + } + + /* Enable receiver if not already enabled */ + if ((InstancePtr->Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + if ((!(Reg & XEMACPS_NWCTRL_RXEN_MASK))==TRUE) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, + Reg | (u32)XEMACPS_NWCTRL_RXEN_MASK); + } + } + + /* Enable TX and RX interrupts */ + XEmacPs_IntEnable(InstancePtr, (XEMACPS_IXR_TX_ERR_MASK | + XEMACPS_IXR_RX_ERR_MASK | (u32)XEMACPS_IXR_FRAMERX_MASK | + (u32)XEMACPS_IXR_TXCOMPL_MASK)); + + /* Enable TX Q1 Interrupts */ + if (InstancePtr->Version > 2) + XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK); + + /* Mark as started */ + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; + + return; +} + + +/*****************************************************************************/ +/** +* Gracefully stop the Ethernet MAC as follows: +* - Disable all interrupts from this device +* - Stop DMA channels +* - Disable the tansmitter and receiver +* +* Device options currently in effect are not changed. +* +* This function will disable all interrupts. Default interrupts settings that +* had been enabled will be restored when XEmacPs_Start() is called. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @note +* This function makes use of internal resources that are shared between the +* Start, Stop, SetOptions, and ClearOptions functions. So if one task might be +* setting device options while another is trying to start the device, the user +* is required to provide protection of this shared data (typically using a +* semaphore). +* +* Stopping the DMA channels causes this function to block until the DMA +* operation is complete. +* +******************************************************************************/ +void XEmacPs_Stop(XEmacPs *InstancePtr) +{ + u32 Reg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Disable all interrupts */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET, + XEMACPS_IXR_ALL_MASK); + + /* Disable the receiver & transmitter */ + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); + Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + + /* Mark as stopped */ + InstancePtr->IsStarted = 0U; +#if defined (XCLOCKING) + Xil_ClockDisable(InstancePtr->Config.RefClk); +#endif +} + + +/*****************************************************************************/ +/** +* Perform a graceful reset of the Ethernet MAC. Resets the DMA channels, the +* transmitter, and the receiver. +* +* Steps to reset +* - Stops transmit and receive channels +* - Stops DMA +* - Configure transmit and receive buffer size to default +* - Clear transmit and receive status register and counters +* - Clear all interrupt sources +* - Clear phy (if there is any previously detected) address +* - Clear MAC addresses (1-4) as well as Type IDs and hash value +* +* All options are placed in their default state. Any frames in the +* descriptor lists will remain in the lists. The side effect of doing +* this is that after a reset and following a restart of the device, frames +* were in the list before the reset may be transmitted or received. +* +* The upper layer software is responsible for re-configuring (if necessary) +* and restarting the MAC after the reset. Note also that driver statistics +* are not cleared on reset. It is up to the upper layer software to clear the +* statistics if needed. +* +* When a reset is required, the driver notifies the upper layer software of +* this need through the ErrorHandler callback and specific status codes. +* The upper layer software is responsible for calling this Reset function +* and then re-configuring the device. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +******************************************************************************/ +void XEmacPs_Reset(XEmacPs *InstancePtr) +{ + u32 Reg; + u8 i; + s8 EmacPs_zero_MAC[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Stop the device and reset hardware */ + XEmacPs_Stop(InstancePtr); + InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS; + + InstancePtr->Version = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, 0xFC); + + InstancePtr->Version = (InstancePtr->Version >> 16) & 0xFFF; + + InstancePtr->MaxMtuSize = XEMACPS_MTU; + InstancePtr->MaxFrameSize = XEMACPS_MTU + XEMACPS_HDR_SIZE + + XEMACPS_TRL_SIZE; + InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + + XEMACPS_HDR_VLAN_SIZE; + InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK; + + /* Setup hardware with default values */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, + (XEMACPS_NWCTRL_STATCLR_MASK | + XEMACPS_NWCTRL_MDEN_MASK) & + (u32)(~XEMACPS_NWCTRL_LOOPEN_MASK)); + + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + Reg &= XEMACPS_NWCFG_MDCCLKDIV_MASK; + + Reg = Reg | (u32)XEMACPS_NWCFG_100_MASK | + (u32)XEMACPS_NWCFG_FDEN_MASK | + (u32)XEMACPS_NWCFG_UCASTHASHEN_MASK; + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, Reg); + if (InstancePtr->Version > 2) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET, + (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET) | + XEMACPS_NWCFG_DWIDTH_64_MASK)); + } + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, + (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) + + (((((u32)XEMACPS_RX_BUF_SIZE % + (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << + (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & + (u32)(XEMACPS_DMACR_RXBUF_MASK)) | + (u32)XEMACPS_DMACR_RXSIZE_MASK | + (u32)XEMACPS_DMACR_TXSIZE_MASK); + + + if (InstancePtr->Version > 2) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, + (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET) | +#if defined(__aarch64__) || defined(__arch64__) + (u32)XEMACPS_DMACR_ADDR_WIDTH_64 | +#endif + (u32)XEMACPS_DMACR_INCR16_AHB_BURST)); + } + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET, XEMACPS_SR_ALL_MASK); + + XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_SEND); + if (InstancePtr->Version > 2) + XEmacPs_SetQueuePtr(InstancePtr, 0, 0x01U, (u16)XEMACPS_SEND); + XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_RECV); + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXSR_OFFSET, XEMACPS_SR_ALL_MASK); + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET, + XEMACPS_IXR_ALL_MASK); + + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_ISR_OFFSET); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, + Reg); + + XEmacPs_ClearHash(InstancePtr); + + for (i = 1U; i < 5U; i++) { + (void)XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i); + (void)XEmacPs_SetTypeIdCheck(InstancePtr, 0x00000000U, i); + } + + /* clear all counters */ + for (i = 0U; i < (u8)((XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4U); + i++) { + (void)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_OCTTXL_OFFSET + (u32)(((u32)i) * ((u32)4))); + } + + /* Disable the receiver */ + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + + /* Sync default options with hardware but leave receiver and + * transmitter disabled. They get enabled with XEmacPs_Start() if + * XEMACPS_TRANSMITTER_ENABLE_OPTION and + * XEMACPS_RECEIVER_ENABLE_OPTION are set. + */ + (void)XEmacPs_SetOptions(InstancePtr, InstancePtr->Options & + ~((u32)XEMACPS_TRANSMITTER_ENABLE_OPTION | + (u32)XEMACPS_RECEIVER_ENABLE_OPTION)); + + (void)XEmacPs_ClearOptions(InstancePtr, ~InstancePtr->Options); +} + + +/******************************************************************************/ +/** + * This is a stub for the asynchronous callbacks. The stub is here in case the + * upper layer forgot to set the handler(s). On initialization, all handlers are + * set to this callback. It is considered an error for this handler to be + * invoked. + * + ******************************************************************************/ +void XEmacPs_StubHandler(void) +{ + Xil_AssertVoidAlways(); +} + +/*****************************************************************************/ +/** +* This function sets the start address of the transmit/receive buffer queue. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param QPtr is the address of the Queue to be written +* @param QueueNum is the Buffer Queue Index +* @param Direction indicates Transmit/Receive +* +* @note +* The buffer queue addresses has to be set before starting the transfer, so +* this function has to be called in prior to XEmacPs_Start() +* +******************************************************************************/ +void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum, + u16 Direction) +{ + /* Assert bad arguments and conditions */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* If already started, then there is nothing to do */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + return; + } + + if (QueueNum == 0x00U) { + if (Direction == XEMACPS_SEND) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXQBASE_OFFSET, + (QPtr & ULONG64_LO_MASK)); + } else { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXQBASE_OFFSET, + (QPtr & ULONG64_LO_MASK)); + } + } + else { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXQ1BASE_OFFSET, + (QPtr & ULONG64_LO_MASK)); + } +#ifdef __aarch64__ + if (Direction == XEMACPS_SEND) { + /* Set the MSB of TX Queue start address */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_MSBBUF_TXQBASE_OFFSET, + (u32)((QPtr & ULONG64_HI_MASK) >> 32U)); + } else { + /* Set the MSB of RX Queue start address */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_MSBBUF_RXQBASE_OFFSET, + (u32)((QPtr & ULONG64_HI_MASK) >> 32U)); + } +#endif +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps.h b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps.h new file mode 100644 index 0000000..ac3e7a7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps.h @@ -0,0 +1,843 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** + * + * @file xemacps.h +* @addtogroup emacps_v3_16 +* @{ +* @details + * + * The Xilinx Embedded Processor Block Ethernet driver. + * + * For a full description of XEMACPS features, please see the hardware spec. + * This driver supports the following features: + * - Memory mapped access to host interface registers + * - Statistics counter registers for RMON/MIB + * - API for interrupt driven frame transfers for hardware configured DMA + * - Virtual memory support + * - Unicast, broadcast, and multicast receive address filtering + * - Full and half duplex operation + * - Automatic PAD & FCS insertion and stripping + * - Flow control + * - Support up to four 48bit addresses + * - Address checking for four specific 48bit addresses + * - VLAN frame support + * - Pause frame support + * - Large frame support up to 1536 bytes + * - Checksum offload + * + * Driver Description + * + * The device driver enables higher layer software (e.g., an application) to + * communicate to the XEmacPs. The driver handles transmission and reception + * of Ethernet frames, as well as configuration and control. No pre or post + * processing of frame data is performed. The driver does not validate the + * contents of an incoming frame in addition to what has already occurred in + * hardware. + * A single device driver can support multiple devices even when those devices + * have significantly different configurations. + * + * Initialization & Configuration + * + * The XEmacPs_Config structure is used by the driver to configure itself. + * This configuration structure is typically created by the tool-chain based + * on hardware build properties. + * + * The driver instance can be initialized in + * + * - XEmacPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddress): Uses a + * configuration structure provided by the caller. If running in a system + * with address translation, the provided virtual memory base address + * replaces the physical address present in the configuration structure. + * + * The device supports DMA only as current development plan. No FIFO mode is + * supported. The driver expects to start the DMA channels and expects that + * the user has set up the buffer descriptor lists. + * + * Interrupts and Asynchronous Callbacks + * + * The driver has no dependencies on the interrupt controller. When an + * interrupt occurs, the handler will perform a small amount of + * housekeeping work, determine the source of the interrupt, and call the + * appropriate callback function. All callbacks are registered by the user + * level application. + * + * Virtual Memory + * + * All virtual to physical memory mappings must occur prior to accessing the + * driver API. + * + * For DMA transactions, user buffers supplied to the driver must be in terms + * of their physical address. + * + * DMA + * + * The DMA engine uses buffer descriptors (BDs) to describe Ethernet frames. + * These BDs are typically chained together into a list the hardware follows + * when transferring data in and out of the packet buffers. Each BD describes + * a memory region containing either a full or partial Ethernet packet. + * + * Interrupt coalescing is not supported from this built-in DMA engine. + * + * This API requires the user to understand how the DMA operates. The + * following paragraphs provide some explanation, but the user is encouraged + * to read documentation in xemacps_bdring.h as well as study example code + * that accompanies this driver. + * + * The API is designed to get BDs to and from the DMA engine in the most + * efficient means possible. The first step is to establish a memory region + * to contain all BDs for a specific channel. This is done with + * XEmacPs_BdRingCreate(). This function sets up a BD ring that hardware will + * follow as BDs are processed. The ring will consist of a user defined number + * of BDs which will all be partially initialized. For example on the transmit + * channel, the driver will initialize all BDs' so that they are configured + * for transmit. The more fields that can be permanently setup at + * initialization, then the fewer accesses will be needed to each BD while + * the DMA engine is in operation resulting in better throughput and CPU + * utilization. The best case initialization would require the user to set + * only a frame buffer address and length prior to submitting the BD to the + * engine. + * + * BDs move through the engine with the help of functions + * XEmacPs_BdRingAlloc(), XEmacPs_BdRingToHw(), XEmacPs_BdRingFromHw(), + * and XEmacPs_BdRingFree(). + * All these functions handle BDs that are in place. That is, there are no + * copies of BDs kept anywhere and any BD the user interacts with is an actual + * BD from the same ring hardware accesses. + * + * BDs in the ring go through a series of states as follows: + * 1. Idle. The driver controls BDs in this state. + * 2. The user has data to transfer. XEmacPs_BdRingAlloc() is called to + * reserve BD(s). Once allocated, the user may setup the BD(s) with + * frame buffer address, length, and other attributes. The user controls + * BDs in this state. + * 3. The user submits BDs to the DMA engine with XEmacPs_BdRingToHw. BDs + * in this state are either waiting to be processed by hardware, are in + * process, or have been processed. The DMA engine controls BDs in this + * state. + * 4. Processed BDs are retrieved with XEmacEpv_BdRingFromHw() by the + * user. Once retrieved, the user can examine each BD for the outcome of + * the DMA transfer. The user controls BDs in this state. After examining + * the BDs the user calls XEmacPs_BdRingFree() which places the BDs back + * into state 1. + * + * Each of the four BD accessor functions operate on a set of BDs. A set is + * defined as a segment of the BD ring consisting of one or more BDs. The user + * views the set as a pointer to the first BD along with the number of BDs for + * that set. The set can be navigated by using macros XEmacPs_BdNext(). The + * user must exercise extreme caution when changing BDs in a set as there is + * nothing to prevent doing a mBdNext past the end of the set and modifying a + * BD out of bounds. + * + * XEmacPs_BdRingAlloc() + XEmacPs_BdRingToHw(), as well as + * XEmacPs_BdRingFromHw() + XEmacPs_BdRingFree() are designed to be used in + * tandem. The same BD set retrieved with BdRingAlloc should be the same one + * provided to hardware with BdRingToHw. Same goes with BdRingFromHw and + * BdRIngFree. + * + * Alignment & Data Cache Restrictions + * + * Due to the design of the hardware, all RX buffers, BDs need to be 4-byte + * aligned. Please reference xemacps_bd.h for cache related macros. + * + * DMA Tx: + * + * - If frame buffers exist in cached memory, then they must be flushed + * prior to committing them to hardware. + * + * DMA Rx: + * + * - If frame buffers exist in cached memory, then the cache must be + * invalidated for the memory region containing the frame prior to data + * access + * + * Both cache invalidate/flush are taken care of in driver code. + * + * Buffer Copying + * + * The driver is designed for a zero-copy buffer scheme. That is, the driver + * will not copy buffers. This avoids potential throughput bottlenecks within + * the driver. If byte copying is required, then the transfer will take longer + * to complete. + * + * Checksum Offloading + * + * The Embedded Processor Block Ethernet can be configured to perform IP, TCP + * and UDP checksum offloading in both receive and transmit directions. + * + * IP packets contain a 16-bit checksum field, which is the 16-bit 1s + * complement of the 1s complement sum of all 16-bit words in the header. + * TCP and UDP packets contain a 16-bit checksum field, which is the 16-bit + * 1s complement of the 1s complement sum of all 16-bit words in the header, + * the data and a conceptual pseudo header. + * + * To calculate these checksums in software requires each byte of the packet + * to be read. For TCP and UDP this can use a large amount of processing power. + * Offloading the checksum calculation to hardware can result in significant + * performance improvements. + * + * The transmit checksum offload is only available to use DMA in packet buffer + * mode. This is because the complete frame to be transmitted must be read + * into the packet buffer memory before the checksum can be calculated and + * written to the header at the beginning of the frame. + * + * For IP, TCP or UDP receive checksum offload to be useful, the operating + * system containing the protocol stack must be aware that this offload is + * available so that it can make use of the fact that the hardware has verified + * the checksum. + * + * When receive checksum offloading is enabled in the hardware, the IP header + * checksum is checked, where the packet meets the following criteria: + * + * 1. If present, the VLAN header must be four octets long and the CFI bit + * must not be set. + * 2. Encapsulation must be RFC 894 Ethernet Type Encoding or RFC 1042 SNAP + * encoding. + * 3. IP v4 packet. + * 4. IP header is of a valid length. + * 5. Good IP header checksum. + * 6. No IP fragmentation. + * 7. TCP or UDP packet. + * + * When an IP, TCP or UDP frame is received, the receive buffer descriptor + * gives an indication if the hardware was able to verify the checksums. + * There is also an indication if the frame had SNAP encapsulation. These + * indication bits will replace the type ID match indication bits when the + * receive checksum offload is enabled. + * + * If any of the checksums are verified incorrect by the hardware, the packet + * is discarded and the appropriate statistics counter incremented. + * + * PHY Interfaces + * + * RGMII 1.3 is the only interface supported. + * + * Asserts + * + * Asserts are used within all Xilinx drivers to enforce constraints on + * parameters. Asserts can be turned off on a system-wide basis by defining, + * at compile time, the NDEBUG identifier. By default, asserts are turned on + * and it is recommended that users leave asserts on during development. For + * deployment use -DNDEBUG compiler switch to remove assert code. + * + * @note + * + * Xilinx drivers are typically composed of two parts, one is the driver + * and the other is the adapter. The driver is independent of OS and processor + * and is intended to be highly portable. The adapter is OS-specific and + * facilitates communication between the driver and an OS. + * This driver is intended to be RTOS and processor independent. Any needs for + * dynamic memory management, threads or thread mutual exclusion, or cache + * control must be satisfied bythe layer above this driver. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wsy  01/10/10 First release
+ * 1.00a asa  11/21/11 The function XEmacPs_BdRingFromHwTx in file
+ *		       xemacps_bdring.c is modified. Earlier it was checking for
+ *		       "BdLimit"(passed argument) number of BDs for finding out
+ *		       which BDs are successfully processed. Now one more check
+ *		       is added. It looks for BDs till the current BD pointer
+ *		       reaches HwTail. By doing this processing time is saved.
+ * 1.00a asa  01/24/12 The function XEmacPs_BdRingFromHwTx in file
+ *		       xemacps_bdring.c is modified. Now start of packet is
+ *		       searched for returning the number of BDs processed.
+ * 1.02a asa  11/05/12 Added a new API for deleting an entry from the HASH
+ *		       registers. Added a new API to set the bust length.
+ *		       Added some new hash-defines.
+ * 1.03a asa  01/23/12 Fix for CR #692702 which updates error handling for
+ *		       Rx errors. Under heavy Rx traffic, there will be a large
+ *		       number of errors related to receive buffer not available.
+ *		       Because of a HW bug (SI #692601), under such heavy errors,
+ *		       the Rx data path can become unresponsive. To reduce the
+ *		       probabilities for hitting this HW bug, the SW writes to
+ *		       bit 18 to flush a packet from Rx DPRAM immediately. The
+ *		       changes for it are done in the function
+ *		       XEmacPs_IntrHandler.
+ * 1.05a asa  09/23/13 Cache operations on BDs are not required and hence
+ *		       removed. It is expected that all BDs are allocated in
+ *		       from uncached area.
+ * 1.06a asa  11/02/13 Changed the value for XEMACPS_RXBUF_LEN_MASK from 0x3fff
+ *				to 0x1fff. This fixes the CR#744902.
+ *			  Made changes in example file xemacps_example.h to fix compilation
+ *			  issues with iarcc compiler.
+ * 2.0   adk  10/12/13 Updated as per the New Tcl API's
+ * 2.1   adk  11/08/14 Fixed the CR#811288. Changes are made in the driver tcl file.
+ * 2.1   bss  09/08/14 Modified driver tcl to fix CR#820349 to export phy
+ *		       address in xparameters.h when GMII to RGMII converter
+ *		       is present in hw.
+ * 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification and 64-bit
+ *		       changes.
+ * 2.2   adk  29/10/14 Fixed CR#827686 when PCS/PMA core is configured with
+ *                    1000BASE-X mode export proper values to the xparameters.h
+ *                    file. Changes are made in the driver tcl file.
+ * 3.0   adk  08/1/15  Don't include gem in peripheral test when gem is
+ *                    configured with PCS/PMA Core. Changes are made in the
+ *		       test app tcl(CR:827686).
+ * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+ * 3.0   hk   03/18/15 Added support for jumbo frames. Increase AHB burst.
+ *                     Disable extended mode. Perform all 64 bit changes under
+ *                     check for arch64.
+ *                     Remove "used bit set" from TX error interrupt masks.
+ * 3.1   hk   07/27/15 Do not call error handler with '0' error code when
+ *                     there is no error. CR# 869403
+ *            08/10/15 Update upper 32 bit tx and rx queue ptr registers.
+ * 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
+ * 3.4   ms   01/23/17 Modified xil_printf statement in main function for all
+ *                     examples to ensure that "Successfully ran" and "Failed"
+ *                     strings are available in all examples. This is a fix
+ *                     for CR-965028.
+ *       ms   03/17/17 Modified text file in examples folder for doxygen
+ *                     generation.
+ *       ms   04/05/17 Added tabspace for return statements in functions of
+ *                     xemacps_ieee1588_example.c for proper documentation
+ *                     while generating doxygen.
+ * 3.5   hk   08/14/17 Update cache coherency information of the interface in
+ *                     its config structure.
+ * 3.6   rb   09/08/17 HwCnt variable (in XEmacPs_BdRing structure) is
+ *		       changed to volatile.
+ *		       Add API XEmacPs_BdRingPtrReset() to reset pointers
+ * 3.8   hk   07/19/18 Fixed CPP, GCC and doxygen warnings - CR-1006327
+ *	 hk   09/17/18 Fix PTP interrupt masks and cleanup comments.
+ * 3.9   hk   01/23/19 Add RX watermark support
+ * 3.11  sd   02/14/20 Add clock support
+ * 3.13  nsk  12/14/20 Updated the tcl to not to use the instance names.
+ *
+ * 
+ * + ****************************************************************************/ + +#ifndef XEMACPS_H /* prevent circular inclusions */ +#define XEMACPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xemacps_hw.h" +#include "xemacps_bd.h" +#include "xemacps_bdring.h" +#if defined (XCLOCKING) +#include "xil_clocking.h" +#endif + +/************************** Constant Definitions ****************************/ + +/* + * Device information + */ +#define XEMACPS_DEVICE_NAME "xemacps" +#define XEMACPS_DEVICE_DESC "Xilinx PS 10/100/1000 MAC" + + +/** @name Configuration options + * + * Device configuration options. See the XEmacPs_SetOptions(), + * XEmacPs_ClearOptions() and XEmacPs_GetOptions() for information on how to + * use options. + * + * The default state of the options are noted and are what the device and + * driver will be set to after calling XEmacPs_Reset() or + * XEmacPs_Initialize(). + * + * @{ + */ + +#define XEMACPS_PROMISC_OPTION 0x00000001U +/**< Accept all incoming packets. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_FRAME1536_OPTION 0x00000002U +/**< Frame larger than 1516 support for Tx & Rx. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_VLAN_OPTION 0x00000004U +/**< VLAN Rx & Tx frame support. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_FLOW_CONTROL_OPTION 0x00000010U +/**< Enable recognition of flow control frames on Rx + * This option defaults to enabled (set) */ + +#define XEMACPS_FCS_STRIP_OPTION 0x00000020U +/**< Strip FCS and PAD from incoming frames. Note: PAD from VLAN frames is not + * stripped. + * This option defaults to enabled (set) */ + +#define XEMACPS_FCS_INSERT_OPTION 0x00000040U +/**< Generate FCS field and add PAD automatically for outgoing frames. + * This option defaults to disabled (cleared) */ + +#define XEMACPS_LENTYPE_ERR_OPTION 0x00000080U +/**< Enable Length/Type error checking for incoming frames. When this option is + * set, the MAC will filter frames that have a mismatched type/length field + * and if XEMACPS_REPORT_RXERR_OPTION is set, the user is notified when these + * types of frames are encountered. When this option is cleared, the MAC will + * allow these types of frames to be received. + * + * This option defaults to disabled (cleared) */ + +#define XEMACPS_TRANSMITTER_ENABLE_OPTION 0x00000100U +/**< Enable the transmitter. + * This option defaults to enabled (set) */ + +#define XEMACPS_RECEIVER_ENABLE_OPTION 0x00000200U +/**< Enable the receiver + * This option defaults to enabled (set) */ + +#define XEMACPS_BROADCAST_OPTION 0x00000400U +/**< Allow reception of the broadcast address + * This option defaults to enabled (set) */ + +#define XEMACPS_MULTICAST_OPTION 0x00000800U +/**< Allows reception of multicast addresses programmed into hash + * This option defaults to disabled (clear) */ + +#define XEMACPS_RX_CHKSUM_ENABLE_OPTION 0x00001000U +/**< Enable the RX checksum offload + * This option defaults to enabled (set) */ + +#define XEMACPS_TX_CHKSUM_ENABLE_OPTION 0x00002000U +/**< Enable the TX checksum offload + * This option defaults to enabled (set) */ + +#define XEMACPS_JUMBO_ENABLE_OPTION 0x00004000U +#define XEMACPS_SGMII_ENABLE_OPTION 0x00008000U + +#define XEMACPS_DEFAULT_OPTIONS \ + ((u32)XEMACPS_FLOW_CONTROL_OPTION | \ + (u32)XEMACPS_FCS_INSERT_OPTION | \ + (u32)XEMACPS_FCS_STRIP_OPTION | \ + (u32)XEMACPS_BROADCAST_OPTION | \ + (u32)XEMACPS_LENTYPE_ERR_OPTION | \ + (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION | \ + (u32)XEMACPS_RECEIVER_ENABLE_OPTION | \ + (u32)XEMACPS_RX_CHKSUM_ENABLE_OPTION | \ + (u32)XEMACPS_TX_CHKSUM_ENABLE_OPTION) + +/**< Default options set when device is initialized or reset */ +/*@}*/ + +/** @name Callback identifiers + * + * These constants are used as parameters to XEmacPs_SetHandler() + * @{ + */ +#define XEMACPS_HANDLER_DMASEND 1U +#define XEMACPS_HANDLER_DMARECV 2U +#define XEMACPS_HANDLER_ERROR 3U +/*@}*/ + +/* Constants to determine the configuration of the hardware device. They are + * used to allow the driver to verify it can operate with the hardware. + */ +#define XEMACPS_MDIO_DIV_DFT MDC_DIV_32 /**< Default MDIO clock divisor */ + +/* The next few constants help upper layers determine the size of memory + * pools used for Ethernet buffers and descriptor lists. + */ +#define XEMACPS_MAC_ADDR_SIZE 6U /* size of Ethernet header */ + +#define XEMACPS_MTU 1500U /* max MTU size of Ethernet frame */ +#define XEMACPS_MTU_JUMBO 10240U /* max MTU size of jumbo frame */ +#define XEMACPS_HDR_SIZE 14U /* size of Ethernet header */ +#define XEMACPS_HDR_VLAN_SIZE 18U /* size of Ethernet header with VLAN */ +#define XEMACPS_TRL_SIZE 4U /* size of Ethernet trailer (FCS) */ +#define XEMACPS_MAX_FRAME_SIZE (XEMACPS_MTU + XEMACPS_HDR_SIZE + \ + XEMACPS_TRL_SIZE) +#define XEMACPS_MAX_VLAN_FRAME_SIZE (XEMACPS_MTU + XEMACPS_HDR_SIZE + \ + XEMACPS_HDR_VLAN_SIZE + XEMACPS_TRL_SIZE) +#define XEMACPS_MAX_VLAN_FRAME_SIZE_JUMBO (XEMACPS_MTU_JUMBO + XEMACPS_HDR_SIZE + \ + XEMACPS_HDR_VLAN_SIZE + XEMACPS_TRL_SIZE) + +/* DMACR Bust length hash defines */ + +#define XEMACPS_SINGLE_BURST 0x00000001 +#define XEMACPS_4BYTE_BURST 0x00000004 +#define XEMACPS_8BYTE_BURST 0x00000008 +#define XEMACPS_16BYTE_BURST 0x00000010 + + +/**************************** Type Definitions ******************************/ +/** @name Typedefs for callback functions + * + * These callbacks are invoked in interrupt context. + * @{ + */ +/** + * Callback invoked when frame(s) have been sent or received in interrupt + * driven DMA mode. To set the send callback, invoke XEmacPs_SetHandler(). + * + * @param CallBackRef is user data assigned when the callback was set. + * + * @note + * See xemacps_hw.h for bitmasks definitions and the device hardware spec for + * further information on their meaning. + * + */ +typedef void (*XEmacPs_Handler) (void *CallBackRef); + +/** + * Callback when an asynchronous error occurs. To set this callback, invoke + * XEmacPs_SetHandler() with XEMACPS_HANDLER_ERROR in the HandlerType + * parameter. + * + * @param CallBackRef is user data assigned when the callback was set. + * @param Direction defines either receive or transmit error(s) has occurred. + * @param ErrorWord definition varies with Direction + * + */ +typedef void (*XEmacPs_ErrHandler) (void *CallBackRef, u8 Direction, + u32 ErrorWord); + +/*@}*/ + +/** + * This typedef contains configuration information for a device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddress;/**< Physical base address of IPIF registers */ + u8 IsCacheCoherent; /**< Applicable only to A53 in EL1 mode; + * describes whether Cache Coherent or not */ +#if defined (XCLOCKING) + u32 RefClk; /**< Input clock */ +#endif + u16 S1GDiv0; /**< 1Gbps Clock Divider 0 */ + u8 S1GDiv1; /**< 1Gbps Clock Divider 1 */ + u16 S100MDiv0; /**< 100Mbps Clock Divider 0 */ + u8 S100MDiv1; /**< 100Mbps Clock Divider 1 */ + u16 S10MDiv0; /**< 10Mbps Clock Divider 0 */ + u8 S10MDiv1; /**< 10Mbps Clock Divider 1 */ +} XEmacPs_Config; + + +/** + * The XEmacPs driver instance data. The user is required to allocate a + * structure of this type for every XEmacPs device in the system. A pointer + * to a structure of this type is then passed to the driver API functions. + */ +typedef struct XEmacPs_Instance { + XEmacPs_Config Config; /* Hardware configuration */ + u32 IsStarted; /* Device is currently started */ + u32 IsReady; /* Device is initialized and ready */ + u32 Options; /* Current options word */ + + XEmacPs_BdRing TxBdRing; /* Transmit BD ring */ + XEmacPs_BdRing RxBdRing; /* Receive BD ring */ + + XEmacPs_Handler SendHandler; + XEmacPs_Handler RecvHandler; + void *SendRef; + void *RecvRef; + + XEmacPs_ErrHandler ErrorHandler; + void *ErrorRef; + u32 Version; + u32 RxBufMask; + u32 MaxMtuSize; + u32 MaxFrameSize; + u32 MaxVlanFrameSize; + +} XEmacPs; + + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* Retrieve the Tx ring object. This object can be used in the various Ring +* API functions. +* +* @param InstancePtr is the DMA channel to operate on. +* +* @return TxBdRing attribute +* +* @note +* C-style signature: +* XEmacPs_BdRing XEmacPs_GetTxRing(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_GetTxRing(InstancePtr) ((InstancePtr)->TxBdRing) + +/****************************************************************************/ +/** +* Retrieve the Rx ring object. This object can be used in the various Ring +* API functions. +* +* @param InstancePtr is the DMA channel to operate on. +* +* @return RxBdRing attribute +* +* @note +* C-style signature: +* XEmacPs_BdRing XEmacPs_GetRxRing(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_GetRxRing(InstancePtr) ((InstancePtr)->RxBdRing) + +/****************************************************************************/ +/** +* +* Enable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to enable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntEnable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntEnable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_IER_OFFSET, \ + ((Mask) & XEMACPS_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* Disable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to disable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntDisable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntDisable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_IDR_OFFSET, \ + ((Mask) & XEMACPS_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* Enable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to enable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntQ1Enable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntQ1Enable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_INTQ1_IER_OFFSET, \ + ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* Disable interrupts specified in Mask. The corresponding interrupt for +* each bit set to 1 in Mask, will be enabled. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Mask contains a bit mask of interrupts to disable. The mask can +* be formed using a set of bitwise or'd values. +* +* @note +* The state of the transmitter and receiver are not modified by this function. +* C-style signature +* void XEmacPs_IntDisable(XEmacPs *InstancePtr, u32 Mask) +* +*****************************************************************************/ +#define XEmacPs_IntQ1Disable(InstancePtr, Mask) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_INTQ1_IDR_OFFSET, \ + ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK)); + +/****************************************************************************/ +/** +* +* This macro triggers trasmit circuit to send data currently in TX buffer(s). +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return +* +* @note +* +* Signature: void XEmacPs_Transmit(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_Transmit(InstancePtr) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_NWCTRL_OFFSET, \ + (XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK)) + +/****************************************************************************/ +/** +* +* This macro determines if the device is configured with checksum offloading +* on the receive channel +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return +* +* Boolean TRUE if the device is configured with checksum offloading, or +* FALSE otherwise. +* +* @note +* +* Signature: u32 XEmacPs_IsRxCsum(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_IsRxCsum(InstancePtr) \ + ((XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_NWCFG_OFFSET) & XEMACPS_NWCFG_RXCHKSUMEN_MASK) != 0U \ + ? TRUE : FALSE) + +/****************************************************************************/ +/** +* +* This macro determines if the device is configured with checksum offloading +* on the transmit channel +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return +* +* Boolean TRUE if the device is configured with checksum offloading, or +* FALSE otherwise. +* +* @note +* +* Signature: u32 XEmacPs_IsTxCsum(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_IsTxCsum(InstancePtr) \ + ((XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_DMACR_OFFSET) & XEMACPS_DMACR_TCPCKSUM_MASK) != 0U \ + ? TRUE : FALSE) + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* This macro sets RX watermark register. +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* @param High is the non-zero RX high watermark value. When SRAM fill level +* is above this, a pause frame will be sent. +* @param Low is the non-zero RX low watermark value. When SRAM fill level +* is below this, a zero length pause frame will be sent IF the last +* pause frame sent was non-zero. +* +* @return None +* +* @note +* +* Signature: void XEmacPs_SetRXWatermark(XEmacPs *InstancePtr, u16 High, +* u16 Low) +* +*****************************************************************************/ +#define XEmacPs_SetRXWatermark(InstancePtr, High, Low) \ + XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_RXWATERMARK_OFFSET, \ + (High & XEMACPS_RXWM_HIGH_MASK) | \ + ((Low << XEMACPS_RXWM_LOW_SHFT_MSK) & XEMACPS_RXWM_LOW_MASK) |) + +/****************************************************************************/ +/** +* +* This macro gets RX watermark register. +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* +* @return RX watermark register value +* +* @note +* +* Signature: void XEmacPs_GetRXWatermark(XEmacPs *InstancePtr) +* +*****************************************************************************/ +#define XEmacPs_GetRXWatermark(InstancePtr) \ + XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XEMACPS_RXWATERMARK_OFFSET) +/* + * Initialization functions in xemacps.c + */ +LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config *CfgPtr, + UINTPTR EffectiveAddress); +void XEmacPs_Start(XEmacPs *InstancePtr); +void XEmacPs_Stop(XEmacPs *InstancePtr); +void XEmacPs_Reset(XEmacPs *InstancePtr); +void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum, + u16 Direction); + +/* + * Lookup configuration in xemacps_sinit.c + */ +XEmacPs_Config *XEmacPs_LookupConfig(u16 DeviceId); + +/* + * Interrupt-related functions in xemacps_intr.c + * DMA only and FIFO is not supported. This DMA does not support coalescing. + */ +LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType, + void *FuncPointer, void *CallBackRef); +void XEmacPs_IntrHandler(void *XEmacPsPtr); + +/* + * MAC configuration/control functions in XEmacPs_control.c + */ +LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options); +LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options); +u32 XEmacPs_GetOptions(XEmacPs *InstancePtr); + +LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index); +LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr); +void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index); + +LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr); +void XEmacPs_ClearHash(XEmacPs *InstancePtr); +void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr); + +void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, + XEmacPs_MdcDiv Divisor); +void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed); +u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr); +LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, + u32 RegisterNum, u16 *PhyDataPtr); +LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress, + u32 RegisterNum, u16 PhyData); +LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index); + +LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr); +void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bd.h b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bd.h new file mode 100644 index 0000000..aff79ff --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bd.h @@ -0,0 +1,762 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xemacps_bd.h +* @addtogroup emacps_v3_16 +* @{ + * + * This header provides operations to manage buffer descriptors in support + * of scatter-gather DMA. + * + * The API exported by this header defines abstracted macros that allow the + * user to read/write specific BD fields. + * + * Buffer Descriptors + * + * A buffer descriptor (BD) defines a DMA transaction. The macros defined by + * this header file allow access to most fields within a BD to tailor a DMA + * transaction according to user and hardware requirements. See the hardware + * IP DMA spec for more information on BD fields and how they affect transfers. + * + * The XEmacPs_Bd structure defines a BD. The organization of this structure + * is driven mainly by the hardware for use in scatter-gather DMA transfers. + * + * Performance + * + * Limiting I/O to BDs can improve overall performance of the DMA channel. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wsy  01/10/10 First release
+ * 2.1   srt  07/15/14 Add support for Zynq Ultrascale MP GEM specification
+ *                     and 64-bit changes.
+ * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+ * 3.0   hk   02/20/15 Added support for jumbo frames.
+ *                     Disable extended mode. Perform all 64 bit changes under
+ *                     check for arch64.
+ * 3.2   hk   11/18/15 Change BD typedef and number of words.
+ * 3.8   hk   08/18/18 Remove duplicate definition of XEmacPs_BdSetLength
+ * 3.8   mus  11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
+ *
+ * 
+ * + * *************************************************************************** + */ + +#ifndef XEMACPS_BD_H /* prevent circular inclusions */ +#define XEMACPS_BD_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ +#ifdef __aarch64__ +/* Minimum BD alignment */ +#define XEMACPS_DMABD_MINIMUM_ALIGNMENT 64U +#define XEMACPS_BD_NUM_WORDS 4U +#else +/* Minimum BD alignment */ +#define XEMACPS_DMABD_MINIMUM_ALIGNMENT 4U +#define XEMACPS_BD_NUM_WORDS 2U +#endif + +/** + * The XEmacPs_Bd is the type for buffer descriptors (BDs). + */ +typedef u32 XEmacPs_Bd[XEMACPS_BD_NUM_WORDS]; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * Zero out BD fields + * + * @param BdPtr is the BD pointer to operate on + * + * @return Nothing + * + * @note + * C-style signature: + * void XEmacPs_BdClear(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClear(BdPtr) \ + memset((BdPtr), 0, sizeof(XEmacPs_Bd)) + +/****************************************************************************/ +/** +* +* Read the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to read +* @param Offset is the word offset to be read +* +* @return The 32-bit value of the field +* +* @note +* C-style signature: +* u32 XEmacPs_BdRead(UINTPTR BaseAddress, UINTPTR Offset) +* +*****************************************************************************/ +#define XEmacPs_BdRead(BaseAddress, Offset) \ + (*(u32 *)((UINTPTR)((void*)(BaseAddress)) + (u32)(Offset))) + +/****************************************************************************/ +/** +* +* Write the given Buffer Descriptor word. +* +* @param BaseAddress is the base address of the BD to write +* @param Offset is the word offset to be written +* @param Data is the 32-bit value to write to the field +* +* @return None. +* +* @note +* C-style signature: +* void XEmacPs_BdWrite(UINTPTR BaseAddress, UINTPTR Offset, UINTPTR Data) +* +*****************************************************************************/ +#define XEmacPs_BdWrite(BaseAddress, Offset, Data) \ + (*(u32 *)((UINTPTR)(void*)(BaseAddress) + (u32)(Offset)) = (u32)(Data)) + +/*****************************************************************************/ +/** + * Set the BD's Address field (word 0). + * + * @param BdPtr is the BD pointer to operate on + * @param Addr is the value to write to BD's status field. + * + * @note : + * + * C-style signature: + * void XEmacPs_BdSetAddressTx(XEmacPs_Bd* BdPtr, UINTPTR Addr) + * + *****************************************************************************/ +#if defined(__aarch64__) || defined(__arch64__) +#define XEmacPs_BdSetAddressTx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + (u32)((Addr) & ULONG64_LO_MASK)); \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET, \ + (u32)(((Addr) & ULONG64_HI_MASK) >> 32U)); +#else +#define XEmacPs_BdSetAddressTx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, (u32)(Addr)) +#endif + +/*****************************************************************************/ +/** + * Set the BD's Address field (word 0). + * + * @param BdPtr is the BD pointer to operate on + * @param Addr is the value to write to BD's status field. + * + * @note : Due to some bits are mixed within receive BD's address field, + * read-modify-write is performed. + * + * C-style signature: + * void XEmacPs_BdSetAddressRx(XEmacPs_Bd* BdPtr, UINTPTR Addr) + * + *****************************************************************************/ +#ifdef __aarch64__ +#define XEmacPs_BdSetAddressRx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + ~XEMACPS_RXBUF_ADD_MASK) | ((u32)((Addr) & ULONG64_LO_MASK)))); \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET, \ + (u32)(((Addr) & ULONG64_HI_MASK) >> 32U)); +#else +#define XEmacPs_BdSetAddressRx(BdPtr, Addr) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + ~XEMACPS_RXBUF_ADD_MASK) | (UINTPTR)(Addr))) +#endif + +/*****************************************************************************/ +/** + * Set the BD's Status field (word 1). + * + * @param BdPtr is the BD pointer to operate on + * @param Data is the value to write to BD's status field. + * + * @note + * C-style signature: + * void XEmacPs_BdSetStatus(XEmacPs_Bd* BdPtr, UINTPTR Data) + * + *****************************************************************************/ +#define XEmacPs_BdSetStatus(BdPtr, Data) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | (Data)) + + +/*****************************************************************************/ +/** + * Retrieve the BD's Packet DMA transfer status word (word 1). + * + * @param BdPtr is the BD pointer to operate on + * + * @return Status word + * + * @note + * C-style signature: + * u32 XEmacPs_BdGetStatus(XEmacPs_Bd* BdPtr) + * + * Due to the BD bit layout differences in transmit and receive. User's + * caution is required. + *****************************************************************************/ +#define XEmacPs_BdGetStatus(BdPtr) \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) + + +/*****************************************************************************/ +/** + * Get the address (bits 0..31) of the BD's buffer address (word 0) + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetBufAddr(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#if defined(__aarch64__) || defined(__arch64__) +#define XEmacPs_BdGetBufAddr(BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) | \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET)) << 32U) +#else +#define XEmacPs_BdGetBufAddr(BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET)) +#endif + +/*****************************************************************************/ +/** + * Set transfer length in bytes for the given BD. The length must be set each + * time a BD is submitted to hardware. + * + * @param BdPtr is the BD pointer to operate on + * @param LenBytes is the number of bytes to transfer. + * + * @note + * C-style signature: + * void XEmacPs_BdSetLength(XEmacPs_Bd* BdPtr, u32 LenBytes) + * + *****************************************************************************/ +#define XEmacPs_BdSetLength(BdPtr, LenBytes) \ + XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_LEN_MASK) | (LenBytes))) + + +/*****************************************************************************/ +/** + * Retrieve the BD length field. + * + * For Tx channels, the returned value is the same as that written with + * XEmacPs_BdSetLength(). + * + * For Rx channels, the returned value is the size of the received packet. + * + * @param BdPtr is the BD pointer to operate on + * + * @return Length field processed by hardware or set by + * XEmacPs_BdSetLength(). + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetLength(XEmacPs_Bd* BdPtr) + * XEAMCPS_RXBUF_LEN_MASK is same as XEMACPS_TXBUF_LEN_MASK. + * + *****************************************************************************/ +#define XEmacPs_BdGetLength(BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_LEN_MASK) + +/*****************************************************************************/ +/** + * Retrieve the RX frame size. + * + * The returned value is the size of the received packet. + * This API supports jumbo frame sizes if enabled. + * + * @param InstancePtr is the pointer to XEmacps instance + * + * @param BdPtr is the BD pointer to operate on + * + * @return Length field processed by hardware or set by + * XEmacPs_BdSetLength(). + * + * @note + * C-style signature: + * UINTPTR XEmacPs_GetRxFrameSize(XEmacPs* InstancePtr, XEmacPs_Bd* BdPtr) + * RxBufMask is dependent on whether jumbo is enabled or not. + * + *****************************************************************************/ +#define XEmacPs_GetRxFrameSize(InstancePtr, BdPtr) \ + (XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + (InstancePtr)->RxBufMask) + +/*****************************************************************************/ +/** + * Test whether the given BD has been marked as the last BD of a packet. + * + * @param BdPtr is the BD pointer to operate on + * + * @return TRUE if BD represents the "Last" BD of a packet, FALSE otherwise + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsLast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsLast(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_EOF_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Tell the DMA engine that the given transmit BD marks the end of the current + * packet to be processed. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetLast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdSetLast(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_LAST_MASK)) + + +/*****************************************************************************/ +/** + * Tell the DMA engine that the current packet does not end with the given + * BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdClearLast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearLast(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_LAST_MASK)) + + +/*****************************************************************************/ +/** + * Set this bit to mark the last descriptor in the receive buffer descriptor + * list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetRxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +/*#define XEmacPs_BdSetRxWrap(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) | \ + XEMACPS_RXBUF_WRAP_MASK)) +*/ + +/*****************************************************************************/ +/** + * Determine the wrap bit of the receive BD which indicates end of the + * BD list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * u8 XEmacPs_BdIsRxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxWrap(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + XEMACPS_RXBUF_WRAP_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Sets this bit to mark the last descriptor in the transmit buffer + * descriptor list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetTxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +/*#define XEmacPs_BdSetTxWrap(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_WRAP_MASK)) +*/ + +/*****************************************************************************/ +/** + * Determine the wrap bit of the transmit BD which indicates end of the + * BD list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * u8 XEmacPs_BdGetTxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxWrap(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_WRAP_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/* + * Must clear this bit to enable the MAC to write data to the receive + * buffer. Hardware sets this bit once it has successfully written a frame to + * memory. Once set, software has to clear the bit before the buffer can be + * used again. This macro clear the new bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdClearRxNew(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearRxNew(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + ~XEMACPS_RXBUF_NEW_MASK)) + + +/*****************************************************************************/ +/** + * Determine the new bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxNew(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxNew(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) & \ + XEMACPS_RXBUF_NEW_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Software sets this bit to disable the buffer to be read by the hardware. + * Hardware sets this bit for the first buffer of a frame once it has been + * successfully transmitted. This macro sets this bit of transmit BD to avoid + * confusion. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetTxUsed(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdSetTxUsed(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_USED_MASK)) + + +/*****************************************************************************/ +/** + * Software clears this bit to enable the buffer to be read by the hardware. + * Hardware sets this bit for the first buffer of a frame once it has been + * successfully transmitted. This macro clears this bit of transmit BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdClearTxUsed(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearTxUsed(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_USED_MASK)) + + +/*****************************************************************************/ +/** + * Determine the used bit of the transmit BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxUsed(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxUsed(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_USED_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if a frame fails to be transmitted due to too many retries. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxRetry(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxRetry(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_RETRY_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if a frame fails to be transmitted due to data can not be + * feteched in time or buffers are exhausted. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxUrun(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxUrun(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_URUN_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if a frame fails to be transmitted due to buffer is exhausted + * mid-frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsTxExh(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsTxExh(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_TXBUF_EXH_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Sets this bit, no CRC will be appended to the current frame. This control + * bit must be set for the first buffer in a frame and will be ignored for + * the subsequent buffers of a frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * This bit must be clear when using the transmit checksum generation offload, + * otherwise checksum generation and substitution will not occur. + * + * C-style signature: + * UINTPTR XEmacPs_BdSetTxNoCRC(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdSetTxNoCRC(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | \ + XEMACPS_TXBUF_NOCRC_MASK)) + + +/*****************************************************************************/ +/** + * Clear this bit, CRC will be appended to the current frame. This control + * bit must be set for the first buffer in a frame and will be ignored for + * the subsequent buffers of a frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * This bit must be clear when using the transmit checksum generation offload, + * otherwise checksum generation and substitution will not occur. + * + * C-style signature: + * UINTPTR XEmacPs_BdClearTxNoCRC(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdClearTxNoCRC(BdPtr) \ + (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET, \ + XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + ~XEMACPS_TXBUF_NOCRC_MASK)) + + +/*****************************************************************************/ +/** + * Determine the broadcast bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxBcast(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxBcast(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_BCAST_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the multicast hash bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxMultiHash(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxMultiHash(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_MULTIHASH_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the unicast hash bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxUniHash(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxUniHash(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_UNIHASH_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if the received frame is a VLAN Tagged frame. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxVlan(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxVlan(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_VLAN_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if the received frame has Type ID of 8100h and null VLAN + * identifier(Priority tag). + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxPri(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxPri(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_PRI_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine if the received frame's Concatenation Format Indicator (CFI) of + * the frames VLANTCI field was set. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdIsRxCFI(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxCFI(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_CFI_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the End Of Frame (EOF) bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetRxEOF(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxEOF(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_EOF_MASK)!=0U ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * Determine the Start Of Frame (SOF) bit of the receive BD. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * UINTPTR XEmacPs_BdGetRxSOF(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +#define XEmacPs_BdIsRxSOF(BdPtr) \ + ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) & \ + XEMACPS_RXBUF_SOF_MASK)!=0U ? TRUE : FALSE) + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bdring.c b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bdring.c new file mode 100644 index 0000000..5a355ff --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bdring.c @@ -0,0 +1,1090 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_bdring.c +* @addtogroup emacps_v3_16 +* @{ +* +* This file implements buffer descriptor ring related functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 1.00a asa  11/21/11 The function XEmacPs_BdRingFromHwTx is modified.
+*		      Earlier it used to search in "BdLimit" number of BDs to
+*		      know which BDs are processed. Now one more check is
+*		      added. It looks for BDs till the current BD pointer
+*		      reaches HwTail. By doing this processing time is saved.
+* 1.00a asa  01/24/12 The function XEmacPs_BdRingFromHwTx in file
+*		      xemacps_bdring.c is modified. Now start of packet is
+*		      searched for returning the number of BDs processed.
+* 1.05a asa  09/23/13 Cache operations on BDs are not required and hence
+*		      removed. It is expected that all BDs are allocated in
+*		      from uncached area. Fix for CR #663885.
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp architecture.
+* 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.6   rb   09/08/17 Add XEmacPs_BdRingPtrReset() API to reset BD ring
+* 		      pointers
+*
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xil_cache.h" +#include "xemacps_hw.h" +#include "xemacps_bd.h" +#include "xemacps_bdring.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************************************************************** + * Compute the virtual address of a descriptor from its physical address + * + * @param BdPtr is the physical address of the BD + * + * @returns Virtual address of BdPtr + * + * @note Assume BdPtr is always a valid BD in the ring + ****************************************************************************/ +#define XEMACPS_PHYS_TO_VIRT(BdPtr) \ + ((UINTPTR)(BdPtr) + (RingPtr->BaseBdAddr - RingPtr->PhysBaseAddr)) + +/**************************************************************************** + * Compute the physical address of a descriptor from its virtual address + * + * @param BdPtr is the physical address of the BD + * + * @returns Physical address of BdPtr + * + * @note Assume BdPtr is always a valid BD in the ring + ****************************************************************************/ +#define XEMACPS_VIRT_TO_PHYS(BdPtr) \ + ((UINTPTR)(BdPtr) - (RingPtr->BaseBdAddr - RingPtr->PhysBaseAddr)) + +/**************************************************************************** + * Move the BdPtr argument ahead an arbitrary number of BDs wrapping around + * to the beginning of the ring if needed. + * + * We know if a wrapaound should occur if the new BdPtr is greater than + * the high address in the ring OR if the new BdPtr crosses over the + * 0xFFFFFFFF to 0 boundary. The latter test is a valid one since we do not + * allow a BD space to span this boundary. + * + * @param RingPtr is the ring BdPtr appears in + * @param BdPtr on input is the starting BD position and on output is the + * final BD position + * @param NumBd is the number of BD spaces to increment + * + ****************************************************************************/ +#define XEMACPS_RING_SEEKAHEAD(RingPtr, BdPtr, NumBd) \ + { \ + UINTPTR Addr = (UINTPTR)(void *)(BdPtr); \ + \ + Addr += ((RingPtr)->Separation * (NumBd)); \ + if ((Addr > (RingPtr)->HighBdAddr) || ((UINTPTR)(void *)(BdPtr) > Addr)) \ + { \ + Addr -= (RingPtr)->Length; \ + } \ + \ + (BdPtr) = (XEmacPs_Bd*)(void *)Addr; \ + } + +/**************************************************************************** + * Move the BdPtr argument backwards an arbitrary number of BDs wrapping + * around to the end of the ring if needed. + * + * We know if a wrapaound should occur if the new BdPtr is less than + * the base address in the ring OR if the new BdPtr crosses over the + * 0xFFFFFFFF to 0 boundary. The latter test is a valid one since we do not + * allow a BD space to span this boundary. + * + * @param RingPtr is the ring BdPtr appears in + * @param BdPtr on input is the starting BD position and on output is the + * final BD position + * @param NumBd is the number of BD spaces to increment + * + ****************************************************************************/ +#define XEMACPS_RING_SEEKBACK(RingPtr, BdPtr, NumBd) \ + { \ + UINTPTR Addr = (UINTPTR)(void *)(BdPtr); \ + \ + Addr -= ((RingPtr)->Separation * (NumBd)); \ + if ((Addr < (RingPtr)->BaseBdAddr) || ((UINTPTR)(void*)(BdPtr) < Addr)) \ + { \ + Addr += (RingPtr)->Length; \ + } \ + \ + (BdPtr) = (XEmacPs_Bd*)(void*)Addr; \ + } + + +/************************** Function Prototypes ******************************/ + +static void XEmacPs_BdSetRxWrap(UINTPTR BdPtr); +static void XEmacPs_BdSetTxWrap(UINTPTR BdPtr); + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** + * Using a memory segment allocated by the caller, create and setup the BD list + * for the given DMA channel. + * + * @param RingPtr is the instance to be worked on. + * @param PhysAddr is the physical base address of user memory region. + * @param VirtAddr is the virtual base address of the user memory region. If + * address translation is not being utilized, then VirtAddr should be + * equivalent to PhysAddr. + * @param Alignment governs the byte alignment of individual BDs. This function + * will enforce a minimum alignment of 4 bytes with no maximum as long + * as it is specified as a power of 2. + * @param BdCount is the number of BDs to setup in the user memory region. It + * is assumed the region is large enough to contain the BDs. + * + * @return + * + * - XST_SUCCESS if initialization was successful + * - XST_NO_FEATURE if the provided instance is a non DMA type + * channel. + * - XST_INVALID_PARAM under any of the following conditions: + * 1) PhysAddr and/or VirtAddr are not aligned to the given Alignment + * parameter. + * 2) Alignment parameter does not meet minimum requirements or is not a + * power of 2 value. + * 3) BdCount is 0. + * - XST_DMA_SG_LIST_ERROR if the memory segment containing the list spans + * over address 0x00000000 in virtual address space. + * + * @note + * Make sure to pass in the right alignment value. + *****************************************************************************/ +LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr, + UINTPTR VirtAddr, u32 Alignment, u32 BdCount) +{ + u32 i; + UINTPTR BdVirtAddr; + UINTPTR BdPhyAddr; + UINTPTR VirtAddrLoc = VirtAddr; + + /* In case there is a failure prior to creating list, make sure the + * following attributes are 0 to prevent calls to other functions + * from doing anything. + */ + RingPtr->AllCnt = 0U; + RingPtr->FreeCnt = 0U; + RingPtr->HwCnt = 0U; + RingPtr->PreCnt = 0U; + RingPtr->PostCnt = 0U; + + /* Make sure Alignment parameter meets minimum requirements */ + if (Alignment < (u32)XEMACPS_DMABD_MINIMUM_ALIGNMENT) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Make sure Alignment is a power of 2 */ + if (((Alignment - 0x00000001U) & Alignment)!=0x00000000U) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Make sure PhysAddr and VirtAddr are on same Alignment */ + if (((PhysAddr % Alignment)!=(u32)0) || ((VirtAddrLoc % Alignment)!=(u32)0)) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Is BdCount reasonable? */ + if (BdCount == 0x00000000U) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Figure out how many bytes will be between the start of adjacent BDs */ + RingPtr->Separation = ((u32)sizeof(XEmacPs_Bd)); + + /* Must make sure the ring doesn't span address 0x00000000. If it does, + * then the next/prev BD traversal macros will fail. + */ + if (VirtAddrLoc > ((VirtAddrLoc + (RingPtr->Separation * BdCount)) - (u32)1)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + /* Initial ring setup: + * - Clear the entire space + * - Setup each BD's BDA field with the physical address of the next BD + */ + (void)memset((void *) VirtAddrLoc, 0, (RingPtr->Separation * BdCount)); + + BdVirtAddr = VirtAddrLoc; + BdPhyAddr = PhysAddr + RingPtr->Separation; + for (i = 1U; i < BdCount; i++) { + BdVirtAddr += RingPtr->Separation; + BdPhyAddr += RingPtr->Separation; + } + + /* Setup and initialize pointers and counters */ + RingPtr->RunState = (u32)(XST_DMA_SG_IS_STOPPED); + RingPtr->BaseBdAddr = VirtAddrLoc; + RingPtr->PhysBaseAddr = PhysAddr; + RingPtr->HighBdAddr = BdVirtAddr; + RingPtr->Length = + ((RingPtr->HighBdAddr - RingPtr->BaseBdAddr) + RingPtr->Separation); + RingPtr->AllCnt = (u32)BdCount; + RingPtr->FreeCnt = (u32)BdCount; + RingPtr->FreeHead = (XEmacPs_Bd *)(void *)VirtAddrLoc; + RingPtr->PreHead = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->HwHead = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->HwTail = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->PostHead = (XEmacPs_Bd *)VirtAddrLoc; + RingPtr->BdaRestart = (XEmacPs_Bd *)(void *)PhysAddr; + + return (LONG)(XST_SUCCESS); +} + + +/*****************************************************************************/ +/** + * Clone the given BD into every BD in the list. + * every field of the source BD is replicated in every BD of the list. + * + * This function can be called only when all BDs are in the free group such as + * they are immediately after initialization with XEmacPs_BdRingCreate(). + * This prevents modification of BDs while they are in use by hardware or the + * user. + * + * @param RingPtr is the pointer of BD ring instance to be worked on. + * @param SrcBdPtr is the source BD template to be cloned into the list. This + * BD will be modified. + * @param Direction is either XEMACPS_SEND or XEMACPS_RECV that indicates + * which direction. + * + * @return + * - XST_SUCCESS if the list was modified. + * - XST_DMA_SG_NO_LIST if a list has not been created. + * - XST_DMA_SG_LIST_ERROR if some of the BDs in this channel are under + * hardware or user control. + * - XST_DEVICE_IS_STARTED if the DMA channel has not been stopped. + * + *****************************************************************************/ +LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr, + u8 Direction) +{ + u32 i; + UINTPTR CurBd; + + /* Can't do this function if there isn't a ring */ + if (RingPtr->AllCnt == 0x00000000U) { + return (LONG)(XST_DMA_SG_NO_LIST); + } + + /* Can't do this function with the channel running */ + if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) { + return (LONG)(XST_DEVICE_IS_STARTED); + } + + /* Can't do this function with some of the BDs in use */ + if (RingPtr->FreeCnt != RingPtr->AllCnt) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Starting from the top of the ring, save BD.Next, overwrite the entire + * BD with the template, then restore BD.Next + */ + CurBd = RingPtr->BaseBdAddr; + for (i = 0U; i < RingPtr->AllCnt; i++) { + memcpy((void *)CurBd, SrcBdPtr, sizeof(XEmacPs_Bd)); + CurBd += RingPtr->Separation; + } + + CurBd -= RingPtr->Separation; + + if (Direction == XEMACPS_RECV) { + XEmacPs_BdSetRxWrap(CurBd); + } + else { + XEmacPs_BdSetTxWrap(CurBd); + } + + return (LONG)(XST_SUCCESS); +} + + +/*****************************************************************************/ +/** + * Reserve locations in the BD list. The set of returned BDs may be modified + * in preparation for future DMA transaction(s). Once the BDs are ready to be + * submitted to hardware, the user must call XEmacPs_BdRingToHw() in the same + * order which they were allocated here. Example: + * + *
+ *        NumBd = 2,
+ *        Status = XEmacPs_BdRingAlloc(MyRingPtr, NumBd, &MyBdSet),
+ *
+ *        if (Status != XST_SUCCESS)
+ *        {
+ *            *Not enough BDs available for the request*
+ *        }
+ *
+ *        CurBd = MyBdSet,
+ *        for (i=0; i
+ *
+ * A more advanced use of this function may allocate multiple sets of BDs.
+ * They must be allocated and given to hardware in the correct sequence:
+ * 
+ *        * Legal *
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
+ *
+ *        * Legal *
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2),
+ *
+ *        * Not legal *
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
+ * 
+ * + * Use the API defined in xemacps_bd.h to modify individual BDs. Traversal + * of the BD set can be done using XEmacPs_BdRingNext() and + * XEmacPs_BdRingPrev(). + * + * @param RingPtr is a pointer to the BD ring instance to be worked on. + * @param NumBd is the number of BDs to allocate + * @param BdSetPtr is an output parameter, it points to the first BD available + * for modification. + * + * @return + * - XST_SUCCESS if the requested number of BDs was returned in the BdSetPtr + * parameter. + * - XST_FAILURE if there were not enough free BDs to satisfy the request. + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + * @note Do not modify more BDs than the number requested with the NumBd + * parameter. Doing so will lead to data corruption and system + * instability. + * + *****************************************************************************/ +LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd ** BdSetPtr) +{ + LONG Status; + /* Enough free BDs available for the request? */ + if (RingPtr->FreeCnt < NumBd) { + Status = (LONG)(XST_FAILURE); + } else { + /* Set the return argument and move FreeHead forward */ + *BdSetPtr = RingPtr->FreeHead; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->FreeHead, NumBd); + RingPtr->FreeCnt -= NumBd; + RingPtr->PreCnt += NumBd; + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + +/*****************************************************************************/ +/** + * Fully or partially undo an XEmacPs_BdRingAlloc() operation. Use this + * function if all the BDs allocated by XEmacPs_BdRingAlloc() could not be + * transferred to hardware with XEmacPs_BdRingToHw(). + * + * This function helps out in situations when an unrelated error occurs after + * BDs have been allocated but before they have been given to hardware. + * An example of this type of error would be an OS running out of resources. + * + * This function is not the same as XEmacPs_BdRingFree(). The Free function + * returns BDs to the free list after they have been processed by hardware, + * while UnAlloc returns them before being processed by hardware. + * + * There are two scenarios where this function can be used. Full UnAlloc or + * Partial UnAlloc. A Full UnAlloc means all the BDs Alloc'd will be returned: + * + *
+ *    Status = XEmacPs_BdRingAlloc(MyRingPtr, 10, &BdPtr),
+ *        ...
+ *    if (Error)
+ *    {
+ *        Status = XEmacPs_BdRingUnAlloc(MyRingPtr, 10, &BdPtr),
+ *    }
+ * 
+ * + * A partial UnAlloc means some of the BDs Alloc'd will be returned: + * + *
+ *    Status = XEmacPs_BdRingAlloc(MyRingPtr, 10, &BdPtr),
+ *    BdsLeft = 10,
+ *    CurBdPtr = BdPtr,
+ *
+ *    while (BdsLeft)
+ *    {
+ *       if (Error)
+ *       {
+ *          Status = XEmacPs_BdRingUnAlloc(MyRingPtr, BdsLeft, CurBdPtr),
+ *       }
+ *
+ *       CurBdPtr = XEmacPs_BdRingNext(MyRingPtr, CurBdPtr),
+ *       BdsLeft--,
+ *    }
+ * 
+ * + * A partial UnAlloc must include the last BD in the list that was Alloc'd. + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param NumBd is the number of BDs to allocate + * @param BdSetPtr is an output parameter, it points to the first BD available + * for modification. + * + * @return + * - XST_SUCCESS if the BDs were unallocated. + * - XST_FAILURE if NumBd parameter was greater that the number of BDs in + * the preprocessing state. + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr) +{ + LONG Status; + (void) BdSetPtr; + Xil_AssertNonvoid(RingPtr != NULL); + Xil_AssertNonvoid(BdSetPtr != NULL); + + /* Enough BDs in the free state for the request? */ + if (RingPtr->PreCnt < NumBd) { + Status = (LONG)(XST_FAILURE); + } else { + /* Set the return argument and move FreeHead backward */ + XEMACPS_RING_SEEKBACK(RingPtr, (RingPtr->FreeHead), NumBd); + RingPtr->FreeCnt += NumBd; + RingPtr->PreCnt -= NumBd; + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + + +/*****************************************************************************/ +/** + * Enqueue a set of BDs to hardware that were previously allocated by + * XEmacPs_BdRingAlloc(). Once this function returns, the argument BD set goes + * under hardware control. Any changes made to these BDs after this point will + * corrupt the BD list leading to data corruption and system instability. + * + * The set will be rejected if the last BD of the set does not mark the end of + * a packet (see XEmacPs_BdSetLast()). + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param NumBd is the number of BDs in the set. + * @param BdSetPtr is the first BD of the set to commit to hardware. + * + * @return + * - XST_SUCCESS if the set of BDs was accepted and enqueued to hardware. + * - XST_FAILURE if the set of BDs was rejected because the last BD of the set + * did not have its "last" bit set. + * - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with + * XEmacPs_BdRingAlloc(). + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr) +{ + XEmacPs_Bd *CurBdPtr; + u32 i; + LONG Status; + /* if no bds to process, simply return. */ + if (0U == NumBd){ + Status = (LONG)(XST_SUCCESS); + } else { + /* Make sure we are in sync with XEmacPs_BdRingAlloc() */ + if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) { + Status = (LONG)(XST_DMA_SG_LIST_ERROR); + } else { + CurBdPtr = BdSetPtr; + for (i = 0U; i < NumBd; i++) { + CurBdPtr = (XEmacPs_Bd *)((void *)XEmacPs_BdRingNext(RingPtr, CurBdPtr)); + } + /* Adjust ring pointers & counters */ + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd); + RingPtr->PreCnt -= NumBd; + RingPtr->HwTail = CurBdPtr; + RingPtr->HwCnt += NumBd; + + Status = (LONG)(XST_SUCCESS); + } + } + return Status; +} + + +/*****************************************************************************/ +/** + * Returns a set of BD(s) that have been processed by hardware. The returned + * BDs may be examined to determine the outcome of the DMA transaction(s). + * Once the BDs have been examined, the user must call XEmacPs_BdRingFree() + * in the same order which they were retrieved here. Example: + * + *
+ *        NumBd = XEmacPs_BdRingFromHwTx(MyRingPtr, MaxBd, &MyBdSet),
+ *        if (NumBd == 0)
+ *        {
+ *           * hardware has nothing ready for us yet*
+ *        }
+ *
+ *        CurBd = MyBdSet,
+ *        for (i=0; i
+ *
+ * A more advanced use of this function may allocate multiple sets of BDs.
+ * They must be retrieved from hardware and freed in the correct sequence:
+ * 
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *
+ *        * Not legal *
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ * 
+ * + * If hardware has only partially completed a packet spanning multiple BDs, + * then none of the BDs for that packet will be included in the results. + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param BdLimit is the maximum number of BDs to return in the set. + * @param BdSetPtr is an output parameter, it points to the first BD available + * for examination. + * + * @return + * The number of BDs processed by hardware. A value of 0 indicates that no + * data is available. No more than BdLimit BDs will be returned. + * + * @note Treat BDs returned by this function as read-only. + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, + XEmacPs_Bd ** BdSetPtr) +{ + XEmacPs_Bd *CurBdPtr; + u32 BdStr = 0U; + u32 BdCount; + u32 BdPartialCount; + u32 Sop = 0U; + u32 Status; + u32 BdLimitLoc = BdLimit; + CurBdPtr = RingPtr->HwHead; + BdCount = 0U; + BdPartialCount = 0U; + + /* If no BDs in work group, then there's nothing to search */ + if (RingPtr->HwCnt == 0x00000000U) { + *BdSetPtr = NULL; + Status = 0U; + } else { + if (BdLimitLoc > RingPtr->HwCnt){ + BdLimitLoc = RingPtr->HwCnt; + } + /* Starting at HwHead, keep moving forward in the list until: + * - A BD is encountered with its new/used bit set which means + * hardware has not completed processing of that BD. + * - RingPtr->HwTail is reached and RingPtr->HwCnt is reached. + * - The number of requested BDs has been processed + */ + while (BdCount < BdLimitLoc) { + /* Read the status */ + if(CurBdPtr != NULL){ + BdStr = XEmacPs_BdRead(CurBdPtr, + XEMACPS_BD_STAT_OFFSET); + } + if ((Sop == 0x00000000U) && + ((BdStr & XEMACPS_TXBUF_USED_MASK)!=0x00000000U)){ + Sop = 1U; + } + if (Sop == 0x00000001U) { + BdCount++; + BdPartialCount++; + } + + /* hardware has processed this BD so check the "last" + * bit. If it is clear, then there are more BDs for + * the current packet. Keep a count of these partial + * packet BDs. + */ + if ((Sop == 0x00000001U) && + ((BdStr & XEMACPS_TXBUF_LAST_MASK)!=0x00000000U)) { + Sop = 0U; + BdPartialCount = 0U; + } + + /* Reached the end of the work group */ + if (CurBdPtr == RingPtr->HwTail) { + break; + } + /* Move on to next BD in work group */ + CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); + } + + /* Subtract off any partial packet BDs found */ + BdCount -= BdPartialCount; + + /* If BdCount is non-zero then BDs were found to return. + * Set return parameters, update pointers and counters, + * return success + */ + if (BdCount > 0x00000000U) { + *BdSetPtr = RingPtr->HwHead; + RingPtr->HwCnt -= BdCount; + RingPtr->PostCnt += BdCount; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); + Status = (BdCount); + } else { + *BdSetPtr = NULL; + Status = 0U; + } + } + return Status; +} + + +/*****************************************************************************/ +/** + * Returns a set of BD(s) that have been processed by hardware. The returned + * BDs may be examined to determine the outcome of the DMA transaction(s). + * Once the BDs have been examined, the user must call XEmacPs_BdRingFree() + * in the same order which they were retrieved here. Example: + * + *
+ *        NumBd = XEmacPs_BdRingFromHwRx(MyRingPtr, MaxBd, &MyBdSet),
+ *
+ *        if (NumBd == 0)
+ *        {
+ *           *hardware has nothing ready for us yet*
+ *        }
+ *
+ *        CurBd = MyBdSet,
+ *        for (i=0; i
+ *
+ * A more advanced use of this function may allocate multiple sets of BDs.
+ * They must be retrieved from hardware and freed in the correct sequence:
+ * 
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *
+ *        * Not legal *
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ * 
+ * + * If hardware has only partially completed a packet spanning multiple BDs, + * then none of the BDs for that packet will be included in the results. + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param BdLimit is the maximum number of BDs to return in the set. + * @param BdSetPtr is an output parameter, it points to the first BD available + * for examination. + * + * @return + * The number of BDs processed by hardware. A value of 0 indicates that no + * data is available. No more than BdLimit BDs will be returned. + * + * @note Treat BDs returned by this function as read-only. + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, + XEmacPs_Bd ** BdSetPtr) +{ + XEmacPs_Bd *CurBdPtr; + u32 BdStr = 0U; + u32 BdCount; + u32 BdPartialCount; + u32 Status; + + CurBdPtr = RingPtr->HwHead; + BdCount = 0U; + BdPartialCount = 0U; + + /* If no BDs in work group, then there's nothing to search */ + if (RingPtr->HwCnt == 0x00000000U) { + *BdSetPtr = NULL; + Status = 0U; + } else { + + /* Starting at HwHead, keep moving forward in the list until: + * - A BD is encountered with its new/used bit set which means + * hardware has completed processing of that BD. + * - RingPtr->HwTail is reached and RingPtr->HwCnt is reached. + * - The number of requested BDs has been processed + */ + while (BdCount < BdLimit) { + + /* Read the status */ + if(CurBdPtr!=NULL){ + BdStr = XEmacPs_BdRead(CurBdPtr, + XEMACPS_BD_STAT_OFFSET); + } + if ((!(XEmacPs_BdIsRxNew(CurBdPtr)))==TRUE) { + break; + } + + BdCount++; + + /* hardware has processed this BD so check the "last" + * bit. If it is clear, then there are more BDs for + * the current packet. Keep a count of these partial + * packet BDs. + */ + if ((BdStr & XEMACPS_RXBUF_EOF_MASK)!=0x00000000U) { + BdPartialCount = 0U; + } else { + BdPartialCount++; + } + + /* Reached the end of the work group */ + if (CurBdPtr == RingPtr->HwTail) { + break; + } + + /* Move on to next BD in work group */ + CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr); + } + + /* Subtract off any partial packet BDs found */ + BdCount -= BdPartialCount; + + /* If BdCount is non-zero then BDs were found to return. + * Set return parameters, update pointers and counters, + * return success + */ + if (BdCount > 0x00000000U) { + *BdSetPtr = RingPtr->HwHead; + RingPtr->HwCnt -= BdCount; + RingPtr->PostCnt += BdCount; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount); + Status = (BdCount); + } else { + *BdSetPtr = NULL; + Status = 0U; + } + } + return Status; +} + + +/*****************************************************************************/ +/** + * Frees a set of BDs that had been previously retrieved with + * XEmacPs_BdRingFromHw(). + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param NumBd is the number of BDs to free. + * @param BdSetPtr is the head of a list of BDs returned by + * XEmacPs_BdRingFromHw(). + * + * @return + * - XST_SUCCESS if the set of BDs was freed. + * - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with + * XEmacPs_BdRingFromHw(). + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr) +{ + LONG Status; + /* if no bds to process, simply return. */ + if (0x00000000U == NumBd){ + Status = (LONG)(XST_SUCCESS); + } else { + /* Make sure we are in sync with XEmacPs_BdRingFromHw() */ + if ((RingPtr->PostCnt < NumBd) || (RingPtr->PostHead != BdSetPtr)) { + Status = (LONG)(XST_DMA_SG_LIST_ERROR); + } else { + /* Update pointers and counters */ + RingPtr->FreeCnt += NumBd; + RingPtr->PostCnt -= NumBd; + XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PostHead, NumBd); + Status = (LONG)(XST_SUCCESS); + } + } + return Status; +} + + +/*****************************************************************************/ +/** + * Check the internal data structures of the BD ring for the provided channel. + * The following checks are made: + * + * - Is the BD ring linked correctly in physical address space. + * - Do the internal pointers point to BDs in the ring. + * - Do the internal counters add up. + * + * The channel should be stopped prior to calling this function. + * + * @param RingPtr is a pointer to the instance to be worked on. + * @param Direction is either XEMACPS_SEND or XEMACPS_RECV that indicates + * which direction. + * + * @return + * - XST_SUCCESS if the set of BDs was freed. + * - XST_DMA_SG_NO_LIST if the list has not been created. + * - XST_IS_STARTED if the channel is not stopped. + * - XST_DMA_SG_LIST_ERROR if a problem is found with the internal data + * structures. If this value is returned, the channel should be reset to + * avoid data corruption or system instability. + * + * @note This function should not be preempted by another XEmacPs_Bd function + * call that modifies the BD space. It is the caller's responsibility to + * provide a mutual exclusion mechanism. + * + *****************************************************************************/ +LONG XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction) +{ + UINTPTR AddrV, AddrP; + u32 i; + + if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) { + return (LONG)(XST_INVALID_PARAM); + } + + /* Is the list created */ + if (RingPtr->AllCnt == 0x00000000U) { + return (LONG)(XST_DMA_SG_NO_LIST); + } + + /* Can't check if channel is running */ + if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) { + return (LONG)(XST_IS_STARTED); + } + + /* RunState doesn't make sense */ + if (RingPtr->RunState != (u32)XST_DMA_SG_IS_STOPPED) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + /* Verify internal pointers point to correct memory space */ + AddrV = (UINTPTR) RingPtr->FreeHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + AddrV = (UINTPTR) RingPtr->PreHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + AddrV = (UINTPTR) RingPtr->HwHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + AddrV = (UINTPTR) RingPtr->HwTail; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + AddrV = (UINTPTR) RingPtr->PostHead; + if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + /* Verify internal counters add up */ + if ((RingPtr->HwCnt + RingPtr->PreCnt + RingPtr->FreeCnt + + RingPtr->PostCnt) != RingPtr->AllCnt) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + /* Verify BDs are linked correctly */ + AddrV = RingPtr->BaseBdAddr; + AddrP = RingPtr->PhysBaseAddr + RingPtr->Separation; + + for (i = 1U; i < RingPtr->AllCnt; i++) { + /* Check BDA for this BD. It should point to next physical addr */ + if (XEmacPs_BdRead(AddrV, XEMACPS_BD_ADDR_OFFSET) != AddrP) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + + /* Move on to next BD */ + AddrV += RingPtr->Separation; + AddrP += RingPtr->Separation; + } + + /* Last BD should have wrap bit set */ + if (XEMACPS_SEND == Direction) { + if ((!XEmacPs_BdIsTxWrap(AddrV))==TRUE) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + } + else { /* XEMACPS_RECV */ + if ((!XEmacPs_BdIsRxWrap(AddrV))==TRUE) { + return (LONG)(XST_DMA_SG_LIST_ERROR); + } + } + + /* No problems found */ + return (LONG)(XST_SUCCESS); +} + +/*****************************************************************************/ +/** + * Set this bit to mark the last descriptor in the receive buffer descriptor + * list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetRxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +static void XEmacPs_BdSetRxWrap(UINTPTR BdPtr) +{ + u32 DataValueRx; + u32 *TempPtr; + + BdPtr += (u32)(XEMACPS_BD_ADDR_OFFSET); + TempPtr = (u32 *)BdPtr; + if(TempPtr != NULL) { + DataValueRx = *TempPtr; + DataValueRx |= XEMACPS_RXBUF_WRAP_MASK; + *TempPtr = DataValueRx; + } +} + +/*****************************************************************************/ +/** + * Sets this bit to mark the last descriptor in the transmit buffer + * descriptor list. + * + * @param BdPtr is the BD pointer to operate on + * + * @note + * C-style signature: + * void XEmacPs_BdSetTxWrap(XEmacPs_Bd* BdPtr) + * + *****************************************************************************/ +static void XEmacPs_BdSetTxWrap(UINTPTR BdPtr) +{ + u32 DataValueTx; + u32 *TempPtr; + + BdPtr += (u32)(XEMACPS_BD_STAT_OFFSET); + TempPtr = (u32 *)BdPtr; + if(TempPtr != NULL) { + DataValueTx = *TempPtr; + DataValueTx |= XEMACPS_TXBUF_WRAP_MASK; + *TempPtr = DataValueTx; + } +} + +/*****************************************************************************/ +/** + * Reset BD ring head and tail pointers. + * + * @param RingPtr is the instance to be worked on. + * @param virtaddrloc is the virtual base address of the user memory region. + * + * @note + * Should be called after XEmacPs_Stop() + * + * @note + * C-style signature: + * void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc) + * + *****************************************************************************/ +void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc) +{ + RingPtr->FreeHead = virtaddrloc; + RingPtr->PreHead = virtaddrloc; + RingPtr->HwHead = virtaddrloc; + RingPtr->HwTail = virtaddrloc; + RingPtr->PostHead = virtaddrloc; +} + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bdring.h b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bdring.h new file mode 100644 index 0000000..f5653db --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_bdring.h @@ -0,0 +1,215 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_bdring.h +* @addtogroup emacps_v3_16 +* @{ +* +* The Xiline EmacPs Buffer Descriptor ring driver. This is part of EmacPs +* DMA functionalities. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp architecture.
+* 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.6   rb   09/08/17 HwCnt variable (in XEmacPs_BdRing structure) is
+*		      changed to volatile.
+*
+* 
+* +******************************************************************************/ + +#ifndef XEMACPS_BDRING_H /* prevent curcular inclusions */ +#define XEMACPS_BDRING_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/**************************** Type Definitions *******************************/ + +/** This is an internal structure used to maintain the DMA list */ +typedef struct { + UINTPTR PhysBaseAddr;/**< Physical address of 1st BD in list */ + UINTPTR BaseBdAddr; /**< Virtual address of 1st BD in list */ + UINTPTR HighBdAddr; /**< Virtual address of last BD in the list */ + u32 Length; /**< Total size of ring in bytes */ + u32 RunState; /**< Flag to indicate DMA is started */ + u32 Separation; /**< Number of bytes between the starting address + of adjacent BDs */ + XEmacPs_Bd *FreeHead; + /**< First BD in the free group */ + XEmacPs_Bd *PreHead;/**< First BD in the pre-work group */ + XEmacPs_Bd *HwHead; /**< First BD in the work group */ + XEmacPs_Bd *HwTail; /**< Last BD in the work group */ + XEmacPs_Bd *PostHead; + /**< First BD in the post-work group */ + XEmacPs_Bd *BdaRestart; + /**< BDA to load when channel is started */ + + volatile u32 HwCnt; /**< Number of BDs in work group */ + u32 PreCnt; /**< Number of BDs in pre-work group */ + u32 FreeCnt; /**< Number of allocatable BDs in the free group */ + u32 PostCnt; /**< Number of BDs in post-work group */ + u32 AllCnt; /**< Total Number of BDs for channel */ +} XEmacPs_BdRing; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* Use this macro at initialization time to determine how many BDs will fit +* in a BD list within the given memory constraints. +* +* The results of this macro can be provided to XEmacPs_BdRingCreate(). +* +* @param Alignment specifies what byte alignment the BDs must fall on and +* must be a power of 2 to get an accurate calculation (32, 64, 128,...) +* @param Bytes is the number of bytes to be used to store BDs. +* +* @return Number of BDs that can fit in the given memory area +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingCntCalc(u32 Alignment, u32 Bytes) +* +******************************************************************************/ +#define XEmacPs_BdRingCntCalc(Alignment, Bytes) \ + (u32)((Bytes) / (sizeof(XEmacPs_Bd))) + +/*****************************************************************************/ +/** +* Use this macro at initialization time to determine how many bytes of memory +* is required to contain a given number of BDs at a given alignment. +* +* @param Alignment specifies what byte alignment the BDs must fall on. This +* parameter must be a power of 2 to get an accurate calculation (32, 64, +* 128,...) +* @param NumBd is the number of BDs to calculate memory size requirements for +* +* @return The number of bytes of memory required to create a BD list with the +* given memory constraints. +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingMemCalc(u32 Alignment, u32 NumBd) +* +******************************************************************************/ +#define XEmacPs_BdRingMemCalc(Alignment, NumBd) \ + (u32)(sizeof(XEmacPs_Bd) * (NumBd)) + +/****************************************************************************/ +/** +* Return the total number of BDs allocated by this channel with +* XEmacPs_BdRingCreate(). +* +* @param RingPtr is the DMA channel to operate on. +* +* @return The total number of BDs allocated for this channel. +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingGetCnt(XEmacPs_BdRing* RingPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingGetCnt(RingPtr) ((RingPtr)->AllCnt) + +/****************************************************************************/ +/** +* Return the number of BDs allocatable with XEmacPs_BdRingAlloc() for pre- +* processing. +* +* @param RingPtr is the DMA channel to operate on. +* +* @return The number of BDs currently allocatable. +* +* @note +* C-style signature: +* u32 XEmacPs_BdRingGetFreeCnt(XEmacPs_BdRing* RingPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingGetFreeCnt(RingPtr) ((RingPtr)->FreeCnt) + +/****************************************************************************/ +/** +* Return the next BD from BdPtr in a list. +* +* @param RingPtr is the DMA channel to operate on. +* @param BdPtr is the BD to operate on. +* +* @return The next BD in the list relative to the BdPtr parameter. +* +* @note +* C-style signature: +* XEmacPs_Bd *XEmacPs_BdRingNext(XEmacPs_BdRing* RingPtr, +* XEmacPs_Bd *BdPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingNext(RingPtr, BdPtr) \ + (((UINTPTR)((void *)(BdPtr)) >= (RingPtr)->HighBdAddr) ? \ + (XEmacPs_Bd*)((void*)(RingPtr)->BaseBdAddr) : \ + (XEmacPs_Bd*)((UINTPTR)((void *)(BdPtr)) + (RingPtr)->Separation)) + +/****************************************************************************/ +/** +* Return the previous BD from BdPtr in the list. +* +* @param RingPtr is the DMA channel to operate on. +* @param BdPtr is the BD to operate on +* +* @return The previous BD in the list relative to the BdPtr parameter. +* +* @note +* C-style signature: +* XEmacPs_Bd *XEmacPs_BdRingPrev(XEmacPs_BdRing* RingPtr, +* XEmacPs_Bd *BdPtr) +* +*****************************************************************************/ +#define XEmacPs_BdRingPrev(RingPtr, BdPtr) \ + (((UINTPTR)(BdPtr) <= (RingPtr)->BaseBdAddr) ? \ + (XEmacPs_Bd*)(RingPtr)->HighBdAddr : \ + (XEmacPs_Bd*)((UINTPTR)(BdPtr) - (RingPtr)->Separation)) + +/************************** Function Prototypes ******************************/ + +/* + * Scatter gather DMA related functions in xemacps_bdring.c + */ +LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr, + UINTPTR VirtAddr, u32 Alignment, u32 BdCount); +LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr, + u8 Direction); +LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd ** BdSetPtr); +LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr); +LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr); +LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd, + XEmacPs_Bd * BdSetPtr); +u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit, + XEmacPs_Bd ** BdSetPtr); +u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit, + XEmacPs_Bd ** BdSetPtr); +LONG XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction); + +void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc); + +#ifdef __cplusplus +} +#endif + + +#endif /* end of protection macros */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_control.c b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_control.c new file mode 100644 index 0000000..4c72f20 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_control.c @@ -0,0 +1,1133 @@ +/****************************************************************************** +* Copyright (C) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xemacps_control.c +* @addtogroup emacps_v3_16 +* @{ + * + * Functions in this file implement general purpose command and control related + * functionality. See xemacps.h for a detailed description of the driver. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wsy  01/10/10 First release
+ * 1.02a asa  11/05/12 Added a new API for deleting an entry from the HASH
+ *					   register. Added a new API for setting the BURST length
+ *					   in DMACR register.
+ * 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp architecture.
+ * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+ * 3.0   hk   02/20/15 Added support for jumbo frames.
+ * 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
+ * 
+ *****************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xemacps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** + * Set the MAC address for this driver/device. The address is a 48-bit value. + * The device must be stopped before calling this function. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param AddressPtr is a pointer to a 6-byte MAC address. + * @param Index is a index to which MAC (1-4) address. + * + * @return + * - XST_SUCCESS if the MAC address was set successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * + *****************************************************************************/ +LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index) +{ + u32 MacAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 IndexLoc = Index; + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Aptr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U)); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } + else{ + /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ + IndexLoc--; + + /* Set the MAC bits [31:0] in BOT */ + MacAddr = *(Aptr); + MacAddr |= ((u32)(*(Aptr+1)) << 8U); + MacAddr |= ((u32)(*(Aptr+2)) << 16U); + MacAddr |= ((u32)(*(Aptr+3)) << 24U); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr); + + /* There are reserved bits in TOP so don't affect them */ + MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8))); + + MacAddr &= (u32)(~XEMACPS_LADDR_MACH_MASK); + + /* Set MAC bits [47:32] in TOP */ + MacAddr |= (u32)(*(Aptr+4)); + MacAddr |= (u32)(*(Aptr+5)) << 8U; + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr); + + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + + +/*****************************************************************************/ +/** + * Get the MAC address for this driver/device. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param AddressPtr is an output parameter, and is a pointer to a buffer into + * which the current MAC address will be copied. + * @param Index is a index to which MAC (1-4) address. + * + *****************************************************************************/ +void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index) +{ + u32 MacAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 IndexLoc = Index; + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Aptr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U)); + + /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ + IndexLoc--; + + MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8))); + *Aptr = (u8) MacAddr; + *(Aptr+1) = (u8) (MacAddr >> 8U); + *(Aptr+2) = (u8) (MacAddr >> 16U); + *(Aptr+3) = (u8) (MacAddr >> 24U); + + /* Read MAC bits [47:32] in TOP */ + MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8))); + *(Aptr+4) = (u8) MacAddr; + *(Aptr+5) = (u8) (MacAddr >> 8U); +} + + +/*****************************************************************************/ +/** + * Set 48-bit MAC addresses in hash table. + * The device must be stopped before calling this function. + * + * The hash address register is 64 bits long and takes up two locations in + * the memory map. The least significant bits are stored in hash register + * bottom and the most significant bits in hash register top. + * + * The unicast hash enable and the multicast hash enable bits in the network + * configuration register enable the reception of hash matched frames. The + * destination address is reduced to a 6 bit index into the 64 bit hash + * register using the following hash function. The hash function is an XOR + * of every sixth bit of the destination address. + * + *
+ * hash_index[05] = da[05]^da[11]^da[17]^da[23]^da[29]^da[35]^da[41]^da[47]
+ * hash_index[04] = da[04]^da[10]^da[16]^da[22]^da[28]^da[34]^da[40]^da[46]
+ * hash_index[03] = da[03]^da[09]^da[15]^da[21]^da[27]^da[33]^da[39]^da[45]
+ * hash_index[02] = da[02]^da[08]^da[14]^da[20]^da[26]^da[32]^da[38]^da[44]
+ * hash_index[01] = da[01]^da[07]^da[13]^da[19]^da[25]^da[31]^da[37]^da[43]
+ * hash_index[00] = da[00]^da[06]^da[12]^da[18]^da[24]^da[30]^da[36]^da[42]
+ * 
+ * + * da[0] represents the least significant bit of the first byte received, + * that is, the multicast/unicast indicator, and da[47] represents the most + * significant bit of the last byte received. + * + * If the hash index points to a bit that is set in the hash register then + * the frame will be matched according to whether the frame is multicast + * or unicast. + * + * A multicast match will be signaled if the multicast hash enable bit is + * set, da[0] is logic 1 and the hash index points to a bit set in the hash + * register. + * + * A unicast match will be signaled if the unicast hash enable bit is set, + * da[0] is logic 0 and the hash index points to a bit set in the hash + * register. + * + * To receive all multicast frames, the hash register should be set with + * all ones and the multicast hash enable bit should be set in the network + * configuration register. + * + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param AddressPtr is a pointer to a 6-byte MAC address. + * + * @return + * - XST_SUCCESS if the HASH MAC address was set successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet + * requirement after calculation + * + * @note + * Having Aptr be unsigned type prevents the following operations from sign + * extending. + *****************************************************************************/ +LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr) +{ + u32 HashAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8; + u32 Result; + LONG Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(AddressPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + Temp1 = (*(Aptr+0)) & 0x3FU; + Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); + + Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x3U) << 4U); + Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); + Temp5 = (*(Aptr+3)) & 0x3FU; + Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); + Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); + Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); + + Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ + (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8); + + if (Result >= (u32)XEMACPS_MAX_HASH_BITS) { + Status = (LONG)(XST_INVALID_PARAM); + } else { + + if (Result < (u32)32) { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET); + HashAddr |= (u32)(0x00000001U << Result); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET, HashAddr); + } else { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET); + HashAddr |= (u32)(0x00000001U << (u32)(Result - (u32)32)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET, HashAddr); + } + Status = (LONG)(XST_SUCCESS); + } + } + return Status; +} + +/*****************************************************************************/ +/** + * Delete 48-bit MAC addresses in hash table. + * The device must be stopped before calling this function. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param AddressPtr is a pointer to a 6-byte MAC address. + * + * @return + * - XST_SUCCESS if the HASH MAC address was deleted successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet + * requirement after calculation + * + * @note + * Having Aptr be unsigned type prevents the following operations from sign + * extending. + *****************************************************************************/ +LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr) +{ + u32 HashAddr; + u8 *Aptr = (u8 *)(void *)AddressPtr; + u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8; + u32 Result; + LONG Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Aptr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + Temp1 = (*(Aptr+0)) & 0x3FU; + Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U); + Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x03U) << 4U); + Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU); + Temp5 = (*(Aptr+3)) & 0x3FU; + Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U); + Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U); + Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU); + + Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^ + (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8); + + if (Result >= (u32)(XEMACPS_MAX_HASH_BITS)) { + Status = (LONG)(XST_INVALID_PARAM); + } else { + if (Result < (u32)32) { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET); + HashAddr &= (u32)(~(0x00000001U << Result)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET, HashAddr); + } else { + HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET); + HashAddr &= (u32)(~(0x00000001U << (u32)(Result - (u32)32))); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET, HashAddr); + } + Status = (LONG)(XST_SUCCESS); + } + } + return Status; +} +/*****************************************************************************/ +/** + * Clear the Hash registers for the mac address pointed by AddressPtr. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * + *****************************************************************************/ +void XEmacPs_ClearHash(XEmacPs *InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET, 0x0U); + + /* write bits [63:32] in TOP */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET, 0x0U); +} + + +/*****************************************************************************/ +/** + * Get the Hash address for this driver/device. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param AddressPtr is an output parameter, and is a pointer to a buffer into + * which the current HASH MAC address will be copied. + * + *****************************************************************************/ +void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr) +{ + u32 *Aptr = (u32 *)(void *)AddressPtr; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(AddressPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + *(Aptr+0) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHL_OFFSET); + + /* Read Hash bits [63:32] in TOP */ + *(Aptr+1) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_HASHH_OFFSET); +} + + +/*****************************************************************************/ +/** + * Set the Type ID match for this driver/device. The register is a 32-bit + * value. The device must be stopped before calling this function. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param Id_Check is type ID to be configured. + * @param Index is a index to which Type ID (1-4). + * + * @return + * - XST_SUCCESS if the MAC address was set successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * + *****************************************************************************/ +LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index) +{ + u8 IndexLoc = Index; + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_TYPE_ID) && (IndexLoc > 0x00U)); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + + /* Index ranges 1 to 4, for offset calculation is 0 to 3. */ + IndexLoc--; + + /* Set the ID bits in MATCHx register */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + ((u32)XEMACPS_MATCH1_OFFSET + ((u32)IndexLoc * (u32)4)), Id_Check); + + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + +/*****************************************************************************/ +/** + * Set options for the driver/device. The driver should be stopped with + * XEmacPs_Stop() before changing options. + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param Options are the options to set. Multiple options can be set by OR'ing + * XTE_*_OPTIONS constants together. Options not specified are not + * affected. + * + * @return + * - XST_SUCCESS if the options were set successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * + * @note + * See xemacps.h for a description of the available options. + * + *****************************************************************************/ +LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options) +{ + u32 Reg; /* Generic register contents */ + u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ + u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + + /* Many of these options will change the NET_CONFIG registers. + * To reduce the amount of IO to the device, group these options here + * and change them all at once. + */ + + /* Grab current register contents */ + RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + RegNewNetCfg = RegNetCfg; + + /* + * It is configured to max 1536. + */ + if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { + RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK); + } + + /* Turn on VLAN packet only, only VLAN tagged will be accepted */ + if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK; + } + + /* Turn on FCS stripping on receive packets */ + if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK; + } + + /* Turn on length/type field checking on receive packets */ + if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_LENERRDSCRD_MASK; + } + + /* Turn on flow control */ + if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK; + } + + /* Turn on promiscuous frame filtering (all frames are received) */ + if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK; + } + + /* Allow broadcast address reception */ + if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_BCASTDI_MASK); + } + + /* Allow multicast address filtering */ + if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK; + } + + /* enable RX checksum offload */ + if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK; + } + + /* Enable jumbo frames */ + if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) && + (InstancePtr->Version > 2)) { + RegNewNetCfg |= XEMACPS_NWCFG_JUMBO_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_JUMBOMAXLEN_OFFSET, XEMACPS_RX_BUF_SIZE_JUMBO); + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg &= ~XEMACPS_DMACR_RXBUF_MASK; + Reg |= (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO / (u32)XEMACPS_RX_BUF_UNIT) + + (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO % + (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << + (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & + (u32)(XEMACPS_DMACR_RXBUF_MASK)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + InstancePtr->MaxMtuSize = XEMACPS_MTU_JUMBO; + InstancePtr->MaxFrameSize = XEMACPS_MTU_JUMBO + + XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; + InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + + XEMACPS_HDR_VLAN_SIZE; + InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_JUMBO_MASK; + } + + if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) && + (InstancePtr->Version > 2)) { + RegNewNetCfg |= (XEMACPS_NWCFG_SGMIIEN_MASK | + XEMACPS_NWCFG_PCSSEL_MASK); + } + + /* Officially change the NET_CONFIG registers if it needs to be + * modified. + */ + if (RegNetCfg != RegNewNetCfg) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, RegNewNetCfg); + } + + /* Enable TX checksum offload */ + if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg |= XEMACPS_DMACR_TCPCKSUM_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + } + + /* Enable transmitter */ + if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg |= XEMACPS_NWCTRL_TXEN_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } + + /* Enable receiver */ + if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg |= XEMACPS_NWCTRL_RXEN_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } + + /* The remaining options not handled here are managed elsewhere in the + * driver. No register modifications are needed at this time. Reflecting + * the option in InstancePtr->Options is good enough for now. + */ + + /* Set options word to its new value */ + InstancePtr->Options |= Options; + + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + + +/*****************************************************************************/ +/** + * Clear options for the driver/device + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param Options are the options to clear. Multiple options can be cleared by + * OR'ing XEMACPS_*_OPTIONS constants together. Options not specified + * are not affected. + * + * @return + * - XST_SUCCESS if the options were set successfully + * - XST_DEVICE_IS_STARTED if the device has not yet been stopped + * + * @note + * See xemacps.h for a description of the available options. + * + *****************************************************************************/ +LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options) +{ + u32 Reg; /* Generic */ + u32 RegNetCfg; /* Reflects original contents of NET_CONFIG */ + u32 RegNewNetCfg; /* Reflects new contents of NET_CONFIG */ + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Be sure device has been stopped */ + if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STARTED); + } else { + + /* Many of these options will change the NET_CONFIG registers. + * To reduce the amount of IO to the device, group these options here + * and change them all at once. + */ + + /* Grab current register contents */ + RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + RegNewNetCfg = RegNetCfg; + + /* There is only RX configuration!? + * It is configured in two different length, up to 1536 and 10240 bytes + */ + if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_1536RXEN_MASK); + } + + /* Turn off VLAN packet only */ + if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_NVLANDISC_MASK); + } + + /* Turn off FCS stripping on receive packets */ + if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_FCSREM_MASK); + } + + /* Turn off length/type field checking on receive packets */ + if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_LENERRDSCRD_MASK); + } + + /* Turn off flow control */ + if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_PAUSEEN_MASK); + } + + /* Turn off promiscuous frame filtering (all frames are received) */ + if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_COPYALLEN_MASK); + } + + /* Disallow broadcast address filtering => broadcast reception */ + if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) { + RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK; + } + + /* Disallow multicast address filtering */ + if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_MCASTHASHEN_MASK); + } + + /* Disable RX checksum offload */ + if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_RXCHKSUMEN_MASK); + } + + /* Disable jumbo frames */ + if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) && + (InstancePtr->Version > 2)) { + RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_JUMBO_MASK); + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg &= ~XEMACPS_DMACR_RXBUF_MASK; + Reg |= (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) + + (((((u32)XEMACPS_RX_BUF_SIZE % + (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) << + (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) & + (u32)(XEMACPS_DMACR_RXBUF_MASK)); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + InstancePtr->MaxMtuSize = XEMACPS_MTU; + InstancePtr->MaxFrameSize = XEMACPS_MTU + + XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE; + InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize + + XEMACPS_HDR_VLAN_SIZE; + InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK; + } + + if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) && + (InstancePtr->Version > 2)) { + RegNewNetCfg &= (u32)(~(XEMACPS_NWCFG_SGMIIEN_MASK | + XEMACPS_NWCFG_PCSSEL_MASK)); + } + + /* Officially change the NET_CONFIG registers if it needs to be + * modified. + */ + if (RegNetCfg != RegNewNetCfg) { + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, RegNewNetCfg); + } + + /* Disable TX checksum offload */ + if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + Reg &= (u32)(~XEMACPS_DMACR_TCPCKSUM_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET, Reg); + } + + /* Disable transmitter */ + if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } + + /* Disable receiver */ + if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) { + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + } + + /* The remaining options not handled here are managed elsewhere in the + * driver. No register modifications are needed at this time. Reflecting + * option in InstancePtr->Options is good enough for now. + */ + + /* Set options word to its new value */ + InstancePtr->Options &= ~Options; + + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + + +/*****************************************************************************/ +/** + * Get current option settings + * + * @param InstancePtr is a pointer to the instance to be worked on. + * + * @return + * A bitmask of XTE_*_OPTION constants. Any bit set to 1 is to be interpreted + * as a set option. + * + * @note + * See xemacps.h for a description of the available options. + * + *****************************************************************************/ +u32 XEmacPs_GetOptions(XEmacPs *InstancePtr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + return (InstancePtr->Options); +} + + +/*****************************************************************************/ +/** + * Send a pause packet + * + * @param InstancePtr is a pointer to the instance to be worked on. + * + * @return + * - XST_SUCCESS if pause frame transmission was initiated + * - XST_DEVICE_IS_STOPPED if the device has not been started. + * + *****************************************************************************/ +LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr) +{ + u32 Reg; + LONG Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* Make sure device is ready for this operation */ + if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) { + Status = (LONG)(XST_DEVICE_IS_STOPPED); + } else { + /* Send flow control frame */ + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + Reg |= XEMACPS_NWCTRL_PAUSETX_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, Reg); + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + +/*****************************************************************************/ +/** + * XEmacPs_GetOperatingSpeed gets the current operating link speed. This may + * be the value set by XEmacPs_SetOperatingSpeed() or a hardware default. + * + * @param InstancePtr references the TEMAC channel on which to operate. + * + * @return XEmacPs_GetOperatingSpeed returns the link speed in units of + * megabits per second. + * + * @note + * + *****************************************************************************/ +u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr) +{ + u32 Reg; + u16 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + + if ((Reg & XEMACPS_NWCFG_1000_MASK) != 0x00000000U) { + Status = (u16)(1000); + } else { + if ((Reg & XEMACPS_NWCFG_100_MASK) != 0x00000000U) { + Status = (u16)(100); + } else { + Status = (u16)(10); + } + } + return Status; +} + + +/*****************************************************************************/ +/** + * XEmacPs_SetOperatingSpeed sets the current operating link speed. For any + * traffic to be passed, this speed must match the current MII/GMII/SGMII/RGMII + * link speed. + * + * @param InstancePtr references the TEMAC channel on which to operate. + * @param Speed is the speed to set in units of Mbps. Valid values are 10, 100, + * or 1000. XEmacPs_SetOperatingSpeed ignores invalid values. + * + * @note + * + *****************************************************************************/ +void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed) +{ + u32 Reg; + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Speed == (u16)10) || (Speed == (u16)100) || (Speed == (u16)1000)); + + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + Reg &= (u32)(~(XEMACPS_NWCFG_1000_MASK | XEMACPS_NWCFG_100_MASK)); + + switch (Speed) { + case (u16)10: + break; + + case (u16)100: + Reg |= XEMACPS_NWCFG_100_MASK; + break; + + case (u16)1000: + Reg |= XEMACPS_NWCFG_1000_MASK; + break; + } + + /* Set register and return */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, Reg); +} + + +/*****************************************************************************/ +/** + * Set the MDIO clock divisor. + * + * Calculating the divisor: + * + *
+ *              f[HOSTCLK]
+ *   f[MDC] = -----------------
+ *            (1 + Divisor) * 2
+ * 
+ * + * where f[HOSTCLK] is the bus clock frequency in MHz, and f[MDC] is the + * MDIO clock frequency in MHz to the PHY. Typically, f[MDC] should not + * exceed 2.5 MHz. Some PHYs can tolerate faster speeds which means faster + * access. Here is the table to show values to generate MDC, + * + *
+ * 000 : divide pclk by   8 (pclk up to  20 MHz)
+ * 001 : divide pclk by  16 (pclk up to  40 MHz)
+ * 010 : divide pclk by  32 (pclk up to  80 MHz)
+ * 011 : divide pclk by  48 (pclk up to 120 MHz)
+ * 100 : divide pclk by  64 (pclk up to 160 MHz)
+ * 101 : divide pclk by  96 (pclk up to 240 MHz)
+ * 110 : divide pclk by 128 (pclk up to 320 MHz)
+ * 111 : divide pclk by 224 (pclk up to 540 MHz)
+ * 
+ * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param Divisor is the divisor to set. Range is 0b000 to 0b111. + * + *****************************************************************************/ +void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor) +{ + u32 Reg; + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Divisor <= (XEmacPs_MdcDiv)0x7); /* only last three bits are valid */ + + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET); + /* clear these three bits, could be done with mask */ + Reg &= (u32)(~XEMACPS_NWCFG_MDCCLKDIV_MASK); + + Reg |= ((u32)Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK); + + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCFG_OFFSET, Reg); +} + + +/*****************************************************************************/ +/** +* Read the current value of the PHY register indicated by the PhyAddress and +* the RegisterNum parameters. The MAC provides the driver with the ability to +* talk to a PHY that adheres to the Media Independent Interface (MII) as +* defined in the IEEE 802.3 standard. +* +* Prior to PHY access with this function, the user should have setup the MDIO +* clock with XEmacPs_SetMdioDivisor(). +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* @param PhyAddress is the address of the PHY to be read (supports multiple +* PHYs) +* @param RegisterNum is the register number, 0-31, of the specific PHY register +* to read +* @param PhyDataPtr is an output parameter, and points to a 16-bit buffer into +* which the current value of the register will be copied. +* +* @return +* +* - XST_SUCCESS if the PHY was read from successfully +* - XST_EMAC_MII_BUSY if there is another PHY operation in progress +* +* @note +* +* This function is not thread-safe. The user must provide mutually exclusive +* access to this function if there are to be multiple threads that can call it. +* +* There is the possibility that this function will not return if the hardware +* is broken (i.e., it never sets the status bit indicating that the read is +* done). If this is of concern to the user, the user should provide a mechanism +* suitable to their needs for recovery. +* +* For the duration of this function, all host interface reads and writes are +* blocked to the current XEmacPs instance. +* +******************************************************************************/ +LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress, + u32 RegisterNum, u16 *PhyDataPtr) +{ + u32 Mgtcr; + volatile u32 Ipisr; + u32 IpReadTemp; + LONG Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Make sure no other PHY operation is currently in progress */ + if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET) & + XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) { + Status = (LONG)(XST_EMAC_MII_BUSY); + } else { + + /* Construct Mgtcr mask for the operation */ + Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK | + (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) | + (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK); + + /* Write Mgtcr and wait for completion */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_PHYMNTNC_OFFSET, Mgtcr); + + do { + Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET); + IpReadTemp = Ipisr; + } while ((IpReadTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U); + + /* Read data */ + *PhyDataPtr = (u16)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_PHYMNTNC_OFFSET); + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + + +/*****************************************************************************/ +/** +* Write data to the specified PHY register. The Ethernet driver does not +* require the device to be stopped before writing to the PHY. Although it is +* probably a good idea to stop the device, it is the responsibility of the +* application to deem this necessary. The MAC provides the driver with the +* ability to talk to a PHY that adheres to the Media Independent Interface +* (MII) as defined in the IEEE 802.3 standard. +* +* Prior to PHY access with this function, the user should have setup the MDIO +* clock with XEmacPs_SetMdioDivisor(). +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* @param PhyAddress is the address of the PHY to be written (supports multiple +* PHYs) +* @param RegisterNum is the register number, 0-31, of the specific PHY register +* to write +* @param PhyData is the 16-bit value that will be written to the register +* +* @return +* +* - XST_SUCCESS if the PHY was written to successfully. Since there is no error +* status from the MAC on a write, the user should read the PHY to verify the +* write was successful. +* - XST_EMAC_MII_BUSY if there is another PHY operation in progress +* +* @note +* +* This function is not thread-safe. The user must provide mutually exclusive +* access to this function if there are to be multiple threads that can call it. +* +* There is the possibility that this function will not return if the hardware +* is broken (i.e., it never sets the status bit indicating that the write is +* done). If this is of concern to the user, the user should provide a mechanism +* suitable to their needs for recovery. +* +* For the duration of this function, all host interface reads and writes are +* blocked to the current XEmacPs instance. +* +******************************************************************************/ +LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress, + u32 RegisterNum, u16 PhyData) +{ + u32 Mgtcr; + volatile u32 Ipisr; + u32 IpWriteTemp; + LONG Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Make sure no other PHY operation is currently in progress */ + if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET) & + XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) { + Status = (LONG)(XST_EMAC_MII_BUSY); + } else { + /* Construct Mgtcr mask for the operation */ + Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK | + (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) | + (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK) | (u32)PhyData; + + /* Write Mgtcr and wait for completion */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_PHYMNTNC_OFFSET, Mgtcr); + + do { + Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWSR_OFFSET); + IpWriteTemp = Ipisr; + } while ((IpWriteTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U); + + Status = (LONG)(XST_SUCCESS); + } + return Status; +} + +/*****************************************************************************/ +/** +* API to update the Burst length in the DMACR register. +* +* @param InstancePtr is a pointer to the XEmacPs instance to be worked on. +* @param BLength is the length in bytes for the dma burst. +* +* @return None +* +******************************************************************************/ +void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength) +{ + u32 Reg; + u32 RegUpdateVal = 0; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((BLength == XEMACPS_SINGLE_BURST) || + (BLength == XEMACPS_4BYTE_BURST) || + (BLength == XEMACPS_8BYTE_BURST) || + (BLength == XEMACPS_16BYTE_BURST)); + + switch (BLength) { + case XEMACPS_SINGLE_BURST: + RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST; + break; + + case XEMACPS_4BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST; + break; + + case XEMACPS_8BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST; + break; + + case XEMACPS_16BYTE_BURST: + RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST; + break; + } + Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_DMACR_OFFSET); + + Reg &= (u32)(~XEMACPS_DMACR_BLENGTH_MASK); + Reg |= RegUpdateVal; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET, + Reg); +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_g.c new file mode 100644 index 0000000..020c6f7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_g.c @@ -0,0 +1,87 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_g.c +* @addtogroup emacps_v3_16 +* @{ +* +* This file contains a configuration table that specifies the configuration of +* ethernet devices in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 2.00  hk   22/01/14 Added check for picking second instance
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +* @internal +* +* This configuration table contains entries that are modified at runtime by the +* driver. This table reflects only the hardware configuration of the device. +* This emac configuration table contains software information in addition to +* hardware configuration. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xemacps.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Prototypes ******************************/ + +/* + * The configuration table for emacps device + */ + +XEmacPs_Config XEmacPs_ConfigTable[XPAR_XEMACPS_NUM_INSTANCES] = { + { + (u16)XPAR_XEMACPS_0_DEVICE_ID, /* Device ID */ + (UINTPTR)XPAR_XEMACPS_0_BASEADDR, /* Device base address */ + (u16)XPAR_XEMACPS_0_IS_CACHE_COHERENT, /* Cache Coherency */ +#if defined (XCLOCKING) + (u32)XPAR_XEMACPS_0_ENET_CLK_FREQ_HZ, +#endif + (u16)XPAR_XEMACPS_0_ENET_SLCR_1000Mbps_DIV0, + (u8)XPAR_XEMACPS_0_ENET_SLCR_1000Mbps_DIV1, + (u16)XPAR_XEMACPS_0_ENET_SLCR_100Mbps_DIV0, + (u8)XPAR_XEMACPS_0_ENET_SLCR_100Mbps_DIV1, + (u16)XPAR_XEMACPS_0_ENET_SLCR_10Mbps_DIV0, + (u8)XPAR_XEMACPS_0_ENET_SLCR_10Mbps_DIV1 + }, +#ifdef XPAR_XEMACPS_1_DEVICE_ID + { + (u16)XPAR_XEMACPS_1_DEVICE_ID, /* Device ID */ + (UINTPTR)XPAR_XEMACPS_1_BASEADDR, /* Device base address */ + (u16)XPAR_XEMACPS_1_IS_CACHE_COHERENT, /* Cache coherency */ +#if defined (XCLOCKING) + (u32)XPAR_XEMACPS_1_ENET_CLK_FREQ_HZ, +#endif + (u16)XPAR_XEMACPS_1_ENET_SLCR_1000Mbps_DIV0, + (u8)XPAR_XEMACPS_1_ENET_SLCR_1000Mbps_DIV1, + (u16)XPAR_XEMACPS_1_ENET_SLCR_100Mbps_DIV0, + (u8)XPAR_XEMACPS_1_ENET_SLCR_100Mbps_DIV1, + (u16)XPAR_XEMACPS_1_ENET_SLCR_10Mbps_DIV0, + (u8)XPAR_XEMACPS_1_ENET_SLCR_10Mbps_DIV1 + } +#endif +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_hw.c b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_hw.c new file mode 100644 index 0000000..fdf9bab --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_hw.c @@ -0,0 +1,97 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_hw.c +* @addtogroup emacps_v3_16 +* @{ +* +* This file contains the implementation of the ethernet interface reset sequence +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.05a kpc  28/06/13 First release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xemacps_hw.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* This function perform the reset sequence to the given emacps interface by +* configuring the appropriate control bits in the emacps specific registers. +* the emacps reset sequence involves the following steps +* Disable all the interuupts +* Clear the status registers +* Disable Rx and Tx engines +* Update the Tx and Rx descriptor queue registers with reset values +* Update the other relevant control registers with reset value +* +* @param BaseAddr of the interface +* +* @return N/A +* +* @note +* This function will not modify the slcr registers that are relevant for +* emacps controller +******************************************************************************/ +void XEmacPs_ResetHw(u32 BaseAddr) +{ + u32 RegVal; + + /* Disable the interrupts */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_IDR_OFFSET,0x0U); + + /* Stop transmission,disable loopback and Stop tx and Rx engines */ + RegVal = XEmacPs_ReadReg(BaseAddr,XEMACPS_NWCTRL_OFFSET); + RegVal &= ~((u32)XEMACPS_NWCTRL_TXEN_MASK| + (u32)XEMACPS_NWCTRL_RXEN_MASK| + (u32)XEMACPS_NWCTRL_HALTTX_MASK| + (u32)XEMACPS_NWCTRL_LOOPEN_MASK); + /* Clear the statistic registers, flush the packets in DPRAM*/ + RegVal |= (XEMACPS_NWCTRL_STATCLR_MASK| + XEMACPS_NWCTRL_FLUSH_DPRAM_MASK); + XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCTRL_OFFSET,RegVal); + /* Clear the interrupt status */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_ISR_OFFSET,XEMACPS_IXR_ALL_MASK); + /* Clear the tx status */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_TXSR_OFFSET,(XEMACPS_TXSR_ERROR_MASK| + (u32)XEMACPS_TXSR_TXCOMPL_MASK| + (u32)XEMACPS_TXSR_TXGO_MASK)); + /* Clear the rx status */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_RXSR_OFFSET, + XEMACPS_RXSR_FRAMERX_MASK); + /* Clear the tx base address */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_TXQBASE_OFFSET,0x0U); + /* Clear the rx base address */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_RXQBASE_OFFSET,0x0U); + /* Update the network config register with reset value */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCFG_OFFSET,XEMACPS_NWCFG_RESET_MASK); + /* Update the hash address registers with reset value */ + XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHL_OFFSET,0x0U); + XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHH_OFFSET,0x0U); +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_hw.h new file mode 100644 index 0000000..59fe1ec --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_hw.h @@ -0,0 +1,664 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_hw.h +* @addtogroup emacps_v3_16 +* @{ +* +* This header file contains identifiers and low-level driver functions (or +* macros) that can be used to access the PS Ethernet MAC (XEmacPs) device. +* High-level driver functions are defined in xemacps.h. +* +* @note +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release.
+* 1.02a asa  11/05/12 Added hash defines for DMACR burst length configuration.
+* 1.05a kpc  28/06/13 Added XEmacPs_ResetHw function prototype
+* 1.06a asa  11/02/13 Changed the value for XEMACPS_RXBUF_LEN_MASK from 0x3fff
+*					  to 0x1fff. This fixes the CR#744902.
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification.
+* 3.0   kvn  12/16/14 Changed name of XEMACPS_NWCFG_LENGTHERRDSCRD_MASK to
+*					  XEMACPS_NWCFG_LENERRDSCRD_MASK as it exceeds 31 characters.
+* 3.0  kpc   1/23/15  Corrected the extended descriptor macro values.
+* 3.0  kvn   02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.0  hk   03/18/15 Added support for jumbo frames.
+*                    Remove "used bit set" from TX error interrupt masks.
+* 3.1  hk   08/10/15 Update upper 32 bit tx and rx queue ptr register offsets.
+* 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
+* 3.8  hk   09/17/18 Fix PTP interrupt masks.
+* 3.9  hk   01/23/19 Add RX watermark support
+* 3.10 hk   05/16/19 Clear status registers properly in reset
+* 3.18  sne 01/11/23 Add PCS control and status registers information.
+* 
+* +******************************************************************************/ + +#ifndef XEMACPS_HW_H /* prevent circular inclusions */ +#define XEMACPS_HW_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +#define XEMACPS_MAX_MAC_ADDR 4U /**< Maxmum number of mac address + supported */ +#define XEMACPS_MAX_TYPE_ID 4U /**< Maxmum number of type id supported */ + +#ifdef __aarch64__ +#define XEMACPS_BD_ALIGNMENT 64U /**< Minimum buffer descriptor alignment + on the local bus */ +#else + +#define XEMACPS_BD_ALIGNMENT 4U /**< Minimum buffer descriptor alignment + on the local bus */ +#endif +#define XEMACPS_RX_BUF_ALIGNMENT 4U /**< Minimum buffer alignment when using + options that impose alignment + restrictions on the buffer data on + the local bus */ + +/** @name Direction identifiers + * + * These are used by several functions and callbacks that need + * to specify whether an operation specifies a send or receive channel. + * @{ + */ +#define XEMACPS_SEND 1U /**< send direction */ +#define XEMACPS_RECV 2U /**< receive direction */ +/*@}*/ + +/** @name MDC clock division + * currently supporting 8, 16, 32, 48, 64, 96, 128, 224. + * @{ + */ +typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, + MDC_DIV_64, MDC_DIV_96, MDC_DIV_128, MDC_DIV_224 +} XEmacPs_MdcDiv; + +/*@}*/ + +#define XEMACPS_RX_BUF_SIZE 1536U /**< Specify the receive buffer size in + bytes, 64, 128, ... 10240 */ +#define XEMACPS_RX_BUF_SIZE_JUMBO 10240U + +#define XEMACPS_RX_BUF_UNIT 64U /**< Number of receive buffer bytes as a + unit, this is HW setup */ + +#define XEMACPS_MAX_RXBD 128U /**< Size of RX buffer descriptor queues */ +#define XEMACPS_MAX_TXBD 128U /**< Size of TX buffer descriptor queues */ + +#define XEMACPS_MAX_HASH_BITS 64U /**< Maximum value for hash bits. 2**6 */ + +/* Register offset definitions. Unless otherwise noted, register access is + * 32 bit. Names are self explained here. + */ + +#define XEMACPS_NWCTRL_OFFSET 0x00000000U /**< Network Control reg */ +#define XEMACPS_NWCFG_OFFSET 0x00000004U /**< Network Config reg */ +#define XEMACPS_NWSR_OFFSET 0x00000008U /**< Network Status reg */ + +#define XEMACPS_DMACR_OFFSET 0x00000010U /**< DMA Control reg */ +#define XEMACPS_TXSR_OFFSET 0x00000014U /**< TX Status reg */ +#define XEMACPS_RXQBASE_OFFSET 0x00000018U /**< RX Q Base address reg */ +#define XEMACPS_TXQBASE_OFFSET 0x0000001CU /**< TX Q Base address reg */ +#define XEMACPS_RXSR_OFFSET 0x00000020U /**< RX Status reg */ + +#define XEMACPS_ISR_OFFSET 0x00000024U /**< Interrupt Status reg */ +#define XEMACPS_IER_OFFSET 0x00000028U /**< Interrupt Enable reg */ +#define XEMACPS_IDR_OFFSET 0x0000002CU /**< Interrupt Disable reg */ +#define XEMACPS_IMR_OFFSET 0x00000030U /**< Interrupt Mask reg */ + +#define XEMACPS_PHYMNTNC_OFFSET 0x00000034U /**< Phy Maintaince reg */ +#define XEMACPS_RXPAUSE_OFFSET 0x00000038U /**< RX Pause Time reg */ +#define XEMACPS_TXPAUSE_OFFSET 0x0000003CU /**< TX Pause Time reg */ + +#define XEMACPS_JUMBOMAXLEN_OFFSET 0x00000048U /**< Jumbo max length reg */ + +#define XEMACPS_RXWATERMARK_OFFSET 0x0000007CU /**< RX watermark reg */ + +#define XEMACPS_HASHL_OFFSET 0x00000080U /**< Hash Low address reg */ +#define XEMACPS_HASHH_OFFSET 0x00000084U /**< Hash High address reg */ + +#define XEMACPS_LADDR1L_OFFSET 0x00000088U /**< Specific1 addr low reg */ +#define XEMACPS_LADDR1H_OFFSET 0x0000008CU /**< Specific1 addr high reg */ +#define XEMACPS_LADDR2L_OFFSET 0x00000090U /**< Specific2 addr low reg */ +#define XEMACPS_LADDR2H_OFFSET 0x00000094U /**< Specific2 addr high reg */ +#define XEMACPS_LADDR3L_OFFSET 0x00000098U /**< Specific3 addr low reg */ +#define XEMACPS_LADDR3H_OFFSET 0x0000009CU /**< Specific3 addr high reg */ +#define XEMACPS_LADDR4L_OFFSET 0x000000A0U /**< Specific4 addr low reg */ +#define XEMACPS_LADDR4H_OFFSET 0x000000A4U /**< Specific4 addr high reg */ + +#define XEMACPS_MATCH1_OFFSET 0x000000A8U /**< Type ID1 Match reg */ +#define XEMACPS_MATCH2_OFFSET 0x000000ACU /**< Type ID2 Match reg */ +#define XEMACPS_MATCH3_OFFSET 0x000000B0U /**< Type ID3 Match reg */ +#define XEMACPS_MATCH4_OFFSET 0x000000B4U /**< Type ID4 Match reg */ + +#define XEMACPS_STRETCH_OFFSET 0x000000BCU /**< IPG Stretch reg */ + +#define XEMACPS_OCTTXL_OFFSET 0x00000100U /**< Octects transmitted Low + reg */ +#define XEMACPS_OCTTXH_OFFSET 0x00000104U /**< Octects transmitted High + reg */ + +#define XEMACPS_TXCNT_OFFSET 0x00000108U /**< Error-free Frmaes + transmitted counter */ +#define XEMACPS_TXBCCNT_OFFSET 0x0000010CU /**< Error-free Broadcast + Frames counter*/ +#define XEMACPS_TXMCCNT_OFFSET 0x00000110U /**< Error-free Multicast + Frame counter */ +#define XEMACPS_TXPAUSECNT_OFFSET 0x00000114U /**< Pause Frames Transmitted + Counter */ +#define XEMACPS_TX64CNT_OFFSET 0x00000118U /**< Error-free 64 byte Frames + Transmitted counter */ +#define XEMACPS_TX65CNT_OFFSET 0x0000011CU /**< Error-free 65-127 byte + Frames Transmitted + counter */ +#define XEMACPS_TX128CNT_OFFSET 0x00000120U /**< Error-free 128-255 byte + Frames Transmitted + counter*/ +#define XEMACPS_TX256CNT_OFFSET 0x00000124U /**< Error-free 256-511 byte + Frames transmitted + counter */ +#define XEMACPS_TX512CNT_OFFSET 0x00000128U /**< Error-free 512-1023 byte + Frames transmitted + counter */ +#define XEMACPS_TX1024CNT_OFFSET 0x0000012CU /**< Error-free 1024-1518 byte + Frames transmitted + counter */ +#define XEMACPS_TX1519CNT_OFFSET 0x00000130U /**< Error-free larger than + 1519 byte Frames + transmitted counter */ +#define XEMACPS_TXURUNCNT_OFFSET 0x00000134U /**< TX under run error + counter */ + +#define XEMACPS_SNGLCOLLCNT_OFFSET 0x00000138U /**< Single Collision Frame + Counter */ +#define XEMACPS_MULTICOLLCNT_OFFSET 0x0000013CU /**< Multiple Collision Frame + Counter */ +#define XEMACPS_EXCESSCOLLCNT_OFFSET 0x00000140U /**< Excessive Collision Frame + Counter */ +#define XEMACPS_LATECOLLCNT_OFFSET 0x00000144U /**< Late Collision Frame + Counter */ +#define XEMACPS_TXDEFERCNT_OFFSET 0x00000148U /**< Deferred Transmission + Frame Counter */ +#define XEMACPS_TXCSENSECNT_OFFSET 0x0000014CU /**< Transmit Carrier Sense + Error Counter */ + +#define XEMACPS_OCTRXL_OFFSET 0x00000150U /**< Octects Received register + Low */ +#define XEMACPS_OCTRXH_OFFSET 0x00000154U /**< Octects Received register + High */ + +#define XEMACPS_RXCNT_OFFSET 0x00000158U /**< Error-free Frames + Received Counter */ +#define XEMACPS_RXBROADCNT_OFFSET 0x0000015CU /**< Error-free Broadcast + Frames Received Counter */ +#define XEMACPS_RXMULTICNT_OFFSET 0x00000160U /**< Error-free Multicast + Frames Received Counter */ +#define XEMACPS_RXPAUSECNT_OFFSET 0x00000164U /**< Pause Frames + Received Counter */ +#define XEMACPS_RX64CNT_OFFSET 0x00000168U /**< Error-free 64 byte Frames + Received Counter */ +#define XEMACPS_RX65CNT_OFFSET 0x0000016CU /**< Error-free 65-127 byte + Frames Received Counter */ +#define XEMACPS_RX128CNT_OFFSET 0x00000170U /**< Error-free 128-255 byte + Frames Received Counter */ +#define XEMACPS_RX256CNT_OFFSET 0x00000174U /**< Error-free 256-512 byte + Frames Received Counter */ +#define XEMACPS_RX512CNT_OFFSET 0x00000178U /**< Error-free 512-1023 byte + Frames Received Counter */ +#define XEMACPS_RX1024CNT_OFFSET 0x0000017CU /**< Error-free 1024-1518 byte + Frames Received Counter */ +#define XEMACPS_RX1519CNT_OFFSET 0x00000180U /**< Error-free 1519-max byte + Frames Received Counter */ +#define XEMACPS_RXUNDRCNT_OFFSET 0x00000184U /**< Undersize Frames Received + Counter */ +#define XEMACPS_RXOVRCNT_OFFSET 0x00000188U /**< Oversize Frames Received + Counter */ +#define XEMACPS_RXJABCNT_OFFSET 0x0000018CU /**< Jabbers Received + Counter */ +#define XEMACPS_RXFCSCNT_OFFSET 0x00000190U /**< Frame Check Sequence + Error Counter */ +#define XEMACPS_RXLENGTHCNT_OFFSET 0x00000194U /**< Length Field Error + Counter */ +#define XEMACPS_RXSYMBCNT_OFFSET 0x00000198U /**< Symbol Error Counter */ +#define XEMACPS_RXALIGNCNT_OFFSET 0x0000019CU /**< Alignment Error Counter */ +#define XEMACPS_RXRESERRCNT_OFFSET 0x000001A0U /**< Receive Resource Error + Counter */ +#define XEMACPS_RXORCNT_OFFSET 0x000001A4U /**< Receive Overrun Counter */ +#define XEMACPS_RXIPCCNT_OFFSET 0x000001A8U /**< IP header Checksum Error + Counter */ +#define XEMACPS_RXTCPCCNT_OFFSET 0x000001ACU /**< TCP Checksum Error + Counter */ +#define XEMACPS_RXUDPCCNT_OFFSET 0x000001B0U /**< UDP Checksum Error + Counter */ +#define XEMACPS_LAST_OFFSET 0x000001B4U /**< Last statistic counter + offset, for clearing */ + +#define XEMACPS_1588_SEC_OFFSET 0x000001D0U /**< 1588 second counter */ +#define XEMACPS_1588_NANOSEC_OFFSET 0x000001D4U /**< 1588 nanosecond counter */ +#define XEMACPS_1588_ADJ_OFFSET 0x000001D8U /**< 1588 nanosecond + adjustment counter */ +#define XEMACPS_1588_INC_OFFSET 0x000001DCU /**< 1588 nanosecond + increment counter */ +#define XEMACPS_PTP_TXSEC_OFFSET 0x000001E0U /**< 1588 PTP transmit second + counter */ +#define XEMACPS_PTP_TXNANOSEC_OFFSET 0x000001E4U /**< 1588 PTP transmit + nanosecond counter */ +#define XEMACPS_PTP_RXSEC_OFFSET 0x000001E8U /**< 1588 PTP receive second + counter */ +#define XEMACPS_PTP_RXNANOSEC_OFFSET 0x000001ECU /**< 1588 PTP receive + nanosecond counter */ +#define XEMACPS_PTPP_TXSEC_OFFSET 0x000001F0U /**< 1588 PTP peer transmit + second counter */ +#define XEMACPS_PTPP_TXNANOSEC_OFFSET 0x000001F4U /**< 1588 PTP peer transmit + nanosecond counter */ +#define XEMACPS_PTPP_RXSEC_OFFSET 0x000001F8U /**< 1588 PTP peer receive + second counter */ +#define XEMACPS_PTPP_RXNANOSEC_OFFSET 0x000001FCU /**< 1588 PTP peer receive + nanosecond counter */ +#define XEMACPS_PCS_CONTROL_OFFSET 0x00000200U /** PCS control register */ +#define XEMACPS_PCS_STATUS_OFFSET 0x00000204U /** PCS status register */ + +#define XEMACPS_INTQ1_STS_OFFSET 0x00000400U /**< Interrupt Q1 Status + reg */ +#define XEMACPS_TXQ1BASE_OFFSET 0x00000440U /**< TX Q1 Base address + reg */ +#define XEMACPS_RXQ1BASE_OFFSET 0x00000480U /**< RX Q1 Base address + reg */ +#define XEMACPS_MSBBUF_TXQBASE_OFFSET 0x000004C8U /**< MSB Buffer TX Q Base + reg */ +#define XEMACPS_MSBBUF_RXQBASE_OFFSET 0x000004D4U /**< MSB Buffer RX Q Base + reg */ +#define XEMACPS_INTQ1_IER_OFFSET 0x00000600U /**< Interrupt Q1 Enable + reg */ +#define XEMACPS_INTQ1_IDR_OFFSET 0x00000620U /**< Interrupt Q1 Disable + reg */ +#define XEMACPS_INTQ1_IMR_OFFSET 0x00000640U /**< Interrupt Q1 Mask + reg */ + +/* Define some bit positions for registers. */ + +/** @name network control register bit definitions + * @{ + */ +#define XEMACPS_NWCTRL_FLUSH_DPRAM_MASK 0x00040000U /**< Flush a packet from + Rx SRAM */ +#define XEMACPS_NWCTRL_ZEROPAUSETX_MASK 0x00000800U /**< Transmit zero quantum + pause frame */ +#define XEMACPS_NWCTRL_PAUSETX_MASK 0x00000800U /**< Transmit pause frame */ +#define XEMACPS_NWCTRL_HALTTX_MASK 0x00000400U /**< Halt transmission + after current frame */ +#define XEMACPS_NWCTRL_STARTTX_MASK 0x00000200U /**< Start tx (tx_go) */ + +#define XEMACPS_NWCTRL_STATWEN_MASK 0x00000080U /**< Enable writing to + stat counters */ +#define XEMACPS_NWCTRL_STATINC_MASK 0x00000040U /**< Increment statistic + registers */ +#define XEMACPS_NWCTRL_STATCLR_MASK 0x00000020U /**< Clear statistic + registers */ +#define XEMACPS_NWCTRL_MDEN_MASK 0x00000010U /**< Enable MDIO port */ +#define XEMACPS_NWCTRL_TXEN_MASK 0x00000008U /**< Enable transmit */ +#define XEMACPS_NWCTRL_RXEN_MASK 0x00000004U /**< Enable receive */ +#define XEMACPS_NWCTRL_LOOPEN_MASK 0x00000002U /**< local loopback */ +/*@}*/ + +/** @name network configuration register bit definitions + * @{ + */ +#define XEMACPS_NWCFG_BADPREAMBEN_MASK 0x20000000U /**< disable rejection of + non-standard preamble */ +#define XEMACPS_NWCFG_IPDSTRETCH_MASK 0x10000000U /**< enable transmit IPG */ +#define XEMACPS_NWCFG_SGMIIEN_MASK 0x08000000U /**< SGMII Enable */ +#define XEMACPS_NWCFG_FCSIGNORE_MASK 0x04000000U /**< disable rejection of + FCS error */ +#define XEMACPS_NWCFG_HDRXEN_MASK 0x02000000U /**< RX half duplex */ +#define XEMACPS_NWCFG_RXCHKSUMEN_MASK 0x01000000U /**< enable RX checksum + offload */ +#define XEMACPS_NWCFG_PAUSECOPYDI_MASK 0x00800000U /**< Do not copy pause + Frames to memory */ +#define XEMACPS_NWCFG_DWIDTH_64_MASK 0x00200000U /**< 64 bit Data bus width */ +#define XEMACPS_NWCFG_MDC_SHIFT_MASK 18U /**< shift bits for MDC */ +#define XEMACPS_NWCFG_MDCCLKDIV_MASK 0x001C0000U /**< MDC Mask PCLK divisor */ +#define XEMACPS_NWCFG_FCSREM_MASK 0x00020000U /**< Discard FCS from + received frames */ +#define XEMACPS_NWCFG_LENERRDSCRD_MASK 0x00010000U +/**< RX length error discard */ +#define XEMACPS_NWCFG_RXOFFS_MASK 0x0000C000U /**< RX buffer offset */ +#define XEMACPS_NWCFG_PAUSEEN_MASK 0x00002000U /**< Enable pause RX */ +#define XEMACPS_NWCFG_RETRYTESTEN_MASK 0x00001000U /**< Retry test */ +#define XEMACPS_NWCFG_XTADDMACHEN_MASK 0x00000200U +/**< External address match enable */ +#define XEMACPS_NWCFG_PCSSEL_MASK 0x00000800U /**< PCS Select */ +#define XEMACPS_NWCFG_1000_MASK 0x00000400U /**< 1000 Mbps */ +#define XEMACPS_NWCFG_1536RXEN_MASK 0x00000100U /**< Enable 1536 byte + frames reception */ +#define XEMACPS_NWCFG_UCASTHASHEN_MASK 0x00000080U /**< Receive unicast hash + frames */ +#define XEMACPS_NWCFG_MCASTHASHEN_MASK 0x00000040U /**< Receive multicast hash + frames */ +#define XEMACPS_NWCFG_BCASTDI_MASK 0x00000020U /**< Do not receive + broadcast frames */ +#define XEMACPS_NWCFG_COPYALLEN_MASK 0x00000010U /**< Copy all frames */ +#define XEMACPS_NWCFG_JUMBO_MASK 0x00000008U /**< Jumbo frames */ +#define XEMACPS_NWCFG_NVLANDISC_MASK 0x00000004U /**< Receive only VLAN + frames */ +#define XEMACPS_NWCFG_FDEN_MASK 0x00000002U/**< full duplex */ +#define XEMACPS_NWCFG_100_MASK 0x00000001U /**< 100 Mbps */ +#define XEMACPS_NWCFG_RESET_MASK 0x00080000U/**< reset value */ +/*@}*/ + +/** @name network status register bit definitaions + * @{ + */ +#define XEMACPS_NWSR_MDIOIDLE_MASK 0x00000004U /**< PHY management idle */ +#define XEMACPS_NWSR_MDIO_MASK 0x00000002U /**< Status of mdio_in */ +/*@}*/ + + +/** @name MAC address register word 1 mask + * @{ + */ +#define XEMACPS_LADDR_MACH_MASK 0x0000FFFFU /**< Address bits[47:32] + bit[31:0] are in BOTTOM */ +/*@}*/ + + +/** @name DMA control register bit definitions + * @{ + */ +#define XEMACPS_DMACR_ADDR_WIDTH_64 0x40000000U /**< 64 bit address bus */ +#define XEMACPS_DMACR_TXEXTEND_MASK 0x20000000U /**< Tx Extended desc mode */ +#define XEMACPS_DMACR_RXEXTEND_MASK 0x10000000U /**< Rx Extended desc mode */ +#define XEMACPS_DMACR_RXBUF_MASK 0x00FF0000U /**< Mask bit for RX buffer + size */ +#define XEMACPS_DMACR_RXBUF_SHIFT 16U /**< Shift bit for RX buffer + size */ +#define XEMACPS_DMACR_TCPCKSUM_MASK 0x00000800U /**< enable/disable TX + checksum offload */ +#define XEMACPS_DMACR_TXSIZE_MASK 0x00000400U /**< TX buffer memory size */ +#define XEMACPS_DMACR_RXSIZE_MASK 0x00000300U /**< RX buffer memory size */ +#define XEMACPS_DMACR_ENDIAN_MASK 0x00000080U /**< endian configuration */ +#define XEMACPS_DMACR_BLENGTH_MASK 0x0000001FU /**< buffer burst length */ +#define XEMACPS_DMACR_SINGLE_AHB_BURST 0x00000001U /**< single AHB bursts */ +#define XEMACPS_DMACR_INCR4_AHB_BURST 0x00000004U /**< 4 bytes AHB bursts */ +#define XEMACPS_DMACR_INCR8_AHB_BURST 0x00000008U /**< 8 bytes AHB bursts */ +#define XEMACPS_DMACR_INCR16_AHB_BURST 0x00000010U /**< 16 bytes AHB bursts */ +/*@}*/ + +/** @name transmit status register bit definitions + * @{ + */ +#define XEMACPS_TXSR_HRESPNOK_MASK 0x00000100U /**< Transmit hresp not OK */ +#define XEMACPS_TXSR_URUN_MASK 0x00000040U /**< Transmit underrun */ +#define XEMACPS_TXSR_TXCOMPL_MASK 0x00000020U /**< Transmit completed OK */ +#define XEMACPS_TXSR_BUFEXH_MASK 0x00000010U /**< Transmit buffs exhausted + mid frame */ +#define XEMACPS_TXSR_TXGO_MASK 0x00000008U /**< Status of go flag */ +#define XEMACPS_TXSR_RXOVR_MASK 0x00000004U /**< Retry limit exceeded */ +#define XEMACPS_TXSR_FRAMERX_MASK 0x00000002U /**< Collision tx frame */ +#define XEMACPS_TXSR_USEDREAD_MASK 0x00000001U /**< TX buffer used bit set */ + +#define XEMACPS_TXSR_ERROR_MASK ((u32)XEMACPS_TXSR_HRESPNOK_MASK | \ + (u32)XEMACPS_TXSR_URUN_MASK | \ + (u32)XEMACPS_TXSR_BUFEXH_MASK | \ + (u32)XEMACPS_TXSR_RXOVR_MASK | \ + (u32)XEMACPS_TXSR_FRAMERX_MASK | \ + (u32)XEMACPS_TXSR_USEDREAD_MASK) +/*@}*/ + +/** + * @name receive status register bit definitions + * @{ + */ +#define XEMACPS_RXSR_HRESPNOK_MASK 0x00000008U /**< Receive hresp not OK */ +#define XEMACPS_RXSR_RXOVR_MASK 0x00000004U /**< Receive overrun */ +#define XEMACPS_RXSR_FRAMERX_MASK 0x00000002U /**< Frame received OK */ +#define XEMACPS_RXSR_BUFFNA_MASK 0x00000001U /**< RX buffer used bit set */ + +#define XEMACPS_RXSR_ERROR_MASK ((u32)XEMACPS_RXSR_HRESPNOK_MASK | \ + (u32)XEMACPS_RXSR_RXOVR_MASK | \ + (u32)XEMACPS_RXSR_BUFFNA_MASK) + +#define XEMACPS_SR_ALL_MASK 0xFFFFFFFFU /**< Mask for full register */ + +/*@}*/ + +/** + * @name PCS control register bit definitions + * @{ + */ +#define XEMACPS_PCS_CON_AUTO_NEG_MASK 0x00001000U /**< Auto-negotiation */ +/*@}*/ + +/** + * @name PCS status register bit definitions + * @{ + */ +#define XEMACPS_PCS_STATUS_LINK_STATUS_MASK 0x00000004U /**< Link status */ +/*@}*/ + +/** + * @name Interrupt Q1 status register bit definitions + * @{ + */ +#define XEMACPS_INTQ1SR_TXCOMPL_MASK 0x00000080U /**< Transmit completed OK */ +#define XEMACPS_INTQ1SR_TXERR_MASK 0x00000040U /**< Transmit AMBA Error */ + +#define XEMACPS_INTQ1_IXR_ALL_MASK ((u32)XEMACPS_INTQ1SR_TXCOMPL_MASK | \ + (u32)XEMACPS_INTQ1SR_TXERR_MASK) + +/*@}*/ + +/** + * @name interrupts bit definitions + * Bits definitions are same in XEMACPS_ISR_OFFSET, + * XEMACPS_IER_OFFSET, XEMACPS_IDR_OFFSET, and XEMACPS_IMR_OFFSET + * @{ + */ +#define XEMACPS_IXR_PTPPSTX_MASK 0x02000000U /**< PTP Pdelay_resp TXed */ +#define XEMACPS_IXR_PTPPDRTX_MASK 0x01000000U /**< PTP Pdelay_req TXed */ +#define XEMACPS_IXR_PTPPSRX_MASK 0x00800000U /**< PTP Pdelay_resp RXed */ +#define XEMACPS_IXR_PTPPDRRX_MASK 0x00400000U /**< PTP Pdelay_req RXed */ + +#define XEMACPS_IXR_PTPSTX_MASK 0x00200000U /**< PTP Sync TXed */ +#define XEMACPS_IXR_PTPDRTX_MASK 0x00100000U /**< PTP Delay_req TXed */ +#define XEMACPS_IXR_PTPSRX_MASK 0x00080000U /**< PTP Sync RXed */ +#define XEMACPS_IXR_PTPDRRX_MASK 0x00040000U /**< PTP Delay_req RXed */ + +#define XEMACPS_IXR_PAUSETX_MASK 0x00004000U /**< Pause frame transmitted */ +#define XEMACPS_IXR_PAUSEZERO_MASK 0x00002000U /**< Pause time has reached + zero */ +#define XEMACPS_IXR_PAUSENZERO_MASK 0x00001000U /**< Pause frame received */ +#define XEMACPS_IXR_HRESPNOK_MASK 0x00000800U /**< hresp not ok */ +#define XEMACPS_IXR_RXOVR_MASK 0x00000400U /**< Receive overrun occurred */ +#define XEMACPS_IXR_TXCOMPL_MASK 0x00000080U /**< Frame transmitted ok */ +#define XEMACPS_IXR_TXEXH_MASK 0x00000040U /**< Transmit err occurred or + no buffers*/ +#define XEMACPS_IXR_RETRY_MASK 0x00000020U /**< Retry limit exceeded */ +#define XEMACPS_IXR_URUN_MASK 0x00000010U /**< Transmit underrun */ +#define XEMACPS_IXR_TXUSED_MASK 0x00000008U /**< Tx buffer used bit read */ +#define XEMACPS_IXR_RXUSED_MASK 0x00000004U /**< Rx buffer used bit read */ +#define XEMACPS_IXR_FRAMERX_MASK 0x00000002U /**< Frame received ok */ +#define XEMACPS_IXR_MGMNT_MASK 0x00000001U /**< PHY management complete */ +#define XEMACPS_IXR_ALL_MASK 0x00007FFFU /**< Everything! */ + +#define XEMACPS_IXR_TX_ERR_MASK ((u32)XEMACPS_IXR_TXEXH_MASK | \ + (u32)XEMACPS_IXR_RETRY_MASK | \ + (u32)XEMACPS_IXR_URUN_MASK) + + +#define XEMACPS_IXR_RX_ERR_MASK ((u32)XEMACPS_IXR_HRESPNOK_MASK | \ + (u32)XEMACPS_IXR_RXUSED_MASK | \ + (u32)XEMACPS_IXR_RXOVR_MASK) + +/*@}*/ + +/** @name PHY Maintenance bit definitions + * @{ + */ +#define XEMACPS_PHYMNTNC_OP_MASK 0x40020000U /**< operation mask bits */ +#define XEMACPS_PHYMNTNC_OP_R_MASK 0x20000000U /**< read operation */ +#define XEMACPS_PHYMNTNC_OP_W_MASK 0x10000000U /**< write operation */ +#define XEMACPS_PHYMNTNC_ADDR_MASK 0x0F800000U /**< Address bits */ +#define XEMACPS_PHYMNTNC_REG_MASK 0x007C0000U /**< register bits */ +#define XEMACPS_PHYMNTNC_DATA_MASK 0x00000FFFU /**< data bits */ +#define XEMACPS_PHYMNTNC_PHAD_SHFT_MSK 23U /**< Shift bits for PHYAD */ +#define XEMACPS_PHYMNTNC_PREG_SHFT_MSK 18U /**< Shift bits for PHREG */ +/*@}*/ + +/** @name RX watermark bit definitions + * @{ + */ +#define XEMACPS_RXWM_HIGH_MASK 0x0000FFFFU /**< RXWM high mask */ +#define XEMACPS_RXWM_LOW_MASK 0xFFFF0000U /**< RXWM low mask */ +#define XEMACPS_RXWM_LOW_SHFT_MSK 16U /**< Shift for RXWM low */ +/*@}*/ + +/* Transmit buffer descriptor status words offset + * @{ + */ +#define XEMACPS_BD_ADDR_OFFSET 0x00000000U /**< word 0/addr of BDs */ +#define XEMACPS_BD_STAT_OFFSET 0x00000004U /**< word 1/status of BDs */ +#define XEMACPS_BD_ADDR_HI_OFFSET 0x00000008U /**< word 2/addr of BDs */ + +/* + * @} + */ + +/* Transmit buffer descriptor status words bit positions. + * Transmit buffer descriptor consists of two 32-bit registers, + * the first - word0 contains a 32-bit address pointing to the location of + * the transmit data. + * The following register - word1, consists of various information to control + * the XEmacPs transmit process. After transmit, this is updated with status + * information, whether the frame was transmitted OK or why it had failed. + * @{ + */ +#define XEMACPS_TXBUF_USED_MASK 0x80000000U /**< Used bit. */ +#define XEMACPS_TXBUF_WRAP_MASK 0x40000000U /**< Wrap bit, last descriptor */ +#define XEMACPS_TXBUF_RETRY_MASK 0x20000000U /**< Retry limit exceeded */ +#define XEMACPS_TXBUF_URUN_MASK 0x10000000U /**< Transmit underrun occurred */ +#define XEMACPS_TXBUF_EXH_MASK 0x08000000U /**< Buffers exhausted */ +#define XEMACPS_TXBUF_TCP_MASK 0x04000000U /**< Late collision. */ +#define XEMACPS_TXBUF_NOCRC_MASK 0x00010000U /**< No CRC */ +#define XEMACPS_TXBUF_LAST_MASK 0x00008000U /**< Last buffer */ +#define XEMACPS_TXBUF_LEN_MASK 0x00003FFFU /**< Mask for length field */ +/* + * @} + */ + +/* Receive buffer descriptor status words bit positions. + * Receive buffer descriptor consists of two 32-bit registers, + * the first - word0 contains a 32-bit word aligned address pointing to the + * address of the buffer. The lower two bits make up the wrap bit indicating + * the last descriptor and the ownership bit to indicate it has been used by + * the XEmacPs. + * The following register - word1, contains status information regarding why + * the frame was received (the filter match condition) as well as other + * useful info. + * @{ + */ +#define XEMACPS_RXBUF_BCAST_MASK 0x80000000U /**< Broadcast frame */ +#define XEMACPS_RXBUF_MULTIHASH_MASK 0x40000000U /**< Multicast hashed frame */ +#define XEMACPS_RXBUF_UNIHASH_MASK 0x20000000U /**< Unicast hashed frame */ +#define XEMACPS_RXBUF_EXH_MASK 0x08000000U /**< buffer exhausted */ +#define XEMACPS_RXBUF_AMATCH_MASK 0x06000000U /**< Specific address + matched */ +#define XEMACPS_RXBUF_IDFOUND_MASK 0x01000000U /**< Type ID matched */ +#define XEMACPS_RXBUF_IDMATCH_MASK 0x00C00000U /**< ID matched mask */ +#define XEMACPS_RXBUF_VLAN_MASK 0x00200000U /**< VLAN tagged */ +#define XEMACPS_RXBUF_PRI_MASK 0x00100000U /**< Priority tagged */ +#define XEMACPS_RXBUF_VPRI_MASK 0x000E0000U /**< Vlan priority */ +#define XEMACPS_RXBUF_CFI_MASK 0x00010000U /**< CFI frame */ +#define XEMACPS_RXBUF_EOF_MASK 0x00008000U /**< End of frame. */ +#define XEMACPS_RXBUF_SOF_MASK 0x00004000U /**< Start of frame. */ +#define XEMACPS_RXBUF_LEN_MASK 0x00001FFFU /**< Mask for length field */ +#define XEMACPS_RXBUF_LEN_JUMBO_MASK 0x00003FFFU /**< Mask for jumbo length */ + +#define XEMACPS_RXBUF_WRAP_MASK 0x00000002U /**< Wrap bit, last BD */ +#define XEMACPS_RXBUF_NEW_MASK 0x00000001U /**< Used bit.. */ +#define XEMACPS_RXBUF_ADD_MASK 0xFFFFFFFCU /**< Mask for address */ +/* + * @} + */ + +/* + * Define appropriate I/O access method to memory mapped I/O or other + * interface if necessary. + */ + +#define XEmacPs_In32 Xil_In32 +#define XEmacPs_Out32 Xil_Out32 + + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddress is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XEmacPs_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XEmacPs_ReadReg(BaseAddress, RegOffset) \ + XEmacPs_In32((BaseAddress) + (u32)(RegOffset)) + + +/****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddress is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XEmacPs_WriteReg(u32 BaseAddress, u32 RegOffset, +* u32 Data) +* +*****************************************************************************/ +#define XEmacPs_WriteReg(BaseAddress, RegOffset, Data) \ + XEmacPs_Out32((BaseAddress) + (u32)(RegOffset), (u32)(Data)) + +/************************** Function Prototypes *****************************/ +/* + * Perform reset operation to the emacps interface + */ +void XEmacPs_ResetHw(u32 BaseAddr); + +#ifdef __cplusplus + } +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_intr.c b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_intr.c new file mode 100644 index 0000000..2dbdb0b --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_intr.c @@ -0,0 +1,242 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_intr.c +* @addtogroup emacps_v3_16 +* @{ +* +* Functions in this file implement general purpose interrupt processing related +* functionality. See xemacps.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 1.03a asa  01/24/13 Fix for CR #692702 which updates error handling for
+*		      Rx errors. Under heavy Rx traffic, there will be a large
+*		      number of errors related to receive buffer not available.
+*		      Because of a HW bug (SI #692601), under such heavy errors,
+*		      the Rx data path can become unresponsive. To reduce the
+*		      probabilities for hitting this HW bug, the SW writes to
+*		      bit 18 to flush a packet from Rx DPRAM immediately. The
+*		      changes for it are done in the function
+*		      XEmacPs_IntrHandler.
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification
+*		       and 64-bit changes.
+* 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1   hk   07/27/15 Do not call error handler with '0' error code when
+*                     there is no error. CR# 869403
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xemacps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** + * Install an asynchronous handler function for the given HandlerType: + * + * @param InstancePtr is a pointer to the instance to be worked on. + * @param HandlerType indicates what interrupt handler type is. + * XEMACPS_HANDLER_DMASEND, XEMACPS_HANDLER_DMARECV and + * XEMACPS_HANDLER_ERROR. + * @param FuncPointer is the pointer to the callback function + * @param CallBackRef is the upper layer callback reference passed back when + * when the callback function is invoked. + * + * @return + * + * None. + * + * @note + * There is no assert on the CallBackRef since the driver doesn't know what + * it is. + * + *****************************************************************************/ +LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType, + void *FuncPointer, void *CallBackRef) +{ + LONG Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(FuncPointer != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + switch (HandlerType) { + case XEMACPS_HANDLER_DMASEND: + Status = (LONG)(XST_SUCCESS); + InstancePtr->SendHandler = ((XEmacPs_Handler)(void *)FuncPointer); + InstancePtr->SendRef = CallBackRef; + break; + case XEMACPS_HANDLER_DMARECV: + Status = (LONG)(XST_SUCCESS); + InstancePtr->RecvHandler = ((XEmacPs_Handler)(void *)FuncPointer); + InstancePtr->RecvRef = CallBackRef; + break; + case XEMACPS_HANDLER_ERROR: + Status = (LONG)(XST_SUCCESS); + InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void *)FuncPointer); + InstancePtr->ErrorRef = CallBackRef; + break; + default: + Status = (LONG)(XST_INVALID_PARAM); + break; + } + return Status; +} + +/*****************************************************************************/ +/** +* Master interrupt handler for EMAC driver. This routine will query the +* status of the device, bump statistics, and invoke user callbacks. +* +* This routine must be connected to an interrupt controller using OS/BSP +* specific methods. +* +* @param XEmacPsPtr is a pointer to the XEMACPS instance that has caused the +* interrupt. +* +******************************************************************************/ +void XEmacPs_IntrHandler(void *XEmacPsPtr) +{ + u32 RegISR; + u32 RegSR; + u32 RegCtrl; + u32 RegQ1ISR = 0U; + XEmacPs *InstancePtr = (XEmacPs *) XEmacPsPtr; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY); + + /* This ISR will try to handle as many interrupts as it can in a single + * call. However, in most of the places where the user's error handler + * is called, this ISR exits because it is expected that the user will + * reset the device in nearly all instances. + */ + RegISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_ISR_OFFSET); + + /* Read Transmit Q1 ISR */ + + if (InstancePtr->Version > 2) + RegQ1ISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_INTQ1_STS_OFFSET); + + /* Clear the interrupt status register */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET, + RegISR); + + /* Receive complete interrupt */ + if ((RegISR & XEMACPS_IXR_FRAMERX_MASK) != 0x00000000U) { + /* Clear RX status register RX complete indication but preserve + * error bits if there is any */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXSR_OFFSET, + ((u32)XEMACPS_RXSR_FRAMERX_MASK | + (u32)XEMACPS_RXSR_BUFFNA_MASK)); + InstancePtr->RecvHandler(InstancePtr->RecvRef); + } + + /* Transmit Q1 complete interrupt */ + if ((InstancePtr->Version > 2) && + ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) { + /* Clear TX status register TX complete indication but preserve + * error bits if there is any */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_INTQ1_STS_OFFSET, + XEMACPS_INTQ1SR_TXCOMPL_MASK); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET, + ((u32)XEMACPS_TXSR_TXCOMPL_MASK | + (u32)XEMACPS_TXSR_USEDREAD_MASK)); + InstancePtr->SendHandler(InstancePtr->SendRef); + } + + /* Transmit complete interrupt */ + if ((RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U) { + /* Clear TX status register TX complete indication but preserve + * error bits if there is any */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET, + ((u32)XEMACPS_TXSR_TXCOMPL_MASK | + (u32)XEMACPS_TXSR_USEDREAD_MASK)); + InstancePtr->SendHandler(InstancePtr->SendRef); + } + + /* Receive error conditions interrupt */ + if ((RegISR & XEMACPS_IXR_RX_ERR_MASK) != 0x00000000U) { + /* Clear RX status register */ + RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXSR_OFFSET); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_RXSR_OFFSET, RegSR); + + /* Fix for CR # 692702. Write to bit 18 of net_ctrl + * register to flush a packet out of Rx SRAM upon + * an error for receive buffer not available. */ + if ((RegISR & XEMACPS_IXR_RXUSED_MASK) != 0x00000000U) { + RegCtrl = + XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET); + RegCtrl |= (u32)XEMACPS_NWCTRL_FLUSH_DPRAM_MASK; + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_NWCTRL_OFFSET, RegCtrl); + } + + if(RegSR != 0) { + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, + XEMACPS_RECV, RegSR); + } + } + + /* When XEMACPS_IXR_TXCOMPL_MASK is flagged, XEMACPS_IXR_TXUSED_MASK + * will be asserted the same time. + * Have to distinguish this bit to handle the real error condition. + */ + /* Transmit Q1 error conditions interrupt */ + if ((InstancePtr->Version > 2) && + ((RegQ1ISR & XEMACPS_INTQ1SR_TXERR_MASK) != 0x00000000U) && + ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) { + /* Clear Interrupt Q1 status register */ + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_INTQ1_STS_OFFSET, RegQ1ISR); + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, + RegQ1ISR); + } + + /* Transmit error conditions interrupt */ + if (((RegISR & XEMACPS_IXR_TX_ERR_MASK) != 0x00000000U) && + (!(RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U)) { + /* Clear TX status register */ + RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET); + XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, + XEMACPS_TXSR_OFFSET, RegSR); + InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND, + RegSR); + } + +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_sinit.c new file mode 100644 index 0000000..8214a7d --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/emacps/src/xemacps_sinit.c @@ -0,0 +1,71 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xemacps_sinit.c +* @addtogroup emacps_v3_16 +* @{ +* +* This file contains lookup method by device ID when success, it returns +* pointer to config table to be used to initialize the device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 New
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xemacps.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/*************************** Variable Definitions *****************************/ +extern XEmacPs_Config XEmacPs_ConfigTable[XPAR_XEMACPS_NUM_INSTANCES]; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return +* A pointer to the configuration table entry corresponding to the given +* device ID, or NULL if no match is found. +* +******************************************************************************/ +XEmacPs_Config *XEmacPs_LookupConfig(u16 DeviceId) +{ + XEmacPs_Config *CfgPtr = NULL; + u32 i; + + for (i = 0U; i < (u32)XPAR_XEMACPS_NUM_INSTANCES; i++) { + if (XEmacPs_ConfigTable[i].DeviceId == DeviceId) { + CfgPtr = &XEmacPs_ConfigTable[i]; + break; + } + } + + return (XEmacPs_Config *)(CfgPtr); +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/Makefile new file mode 100644 index 0000000..5feeb49 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/Makefile @@ -0,0 +1,39 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf $(DEPFILES) diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops.c b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops.c new file mode 100644 index 0000000..460bb2b --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops.c @@ -0,0 +1,820 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xgpiops.c +* @addtogroup gpiops Overview +* @{ +* +* The XGpioPs driver. Functions in this file are the minimum required functions +* for this driver. See xgpiops.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.01a sv   04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
+*                     XGpioPs_GetMode, XGpioPs_GetModePin as they are not
+*		      relevant to Zynq device. The interrupts are disabled
+*		      for output pins on all banks during initialization.
+* 2.1   hk   04/29/14 Use Input data register DATA_RO for read. CR# 771667.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.1   aru  07/13/18 Resolved doxygen reported warnings. CR# 1006331.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in safety mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the pointer param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/13/19 Added Versal support.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops.h" + +/************************** Constant Definitions *****************************/ +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + +void StubHandler(void *CallBackRef, u32 Bank, u32 Status); /**< Stub handler */ + +/*****************************************************************************/ +/** +* +* This function initializes a XGpioPs instance/driver. +* All members of the XGpioPs instance structure are initialized and +* StubHandlers are assigned to the Bank Status Handlers. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param ConfigPtr points to the XGpioPs device configuration structure. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. If the address translation is not used then the +* physical address should be passed. +* Unexpected errors may occur if the address mapping is changed +* after this function is invoked. +* +* @return XST_SUCCESS always. +* +* @note None. +* +******************************************************************************/ +s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + s32 Status = (s32)0; + u8 i; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + Xil_AssertNonvoid(EffectiveAddr != (u32)0); + /* + * Set some default values for instance data, don't indicate the device + * is ready to use until everything has been initialized successfully. + */ + InstancePtr->IsReady = 0U; + InstancePtr->GpioConfig.BaseAddr = EffectiveAddr; + InstancePtr->GpioConfig.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Handler = (XGpioPs_Handler)StubHandler; + InstancePtr->Platform = XGetPlatform_Info(); + + /* Initialize the Bank data based on platform */ + if (InstancePtr->Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + /* + * Max pins in the ZynqMP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 + */ + InstancePtr->MaxPinNum = (u32)174; + InstancePtr->MaxBanks = (u8)6; + } + else if (InstancePtr->Platform == (u32)XPLAT_VERSAL) + { + if(InstancePtr->PmcGpio == (u32)FALSE) + { + /* Max pins in the PS_GPIO devices + * 0 -25, Bank 0 + * 26-57, Bank 3 + */ + InstancePtr->MaxPinNum = (u32)58; + InstancePtr->MaxBanks = (u8)4; + } + else + { + /* Max pins in the PMC_GPIO devices + * 0 - 25,Bank 0 + * 26 - 51,Bank 1 + * 52 - 83,Bank 3 + * 84 - 115, Bank 4 + */ + InstancePtr->MaxPinNum = (u32)116; + InstancePtr->MaxBanks = (u8)5; + } + } + else { + /* + * Max pins in the GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 + */ + InstancePtr->MaxPinNum = (u32)118; + InstancePtr->MaxBanks = (u8)4; + } + + /* + * By default, interrupts are not masked in GPIO. Disable + * interrupts for all pins in all the 4 banks. + */ + for (i=(u8)0U;iMaxBanks;i++) { + if (InstancePtr->Platform == XPLAT_VERSAL){ + if(InstancePtr->PmcGpio == (u32)FALSE) + { + if((i== (u8)XGPIOPS_ONE)||(i== (u8)XGPIOPS_TWO)) + { + continue; + } + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); + } + else + { + if(i==(u32)XGPIOPS_TWO) + { + continue; + } + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); + + } + } + else + { + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU); + } + } + + /* Indicate the component is now ready to use. */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return Status; +} + +/****************************************************************************/ +/** +* +* Read the Data register of the specified GPIO bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* +* @return Current value of the Data register. +* +* @note This function is used for reading the state of all the GPIO pins +* of specified bank. +* +*****************************************************************************/ +u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_RO_OFFSET); +} + +/****************************************************************************/ +/** +* +* Read Data from the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the data has to be read. +* +* @return Current value of the Pin (0 or 1). +* +* @note This function is used for reading the state of the specified +* GPIO pin. +* +*****************************************************************************/ +u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_RO_OFFSET) >> (u32)PinNumber) & (u32)1; + +} + +/****************************************************************************/ +/** +* +* Write to the Data register of the specified GPIO bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* @param Data is the value to be written to the Data register. +* +* @return None. +* +* @note This function is used for writing to all the GPIO pins of +* the bank. The previous state of the pins is not maintained. +* +*****************************************************************************/ +void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_OFFSET, Data); +} + +/****************************************************************************/ +/** +* +* Write data to the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* @param Data is the data to be written to the specified pin (0 or 1). +* +* @return None. +* +* @note This function does a masked write to the specified pin of +* the specified GPIO bank. The previous state of other pins +* is maintained. +* +*****************************************************************************/ +void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data) +{ + u32 RegOffset; + u32 Value; + u8 Bank; + u8 PinNumber; + u32 DataVar = Data; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + if (PinNumber > 15U) { + /* There are only 16 data bits in bit maskable register. */ + PinNumber -= (u8)16; + RegOffset = XGPIOPS_DATA_MSW_OFFSET; + } else { + RegOffset = XGPIOPS_DATA_LSW_OFFSET; + } + + /* + * Get the 32 bit value to be written to the Mask/Data register where + * the upper 16 bits is the mask and lower 16 bits is the data. + */ + DataVar &= (u32)0x01; + Value = ~((u32)1 << (PinNumber + 16U)) & ((DataVar << PinNumber) | 0xFFFF0000U); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) + + RegOffset, Value); + +} + + + +/****************************************************************************/ +/** +* +* Set the Direction of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* @param Direction is the 32 bit mask of the Pin direction to be set for +* all the pins in the Bank. Bits with 0 are set to Input mode, +* bits with 1 are set to Output Mode. +* +* @return None. +* +* @note This function is used for setting the direction of all the pins +* in the specified bank. The previous state of the pins is +* not maintained. +* +*****************************************************************************/ +void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET, Direction); +} + +/****************************************************************************/ +/** +* +* Set the Direction of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* @param Direction is the direction to be set for the specified pin. +* Valid values are 0 for Input Direction, 1 for Output Direction. +* +* @return None. +* +*****************************************************************************/ +void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction) +{ + u8 Bank; + u8 PinNumber; + u32 DirModeReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(Direction <= (u32)1); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + DirModeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET); + + if (Direction!=(u32)0) { /* Output Direction */ + DirModeReg |= ((u32)1 << (u32)PinNumber); + } else { /* Input Direction */ + DirModeReg &= ~ ((u32)1 << (u32)PinNumber); + } + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET, DirModeReg); +} + +/****************************************************************************/ +/** +* +* Get the Direction of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* +* @return Returns a 32 bit mask of the Direction register. Bits with 0 are +* in Input mode, bits with 1 are in Output Mode. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET); +} + +/****************************************************************************/ +/** +* +* Get the Direction of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the Direction is to be +* retrieved. +* +* @return Direction of the specified pin. +* - 0 for Input Direction +* - 1 for Output Direction +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET) >> (u32)PinNumber) & (u32)1; +} + +/****************************************************************************/ +/** +* +* Set the Output Enable of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* @param OpEnable is the 32 bit mask of the Output Enables to be set for +* all the pins in the Bank. The Output Enable of bits with 0 are +* disabled, the Output Enable of bits with 1 are enabled. +* +* @return None. +* +* @note This function is used for setting the Output Enables of all the +* pins in the specified bank. The previous state of the Output +* Enables is not maintained. +* +*****************************************************************************/ +void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET, OpEnable); +} + +/****************************************************************************/ +/** +* +* Set the Output Enable of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number to which the Data is to be written. +* @param OpEnable specifies whether the Output Enable for the specified +* pin should be enabled. +* Valid values are 0 for Disabling Output Enable, +* 1 for Enabling Output Enable. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable) +{ + u8 Bank; + u8 PinNumber; + u32 OpEnableReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(OpEnable <= (u32)1); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + OpEnableReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET); + + if (OpEnable != (u32)0) { /* Enable Output Enable */ + OpEnableReg |= ((u32)1 << (u32)PinNumber); + } else { /* Disable Output Enable */ + OpEnableReg &= ~ ((u32)1 << (u32)PinNumber); + } + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET, OpEnableReg); +} +/****************************************************************************/ +/** +* +* Get the Output Enable status of the pins of the specified GPIO Bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* +* @return Returns a a 32 bit mask of the Output Enable register. +* Bits with 0 are in Disabled state, bits with 1 are in +* Enabled State. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET); +} + +/****************************************************************************/ +/** +* +* Get the Output Enable status of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the Output Enable status is to +* be retrieved. +* +* @return Output Enable of the specified pin. +* - 0 if Output Enable is disabled for this pin +* - 1 if Output Enable is enabled for this pin +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET) >> (u32)PinNumber) & (u32)1; +} + +/****************************************************************************/ +/** +* +* Get the Bank number and the Pin number in the Bank, for the given PinNumber +* in the GPIO device. +* +* @param PinNumber is the Pin number in the GPIO device. +* @param BankNumber returns the Bank in which this GPIO pin is present. +* Valid values are 0 to XGPIOPS_MAX_BANKS - 1. +* @param PinNumberInBank returns the Pin Number within the Bank. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#ifdef versal +void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank) +#else +void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank) +#endif +{ + u32 XGpioPsPinTable[6] = {0}; +#ifdef versal + u8 i=(u8)0; +#endif + u32 Platform = XGetPlatform_Info(); + + if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + /* + * This structure defines the mapping of the pin numbers to the banks when + * the driver APIs are used for working on the individual pins. + */ + + XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ + XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */ + XGpioPsPinTable[2] = (u32)77; /* 52 - 77, Bank 2 */ + XGpioPsPinTable[3] = (u32)109; /* 78 - 109, Bank 3 */ + XGpioPsPinTable[4] = (u32)141; /* 110 - 141, Bank 4 */ + XGpioPsPinTable[5] = (u32)173; /* 142 - 173 Bank 5 */ + + *BankNumber = 0U; + while (*BankNumber < XGPIOPS_SIX) { + if (PinNumber <= XGpioPsPinTable[*BankNumber]) { + break; + } + (*BankNumber)++; + } + } +#ifdef versal + else if(Platform == XPLAT_VERSAL) + { + if(InstancePtr->PmcGpio == (u32)(FALSE)) + { + XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ + XGpioPsPinTable[1] = (u32)57; /* 26 - 57, Bank 3 */ + *BankNumber =0U; + if(PinNumber <= XGpioPsPinTable[*BankNumber]) + { + *BankNumber = (u8)XGPIOPS_ZERO; + } + else + { + *BankNumber = (u8)XGPIOPS_THREE; + } + + } + else + { + XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */ + XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */ + XGpioPsPinTable[2] = (u32)83; /* 52 - 83, Bank 3 */ + XGpioPsPinTable[3] = (u32)115; /*84 - 115, Bank 4 */ + + *BankNumber =0U; + while(i < XGPIOPS_FOUR) + { + if(i <= (u8)XGPIOPS_ONE) + { + if (PinNumber <= XGpioPsPinTable[i]) + { + *BankNumber = (u8)i; + break; + } + i++; + } + else + { + if (PinNumber <= XGpioPsPinTable[i]) + { + *BankNumber = (u8)i+1U; + break; + } + i++; + } + + } + } + + } +#endif + else { + XGpioPsPinTable[0] = (u32)31; /* 0 - 31, Bank 0 */ + XGpioPsPinTable[1] = (u32)53; /* 32 - 53, Bank 1 */ + XGpioPsPinTable[2] = (u32)85; /* 54 - 85, Bank 2 */ + XGpioPsPinTable[3] = (u32)117; /* 86 - 117 Bank 3 */ + + *BankNumber = 0U; + while (*BankNumber < XGPIOPS_FOUR) { + if (PinNumber <= XGpioPsPinTable[*BankNumber]) { + break; + } + (*BankNumber)++; + } + } + if (*BankNumber == (u8)0) { + *PinNumberInBank = PinNumber; + } + +#ifdef versal + else if(Platform == XPLAT_VERSAL) + { + if(InstancePtr->PmcGpio == (u32)(FALSE)) + { + *PinNumberInBank = (u8)((u32)PinNumber - (XGpioPsPinTable[0] + (u32)1)); + } + else { + if((*BankNumber ==(u8)XGPIOPS_THREE) || (*BankNumber ==(u8)XGPIOPS_FOUR)) + { + *PinNumberInBank = (u8)((u32)PinNumber % + (XGpioPsPinTable[*BankNumber - (u8)XGPIOPS_TWO] + (u32)1)); + } + else + { + *PinNumberInBank = (u8)((u32)PinNumber % + (XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1)); + } + } + + } +#endif + + else { + *PinNumberInBank = (u8)((u32)PinNumber % + (XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1)); + } +} + +/*****************************************************************************/ +/** +* +* This is a stub for the status callback. The stub is here in case the upper +* layers do not set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* @param Bank is the GPIO Bank in which an interrupt occurred. +* @param Status is the Interrupt status of the GPIO bank. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void StubHandler(void *CallBackRef, u32 Bank, u32 Status) +{ + (void) CallBackRef; + (void) Bank; + (void) Status; + + Xil_AssertVoidAlways(); +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops.h b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops.h new file mode 100644 index 0000000..8b1d89f --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops.h @@ -0,0 +1,299 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xgpiops.h +* @addtogroup gpiops Overview +* @{ +* @details +* +* The Xilinx PS GPIO driver. This driver supports the Xilinx PS GPIO +* Controller. +* +* The GPIO Controller supports the following features: +* - 6 banks +* - Masked writes (There are no masked reads) +* - Bypass mode +* - Configurable Interrupts (Level/Edge) +* +* This driver is intended to be RTOS and processor independent. Any needs for +* dynamic memory management, threads or thread mutual exclusion, virtual +* memory, or cache control must be satisfied by the layer above this driver. +* +* Here is GPIO Bank and Pin mapping information for different platforms. +* Zynq: +* PS GPIO contain 4 banks and 118 pins +* Bank 0 MIO pins 0 - 31 +* Bank 1 MIO pins 32 - 53 +* Bank 2 MIO pins 54 - 85 +* Bank 3 EMIO signals 86 - 117 +* +* Zynq Ultrascale+ MP: +* PS GPIO contain 6 banks and 174 pins +* Bank 0 MIO pins 0 - 25 +* Bank 1 MIO pins 26 - 51 +* Bank 2 MIO pins 52 - 77 +* Bank 3 EMIO signals 78 - 109 +* Bank 4 EMIO signals 110 - 141 +* Bank 5 EMIO signals 142 - 173 + +* Versal: Two GPIOPS instances PMC GPIO and PS GPIO +* PMC GPIO contain 4 banks and 116 pins +* Bank 0 MIO pins 0 - 25 +* Bank 1 MIO pins 26 - 51 +* Bank 3 EMIO signals 52 - 83 +* Bank 4 EMIO signals 84 - 115 +* PS GPIO contains 2 banks and 58 pins +* Bank 0 MIO pins 0 - 25 +* Bank 3 EMIO signals 26-57 +* +* This driver supports all the features listed above, if applicable. +* +* Driver Description +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the GPIO. +* +* Interrupts +* +* The driver provides interrupt management functions and an interrupt handler. +* Users of this driver need to provide callback functions. An interrupt handler +* example is available with the driver. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XGpioPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +*

+* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.01a sv   04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
+*                     XGpioPs_GetMode, XGpioPs_GetModePin as they are not
+*		      relevant to Zynq device.The interrupts are disabled
+*		      for output pins on all banks during initialization.
+* 1.02a hk   08/22/13 Added low level reset API
+* 2.1   hk   04/29/14 Use Input data register DATA_RO for read. CR# 771667.
+* 2.2	sk	 10/13/14 Used Pin number in Bank instead of pin number
+* 					  passed to APIs. CR# 822636
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+*       ms   04/05/17 Added tabspace for return statements in functions of
+*                     gpiops examples for proper documentation while
+*                     generating doxygen.
+* 3.3   ms   04/17/17 Added notes about gpio input and output pin description
+*                     for zcu102 and zc702 boards in polled and interrupt
+*                     example, configured Interrupt pin to input pin for
+*                     proper functioning of interrupt example.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in safety mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the pointer param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added Versal support.
+* 3.6   mus  04/05/19 Replaced XPLAT_versal macro with XPLAT_VERSAL, to be in
+*                     sync with standalone BSP
+* 3.6	sne  06/12/19 Fixed IAR compiler warning.
+* 3.6   sne  08/14/19 Added interrupt handler support on versal.
+* 3.7	sne  12/04/19 Reverted versal examples support.
+* 3.8   sne  08/28/20 Modify Makefile to support parallel make execution.
+* 3.8	sne  09/17/20 Added description for Versal PS and PMC GPIO pins.
+* 3.9	sne  03/15/21 Fixed MISRA-C violations.
+* 3.11  sg   02/23/23 Update bank and pin mapping information.
+*
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_H /* prevent circular inclusions */ +#define XGPIOPS_H /**< by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xgpiops_hw.h" +#include "xplatform_info.h" + +/************************** Constant Definitions *****************************/ + +/** @name Interrupt types + * @{ + * The following constants define the interrupt types that can be set for each + * GPIO pin. + */ +#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0x00U /**< Interrupt on Rising edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 0x01U /**< Interrupt Falling edge */ +#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 0x02U /**< Interrupt on both edges */ +#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 0x03U /**< Interrupt on high level */ +#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 0x04U /**< Interrupt on low level */ +/** @}*/ + +#define XGPIOPS_BANK_MAX_PINS (u32)32 /**< Max pins in a GPIO bank */ +#define XGPIOPS_BANK0 0x00U /**< GPIO Bank 0 */ +#define XGPIOPS_BANK1 0x01U /**< GPIO Bank 1 */ +#define XGPIOPS_BANK2 0x02U /**< GPIO Bank 2 */ +#define XGPIOPS_BANK3 0x03U /**< GPIO Bank 3 */ +#define XGPIOPS_BANK4 0x04U /**< GPIO Bank 4 */ +#define XGPIOPS_BANK5 0x05U /**< GPIO Bank 5 */ + +#define XGPIOPS_MAX_BANKS_ZYNQMP 0x06U /**< Max banks in a + * Zynq Ultrascale+ MP GPIO device + */ +#define XGPIOPS_MAX_BANKS 0x04U /**< Max banks in a Zynq GPIO device */ + +#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP (u32)174 /**< Max pins in the + * Zynq Ultrascale+ MP GPIO device + * 0 - 25, Bank 0 + * 26 - 51, Bank 1 + * 52 - 77, Bank 2 + * 78 - 109, Bank 3 + * 110 - 141, Bank 4 + * 142 - 173, Bank 5 + */ +#define XGPIOPS_DEVICE_MAX_PIN_NUM (u32)118 /**< Max pins in the Zynq GPIO device + * 0 - 31, Bank 0 + * 32 - 53, Bank 1 + * 54 - 85, Bank 2 + * 86 - 117, Bank 3 + */ + +/**************************** Type Definitions *******************************/ + +/****************************************************************************/ +/** + * This handler data type allows the user to define a callback function to + * handle the interrupts for the GPIO device. The application using this + * driver is expected to define a handler of this type, to support interrupt + * driven mode. The handler executes in an interrupt context such that minimal + * processing should be performed. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the callback functions for a GPIO bank. It is + * passed back to the upper layer when the callback is invoked. Its + * type is not important to the driver component, so it is a void + * pointer. + * @param Bank is the bank for which the interrupt status has changed. + * @param Status is the Interrupt status of the GPIO bank. + * + *****************************************************************************/ +typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status); + +/** + * This typedef contains configuration information for a device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + UINTPTR BaseAddr; /**< Register base address */ +} XGpioPs_Config; + +/** + * The XGpioPs driver instance data. The user is required to allocate a + * variable of this type for the GPIO device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XGpioPs_Config GpioConfig; /**< Device configuration */ + u32 IsReady; /**< Device is initialized and ready */ + XGpioPs_Handler Handler; /**< Status handlers for all banks */ + void *CallBackRef; /**< Callback ref for bank handlers */ + u32 Platform; /**< Platform data */ + u32 MaxPinNum; /**< Max pins in the GPIO device */ + u8 MaxBanks; /**< Max banks in a GPIO device */ + u32 PmcGpio; /**< Flag for accessing PS GPIO for versal*/ +} XGpioPs; + +/************************** Variable Definitions *****************************/ +extern XGpioPs_Config XGpioPs_ConfigTable[]; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/* Functions in xgpiops.c */ +s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr, + u32 EffectiveAddr); + +/* Bank APIs in xgpiops.c */ +u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data); +void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction); +u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable); +u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank); +#ifdef versal +void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#else +void XGpioPs_GetBankPin(u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank); +#endif + +/* Pin APIs in xgpiops.c */ +u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data); +void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction); +u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable); +u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin); + +/* Diagnostic functions in xgpiops_selftest.c */ +s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr); + +/* Functions in xgpiops_intr.c */ +/* Bank APIs in xgpiops_intr.c */ +void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank); +u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank); +void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask); +void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, + u32 IntrPolarity, u32 IntrOnAny); +void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, + u32 *IntrPolarity, u32 *IntrOnAny); +void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, + XGpioPs_Handler FuncPointer); +void XGpioPs_IntrHandler(const XGpioPs *InstancePtr); + +/* Pin APIs in xgpiops_intr.c */ +void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType); +u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin); + +void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin); +u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin); +void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin); + +/* Functions in xgpiops_sinit.c */ +XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_g.c new file mode 100644 index 0000000..8d55f88 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_g.c @@ -0,0 +1,53 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xgpiops_g.c +* @addtogroup gpiops Overview +* @{ +* +* This file contains a configuration table that specifies the configuration +* of GPIO devices in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Prototypes ******************************/ + +/** + * This table contains configuration information for each GPIO device + * in the system. + */ +XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES] = { + { + (u16)XPAR_XGPIOPS_0_DEVICE_ID, /* Unique ID of device */ + (u32)XPAR_XGPIOPS_0_BASEADDR /* Base address of device */ + } +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_hw.c b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_hw.c new file mode 100644 index 0000000..7734ba8 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_hw.c @@ -0,0 +1,241 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xgpiops_hw.c +* @addtogroup gpiops Overview +* @{ +* +* This file contains low level GPIO functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.02a hk   08/22/13 First Release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in safety mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the pointer param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added versal support.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops_hw.h" +#include "xgpiops.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/** +* +* This function resets the GPIO module by writing reset values to +* all registers +* +* @param BaseAddress address of GPIO module +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XGpioPs_ResetHw(UINTPTR BaseAddress) +{ + u32 BankCount; + u32 Platform,MaxBanks; + + Platform = XGetPlatform_Info(); + if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + MaxBanks = (u32)6; + } + else if(Platform == (u32)XPLAT_VERSAL) + { + if (BaseAddress == (u32)XGPIOPS_PS_GPIO_BASEADDR) + { + MaxBanks = (u32)4; + } + else + { + MaxBanks = (u32)5; + } + } + else { + MaxBanks = (u32)4; + } + + if (Platform == (u32)XPLAT_VERSAL) + { + /* Write reset values to all mask data registers */ + for(BankCount = 3U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_LSW_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_MSW_OFFSET), 0x0U); + } + /* Write reset values to all output data registers */ + for(BankCount = 3U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_OFFSET), 0x0U); + } + + /* Reset all registers of all GPIO banks */ + for(BankCount = 0U; BankCount < (u32)MaxBanks; BankCount++) { + + + if((BaseAddress == (u32)XGPIOPS_PS_GPIO_BASEADDR) && ((BankCount == (u32)XGPIOPS_ONE) ||(BankCount == (u32)XGPIOPS_TWO))) + { + continue; + } + else + { + if((BaseAddress != (u32)XGPIOPS_PS_GPIO_BASEADDR) && (BankCount == (u32)XGPIOPS_ONE)) + { + continue; + } + } + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET), 0x0U); + + } + + /* Bank 0 Int type */ + XGpioPs_WriteReg(BaseAddress, XGPIOPS_INTTYPE_OFFSET, + XGPIOPS_INTTYPE_BANK0_RESET); + /* Bank 1 Int type */ + XGpioPs_WriteReg(BaseAddress, + ((u32)XGPIOPS_REG_MASK_OFFSET + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK1_RESET); + /* Bank 3 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)3 * XGPIOPS_REG_MASK_OFFSET) + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK3_RESET); + /* Bank 4 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)4 * XGPIOPS_REG_MASK_OFFSET) + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK4_RESET); + } + else + { + /* Write reset values to all mask data registers */ + for(BankCount = 2U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_LSW_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_MASK_OFFSET) + + XGPIOPS_DATA_MSW_OFFSET), 0x0U); + } + /* Write reset values to all output data registers */ + for(BankCount = 2U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_DATA_BANK_OFFSET) + + XGPIOPS_DATA_OFFSET), 0x0U); + } + /* Reset all registers of all GPIO banks */ + for(BankCount = 0U; BankCount < (u32)MaxBanks; BankCount++) { + + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_DIRM_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_OUTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET), 0x0U); + XGpioPs_WriteReg(BaseAddress, + ((BankCount * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET), 0x0U); + } + /* Bank 0 Int type */ + XGpioPs_WriteReg(BaseAddress, XGPIOPS_INTTYPE_OFFSET, + XGPIOPS_INTTYPE_BANK0_RESET); + /* Bank 1 Int type */ + XGpioPs_WriteReg(BaseAddress, + ((u32)XGPIOPS_REG_MASK_OFFSET + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK1_RESET); + /* Bank 2 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)2 * XGPIOPS_REG_MASK_OFFSET) + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK2_RESET); + /* Bank 3 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)3 * XGPIOPS_REG_MASK_OFFSET) + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK3_RESET); + + if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) { + /* Bank 4 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)4 * XGPIOPS_REG_MASK_OFFSET) + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK4_RESET); + /* Bank 5 Int type */ + XGpioPs_WriteReg(BaseAddress, + (((u32)5 * XGPIOPS_REG_MASK_OFFSET) + (u32)XGPIOPS_INTTYPE_OFFSET), + XGPIOPS_INTTYPE_BANK5_RESET); + } + } + +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_hw.h new file mode 100644 index 0000000..d291abb --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_hw.h @@ -0,0 +1,147 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xgpiops_hw.h +* @addtogroup gpiops Overview +* @{ +* +* This header file contains the identifiers and basic driver functions (or +* macros) that can be used to access the device. Other driver functions +* are defined in xgpiops.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 1.02a hk   08/22/13 Added low level reset API function prototype and
+*                     related constant definitions
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Corrected reset values of banks.
+* 3.5   sne  03/14/19 Added versal support.
+* 
+* +******************************************************************************/ +#ifndef XGPIOPS_HW_H /* prevent circular inclusions */ +#define XGPIOPS_HW_H /**< by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register offsets for the GPIO. Each register is 32 bits. + * @{ + */ +#define XGPIOPS_DATA_LSW_OFFSET 0x00000000U /**< Mask and Data Register LSW, WO */ +#define XGPIOPS_DATA_MSW_OFFSET 0x00000004U /**< Mask and Data Register MSW, WO */ +#define XGPIOPS_DATA_OFFSET 0x00000040U /**< Data Register, RW */ +#define XGPIOPS_DATA_RO_OFFSET 0x00000060U /**< Data Register - Input, RO */ +#define XGPIOPS_DIRM_OFFSET 0x00000204U /**< Direction Mode Register, RW */ +#define XGPIOPS_OUTEN_OFFSET 0x00000208U /**< Output Enable Register, RW */ +#define XGPIOPS_INTMASK_OFFSET 0x0000020CU /**< Interrupt Mask Register, RO */ +#define XGPIOPS_INTEN_OFFSET 0x00000210U /**< Interrupt Enable Register, WO */ +#define XGPIOPS_INTDIS_OFFSET 0x00000214U /**< Interrupt Disable Register, WO*/ +#define XGPIOPS_INTSTS_OFFSET 0x00000218U /**< Interrupt Status Register, RO */ +#define XGPIOPS_INTTYPE_OFFSET 0x0000021CU /**< Interrupt Type Register, RW */ +#define XGPIOPS_INTPOL_OFFSET 0x00000220U /**< Interrupt Polarity Register, RW */ +#define XGPIOPS_INTANY_OFFSET 0x00000224U /**< Interrupt On Any Register, RW */ +/** @} */ + +/** @name Register offsets for each Bank. + * @{ + */ +#define XGPIOPS_DATA_MASK_OFFSET 0x00000008U /**< Data/Mask Registers offset */ +#define XGPIOPS_DATA_BANK_OFFSET 0x00000004U /**< Data Registers offset */ +#define XGPIOPS_REG_MASK_OFFSET 0x00000040U /**< Registers offset */ +/** @} */ + +/* For backwards compatibility */ +#define XGPIOPS_BYPM_MASK_OFFSET (u32)0x40 /**< Mask for backward support */ + +/** @name Interrupt type reset values for each bank + * @{ + */ +#ifdef XPAR_PSU_GPIO_0_BASEADDR +#define XGPIOPS_INTTYPE_BANK0_RESET 0x03FFFFFFU /**< Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x03FFFFFFU /**< Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK2_RESET 0x03FFFFFFU /**< Resets specific to Zynq Ultrascale+ MP */ +#else +#define XGPIOPS_INTTYPE_BANK0_RESET 0xFFFFFFFFU /**< Resets specific to Zynq */ +#define XGPIOPS_INTTYPE_BANK1_RESET 0x003FFFFFU /**< Resets specific to Zynq */ +#define XGPIOPS_INTTYPE_BANK2_RESET 0xFFFFFFFFU /**< Resets specific to Zynq */ +#endif + +#define XGPIOPS_INTTYPE_BANK3_RESET 0xFFFFFFFFU /**< Reset common to both platforms */ +#define XGPIOPS_INTTYPE_BANK4_RESET 0xFFFFFFFFU /**< Resets specific to Zynq Ultrascale+ MP */ +#define XGPIOPS_INTTYPE_BANK5_RESET 0xFFFFFFFFU /**< Resets specific to Zynq Ultrascale+ MP */ +/** @} */ +#define XGPIOPS_PS_GPIO_BASEADDR 0xFF0B0000U /**< Flag for Base Address for PS_GPIO in Versal */ +#define XGPIOPS_ZERO 0U /**< Flag for 0 Value */ +#define XGPIOPS_ONE 1U /**< Flag for 1 Value */ +#define XGPIOPS_TWO 2U /**< Flag for 2 Value */ +#define XGPIOPS_THREE 3U /**< Flag for 3 Value */ +#define XGPIOPS_FOUR 4U /**< Flag for 4 Value */ +#define XGPIOPS_SIX 6U /**< Flag for 6 Value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* This macro reads the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the register offset to be read. +* +* @return The 32-bit value of the register +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (u32)(RegOffset)) + +/****************************************************************************/ +/** +* +* This macro writes to the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the offset of the register to be written. +* @param Data is the 32-bit value to write to the register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) + +/************************** Function Prototypes ******************************/ + +void XGpioPs_ResetHw(UINTPTR BaseAddress); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XGPIOPS_HW_H */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_intr.c b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_intr.c new file mode 100644 index 0000000..0f3e26b --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_intr.c @@ -0,0 +1,767 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xgpiops_intr.c +* @addtogroup gpiops Overview +* @{ +* +* This file contains functions related to GPIO interrupt handling. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/18/10 First Release
+* 2.2	sk	 10/13/14 Used Pin number in Bank instead of pin number
+* 					  passed to API's. CR# 822636
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.1   aru  07/13/18 Ressolved doxygen reported warnings. CR# 1006331.
+* 3.4   aru  08/09/18 Ressolved cppcheck warnings.
+* 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in safety mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the pointer param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 3.5   sne  03/14/19 Added Versal support.
+* 3.5   sne  03/20/19 Fixed multiple interrupts problem CR#1024556.
+* 3.6	sne  06/12/19 Fixed IAR compiler warning.
+* 3.6   sne  08/14/19 Added interrupt handler support on versal.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +/****************************************************************************/ +/** +* +* This function enables the interrupts for the specified pins in the specified +* bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* @param Mask is the bit mask of the pins for which interrupts are to +* be enabled. Bit positions of 1 will be enabled. Bit positions +* of 0 will keep the previous setting. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET, Mask); +} + +/****************************************************************************/ +/** +* +* This function enables the interrupt for the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt is to be enabled. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = ((u32)1 << (u32)PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTEN_OFFSET, IntrReg); +} + +/****************************************************************************/ +/** +* +* This function disables the interrupts for the specified pins in the specified +* bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* @param Mask is the bit mask of the pins for which interrupts are +* to be disabled. Bit positions of 1 will be disabled. Bit +* positions of 0 will keep the previous setting. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, Mask); +} + +/****************************************************************************/ +/** +* +* This function disables the interrupts for the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt is to be disabled. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = ((u32)1 << (u32)PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTDIS_OFFSET, IntrReg); +} + +/****************************************************************************/ +/** +* +* This function returns the interrupt enable status for a bank. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* +* @return Enabled interrupt(s) in a 32-bit format. Bit positions with 1 +* indicate that the interrupt for that pin is enabled, bit +* positions with 0 indicate that the interrupt for that pin is +* disabled. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank) +{ + u32 IntrMask; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + IntrMask = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET); + return (~IntrMask); +} + +/****************************************************************************/ +/** +* +* This function returns whether interrupts are enabled for the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt enable status +* is to be known. +* +* @return +* - TRUE if the interrupt is enabled. +* - FALSE if the interrupt is disabled. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTMASK_OFFSET); + + return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? (u32)FALSE : (u32)TRUE); +} + +/****************************************************************************/ +/** +* +* This function returns interrupt status read from Interrupt Status Register. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* +* @return The value read from Interrupt Status Register. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertNonvoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); +} + +/****************************************************************************/ +/** +* +* This function returns interrupt enable status of the specified pin. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt enable status +* is to be known. +* +* @return +* - TRUE if the interrupt has occurred. +* - FALSE if the interrupt has not occurred. +* +* @note None. +* +*****************************************************************************/ +u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); + + return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? (u32)TRUE : (u32)FALSE); +} + +/****************************************************************************/ +/** +* +* This function clears pending interrupt(s) with the provided mask. This +* function should be called after the software has serviced the interrupts +* that are pending. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* @param Mask is the mask of the interrupts to be cleared. Bit positions +* of 1 will be cleared. Bit positions of 0 will not change the +* previous interrupt status. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + /* Clear the currently pending interrupts. */ + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET, Mask); +} + +/****************************************************************************/ +/** +* +* This function clears the specified pending interrupt. This function should be +* called after the software has serviced the interrupts that are pending. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param Pin is the pin number for which the interrupt status is to be +* cleared. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin) +{ + u8 Bank; + u8 PinNumber; + u32 IntrReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + /* Clear the specified pending interrupts. */ + IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET); + + IntrReg &= ((u32)1 << PinNumber); + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTSTS_OFFSET, IntrReg); +} + +/****************************************************************************/ +/** +* +* This function is used for setting the Interrupt Type, Interrupt Polarity and +* Interrupt On Any for the specified GPIO Bank pins. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* @param IntrType is the 32 bit mask of the interrupt type. +* 0 means Level Sensitive and 1 means Edge Sensitive. +* @param IntrPolarity is the 32 bit mask of the interrupt polarity. +* 0 means Active Low or Falling Edge and 1 means Active High or +* Rising Edge. +* @param IntrOnAny is the 32 bit mask of the interrupt trigger for +* edge triggered interrupts. 0 means trigger on single edge using +* the configured interrupt polarity and 1 means trigger on both +* edges. +* +* @return None. +* +* @note This function is used for setting the interrupt related +* properties of all the pins in the specified bank. The previous +* state of the pins is not maintained. +* To change the Interrupt properties of a single GPIO pin, use the +* function XGpioPs_SetPinIntrType(). +* +*****************************************************************************/ +void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, + u32 IntrPolarity, u32 IntrOnAny) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET, IntrType); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET, IntrPolarity); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET, IntrOnAny); +} + +/****************************************************************************/ +/** +* +* This function is used for getting the Interrupt Type, Interrupt Polarity and +* Interrupt On Any for the specified GPIO Bank pins. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Bank is the bank number of the GPIO to operate on. +* @param IntrType returns the 32 bit mask of the interrupt type. +* 0 means Level Sensitive and 1 means Edge Sensitive. +* @param IntrPolarity returns the 32 bit mask of the interrupt +* polarity. 0 means Active Low or Falling Edge and 1 means +* Active High or Rising Edge. +* @param IntrOnAny returns the 32 bit mask of the interrupt trigger for +* edge triggered interrupts. 0 means trigger on single edge using +* the configured interrupt polarity and 1 means trigger on both +* edges. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType, + u32 *IntrPolarity, u32 *IntrOnAny) + +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Bank < InstancePtr->MaxBanks); +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + Xil_AssertVoid(Bank != XGPIOPS_TWO); + } else { + Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO)); + } +#endif + + *IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET); + + *IntrPolarity = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET); + + *IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET); +} + +/****************************************************************************/ +/** +* +* This function is used for setting the IRQ Type of a single GPIO pin. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Pin is the pin number whose IRQ type is to be set. +* @param IrqType is the IRQ type for GPIO Pin. Use XGPIOPS_IRQ_TYPE_* +* defined in xgpiops.h to specify the IRQ type. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType) +{ + u32 IntrTypeReg; + u32 IntrPolReg; + u32 IntrOnAnyReg; + u8 Bank; + u8 PinNumber; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); + Xil_AssertVoid(IrqType <= XGPIOPS_IRQ_TYPE_LEVEL_LOW); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrTypeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET); + + IntrPolReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET); + + IntrOnAnyReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET); + + switch (IrqType) { + case XGPIOPS_IRQ_TYPE_EDGE_RISING: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrPolReg |= ((u32)1 << (u32)PinNumber); + IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_EDGE_FALLING: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrPolReg &= ~((u32)1 << (u32)PinNumber); + IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_EDGE_BOTH: + IntrTypeReg |= ((u32)1 << (u32)PinNumber); + IntrOnAnyReg |= ((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_LEVEL_HIGH: + IntrTypeReg &= ~((u32)1 << (u32)PinNumber); + IntrPolReg |= ((u32)1 << (u32)PinNumber); + break; + case XGPIOPS_IRQ_TYPE_LEVEL_LOW: + IntrTypeReg &= ~((u32)1 << (u32)PinNumber); + IntrPolReg &= ~((u32)1 << (u32)PinNumber); + break; + default: + /**< Default statement is added for MISRA C compliance. */ + break; + } + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET, IntrTypeReg); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET, IntrPolReg); + + XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET, IntrOnAnyReg); +} + +/****************************************************************************/ +/** +* +* This function returns the IRQ Type of a given GPIO pin. +* +* @param InstancePtr is a pointer to an XGpioPs instance. +* @param Pin is the pin number whose IRQ type is to be obtained. +* +* @return None. +* +* @note Use XGPIOPS_IRQ_TYPE_* defined in xgpiops.h for the IRQ type +* returned by this function. +* +*****************************************************************************/ +u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin) +{ + u32 IntrType; + u32 IntrPol; + u32 IntrOnAny; + u8 Bank; + u8 PinNumber; + u8 IrqType; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum); + + /* Get the Bank number and Pin number within the bank. */ +#ifdef versal + XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber); +#else + XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); +#endif + + IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTTYPE_OFFSET) & ((u32)1 << PinNumber); + + if (IntrType == ((u32)1 << PinNumber)) { + + IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTANY_OFFSET) & ((u32)1 << PinNumber); + + IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); + + + if (IntrOnAny == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_BOTH; + } else if (IntrPol == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_RISING; + } else { + IrqType = XGPIOPS_IRQ_TYPE_EDGE_FALLING; + } + } else { + + IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr, + ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) + + XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber); + + if (IntrPol == ((u32)1 << PinNumber)) { + IrqType = XGPIOPS_IRQ_TYPE_LEVEL_HIGH; + } else { + IrqType = XGPIOPS_IRQ_TYPE_LEVEL_LOW; + } + } + + return IrqType; +} + +/*****************************************************************************/ +/** +* +* This function sets the status callback function. The callback function is +* called by the XGpioPs_IntrHandler when an interrupt occurs. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param FuncPointer is the pointer to the callback function. +* +* +* @return None. +* +* @note The handler is called within interrupt context, so it should do +* its work quickly and queue potentially time-consuming work to a +* task-level thread. +* +******************************************************************************/ +void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef, + XGpioPs_Handler FuncPointer) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPointer != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->Handler = FuncPointer; + InstancePtr->CallBackRef = CallBackRef; +} + +/*****************************************************************************/ +/** +* +* This function is the interrupt handler for GPIO interrupts.It checks the +* interrupt status registers of all the banks to determine the actual bank in +* which an interrupt has been triggered. It then calls the upper layer callback +* handler set by the function XGpioPs_SetBankHandler(). The callback is called +* when an interrupt +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* +* @return None. +* +* @note This function does not save and restore the processor context +* such that the user must provide this processing. +* +******************************************************************************/ +void XGpioPs_IntrHandler(const XGpioPs *InstancePtr) +{ + u8 Bank; + u32 IntrStatus; + u32 IntrEnabled; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + for (Bank = 0U; Bank < InstancePtr->MaxBanks; Bank++) { +#ifdef versal + if(InstancePtr->PmcGpio == (u32)TRUE) { + if(Bank == XGPIOPS_TWO) { + continue; + } + } else { + if((Bank == XGPIOPS_ONE) || (Bank == XGPIOPS_TWO)) { + continue; + } + } +#endif + IntrStatus = XGpioPs_IntrGetStatus(InstancePtr, Bank); + IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr,Bank); + if ((IntrStatus & IntrEnabled) != (u32)0) { + XGpioPs_IntrClear(InstancePtr, Bank, + (IntrStatus & IntrEnabled)); + InstancePtr->Handler(InstancePtr-> + CallBackRef, Bank, + (IntrStatus & IntrEnabled)); + } + } +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_selftest.c b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_selftest.c new file mode 100644 index 0000000..b666f7d --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_selftest.c @@ -0,0 +1,113 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xgpiops_selftest.c +* @addtogroup gpiops Overview +* @{ +* +* This file contains a diagnostic self-test function for the XGpioPs driver. +* +* Read xgpiops.h file for more information. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/18/10 First Release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
+*                     in safety mode and modified the code such as
+*                     Use of mixed mode arithmetic,Declared the pointer param
+*                     as Pointer to const,Casting operation to a pointer,
+*                     Literal value requires a U suffix.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xgpiops.h" + +/************************** Constant Definitions ****************************/ + + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +/*****************************************************************************/ +/** +* +* This function runs a self-test on the GPIO driver/device. This function +* does a register read/write test on some of the Interrupt Registers. +* +* @param InstancePtr is a pointer to the XGpioPs instance. +* +* @return +* - XST_SUCCESS if the self-test passed. +* - XST_FAILURE otherwise. +* +* +******************************************************************************/ +s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr) +{ + s32 Status = (s32)0; + u32 IntrEnabled; + u32 CurrentIntrType = 0U; + u32 CurrentIntrPolarity = 0U; + u32 CurrentIntrOnAny = 0U; + u32 IntrType = 0U; + u32 IntrPolarity = 0U; + u32 IntrOnAny = 0U; + u32 IntrTestValue = 0x22U; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Disable the Interrupts for Bank 0 . */ + IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr, XGPIOPS_BANK0); + XGpioPs_IntrDisable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); + + /* + * Get the Current Interrupt properties for Bank 0. + * Set them to a known value, read it back and compare. + */ + XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &CurrentIntrType, + &CurrentIntrPolarity, &CurrentIntrOnAny); + + XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, IntrTestValue, + IntrTestValue, IntrTestValue); + + XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &IntrType, + &IntrPolarity, &IntrOnAny); + + if ((IntrType != IntrTestValue) && (IntrPolarity != IntrTestValue) && + (IntrOnAny != IntrTestValue)) { + + Status = (s32)XST_FAILURE; + } + + /* + * Restore the contents of all the interrupt registers modified in this + * test. + */ + XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, CurrentIntrType, + CurrentIntrPolarity, CurrentIntrOnAny); + + XGpioPs_IntrEnable(InstancePtr, XGPIOPS_BANK0, IntrEnabled); + + return Status; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_sinit.c new file mode 100644 index 0000000..72a2ad8 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/gpiops/src/xgpiops_sinit.c @@ -0,0 +1,74 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xgpiops_sinit.c +* @addtogroup gpiops Overview +* @{ +* +* This file contains the implementation of the XGpioPs driver's static +* initialization functionality. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sv   01/15/10 First Release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xgpiops.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/** +* +* This function looks for the device configuration based on the unique device +* ID. The table XGpioPs_ConfigTable[] contains the configuration information +* for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId) +{ + XGpioPs_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_XGPIOPS_NUM_INSTANCES; Index++) { + if (XGpioPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XGpioPs_ConfigTable[Index]; + break; + } + } + + return (XGpioPs_Config *)CfgPtr; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/Makefile new file mode 100644 index 0000000..5feeb49 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/Makefile @@ -0,0 +1,39 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf $(DEPFILES) diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips.c b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips.c new file mode 100644 index 0000000..68f1d3f --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips.c @@ -0,0 +1,1603 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xqspips.c +* @addtogroup qspips_v3_10 +* @{ +* +* Contains implements the interface functions of the XQspiPs driver. +* See xqspips.h for a detailed description of the device and driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a kka 07/25/12 Removed XQspiPs_GetWriteData API.
+*		     The XQspiPs_SetSlaveSelect has been modified to remove
+*		     the argument of the slave select as the QSPI controller
+*		     only supports one slave.
+* 		     XQspiPs_GetSlaveSelect API has been removed
+* 		     Added logic to XQspiPs_GetReadData to handle data
+*		     shift for normal data reads and instruction/status
+*		     reads differently based on the ShiftReadData flag.
+* 		     Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode and doesnot support
+*		     Slave mode or the legacy mode.
+*		     Modified the XQspiPs_PolledTransfer and XQspiPs_Transfer
+*		     APIs so that the last argument (IsInst) specifying whether
+*		     it is instruction or data has been removed. The first byte
+*		     in the SendBufPtr argument of these APIs specify the
+*		     instruction to be sent to the Flash Device.
+*		     The XQspiPs_PolledTransfer function has been updated
+*		     to fill the data to fifo depth.
+*		     This version of the driver fixes CRs 670197/663787.
+* 2.01a sg  02/03/13 Added flash opcodes for DUAL_IO_READ,QUAD_IO_READ.
+*		     Created macros XQspiPs_IsManualStart and
+*		     XQspiPs_IsManualChipSelect.
+*		     Changed QSPI transfer logic for polled and interrupt
+*		     modes to be based on filled tx fifo count and receive
+*		     based on it. RXNEMPTY interrupt is not used.
+*		     Added assertions to XQspiPs_LqspiRead function.
+*
+* 2.02a hk  05/14/13 Added enable and disable to the XQspiPs_LqspiRead()
+*			 function
+*            Added instructions for bank selection, die erase and
+*            flag status register to the flash instruction table
+*            Handling for instructions not in flash instruction
+*			 table added. Checking for Tx FIFO empty when switching from
+*			 TXD1/2/3 to TXD0 added. If WRSR instruction is sent with
+*            byte count 3 (spansion), instruction size and TXD register
+*			 changed accordingly. CR# 712502 and 703869.
+*            Added (#ifdef linear base address) in the Linear read function.
+*            Changed  XPAR_XQSPIPS_0_LINEAR_BASEADDR to
+*            XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR in
+*            XQspiPs_LqspiRead function. Fix for CR#718141
+*
+* 2.03a hk  09/05/13 Modified polled and interrupt transfers to make use of
+*                    thresholds. This is to improve performance.
+*                    Added RX and TX threshold reset to one in XQspiPs_Abort.
+*                    Added RX threshold reset(1) after transfer in polled and
+*                    interrupt transfers. Made changes to make sure threshold
+*                    change is done only when no transfer is in progress.
+* 3.1   hk  08/13/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+* 3.5	tjs 13/08/18 Fixed compilation warnings for ARMCC.
+* 3.6	akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+* 3.6 	akm 04/15/19 Modified the mask in XQspiPs_GetReadData() API to retrieve
+*		     configuration register values of both the Flashes in dual
+*		     parellel connection.
+* 3.7	akm 11/19/19 Fixed Coverity unused value warning in XQspiPs_PolledTransfer()
+* 			and XQspiPs_Transfer() APIs.
+* 3.7	akm 03/19/20 Modified XQspiPs_PolledTransfer(), XQspiPs_Transfer() and
+*			XQspiPs_InterruptHandler() APIs to fill TX FIFO with valid
+*			data when RX buffer is not NULL.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/** + * This typedef defines qspi flash instruction format + */ +typedef struct { + u8 OpCode; /**< Operational code of the instruction */ + u8 InstSize; /**< Size of the instruction including address bytes */ + u8 TxOffset; /**< Register address where instruction has to be + written */ +} XQspiPsInstFormat; + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0])) + +/************************** Function Prototypes ******************************/ +static void XQspiPs_GetReadData(XQspiPs *InstancePtr, u32 Data, u8 Size); +static void StubStatusHandler(void *CallBackRef, u32 StatusEvent, + unsigned ByteCount); + +/************************** Variable Definitions *****************************/ + +/* + * List of all the QSPI instructions and its format + */ +static XQspiPsInstFormat FlashInst[] = { + { XQSPIPS_FLASH_OPCODE_WREN, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_WRDS, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_RDSR1, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_RDSR2, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_WRSR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_PP, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_SE, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BE_32K, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BE_4K, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BE, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_ERASE_SUS, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_ERASE_RES, 1, XQSPIPS_TXD_01_OFFSET }, + { XQSPIPS_FLASH_OPCODE_RDID, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_NORM_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_FAST_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_DUAL_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_QUAD_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_DUAL_IO_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_QUAD_IO_READ, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BRWR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_BRRD, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_EARWR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_EARRD, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_DIE_ERASE, 4, XQSPIPS_TXD_00_OFFSET }, + { XQSPIPS_FLASH_OPCODE_READ_FLAG_SR, 2, XQSPIPS_TXD_10_OFFSET }, + { XQSPIPS_FLASH_OPCODE_CLEAR_FLAG_SR, 1, XQSPIPS_TXD_01_OFFSET }, + /* Add all the instructions supported by the flash device */ +}; + +/*****************************************************************************/ +/** +* +* Initializes a specific XQspiPs instance such that the driver is ready to use. +* +* The state of the device after initialization is: +* - Master mode +* - Active high clock polarity +* - Clock phase 0 +* - Baud rate divisor 2 +* - Transfer width 32 +* - Master reference clock = pclk +* - No chip select active +* - Manual CS and Manual Start disabled +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param ConfigPtr is a reference to a structure containing information +* about a specific QSPI device. This function initializes an +* InstancePtr object for a specific device specified by the +* contents of Config. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, use +* ConfigPtr->Config.BaseAddress for this device. +* +* @return +* - XST_SUCCESS if successful. +* - XST_DEVICE_IS_STARTED if the device is already started. +* It must be stopped to re-initialize. +* +* @note None. +* +******************************************************************************/ +int XQspiPs_CfgInitialize(XQspiPs *InstancePtr, XQspiPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * If the device is busy, disallow the initialize and return a status + * indicating it is already started. This allows the user to stop the + * device and re-initialize, but prevents a user from inadvertently + * initializing. This assumes the busy flag is cleared at startup. + */ + if (InstancePtr->IsBusy == TRUE) { + return XST_DEVICE_IS_STARTED; + } + + /* + * Set some default values. + */ + InstancePtr->IsBusy = FALSE; + + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->StatusHandler = StubStatusHandler; + + InstancePtr->SendBufferPtr = NULL; + InstancePtr->RecvBufferPtr = NULL; + InstancePtr->RequestedBytes = 0; + InstancePtr->RemainingBytes = 0; + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + InstancePtr->Config.ConnectionMode = ConfigPtr->ConnectionMode; + + /* + * Reset the QSPI device to get it into its initial state. It is + * expected that device configuration will take place after this + * initialization is done, but before the device is started. + */ + XQspiPs_Reset(InstancePtr); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Resets the QSPI device. Reset must only be called after the driver has been +* initialized. Any data transfer that is in progress is aborted. +* +* The upper layer software is responsible for re-configuring (if necessary) +* and restarting the QSPI device after the reset. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_Reset(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Abort any transfer that is in progress + */ + XQspiPs_Abort(InstancePtr); + + /* + * Write default value to configuration register. + * Do not modify reserved bits. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_RESET_MASK_SET; + ConfigReg &= ~XQSPIPS_CR_RESET_MASK_CLR; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, + ConfigReg); +} + +/*****************************************************************************/ +/** +* +* Aborts a transfer in progress by disabling the device and flush the RxFIFO. +* The byte counts are cleared, the busy flag is cleared. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note +* +* This function does a read/modify/write of the config register. The user of +* this function needs to take care of critical sections. +* +******************************************************************************/ +void XQspiPs_Abort(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + u32 IsLock; + + XQspiPs_Disable(InstancePtr); + + /* + * De-assert slave select lines. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= (XQSPIPS_CR_SSCTRL_MASK | XQSPIPS_CR_SSFORCE_MASK); + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * QSPI Software Reset + */ + IsLock = XQspiPs_ReadReg(XPAR_XSLCR_0_BASEADDR, SLCR_LOCKSTA); + if (IsLock) { + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, SLCR_UNLOCK, + SLCR_UNLOCK_MASK); + } + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, LQSPI_RST_CTRL, + LQSPI_RST_CTRL_MASK); + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, LQSPI_RST_CTRL, 0x0); + if (IsLock) { + XQspiPs_WriteReg(XPAR_XSLCR_0_BASEADDR, SLCR_LOCK, + SLCR_LOCK_MASK); + } + + /* + * Set the RX and TX FIFO threshold to reset value (one) + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXWR_OFFSET, XQSPIPS_TXWR_RESET_VALUE); + + InstancePtr->RemainingBytes = 0; + InstancePtr->RequestedBytes = 0; + InstancePtr->IsBusy = FALSE; +} + +/*****************************************************************************/ +/** +* +* Transfers specified data on the QSPI bus. Initiates bus communication and +* sends/receives data to/from the selected QSPI slave. For every byte sent, +* a byte is received. +* +* The caller has the option of providing two different buffers for send and +* receive, or one buffer for both send and receive, or no buffer for receive. +* The receive buffer must be at least as big as the send buffer to prevent +* unwanted memory writes. This implies that the byte count passed in as an +* argument must be the smaller of the two buffers if they differ in size. +* Here are some sample usages: +*
+*   XQspiPs_Transfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
+*	The caller wishes to send and receive, and provides two different
+*	buffers for send and receive.
+*
+*   XQspiPs_Transfer(InstancePtr, SendBuf, NULL, ByteCount)
+*	The caller wishes only to send and does not care about the received
+*	data. The driver ignores the received data in this case.
+*
+*   XQspiPs_Transfer(InstancePtr, SendBuf, SendBuf, ByteCount)
+*	The caller wishes to send and receive, but provides the same buffer
+*	for doing both. The driver sends the data and overwrites the send
+*	buffer with received data as it transfers the data.
+*
+*   XQspiPs_Transfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)
+*	The caller wishes to only receive and does not care about sending
+*	data.  In this case, the caller must still provide a send buffer, but
+*	it can be the same as the receive buffer if the caller does not care
+*	what it sends.  The device must send N bytes of data if it wishes to
+*	receive N bytes of data.
+* 
+* Although this function takes entire buffers as arguments, the driver can only +* transfer a limited number of bytes at a time, limited by the size of the +* FIFO. A call to this function only starts the transfer, then subsequent +* transfers of the data is performed by the interrupt service routine until +* the entire buffer has been transferred. The status callback function is +* called when the entire buffer has been sent/received. +* +* This function is non-blocking. The SetSlaveSelect function must be called +* prior to this function. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param SendBufPtr is a pointer to a data buffer that needs to be +* transmitted. This buffer must not be NULL. +* @param RecvBufPtr is a pointer to a buffer for received data. +* This argument can be NULL if do not care about receiving. +* @param ByteCount contains the number of bytes to send/receive. +* The number of bytes received always equals the number of bytes +* sent. +* +* @return +* - XST_SUCCESS if the buffers are successfully handed off to the +* device for transfer. +* - XST_DEVICE_BUSY indicates that a data transfer is already in +* progress. This is determined by the driver. +* +* @note +* +* This function is not thread-safe. The higher layer software must ensure that +* no two threads are transferring data on the QSPI bus at the same time. +* +******************************************************************************/ +s32 XQspiPs_Transfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, + u32 ByteCount) +{ + u32 StatusReg; + u32 ConfigReg; + u8 Instruction; + u32 Data; + unsigned int Index; + u8 TransCount = 0; + XQspiPsInstFormat *CurrInst; + XQspiPsInstFormat NewInst[2]; + u8 SwitchFlag = 0; + + CurrInst = &NewInst[0]; + + /* + * The RecvBufPtr argument can be null + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SendBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check whether there is another transfer in progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Set the busy flag, which will be cleared in the ISR when the + * transfer is entirely done. + */ + InstancePtr->IsBusy = TRUE; + + /* + * Set up buffer pointers. + */ + InstancePtr->SendBufferPtr = SendBufPtr; + InstancePtr->RecvBufferPtr = RecvBufPtr; + + InstancePtr->RequestedBytes = ByteCount; + InstancePtr->RemainingBytes = ByteCount; + + /* + * The first byte with every chip-select assertion is always + * expected to be an instruction for flash interface mode + */ + Instruction = *InstancePtr->SendBufferPtr; + + for (Index = 0 ; Index < ARRAY_SIZE(FlashInst); Index++) { + if (Instruction == FlashInst[Index].OpCode) { + break; + } + } + + /* + * Set the RX FIFO threshold + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXFIFO_THRESHOLD_OPT); + + /* + * If the slave select is "Forced" or under manual control, + * set the slave select now, before beginning the transfer. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg &= ~XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + } + + /* + * Enable the device. + */ + XQspiPs_Enable(InstancePtr); + + /* + * Clear all the interrupts. + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_SR_OFFSET, + XQSPIPS_IXR_WR_TO_CLR_MASK); + + if (Index < ARRAY_SIZE(FlashInst)) { + CurrInst = &FlashInst[Index]; + /* + * Check for WRSR instruction which has different size for + * Spansion (3 bytes) and Micron (2 bytes) + */ + if ((CurrInst->OpCode == XQSPIPS_FLASH_OPCODE_WRSR) && + (ByteCount == 3)) { + CurrInst->InstSize = 3; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + } + } + + /* + * If instruction not present in table + */ + if (Index == ARRAY_SIZE(FlashInst)) { + /* + * Assign current instruction, size and TXD register to be used + * The InstSize mentioned in case of instructions greater than + * 4 bytes is not the actual size, but is indicative of + * the TXD register used. + * The remaining bytes of the instruction will be transmitted + * through TXD0 below. + */ + switch (ByteCount%4) { + case XQSPIPS_SIZE_ONE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_ONE; + CurrInst->TxOffset = XQSPIPS_TXD_01_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_TWO: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_TWO; + CurrInst->TxOffset = XQSPIPS_TXD_10_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_THREE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_THREE; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + default: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_FOUR; + CurrInst->TxOffset = XQSPIPS_TXD_00_OFFSET; + break; + } + } + + /* + * If the instruction size in not 4 bytes then the data received needs + * to be shifted + */ + if (CurrInst->InstSize != 4) { + InstancePtr->ShiftReadData = 1; + } else { + InstancePtr->ShiftReadData = 0; + } + + /* Get the complete command (flash inst + address/data) */ + Data = *((u32 *)InstancePtr->SendBufferPtr); + InstancePtr->SendBufferPtr += CurrInst->InstSize; + InstancePtr->RemainingBytes -= CurrInst->InstSize; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + + /* Write the command to the FIFO */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + CurrInst->TxOffset, Data); + TransCount++; + + /* + * If switching from TXD1/2/3 to TXD0, then start transfer and + * check for FIFO empty + */ + if (SwitchFlag == 1) { + /* + * If, in Manual Start mode, start the transfer. + */ + if (XQspiPs_IsManualStart(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + /* + * Wait for the transfer to finish by polling Tx fifo status. + */ + do { + StatusReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + } while ((StatusReg & XQSPIPS_IXR_TXOW_MASK) == 0); + + } + + /* + * Fill the Tx FIFO with as many bytes as it takes (or as many as + * we have to send). + */ + while ((InstancePtr->RemainingBytes > 0) && + (TransCount < XQSPIPS_FIFO_DEPTH)) { + /* + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the TX FIFO with first 4bytes(1Byte Command + 3Byte Address) + * of data from TX Buffer and the remaining bytes(i.e., RequestedBytes - 4) + * with DUMMY. + */ + if(InstancePtr->RecvBufferPtr && + ((InstancePtr->RequestedBytes - InstancePtr->RemainingBytes) > 4)) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, XQSPIPS_DUMMY_TX_DATA); + } else { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)InstancePtr->SendBufferPtr)); + + InstancePtr->SendBufferPtr += 4; + } + InstancePtr->RemainingBytes -= 4; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + TransCount++; + } + + /* + * Enable QSPI interrupts (connecting to the interrupt controller and + * enabling interrupts should have been done by the caller). + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_IER_OFFSET, XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_TXOW_MASK | XQSPIPS_IXR_RXOVR_MASK | + XQSPIPS_IXR_TXUF_MASK); + + /* + * If, in Manual Start mode, Start the transfer. + */ + if (XQspiPs_IsManualStart(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* Transfers specified data on the QSPI bus in polled mode. +* +* The caller has the option of providing two different buffers for send and +* receive, or one buffer for both send and receive, or no buffer for receive. +* The receive buffer must be at least as big as the send buffer to prevent +* unwanted memory writes. This implies that the byte count passed in as an +* argument must be the smaller of the two buffers if they differ in size. +* Here are some sample usages: +*
+*   XQspiPs_PolledTransfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
+*	The caller wishes to send and receive, and provides two different
+*	buffers for send and receive.
+*
+*   XQspiPs_PolledTransfer(InstancePtr, SendBuf, NULL, ByteCount)
+*	The caller wishes only to send and does not care about the received
+*	data. The driver ignores the received data in this case.
+*
+*   XQspiPs_PolledTransfer(InstancePtr, SendBuf, SendBuf, ByteCount)
+*	The caller wishes to send and receive, but provides the same buffer
+*	for doing both. The driver sends the data and overwrites the send
+*	buffer with received data as it transfers the data.
+*
+*   XQspiPs_PolledTransfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)
+*	The caller wishes to only receive and does not care about sending
+*	data.  In this case, the caller must still provide a send buffer, but
+*	it can be the same as the receive buffer if the caller does not care
+*	what it sends.  The device must send N bytes of data if it wishes to
+*	receive N bytes of data.
+*
+* 
+* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param SendBufPtr is a pointer to a data buffer that needs to be +* transmitted. This buffer must not be NULL. +* @param RecvBufPtr is a pointer to a buffer for received data. +* This argument can be NULL if do not care about receiving. +* @param ByteCount contains the number of bytes to send/receive. +* The number of bytes received always equals the number of bytes +* sent. +* @return +* - XST_SUCCESS if the buffers are successfully handed off to the +* device for transfer. +* - XST_DEVICE_BUSY indicates that a data transfer is already in +* progress. This is determined by the driver. +* +* @note +* +* This function is not thread-safe. The higher layer software must ensure that +* no two threads are transferring data on the QSPI bus at the same time. +* +******************************************************************************/ +s32 XQspiPs_PolledTransfer(XQspiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount) +{ + u32 StatusReg; + u32 ConfigReg; + u8 Instruction; + u32 Data; + u8 TransCount; + unsigned int Index; + XQspiPsInstFormat *CurrInst; + XQspiPsInstFormat NewInst[2]; + u8 SwitchFlag = 0; + u8 IsManualStart = FALSE; + u32 RxCount = 0; + + CurrInst = &NewInst[0]; + /* + * The RecvBufPtr argument can be NULL. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SendBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check whether there is another transfer in progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Set the busy flag, which will be cleared when the transfer is + * entirely done. + */ + InstancePtr->IsBusy = TRUE; + + /* + * Set up buffer pointers. + */ + InstancePtr->SendBufferPtr = SendBufPtr; + InstancePtr->RecvBufferPtr = RecvBufPtr; + + InstancePtr->RequestedBytes = ByteCount; + InstancePtr->RemainingBytes = ByteCount; + + /* + * The first byte with every chip-select assertion is always + * expected to be an instruction for flash interface mode + */ + Instruction = *InstancePtr->SendBufferPtr; + + for (Index = 0 ; Index < ARRAY_SIZE(FlashInst); Index++) { + if (Instruction == FlashInst[Index].OpCode) { + break; + } + } + + /* + * Set the RX FIFO threshold + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXFIFO_THRESHOLD_OPT); + + /* + * If the slave select is "Forced" or under manual control, + * set the slave select now, before beginning the transfer. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg &= ~XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + } + + /* + * Enable the device. + */ + XQspiPs_Enable(InstancePtr); + + if (Index < ARRAY_SIZE(FlashInst)) { + + CurrInst = &FlashInst[Index]; + /* + * Check for WRSR instruction which has different size for + * Spansion (3 bytes) and Micron (2 bytes) + */ + if ((CurrInst->OpCode == XQSPIPS_FLASH_OPCODE_WRSR) && + (ByteCount == 3)) { + CurrInst->InstSize = 3; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + } + } + + /* + * If instruction not present in table + */ + if (Index == ARRAY_SIZE(FlashInst)) { + /* + * Assign current instruction, size and TXD register to be used. + * The InstSize mentioned in case of instructions greater than 4 bytes + * is not the actual size, but is indicative of the TXD register used. + * The remaining bytes of the instruction will be transmitted + * through TXD0 below. + */ + switch (ByteCount % 4) { + case XQSPIPS_SIZE_ONE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_ONE; + CurrInst->TxOffset = XQSPIPS_TXD_01_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_TWO: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_TWO; + CurrInst->TxOffset = XQSPIPS_TXD_10_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + case XQSPIPS_SIZE_THREE: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_THREE; + CurrInst->TxOffset = XQSPIPS_TXD_11_OFFSET; + if (ByteCount > 4) { + SwitchFlag = 1; + } + break; + default: + CurrInst->OpCode = Instruction; + CurrInst->InstSize = XQSPIPS_SIZE_FOUR; + CurrInst->TxOffset = XQSPIPS_TXD_00_OFFSET; + break; + } + } + + /* + * If the instruction size in not 4 bytes then the data received needs + * to be shifted + */ + if (CurrInst->InstSize != 4) { + InstancePtr->ShiftReadData = 1; + } else { + InstancePtr->ShiftReadData = 0; + } + TransCount = 0; + /* Get the complete command (flash inst + address/data) */ + Data = *((u32 *)InstancePtr->SendBufferPtr); + InstancePtr->SendBufferPtr += CurrInst->InstSize; + InstancePtr->RemainingBytes -= CurrInst->InstSize; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + + /* Write the command to the FIFO */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + CurrInst->TxOffset, Data); + ++TransCount; + + /* + * If switching from TXD1/2/3 to TXD0, then start transfer and + * check for FIFO empty + */ + if (SwitchFlag == 1) { + /* + * If, in Manual Start mode, start the transfer. + */ + if (XQspiPs_IsManualStart(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + /* + * Wait for the transfer to finish by polling Tx fifo status. + */ + do { + StatusReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + } while ((StatusReg & XQSPIPS_IXR_TXOW_MASK) == 0); + + } + + /* + * Check if manual start is selected and store it in a + * local variable for reference. This is to avoid reading + * the config register every time. + */ + IsManualStart = XQspiPs_IsManualStart(InstancePtr); + /* + * Fill the DTR/FIFO with as many bytes as it will take (or as + * many as we have to send). + */ + while ((InstancePtr->RemainingBytes > 0) && + (TransCount < XQSPIPS_FIFO_DEPTH)) { + /* + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the TX FIFO with first 4bytes(1Byte Command + 3Byte Address) + * of data from TX Buffer and the remaining bytes(i.e., RequestedBytes - 4) + * with DUMMY. + */ + if(InstancePtr->RecvBufferPtr && + ((InstancePtr->RequestedBytes - InstancePtr->RemainingBytes) > 4)) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, XQSPIPS_DUMMY_TX_DATA); + } else { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)InstancePtr->SendBufferPtr)); + + InstancePtr->SendBufferPtr += 4; + } + InstancePtr->RemainingBytes -= 4; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + ++TransCount; + } + + while ((InstancePtr->RemainingBytes > 0) || + (InstancePtr->RequestedBytes > 0)) { + + /* + * Fill the TX FIFO with RX threshold no. of entries (or as + * many as we have to send, in case that's less). + */ + while ((InstancePtr->RemainingBytes > 0) && + (TransCount < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + /* + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the TX FIFO with first 4bytes(1Byte Command + 3Byte Address) + * of data from TX Buffer and the remaining bytes(i.e., RequestedBytes - 4) + * with DUMMY. + */ + if(InstancePtr->RecvBufferPtr && + ((InstancePtr->RequestedBytes - InstancePtr->RemainingBytes) > 4)) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, XQSPIPS_DUMMY_TX_DATA); + } else { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)InstancePtr->SendBufferPtr)); + + InstancePtr->SendBufferPtr += 4; + } + InstancePtr->RemainingBytes -= 4; + if (InstancePtr->RemainingBytes < 0) { + InstancePtr->RemainingBytes = 0; + } + ++TransCount; + } + + /* + * If, in Manual Start mode, start the transfer. + */ + if (IsManualStart == TRUE) { + ConfigReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Reset TransCount - this is only used to fill TX FIFO + * in the above loop; + * RxCount is used to keep track of data received + */ + TransCount = 0; + + /* + * Wait for RX FIFO to reach threshold (or) + * TX FIFO to become empty. + * The latter check is required for + * small transfers (<32 words) and + * when the last chunk in a large data transfer is < 32 words. + */ + + do { + StatusReg = XQspiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + } while (((StatusReg & XQSPIPS_IXR_TXOW_MASK) == 0) && + ((StatusReg & XQSPIPS_IXR_RXNEMPTY_MASK) == 0)); + + /* + * A transmit has just completed. Process received data + * and check for more data to transmit. + * First get the data received as a result of the + * transmit that just completed. Receive data based on the + * count obtained while filling tx fifo. Always get + * the received data, but only fill the receive + * buffer if it points to something (the upper layer + * software may not care to receive data). + */ + while ((InstancePtr->RequestedBytes > 0) && + (RxCount < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + u32 Data; + + RxCount++; + + if (InstancePtr->RecvBufferPtr != NULL) { + if (InstancePtr->RequestedBytes < 4) { + Data = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + XQspiPs_GetReadData(InstancePtr, Data, + InstancePtr->RequestedBytes); + } else { + (*(u32 *)InstancePtr->RecvBufferPtr) = + XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + InstancePtr->RecvBufferPtr += 4; + InstancePtr->RequestedBytes -= 4; + if (InstancePtr->RequestedBytes < 0) { + InstancePtr->RequestedBytes = 0; + } + } + } else { + Data = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + InstancePtr->RequestedBytes -= 4; + } + } + RxCount = 0; + } + + /* + * If the Slave select lines are being manually controlled, disable + * them because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Clear the busy flag. + */ + InstancePtr->IsBusy = FALSE; + + /* + * Disable the device. + */ + XQspiPs_Disable(InstancePtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Read the flash in Linear QSPI mode. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RecvBufPtr is a pointer to a buffer for received data. +* @param Address is the starting address within the flash from +* from where data needs to be read. +* @param ByteCount contains the number of bytes to receive. +* +* @return +* - XST_SUCCESS if read is performed +* - XST_FAILURE if Linear mode is not set +* +* @note None. +* +* +******************************************************************************/ +int XQspiPs_LqspiRead(XQspiPs *InstancePtr, u8 *RecvBufPtr, + u32 Address, unsigned ByteCount) +{ + int Status = (int)XST_SUCCESS; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(RecvBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#ifndef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR +#define XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR 0xFC000000 +#endif + /* + * Enable the controller + */ + XQspiPs_Enable(InstancePtr); + + if (XQspiPs_GetLqspiConfigReg(InstancePtr) & + XQSPIPS_LQSPI_CR_LINEAR_MASK) { + memcpy((void *)RecvBufPtr, + (const void *)(XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR + + Address), + (size_t)ByteCount); + Status = (int)XST_SUCCESS; + } else { + Status = (int)XST_FAILURE; + } + + /* + * Disable the controller + */ + XQspiPs_Disable(InstancePtr); + + return Status; +} + +/*****************************************************************************/ +/** +* +* Selects the slave with which the master communicates. +* +* The user is not allowed to select the slave while a transfer is in progress. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - XST_SUCCESS if the slave is selected or deselected +* successfully. +* - XST_DEVICE_BUSY if a transfer is in progress, slave cannot be +* changed. +* +* @note +* +* This function only sets the slave which will be selected when a transfer +* occurs. The slave is not selected when the QSPI is idle. +* +******************************************************************************/ +int XQspiPs_SetSlaveSelect(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Do not allow the slave select to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Select the slave + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg &= ~XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Sets the status callback function, the status handler, which the driver +* calls when it encounters conditions that should be reported to upper +* layer software. The handler executes in an interrupt context, so it must +* minimize the amount of processing performed. One of the following status +* events is passed to the status handler. +* +*
+*
+* XST_SPI_TRANSFER_DONE		The requested data transfer is done
+*
+* XST_SPI_TRANSMIT_UNDERRUN	As a slave device, the master clocked data
+*				but there were none available in the transmit
+*				register/FIFO. This typically means the slave
+*				application did not issue a transfer request
+*				fast enough, or the processor/driver could not
+*				fill the transmit register/FIFO fast enough.
+*
+* XST_SPI_RECEIVE_OVERRUN	The QSPI device lost data. Data was received
+*				but the receive data register/FIFO was full.
+*
+* 
+* @param InstancePtr is a pointer to the XQspiPs instance. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param FuncPtr is the pointer to the callback function. +* +* @return None. +* +* @note +* +* The handler is called within interrupt context, so it should do its work +* quickly and queue potentially time-consuming work to a task-level thread. +* +******************************************************************************/ +void XQspiPs_SetStatusHandler(XQspiPs *InstancePtr, void *CallBackRef, + XQspiPs_StatusHandler FuncPtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->StatusHandler = FuncPtr; + InstancePtr->StatusRef = CallBackRef; +} + +/*****************************************************************************/ +/** +* +* This is a stub for the status callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubStatusHandler(void *CallBackRef, u32 StatusEvent, + unsigned ByteCount) +{ + (void) CallBackRef; + (void) StatusEvent; + (void) ByteCount; + + Xil_AssertVoidAlways(); +} + +/*****************************************************************************/ +/** +* +* The interrupt handler for QSPI interrupts. This function must be connected +* by the user to an interrupt controller. +* +* The interrupts that are handled are: +* +* +* - Data Transmit Register (FIFO) Empty. This interrupt is generated when the +* transmit register or FIFO is empty. The driver uses this interrupt during a +* transmission to continually send/receive data until the transfer is done. +* +* - Data Transmit Register (FIFO) Underflow. This interrupt is generated when +* the QSPI device, when configured as a slave, attempts to read an empty +* DTR/FIFO. An empty DTR/FIFO usually means that software is not giving the +* device data in a timely manner. No action is taken by the driver other than +* to inform the upper layer software of the error. +* +* - Data Receive Register (FIFO) Overflow. This interrupt is generated when the +* QSPI device attempts to write a received byte to an already full DRR/FIFO. +* A full DRR/FIFO usually means software is not emptying the data in a timely +* manner. No action is taken by the driver other than to inform the upper +* layer software of the error. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note +* +* The slave select register is being set to deselect the slave when a transfer +* is complete. +* +******************************************************************************/ +void XQspiPs_InterruptHandler(void *InstancePtr) +{ + XQspiPs *QspiPtr = (XQspiPs *)InstancePtr; + u32 IntrStatus; + u32 ConfigReg; + u32 Data; + u32 TransCount; + u32 Count = 0; + unsigned BytesDone; /* Number of bytes done so far. */ + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(QspiPtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Immediately clear the interrupts in case the ISR causes another + * interrupt to be generated. If we clear at the end of the ISR, + * we may miss newly generated interrupts. This occurs because we + * transmit from within the ISR, which could potentially cause another + * TX_EMPTY interrupt. + */ + IntrStatus = XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_SR_OFFSET); + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, XQSPIPS_SR_OFFSET, + (IntrStatus & XQSPIPS_IXR_WR_TO_CLR_MASK)); + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, XQSPIPS_IDR_OFFSET, + XQSPIPS_IXR_TXOW_MASK | XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_RXOVR_MASK | XQSPIPS_IXR_TXUF_MASK); + + if ((IntrStatus & XQSPIPS_IXR_TXOW_MASK) || + (IntrStatus & XQSPIPS_IXR_RXNEMPTY_MASK)) { + + /* + * Rx FIFO has just reached threshold no. of entries. + * Read threshold no. of entries from RX FIFO + * Another possibility of entering this loop is when + * the last byte has been transmitted and TX FIFO is empty, + * in which case, read all the data from RX FIFO. + * Always get the received data, but only fill the + * receive buffer if it is not null (it can be null when + * the device does not care to receive data). + */ + TransCount = QspiPtr->RequestedBytes - QspiPtr->RemainingBytes; + if (TransCount % 4) { + TransCount = TransCount/4 + 1; + } else { + TransCount = TransCount/4; + } + + while ((Count < TransCount) && + (Count < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + + if (QspiPtr->RecvBufferPtr != NULL) { + if (QspiPtr->RequestedBytes < 4) { + Data = XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + XQspiPs_GetReadData(QspiPtr, Data, + QspiPtr->RequestedBytes); + } else { + (*(u32 *)QspiPtr->RecvBufferPtr) = + XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + QspiPtr->RecvBufferPtr += 4; + QspiPtr->RequestedBytes -= 4; + if (QspiPtr->RequestedBytes < 0) { + QspiPtr->RequestedBytes = 0; + } + } + } else { + XQspiPs_ReadReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXD_OFFSET); + QspiPtr->RequestedBytes -= 4; + if (QspiPtr->RequestedBytes < 0) { + QspiPtr->RequestedBytes = 0; + } + + } + Count++; + } + Count = 0; + /* + * Interrupt asserted as TX_OW got asserted + * See if there is more data to send. + * Fill TX FIFO with RX threshold no. of entries or + * remaining entries (in case that is less than threshold) + */ + while ((QspiPtr->RemainingBytes > 0) && + (Count < XQSPIPS_RXFIFO_THRESHOLD_OPT)) { + /* + * Send more data. + * In case of Write fill the Tx FIFO with data to be transmitted. + * In case of Read fill the TX FIFO with first 4bytes(1Byte Command + 3Byte Address) + * of data from TX Buffer and the remaining bytes(i.e., RequestedBytes - 4) + * with DUMMY. + */ + if(QspiPtr->RecvBufferPtr && + ((QspiPtr->RequestedBytes - QspiPtr->RemainingBytes) > 4)) { + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, XQSPIPS_DUMMY_TX_DATA); + } else { + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_TXD_00_OFFSET, + *((u32 *)QspiPtr->SendBufferPtr)); + + QspiPtr->SendBufferPtr += 4; + } + QspiPtr->RemainingBytes -= 4; + if (QspiPtr->RemainingBytes < 0) { + QspiPtr->RemainingBytes = 0; + } + + Count++; + } + + if ((QspiPtr->RemainingBytes == 0) && + (QspiPtr->RequestedBytes == 0)) { + /* + * No more data to send. Disable the interrupt + * and inform the upper layer software that the + * transfer is done. The interrupt will be re-enabled + * when another transfer is initiated. + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_IDR_OFFSET, + XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_TXOW_MASK | + XQSPIPS_IXR_RXOVR_MASK | + XQSPIPS_IXR_TXUF_MASK); + + /* + * If the Slave select is being manually controlled, + * disable it because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + } + + /* + * Clear the busy flag. + */ + QspiPtr->IsBusy = FALSE; + + /* + * Disable the device. + */ + XQspiPs_Disable(QspiPtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + QspiPtr->StatusHandler(QspiPtr->StatusRef, + XST_SPI_TRANSFER_DONE, + QspiPtr->RequestedBytes); + } else { + /* + * Enable the TXOW interrupt. + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_IER_OFFSET, + XQSPIPS_IXR_RXNEMPTY_MASK | + XQSPIPS_IXR_TXOW_MASK | + XQSPIPS_IXR_RXOVR_MASK | + XQSPIPS_IXR_TXUF_MASK); + /* + * If, in Manual Start mode, start the transfer. + */ + if (XQspiPs_IsManualStart(QspiPtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_MANSTRT_MASK; + XQspiPs_WriteReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + } + } + + /* + * Check for overflow and underflow errors. + */ + if (IntrStatus & XQSPIPS_IXR_RXOVR_MASK) { + BytesDone = QspiPtr->RequestedBytes - QspiPtr->RemainingBytes; + QspiPtr->IsBusy = FALSE; + + /* + * If the Slave select lines is being manually controlled, + * disable it because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Disable the device. + */ + XQspiPs_Disable(QspiPtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + QspiPtr->StatusHandler(QspiPtr->StatusRef, + XST_SPI_RECEIVE_OVERRUN, BytesDone); + } + + if (IntrStatus & XQSPIPS_IXR_TXUF_MASK) { + BytesDone = QspiPtr->RequestedBytes - QspiPtr->RemainingBytes; + + QspiPtr->IsBusy = FALSE; + /* + * If the Slave select lines is being manually controlled, + * disable it because the transfer is complete. + */ + if (XQspiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XQspiPs_ReadReg( + QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_SSCTRL_MASK; + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Disable the device. + */ + XQspiPs_Disable(QspiPtr); + + /* + * Reset the RX FIFO threshold to one + */ + XQspiPs_WriteReg(QspiPtr->Config.BaseAddress, + XQSPIPS_RXWR_OFFSET, XQSPIPS_RXWR_RESET_VALUE); + + QspiPtr->StatusHandler(QspiPtr->StatusRef, + XST_SPI_TRANSMIT_UNDERRUN, BytesDone); + } +} + + +/*****************************************************************************/ +/** +* +* Copies data from Data to the Receive buffer. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param Data is the data which needs to be copied to the Rx buffer. +* @param Size is the number of bytes to be copied to the Receive buffer. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XQspiPs_GetReadData(XQspiPs *InstancePtr, u32 Data, u8 Size) +{ + u8 DataByte3; + + if (InstancePtr->RecvBufferPtr) { + switch (Size) { + case 1: + if (InstancePtr->ShiftReadData == 1) { + *((u8 *)InstancePtr->RecvBufferPtr) = + ((Data & 0xFF000000) >> 24); + } else { + *((u8 *)InstancePtr->RecvBufferPtr) = + (Data & 0xFF); + } + InstancePtr->RecvBufferPtr += 1; + break; + case 2: + if (InstancePtr->ShiftReadData == 1) { + *((u16 *)InstancePtr->RecvBufferPtr) = + ((Data >> 16) & 0xFF00) | + ((Data >> 8) & 0xFF); + } else { + *((u16 *)InstancePtr->RecvBufferPtr) = + (Data & 0xFFFF); + } + InstancePtr->RecvBufferPtr += 2; + break; + case 3: + if (InstancePtr->ShiftReadData == 1) { + *((u16 *)InstancePtr->RecvBufferPtr) = + ((Data & 0x00FFFF00) >> 8); + InstancePtr->RecvBufferPtr += 2; + DataByte3 = ((Data & 0xFF000000) >> 24); + *((u8 *)InstancePtr->RecvBufferPtr) = DataByte3; + } else { + *((u16 *)InstancePtr->RecvBufferPtr) = + (Data & 0xFFFF); + InstancePtr->RecvBufferPtr += 2; + DataByte3 = ((Data & 0x00FF0000) >> 16); + *((u8 *)InstancePtr->RecvBufferPtr) = DataByte3; + } + InstancePtr->RecvBufferPtr += 1; + break; + default: + /* This will never execute */ + break; + } + } + InstancePtr->ShiftReadData = 0; + InstancePtr->RequestedBytes -= Size; + if (InstancePtr->RequestedBytes < 0) { + InstancePtr->RequestedBytes = 0; + } +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips.h b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips.h new file mode 100644 index 0000000..d7bae80 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips.h @@ -0,0 +1,788 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xqspips.h +* @addtogroup qspips_v3_10 +* @{ +* @details +* +* This file contains the implementation of the XQspiPs driver. It supports only +* master mode. User documentation for the driver functions is contained in this +* file in the form of comment blocks at the front of each function. +* +* A QSPI device connects to an QSPI bus through a 4-wire serial interface. +* The QSPI bus is a full-duplex, synchronous bus that facilitates communication +* between one master and one slave. The device is always full-duplex, +* which means that for every byte sent, one is received, and vice-versa. +* The master controls the clock, so it can regulate when it wants to +* send or receive data. The slave is under control of the master, it must +* respond quickly since it has no control of the clock and must send/receive +* data as fast or as slow as the master does. +* +* Linear Mode +* The Linear Quad-SPI Controller extends the existing Quad-SPI Controller�s +* functionality by adding a linear addressing scheme that allows the SPI flash +* memory subsystem to behave like a typical ROM device. The new feature hides +* the normal SPI protocol from a master reading from the SPI flash memory. The +* feature improves both the user friendliness and the overall read memory +* throughput over that of the current Quad-SPI Controller by lessening the +* amount of software overheads required and by the use of the faster AXI +* interface. +* +* Initialization & Configuration +* +* The XQspiPs_Config structure is used by the driver to configure itself. This +* configuration structure is typically created by the tool-chain based on HW +* build properties. +* +* To support multiple runtime loading and initialization strategies employed by +* various operating systems, the driver instance can be initialized in the +* following way: +* - XQspiPs_LookupConfig(DeviceId) - Use the device identifier to find +* static configuration structure defined in xqspips_g.c. This is setup +* by the tools. For some operating systems the config structure will be +* initialized by the software and this call is not needed. +* - XQspiPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the provided virtual memory base address +* replaces the physical address present in the configuration structure. +* +* Multiple Masters +* +* More than one master can exist, but arbitration is the responsibility of +* the higher layer software. The device driver does not perform any type of +* arbitration. +* +* Modes of Operation +* +* There are four modes to perform a data transfer and the selection of a mode +* is based on Chip Select(CS) and Start. These two options individually, can +* be controlled either by software(Manual) or hardware(Auto). +* - Auto CS: Chip select is automatically asserted as soon as the first word +* is written into the TXFIFO and de asserted when the TXFIFO becomes +* empty +* - Manual CS: Software must assert and de assert CS. +* - Auto Start: Data transmission starts as soon as there is data in the +* TXFIFO and stalls when the TXFIFO is empty +* - Manual Start: Software must start data transmission at the beginning of +* the transaction or whenever the TXFIFO has become empty +* +* The preferred combination is Manual CS and Auto Start. +* In this combination, the software asserts CS before loading any data into +* TXFIFO. In Auto Start mode, whenever data is in TXFIFO, controller sends it +* out until TXFIFO becomes empty. The software reads the RXFIFO whenever the +* data is available. If no further data, software disables CS. +* +* Risks/challenges of other combinations: +* - Manual CS and Manual Start: Manual Start bit should be set after each +* TXFIFO write otherwise there could be a race condition where the TXFIFO +* becomes empty before the new word is written. In that case the +* transmission stops. +* - Auto CS with Manual or Auto Start: It is very difficult for software to +* keep the TXFIFO filled. Whenever the TXFIFO runs empty, CS is de asserted. +* This results in a single transaction to be split into multiple pieces each +* with its own chip select. This will result in garbage data to be sent. +* +* Interrupts +* +* The user must connect the interrupt handler of the driver, +* XQspiPs_InterruptHandler, to an interrupt system such that it will be +* called when an interrupt occurs. This function does not save and restore +* the processor context such that the user must provide this processing. +* +* The driver handles the following interrupts: +* - Data Transmit Register/FIFO Underflow +* - Data Receive Register/FIFO Not Empty +* - Data Transmit Register/FIFO Overwater +* - Data Receive Register/FIFO Overrun +* +* The Data Transmit Register/FIFO Overwater interrupt -- indicates that the +* QSPI device has transmitted the data available to transmit, and now its data +* register and FIFO is ready to accept more data. The driver uses this +* interrupt to indicate progress while sending data. The driver may have +* more data to send, in which case the data transmit register and FIFO is +* filled for subsequent transmission. When this interrupt arrives and all +* the data has been sent, the driver invokes the status callback with a +* value of XST_SPI_TRANSFER_DONE to inform the upper layer software that +* all data has been sent. +* +* The Data Transmit Register/FIFO Underflow interrupt -- indicates that, +* as slave, the QSPI device was required to transmit but there was no data +* available to transmit in the transmit register (or FIFO). This may not +* be an error if the master is not expecting data. But in the case where +* the master is expecting data, this serves as a notification of such a +* condition. The driver reports this condition to the upper layer +* software through the status handler. +* +* The Data Receive Register/FIFO Overrun interrupt -- indicates that the QSPI +* device received data and subsequently dropped the data because the data +* receive register and FIFO was full. The driver reports this condition to the +* upper layer software through the status handler. This likely indicates a +* problem with the higher layer protocol, or a problem with the slave +* performance. +* +* +* Polled Operation +* +* Transfer in polled mode is supported through a separate interface function +* XQspiPs_PolledTransfer(). Unlike the transfer function in the interrupt mode, +* this function blocks until all data has been sent/received. +* +* Device Busy +* +* Some operations are disallowed when the device is busy. The driver tracks +* whether a device is busy. The device is considered busy when a data transfer +* request is outstanding, and is considered not busy only when that transfer +* completes (or is aborted with a mode fault error). +* +* Device Configuration +* +* The device can be configured in various ways during the FPGA implementation +* process. Configuration parameters are stored in the xqspips_g.c file or +* passed in via XQspiPs_CfgInitialize(). A table is defined where each entry +* contains configuration information for an QSPI device, including the base +* address for the device. +* +* RTOS Independence +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads or +* thread mutual exclusion, virtual memory, or cache control must be satisfied +* by the layer above this driver. +* +* NOTE: This driver was always tested with endianness set to little-endian. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00a sdm 11/25/10 First release, based on the PS SPI driver...
+* 1.01a sdm 11/22/11 Added TCL file for generating QSPI parameters
+*		     in xparameters.h
+* 2.00a kka 07/25/12 Added a few register defines for CR 670297
+* 		     Removed code related to mode fault for CR 671468
+*		     The XQspiPs_SetSlaveSelect has been modified to remove
+*		     the argument of the slave select as the QSPI controller
+*		     only supports one slave.
+* 		     XQspiPs_GetSlaveSelect API has been removed
+* 		     Added a flag ShiftReadData to the instance structure
+*.		     and is used in the XQspiPs_GetReadData API.
+*		     The ShiftReadData Flag indicates whether the data
+*		     read from the Rx FIFO needs to be shifted
+*		     in cases where the data is less than 4  bytes
+* 		     Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode and doesnot support
+*		     Slave mode or the legacy mode.
+*		     Modified the XQspiPs_PolledTransfer and XQspiPs_Transfer
+*		     APIs so that the last argument (IsInst) specifying whether
+*		     it is instruction or data has been removed. The first byte
+*		     in the SendBufPtr argument of these APIs specify the
+*		     instruction to be sent to the Flash Device.
+*		     This version of the driver fixes CRs 670197/663787/
+*		     670297/671468.
+* 		     Added the option for setting the Holdb_dr bit in the
+*		     configuration options, XQSPIPS_HOLD_B_DRIVE_OPTION
+*		     is the option to be used for setting this bit in the
+*		     configuration register.
+*		     The XQspiPs_PolledTransfer function has been updated
+*		     to fill the data to fifo depth.
+* 2.01a sg  02/03/13 Added flash opcodes for DUAL_IO_READ,QUAD_IO_READ.
+*		     Added macros for Set/Get Rx Watermark. Changed QSPI
+*		     Enable/Disable macro argument from BaseAddress to
+*		     Instance Pointer. Added DelayNss argument to SetDelays
+*		     and GetDelays API's.
+*		     Created macros XQspiPs_IsManualStart and
+*		     XQspiPs_IsManualChipSelect.
+*		     Changed QSPI transfer logic for polled and interrupt
+*		     modes to be based on filled tx fifo count and receive
+*		     based on it. RXNEMPTY interrupt is not used.
+*		     Added assertions to XQspiPs_LqspiRead function.
+*		     SetDelays and GetDelays API's include DelayNss parameter.
+*		     Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register. Renamed Fixed burst error to
+*		     data FSM error in  LQSPI Status register.
+*
+* 2.02a hk  05/07/13 Added ConnectionMode to config structure.
+*			 Corresponds to C_QSPI_MODE - 0:Single, 1:Stacked, 2:Parallel
+*			 Added enable and disable to the XQspiPs_LqspiRead() function
+*			 Removed XQspi_Reset() in Set_Options() function when
+*			 LQSPI_MODE_OPTION is set.
+*            Added instructions for bank selection, die erase and
+*            flag status register to the flash instruction table
+*            Handling for instructions not in flash instruction
+*			 table added. Checking for Tx FIFO empty when switching from
+*			 TXD1/2/3 to TXD0 added. If WRSR instruction is sent with
+*            byte count 3 (spansion), instruction size and TXD register
+*			 changed accordingly. CR# 712502 and 703869.
+*            Added prefix to constant definitions for ConnectionMode
+*            Added (\#ifdef linear base address) in the Linear read function.
+*            Changed  XPAR_XQSPIPS_0_LINEAR_BASEADDR to
+*            XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR in
+*            XQspiPs_LqspiRead function. Fix for CR#718141.
+*
+* 2.03a hk  09/17/13 Modified polled and interrupt transfers to make use of
+*                    thresholds. This is to improve performance.
+*                    Added API's for QSPI reset and
+*                    linear mode initialization for boot.
+*                    Added RX and TX threshold reset to one in XQspiPs_Abort.
+*                    Added RX threshold reset(1) after transfer in polled and
+*                    interrupt transfers. Made changes to make sure threshold
+*                    change is done only when no transfer is in progress.
+*                    Updated linear init API for parallel and stacked modes.
+*                    CR#737760.
+* 3.1   hk  08/13/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+*       ms  04/05/17 Modified Comment lines in functions of qspips
+*                    examples to recognize it as documentation block
+*                    and modified filename tag in
+*                    xqspips_dual_flash_stack_lqspi_example.c to include it in
+*                    doxygen examples.
+* 3.4   nsk 31/07/17 Added QSPI_BUS_WIDTH parameter in xparameters.h file
+* 3.5	tjs 08/21/18 Fixed compilation warnings for the ARMCC.
+* 3.5	tjs 07/16/18 Added support for low density ISSI flash parts.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+* 3.6   akm 04/15/19 Modified FlashQuadEnable, FlashWrie and FlashErase APIs,
+*                    to wait for the on going operation to complete before
+*                    performing the next operation.
+* 3.6   akm 04/15/19 Modified the mask in XQspiPs_GetReadData() API to retrieve
+*                    configuration register values of both the Flashes in dual
+*                    parellel connection.
+* 3.7	akm 11/19/19 Fixed Coverity unused value warning in XQspiPs_PolledTransfer()
+* 			and XQspiPs_Transfer() APIs.
+* 3.7	akm 03/19/20 Modified XQspiPs_PolledTransfer(), XQspiPs_Transfer() and
+*			XQspiPs_InterruptHandler() APIs to fill TX FIFO with valid
+*			data when RX buffer is not NULL.
+* 3.8	akm 09/02/20 Updated the Makefile to support parallel make execution.
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_H /* prevent circular inclusions */ +#define XQSPIPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xqspips_hw.h" +#include + +/************************** Constant Definitions *****************************/ + +/** @name Configuration options + * + * The following options are supported to enable/disable certain features of + * an QSPI device. Each of the options is a bit mask, so more than one may be + * specified. + * + * + * The Active Low Clock option configures the device's clock polarity. + * Setting this option means the clock is active low and the SCK signal idles + * high. By default, the clock is active high and SCK idles low. + * + * The Clock Phase option configures the QSPI device for one of two + * transfer formats. A clock phase of 0, the default, means data is valid on + * the first SCK edge (rising or falling) after the slave select (SS) signal + * has been asserted. A clock phase of 1 means data is valid on the second SCK + * edge (rising or falling) after SS has been asserted. + * + * + * The QSPI Force Slave Select option is used to enable manual control of + * the slave select signal. + * 0: The SPI_SS signal is controlled by the QSPI controller during + * transfers. (Default) + * 1: The SPI_SS signal is forced active (driven low) regardless of any + * transfers in progress. + * + * NOTE: The driver will handle setting and clearing the Slave Select when + * the user sets the "FORCE_SSELECT_OPTION". Using this option will allow the + * QSPI clock to be set to a faster speed. If the QSPI clock is too fast, the + * processor cannot empty and refill the FIFOs before the TX FIFO is empty + * When the QSPI hardware is controlling the Slave Select signals, this + * will cause slave to be de-selected and terminate the transfer. + * + * The Manual Start option is used to enable manual control of + * the Start command to perform data transfer. + * 0: The Start command is controlled by the QSPI controller during + * transfers(Default). Data transmission starts as soon as there is data in + * the TXFIFO and stalls when the TXFIFO is empty + * 1: The Start command must be issued by software to perform data transfer. + * Bit 15 of Configuration register is used to issue Start command. This bit + * must be set whenever TXFIFO is filled with new data. + * + * NOTE: The driver will set the Manual Start Enable bit in Configuration + * Register, if Manual Start option is selected. Software will issue + * Manual Start command whenever TXFIFO is filled with data. When there is + * no further data, driver will clear the Manual Start Enable bit. + * + * @{ + */ +#define XQSPIPS_CLK_ACTIVE_LOW_OPTION 0x2 /**< Active Low Clock option */ +#define XQSPIPS_CLK_PHASE_1_OPTION 0x4 /**< Clock Phase one option */ +#define XQSPIPS_FORCE_SSELECT_OPTION 0x10 /**< Force Slave Select */ +#define XQSPIPS_MANUAL_START_OPTION 0x20 /**< Manual Start enable */ +#define XQSPIPS_LQSPI_MODE_OPTION 0x80 /**< Linear QPSI mode */ +#define XQSPIPS_HOLD_B_DRIVE_OPTION 0x100 /**< Drive HOLD_B Pin */ +/*@}*/ + + +/** @name QSPI Clock Prescaler options + * The QSPI Clock Prescaler Configuration bits are used to program master mode + * bit rate. The bit rate can be programmed in divide-by-two decrements from + * pclk/2 to pclk/256. + * + * @{ + */ +#define XQSPIPS_CLK_PRESCALE_2 0x00 /**< PCLK/2 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_4 0x01 /**< PCLK/4 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_8 0x02 /**< PCLK/8 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_16 0x03 /**< PCLK/16 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_32 0x04 /**< PCLK/32 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_64 0x05 /**< PCLK/64 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_128 0x06 /**< PCLK/128 Prescaler */ +#define XQSPIPS_CLK_PRESCALE_256 0x07 /**< PCLK/256 Prescaler */ + +/*@}*/ + + +/** @name Callback events + * + * These constants specify the handler events that are passed to + * a handler from the driver. These constants are not bit masks such that + * only one will be passed at a time to the handler. + * + * @{ + */ +#define XQSPIPS_EVENT_TRANSFER_DONE 2 /**< Transfer done */ +#define XQSPIPS_EVENT_TRANSMIT_UNDERRUN 3 /**< TX FIFO empty */ +#define XQSPIPS_EVENT_RECEIVE_OVERRUN 4 /**< Receive data loss because + * RX FIFO full + */ +/*@}*/ + +/** @name Flash commands + * + * The following constants define most of the commands supported by flash + * devices. Users can add more commands supported by the flash devices + * + * @{ + */ +#define XQSPIPS_FLASH_OPCODE_WRSR 0x01 /* Write status register */ +#define XQSPIPS_FLASH_OPCODE_PP 0x02 /* Page program */ +#define XQSPIPS_FLASH_OPCODE_NORM_READ 0x03 /* Normal read data bytes */ +#define XQSPIPS_FLASH_OPCODE_WRDS 0x04 /* Write disable */ +#define XQSPIPS_FLASH_OPCODE_RDSR1 0x05 /* Read status register 1 */ +#define XQSPIPS_FLASH_OPCODE_WREN 0x06 /* Write enable */ +#define XQSPIPS_FLASH_OPCODE_FAST_READ 0x0B /* Fast read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_4K 0x20 /* Erase 4KiB block */ +#define XQSPIPS_FLASH_OPCODE_RDSR2 0x35 /* Read status register 2 */ +#define XQSPIPS_FLASH_OPCODE_DUAL_READ 0x3B /* Dual read data bytes */ +#define XQSPIPS_FLASH_OPCODE_BE_32K 0x52 /* Erase 32KiB block */ +#define XQSPIPS_FLASH_OPCODE_QUAD_READ 0x6B /* Quad read data bytes */ +#define XQSPIPS_FLASH_OPCODE_ERASE_SUS 0x75 /* Erase suspend */ +#define XQSPIPS_FLASH_OPCODE_ERASE_RES 0x7A /* Erase resume */ +#define XQSPIPS_FLASH_OPCODE_RDID 0x9F /* Read JEDEC ID */ +#define XQSPIPS_FLASH_OPCODE_BE 0xC7 /* Erase whole flash block */ +#define XQSPIPS_FLASH_OPCODE_SE 0xD8 /* Sector erase (usually 64KB)*/ +#define XQSPIPS_FLASH_OPCODE_DUAL_IO_READ 0xBB /* Read data using Dual I/O */ +#define XQSPIPS_FLASH_OPCODE_QUAD_IO_READ 0xEB /* Read data using Quad I/O */ +#define XQSPIPS_FLASH_OPCODE_BRWR 0x17 /* Bank Register Write */ +#define XQSPIPS_FLASH_OPCODE_BRRD 0x16 /* Bank Register Read */ +/* Extende Address Register Write - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARWR 0xC5 +/* Extende Address Register Read - Micron's equivalent of Bank Register */ +#define XQSPIPS_FLASH_OPCODE_EARRD 0xC8 +#define XQSPIPS_FLASH_OPCODE_DIE_ERASE 0xC4 +#define XQSPIPS_FLASH_OPCODE_READ_FLAG_SR 0x70 +#define XQSPIPS_FLASH_OPCODE_CLEAR_FLAG_SR 0x50 +#define XQSPIPS_FLASH_OPCODE_READ_LOCK_REG 0xE8 /* Lock Reg Read */ +#define XQSPIPS_FLASH_OPCODE_WRITE_LOCK_REG 0xE5 /* Lock Reg Write */ + +/*@}*/ + +/** @name Instruction size + * + * The following constants define numbers 1 to 4. + * Used to identify whether TXD0,1,2 or 3 is to be used. + * + * @{ + */ +#define XQSPIPS_SIZE_ONE 1 +#define XQSPIPS_SIZE_TWO 2 +#define XQSPIPS_SIZE_THREE 3 +#define XQSPIPS_SIZE_FOUR 4 + +/*@}*/ + +/** @name ConnectionMode + * + * The following constants are the possible values of ConnectionMode in + * Config structure. + * + * @{ + */ +#define XQSPIPS_CONNECTION_MODE_SINGLE 0 +#define XQSPIPS_CONNECTION_MODE_STACKED 1 +#define XQSPIPS_CONNECTION_MODE_PARALLEL 2 + +/*@}*/ + +/** @name FIFO threshold value + * + * This is the Rx FIFO threshold (in words) that was found to be most + * optimal in terms of performance + * + * @{ + */ +#define XQSPIPS_RXFIFO_THRESHOLD_OPT 32 + +/*@}*/ + +/**************************** Type Definitions *******************************/ +/** + * The handler data type allows the user to define a callback function to + * handle the asynchronous processing for the QSPI device. The application + * using this driver is expected to define a handler of this type to support + * interrupt driven mode. The handler executes in an interrupt context, so + * only minimal processing should be performed. + * + * @param CallBackRef is the callback reference passed in by the upper + * layer when setting the callback functions, and passed back to + * the upper layer when the callback is invoked. Its type is + * not important to the driver, so it is a void pointer. + * @param StatusEvent holds one or more status events that have occurred. + * See the XQspiPs_SetStatusHandler() for details on the status + * events that can be passed in the callback. + * @param ByteCount indicates how many bytes of data were successfully + * transferred. This may be less than the number of bytes + * requested if the status event indicates an error. + */ +typedef void (*XQspiPs_StatusHandler) (void *CallBackRef, u32 StatusEvent, + unsigned ByteCount); + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of the device */ + u32 InputClockHz; /**< Input clock frequency */ + u8 ConnectionMode; /**< Single, Stacked and Parallel mode */ +} XQspiPs_Config; + +/** + * The XQspiPs driver instance data. The user is required to allocate a + * variable of this type for every QSPI device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XQspiPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + + u8 *SendBufferPtr; /**< Buffer to send (state) */ + u8 *RecvBufferPtr; /**< Buffer to receive (state) */ + int RequestedBytes; /**< Number of bytes to transfer (state) */ + int RemainingBytes; /**< Number of bytes left to transfer(state) */ + u32 IsBusy; /**< A transfer is in progress (state) */ + XQspiPs_StatusHandler StatusHandler; + void *StatusRef; /**< Callback reference for status handler */ + u32 ShiftReadData; /**< Flag to indicate whether the data + * read from the Rx FIFO needs to be shifted + * in cases where the data is less than 4 + * bytes + */ +} XQspiPs; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Start Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualStart(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualStart(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_MANUAL_START_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/* +* +* Check in OptionsTable if Manual Chip Select Option is enabled or disabled. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return +* - TRUE if option is set +* - FALSE if option is not set +* +* @note C-Style signature: +* u8 XQspiPs_IsManualChipSelect(XQspiPs *InstancePtr); +* +*****************************************************************************/ +#define XQspiPs_IsManualChipSelect(InstancePtr) \ + ((XQspiPs_GetOptions(InstancePtr) & \ + XQSPIPS_FORCE_SSELECT_OPTION) ? TRUE : FALSE) + +/****************************************************************************/ +/** +* +* Set the contents of the slave idle count register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are +* 0-255. +* +* @return None +* +* @note C-Style signature: +* void XQspiPs_SetSlaveIdle(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetSlaveIdle(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the slave idle count register. Use the XQSPIPS_SICR_* +* constants defined in xqspips_hw.h to interpret the bit-mask returned. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return An 8-bit value representing Slave Idle Count. +* +* @note C-Style signature: +* u32 XQspiPs_GetSlaveIdle(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetSlaveIdle(InstancePtr) \ + XQspiPs_In32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_SICR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the transmit FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetTXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetTXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_TXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the transmit FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Tx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetTXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetTXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_TXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Set the contents of the receive FIFO watermark register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written, valid values are 1-63. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetRXWatermark(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetRXWatermark(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_RXWR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the receive FIFO watermark register. +* Valid values are in the range 1-63. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 6-bit value representing Rx Watermark level. +* +* @note C-Style signature: +* u32 XQspiPs_GetRXWatermark(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetRXWatermark(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + XQSPIPS_RXWR_OFFSET) + +/****************************************************************************/ +/** +* +* Enable the device and uninhibit master transactions. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Enable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Enable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, \ + XQSPIPS_ER_ENABLE_MASK) + +/****************************************************************************/ +/** +* +* Disable the device. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_Disable(XQspiPs *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_Disable(InstancePtr) \ + XQspiPs_Out32((InstancePtr->Config.BaseAddress) + XQSPIPS_ER_OFFSET, 0) + +/****************************************************************************/ +/** +* +* Set the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param RegisterValue is the value to be written to the Linear QSPI +* configuration register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_SetLqspiConfigReg(XQspiPs *InstancePtr, +* u32 RegisterValue) +* +*****************************************************************************/ +#define XQspiPs_SetLqspiConfigReg(InstancePtr, RegisterValue) \ + XQspiPs_Out32(((InstancePtr)->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET, (RegisterValue)) + +/****************************************************************************/ +/** +* +* Get the contents of the Linear QSPI Configuration register. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return A 32-bit value representing the contents of the LQSPI Config +* register. +* +* @note C-Style signature: +* u32 XQspiPs_GetLqspiConfigReg(u32 *InstancePtr) +* +*****************************************************************************/ +#define XQspiPs_GetLqspiConfigReg(InstancePtr) \ + XQspiPs_In32((InstancePtr->Config.BaseAddress) + \ + XQSPIPS_LQSPI_CR_OFFSET) + +/************************** Function Prototypes ******************************/ + +/* + * Initialization function, implemented in xqspips_sinit.c + */ +XQspiPs_Config *XQspiPs_LookupConfig(u16 DeviceId); + +/* + * Functions implemented in xqspips.c + */ +int XQspiPs_CfgInitialize(XQspiPs *InstancePtr, XQspiPs_Config *Config, + u32 EffectiveAddr); +void XQspiPs_Reset(XQspiPs *InstancePtr); +void XQspiPs_Abort(XQspiPs *InstancePtr); + +s32 XQspiPs_Transfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, + u32 ByteCount); +s32 XQspiPs_PolledTransfer(XQspiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, u32 ByteCount); +int XQspiPs_LqspiRead(XQspiPs *InstancePtr, u8 *RecvBufPtr, + u32 Address, unsigned ByteCount); + +int XQspiPs_SetSlaveSelect(XQspiPs *InstancePtr); + +void XQspiPs_SetStatusHandler(XQspiPs *InstancePtr, void *CallBackRef, + XQspiPs_StatusHandler FuncPtr); +void XQspiPs_InterruptHandler(void *InstancePtr); + +/* + * Functions for selftest, in xqspips_selftest.c + */ +int XQspiPs_SelfTest(XQspiPs *InstancePtr); + +/* + * Functions for options, in xqspips_options.c + */ +s32 XQspiPs_SetOptions(XQspiPs *InstancePtr, u32 Options); +u32 XQspiPs_GetOptions(XQspiPs *InstancePtr); + +s32 XQspiPs_SetClkPrescaler(XQspiPs *InstancePtr, u8 Prescaler); +u8 XQspiPs_GetClkPrescaler(XQspiPs *InstancePtr); + +int XQspiPs_SetDelays(XQspiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit); +void XQspiPs_GetDelays(XQspiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_g.c new file mode 100644 index 0000000..31c0507 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_g.c @@ -0,0 +1,57 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xqspips_g.c +* @addtogroup qspips_v3_10 +* @{ +* +* This file contains a configuration table that specifies the configuration of +* QSPI devices in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Prototypes ******************************/ + +/** + * This table contains configuration information for each QSPI device + * in the system. + */ +XQspiPs_Config XQspiPs_ConfigTable[XPAR_XQSPIPS_NUM_INSTANCES] = { + { + XPAR_XQSPIPS_0_DEVICE_ID, /* Device ID for instance */ + XPAR_XQSPIPS_0_BASEADDR, /* Device base address */ + XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ, + XPAR_XQSPIPS_0_QSPI_MODE + }, +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_hw.c b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_hw.c new file mode 100644 index 0000000..77af96c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_hw.c @@ -0,0 +1,198 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xqspips_hw.c +* @addtogroup qspips_v3_10 +* @{ +* +* Contains low level functions, primarily reset related. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 2.03a hk  09/17/13 First release
+* 3.1   hk  06/19/14 When writing to the configuration register, set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips_hw.h" +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + +/** @name Pre-scaler value for divided by 4 + * + * Pre-scaler value for divided by 4 + * + * @{ + */ +#define XQSPIPS_CR_PRESC_DIV_BY_4 0x01 +/* @} */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Resets QSPI by disabling the device and bringing it to reset state through +* register writes. +* +* @param BaseAddress +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_ResetHw(u32 BaseAddress) +{ + u32 ConfigReg; + + /* + * Disable interrupts + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_IDR_OFFSET, + XQSPIPS_IXR_DISABLE_ALL); + + /* + * Disable device + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_ER_OFFSET, + 0); + + /* + * De-assert slave select lines. + */ + ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET); + ConfigReg |= (XQSPIPS_CR_SSCTRL_MASK | XQSPIPS_CR_SSFORCE_MASK); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * Write default value to RX and TX threshold registers + * RX threshold should be set to 1 here because the corresponding + * status bit is used next to clear the RXFIFO + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_TXWR_OFFSET, + (XQSPIPS_TXWR_RESET_VALUE & XQSPIPS_TXWR_MASK)); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_RXWR_OFFSET, + (XQSPIPS_RXWR_RESET_VALUE & XQSPIPS_RXWR_MASK)); + + /* + * Clear RXFIFO + */ + while ((XQspiPs_ReadReg(BaseAddress,XQSPIPS_SR_OFFSET) & + XQSPIPS_IXR_RXNEMPTY_MASK) != 0) { + XQspiPs_ReadReg(BaseAddress, XQSPIPS_RXD_OFFSET); + } + + /* + * Clear status register by reading register and + * writing 1 to clear the write to clear bits + */ + XQspiPs_ReadReg(BaseAddress, XQSPIPS_SR_OFFSET); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_SR_OFFSET, + XQSPIPS_IXR_WR_TO_CLR_MASK); + + /* + * Write default value to configuration register + */ + ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET); + ConfigReg |= XQSPIPS_CR_RESET_MASK_SET; + ConfigReg &= ~XQSPIPS_CR_RESET_MASK_CLR; + XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * De-select linear mode + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_LQSPI_CR_OFFSET, + 0x0); + +} + +/*****************************************************************************/ +/** +* +* Initializes QSPI to Linear mode with default QSPI boot settings. +* +* @param BaseAddress +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_LinearInit(u32 BaseAddress) +{ + u32 BaudRateDiv; + u32 LinearCfg; + u32 ConfigReg; + + /* + * Baud rate divisor for dividing by 4. Value of CR bits [5:3] + * should be set to 0x001; hence shift the value and use the mask. + */ + BaudRateDiv = ( (XQSPIPS_CR_PRESC_DIV_BY_4) << + XQSPIPS_CR_PRESC_SHIFT) & XQSPIPS_CR_PRESC_MASK; + /* + * Write configuration register with default values, slave selected & + * pre-scaler value for divide by 4 + */ + ConfigReg = XQspiPs_ReadReg(BaseAddress, XQSPIPS_CR_OFFSET); + ConfigReg |= (XQSPIPS_CR_RESET_MASK_SET | BaudRateDiv); + ConfigReg &= ~(XQSPIPS_CR_RESET_MASK_CLR | XQSPIPS_CR_SSCTRL_MASK); + XQspiPs_WriteReg(BaseAddress, XQSPIPS_CR_OFFSET, ConfigReg); + + /* + * Write linear configuration register with default value - + * enable linear mode and use fast read. + */ + + if(XPAR_XQSPIPS_0_QSPI_MODE == XQSPIPS_CONNECTION_MODE_SINGLE){ + + LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE; + + }else if(XPAR_XQSPIPS_0_QSPI_MODE == + XQSPIPS_CONNECTION_MODE_STACKED){ + + LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE | + XQSPIPS_LQSPI_CR_TWO_MEM_MASK; + + }else if(XPAR_XQSPIPS_0_QSPI_MODE == + XQSPIPS_CONNECTION_MODE_PARALLEL){ + + LinearCfg = XQSPIPS_LQSPI_CR_RST_STATE | + XQSPIPS_LQSPI_CR_TWO_MEM_MASK | + XQSPIPS_LQSPI_CR_SEP_BUS_MASK; + + } + + XQspiPs_WriteReg(BaseAddress, XQSPIPS_LQSPI_CR_OFFSET, + LinearCfg); + + /* + * Enable device + */ + XQspiPs_WriteReg(BaseAddress, XQSPIPS_ER_OFFSET, + XQSPIPS_ER_ENABLE_MASK); + +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_hw.h new file mode 100644 index 0000000..ab50675 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_hw.h @@ -0,0 +1,399 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xqspips_hw.h +* @addtogroup qspips_v3_10 +* @{ +* +* This header file contains the identifiers and basic HW access driver +* functions (or macros) that can be used to access the device. Other driver +* functions are defined in xqspips.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a ka  07/25/12 Added a few register defines for CR 670297
+*		     and removed some defines of reserved fields for
+*		     CR 671468
+*		     Added define XQSPIPS_CR_HOLD_B_MASK for Holdb_dr
+*		     bit in Configuration register.
+* 2.01a sg  02/03/13 Added defines for DelayNss,Rx Watermark,Interrupts
+*		     which need write to clear. Removed Read zeros mask from
+*		     LQSPI Config register.
+* 2.03a hk  08/22/13 Added prototypes of API's for QSPI reset and
+*                    linear mode initialization for boot. Added related
+*                    constant definitions.
+* 3.1   hk  08/13/14 Changed definition of CR reset value masks to set/reset
+*                    required bits leaving reserved bits untouched. CR# 796813.
+* 3.2	sk	02/05/15 Add SLCR reset in abort function as a workaround because
+* 					 controller does not update FIFO status flags as expected
+* 					 when thresholds are used.
+* 3.6   akm 03/28/19 Fixed memory leak issue while reading from qspi.(CR#1016357)
+*
+* 
+* +******************************************************************************/ +#ifndef XQSPIPS_HW_H /* prevent circular inclusions */ +#define XQSPIPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets from the base address of an QSPI device. + * @{ + */ +#define XQSPIPS_CR_OFFSET 0x00 /**< Configuration Register */ +#define XQSPIPS_SR_OFFSET 0x04 /**< Interrupt Status */ +#define XQSPIPS_IER_OFFSET 0x08 /**< Interrupt Enable */ +#define XQSPIPS_IDR_OFFSET 0x0c /**< Interrupt Disable */ +#define XQSPIPS_IMR_OFFSET 0x10 /**< Interrupt Enabled Mask */ +#define XQSPIPS_ER_OFFSET 0x14 /**< Enable/Disable Register */ +#define XQSPIPS_DR_OFFSET 0x18 /**< Delay Register */ +#define XQSPIPS_TXD_00_OFFSET 0x1C /**< Transmit 4-byte inst/data */ +#define XQSPIPS_RXD_OFFSET 0x20 /**< Data Receive Register */ +#define XQSPIPS_SICR_OFFSET 0x24 /**< Slave Idle Count */ +#define XQSPIPS_TXWR_OFFSET 0x28 /**< Transmit FIFO Watermark */ +#define XQSPIPS_RXWR_OFFSET 0x2C /**< Receive FIFO Watermark */ +#define XQSPIPS_GPIO_OFFSET 0x30 /**< GPIO Register */ +#define XQSPIPS_LPBK_DLY_ADJ_OFFSET 0x38 /**< Loopback Delay Adjust Reg */ +#define XQSPIPS_TXD_01_OFFSET 0x80 /**< Transmit 1-byte inst */ +#define XQSPIPS_TXD_10_OFFSET 0x84 /**< Transmit 2-byte inst */ +#define XQSPIPS_TXD_11_OFFSET 0x88 /**< Transmit 3-byte inst */ +#define XQSPIPS_LQSPI_CR_OFFSET 0xA0 /**< Linear QSPI config register */ +#define XQSPIPS_LQSPI_SR_OFFSET 0xA4 /**< Linear QSPI status register */ +#define XQSPIPS_MOD_ID_OFFSET 0xFC /**< Module ID register */ + +/* @} */ + +/** @name Configuration Register + * + * This register contains various control bits that + * affect the operation of the QSPI device. Read/Write. + * @{ + */ + +#define XQSPIPS_CR_IFMODE_MASK 0x80000000 /**< Flash mem interface mode */ +#define XQSPIPS_CR_ENDIAN_MASK 0x04000000 /**< Tx/Rx FIFO endianness */ +#define XQSPIPS_CR_MANSTRT_MASK 0x00010000 /**< Manual Transmission Start */ +#define XQSPIPS_CR_MANSTRTEN_MASK 0x00008000 /**< Manual Transmission Start + Enable */ +#define XQSPIPS_CR_SSFORCE_MASK 0x00004000 /**< Force Slave Select */ +#define XQSPIPS_CR_SSCTRL_MASK 0x00000400 /**< Slave Select Decode */ +#define XQSPIPS_CR_SSCTRL_SHIFT 10 /**< Slave Select Decode shift */ +#define XQSPIPS_CR_DATA_SZ_MASK 0x000000C0 /**< Size of word to be + transferred */ +#define XQSPIPS_CR_PRESC_MASK 0x00000038 /**< Prescaler Setting */ +#define XQSPIPS_CR_PRESC_SHIFT 3 /**< Prescaler shift */ +#define XQSPIPS_CR_PRESC_MAXIMUM 0x07 /**< Prescaler maximum value */ + +#define XQSPIPS_CR_CPHA_MASK 0x00000004 /**< Phase Configuration */ +#define XQSPIPS_CR_CPOL_MASK 0x00000002 /**< Polarity Configuration */ + +#define XQSPIPS_CR_MSTREN_MASK 0x00000001 /**< Master Mode Enable */ + +#define XQSPIPS_CR_HOLD_B_MASK 0x00080000 /**< HOLD_B Pin Drive Enable */ + +#define XQSPIPS_CR_REF_CLK_MASK 0x00000100 /**< Ref clk bit - should be 0 */ + +/* Deselect the Slave select line and set the transfer size to 32 at reset */ +#define XQSPIPS_CR_RESET_MASK_SET XQSPIPS_CR_IFMODE_MASK | \ + XQSPIPS_CR_SSCTRL_MASK | \ + XQSPIPS_CR_DATA_SZ_MASK | \ + XQSPIPS_CR_MSTREN_MASK | \ + XQSPIPS_CR_SSFORCE_MASK | \ + XQSPIPS_CR_HOLD_B_MASK +#define XQSPIPS_CR_RESET_MASK_CLR XQSPIPS_CR_CPOL_MASK | \ + XQSPIPS_CR_CPHA_MASK | \ + XQSPIPS_CR_PRESC_MASK | \ + XQSPIPS_CR_MANSTRTEN_MASK | \ + XQSPIPS_CR_MANSTRT_MASK | \ + XQSPIPS_CR_ENDIAN_MASK | \ + XQSPIPS_CR_REF_CLK_MASK +/* @} */ + + +/** @name QSPI Interrupt Registers + * + * QSPI Status Register + * + * This register holds the interrupt status flags for an QSPI device. Some + * of the flags are level triggered, which means that they are set as long + * as the interrupt condition exists. Other flags are edge triggered, + * which means they are set once the interrupt condition occurs and remain + * set until they are cleared by software. The interrupts are cleared by + * writing a '1' to the interrupt bit position in the Status Register. + * Read/Write. + * + * QSPI Interrupt Enable Register + * + * This register is used to enable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register sets the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Disable Register + * + * This register is used to disable chosen interrupts for an QSPI device. + * Writing a '1' to a bit in this register clears the corresponding bit in the + * QSPI Interrupt Mask register. Write only. + * + * QSPI Interrupt Mask Register + * + * This register shows the enabled/disabled interrupts of an QSPI device. + * Read only. + * + * All four registers have the same bit definitions. They are only defined once + * for each of the Interrupt Enable Register, Interrupt Disable Register, + * Interrupt Mask Register, and Channel Interrupt Status Register + * @{ + */ + +#define XQSPIPS_IXR_TXUF_MASK 0x00000040 /**< QSPI Tx FIFO Underflow */ +#define XQSPIPS_IXR_RXFULL_MASK 0x00000020 /**< QSPI Rx FIFO Full */ +#define XQSPIPS_IXR_RXNEMPTY_MASK 0x00000010 /**< QSPI Rx FIFO Not Empty */ +#define XQSPIPS_IXR_TXFULL_MASK 0x00000008 /**< QSPI Tx FIFO Full */ +#define XQSPIPS_IXR_TXOW_MASK 0x00000004 /**< QSPI Tx FIFO Overwater */ +#define XQSPIPS_IXR_RXOVR_MASK 0x00000001 /**< QSPI Rx FIFO Overrun */ +#define XQSPIPS_IXR_DFLT_MASK 0x00000025 /**< QSPI default interrupts + mask */ +#define XQSPIPS_IXR_WR_TO_CLR_MASK 0x00000041 /**< Interrupts which + need write to clear */ +#define XQSPIPS_ISR_RESET_STATE 0x00000004 /**< Default to tx/rx empty */ +#define XQSPIPS_IXR_DISABLE_ALL 0x0000007D /**< Disable all interrupts */ +/* @} */ + + +/** @name Enable Register + * + * This register is used to enable or disable an QSPI device. + * Read/Write + * @{ + */ +#define XQSPIPS_ER_ENABLE_MASK 0x00000001 /**< QSPI Enable Bit Mask */ +/* @} */ + + +/** @name Delay Register + * + * This register is used to program timing delays in + * slave mode. Read/Write + * @{ + */ +#define XQSPIPS_DR_NSS_MASK 0xFF000000 /**< Delay to de-assert slave select + between two words mask */ +#define XQSPIPS_DR_NSS_SHIFT 24 /**< Delay to de-assert slave select + between two words shift */ +#define XQSPIPS_DR_BTWN_MASK 0x00FF0000 /**< Delay Between Transfers + mask */ +#define XQSPIPS_DR_BTWN_SHIFT 16 /**< Delay Between Transfers shift */ +#define XQSPIPS_DR_AFTER_MASK 0x0000FF00 /**< Delay After Transfers mask */ +#define XQSPIPS_DR_AFTER_SHIFT 8 /**< Delay After Transfers shift */ +#define XQSPIPS_DR_INIT_MASK 0x000000FF /**< Delay Initially mask */ +/* @} */ + +/** @name Slave Idle Count Registers + * + * This register defines the number of pclk cycles the slave waits for a the + * QSPI clock to become stable in quiescent state before it can detect the start + * of the next transfer in CPHA = 1 mode. + * Read/Write + * + * @{ + */ +#define XQSPIPS_SICR_MASK 0x000000FF /**< Slave Idle Count Mask */ +/* @} */ + + +/** @name Transmit FIFO Watermark Register + * + * This register defines the watermark setting for the Transmit FIFO. + * + * @{ + */ +#define XQSPIPS_TXWR_MASK 0x0000003F /**< Transmit Watermark Mask */ +#define XQSPIPS_TXWR_RESET_VALUE 0x00000001 /**< Transmit Watermark + * register reset value */ + +/* @} */ + +/** @name Receive FIFO Watermark Register + * + * This register defines the watermark setting for the Receive FIFO. + * + * @{ + */ +#define XQSPIPS_RXWR_MASK 0x0000003F /**< Receive Watermark Mask */ +#define XQSPIPS_RXWR_RESET_VALUE 0x00000001 /**< Receive Watermark + * register reset value */ + +/* @} */ + +/** @name FIFO Depth + * + * This macro provides the depth of transmit FIFO and receive FIFO. + * + * @{ + */ +#define XQSPIPS_FIFO_DEPTH 63 /**< FIFO depth (words) */ +/* @} */ + + +/** @name Linear QSPI Configuration Register + * + * This register contains various control bits that + * affect the operation of the Linear QSPI controller. Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_CR_LINEAR_MASK 0x80000000 /**< LQSPI mode enable */ +#define XQSPIPS_LQSPI_CR_TWO_MEM_MASK 0x40000000 /**< Both memories or one */ +#define XQSPIPS_LQSPI_CR_SEP_BUS_MASK 0x20000000 /**< Separate memory bus */ +#define XQSPIPS_LQSPI_CR_U_PAGE_MASK 0x10000000 /**< Upper memory page */ +#define XQSPIPS_LQSPI_CR_MODE_EN_MASK 0x02000000 /**< Enable mode bits */ +#define XQSPIPS_LQSPI_CR_MODE_ON_MASK 0x01000000 /**< Mode on */ +#define XQSPIPS_LQSPI_CR_MODE_BITS_MASK 0x00FF0000 /**< Mode value for dual I/O + or quad I/O */ +#define XQSPIPS_LQSPI_CR_DUMMY_MASK 0x00000700 /**< Number of dummy bytes + between addr and return + read data */ +#define XQSPIPS_LQSPI_CR_INST_MASK 0x000000FF /**< Read instr code */ +#define XQSPIPS_LQSPI_CR_RST_STATE 0x8000016B /**< Default CR value */ +/* @} */ + +/** @name Linear QSPI Status Register + * + * This register contains various status bits of the Linear QSPI controller. + * Read/Write. + * + * @{ + */ +#define XQSPIPS_LQSPI_SR_D_FSM_ERR_MASK 0x00000004 /**< AXI Data FSM Error + received */ +#define XQSPIPS_LQSPI_SR_WR_RECVD_MASK 0x00000002 /**< AXI write command + received */ +/* @} */ + + +/** @name Loopback Delay Adjust Register + * + * This register contains various bit masks of Loopback Delay Adjust Register. + * + * @{ + */ + +#define XQSPIPS_LPBK_DLY_ADJ_USE_LPBK_MASK 0x00000020 /**< Loopback Bit */ + +/* @} */ + + +/** @name SLCR Register + * + * Register offsets from SLCR base address. + * + * @{ + */ + +#define SLCR_LOCK 0x00000004 /**< SLCR Write Protection Lock */ +#define SLCR_UNLOCK 0x00000008 /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL 0x00000230 /**< Quad SPI Software Reset Control */ +#define SLCR_LOCKSTA 0x0000000C /**< SLCR Write Protection status */ + +/* @} */ + + +/** @name SLCR Register + * + * Bit Masks of above SLCR Registers . + * + * @{ + */ + +#ifndef XPAR_XSLCR_0_BASEADDR +#define XPAR_XSLCR_0_BASEADDR 0xF8000000 +#endif +#define SLCR_LOCK_MASK 0x767B /**< Write Protection Lock mask*/ +#define SLCR_UNLOCK_MASK 0xDF0D /**< SLCR Write Protection Unlock */ +#define LQSPI_RST_CTRL_MASK 0x3 /**< Quad SPI Software Reset Control */ + +/* @} */ + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XQspiPs_In32 Xil_In32 +#define XQspiPs_Out32 Xil_Out32 +#define XQSPIPS_DUMMY_TX_DATA 0xFFFFFFFF + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XQspiPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +#define XQspiPs_ReadReg(BaseAddress, RegOffset) \ + XQspiPs_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XQspiPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +* +******************************************************************************/ +#define XQspiPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XQspiPs_Out32((BaseAddress) + (RegOffset), (RegisterValue)) + +/************************** Function Prototypes ******************************/ + +/* + * Functions implemented in xqspips_hw.c + */ +void XQspiPs_ResetHw(u32 BaseAddress); +void XQspiPs_LinearInit(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_options.c b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_options.c new file mode 100644 index 0000000..54d455d --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_options.c @@ -0,0 +1,404 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xqspips_options.c +* @addtogroup qspips_v3_10 +* @{ +* +* Contains functions for the configuration of the XQspiPs driver component. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.00a kka 07/25/12 Removed the selection for the following options:
+*		     Master mode (XQSPIPS_MASTER_OPTION) and
+*		     Flash interface mode (XQSPIPS_FLASH_MODE_OPTION) option
+*		     as the QSPI driver supports the Master mode
+*		     and Flash Interface mode. The driver doesnot support
+*		     Slave mode or the legacy mode.
+* 		     Added the option for setting the Holdb_dr bit in the
+*		     configuration options, XQSPIPS_HOLD_B_DRIVE_OPTION
+*		     is the option to be used for setting this bit in the
+*		     configuration register.
+* 2.01a sg  02/03/13 SetDelays and GetDelays API's include DelayNss parameter.
+*
+* 2.02a hk  26/03/13 Removed XQspi_Reset() in Set_Options() function when
+*			 LQSPI_MODE_OPTION is set. Moved Enable() to XQpsiPs_LqspiRead().
+* 3.3   sk  11/07/15 Modified the API prototypes according to MISRAC standards
+*                    to remove compilation warnings. CR# 868893.
+*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/* + * Create the table of options which are processed to get/set the device + * options. These options are table driven to allow easy maintenance and + * expansion of the options. + */ +typedef struct { + u32 Option; + u32 Mask; +} OptionsMap; + +static OptionsMap OptionsTable[] = { + {XQSPIPS_CLK_ACTIVE_LOW_OPTION, XQSPIPS_CR_CPOL_MASK}, + {XQSPIPS_CLK_PHASE_1_OPTION, XQSPIPS_CR_CPHA_MASK}, + {XQSPIPS_FORCE_SSELECT_OPTION, XQSPIPS_CR_SSFORCE_MASK}, + {XQSPIPS_MANUAL_START_OPTION, XQSPIPS_CR_MANSTRTEN_MASK}, + {XQSPIPS_HOLD_B_DRIVE_OPTION, XQSPIPS_CR_HOLD_B_MASK}, +}; + +#define XQSPIPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap)) + +/*****************************************************************************/ +/** +* +* This function sets the options for the QSPI device driver. The options control +* how the device behaves relative to the QSPI bus. The device must be idle +* rather than busy transferring data before setting these device options. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param Options contains the specified options to be set. This is a bit +* mask where a 1 means to turn the option on, and a 0 means to +* turn the option off. One or more bit values may be contained in +* the mask. See the bit definitions named XQSPIPS_*_OPTIONS in +* the file xqspips.h. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note +* This function is not thread-safe. +* +******************************************************************************/ +s32 XQspiPs_SetOptions(XQspiPs *InstancePtr, u32 Options) +{ + u32 ConfigReg; + unsigned int Index; + u32 QspiOptions; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Do not allow to modify the Control Register while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + QspiOptions = Options & XQSPIPS_LQSPI_MODE_OPTION; + Options &= ~XQSPIPS_LQSPI_MODE_OPTION; + + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + /* + * Loop through the options table, turning the option on or off + * depending on whether the bit is set in the incoming options flag. + */ + for (Index = 0; Index < XQSPIPS_NUM_OPTIONS; Index++) { + if (Options & OptionsTable[Index].Option) { + /* Turn it on */ + ConfigReg |= OptionsTable[Index].Mask; + } else { + /* Turn it off */ + ConfigReg &= ~(OptionsTable[Index].Mask); + } + } + + /* + * Now write the control register. Leave it to the upper layers + * to restart the device. + */ + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, + ConfigReg); + + /* + * Check for the LQSPI configuration options. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET); + + + if (QspiOptions & XQSPIPS_LQSPI_MODE_OPTION) { + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET, + XQSPIPS_LQSPI_CR_RST_STATE); + XQspiPs_SetSlaveSelect(InstancePtr); + } else { + ConfigReg &= ~XQSPIPS_LQSPI_CR_LINEAR_MASK; + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET, ConfigReg); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function gets the options for the QSPI device. The options control how +* the device behaves relative to the QSPI bus. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* +* Options contains the specified options currently set. This is a bit value +* where a 1 means the option is on, and a 0 means the option is off. +* See the bit definitions named XQSPIPS_*_OPTIONS in file xqspips.h. +* +* @note None. +* +******************************************************************************/ +u32 XQspiPs_GetOptions(XQspiPs *InstancePtr) +{ + u32 OptionsFlag = 0; + u32 ConfigReg; + unsigned int Index; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the current options from QSPI configuration register. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + /* + * Loop through the options table to grab options + */ + for (Index = 0; Index < XQSPIPS_NUM_OPTIONS; Index++) { + if (ConfigReg & OptionsTable[Index].Mask) { + OptionsFlag |= OptionsTable[Index].Option; + } + } + + /* + * Check for the LQSPI configuration options. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_LQSPI_CR_OFFSET); + + if ((ConfigReg & XQSPIPS_LQSPI_CR_LINEAR_MASK) != 0) { + OptionsFlag |= XQSPIPS_LQSPI_MODE_OPTION; + } + + return OptionsFlag; +} + +/*****************************************************************************/ +/** +* +* This function sets the clock prescaler for an QSPI device. The device +* must be idle rather than busy transferring data before setting these device +* options. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param Prescaler is the value that determine how much the clock should +* be divided by. Use the XQSPIPS_CLK_PRESCALE_* constants defined +* in xqspips.h for this setting. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note +* This function is not thread-safe. +* +******************************************************************************/ +s32 XQspiPs_SetClkPrescaler(XQspiPs *InstancePtr, u8 Prescaler) +{ + u32 ConfigReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Prescaler <= XQSPIPS_CR_PRESC_MAXIMUM); + + /* + * Do not allow the slave select to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Read the configuration register, mask out the interesting bits, and set + * them with the shifted value passed into the function. Write the + * results back to the configuration register. + */ + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + ConfigReg &= ~XQSPIPS_CR_PRESC_MASK; + ConfigReg |= (u32) (Prescaler & XQSPIPS_CR_PRESC_MAXIMUM) << + XQSPIPS_CR_PRESC_SHIFT; + + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET, + ConfigReg); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function gets the clock prescaler of an QSPI device. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return The prescaler value. +* +* @note None. +* +* +******************************************************************************/ +u8 XQspiPs_GetClkPrescaler(XQspiPs *InstancePtr) +{ + u32 ConfigReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + ConfigReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_CR_OFFSET); + + ConfigReg &= XQSPIPS_CR_PRESC_MASK; + + return (u8)(ConfigReg >> XQSPIPS_CR_PRESC_SHIFT); +} + +/*****************************************************************************/ +/** +* +* This function sets the delay register for the QSPI device driver. +* The delay register controls the Delay Between Transfers, Delay After +* Transfers, and the Delay Initially. The default value is 0x0. The range of +* each delay value is 0-255. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param DelayNss is the delay to de-assert slave select between +* two word transfers. +* @param DelayBtwn is the delay between one Slave Select being +* de-activated and the activation of another slave. The delay is +* the number of master clock periods given by DelayBtwn + 2. +* @param DelayAfter define the delay between the last bit of the current +* byte transfer and the first bit of the next byte transfer. +* The delay in number of master clock periods is given as: +* CHPA=0:DelayInit+DelayAfter+3 +* CHPA=1:DelayAfter+1 +* @param DelayInit is the delay between asserting the slave select signal +* and the first bit transfer. The delay int number of master clock +* periods is DelayInit+1. +* +* @return +* - XST_SUCCESS if delays are successfully set. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting options. +* +* @note None. +* +******************************************************************************/ +int XQspiPs_SetDelays(XQspiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn, + u8 DelayAfter, u8 DelayInit) +{ + u32 DelayRegister; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Do not allow the delays to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* Shift, Mask and OR the values to build the register settings */ + DelayRegister = (u32) DelayNss << XQSPIPS_DR_NSS_SHIFT; + DelayRegister |= (u32) DelayBtwn << XQSPIPS_DR_BTWN_SHIFT; + DelayRegister |= (u32) DelayAfter << XQSPIPS_DR_AFTER_SHIFT; + DelayRegister |= (u32) DelayInit; + + XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPS_DR_OFFSET, DelayRegister); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function gets the delay settings for an QSPI device. +* The delay register controls the Delay Between Transfers, Delay After +* Transfers, and the Delay Initially. The default value is 0x0. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* @param DelayNss is a pointer to the Delay to de-assert slave select +* between two word transfers. +* @param DelayBtwn is a pointer to the Delay Between transfers value. +* This is a return parameter. +* @param DelayAfter is a pointer to the Delay After transfer value. +* This is a return parameter. +* @param DelayInit is a pointer to the Delay Initially value. This is +* a return parameter. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XQspiPs_GetDelays(XQspiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn, + u8 *DelayAfter, u8 *DelayInit) +{ + u32 DelayRegister; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + DelayRegister = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPS_DR_OFFSET); + + *DelayInit = (u8)(DelayRegister & XQSPIPS_DR_INIT_MASK); + + *DelayAfter = (u8)((DelayRegister & XQSPIPS_DR_AFTER_MASK) >> + XQSPIPS_DR_AFTER_SHIFT); + + *DelayBtwn = (u8)((DelayRegister & XQSPIPS_DR_BTWN_MASK) >> + XQSPIPS_DR_BTWN_SHIFT); + + *DelayNss = (u8)((DelayRegister & XQSPIPS_DR_NSS_MASK) >> + XQSPIPS_DR_NSS_SHIFT); +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_selftest.c b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_selftest.c new file mode 100644 index 0000000..a35158d --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_selftest.c @@ -0,0 +1,113 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xqspips_selftest.c +* @addtogroup qspips_v3_10 +* @{ +* +* This file contains the implementation of selftest function for the QSPI +* device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 2.01a sg  02/03/13 Delay Register test is added with DelayNss parameter.
+* 3.1   hk  06/19/14 Remove checks for CR and ISR register values as they are
+*                    reset in the previous step.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspips.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* Runs a self-test on the driver/device. The self-test is destructive in that +* a reset of the device is performed in order to check the reset values of +* the registers and to get the device into a known state. +* +* Upon successful return from the self-test, the device is reset. +* +* @param InstancePtr is a pointer to the XQspiPs instance. +* +* @return +* - XST_SUCCESS if successful +* - XST_REGISTER_ERROR indicates a register did not read or write +* correctly. +* +* @note None. +* +******************************************************************************/ +int XQspiPs_SelfTest(XQspiPs *InstancePtr) +{ + int Status; + u8 DelayTestNss; + u8 DelayTestBtwn; + u8 DelayTestAfter; + u8 DelayTestInit; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Reset the QSPI device to leave it in a known good state + */ + XQspiPs_Reset(InstancePtr); + + DelayTestNss = 0x5A; + DelayTestBtwn = 0xA5; + DelayTestAfter = 0xAA; + DelayTestInit = 0x55; + + /* + * Write and read the delay register, just to be sure there is some + * hardware out there. + */ + Status = XQspiPs_SetDelays(InstancePtr, DelayTestNss, DelayTestBtwn, + DelayTestAfter, DelayTestInit); + if (Status != XST_SUCCESS) { + return Status; + } + + XQspiPs_GetDelays(InstancePtr, &DelayTestNss, &DelayTestBtwn, + &DelayTestAfter, &DelayTestInit); + if ((0x5A != DelayTestNss) || (0xA5 != DelayTestBtwn) || + (0xAA != DelayTestAfter) || (0x55 != DelayTestInit)) { + return XST_REGISTER_ERROR; + } + + Status = XQspiPs_SetDelays(InstancePtr, 0, 0, 0, 0); + if (Status != XST_SUCCESS) { + return Status; + } + + /* + * Reset the QSPI device to leave it in a known good state + */ + XQspiPs_Reset(InstancePtr); + + return XST_SUCCESS; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_sinit.c new file mode 100644 index 0000000..f47fb67 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/qspips/src/xqspips_sinit.c @@ -0,0 +1,74 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xqspips_sinit.c +* @addtogroup qspips_v3_10 +* @{ +* +* The implementation of the XQspiPs component's static initialization +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sdm 11/25/10 First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xqspips.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +extern XQspiPs_Config XQspiPs_ConfigTable[]; + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the ID of the device to look up the +* configuration for. +* +* @return +* +* A pointer to the configuration found or NULL if the specified device ID was +* not found. See xqspips.h for the definition of XQspiPs_Config. +* +* @note None. +* +******************************************************************************/ +XQspiPs_Config *XQspiPs_LookupConfig(u16 DeviceId) +{ + XQspiPs_Config *CfgPtr = NULL; + int Index; + + for (Index = 0; Index < XPAR_XQSPIPS_NUM_INSTANCES; Index++) { + if (XQspiPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XQspiPs_ConfigTable[Index]; + break; + } + } + return CfgPtr; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/Makefile new file mode 100644 index 0000000..eb496ea --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/Makefile @@ -0,0 +1,39 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf ${DEPFILES} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic.c b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic.c new file mode 100644 index 0000000..bb74614 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic.c @@ -0,0 +1,1504 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscugic.c +* @addtogroup scugic Overview +* @{ +* +* Contains required functions for the XScuGic driver for the Interrupt +* Controller. See xscugic.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 Changes are made in function XScuGic_CfgInitialize
+*                     Since entry is now made as pointer in the XScuGic
+*                     structure, necessary changes are made.
+*                     The HandlerTable can now be populated through the low
+*                     level routine XScuGic_RegisterHandler added in this
+*                     release. Hence necessary checks are added not to
+*                     overwrite the HandlerTable entries in function
+*                     XScuGic_CfgInitialize.
+* 1.03a srt  02/27/13 Added APIs
+*                       -XScuGic_SetPriTrigTypeByDistAddr()
+*                       -XScuGic_GetPriTrigTypeByDistAddr()
+*                     Removed Offset calculation macros, defined in _hw.h
+*                     (CR 702687)
+*                     added support to direct interrupts  to the appropriate
+*                     CPU Earlier interrupts were directed to CPU1
+*                     (hard coded).Now depending upon the CPU selected by the
+*                     user(xparameters.h), interrupts will be directed to
+*                     the  relevant CPU. This fixes CR 699688.
+*
+* 1.04a hk   05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
+*                     XScuGic_CfgInitialize. Fix for CR#704400 to remove
+*                     warnings.
+*                     Moved functions XScuGic_SetPriTrigTypeByDistAddr and
+*                    XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
+*                    This is fix for CR#705621.
+* 1.06a asa  16/11/13 Fix for CR#749178. Assignment for EffectiveAddr
+*                     in function XScuGic_CfgInitialize is removed as it was
+*                     a bug.
+* 3.00  kvn  02/13/14 Modified code for MISRA-C:2012 compliance.
+* 3.01  pkp  06/19/15 Added XScuGic_InterruptMaptoCpu API for an interrupt
+*                     target CPU mapping
+* 3.02  pkp  11/09/15 Modified DistributorInit function for AMP case to add
+*                     the current cpu to interrupt processor targets registers
+* 3.2   asa  02/29/16 Modified DistributorInit function for Zynq AMP case. The
+*                     distributor is left uninitialized for Zynq AMP. It is
+*                     assumed that the distributor will be initialized by
+*                     Linux master. However for CortexR5 case, the earlier code
+*                     is left unchanged where the interrupt processor target
+*                     registers in the distributor is initialized with the
+*                     corresponding CPU ID on which the application built over
+*                     the scugic driver runs. These changes fix CR#937243.
+* 3.3   pkp  05/12/16 Modified XScuGic_InterruptMaptoCpu to write proper value
+*                     to interrupt target register to fix CR#951848
+*
+* 3.4   asa  04/07/16 Created a new static function DoDistributorInit to
+*                     simplify the flow and avoid code duplication. Changes are
+*                     made for USE_AMP use case for R5. In a scenario
+*                     (in R5 split mode) when one R5 is operating with A53 in
+*                     open amp config and other R5 running baremetal app, the
+*                     existing code had the potential to stop the whole AMP
+*                     solution to work (if for some reason the R5 running the
+*                     baremetal app tasked to initialize the Distributor hangs
+*                     or crashes before initializing).Changes are made so that
+*                     the R5 under AMP first checks if the distributor is
+*                     enabled or not and if not, it does the standard
+*                     Distributor initialization.This fixes the CR#952962.
+* 3.4   mus  09/08/16 Added assert to avoid invalid access of GIC from CPUID 1
+*                     for single core zynq-7000s
+* 3.5   mus  10/05/16 Modified DistributorInit function to avoid
+*                     re-initialization of distributor, If it is already
+*                     initialized by other CPU.
+* 3.5   pkp  10/17/16 Modified XScuGic_InterruptMaptoCpu to correct the CPU Id
+*                     value and properly mask interrupt target processor value
+*                     to modify interrupt target processor register for a given
+*                     interrupt ID and cpu ID
+* 3.6   pkp  20/01/17 Added new API XScuGic_Stop to Disable distributor and
+*                     interrupts in case they are being used only by current
+*                     cpu. It also removes current cpu from interrupt target
+*                     registers for all interrupts.
+*       kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+* 3.9   mus  02/21/18 Added new API's XScuGic_UnmapAllInterruptsFromCpu and
+*                     XScuGic_InterruptUnmapFromCpu, These API's can be used
+*                     by applications to unmap specific/all interrupts from
+*                     target CPU. It fixes CR#992490.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+*                     It fixes CR#1007753.
+* 3.10  mus  09/19/18 Fix cppcheck warnings
+* 4.0   mus  11/22/18 Fixed bugs in software interrupt generation through
+*                     XScuGic_SoftwareIntr API
+* 4.1   asa  03/30/19 Made changes not to direct each interrupt to all
+*                     available CPUs by default. This was breaking AMP
+*                     behavior. Instead every time an interrupt enable
+*                     request is received, the interrupt was mapped to
+*                     the respective CPU. There were several other changes
+*                     made to implement this. This set of changes was to
+*                     fix CR-1024716.
+* 4.1   mus  06/19/19 Added API's XScuGic_MarkCoreAsleep and
+*                     XScuGic_MarkCoreAwake to mark processor core as
+*                     asleep or awake. Fix for CR#1027220.
+* 4.3   mus  10/14/20 Updated XScuGic_Stop for scenarios where USE_AMP flag
+*                     is set to 1. Now, XScuGic_Stop would not disable
+*                     distributor for USE_AMP=1, even when SPI interrupts
+*                     are not being used by other CPU. This update is needed
+*                     to support scenarios, where master CPU is using only
+*                     SGI/PPI interrupts. It fixes CR#1079241.
+* 4.5   asa  03/07/21 Added spinlock protection for critical sections in the
+*                     code. The sections are critical when applications
+*                     running on separate CPUs (R5s or A9s) try to update
+*                     the same register. The spinlock mechanism used here
+*                     used exclusive load and store instructions. To ensure
+*                     that legacy behavior is not broken, unless someone
+*                     enables spinlocks explicitely in their applications
+*                     the existing flow will remain unchanged. On how to
+*                     enable spinlocks, please refer to the documentations
+*                     at: lib/bsp/standalone/src/arm/common/gcc/xil_spinlock.c
+* 4.6	sk   08/05/21 Fix scugic Misra-c violations.
+* 4.7	sk   09/14/21 Fix gcc compiler warnings for A72 processor.
+* 4.7	sk   10/13/21 Update APIs to perform interrupt mapping/unmapping only
+* 		      when (Int_Id >= XSCUGIC_SPI_INT_ID_START).
+* 4.7   dp   11/22/21 Added new API XScuGic_IsInitialized() to check and return
+*                     the GIC initialization status.
+* 4.7   mus  03/17/22 Fixed XScuGic_InterruptMaptoCpu and
+*                     XScuGic_InterruptUnmapFromCpu for GICv3. It fixes
+*                     CR#1126156.
+* 5.0   mus  22/02/22 Added support for VERSAL NET.
+* 5.0   asa  03/29/22 The API XScuGic_IsInitialized has a bug where if
+* 		      Distributor Control Register, GICD_CTLR has both
+* 		      bit 0 and 1 set, the API wrongly returns 0.
+*                     This is fixed with this change.
+* 5.0   dp   04/25/22 Update XScuGic_GetPriorityTriggerType() to read and
+*                     update priority and trigger properly for GICv3.
+* 5.1   mus  02/09/23 Updated DoDistributorInit function to skip enablement
+*                     of group0 interrupts when processor is running at
+*                     EL1 NS. This is required to avoid abort, since access
+*                     to ICC_IGRPEN0_EL1 is resulting into sync abort.
+*                     It fixes CR#1152445.
+* 5.1   mus  02/13/23 Updated XScuGic_CfgInitialize, XScuGic_Enable and
+*                     XScuGic_Disable to support interrupts on each core
+*                     of all CortexA78/CortexR52 clusters in VERSAL NET SoC.
+*                     While at it, modified interrupt routing logic to make
+*                     use of CPU affinity register instead of XPAR_CPU_ID macro.
+*                     Also, XScuGic_CfgInitialize has been updated to find
+*                     redistributor base address of core on which API is
+*                     executed, redistributor address will be stored in newly
+*                     added member of XScuGic data structure "RedistBaseAddr".
+*                     It fixes CR#1150432.
+* 5.1   mus  02/27/23 Updated XScuGic_Stop for GICv3, to check routing register for
+*                     detecting targeted cores for specific interrupt id.
+*                     Also, DoDistributorInit has been modified to move CPU
+*                     interface specific register writes to XScuGic_CfgInitialize.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" +#if defined (VERSAL_NET) +#include "xplatform_info.h" +#endif +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ +static u32 CpuId = XPAR_CPU_ID; /**< CPU Core identifier */ + +/************************** Function Prototypes ******************************/ + +static void StubHandler(void *CallBackRef); + +/*****************************************************************************/ +/** +* +* DoDistributorInit initializes the distributor of the GIC. The +* initialization entails: +* +* - Write the trigger mode, priority +* - All interrupt sources are disabled +* - Enable the distributor +* +* @param InstancePtr is a pointer to the XScuGic instance. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void DoDistributorInit(const XScuGic *InstancePtr) +{ + u32 Int_Id; + +#if defined (GICv3) + u32 Temp; + + Temp = XScuGic_DistReadReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET); + Temp = (XSCUGIC500_DCTLR_ARE_NS_ENABLE | XSCUGIC500_DCTLR_ARE_S_ENABLE); + Temp &= ~(XSCUGIC_EN_INT_MASK); + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, Temp); +#else + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, 0U); +#endif + + /* + * Set the security domains in the int_security registers for + * non-secure interrupts + * All are secure, so leave at the default. Set to 1 for non-secure + * interrupts. + */ + + /* + * For the Shared Peripheral Interrupts INT_ID[MAX..32], set: + */ + + /* + * 1. The trigger mode in the int_config register + * Only write to the SPI interrupts, so start at 32 + */ + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+16U) { + /* + * Each INT_ID uses two bits, or 16 INT_ID per register + * Set them all to be level sensitive, active HIGH. + */ + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), + 0U); + } + + +#define DEFAULT_PRIORITY 0xa0a0a0a0U + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + /* + * 2. The priority using int the priority_level register + * The priority_level and spi_target registers use one byte per + * INT_ID. + * Write a default value that can be changed elsewhere. + */ + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + DEFAULT_PRIORITY); + } + +#if defined (GICv3) + for (Int_Id = 0U; Int_IdBaseAddress for this parameters, passing the physical +* address instead. +* +* @return +* - XST_SUCCESS if initialization was successful +* +* @note None. +* +******************************************************************************/ +s32 XScuGic_CfgInitialize(XScuGic *InstancePtr, + XScuGic_Config *ConfigPtr, + u32 EffectiveAddr) +{ + u32 Int_Id; + (void) EffectiveAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + /* + * Check Zynq-7000 base silicon configuration. + * If it is single CPU configuration then invoke assert for CPU ID 1. + */ +#ifdef ARMA9 + if (XPAR_CPU_ID == 0x01) { + Xil_AssertNonvoid((Xil_In32(XPS_EFUSE_BASEADDR + + EFUSE_STATUS_OFFSET) & EFUSE_STATUS_CPU_MASK) == 0); + } +#endif + + if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) { + + InstancePtr->IsReady = 0U; + InstancePtr->Config = ConfigPtr; + #if defined(ARMR52) + /* Read Distributor base address through IMP_CBAR register */ + ConfigPtr->DistBaseAddress = mfcp(XREG_IMP_CBAR); + #endif + + + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id++) { + /* + * Initialize the handler to point to a stub to handle an + * interrupt which has not been connected to a handler + * Only initialize it if the handler is 0 which means it + * was not initialized statically by the tools/user. Set + * the callback reference to this instance so that + * unhandled interrupts can be tracked. + */ + if ((InstancePtr->Config->HandlerTable[Int_Id].Handler + == (Xil_InterruptHandler)NULL)) { + InstancePtr->Config->HandlerTable[Int_Id].Handler + = (Xil_InterruptHandler)StubHandler; + } + InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = + InstancePtr; + } +#if defined (GICv3) + u32 Waker_State; + + InstancePtr->RedistBaseAddr = XScuGic_GetRedistBaseAddr(); + + #if defined (GIC600) + XScuGic_ReDistWriteReg(InstancePtr,XSCUGIC_RDIST_PWRR_OFFSET, + (XScuGic_ReDistReadReg(InstancePtr, XSCUGIC_RDIST_PWRR_OFFSET) & + (~XSCUGIC_RDIST_PWRR_RDPD_MASK))); + #endif + + Waker_State = XScuGic_ReDistReadReg(InstancePtr,XSCUGIC_RDIST_WAKER_OFFSET); + XScuGic_ReDistWriteReg(InstancePtr,XSCUGIC_RDIST_WAKER_OFFSET, + Waker_State & (~ XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK)); + /* Enable system reg interface through ICC_SRE_EL1 */ + #if EL3 + XScuGic_Enable_SystemReg_CPU_Interface_EL3(); + #endif + XScuGic_Enable_SystemReg_CPU_Interface_EL1(); + isb(); +#endif + XScuGic_Stop(InstancePtr); + DistributorInit(InstancePtr); +#if defined (GICv3) + XScuGic_Enable_Group1_Interrupts(); + #if defined (ARMR52) || (defined (__aarch64__) && (EL1_NONSECURE == 0)) + XScuGic_Enable_Group0_Interrupts(); + #endif + XScuGic_set_priority_filter(0xff); +#else + CPUInitialize(InstancePtr); +#endif + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Makes the connection between the Int_Id of the interrupt source and the +* associated handler that is to run when the interrupt is recognized. The +* argument provided in this call as the Callbackref is used as the argument +* for the handler when it is called. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* @param Handler to the handler for that interrupt. +* @param CallBackRef is the callback reference, usually the instance +* pointer of the connecting driver. +* +* @return +* +* - XST_SUCCESS if the handler was connected correctly. +* +* @note +* +* WARNING: The handler provided as an argument will overwrite any handler +* that was previously connected. +* +****************************************************************************/ +s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id, + Xil_InterruptHandler Handler, void *CallBackRef) +{ + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertNonvoid(Handler != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The Int_Id is used as an index into the table to select the proper + * handler + */ + InstancePtr->Config->HandlerTable[Int_Id].Handler = (Xil_InterruptHandler)Handler; + InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = CallBackRef; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Updates the interrupt table with the Null Handler and NULL arguments at the +* location pointed at by the Int_Id. This effectively disconnects that interrupt +* source from any handler. The interrupt is disabled also. +* +* @param InstancePtr is a pointer to the XScuGic instance to be worked on. +* @param Int_Id contains the ID of the interrupt source and should +* be in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id) +{ + u32 Mask; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + + /* + * The Int_Id is used to create the appropriate mask for the + * desired bit position. Int_Id currently limited to 0 - 31 + */ + Mask = (u32)0x00000001U << (Int_Id % 32U); + + /* + * Disable the interrupt such that it won't occur while disconnecting + * the handler, only disable the specified interrupt id without + * modifying the other interrupt ids + */ + XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_DISABLE_OFFSET + + ((Int_Id / 32U) * 4U), Mask); + + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); + /* + * Disconnect the handler and connect a stub, the callback reference + * must be set to this instance to allow unhandled interrupts to be + * tracked + */ + InstancePtr->Config->HandlerTable[Int_Id].Handler = (Xil_InterruptHandler)StubHandler; + InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = InstancePtr; +} + +/*****************************************************************************/ +/** +* +* Enables the interrupt source provided as the argument Int_Id. Any pending +* interrupt condition for the specified Int_Id will occur after this function is +* called. +* This API also maps the interrupt to the requesting CPU. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id) +{ + u32 Mask; + u8 Cpu_Identifier = (u8)CpuId; + +#if defined (GICv3) + u32 Temp; +#endif + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#if defined (GICv3) + if (Int_Id < XSCUGIC_SPI_INT_ID_START) { + + Int_Id &= 0x1f; + Int_Id = 1 << Int_Id; + + Temp = XScuGic_ReDistSGIPPIReadReg(InstancePtr,XSCUGIC_RDIST_ISENABLE_OFFSET); + Temp |= Int_Id; + XScuGic_ReDistSGIPPIWriteReg(InstancePtr,XSCUGIC_RDIST_ISENABLE_OFFSET,Temp); + return; + } +#endif + #if defined (VERSAL_NET) + #if defined (ARMR52) + Cpu_Identifier = XGetCoreId(); + #else + Cpu_Identifier = XGetCoreId(); + Cpu_Identifier |= (XGetClusterId() << XSCUGIC_CLUSTERID_SHIFT); + #endif + #endif + XScuGic_InterruptMaptoCpu(InstancePtr, Cpu_Identifier, Int_Id); + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + /* + * The Int_Id is used to create the appropriate mask for the + * desired bit position. + */ + Mask = (u32)0x00000001U << (Int_Id % 32U); + /* + * Enable the selected interrupt source by setting the + * corresponding bit in the Enable Set register. + */ + XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_ENABLE_SET_OFFSET + + ((Int_Id / 32U) * 4U), Mask); + + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +} + +/*****************************************************************************/ +/** +* +* Disables the interrupt source provided as the argument Int_Id such that the +* interrupt controller will not cause interrupts for the specified Int_Id. The +* interrupt controller will continue to hold an interrupt condition for the +* Int_Id, but will not cause an interrupt. +* This API also unmaps the interrupt for the requesting CPU. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id) +{ + u32 Mask; + u8 Cpu_Identifier = (u8)CpuId; +#if defined (GICv3) + u32 Temp; +#endif + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#if defined (GICv3) + if (Int_Id < XSCUGIC_SPI_INT_ID_START) { + + Int_Id &= 0x1f; + Int_Id = 1 << Int_Id; + + Temp = XScuGic_ReDistSGIPPIReadReg(InstancePtr,XSCUGIC_RDIST_ISENABLE_OFFSET); + Temp &= ~Int_Id; + XScuGic_ReDistSGIPPIWriteReg(InstancePtr,XSCUGIC_RDIST_ISENABLE_OFFSET,Temp); + return; + } +#endif + #if defined (VERSAL_NET) + #if defined (ARMR52) + Cpu_Identifier = XGetCoreId(); + #else + Cpu_Identifier = XGetCoreId(); + Cpu_Identifier |= (XGetClusterId() << XSCUGIC_CLUSTERID_SHIFT); + #endif + #endif + + XScuGic_InterruptUnmapFromCpu(InstancePtr, Cpu_Identifier, Int_Id); + + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + /* + * The Int_Id is used to create the appropriate mask for the + * desired bit position. Int_Id currently limited to 0 - 31 + */ + Mask = (u32)0x00000001U << (Int_Id % 32U); + + /* + * Disable the selected interrupt source by setting the + * corresponding bit in the IDR. + */ + XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_DISABLE_OFFSET + + ((Int_Id / 32U) * 4U), Mask); + + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +} + +/*****************************************************************************/ +/** +* +* Allows software to simulate an interrupt in the interrupt controller. This +* function will only be successful when the interrupt controller has been +* started in simulation mode. A simulated interrupt allows the interrupt +* controller to be tested without any device to drive an interrupt input +* signal into it. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id is the software interrupt ID to simulate an interrupt. +* @param Cpu_Identifier is the list of CPUs to send the interrupt. +* For VERSAL_NET bits 0-7 specifies core id to send the interrupt. +* bits 8-15 specifies the cluster id. +* +* @return +* +* XST_SUCCESS if successful, or XST_FAILURE if the interrupt could not be +* simulated +* +* @note None. +* +******************************************************************************/ +s32 XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Identifier) +{ +#if defined (GICv3) + u64 Mask; +#else + u32 Mask; +#endif + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Int_Id <= 15U); +#if ! defined (VERSAL_NET) + Xil_AssertNonvoid(Cpu_Identifier <= 255U); +#endif + +#if defined (GICv3) + #if defined (VERSAL_NET) + #if defined (ARMR52) + Mask = ((Cpu_Identifier & XSCUGIC_CLUSTERID_MASK) >> XSCUGIC_CLUSTERID_SHIFT); + Mask = ( Mask << XSCUGIC_SGI1R_AFFINITY1_SHIFT); + Mask |= (Cpu_Identifier & XSCUGIC_COREID_MASK); + #else + Mask = ((Cpu_Identifier & XSCUGIC_CLUSTERID_MASK) >> XSCUGIC_CLUSTERID_SHIFT); + Mask = ( Mask << XSCUGIC_SGI1R_AFFINITY2_SHIFT); + + Mask |= ((Cpu_Identifier & XSCUGIC_COREID_MASK) << XSCUGIC_SGI1R_AFFINITY1_SHIFT); + Mask |= 0x1; + #endif + + Mask |= (Int_Id << XSCUGIC_SGIR_EL1_INITID_SHIFT); + #else + Mask = (Cpu_Identifier | (Int_Id << XSCUGIC_SGIR_EL1_INITID_SHIFT)); + #endif +#if EL3 + XScuGic_WriteICC_SGI0R_EL1(Mask); +#else + XScuGic_WriteICC_SGI1R_EL1(Mask); +#endif +#else + + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + + /* + * The Int_Id is used to create the appropriate mask for the + * desired interrupt. Int_Id currently limited to 0 - 15 + * Use the target list for the Cpu ID. + */ + Mask = ((Cpu_Identifier << 16U) | Int_Id) & + (XSCUGIC_SFI_TRIG_CPU_MASK | XSCUGIC_SFI_TRIG_INTID_MASK); + + /* + * Write to the Software interrupt trigger register. Use the appropriate + * CPU Int_Id. + */ + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_SFI_TRIG_OFFSET, Mask); + + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); + + /* Indicate the interrupt was successfully simulated */ +#endif + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* A stub for the asynchronous callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubHandler(void *CallBackRef) +{ + /* + * verify that the inputs are valid + */ + Xil_AssertVoid(CallBackRef != NULL); + + /* + * Indicate another unhandled interrupt for stats + */ + ((XScuGic *)((void *)CallBackRef))->UnhandledInterrupts++; +} + +/****************************************************************************/ +/** +* Sets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Int_Id is the IRQ source number to modify +* @param Priority is the new priority for the IRQ source. 0 is highest +* priority, 0xF8(248) is lowest. There are 32 priority levels +* supported with a step of 8. Hence the supported priorities are +* 0, 8, 16, 32, 40 ..., 248. +* @param Trigger is the new trigger type for the IRQ source. +* Each bit pair describes the configuration for an INT_ID. +* SFI Read Only b10 always +* PPI Read Only depending on how the PPIs are configured. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive +* SPI LSB is read only. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive/ +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 Priority, u8 Trigger) +{ + u32 RegValue; +#if defined (GICv3) + u32 Temp; + u32 Index; +#endif + u8 LocalPriority; + LocalPriority = Priority; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Trigger <= (u8)XSCUGIC_INT_CFG_MASK); + Xil_AssertVoid(LocalPriority <= (u8)XSCUGIC_MAX_INTR_PRIO_VAL); +#if defined (GICv3) + if (Int_Id < XSCUGIC_SPI_INT_ID_START ) + { + XScuGic_ReDistSGIPPIWriteReg(InstancePtr,XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(Int_Id),Priority); + Temp = XScuGic_ReDistSGIPPIReadReg(InstancePtr,XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id)); + Index = XScuGic_Get_Rdist_Int_Trigger_Index(Int_Id); + Temp |= (Trigger << Index); + XScuGic_ReDistSGIPPIWriteReg(InstancePtr,XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id),Temp); + return; + } +#endif + + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * The priority bits are Bits 7 to 3 in GIC Priority Register. This + * means the number of priority levels supported are 32 and they are + * in steps of 8. The priorities can be 0, 8, 16, 32, 48, ... etc. + * The lower order 3 bits are masked before putting it in the register. + */ + LocalPriority = LocalPriority & (u8)XSCUGIC_INTR_PRIO_MASK; + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~((u32)XSCUGIC_PRIORITY_MASK << ((Int_Id%4U)*8U)); + RegValue |= (u32)LocalPriority << ((Int_Id%4U)*8U); + + /* + * Write the value back to the register. + */ + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + RegValue); + + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~((u32)XSCUGIC_INT_CFG_MASK << ((Int_Id%16U)*2U)); + RegValue |= (u32)Trigger << ((Int_Id%16U)*2U); + + /* + * Write the value back to the register. + */ + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), + RegValue); + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +} + +/****************************************************************************/ +/** +* Gets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Int_Id is the IRQ source number to modify +* @param Priority is a pointer to the value of the priority of the IRQ +* source. This is a return value. +* @param Trigger is pointer to the value of the trigger of the IRQ +* source. This is a return value. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 *Priority, u8 *Trigger) +{ + u32 RegValue; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Priority != NULL); + Xil_AssertVoid(Trigger != NULL); + +#if defined (GICv3) + if (Int_Id < XSCUGIC_SPI_INT_ID_START ) + { + *Priority = XScuGic_ReDistSGIPPIReadReg(InstancePtr,XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(Int_Id)); + RegValue = XScuGic_ReDistSGIPPIReadReg(InstancePtr,XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id)); + RegValue = RegValue >> ((Int_Id%16U)*2U); + *Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK); + return; + } +#endif + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%4U)*8U); + *Priority = (u8)(RegValue & XSCUGIC_PRIORITY_MASK); + + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%16U)*2U); + + *Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK); +} +/****************************************************************************/ +/** +* Sets the target CPU for the interrupt of a peripheral +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cpu_Identifier is a CPU number for which the interrupt has to be targeted +* For VERSAL_NET APU: 0 t0 3 bits sepcifies core id and 4 to 7 bits specifies +* cluster id of the targeted core. +* @param Int_Id is the IRQ source number to modify +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Identifier, u32 Int_Id) +{ + u32 RegValue; + +if (Int_Id >= XSCUGIC_SPI_INT_ID_START) { +#if defined (GICv3) + Xil_AssertVoid(InstancePtr != NULL); + + #if defined (VERSAL_NET) + #if defined (ARMR52) + RegValue = (Cpu_Identifier & XSCUGIC_COREID_MASK); + #else + RegValue = ((Cpu_Identifier & XSCUGIC_CLUSTERID_MASK) >> XSCUGIC_CLUSTERID_SHIFT); + RegValue = (RegValue << XSCUGIC_IROUTER_AFFINITY2_SHIFT); + RegValue |= ((Cpu_Identifier & XSCUGIC_COREID_MASK) << XSCUGIC_IROUTER_AFFINITY1_SHIFT); + #endif + #else + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_IROUTER_OFFSET_CALC(Int_Id)); + RegValue |= Cpu_Identifier; + #endif + + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_IROUTER_OFFSET_CALC(Int_Id), + RegValue); +#else + u8 Cpu_CoreId; + u32 Offset; + Xil_AssertVoid(InstancePtr != NULL); + + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + + Offset = (Int_Id & 0x3U); + Cpu_CoreId = (0x1U << Cpu_Identifier); + + RegValue |= (u32)(Cpu_CoreId) << (Offset*8U); + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), + RegValue); + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +#endif +} +} +/****************************************************************************/ +/** +* Unmaps specific SPI interrupt from the target CPU +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cpu_Identifier is a CPU number from which the interrupt has to be +* unmapped +* For VERSAL_NET APU: 0 t0 3 bits sepcifies core id and 4 to 7 +* bits specifies cluster id of the targeted core. +* @param Int_Id is the IRQ source number to modify +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_InterruptUnmapFromCpu(XScuGic *InstancePtr, u8 Cpu_Identifier, u32 Int_Id) +{ + u32 RegValue; +#if defined (VERSAL_NET) + u32 Temp; +#endif + +if (Int_Id >= XSCUGIC_SPI_INT_ID_START) { +#if defined (GICv3) + Xil_AssertVoid(InstancePtr != NULL); + + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_IROUTER_OFFSET_CALC(Int_Id)); + + #if defined (VERSAL_NET) + #if defined (ARMR52) + Temp = (Cpu_Identifier & XSCUGIC_COREID_MASK); + #else + Temp = ((Cpu_Identifier & XSCUGIC_CLUSTERID_MASK) >> XSCUGIC_CLUSTERID_SHIFT); + Temp = (Temp << XSCUGIC_IROUTER_AFFINITY2_SHIFT); + Temp |= ((Cpu_Identifier & XSCUGIC_COREID_MASK) << XSCUGIC_IROUTER_AFFINITY1_SHIFT); + #endif + RegValue &= ~Temp; + #else + RegValue &= ~Cpu_Identifier; + #endif + + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_IROUTER_OFFSET_CALC(Int_Id), + RegValue); +#else + u32 Cpu_CoreId; + u32 Offset; + Xil_AssertVoid(InstancePtr != NULL); + + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + + RegValue = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + + Offset = (Int_Id & 0x3U); + Cpu_CoreId = ((u32)0x1U << Cpu_Identifier); + + RegValue &= ~(Cpu_CoreId << (Offset*8U)); + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), + RegValue); + + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +#endif +} +} +/****************************************************************************/ +/** +* Unmaps all SPI interrupts from the target CPU +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cpu_Identifier is a CPU number from which the interrupts has to be +* unmapped +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_UnmapAllInterruptsFromCpu(XScuGic *InstancePtr, u8 Cpu_Identifier) +{ + u32 Int_Id; + u32 Target_Cpu; + u32 LocalCpuID = ((u32)1U << Cpu_Identifier); + + Xil_AssertVoid(InstancePtr != NULL); + + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + + LocalCpuID |= LocalCpuID << 8U; + LocalCpuID |= LocalCpuID << 16U; + + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + + Target_Cpu = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + /* Remove LocalCpuID from interrupt target register */ + Target_Cpu &= (~LocalCpuID); + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), Target_Cpu); + + } + + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +} +/****************************************************************************/ +/** +* It checks if the interrupt target register contains all interrupts to be +* targeted for current CPU. If they are programmed to be forwarded to current +* cpu, this API disable all interrupts and disable GIC distributor. +* This API also removes current CPU from interrupt target registers for all +* interrupt. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_Stop(XScuGic *InstancePtr) +{ + u32 Int_Id; + u32 RegValue; + u32 Target_Cpu; + #if (defined (USE_AMP) && (USE_AMP==1)) + u32 DistDisable = 0; /* Do not disable distributor */ + #else + u32 DistDisable = 1; /* Track distributor status*/ + #endif + u32 LocalCpuID = ((u32)0x1 << CpuId); + + Xil_AssertVoid(InstancePtr != NULL); + + + /* If distributor is already disabled, no need to do anything */ + RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET); + if ((RegValue & XSCUGIC_EN_INT_MASK) == 0U) { + return; + } + + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); +#if defined (GICv3) + #if defined (VERSAL_NET) + #if defined (ARMR52) + LocalCpuID = XGetCoreId(); + #else + /* VERSAL_NET CortexA78 case */ + LocalCpuID = XGetClusterId(); + LocalCpuID = (LocalCpuID << XSCUGIC_IROUTER_AFFINITY2_SHIFT); + LocalCpuID |= ((u32)XGetCoreId() << XSCUGIC_IROUTER_AFFINITY1_SHIFT); + #endif /*#if defined (ARMR52)*/ + #else + /* Versal CortexA72 case */ + LocalCpuID = CpuId; + #endif /*#if defined (VERSAL_NET)*/ + + /* + * Check if the interrupt are targeted to current cpu only or not. + * Also remove current cpu from interrupt target register for all + * interrupts. + */ + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id++) { + + Target_Cpu = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_IROUTER_OFFSET_CALC(Int_Id)); + if ((Target_Cpu != LocalCpuID)) { + /* + * If any other CPU is also programmed for interrupts + * GIC distributor can not be disabled. + */ + DistDisable = 0; + } + + /* Remove current CPU from interrupt target register */ + Target_Cpu &= (~LocalCpuID); + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_IROUTER_OFFSET_CALC(Int_Id), Target_Cpu); + + } + +#else + LocalCpuID |= LocalCpuID << 8U; + LocalCpuID |= LocalCpuID << 16U; + + /* + * Check if the interrupt are targeted to current cpu only or not. + * Also remove current cpu from interrupt target register for all + * interrupts. + */ + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + + Target_Cpu = XScuGic_DistReadReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + if ((Target_Cpu != LocalCpuID) && (Target_Cpu != (u32)0)) { + /* + * If any other CPU is also programmed to target + * register, GIC distributor can not be disabled. + */ + DistDisable = 0; + } + + /* Remove current CPU from interrupt target register */ + Target_Cpu &= (~LocalCpuID); + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), Target_Cpu); + + } +#endif + /* + * If GIC distributor is safe to be disabled, disable all the interrupt + * and then disable distributor. + */ + if (DistDisable == (u32)1) { + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+32U) { + /* + * Disable all the interrupts + */ + XScuGic_DistWriteReg(InstancePtr, + XSCUGIC_EN_DIS_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET, + Int_Id), + 0xFFFFFFFFU); + } + XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, 0U); + } + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +} + +/****************************************************************************/ +/** +* This updates the CpuId global variable. +* +* @param CpuCoreId is the CPU core number. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_SetCpuID(u32 CpuCoreId) +{ + Xil_AssertVoid(CpuCoreId <= 1U); + + CpuId = CpuCoreId; +} + +/****************************************************************************/ +/** +* This function returns the CpuId variable. +* +* @return The CPU core number. +* +* @note None. +* +*****************************************************************************/ +u32 XScuGic_GetCpuID(void) +{ + return CpuId; +} + +/****************************************************************************/ +/** +* It checks whether the XScGic is initialized or not given the device id. +* +* @param DeviceId the XScuGic device. +* +* @return Returns 1 if initialized otherwise 0. +* +* @note None +* +*****************************************************************************/ +u8 XScuGic_IsInitialized(u32 DeviceId) +{ + u8 Device_Initilaized = 0U; + XScuGic_Config *CfgPtr; + u32 RegVal; + + CfgPtr = XScuGic_LookupConfig(DeviceId); + if (CfgPtr != NULL) { + RegVal = XScuGic_ReadReg(CfgPtr->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET); + if (RegVal & XSCUGIC_EN_INT_MASK) { + Device_Initilaized = 1U; + } + } + + return Device_Initilaized; +} +#if defined (GICv3) +/****************************************************************************/ +/** +* It marks processor core which calls this API as asleep +* +* @return None. +* +* @note It should be called before suspending processor core. Once this +* API is invoked, pending interrupts for processor core asserts +* WakeRequest, to indicate that the PE is to have its power +* restored In case of Versal SoC, WakeRequest will be consumed by +* psv_psm processor and psmfw will wake up APU processor core. +* +*****************************************************************************/ +void XScuGic_MarkCoreAsleep(XScuGic *InstancePtr) +{ + u32 Waker_State; + + Waker_State = XScuGic_ReDistReadReg(InstancePtr,XSCUGIC_RDIST_WAKER_OFFSET); + XScuGic_ReDistWriteReg(InstancePtr,XSCUGIC_RDIST_WAKER_OFFSET, + Waker_State | + XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK); +} + +/****************************************************************************/ +/** +* It marks processor core which calls this API as awake +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_MarkCoreAwake(XScuGic *InstancePtr) +{ + u32 Waker_State; + + Waker_State = XScuGic_ReDistReadReg(InstancePtr, + XSCUGIC_RDIST_WAKER_OFFSET); + XScuGic_ReDistWriteReg(InstancePtr,XSCUGIC_RDIST_WAKER_OFFSET, + Waker_State & + (~ XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK)); +} +#endif +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic.h b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic.h new file mode 100644 index 0000000..0ee7342 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic.h @@ -0,0 +1,689 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscugic.h +* @addtogroup scugic Overview +* @{ +* @details +* +* The generic interrupt controller driver component. +* +* The interrupt controller driver uses the idea of priority for the various +* handlers. Priority is an integer within the range of 1 and 31 inclusive with +* default of 1 being the highest priority interrupt source. The priorities +* of the various sources can be dynamically altered as needed through +* hardware configuration. +* +* The generic interrupt controller supports the following +* features: +* +* - specific individual interrupt enabling/disabling +* - specific individual interrupt acknowledging +* - attaching specific callback function to handle interrupt source +* - assigning desired priority to interrupt source if default is not +* acceptable. +* +* Details about connecting the interrupt handler of the driver are contained +* in the source file specific to interrupt processing, xscugic_intr.c. +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads +* or thread mutual exclusion, virtual memory, or cache control must be +* satisfied by the layer above this driver. +* +* Interrupt Vector Tables +* +* The device ID of the interrupt controller device is used by the driver as a +* direct index into the configuration data table. The user should populate the +* vector table with handlers and callbacks at run-time using the +* XScuGic_Connect() and XScuGic_Disconnect() functions. +* +* Each vector table entry corresponds to a device that can generate an +* interrupt. Each entry contains an interrupt handler function and an +* argument to be passed to the handler when an interrupt occurs. The +* user must use XScuGic_Connect() when the interrupt handler takes an +* argument other than the base address. +* +* Nested Interrupts Processing +* +* Nested interrupts are not supported by this driver. +* +* NOTE: +* The generic interrupt controller is not a part of the snoop control unit +* as indicated by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a drg  01/19/00 First release
+* 1.01a sdm  11/09/11 The XScuGic and XScuGic_Config structures have changed.
+*		      The HandlerTable (of type XScuGic_VectorTableEntry) is
+*		      moved to XScuGic_Config structure from XScuGic structure.
+*
+*		      The "Config" entry in XScuGic structure is made as
+*		      pointer for better efficiency.
+*
+*		      A new file named as xscugic_hw.c is now added. It is
+*		      to implement low level driver routines without using
+*		      any xscugic instance pointer. They are useful when the
+*		      user wants to use xscugic through device id or
+*		      base address. The driver routines provided are explained
+*		      below.
+*		      XScuGic_DeviceInitialize that takes device id as
+*		      argument and initializes the device (without calling
+*		      XScuGic_CfgInitialize).
+*		      XScuGic_DeviceInterruptHandler that takes device id
+*		      as argument and calls appropriate handlers from the
+*		      HandlerTable.
+*		      XScuGic_RegisterHandler that registers a new handler
+*		      by taking xscugic hardware base address as argument.
+*		      LookupConfigByBaseAddress is used to return the
+*		      corresponding config structure from XScuGic_ConfigTable
+*		      based on the scugic base address passed.
+* 1.02a sdm  12/20/11 Removed AckBeforeService from the XScuGic_Config
+*		      structure.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *.c and *_hw.c to
+*		      *_hw.h
+*		      Added APIs
+*			- XScuGic_SetPriTrigTypeByDistAddr()
+*			- XScuGic_GetPriTrigTypeByDistAddr()
+*		      (CR 702687)
+*			Added support to direct interrupts to the appropriate CPU. Earlier
+*			  interrupts were directed to CPU1 (hard coded). Now depending
+*			  upon the CPU selected by the user (xparameters.h), interrupts
+*			  will be directed to the relevant CPU. This fixes CR 699688.
+* 1.04a hk   05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
+*			  XScuGic_CfgInitialize. Fix for CR#704400 to remove warnings.
+*			  Moved functions XScuGic_SetPriTrigTypeByDistAddr and
+*             XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
+*			  This is fix for CR#705621.
+* 1.05a hk   06/26/13 Modified tcl to export external interrupts correctly to
+*                     xparameters.h. Fix for CR's 690505, 708928 & 719359.
+* 2.0   adk  12/10/13 Updated as per the New Tcl API's
+* 2.1   adk  25/04/14 Fixed the CR:789373 changes are made in the driver tcl file.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.2   asa  02/29/16 Modified DistributorInit function for Zynq AMP case. The
+*			  distributor is left uninitialized for Zynq AMP. It is assumed
+*             that the distributor will be initialized by Linux master. However
+*             for CortexR5 case, the earlier code is left unchanged where the
+*             the interrupt processor target registers in the distributor is
+*             initialized with the corresponding CPU ID on which the application
+*             built over the scugic driver runs.
+*             These changes fix CR#937243.
+*
+* 3.4   asa  04/07/16 Created a new static function DoDistributorInit to simplify
+*            the flow and avoid code duplication. Changes are made for
+*            USE_AMP use case for R5. In a scenario (in R5 split mode) when
+*            one R5 is operating with A53 in open amp config and other
+*            R5 running baremetal app, the existing code
+*            had the potential to stop the whole AMP solution to work (if
+*            for some reason the R5 running the baremetal app tasked to
+*            initialize the Distributor hangs or crashes before initializing).
+*            Changes are made so that the R5 under AMP first checks if
+*            the distributor is enabled or not and if not, it does the
+*            standard Distributor initialization.
+*            This fixes the CR#952962.
+* 3.6   ms   01/23/17 Modified xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 3.7   ms   04/11/17 Modified tcl file to add suffix U for all macro
+*                     definitions of scugic in xparameters.h
+* 3.8   mus  07/05/17 Updated scugic.tcl to add support for interrupts connected
+*                     through util_reduced_vector IP(OR gate)
+*       mus  07/05/17 Updated xdefine_zynq_canonical_xpars proc to initialize
+*                     the HandlerTable in XScuGic_ConfigTable to 0, it removes
+*                     the compilation warning in xscugic_g.c. Fix for CR#978736.
+*       mus  07/25/17 Updated xdefine_gic_params proc to export correct canonical
+*                     definitions for pl to ps interrupts.Fix for CR#980534
+* 3.9   mus  02/21/18 Added new API's XScuGic_UnmapAllInterruptsFromCpu and
+*                     XScuGic_InterruptUnmapFromCpu, These API's can be used
+*                     by applications to unmap specific/all interrupts from
+*                     target CPU.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+* 4.0   mus  11/22/18 Fixed bugs in software interrupt generation through
+*                      XScuGic_SoftwareIntr API
+* 4.1   asa  03/30/19 Made changes not to direct each interrupt to all
+*                     available CPUs by default. This was breaking AMP
+*                     behavior. Instead every time an interrupt enable
+*                     request is received, the interrupt was mapped to
+*                     the respective CPU. There were several other changes
+*                     made to implement this. This set of changes was to
+*                     fix CR-1024716.
+* 4.1   mus  06/19/19 Added API's XScuGic_MarkCoreAsleep and
+*                     XScuGic_MarkCoreAwake to mark processor core as
+*                     asleep or awake. Fix for CR#1027220.
+* 4.5   asa  03/07/21 Included a header file xil_spinlock.h to ensure that
+*                     GIC driver can use newly introduced spinlock
+*                     functionality.
+* 4.6	sk   08/05/21 Fix scugic misrac violations.
+* 4.7   dp   11/22/21 Added new API XScuGic_IsInitialized() to check and return
+*                     the GIC initialization status.
+* 5.0   mus  22/02/22 Add support for VERSAL NET
+* 	adk  04/18/22 Replace infinite while loops in the examples with
+* 		      Xil_WaitForEventSet() API.
+*       dp   04/25/22 Correct Trigger index calculation in macro
+*                     XScuGic_Get_Rdist_Int_Trigger_Index
+* 5.0   dp   11/07/22 Add macros for accessing the GIC Binary Point and
+*                     Running Priority registers of Cortex-R52.
+* 5.1   mus  02/13/23 Updated XScuGic_CfgInitialize, XScuGic_Enable and
+*                     XScuGic_Disable to support interrupts on each core
+*                     of all CortexA78/CortexR52 clusters in VERSAL NET SoC.
+*                     While at it, modified interrupt routing logic to make
+*                     use of CPU affinity register instead of XPAR_CPU_ID macro.
+*                     Also, XScuGic_CfgInitialize has been updated to find
+*                     redistributor base address of core on which API is
+*                     executed, redistributor address will be stored in newly
+*                     added member of XScuGic data structure "RedistBaseAddr".
+*                     It fixes CR#1150432.
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_H /* prevent circular inclusions */ +#define XSCUGIC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xil_io.h" +#include "xscugic_hw.h" +#include "xil_exception.h" +#include "xil_spinlock.h" + +/************************** Constant Definitions *****************************/ + +#define EFUSE_STATUS_OFFSET 0x10 +#define EFUSE_STATUS_CPU_MASK 0x80 + +#if !defined (ARMR5) && !defined (__aarch64__) && !defined (ARMA53_32) +#define ARMA9 +#endif + +#define XSCUGIC500_DCTLR_ARE_NS_ENABLE 0x20 +#define XSCUGIC500_DCTLR_ARE_S_ENABLE 0x10 + +#if defined (VERSAL_NET) +#define XSCUGIC_CLUSTERID_MASK 0xF0U +#define XSCUGIC_COREID_MASK 0xFU +#define XSCUGIC_CLUSTERID_SHIFT 4U +#define XSCUGIC_COREID_SHIFT 0U + +#define XSCUGIC_SGI1R_AFFINITY1_SHIFT 16U +#define XSCUGIC_SGI1R_AFFINITY2_SHIFT 32U + +#define XSCUGIC_IROUTER_AFFINITY1_SHIFT 8U +#define XSCUGIC_IROUTER_AFFINITY2_SHIFT 16U + +#define XSCUGIC_IROUTER_IRM_MASK 0x80000000U +#endif + +/**************************** Type Definitions *******************************/ + +/* The following data type defines each entry in an interrupt vector table. + * The callback reference is the base address of the interrupting device + * for the low level driver and an instance pointer for the high level driver. + */ +typedef struct +{ + Xil_InterruptHandler Handler; + void *CallBackRef; +} XScuGic_VectorTableEntry; + +/** + * This typedef contains configuration information for the device. + */ +typedef struct +{ + u16 DeviceId; /**< Unique ID of device */ + u32 CpuBaseAddress; /**< CPU Interface Register base address */ + u32 DistBaseAddress; /**< Distributor Register base address */ + XScuGic_VectorTableEntry HandlerTable[XSCUGIC_MAX_NUM_INTR_INPUTS];/**< + Vector table of interrupt handlers */ +} XScuGic_Config; + +/** + * The XScuGic driver instance data. The user is required to allocate a + * variable of this type for every intc device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct +{ + XScuGic_Config *Config; /**< Configuration table entry */ +#if defined (GICv3) + UINTPTR RedistBaseAddr; +#endif + u32 IsReady; /**< Device is initialized and ready */ + u32 UnhandledInterrupts; /**< Intc Statistics */ +} XScuGic; + +/************************** Variable Definitions *****************************/ + +extern XScuGic_Config XScuGic_ConfigTable[]; /**< Config table */ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_CPUWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_CPUWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given CPU Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_CPUReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_CPUReadReg(InstancePtr, RegOffset) \ + (XScuGic_ReadReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_DistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset), \ + ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given Distributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_DistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset))) + +#if defined (GICv3) +/****************************************************************************/ +/** +* +* Write the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(InstancePtr->RedistBaseAddr, RegOffset, (u32)Data)) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg(InstancePtr->RedistBaseAddr, RegOffset)) + +/****************************************************************************/ +/** +* +* Write the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIWriteReg(InstancePtr, RegOffset, Data) \ +(XScuGic_WriteReg(InstancePtr->RedistBaseAddr + \ + XSCUGIC_RDIST_SGI_PPI_OFFSET, (RegOffset), ((u32)(Data)))) + +/****************************************************************************/ +/** +* +* Read the given ReDistributor SGI PPI Interface register +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReDistSGIPPIReadReg(InstancePtr, RegOffset) \ +(XScuGic_ReadReg(InstancePtr->RedistBaseAddr + XSCUGIC_RDIST_SGI_PPI_OFFSET, \ + RegOffset)) + +#if defined(ARMR52) +#define XREG_ICC_SRE_EL1 "p15, 0, %0, c12, c12, 5" +#define XREG_ICC_IGRPEN0_EL1 "p15, 0, %0, c12, c12, 6" +#define XREG_ICC_IGRPEN1_EL1 "p15, 0, %0, c12, c12, 7" +#define XREG_ICC_SGI0R_EL1 "p15, 2, %0, %1, c12" +#define XREG_ICC_SGI1R_EL1 "p15, 0, %0, %1, c12" +#define XREG_ICC_PMR_EL1 "p15, 0, %0, c4, c6, 0" +#define XREG_ICC_IAR0_EL1 "p15, 0, %0, c12, c8, 0" +#define XREG_ICC_EOIR0_EL1 "p15, 0, %0, c12, c8, 1" +#define XREG_IMP_CBAR "p15, 1, %0, c15, c3, 0" +#define XREG_ICC_BPR0_EL1 "p15, 0, %0, c12, c8, 3" +#define XREG_ICC_RPR_EL1 "p15, 0, %0, c12, c11, 3" +#else +#define XREG_ICC_SRE_EL1 "S3_0_C12_C12_5" +#define XREG_ICC_SRE_EL3 "S3_6_C12_C12_5" +#define XREG_ICC_IGRPEN0_EL1 "S3_0_C12_C12_6" +#define XREG_ICC_IGRPEN1_EL1 "S3_0_C12_C12_7" +#define XREG_ICC_IGRPEN1_EL3 "S3_6_C12_C12_7" +#define XREG_ICC_SGI0R_EL1 "S3_0_C12_C11_7" +#define XREG_ICC_SGI1R_EL1 "S3_0_C12_C11_5" +#define XREG_ICC_PMR_EL1 "S3_0_C4_C6_0" +#define XREG_ICC_IAR0_EL1 "S3_0_C12_C8_0" +#define XREG_ICC_IAR1_EL1 "S3_0_C12_C12_0" +#define XREG_ICC_EOIR0_EL1 "S3_0_C12_C8_1" +#define XREG_ICC_EOIR1_EL1 "S3_0_C12_C12_1" +#endif +/****************************************************************************/ +/** +* This function enables system register interface for GIC CPU Interface +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (__aarch64__) +#define XScuGic_Enable_SystemReg_CPU_Interface_EL3() mtcpnotoken(XREG_ICC_SRE_EL3, 0xF); +#define XScuGic_Enable_SystemReg_CPU_Interface_EL1() mtcpnotoken(XREG_ICC_SRE_EL1, 0xF); +#elif defined (ARMR52) +#define XScuGic_Enable_SystemReg_CPU_Interface_EL1() mtcp(XREG_ICC_SRE_EL1, 0xF); +#endif +/****************************************************************************/ +/** +* This function enables Grou0 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined(ARMR52) +#define XScuGic_Enable_Group0_Interrupts() mtcp(XREG_ICC_IGRPEN0_EL1,0x1); +#else +#define XScuGic_Enable_Group0_Interrupts() mtcpnotoken(XREG_ICC_IGRPEN0_EL1,0x1); +#endif +/****************************************************************************/ +/** +* This function enables Group1 interrupts +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (ARMR52) + +#define XScuGic_Enable_Group1_Interrupts() \ + mtcp (XREG_ICC_IGRPEN1_EL1, 0x1 | mfcp(XREG_ICC_IGRPEN1_EL1) ); +#elif EL1_NONSECURE +#define XScuGic_Enable_Group1_Interrupts() \ + mtcpnotoken(XREG_ICC_IGRPEN1_EL1, 0x1 | mfcpnotoken(XREG_ICC_IGRPEN1_EL1) ); +#else +#define XScuGic_Enable_Group1_Interrupts() \ + mtcpnotoken(XREG_ICC_IGRPEN1_EL3, 0x1 | mfcpnotoken(XREG_ICC_IGRPEN1_EL3) ); +#endif +/****************************************************************************/ +/** +* This function writes to ICC_SGI0R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined(ARMR52) +#define XScuGic_WriteICC_SGI0R_EL1(val) mtcp2(XREG_ICC_SGI0R_EL1,val) +#else +#define XScuGic_WriteICC_SGI0R_EL1(val) mtcpnotoken(XREG_ICC_SGI0R_EL1,val) +#endif + +/****************************************************************************/ +/** +* This function writes to ICC_SGI1R_EL1 +* +* @param value to be written +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined(ARMR52) +#define XScuGic_WriteICC_SGI1R_EL1(val) mtcp2(XREG_ICC_SGI1R_EL1,val) +#else +#define XScuGic_WriteICC_SGI1R_EL1(val) mtcpnotoken(XREG_ICC_SGI1R_EL1,val) +#endif + +/****************************************************************************/ +/** +* This function reads ICC_SGI1R_EL1 register +* +* @param None +* +* @return Value of ICC_SGI1R_EL1 register +* +* @note None. +* +*****************************************************************************/ +#if defined (ARMR52) +#define XScuGic_ReadICC_SGI1R_EL1() mfcp(XREG_ICC_SGI1R_EL1) +#else +#define XScuGic_ReadICC_SGI1R_EL1() mfcpnotoken(XREG_ICC_SGI1R_EL1) +#endif +/****************************************************************************/ +/** +* This function sets interrupt priority filter +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined (ARMR52) +#define XScuGic_set_priority_filter(val) mtcp(XREG_ICC_PMR_EL1, val) +#else +#define XScuGic_set_priority_filter(val) mtcpnotoken(XREG_ICC_PMR_EL1, val) +#endif +/****************************************************************************/ +/** +* This function returns interrupt id of highest priority pending interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined(ARMR52) +#define XScuGic_get_IntID() mfcp(XREG_ICC_IAR0_EL1) +#elif EL3 +#define XScuGic_get_IntID() mfcpnotoken(XREG_ICC_IAR0_EL1) +#else +#define XScuGic_get_IntID() mfcpnotoken(XREG_ICC_IAR1_EL1) +#endif +/****************************************************************************/ +/** +* This function acks the interrupt +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#if defined(ARMR52) +#define XScuGic_ack_Int(val) mtcp(XREG_ICC_EOIR0_EL1,val) +#elif EL3 +#define XScuGic_ack_Int(val) mtcpnotoken(XREG_ICC_EOIR0_EL1,val) +#else +#define XScuGic_ack_Int(val) mtcpnotoken(XREG_ICC_EOIR1_EL1,val) +#endif +/****************************************************************************/ +/** +* This macro returns bit position for the specific interrupt's trigger type +* configuration within GICR_ICFGR0/GICR_ICFGR1 register +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define XScuGic_Get_Rdist_Int_Trigger_Index(IntrId) ((Int_Id%16) * 2U) +#endif +/************************** Function Prototypes ******************************/ + +/* + * Required functions in xscugic.c + */ + +s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id, + Xil_InterruptHandler Handler, void *CallBackRef); +void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id); + +void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id); +void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id); + +s32 XScuGic_CfgInitialize(XScuGic *InstancePtr, XScuGic_Config *ConfigPtr, + u32 EffectiveAddr); + +s32 XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Identifier); + +void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Identifier, u32 Int_Id); +void XScuGic_InterruptUnmapFromCpu(XScuGic *InstancePtr, u8 Cpu_Identifier, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpu(XScuGic *InstancePtr, u8 Cpu_Identifier); +void XScuGic_Stop(XScuGic *InstancePtr); +void XScuGic_SetCpuID(u32 CpuCoreId); +u32 XScuGic_GetCpuID(void); +u8 XScuGic_IsInitialized(u32 DeviceId); +/* + * Initialization functions in xscugic_sinit.c + */ +XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId); +XScuGic_Config *XScuGic_LookupConfigBaseAddr(UINTPTR BaseAddress); + +/* + * Interrupt functions in xscugic_intr.c + */ +void XScuGic_InterruptHandler(XScuGic *InstancePtr); + +/* + * Self-test functions in xscugic_selftest.c + */ +s32 XScuGic_SelfTest(XScuGic *InstancePtr); + +#if defined (GICv3) +void XScuGic_MarkCoreAsleep(XScuGic *InstancePtr); +void XScuGic_MarkCoreAwake(XScuGic *InstancePtr); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_g.c new file mode 100644 index 0000000..7b5f3ae --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_g.c @@ -0,0 +1,73 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscugic_g.c +* @addtogroup scugic Overview +* @{ +* +* This file contains a configuration table that specifies the configuration of +* interrupt controller devices in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+*
+* 
+* +* @internal +* +* This configuration table contains entries that are modified at runtime by the +* driver. This table reflects only the hardware configuration of the device. +* This Intc configuration table contains software information in addition to +* hardware configuration. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscugic.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Prototypes ******************************/ + +/** + * This table contains configuration information for each GIC device + * in the system. The XScuGic driver must know when to acknowledge the + * interrupt. The entry which specifies this as a bit mask where each bit + * corresponds to a specific interrupt. A bit set indicates to ACK it + * before servicing it. Generally, acknowledge before service is used when + * the interrupt signal is edge-sensitive, and after when the signal is + * level-sensitive. + * + * Refer to the XScuGic_Config data structure in xscugic.h for details on how + * this table should be initialized. + */ +XScuGic_Config XScuGic_ConfigTable[XPAR_XSCUGIC_NUM_INSTANCES] = { + { + (u16)XPAR_SCUGIC_0_DEVICE_ID, /* Unique ID of device */ + (u32)XPAR_SCUGIC_0_CPU_BASEADDR, /* CPU Interface base address */ + (u32)XPAR_SCUGIC_0_DIST_BASEADDR, /* Distributor base address */ + {{0}} /**< Initialize the HandlerTable to 0 */ + } +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_hw.c b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_hw.c new file mode 100644 index 0000000..88c38c7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_hw.c @@ -0,0 +1,1079 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscugic_hw.c +* @addtogroup scugic Overview +* @{ +* +* This file contains low-level driver functions that can be used to access the +* device. The user should refer to the hardware device specification for more +* details of the device operation. +* These routines are used when the user does not want to create an instance of +* XScuGic structure but still wants to use the ScuGic device. Hence the +* routines provided here take device id or scugic base address as arguments. +* Separate static versions of DistInit and CPUInit are provided to implement +* the low level driver routines. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.01a sdm  07/18/11 First release
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *_hw.c (CR
+*                     702687).
+*                     Added support to direct interrupts to the appropriate
+*                     CPU. Earlier interrupts were directed to CPU1
+*                     (hard coded). Now depending upon the CPU selected by
+*                     the user (xparameters.h), interrupts will be directed
+*                     to the relevant CPU.This fixes CR 699688.
+* 1.04a hk   05/04/13 Fix for CR#705621. Moved functions
+*                     XScuGic_SetPriTrigTypeByDistAddr and
+*                     XScuGic_GetPriTrigTypeByDistAddr here from xscugic.c
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.6   kvn  02/17/17 Add support for changing GIC CPU master at run time.
+*       kvn  02/28/17 Make the CpuId as static variable and Added new
+*                     XScugiC_GetCpuId to access CpuId.
+* 3.9   mus  02/21/18 Added new API's
+*                     XScuGic_InterruptUnmapFromCpuByDistAddr and
+*                     XScuGic_UnmapAllInterruptsFromCpuByDistAddr, These
+*                     API's can be used by applications to unmap
+*                     specific/all interrupts from target CPU. It fixes
+*                     CR#992490.
+* 3.10  mus  07/17/18 Updated XScuGic_DeviceInterruptHandler to fix array
+*                     overrun reported by coverity tool. It fixes
+*                     CR#1006344.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+*                     It fixes CR#1007753
+* 3.10  mus  09/19/18 Update documentation for XScuGic_RegisterHandler to
+*                     fix doxygen warnings.
+* 4.1   asa  03/30/19 Made changes not to direct each interrupt to all
+*                     available CPUs by default. This was breaking AMP
+*                     behavior. Instead every time an interrupt enable
+*                     request is received, the interrupt was mapped to
+*                     the respective CPU. There were several other changes
+*                     made to implement this including adding APIs:
+*                     XScuGic_InterruptMapFromCpuByDistAddr,
+*                     XScuGic_EnableIntr, and XScuGic_DisableIntr.
+*                     This set of changes was to fix CR-1024716.
+* 4.1   mus  06/12/19 Updated existing low level API's to support GIC500. It
+*                     fixes CR#1033401.
+* 4.3   mus  05/11/20 Added assert checks in XScuGic_EnableIntr and
+*                     XScuGic_DisableIntr API. It fixes CR#1063034.
+* 4.5   asa  03/07/21 Added spinlock protection for critical sections in the
+*                     code. The sections are critical when applications
+*                     running on separate CPUs (R5s or A9s) try to update
+*                     the same register. The spinlock mechanism used here
+*                     used exclusive load and store instructions. To ensure
+*                     that legacy behavior is not broken, unless someone
+*                     enables spinlocks explicitely in their applications
+*                     the existing flow will remain unchanged. On how to
+*                     enable spinlocks, please refer to the documentations
+*                     at: lib/bsp/standalone/src/arm/common/gcc/xil_spinlock.c
+* 4.6	sk   08/05/21 Fix Scugic Misrac violations.
+* 4.7	sk   09/14/21 Fix gcc compiler warnings for A72 processor.
+* 4.7	sk   10/13/21 Update APIs to perform interrupt mapping/unmapping only
+* 		      when (Int_Id >= XSCUGIC_SPI_INT_ID_START).
+* 5.0   dp   04/25/22 Update XScuGic_GetPriTrigTypeByDistAddr() to read and
+*                     update priority and triggerproperly for GICv3.
+* 5.1   mus  02/09/23 Updated DistInit function to skip enablement
+*                     of group0 interrupts when processor is running at
+*                     EL1 NS. This is required to avoid abort, since access
+*                     to ICC_IGRPEN0_EL1 is resulting into sync abort.
+*                     It fixes CR#1152445.
+* 5.1   mus  02/15/23 Added support for VERSAL_NET APU and RPU GIC.
+* 5.1   mus  03/07/23 Fix XScuGic_InterruptMapFromCpuByDistAddr and
+*                     XScuGic_InterruptUnmapFromCpuByDistAddr for GICv3.
+*
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" +#include "xparameters.h" +#if defined (VERSAL_NET) +#include "xplatform_info.h" +#endif +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static void DistInit(const XScuGic_Config *Config); +#if !defined (GICv3) +static void CPUInit(const XScuGic_Config *Config); +#endif +static XScuGic_Config *LookupConfigByBaseAddress(u32 CpuBaseAddress); + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* DistInit initializes the distributor of the GIC. The +* initialization entails: +* +* - Write the trigger mode, priority and target CPU +* - All interrupt sources are disabled +* - Enable the distributor +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param CpuID is the Cpu ID to be initialized. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void DistInit(const XScuGic_Config *Config) +{ + u32 Int_Id; + +#if (defined (USE_AMP) && (USE_AMP==1)) + #warning "Building GIC for AMP" + + /* + * The distributor should not be initialized by FreeRTOS in the case of + * AMP -- it is assumed that Linux is the master of this device in that + * case. + */ + return; +#endif + +#if defined (GICv3) + u32 Temp; + u32 Waker_State; + UINTPTR RedistBaseAddr; + + RedistBaseAddr = XScuGic_GetRedistBaseAddr(); + #if defined (GIC600) + XScuGic_WriteReg(RedistBaseAddr,XSCUGIC_RDIST_PWRR_OFFSET, + (XScuGic_ReadReg(RedistBaseAddr, XSCUGIC_RDIST_PWRR_OFFSET) & + (~XSCUGIC_RDIST_PWRR_RDPD_MASK))); + #endif + Waker_State = XScuGic_ReadReg(RedistBaseAddr,XSCUGIC_RDIST_WAKER_OFFSET); + XScuGic_WriteReg(RedistBaseAddr,XSCUGIC_RDIST_WAKER_OFFSET, + Waker_State & (~ XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK)); + /* Enable system reg interface through ICC_SRE_EL1 */ +#if EL3 + XScuGic_Enable_SystemReg_CPU_Interface_EL3(); +#endif + XScuGic_Enable_SystemReg_CPU_Interface_EL1(); + isb(); + + Temp = XScuGic_ReadReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET); + Temp |= (XSCUGIC500_DCTLR_ARE_NS_ENABLE | XSCUGIC500_DCTLR_ARE_S_ENABLE); + Temp &= ~(XSCUGIC_EN_INT_MASK); + XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, Temp); +#else + XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, 0U); +#endif + + /* + * Set the security domains in the int_security registers for non-secure + * interrupts. All are secure, so leave at the default. Set to 1 for + * non-secure interrupts. + */ + + + /* + * For the Shared Peripheral Interrupts INT_ID[MAX..32], set: + */ + + /* + * 1. The trigger mode in the int_config register + * Only write to the SPI interrupts, so start at 32 + */ + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+16U) { + /* + * Each INT_ID uses two bits, or 16 INT_ID per register + * Set them all to be level sensitive, active HIGH. + */ + XScuGic_WriteReg(Config->DistBaseAddress, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), 0U); + } + + +#define DEFAULT_PRIORITY 0xa0a0a0a0U + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + /* + * 2. The priority using int the priority_level register + * The priority_level and spi_target registers use one byte per + * INT_ID. + * Write a default value that can be changed elsewhere. + */ + XScuGic_WriteReg(Config->DistBaseAddress, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + DEFAULT_PRIORITY); + } + +#if defined (GICv3) + for (Int_Id = 0U; Int_IdDistBaseAddress, + XSCUGIC_SECURITY_TARGET_OFFSET_CALC(Int_Id), + XSCUGIC_DEFAULT_SECURITY); + } + /* + * Set security for SGI/PPI + * + */ + XScuGic_WriteReg( RedistBaseAddr + XSCUGIC_RDIST_SGI_PPI_OFFSET, + XSCUGIC_RDIST_IGROUPR_OFFSET, XSCUGIC_DEFAULT_SECURITY); +#endif + + for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+32U) { + /* + * 4. Enable the SPI using the enable_set register. + * Leave all disabled for now. + */ + XScuGic_WriteReg(Config->DistBaseAddress, + XSCUGIC_EN_DIS_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET, + Int_Id), + 0xFFFFFFFFU); + + } + +#if defined (GICv3) + Temp = XScuGic_ReadReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET); + Temp |= XSCUGIC_EN_INT_MASK; + XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, Temp); + XScuGic_Enable_Group1_Interrupts(); + #if defined (ARMR52) || (defined (__aarch64__) && (EL1_NONSECURE == 0)) + XScuGic_Enable_Group0_Interrupts(); + #endif + XScuGic_set_priority_filter(0xff); +#else + + XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, + XSCUGIC_EN_INT_MASK); +#endif + +} + +#if !defined (GICv3) +/*****************************************************************************/ +/** +* +* CPUInit initializes the CPU Interface of the GIC. The initialization entails: +* +* - Set the priority of the CPU. +* - Enable the CPU interface +* +* @param ConfigPtr is a pointer to a config table for the particular +* device this driver is associated with. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void CPUInit(const XScuGic_Config *Config) +{ + /* + * Program the priority mask of the CPU using the Priority mask + * register + */ + XScuGic_WriteReg(Config->CpuBaseAddress, XSCUGIC_CPU_PRIOR_OFFSET, + 0xF0U); + + /* + * If the CPU operates in both security domains, set parameters in the + * control_s register. + * 1. Set FIQen=1 to use FIQ for secure interrupts, + * 2. Program the AckCtl bit + * 3. Program the SBPR bit to select the binary pointer behavior + * 4. Set EnableS = 1 to enable secure interrupts + * 5. Set EnbleNS = 1 to enable non secure interrupts + */ + + /* + * If the CPU operates only in the secure domain, setup the + * control_s register. + * 1. Set FIQen=1, + * 2. Set EnableS=1, to enable the CPU interface to signal secure . + * interrupts Only enable the IRQ output unless secure interrupts + * are needed. + */ + XScuGic_WriteReg(Config->CpuBaseAddress, XSCUGIC_CONTROL_OFFSET, 0x07U); + +} +#endif + +/*****************************************************************************/ +/** +* +* Initialize the GIC based on the device id. The +* initialization entails: +* +* - Initialize distributor interface +* - Initialize cpu interface +* +* @param DeviceId is device id to be worked on. +* +* @return +* +* - XST_SUCCESS if initialization was successful +* +* @note +* +* None. +* +******************************************************************************/ +s32 XScuGic_DeviceInitialize(u32 DeviceId) +{ + XScuGic_Config *Config; + + Config = &XScuGic_ConfigTable[(u32)DeviceId]; + DistInit(Config); +#if !defined (GICv3) + CPUInit(Config); +#endif + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function is the primary interrupt handler for the driver. It must be +* connected to the interrupt source such that it is called when an interrupt of +* the interrupt controller is active. It will resolve which interrupts are +* active and enabled and call the appropriate interrupt handler. It uses +* the Interrupt Type information to determine when to acknowledge the +* interrupt.Highest priority interrupts are serviced first. +* +* This function assumes that an interrupt vector table has been previously +* initialized. It does not verify that entries in the table are valid before +* calling an interrupt handler. +* +* @param DeviceId is the unique identifier for the ScuGic device. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuGic_DeviceInterruptHandler(void *DeviceId) +{ + + u32 InterruptID; +#if !defined (GICv3) + u32 IntIDFull; +#endif + XScuGic_VectorTableEntry *TablePtr; + XScuGic_Config *CfgPtr; + + CfgPtr = &XScuGic_ConfigTable[(INTPTR)DeviceId]; + +#if defined (GICv3) + InterruptID = XScuGic_get_IntID(); +#else + /* + * Read the int_ack register to identify the highest priority + * interrupt ID and make sure it is valid. Reading Int_Ack will + * clear the interrupt in the GIC. + */ + IntIDFull = XScuGic_ReadReg(CfgPtr->CpuBaseAddress, + XSCUGIC_INT_ACK_OFFSET); + InterruptID = IntIDFull & XSCUGIC_ACK_INTID_MASK; + +#endif + if (XSCUGIC_MAX_NUM_INTR_INPUTS <= InterruptID) { + goto IntrExit; + } + + /* + * If the interrupt is shared, do some locking here if there are + * multiple processors. + */ + /* + * If preemption is required: + * Re-enable preemption by setting the CPSR I bit for non-secure , + * interrupts or the F bit for secure interrupts + */ + + /* + * If we need to change security domains, issue a SMC instruction here. + */ + + /* + * Execute the ISR. Jump into the Interrupt service routine based on + * the IRQSource. A software trigger is cleared by the ACK. + */ + TablePtr = &(CfgPtr->HandlerTable[InterruptID]); + if (TablePtr != NULL) { + TablePtr->Handler(TablePtr->CallBackRef); + } + +IntrExit: + /* + * Write to the EOI register, we are all done here. + * Let this function return, the boot code will restore the stack. + */ +#if defined (GICv3) + XScuGic_ack_Int(InterruptID); +#else + XScuGic_WriteReg(CfgPtr->CpuBaseAddress, XSCUGIC_EOI_OFFSET, IntIDFull); +#endif + + /* + * Return from the interrupt. Change security domains could happen + * here. + */ +} + +/*****************************************************************************/ +/** +* +* Register a handler function for a specific interrupt ID. The vector table +* of the interrupt controller is updated, overwriting any previous handler. +* The handler function will be called when an interrupt occurs for the given +* interrupt ID. +* +* @param BaseAddress is the CPU Interface Register base address of the +* interrupt controller whose vector table will be modified. +* @param InterruptID is the interrupt ID to be associated with the input +* handler. +* @param IntrHandler is the function pointer that will be added to +* the vector table for the given interrupt ID. +* @param CallBackRef is the argument that will be passed to the new +* handler function when it is called. This is user-specific. +* +* @return None. +* +* @note +* +* Note that this function has no effect if the input base address is invalid. +* +******************************************************************************/ +void XScuGic_RegisterHandler(u32 BaseAddress, s32 InterruptID, + Xil_InterruptHandler IntrHandler, void *CallBackRef) +{ + XScuGic_Config *CfgPtr; + CfgPtr = LookupConfigByBaseAddress(BaseAddress); + + if (CfgPtr != NULL) { + if (IntrHandler != NULL) { + CfgPtr->HandlerTable[InterruptID].Handler = + (Xil_InterruptHandler)IntrHandler; + } + if (CallBackRef != NULL) { + CfgPtr->HandlerTable[InterruptID].CallBackRef = + CallBackRef; + } + } +} + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the CPU interface base address of +* the device. A table contains the configuration info for each device in the +* system. +* +* @param CpuBaseAddress is the CPU Interface Register base address. +* +* @return A pointer to the configuration structure for the specified +* device, or NULL if the device was not found. +* +* @note None. +* +******************************************************************************/ +static XScuGic_Config *LookupConfigByBaseAddress(u32 CpuBaseAddress) +{ + XScuGic_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_SCUGIC_NUM_INSTANCES; Index++) { + if (XScuGic_ConfigTable[Index].CpuBaseAddress == + CpuBaseAddress) { + CfgPtr = &XScuGic_ConfigTable[Index]; + break; + } + } + + return (XScuGic_Config *)CfgPtr; +} + +/****************************************************************************/ +/** +* Sets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param DistBaseAddress is the distributor base address +* @param Int_Id is the IRQ source number to modify +* @param Priority is the new priority for the IRQ source. 0 is highest +* priority, 0xF8(248) is lowest. There are 32 priority +* levels supported with a step of 8. Hence the supported +* priorities are 0, 8, 16, 32, 40 ..., 248. +* @param Trigger is the new trigger type for the IRQ source. +* Each bit pair describes the configuration for an INT_ID. +* SFI Read Only b10 always +* PPI Read Only depending on how the PPIs are configured. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive +* SPI LSB is read only. +* b01 Active HIGH level sensitive +* b11 Rising edge sensitive/ +* +* @return None. +* +* @note This API has the similar functionality of XScuGic_SetPriority +* TriggerType() and should be used when there is no InstancePtr. +* +*****************************************************************************/ +void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 Priority, u8 Trigger) +{ + u32 RegValue; +#if defined (GICv3) + u32 Temp; + u32 Index; + UINTPTR RedistBaseAddr; +#endif + u8 LocalPriority = Priority; + + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Trigger <= XSCUGIC_INT_CFG_MASK); + Xil_AssertVoid(LocalPriority <= XSCUGIC_MAX_INTR_PRIO_VAL); +#if defined (GICv3) + if (Int_Id < XSCUGIC_SPI_INT_ID_START ) + { + RedistBaseAddr = XScuGic_GetRedistBaseAddr(); + XScuGic_WriteReg(RedistBaseAddr + XSCUGIC_RDIST_SGI_PPI_OFFSET, + XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(Int_Id),Priority); + Temp = XScuGic_ReadReg(RedistBaseAddr + XSCUGIC_RDIST_SGI_PPI_OFFSET, + XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id)); + Index = XScuGic_Get_Rdist_Int_Trigger_Index(Int_Id); + Temp |= (Trigger << Index); + XScuGic_WriteReg(RedistBaseAddr + XSCUGIC_RDIST_SGI_PPI_OFFSET, + XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id),Temp); + return; + } +#endif + + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * The priority bits are Bits 7 to 3 in GIC Priority Register. This + * means the number of priority levels supported are 32 and they are + * in steps of 8. The priorities can be 0, 8, 16, 32, 48, ... etc. + * The lower order 3 bits are masked before putting it in the register. + */ + LocalPriority = LocalPriority & XSCUGIC_INTR_PRIO_MASK; + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~((u32)XSCUGIC_PRIORITY_MASK << ((Int_Id%4U)*8U)); + RegValue |= (u32)LocalPriority << ((Int_Id%4U)*8U); + + /* + * Write the value back to the register. + */ + XScuGic_WriteReg(DistBaseAddress, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), + RegValue); + /* + * Determine the register to write to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue &= ~((u32)XSCUGIC_INT_CFG_MASK << ((Int_Id%16U)*2U)); + RegValue |= (u32)Trigger << ((Int_Id%16U)*2U); + + /* + * Write the value back to the register. + */ + XScuGic_WriteReg(DistBaseAddress, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), + RegValue); + + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +} + +/****************************************************************************/ +/** +* Gets the interrupt priority and trigger type for the specificd IRQ source. +* +* @param DistBaseAddress is the distributor base address +* @param Int_Id is the IRQ source number to modify +* @param Priority is a pointer to the value of the priority of the IRQ +* source. This is a return value. +* @param Trigger is pointer to the value of the trigger of the IRQ +* source. This is a return value. +* +* @return None. +* +* @note This API has the similar functionality of XScuGic_GetPriority +* TriggerType() and should be used when there is no InstancePtr. +* +*****************************************************************************/ +void XScuGic_GetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 *Priority, u8 *Trigger) +{ + u32 RegValue; +#if defined (GICv3) + UINTPTR RedistBaseAddr; +#endif + + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(Priority != NULL); + Xil_AssertVoid(Trigger != NULL); +#if defined (GICv3) + if (Int_Id < XSCUGIC_SPI_INT_ID_START ) + { + RedistBaseAddr = XScuGic_GetRedistBaseAddr(); + *Priority = XScuGic_ReadReg(RedistBaseAddr + XSCUGIC_RDIST_SGI_PPI_OFFSET, + XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(Int_Id)); + RegValue = XScuGic_ReadReg(RedistBaseAddr + XSCUGIC_RDIST_SGI_PPI_OFFSET, + XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id)); + RegValue = RegValue >> ((Int_Id%16U)*2U); + *Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK); + return; + } +#endif + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%4U)*8U); + *Priority = (u8)(RegValue & XSCUGIC_PRIORITY_MASK); + + /* + * Determine the register to read to using the Int_Id. + */ + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id)); + + /* + * Shift and Mask the correct bits for the priority and trigger in the + * register + */ + RegValue = RegValue >> ((Int_Id%16U)*2U); + + *Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK); +} + +/****************************************************************************/ +/** +* Sets the target CPU for the interrupt of a peripheral +* +* @param DistBaseAddress is the device base address +* @param Cpu_Id is a CPU number from which the interrupt has to be +* unmapped +* @param Int_Id is the IRQ source number to modify +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_InterruptMapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id) +{ + u32 RegValue; +#if !defined (GICv3) + u32 Offset; + u8 Cpu_CoreId; +#endif + + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + +if (Int_Id >= XSCUGIC_SPI_INT_ID_START) { +#if defined (GICv3) + u32 Temp; + Temp = Int_Id; + + #if defined (VERSAL_NET) + #if defined (ARMR52) + RegValue = (Cpu_Id & XSCUGIC_COREID_MASK); + #else + RegValue = ((Cpu_Id & XSCUGIC_CLUSTERID_MASK) >> XSCUGIC_CLUSTERID_SHIFT); + RegValue = (RegValue << XSCUGIC_IROUTER_AFFINITY2_SHIFT); + RegValue |= ((Cpu_Id & XSCUGIC_COREID_MASK) << XSCUGIC_IROUTER_AFFINITY1_SHIFT); + #endif + #else + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_IROUTER_OFFSET_CALC(Temp)); + RegValue |= (Cpu_Id); + #endif + + XScuGic_WriteReg(DistBaseAddress, XSCUGIC_IROUTER_OFFSET_CALC(Temp), + RegValue); +#else + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + + Offset = (Int_Id & 0x3U); + Cpu_CoreId = (0x1U << Cpu_Id); + + RegValue |= (u32)(Cpu_CoreId) << (Offset*8U); + + XScuGic_WriteReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), + RegValue); + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +#endif +} +} + +/****************************************************************************/ +/** +* Unmaps specific SPI interrupt from the target CPU +* +* @param DistBaseAddress is the device base address +* @param Cpu_Id is a CPU number from which the interrupt has to be +* unmapped +* @param Int_Id is the IRQ source number to modify +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_InterruptUnmapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id) +{ + u32 RegValue; +#if !defined (GICv3) + u32 Offset; + u32 Cpu_CoreId; +#endif + + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + +if (Int_Id >= XSCUGIC_SPI_INT_ID_START) { +#if defined (GICv3) + u32 Temp; + Temp = Int_Id; + + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_IROUTER_OFFSET_CALC(Temp)); + #if defined (VERSAL_NET) + #if defined (ARMR52) + Temp = (Cpu_Id & XSCUGIC_COREID_MASK); + #else + Temp = ((Cpu_Id & XSCUGIC_CLUSTERID_MASK) >> XSCUGIC_CLUSTERID_SHIFT); + Temp = (Temp << XSCUGIC_IROUTER_AFFINITY2_SHIFT); + Temp |= ((Cpu_Id & XSCUGIC_COREID_MASK) << XSCUGIC_IROUTER_AFFINITY1_SHIFT); + #endif + RegValue &= ~Temp; + #else + RegValue &= ~(Cpu_Id); + #endif + XScuGic_WriteReg(DistBaseAddress, XSCUGIC_IROUTER_OFFSET_CALC(Temp), + RegValue); +#else + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + + RegValue = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + + Offset = (Int_Id & 0x3U); + Cpu_CoreId = ((u32)0x1U << Cpu_Id); + + RegValue &= ~(Cpu_CoreId << (Offset*8U)); + XScuGic_WriteReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), RegValue); + + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +#endif +} +} + +/****************************************************************************/ +/** +* Unmaps all SPI interrupts from the target CPU +* +* @param DistBaseAddress is the device base address +* @param Cpu_Id is a CPU number from which the interrupts has to be +* unmapped +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XScuGic_UnmapAllInterruptsFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id) +{ + u32 Int_Id; + u32 Target_Cpu; + u32 LocalCpuID = ((u32)1U << Cpu_Id); + + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + + LocalCpuID |= LocalCpuID << 8U; + LocalCpuID |= LocalCpuID << 16U; + + for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; + Int_Id = Int_Id+4U) { + + Target_Cpu = XScuGic_ReadReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); + /* Remove LocalCpuID from interrupt target register */ + Target_Cpu &= (~LocalCpuID); + XScuGic_WriteReg(DistBaseAddress, + XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), Target_Cpu); + + } + + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +} + +/*****************************************************************************/ +/** +* +* Enables the interrupt source provided as the argument Int_Id. Any pending +* interrupt condition for the specified Int_Id will occur after this function is +* called. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XScuGic_EnableIntr (u32 DistBaseAddress, u32 Int_Id) +{ + u8 Cpu_Id = (u8)XScuGic_GetCpuID(); +#if defined (GICv3) + u32 Temp; + UINTPTR RedistBaseAddr; +#endif + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + +#if defined (GICv3) + if (Int_Id < XSCUGIC_SPI_INT_ID_START) { + RedistBaseAddr = XScuGic_GetRedistBaseAddr(); + + Int_Id &= 0x1f; + Int_Id = 1 << Int_Id; + + Temp = XScuGic_ReadReg(RedistBaseAddr + + XSCUGIC_RDIST_SGI_PPI_OFFSET, XSCUGIC_RDIST_ISENABLE_OFFSET); + Temp |= Int_Id; + XScuGic_WriteReg(RedistBaseAddr + XSCUGIC_RDIST_SGI_PPI_OFFSET, + XSCUGIC_RDIST_ISENABLE_OFFSET,Temp); + return; + } +#endif + #if defined (VERSAL_NET) + #if defined (ARMR52) + Cpu_Id = XGetCoreId(); + #else + Cpu_Id = XGetCoreId(); + Cpu_Id |= (XGetClusterId() << XSCUGIC_CLUSTERID_SHIFT); + #endif + #endif + + XScuGic_InterruptMapFromCpuByDistAddr(DistBaseAddress, Cpu_Id, Int_Id); + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + XScuGic_WriteReg((DistBaseAddress), XSCUGIC_ENABLE_SET_OFFSET + + (((Int_Id) / 32U) * 4U), ((u32)0x00000001U << ((Int_Id) % 32U))); + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +} + +/*****************************************************************************/ +/** +* +* Disables the interrupt source provided as the argument Int_Id such that the +* interrupt controller will not cause interrupts for the specified Int_Id. The +* interrupt controller will continue to hold an interrupt condition for the +* Int_Id, but will not cause an interrupt. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* @param Int_Id contains the ID of the interrupt source and should be +* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XScuGic_DisableIntr (u32 DistBaseAddress, u32 Int_Id) +{ + u8 Cpu_Id = (u8)XScuGic_GetCpuID(); + Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); + +#if defined (GICv3) + u32 Temp; + UINTPTR RedistBaseAddr; + + if (Int_Id < XSCUGIC_SPI_INT_ID_START) { + + Int_Id &= 0x1f; + Int_Id = 1 << Int_Id; + + RedistBaseAddr = XScuGic_GetRedistBaseAddr(); + + Temp = XScuGic_ReadReg(RedistBaseAddr + XSCUGIC_RDIST_SGI_PPI_OFFSET, + XSCUGIC_RDIST_ISENABLE_OFFSET); + Temp &= ~Int_Id; + XScuGic_WriteReg(RedistBaseAddr + XSCUGIC_RDIST_SGI_PPI_OFFSET, + XSCUGIC_RDIST_ISENABLE_OFFSET,Temp); + return; + } +#endif + #if defined (VERSAL_NET) + #if defined (ARMR52) + Cpu_Id = XGetCoreId(); + #else + Cpu_Id = XGetCoreId(); + Cpu_Id |= (XGetClusterId() << XSCUGIC_CLUSTERID_SHIFT); + #endif + #endif + + XScuGic_InterruptUnmapFromCpuByDistAddr(DistBaseAddress, Cpu_Id, Int_Id); + /* + * Call spinlock to protect multiple applications running at separate + * CPUs to write to the same register. This macro also ensures that + * the spinlock mechanism is used only if spinlock is enabled by + * user. + */ + XIL_SPINLOCK(); + XScuGic_WriteReg((DistBaseAddress), XSCUGIC_DISABLE_OFFSET + + (((Int_Id) / 32U) * 4U), ((u32)0x00000001U << ((Int_Id) % 32U))); + /* + * Release the lock previously taken. This macro ensures that the lock + * is given only if spinlock mechanism is enabled by the user. + */ + XIL_SPINUNLOCK(); +} + +#if defined (GICv3) +/*****************************************************************************/ +/** +* +* Find redistributor base address for CPU core on which API is executed +* +* @return Redistributor base address or NULL if the device was +* not found. +* +* @note None. +* +******************************************************************************/ +UINTPTR XScuGic_GetRedistBaseAddr(void) { + u32 Cpu_Affinity; + u64 Gicr_Typer; + UINTPTR BaseAddr = 0, Addr; + + /* + * Find redistributor for CPU core on which this API is executed. + * Redistributor is found by comparing affinity bits of each + * redistributor present in SoC against affinity of CPU core. Affinity + * bits of redistributor are specified in GICR_TYPER register. + * CortexR52 GIC redistributor always reads cluster number (affinity1) + * as 0, that is why for CortexR52 case, affinity read from GICR_TYPER + * is compared with affinity0 (core number) read from CPU register. + */ + #if defined (ARMR52) + Cpu_Affinity = (mfcp(XREG_CP15_MULTI_PROC_AFFINITY) & XREG_MPIDR_AFFINITY0_MASK); + #else + Cpu_Affinity = (mfcp(MPIDR_EL1) & XREG_MPIDR_MASK); + #endif + + for (Addr = XSCUGIC_RDIST_START_ADDR; Addr < XSCUGIC_RDIST_END_ADDR; + Addr += XSCUGIC_RDIST_OFFSET) { + + Gicr_Typer = XScuGic_ReadReg64(Addr, XSCUGIC_RDIST_TYPER_OFFSET); + Gicr_Typer &= XSCUGIC_GICR_TYPER_AFFINITY_MASK; + Gicr_Typer >>= XSCUGIC_GICR_TYPER_AFFINITY_SHIFT; + if (Cpu_Affinity == Gicr_Typer) { + BaseAddr = Addr; + break; + } + } + + return BaseAddr; +} +#endif +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_hw.h new file mode 100644 index 0000000..0bbd0c4 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_hw.h @@ -0,0 +1,753 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscugic_hw.h +* @addtogroup scugic Overview +* @{ +* +* This header file contains identifiers and HW access functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* The driver functions/APIs are defined in xscugic.h. +* +* This GIC device has two parts, a distributor and CPU interface(s). Each part +* has separate register definition sections. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 "xil_exception.h" added as include.
+*		      Macros XScuGic_EnableIntr and XScuGic_DisableIntr are
+*		      added to enable or disable interrupts based on
+*		      Distributor Register base address. Normally users use
+*		      XScuGic instance and call XScuGic_Enable or
+*		      XScuGic_Disable to enable/disable interrupts. These
+*		      new macros are provided when user does not want to
+*		      use an instance pointer but still wants to enable or
+*		      disable interrupts.
+*		      Function prototypes for functions (present in newly
+*		      added file xscugic_hw.c) are added.
+* 1.03a srt  02/27/13 Moved Offset calculation macros from *_hw.c (CR
+*		      702687).
+* 1.04a hk   05/04/13 Fix for CR#705621. Moved function prototypes
+*		      XScuGic_SetPriTrigTypeByDistAddr and
+*         	      XScuGic_GetPriTrigTypeByDistAddr here from xscugic.h
+* 3.0	pkp  12/09/14 changed XSCUGIC_MAX_NUM_INTR_INPUTS for
+*		      Zynq Ultrascale Mp
+* 3.0   kvn  02/13/14 Modified code for MISRA-C:2012 compliance.
+* 3.2	pkp  11/09/15 Corrected the interrupt processsor target mask value
+*					  for CPU interface 2 i.e. XSCUGIC_SPI_CPU2_MASK
+* 3.9   mus  02/21/18 Added new API's XScuGic_InterruptUnmapFromCpuByDistAddr
+*					  and XScuGic_UnmapAllInterruptsFromCpuByDistAddr, These
+*					  API's can be used by applications to unmap specific/all
+*					  interrupts from target CPU. It fixes CR#992490.
+* 3.10  aru  08/23/18 Resolved MISRA-C:2012 compliance mandatory violations
+* 4.1   asa  03/30/19 Removed macros for XScuGic_EnableIntr, and
+*                     XScuGic_DisableIntr. These are now C functions. This
+*                     change was to fix CR-1024716.
+* 4.1   mus  06/12/19 Updated XSCUGIC_MAX_NUM_INTR_INPUTS for Versal.
+* 4.6	sk   06/07/21 Delete the commented macro code to fix the MISRA-C warning.
+* 4.6	sk   08/05/21 Fix Scugic Misrac violations.
+* 4.7	sk   12/10/21 Update XSCUGIC_SPI_INT_ID_START macro from signed to unsigned
+* 		      to fix misrac violation.
+* 4.7   mus  03/17/22 GICv3 coupled with A72 has different redistributor for
+*                     each core, and each redistributor has different address,
+*                     Updated #define for re-distributor address to have correct
+*                     value based on the cpu number. It fixes CR#1126156.
+* 5.0   mus  22/02/22 Added support for VERSAL NET
+* 5.1   mus  02/13/23 Added #defines required for logic to find redistributor
+*                     based address for specific CPU core. Also, added new macro
+*                     XScuGic_ReadReg64 to read 64 bit value from specific address.
+* 5.1   mus  02/15/23 Added support for VERSAL_NET APU and RPU GIC.
+*
+* 
+* +******************************************************************************/ + +#ifndef XSCUGIC_HW_H /* prevent circular inclusions */ +#define XSCUGIC_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xil_exception.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ +#if (defined (versal) && !defined(ARMR5)) || defined (ARMR52) +#define GICv3 +#endif + +#if defined (VERSAL_NET) && ! defined (ARMR52) +#define GIC600 +#endif + +#if defined (VERSAL_NET) +#if defined (ARMR52) +#define XSCUGIC_NUM_OF_CORES_PER_CLUSTER 2U +#else +#define XSCUGIC_NUM_OF_CORES_PER_CLUSTER 4U +#endif +#endif + +/* + * The maximum number of interrupts supported by the hardware. + */ +#ifdef PLATFORM_ZYNQ +#define XSCUGIC_MAX_NUM_INTR_INPUTS 95U /* Maximum number of interrupt defined by Zynq */ +#elif defined (VERSAL_NET) +#define XSCUGIC_MAX_NUM_INTR_INPUTS 256U /* Maximum number of interrupt sources in VERSAL NET */ +#elif defined (versal) +#define XSCUGIC_MAX_NUM_INTR_INPUTS 192U +#else +#define XSCUGIC_MAX_NUM_INTR_INPUTS 195U /* Maximum number of interrupt defined by Zynq Ultrascale Mp */ +#endif + +/* + * First Interrupt Id for SPI interrupts. + */ +#define XSCUGIC_SPI_INT_ID_START 0x20U +/* + * The maximum priority value that can be used in the GIC. + */ +#define XSCUGIC_MAX_INTR_PRIO_VAL 248U +#define XSCUGIC_INTR_PRIO_MASK 0x000000F8U + +/** @name Distributor Interface Register Map + * + * Define the offsets from the base address for all Distributor registers of + * the interrupt controller, some registers may be reserved in the hardware + * device. + * @{ + */ +#define XSCUGIC_DIST_EN_OFFSET 0x00000000U /**< Distributor Enable + Register */ +#define XSCUGIC_IC_TYPE_OFFSET 0x00000004U /**< Interrupt Controller + Type Register */ +#define XSCUGIC_DIST_IDENT_OFFSET 0x00000008U /**< Implementor ID + Register */ +#define XSCUGIC_SECURITY_OFFSET 0x00000080U /**< Interrupt Security + Register */ +#define XSCUGIC_ENABLE_SET_OFFSET 0x00000100U /**< Enable Set + Register */ +#define XSCUGIC_DISABLE_OFFSET 0x00000180U /**< Enable Clear Register */ +#define XSCUGIC_PENDING_SET_OFFSET 0x00000200U /**< Pending Set + Register */ +#define XSCUGIC_PENDING_CLR_OFFSET 0x00000280U /**< Pending Clear + Register */ +#define XSCUGIC_ACTIVE_OFFSET 0x00000300U /**< Active Status Register */ +#define XSCUGIC_PRIORITY_OFFSET 0x00000400U /**< Priority Level Register */ +#define XSCUGIC_SPI_TARGET_OFFSET 0x00000800U /**< SPI Target + Register 0x800-0x8FB */ +#define XSCUGIC_INT_CFG_OFFSET 0x00000C00U /**< Interrupt Configuration + Register 0xC00-0xCFC */ +#define XSCUGIC_PPI_STAT_OFFSET 0x00000D00U /**< PPI Status Register */ +#define XSCUGIC_SPI_STAT_OFFSET 0x00000D04U /**< SPI Status Register + 0xd04-0xd7C */ +#define XSCUGIC_AHB_CONFIG_OFFSET 0x00000D80U /**< AHB Configuration + Register */ +#define XSCUGIC_SFI_TRIG_OFFSET 0x00000F00U /**< Software Triggered + Interrupt Register */ +#define XSCUGIC_PERPHID_OFFSET 0x00000FD0U /**< Peripheral ID Reg */ +#if defined (GICv3) +#define XSCUGIC_PCELLID_OFFSET 0x0000FFF0U /**< Pcell ID Register */ +#else +#define XSCUGIC_PCELLID_OFFSET 0x00000FF0U /**< Pcell ID Register */ +#endif +/* @} */ + +/** @name Distributor Enable Register + * Controls if the distributor response to external interrupt inputs. + * @{ + */ +#if defined (GICv3) +#define XSCUGIC_EN_INT_MASK 0x00000003U /**< Interrupt In Enable */ +#else +#define XSCUGIC_EN_INT_MASK 0x00000001U /**< Interrupt In Enable */ +#endif +/* @} */ + +/** @name Interrupt Controller Type Register + * @{ + */ +#define XSCUGIC_LSPI_MASK 0x0000F800U /**< Number of Lockable + Shared Peripheral + Interrupts*/ +#define XSCUGIC_DOMAIN_MASK 0x00000400U /**< Number os Security domains*/ +#define XSCUGIC_CPU_NUM_MASK 0x000000E0U /**< Number of CPU Interfaces */ +#define XSCUGIC_NUM_INT_MASK 0x0000001FU /**< Number of Interrupt IDs */ +/* @} */ + +/** @name Implementor ID Register + * Implementor and revision information. + * @{ + */ +#define XSCUGIC_REV_MASK 0x00FFF000U /**< Revision Number */ +#define XSCUGIC_IMPL_MASK 0x00000FFFU /**< Implementor */ +/* @} */ + +/** @name Interrupt Security Registers + * Each bit controls the security level of an interrupt, either secure or non + * secure. These registers can only be accessed using secure read and write. + * There are registers for each of the CPU interfaces at offset 0x080. A + * register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x084. + * @{ + */ +#define XSCUGIC_INT_NS_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Set Register + * Each bit controls the enabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Use the ENABLE_CLR register to set a + * bit to 0. + * There are registers for each of the CPU interfaces at offset 0x100. With up + * to 8 registers aliased to the same address. A register set for the SPI + * interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x104. + * @{ + */ +#define XSCUGIC_INT_EN_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Enable Clear Register + * Each bit controls the disabling of an interrupt, a 0 is disabled, a 1 is + * enabled. Writing a 0 has no effect. Writing a 1 disables an interrupt and + * sets the corresponding bit to 0. + * There are registers for each of the CPU interfaces at offset 0x180. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x184. + * @{ + */ +#define XSCUGIC_INT_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Set Register + * Each bit controls the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 sets + * an interrupt to the pending state. + * There are registers for each of the CPU interfaces at offset 0x200. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x204. + * @{ + */ +#define XSCUGIC_PEND_SET_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Pending Clear Register + * Each bit can clear the Pending or Active and Pending state of an interrupt, a + * 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 + * clears the pending state of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x280. With up + * to 8 registers aliased to the same address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x284. + * @{ + */ +#define XSCUGIC_PEND_CLR_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Active Status Register + * Each bit provides the Active status of an interrupt, a + * 0 is not Active, a 1 is Active. This is a read only register. + * There are registers for each of the CPU interfaces at offset 0x300. With up + * to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 32 of these registers staring at location 0x380. + * @{ + */ +#define XSCUGIC_ACTIVE_MASK 0x00000001U /**< Each bit corresponds to an + INT_ID */ +/* @} */ + +/** @name Priority Level Register + * Each byte in a Priority Level Register sets the priority level of an + * interrupt. Reading the register provides the priority level of an interrupt. + * There are registers for each of the CPU interfaces at offset 0x400 through + * 0x41C. With up to 8 registers aliased to each address. + * 0 is highest priority, 0xFF is lowest. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x420. + * @{ + */ +#define XSCUGIC_PRIORITY_MASK 0x000000FFU /**< Each Byte corresponds to an + INT_ID */ +#define XSCUGIC_PRIORITY_MAX 0x000000FFU /**< Highest value of a priority + actually the lowest priority*/ +/* @} */ + +/** @name SPI Target Register 0x800-0x8FB + * Each byte references a separate SPI and programs which of the up to 8 CPU + * interfaces are sent a Pending interrupt. + * There are registers for each of the CPU interfaces at offset 0x800 through + * 0x81C. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0x820. + * + * This driver does not support multiple CPU interfaces. These are included + * for complete documentation. + * @{ + */ +#define XSCUGIC_SPI_CPU7_MASK 0x00000080U /**< CPU 7 Mask*/ +#define XSCUGIC_SPI_CPU6_MASK 0x00000040U /**< CPU 6 Mask*/ +#define XSCUGIC_SPI_CPU5_MASK 0x00000020U /**< CPU 5 Mask*/ +#define XSCUGIC_SPI_CPU4_MASK 0x00000010U /**< CPU 4 Mask*/ +#define XSCUGIC_SPI_CPU3_MASK 0x00000008U /**< CPU 3 Mask*/ +#define XSCUGIC_SPI_CPU2_MASK 0x00000004U /**< CPU 2 Mask*/ +#define XSCUGIC_SPI_CPU1_MASK 0x00000002U /**< CPU 1 Mask*/ +#define XSCUGIC_SPI_CPU0_MASK 0x00000001U /**< CPU 0 Mask*/ +/* @} */ + +/** @name Interrupt Configuration Register 0xC00-0xCFC + * The interrupt configuration registers program an SFI to be active HIGH level + * sensitive or rising edge sensitive. + * Each bit pair describes the configuration for an INT_ID. + * SFI Read Only b10 always + * PPI Read Only depending on how the PPIs are configured. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive + * SPI LSB is read only. + * b01 Active HIGH level sensitive + * b11 Rising edge sensitive/ + * There are registers for each of the CPU interfaces at offset 0xC00 through + * 0xC04. With up to 8 registers aliased to each address. + * A register set for the SPI interrupts is available to all CPU interfaces. + * There are up to 255 of these registers staring at location 0xC08. + * @{ + */ +#define XSCUGIC_INT_CFG_MASK 0x00000003U /**< */ +/* @} */ + +/** @name PPI Status Register + * Enables an external AMBA master to access the status of the PPI inputs. + * A CPU can only read the status of its local PPI signals and cannot read the + * status for other CPUs. + * This register is aliased for each CPU interface. + * @{ + */ +#define XSCUGIC_PPI_C15_MASK 0x00008000U /**< PPI Status */ +#define XSCUGIC_PPI_C14_MASK 0x00004000U /**< PPI Status */ +#define XSCUGIC_PPI_C13_MASK 0x00002000U /**< PPI Status */ +#define XSCUGIC_PPI_C12_MASK 0x00001000U /**< PPI Status */ +#define XSCUGIC_PPI_C11_MASK 0x00000800U /**< PPI Status */ +#define XSCUGIC_PPI_C10_MASK 0x00000400U /**< PPI Status */ +#define XSCUGIC_PPI_C09_MASK 0x00000200U /**< PPI Status */ +#define XSCUGIC_PPI_C08_MASK 0x00000100U /**< PPI Status */ +#define XSCUGIC_PPI_C07_MASK 0x00000080U /**< PPI Status */ +#define XSCUGIC_PPI_C06_MASK 0x00000040U /**< PPI Status */ +#define XSCUGIC_PPI_C05_MASK 0x00000020U /**< PPI Status */ +#define XSCUGIC_PPI_C04_MASK 0x00000010U /**< PPI Status */ +#define XSCUGIC_PPI_C03_MASK 0x00000008U /**< PPI Status */ +#define XSCUGIC_PPI_C02_MASK 0x00000004U /**< PPI Status */ +#define XSCUGIC_PPI_C01_MASK 0x00000002U /**< PPI Status */ +#define XSCUGIC_PPI_C00_MASK 0x00000001U /**< PPI Status */ +/* @} */ + +/** @name SPI Status Register 0xd04-0xd7C + * Enables an external AMBA master to access the status of the SPI inputs. + * There are up to 63 registers if the maximum number of SPI inputs are + * configured. + * @{ + */ +#define XSCUGIC_SPI_N_MASK 0x00000001U /**< Each bit corresponds to an SPI + input */ +/* @} */ + +/** @name AHB Configuration Register + * Provides the status of the CFGBIGEND input signal and allows the endianness + * of the GIC to be set. + * @{ + */ +#define XSCUGIC_AHB_END_MASK 0x00000004U /**< 0-GIC uses little Endian, + 1-GIC uses Big Endian */ +#define XSCUGIC_AHB_ENDOVR_MASK 0x00000002U /**< 0-Uses CFGBIGEND control, + 1-use the AHB_END bit */ +#define XSCUGIC_AHB_TIE_OFF_MASK 0x00000001U /**< State of CFGBIGEND */ + +/* @} */ + +/** @name Software Triggered Interrupt Register + * Controls issuing of software interrupts. + * @{ + */ +#define XSCUGIC_SFI_SELFTRIG_MASK 0x02010000U +#define XSCUGIC_SFI_TRIG_TRGFILT_MASK 0x03000000U /**< Target List filter + b00-Use the target List + b01-All CPUs except requester + b10-To Requester + b11-reserved */ +#define XSCUGIC_SFI_TRIG_CPU_MASK 0x00FF0000U /**< CPU Target list */ +#define XSCUGIC_SFI_TRIG_SATT_MASK 0x00008000U /**< 0= Use a secure interrupt */ +#define XSCUGIC_SFI_TRIG_INTID_MASK 0x0000000FU /**< Set to the INTID + signaled to the CPU*/ +/* @} */ + +/** @name CPU Interface Register Map + * + * Define the offsets from the base address for all CPU registers of the + * interrupt controller, some registers may be reserved in the hardware device. + * @{ + */ +#define XSCUGIC_CONTROL_OFFSET 0x00000000U /**< CPU Interface Control + Register */ +#define XSCUGIC_CPU_PRIOR_OFFSET 0x00000004U /**< Priority Mask Reg */ +#define XSCUGIC_BIN_PT_OFFSET 0x00000008U /**< Binary Point Register */ +#define XSCUGIC_INT_ACK_OFFSET 0x0000000CU /**< Interrupt ACK Reg */ +#define XSCUGIC_EOI_OFFSET 0x00000010U /**< End of Interrupt Reg */ +#define XSCUGIC_RUN_PRIOR_OFFSET 0x00000014U /**< Running Priority Reg */ +#define XSCUGIC_HI_PEND_OFFSET 0x00000018U /**< Highest Pending Interrupt + Register */ +#define XSCUGIC_ALIAS_BIN_PT_OFFSET 0x0000001CU /**< Aliased non-Secure + Binary Point Register */ + +/**< 0x00000020 to 0x00000FBC are reserved and should not be read or written + * to. */ +/* @} */ + + +/** @name Control Register + * CPU Interface Control register definitions + * All bits are defined here although some are not available in the non-secure + * mode. + * @{ + */ +#define XSCUGIC_CNTR_SBPR_MASK 0x00000010U /**< Secure Binary Pointer, + 0=separate registers, + 1=both use bin_pt_s */ +#define XSCUGIC_CNTR_FIQEN_MASK 0x00000008U /**< Use nFIQ_C for secure + interrupts, + 0= use IRQ for both, + 1=Use FIQ for secure, IRQ for non*/ +#define XSCUGIC_CNTR_ACKCTL_MASK 0x00000004U /**< Ack control for secure or non secure */ +#define XSCUGIC_CNTR_EN_NS_MASK 0x00000002U /**< Non Secure enable */ +#define XSCUGIC_CNTR_EN_S_MASK 0x00000001U /**< Secure enable, 0=Disabled, 1=Enabled */ +/* @} */ + + +/** @name Binary Point Register + * Binary Point register definitions + * @{ + */ + +#define XSCUGIC_BIN_PT_MASK 0x00000007U /**< Binary point mask value + Value Secure Non-secure + b000 0xFE 0xFF + b001 0xFC 0xFE + b010 0xF8 0xFC + b011 0xF0 0xF8 + b100 0xE0 0xF0 + b101 0xC0 0xE0 + b110 0x80 0xC0 + b111 0x00 0x80 + */ +/*@}*/ + +/** @name Interrupt Acknowledge Register + * Interrupt Acknowledge register definitions + * Identifies the current Pending interrupt, and the CPU ID for software + * interrupts. + */ +#define XSCUGIC_ACK_INTID_MASK 0x000003FFU /**< Interrupt ID */ +#define XSCUGIC_CPUID_MASK 0x00000C00U /**< CPU ID */ +/* @} */ + +/** @name End of Interrupt Register + * End of Interrupt register definitions + * Allows the CPU to signal the GIC when it completes an interrupt service + * routine. + */ +#define XSCUGIC_EOI_INTID_MASK 0x000003FFU /**< Interrupt ID */ + +/* @} */ + +/** @name Running Priority Register + * Running Priority register definitions + * Identifies the interrupt priority level of the highest priority active + * interrupt. + */ +#define XSCUGIC_RUN_PRIORITY_MASK 0x000000FFU /**< Interrupt Priority */ +/* @} */ + +#if defined (GICv3) +#define XSCUGIC_IROUTER_BASE_OFFSET 0x6000U +#endif +/* + * Highest Pending Interrupt register definitions + * Identifies the interrupt priority of the highest priority pending interrupt + */ +#define XSCUGIC_PEND_INTID_MASK 0x000003FFU /**< Pending Interrupt ID */ +/* @} */ +#if defined (GICv3) +/** @name ReDistributor Interface Register Map + * + * @{ + */ +#if defined (VERSAL_NET) && ! defined (ARMR52) +#define XSCUGIC_RDIST_START_ADDR 0xE2060000U +#define XSCUGIC_RDIST_END_ADDR 0xE2260000U +#elif defined (ARMR52) +#define XSCUGIC_RDIST_START_ADDR 0xE2100000U +#define XSCUGIC_RDIST_END_ADDR 0xE2130000U +#else +#define XSCUGIC_RDIST_START_ADDR 0xF9080000U +#define XSCUGIC_RDIST_END_ADDR 0xF90B0000U +#endif +#define XSCUGIC_RDIST_OFFSET 0x20000U /* offset between consecutive redistributors */ +#define XSCUGIC_RDIST_SGI_PPI_OFFSET 0x10000U /* offset between control redistributor and SGI/PPI redistributor */ +#define XSCUGIC_GICR_TYPER_AFFINITY_SHIFT 32U +#define XSCUGIC_GICR_TYPER_AFFINITY_MASK 0xFFFFFFFF00000000UL + +#define XSCUGIC_RDIST_ISENABLE_OFFSET 0x100U +#define XSCUGIC_RDIST_IPRIORITYR_OFFSET 0x400U +#define XSCUGIC_RDIST_IGROUPR_OFFSET 0x80U +#define XSCUGIC_RDIST_GRPMODR_OFFSET 0xD00U +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET 0xC00U +#define XSCUGIC_RDIST_TYPER_OFFSET 0x8U +#define XSCUGIC_RDIST_WAKER_OFFSET 0x14U +#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U + +#if defined (GIC600) +#define XSCUGIC_RDIST_PWRR_OFFSET 0x24U +#endif +/* + * GICR_IGROUPR register definitions + */ +#if (defined(ARMR52) || EL3) +#define XSCUGIC_DEFAULT_SECURITY 0x0U +#else +#define XSCUGIC_DEFAULT_SECURITY 0xFFFFFFFFU +#endif +/* + * GICR_WAKER register definitions + */ +#define XSCUGIC_RDIST_WAKER_LOW_POWER_STATE_MASK 0x7 +#define XSCUGIC_RDIST_PWRR_RDPD_MASK 0x1U +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the Interrupt Configuration Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_INT_CFG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_INT_CFG_OFFSET + (((InterruptID)/16U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Priority Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_PRIORITY_OFFSET + (((InterruptID)/4U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the Interrupt Routing Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_IROUTER_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_IROUTER_BASE_OFFSET + (InterruptID * 8)) + +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SPI_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SPI_TARGET_OFFSET + (((InterruptID)/4U) * 4U)) +/****************************************************************************/ +/** +* +* Read the SPI Target Register offset for an interrupt id. +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_SECURITY_TARGET_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_SECURITY_OFFSET + (((InterruptID)/32U)*4U)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt configuration register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_INT_CONFIG_OFFSET + ((InterruptID /16)*4)) + +/****************************************************************************/ +/** +* +* Read the Re-distributor Interrupt Priority register offset +* +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(InterruptID) \ + ((u32)XSCUGIC_RDIST_IPRIORITYR_OFFSET + (InterruptID * 4)) +/****************************************************************************/ +/** +* +* Read the Interrupt Clear-Enable Register offset for an interrupt ID +* +* @param Register is the register offset for the clear/enable bank. +* @param InterruptID is the interrupt number. +* +* @return The 32-bit value of the offset +* +* @note +* +*****************************************************************************/ +#define XSCUGIC_EN_DIS_OFFSET_CALC(Register, InterruptID) \ + ((Register) + (((InterruptID)/32U) * 4U)) + +/****************************************************************************/ +/** +* +* Read the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReadReg(BaseAddress, RegOffset) \ + (Xil_In32((BaseAddress) + (RegOffset))) + +/****************************************************************************/ +/** +* +* Read the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be read +* +* @return The 64-bit value of the register +* +* @note +* C-style signature: +* u32 XScuGic_ReadReg64(UINTPTR BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XScuGic_ReadReg64(BaseAddress, RegOffset) \ + (Xil_In64((BaseAddress) + (RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given Intc register. +* +* @param BaseAddress is the base address of the device. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XScuGic_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuGic_WriteReg(BaseAddress, RegOffset, Data) \ + (Xil_Out32(((BaseAddress) + (RegOffset)), ((u32)(Data)))) + + +/************************** Function Prototypes ******************************/ + +void XScuGic_DeviceInterruptHandler(void *DeviceId); +s32 XScuGic_DeviceInitialize(u32 DeviceId); +void XScuGic_RegisterHandler(u32 BaseAddress, s32 InterruptID, + Xil_InterruptHandler IntrHandler, void *CallBackRef); +void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 Priority, u8 Trigger); +void XScuGic_GetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id, + u8 *Priority, u8 *Trigger); +void XScuGic_InterruptMapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id); +void XScuGic_InterruptUnmapFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id, u32 Int_Id); +void XScuGic_UnmapAllInterruptsFromCpuByDistAddr(u32 DistBaseAddress, + u8 Cpu_Id); +void XScuGic_EnableIntr (u32 DistBaseAddress, u32 Int_Id); +void XScuGic_DisableIntr (u32 DistBaseAddress, u32 Int_Id); +#if defined(GICv3) +UINTPTR XScuGic_GetRedistBaseAddr(void); +#endif +/************************** Variable Definitions *****************************/ +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_intr.c b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_intr.c new file mode 100644 index 0000000..477961e --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_intr.c @@ -0,0 +1,164 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscugic_intr.c +* @addtogroup scugic Overview +* @{ +* +* This file contains the interrupt processing for the driver for the Xilinx +* Interrupt Controller. The interrupt processing is partitioned separately such +* that users are not required to use the provided interrupt processing. This +* file requires other files of the driver to be linked in also. +* +* The interrupt handler, XScuGic_InterruptHandler, uses an input argument which +* is an instance pointer to an interrupt controller driver such that multiple +* interrupt controllers can be supported. This handler requires the calling +* function to pass it the appropriate argument, so another level of indirection +* may be required. +* +* The interrupt processing may be used by connecting the interrupt handler to +* the interrupt system. The handler does not save and restore the processor +* context but only handles the processing of the Interrupt Controller. The user +* is encouraged to supply their own interrupt handler when performance tuning is +* deemed necessary. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 1.01a sdm  11/09/11 XScuGic_InterruptHandler has changed correspondingly
+*		      since the HandlerTable has now moved to XScuGic_Config.
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.10  mus  07/17/18 Updated XScuGic_InterruptHandler to fix array overrun
+*                     reported by coverity tool. It fixes CR#1006344.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+*
+* 
+* +* @internal +* +* This driver assumes that the context of the processor has been saved prior to +* the calling of the Interrupt Controller interrupt handler and then restored +* after the handler returns. This requires either the running RTOS to save the +* state of the machine or that a wrapper be used as the destination of the +* interrupt vector to save the state of the processor and restore the state +* after the interrupt handler returns. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* This function is the primary interrupt handler for the driver. It must be +* connected to the interrupt source such that it is called when an interrupt of +* the interrupt controller is active. It will resolve which interrupts are +* active and enabled and call the appropriate interrupt handler. It uses +* the Interrupt Type information to determine when to acknowledge the interrupt. +* Highest priority interrupts are serviced first. +* +* This function assumes that an interrupt vector table has been previously +* initialized. It does not verify that entries in the table are valid before +* calling an interrupt handler. +* +* +* @param InstancePtr is a pointer to the XScuGic instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuGic_InterruptHandler(XScuGic *InstancePtr) +{ + + u32 InterruptID; +#if !defined (GICv3) + u32 IntIDFull; +#endif + XScuGic_VectorTableEntry *TablePtr; + + /* Assert that the pointer to the instance is valid + */ + Xil_AssertVoid(InstancePtr != NULL); + + /* + * Read the int_ack register to identify the highest priority + * interrupt ID and make sure it is valid. Reading Int_Ack will + * clear the interrupt in the GIC. + */ +#if defined (GICv3) + InterruptID = XScuGic_get_IntID(); +#else + IntIDFull = XScuGic_CPUReadReg(InstancePtr, XSCUGIC_INT_ACK_OFFSET); + InterruptID = IntIDFull & XSCUGIC_ACK_INTID_MASK; +#endif + if (XSCUGIC_MAX_NUM_INTR_INPUTS <= InterruptID) { + goto IntrExit; + } + + /* + * If the interrupt is shared, do some locking here if + * there are multiple processors. + */ + /* + * If pre-eption is required: + * Re-enable pre-emption by setting the CPSR I bit for non-secure , + * interrupts or the F bit for secure interrupts + */ + + /* + * If we need to change security domains, issue a SMC + * instruction here. + */ + + /* + * Execute the ISR. Jump into the Interrupt service routine + * based on the IRQSource. A software trigger is cleared by + *.the ACK. + */ + TablePtr = &(InstancePtr->Config->HandlerTable[InterruptID]); + if (TablePtr != NULL) { + TablePtr->Handler(TablePtr->CallBackRef); + } + +IntrExit: + /* + * Write to the EOI register, we are all done here. + * Let this function return, the boot code will restore the stack. + */ +#if defined (GICv3) + XScuGic_ack_Int(InterruptID); + +#else + XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_EOI_OFFSET, IntIDFull); +#endif + /* + * Return from the interrupt. Change security domains + * could happen here. + */ +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_selftest.c b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_selftest.c new file mode 100644 index 0000000..94b29f9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_selftest.c @@ -0,0 +1,93 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscugic_selftest.c +* @addtogroup scugic Overview +* @{ +* +* Contains diagnostic self-test functions for the XScuGic driver. +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xscugic.h" + +/************************** Constant Definitions *****************************/ + +#define XSCUGIC_PCELL_ID 0xB105F00DU + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* Run a self-test on the driver/device. This test reads the ID registers and +* compares them. +* +* @param InstancePtr is a pointer to the XScuGic instance. +* +* @return +* +* -XST_SUCCESS if self-test is successful. +* -XST_FAILURE if the self-test is not successful. +* +* @note None. +* +******************************************************************************/ +s32 XScuGic_SelfTest(XScuGic *InstancePtr) +{ + u32 RegValue1 = 0U; + u32 Index; + s32 Status; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the ID registers. + */ + for (Index = 0U; Index <= 3U; Index++) { + RegValue1 |= XScuGic_DistReadReg(InstancePtr, + ((u32)XSCUGIC_PCELLID_OFFSET + (Index * 4U))) << + (Index * 8U); + } + + if (XSCUGIC_PCELL_ID != RegValue1) { + Status = XST_FAILURE; + } else { + Status = XST_SUCCESS; + } + return Status; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_sinit.c new file mode 100644 index 0000000..50101cf --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scugic/src/xscugic_sinit.c @@ -0,0 +1,95 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscugic_sinit.c +* @addtogroup scugic Overview +* @{ +* +* Contains static init functions for the XScuGic driver for the Interrupt +* Controller. See xscugic.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.00a drg  01/19/10 First release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.10  mus  07/17/18 Updated file to fix the various coding style issues
+*                     reported by checkpatch. It fixes CR#1006344.
+* 4.6	sk   08/05/21 Remove XScuGic_Config variable definition to fix
+* 		      misrac violation.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "xscugic.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique identifier for a device. +* +* @return A pointer to the XScuGic configuration structure for the +* specified device, or NULL if the device was not found. +* +* @note None. +* +******************************************************************************/ +XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId) +{ + XScuGic_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_SCUGIC_NUM_INSTANCES; Index++) { + if (XScuGic_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XScuGic_ConfigTable[Index]; + break; + } + } + + return (XScuGic_Config *)CfgPtr; +} + +XScuGic_Config *XScuGic_LookupConfigBaseAddr(UINTPTR BaseAddress) +{ + XScuGic_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_SCUGIC_NUM_INSTANCES; Index++) { + if (XScuGic_ConfigTable[Index].DistBaseAddress == BaseAddress) { + CfgPtr = &XScuGic_ConfigTable[Index]; + break; + } + } + return (XScuGic_Config *)CfgPtr; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/Makefile new file mode 100644 index 0000000..eb496ea --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/Makefile @@ -0,0 +1,39 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf ${DEPFILES} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer.c b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer.c new file mode 100644 index 0000000..8cdf4c3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer.c @@ -0,0 +1,264 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscutimer.c +* @addtogroup scutimer_v2_4 +* @{ +* +* Contains the implementation of interface functions of the SCU Timer driver. +* See xscutimer.h for a description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscutimer.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Initialize a specific timer instance/driver. This function must be called +* before other functions of the driver are called. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param ConfigPtr points to the XScuTimer configuration structure. +* @param EffectiveAddress is the base address for the device. It could be +* a virtual address if address translation is supported in the +* system, otherwise it is the physical address. +* +* @return +* - XST_SUCCESS if initialization was successful. +* - XST_DEVICE_IS_STARTED if the device has already been started. +* +* @note None. +* +******************************************************************************/ +s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr, + XScuTimer_Config *ConfigPtr, u32 EffectiveAddress) +{ + s32 Status; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * If the device is started, disallow the initialize and return a + * status indicating it is started. This allows the user to stop the + * device and reinitialize, but prevents a user from inadvertently + * initializing. + */ + if (InstancePtr->IsStarted != XIL_COMPONENT_IS_STARTED) { + /* + * Copy configuration into the instance structure. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + + /* + * Save the base address pointer such that the registers of the block + * can be accessed and indicate it has not been started yet. + */ + InstancePtr->Config.BaseAddr = EffectiveAddress; + + InstancePtr->IsStarted = (u32)0; + + /* + * Indicate the instance is ready to use, successfully initialized. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; +#ifdef XIL_INTERRUPT + InstancePtr->Config.IntrId = ConfigPtr->IntrId; + InstancePtr->Config.IntrParent = ConfigPtr->IntrParent; +#endif + + Status =(s32)XST_SUCCESS; + } + else { + Status = (s32)XST_DEVICE_IS_STARTED; + } + return Status; +} + +/****************************************************************************/ +/** +* +* Start the timer. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuTimer_Start(XScuTimer *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + + /* + * Set the 'timer enable' bit in the register. + */ + Register |= XSCUTIMER_CONTROL_ENABLE_MASK; + + /* + * Update the Control register with the new value. + */ + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is started. + */ + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; +} + +/****************************************************************************/ +/** +* +* Stop the timer. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuTimer_Stop(XScuTimer *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + + /* + * Clear the 'timer enable' bit in the register. + */ + Register &= (u32)(~XSCUTIMER_CONTROL_ENABLE_MASK); + + /* + * Update the Control register with the new value. + */ + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is stopped. + */ + InstancePtr->IsStarted = (u32)0; +} + +/*****************************************************************************/ +/** +* +* This function sets the prescaler bits in the timer control register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param PrescalerValue is a 8 bit value that sets the prescaler to use. +* +* @return None +* +* @note None +* +****************************************************************************/ +void XScuTimer_SetPrescaler(XScuTimer *InstancePtr, u8 PrescalerValue) +{ + u32 ControlReg; + + /* + * Assert to validate input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + /* + * Read the Timer control register. + */ + ControlReg = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + + /* + * Clear all of the prescaler control bits in the register. + */ + ControlReg &= (u32)(~XSCUTIMER_CONTROL_PRESCALER_MASK); + + /* + * Set the prescaler value. + */ + ControlReg |= (((u32)PrescalerValue) << XSCUTIMER_CONTROL_PRESCALER_SHIFT); + + /* + * Write the register with the new values. + */ + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, ControlReg); +} + +/*****************************************************************************/ +/** +* +* This function returns the current prescaler value. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return The prescaler value. +* +* @note None. +* +****************************************************************************/ +u8 XScuTimer_GetPrescaler(XScuTimer *InstancePtr) +{ + u32 ControlReg; + + /* + * Assert to validate input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Timer control register. + */ + ControlReg = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + ControlReg &= XSCUTIMER_CONTROL_PRESCALER_MASK; + + return (u8)(ControlReg >> XSCUTIMER_CONTROL_PRESCALER_SHIFT); +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer.h b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer.h new file mode 100644 index 0000000..bdce1c6 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer.h @@ -0,0 +1,350 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscutimer.h +* @addtogroup scutimer_v2_4 +* @{ +* @details +* +* The timer driver supports the Cortex A9 private timer. +* +* The timer driver supports the following features: +* - Normal mode and Auto reload mode +* - Interrupts (Interrupt handler is not provided in this driver. Application +* has to register it's own handler) +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Timer. +* +* XScuTimer_CfgInitialize() API is used to initialize the Timer. The +* user needs to first call the XScuTimer_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuTimer_CfgInitialize() API. +* +* Interrupts +* +* The Timer hardware supports interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuTimer driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The timer is not a part of the snoop control unit as indicated by the +* prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.02a sg  07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 2.3   mus 08/31/20 Updated makefile to support parallel make and
+*                    incremental builds, it would help to reduce compilation
+*                    time.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_H /* prevent circular inclusions */ +#define XSCUTIMER_H /* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscutimer_hw.h" +#include "bspconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +#ifdef XIL_INTERRUPT + u32 IntrId; + UINTPTR IntrParent; /** Bit[0] Interrupt parent type Bit[64/32:1] Parent base address */ +#endif +} XScuTimer_Config; + +/** + * The XScuTimer driver instance data. The user is required to allocate a + * variable of this type for every timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuTimer_Config Config; /**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device timer is running */ +} XScuTimer; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Check if the timer has expired. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return +* - TRUE if the timer has expired. +* - FALSE if the timer has not expired. +* +* @note C-style signature: +* int XScuTimer_IsExpired(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_IsExpired(InstancePtr) \ + ((XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) & \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) == \ + XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the timer. This macro will read the timer load register +* and writes the same value to load register to update the counter register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_RestartTimer(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_RestartTimer(InstancePtr) \ + XScuTimer_LoadTimer((InstancePtr), \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET)) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_LoadTimer(XScuTimer *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_LoadTimer(InstancePtr, Value) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. It can be called at any +* time. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterValue(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetCounterValue(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_AUTO_RELOAD_MASK)) + +/****************************************************************************/ +/** +* +* Disable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableAutoReload(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableAutoReload(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_AUTO_RELOAD_MASK))) + +/****************************************************************************/ +/** +* +* Enable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_EnableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_EnableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) | \ + XSCUTIMER_CONTROL_IRQ_ENABLE_MASK)) + +/****************************************************************************/ +/** +* +* Disable the Timer interrupt. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_DisableInterrupt(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_DisableInterrupt(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET, \ + (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_CONTROL_OFFSET) & \ + ~(XSCUTIMER_CONTROL_IRQ_ENABLE_MASK))) + +/*****************************************************************************/ +/** +* +* This function reads the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_GetInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_GetInterruptStatus(InstancePtr) \ + XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET) + +/*****************************************************************************/ +/** +* +* This function clears the interrupt status. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_ClearInterruptStatus(XScuTimer *InstancePtr) +* +******************************************************************************/ +#define XScuTimer_ClearInterruptStatus(InstancePtr) \ + XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUTIMER_ISR_OFFSET, XSCUTIMER_ISR_EVENT_FLAG_MASK) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscutimer_sinit.c + */ +XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscutimer_selftest.c + */ +s32 XScuTimer_SelfTest(XScuTimer *InstancePtr); + +/* + * Interface functions in xscutimer.c + */ +s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr, + XScuTimer_Config *ConfigPtr, u32 EffectiveAddress); +void XScuTimer_Start(XScuTimer *InstancePtr); +void XScuTimer_Stop(XScuTimer *InstancePtr); +void XScuTimer_SetPrescaler(XScuTimer *InstancePtr, u8 PrescalerValue); +u8 XScuTimer_GetPrescaler(XScuTimer *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_g.c new file mode 100644 index 0000000..75461ce --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_g.c @@ -0,0 +1,52 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscutimer_g.c +* @addtogroup scutimer_v2_4 +* @{ +* +* This file contains a table that specifies the configuration of the SCU +* Timer in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscutimer.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Prototypes ******************************/ + +/** + * This table contains configuration information for each timer + * device in the system. + */ +XScuTimer_Config XScuTimer_ConfigTable[XPAR_XSCUTIMER_NUM_INSTANCES] = { + { + (u16)XPAR_XSCUTIMER_0_DEVICE_ID, + (u32)XPAR_XSCUTIMER_0_BASEADDR + } +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_hw.h new file mode 100644 index 0000000..c34acd1 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_hw.h @@ -0,0 +1,261 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscutimer_hw.h +* @addtogroup scutimer_v2_4 +* @{ +* +* This file contains the hardware interface to the Timer. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 1.01a sdm 02/02/12 Added low level macros to read/write load, counter, control
+*		     and interrupt registers
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUTIMER_HW_H /* prevent circular inclusions */ +#define XSCUTIMER_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device + * @{ + */ + +#define XSCUTIMER_LOAD_OFFSET 0x00U /**< Timer Load Register */ +#define XSCUTIMER_COUNTER_OFFSET 0x04U /**< Timer Counter Register */ +#define XSCUTIMER_CONTROL_OFFSET 0x08U /**< Timer Control Register */ +#define XSCUTIMER_ISR_OFFSET 0x0CU /**< Timer Interrupt + Status Register */ +/* @} */ + +/** @name Timer Control register + * This register bits control the prescaler, Intr enable, + * auto-reload and timer enable. + * @{ + */ + +#define XSCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUTIMER_CONTROL_PRESCALER_SHIFT 8U +#define XSCUTIMER_CONTROL_IRQ_ENABLE_MASK 0x00000004U /**< Intr enable */ +#define XSCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload */ +#define XSCUTIMER_CONTROL_ENABLE_MASK 0x00000001U /**< Timer enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Timer counter register has reached zero. + * @{ + */ + +#define XSCUTIMER_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetLoadReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetLoadReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: +* u32 XScuTimer_GetLoadReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetLoadReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_LOAD_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetCounterReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetCounterReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetCounterReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetCounterReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_COUNTER_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer load register. This will also update the +* timer counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the load register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetControlReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetControlReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer load register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer load register. +* +* @note C-style signature: + u32 XScuTimer_GetControlReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetControlReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the timer counter register. +* +* @param BaseAddr is the base address of the scu timer. +* @param Value is the count to be loaded in to the counter register. +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_SetIntrReg(u32 BaseAddr, u32 Value) +* +******************************************************************************/ +#define XScuTimer_SetIntrReg(BaseAddr, Value) \ + XScuTimer_WriteReg(BaseAddr, XSCUTIMER_ISR_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Returns the current timer counter register value. +* +* @param BaseAddr is the base address of the scu timer. +* +* @return Contents of the timer counter register. +* +* @note C-style signature: + u32 XScuTimer_GetIntrReg(u32 BaseAddr) +* +******************************************************************************/ +#define XScuTimer_GetIntrReg(BaseAddr) \ + XScuTimer_ReadReg(BaseAddr, XSCUTIMER_ISR_OFFSET) + +/****************************************************************************/ +/** +* +* Read from the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuTimer_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuTimer_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write to the given Timer register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuTimer_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuTimer_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + (RegOffset), (Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_selftest.c b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_selftest.c new file mode 100644 index 0000000..609c217 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_selftest.c @@ -0,0 +1,113 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscutimer_selftest.c +* @addtogroup scutimer_v2_4 +* @{ +* +* Contains diagnostic self-test functions for the XScuTimer driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscutimer.h" + +/************************** Constant Definitions *****************************/ + +#define XSCUTIMER_SELFTEST_VALUE 0xA55AF00FU + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Run a self-test on the timer. This test clears the timer enable bit in +* the control register, writes to the timer load register and verifies the +* value read back matches the value written and restores the control register +* and the timer load register. +* +* @param InstancePtr is a pointer to the XScuTimer instance. +* +* @return +* - XST_SUCCESS if self-test was successful. +* - XST_FAILURE if self test was not successful. +* +* @note None. +* +******************************************************************************/ +s32 XScuTimer_SelfTest(XScuTimer *InstancePtr) +{ + u32 Register; + u32 CtrlOrig; + u32 LoadOrig; + s32 Status; + + /* + * Assert to ensure the inputs are valid and the instance has been + * initialized. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Save the contents of the Control Register and stop the timer. + */ + CtrlOrig = XScuTimer_ReadReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET); + Register = CtrlOrig & (u32)(~XSCUTIMER_CONTROL_ENABLE_MASK); + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, Register); + + /* + * Save the contents of the Load Register. + * Load a new test value in the Load Register, read it back and + * compare it with the written value. + */ + LoadOrig = XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUTIMER_LOAD_OFFSET); + XScuTimer_LoadTimer(InstancePtr, XSCUTIMER_SELFTEST_VALUE); + Register = XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUTIMER_LOAD_OFFSET); + + /* + * Restore the contents of the Load Register and Control Register. + */ + XScuTimer_LoadTimer(InstancePtr, LoadOrig); + XScuTimer_WriteReg(InstancePtr->Config.BaseAddr, + XSCUTIMER_CONTROL_OFFSET, CtrlOrig); + + /* + * Return a Failure if the contents of the Load Register do not + * match with the value written to it. + */ + if (Register != XSCUTIMER_SELFTEST_VALUE) { + Status = (s32)XST_FAILURE; + } + else { + Status = (s32)XST_SUCCESS; + } + + return Status; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_sinit.c new file mode 100644 index 0000000..f68200e --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scutimer/src/xscutimer_sinit.c @@ -0,0 +1,70 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscutimer_sinit.c +* @addtogroup scutimer_v2_4 +* @{ +* +* This file contains method for static initialization (compile-time) of the +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a nm  03/10/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscutimer.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions ****************************/ +extern XScuTimer_Config XScuTimer_ConfigTable[XPAR_XSCUTIMER_NUM_INSTANCES]; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId) +{ + XScuTimer_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_XSCUTIMER_NUM_INSTANCES; Index++) { + if (XScuTimer_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XScuTimer_ConfigTable[Index]; + break; + } + } + + return (XScuTimer_Config *)CfgPtr; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/Makefile new file mode 100644 index 0000000..eb496ea --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/Makefile @@ -0,0 +1,39 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf ${DEPFILES} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt.c b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt.c new file mode 100644 index 0000000..1c392ec --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt.c @@ -0,0 +1,191 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscuwdt.c +* @addtogroup scuwdt_v2_4 +* @{ +* +* Contains the implementation of interface functions of the XScuWdt driver. +* See xscuwdt.h for a description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscuwdt.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Initialize a specific watchdog timer instance/driver. This function +* must be called before other functions of the driver are called. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param ConfigPtr is the config structure. +* @param EffectiveAddress is the base address for the device. It could be +* a virtual address if address translation is supported in the +* system, otherwise it is the physical address. +* +* @return +* - XST_SUCCESS if initialization was successful. +* - XST_DEVICE_IS_STARTED if the device has already been started. +* +* @note This function enables the watchdog mode. +* +******************************************************************************/ +s32 XScuWdt_CfgInitialize(XScuWdt *InstancePtr, + XScuWdt_Config *ConfigPtr, u32 EffectiveAddress) +{ + s32 CfgStatus; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + Xil_AssertNonvoid(EffectiveAddress != 0x00U); + + /* + * If the device is started, disallow the initialize and return a + * status indicating it is started. This allows the user to stop the + * device and reinitialize, but prevents a user from inadvertently + * initializing. + */ + if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { + CfgStatus = (s32)XST_DEVICE_IS_STARTED; + } + else { + /* + * Copy configuration into instance. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + + /* + * Save the base address pointer such that the registers of the block + * can be accessed and indicate it has not been started yet. + */ + InstancePtr->Config.BaseAddr = EffectiveAddress; + InstancePtr->IsStarted = 0U; + + /* + * Put the watchdog timer in Watchdog mode. + */ + XScuWdt_SetWdMode(InstancePtr); + + /* + * Indicate the instance is ready to use, successfully initialized. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + CfgStatus =(s32)XST_SUCCESS; + } + return CfgStatus; +} + +/****************************************************************************/ +/** +* +* Start the watchdog counter of the device. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note User needs to select the appropriate mode (watchdog/timer) +* before using this API. +* See XScuWdt_SetWdMode/XScuWdt_SetTimerMode macros in +* xscuwdt.h. +* +******************************************************************************/ +void XScuWdt_Start(XScuWdt *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuWdt_ReadReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET); + + /* + * Set the 'watchdog enable' bit in the register. + */ + Register |= XSCUWDT_CONTROL_WD_ENABLE_MASK; + + /* + * Update the Control register with the new value. + */ + XScuWdt_WriteReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is started. + */ + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; +} + +/****************************************************************************/ +/** +* +* Stop the watchdog timer. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XScuWdt_Stop(XScuWdt *InstancePtr) +{ + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the contents of the Control register. + */ + Register = XScuWdt_ReadReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET); + + /* + * Clear the 'watchdog enable' bit in the register. + */ + Register &= (~(u32)XSCUWDT_CONTROL_WD_ENABLE_MASK); + + /* + * Update the Control register with the new value. + */ + XScuWdt_WriteReg(InstancePtr->Config.BaseAddr, + XSCUWDT_CONTROL_OFFSET, Register); + + /* + * Indicate that the device is stopped. + */ + InstancePtr->IsStarted = 0U; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt.h b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt.h new file mode 100644 index 0000000..8d11ff8 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt.h @@ -0,0 +1,365 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscuwdt.h +* @addtogroup scuwdt_v2_4 +* @{ +* @details +* +* The Xilinx SCU watchdog timer driver (XScuWdt) supports the Xilinx SCU private +* watchdog timer hardware. +* +* The XScuWdt driver supports the following features: +* - Watchdog mode +* - Timer mode +* - Auto reload (timer mode only) +* +* The watchdog counter register is a down counter and starts decrementing when +* the watchdog is started. +* In watchdog mode, when the counter reaches 0, the Reset flag is set in the +* Reset status register and the WDRESETREQ pin is asserted, causing a system +* reset. The Reset flag is not reset by normal processor reset and is cleared +* when written with a value of 1. This enables the user to differentiate a +* normal reset and a reset caused by watchdog time-out. The user needs to call +* XScuWdt_RestartWdt() periodically, to avoid the watchdog from being timed-out. +* +* The IsWdtExpired function can be used to check if the watchdog was the cause +* of the last reset. In this situation, call Initialize then call IsWdtExpired. +* If the result is true, watchdog timeout caused the last system reset. The +* application then needs to clear the Reset flag. +* +* In timer mode, when the counter reaches 0, the Event flag is set in the +* Interrupt status register and if interrupts are enabled, interrupt ID 30 is +* set as pending in the interrupt distributor. The IsTimerExpired function +* is used to check if the watchdog counter has decremented to 0 in timer mode. +* If auto-reload mode is enabled, the Counter register is automatically reloaded +* from the Load register. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate with the Watchdog Timer. +* +* XScuWdt_CfgInitialize() API is used to initialize the Watchdog Timer. The +* user needs to first call the XScuWdt_LookupConfig() API which returns +* the Configuration structure pointer which is passed as a parameter to +* the XScuWdt_CfgInitialize() API. +* +* Interrupts +* +* The SCU Watchdog Timer supports interrupts in Timer mode. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* Timer in interrupt mode. +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* Building the driver +* +* The XScuWdt driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +*

+* +* NOTE: +* The watchdog timer is not a part of the snoop control unit as indicated +* by the prefix "scu" in the name of the driver. +* It is an independent module in APU. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+*       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+*                    generation.
+* 2.3   mus 08/31/20 Updated makefile to support parallel make and
+*                    incremental builds. It would help to reduce compilaton
+*                    time.
+* 2.3	sne 09/16/20 Fixed MISRA-C violations.
+* 2.4	sne 02/04/21 Fixed Doxygen warnings.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_H /**< prevent circular inclusions */ +#define XSCUWDT_H /**< by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xscuwdt_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddr; /**< Base address of the device */ +} XScuWdt_Config; + +/** + * The XScuWdt driver instance data. The user is required to allocate a + * variable of this type for every watchdog/timer device in the system. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + XScuWdt_Config Config;/**< Hardware Configuration */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device watchdog timer is running */ +} XScuWdt; + +/************************** Variable Definitions *****************************/ +extern XScuWdt_Config XScuWdt_ConfigTable[]; + +/***************** Macros (Inline Functions) Definitions *********************/ +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog has timed-out and the last +* reset was caused by the watchdog reset. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsWdtExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsWdtExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_RST_STS_OFFSET) & \ + XSCUWDT_RST_STS_RESET_FLAG_MASK) == XSCUWDT_RST_STS_RESET_FLAG_MASK) + +/****************************************************************************/ +/** +* +* This function is used to check if the watchdog counter has reached 0 in timer +* mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - TRUE if the watchdog has expired. +* - FALSE if the watchdog has not expired. +* +* @note C-style signature: +* int XScuWdt_IsTimerExpired(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_IsTimerExpired(InstancePtr) \ + ((XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_ISR_OFFSET) & \ + XSCUWDT_ISR_EVENT_FLAG_MASK) == XSCUWDT_ISR_EVENT_FLAG_MASK) + +/****************************************************************************/ +/** +* +* Re-start the watchdog timer. This macro will read the watchdog load register +* and write the same value to load register to update the counter register. +* An application needs to call this function periodically to keep the watchdog +* from asserting the WDRESETREQ reset request output pin. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_RestartWdt(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_RestartWdt(InstancePtr) \ + XScuWdt_LoadWdt((InstancePtr), \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET))) + +/****************************************************************************/ +/** +* +* Write to the watchdog timer load register. This will also update the +* watchdog counter register with the new value. This macro can be used to +* change the time-out value. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param Value is the value to be written to the Watchdog Load register. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_LoadWdt(XScuWdt *InstancePtr, u32 Value) +* +******************************************************************************/ +#define XScuWdt_LoadWdt(InstancePtr, Value) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_LOAD_OFFSET, (Value)) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Watchdog mode by setting the WD mode bit of the +* Watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetWdMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetWdMode(InstancePtr) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, \ + (XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) | \ + (XSCUWDT_CONTROL_WD_MODE_MASK))) + +/****************************************************************************/ +/** +* +* Put the watchdog timer in Timer mode by writing 0x12345678 and 0x87654321 +* successively to the Watchdog Disable Register. +* The software must write 0x12345678 and 0x87654321 successively to the +* Watchdog Disable Register so that the watchdog mode bit in the Watchdog +* Control Register is set to zero. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_SetTimerMode(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_SetTimerMode(InstancePtr) \ +{ \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE1); \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_DISABLE_OFFSET, \ + XSCUWDT_DISABLE_VALUE2); \ +} + +/****************************************************************************/ +/** +* +* Get the contents of the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return Contents of the watchdog control register. +* +* @note C-style signature: + u32 XScuWdt_GetControlReg(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_GetControlReg(InstancePtr) \ + XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET) + +/****************************************************************************/ +/** +* +* Write to the watchdog control register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* @param ControlReg is the value to be written to the watchdog control +* register. +* +* @return None. +* +* @note C-style signature: + void XScuWdt_SetControlReg(XScuWdt *InstancePtr, u32 ControlReg) +* +******************************************************************************/ +#define XScuWdt_SetControlReg(InstancePtr, ControlReg) \ + XScuWdt_WriteReg((InstancePtr)->Config.BaseAddr, \ + XSCUWDT_CONTROL_OFFSET, (ControlReg)) + +/****************************************************************************/ +/** +* +* Enable auto-reload mode. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_EnableAutoReload(XScuWdt *InstancePtr) +* +******************************************************************************/ +#define XScuWdt_EnableAutoReload(InstancePtr) \ + XScuWdt_SetControlReg((InstancePtr), \ + (XScuWdt_GetControlReg(InstancePtr) | \ + XSCUWDT_CONTROL_AUTO_RELOAD_MASK)) + +/************************** Function Prototypes ******************************/ + +/* + * Lookup configuration in xscuwdt_sinit.c. + */ +XScuWdt_Config *XScuWdt_LookupConfig(u16 DeviceId); + +/* + * Selftest function in xscuwdt_selftest.c + */ +s32 XScuWdt_SelfTest(XScuWdt *InstancePtr); + +/* + * Interface functions in xscuwdt.c + */ +s32 XScuWdt_CfgInitialize(XScuWdt *InstancePtr, + XScuWdt_Config *ConfigPtr, u32 EffectiveAddress); + +void XScuWdt_Start(XScuWdt *InstancePtr); + +void XScuWdt_Stop(XScuWdt *InstancePtr); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_g.c new file mode 100644 index 0000000..a8726a6 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_g.c @@ -0,0 +1,53 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscuwdt_g.c +* @addtogroup scuwdt_v2_4 +* @{ +* +* This file contains a table that specifies the configuration of the SCU +* watchdog timer devices in the system. Each device should have an entry +* in the table. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscuwdt.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Prototypes ******************************/ + +/** + * This table contains configuration information for each watchdog timer + * device in the system. + */ +XScuWdt_Config XScuWdt_ConfigTable[XPAR_XSCUWDT_NUM_INSTANCES] = { + { + (u16)XPAR_SCUWDT_0_DEVICE_ID, + (u32)XPAR_SCUWDT_0_BASEADDR + } +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_hw.h new file mode 100644 index 0000000..0cdfc1e --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_hw.h @@ -0,0 +1,156 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscuwdt_hw.h +* @addtogroup scuwdt_v2_4 +* @{ +* +* This file contains the hardware interface to the Xilinx SCU private Watch Dog +* Timer (XSCUWDT). +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 1.01a bss 02/27/12 Updated the register offsets to start at 0x0 instead
+*                    of 0x20 as the base address obtained from the tools
+*		     starts at 0x20.
+* 1.02a  sg 07/17/12 Included xil_assert.h for CR 667947. This is an issue
+*		     when the xstatus.h in the common driver overwrites
+*		     the xstatus.h of the standalone BSP during the
+*		     libgen.
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ +#ifndef XSCUWDT_HW_H /**< prevent circular inclusions */ +#define XSCUWDT_HW_H /**< by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" +#include "xil_assert.h" +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * Offsets of registers from the start of the device. The WDT registers start at + * an offset 0x20 + * @{ + */ + +#define XSCUWDT_LOAD_OFFSET 0x00U /**< Watchdog Load Register */ +#define XSCUWDT_COUNTER_OFFSET 0x04U /**< Watchdog Counter Register */ +#define XSCUWDT_CONTROL_OFFSET 0x08U /**< Watchdog Control Register */ +#define XSCUWDT_ISR_OFFSET 0x0CU /**< Watchdog Interrupt Status Register */ +#define XSCUWDT_RST_STS_OFFSET 0x10U /**< Watchdog Reset Status Register */ +#define XSCUWDT_DISABLE_OFFSET 0x14U /**< Watchdog Disable Register */ +/* @} */ + +/** @name Watchdog Control register + * This register bits control the prescaler, WD/Timer mode, Intr enable, + * auto-reload, watchdog enable. + * @{ + */ + +#define XSCUWDT_CONTROL_PRESCALER_MASK 0x0000FF00U /**< Prescaler */ +#define XSCUWDT_CONTROL_PRESCALER_SHIFT 8U +#define XSCUWDT_CONTROL_WD_MODE_MASK 0x00000008U /**< Watchdog/Timer mode */ +#define XSCUWDT_CONTROL_IT_ENABLE_MASK 0x00000004U /**< Intr enable (in + timer mode) */ +#define XSCUWDT_CONTROL_AUTO_RELOAD_MASK 0x00000002U /**< Auto-reload (in + timer mode) */ +#define XSCUWDT_CONTROL_WD_ENABLE_MASK 0x00000001U /**< Watchdog enable */ +/* @} */ + +/** @name Interrupt Status register + * This register indicates the Counter register has reached zero in Counter + * mode. + * @{ + */ + +#define XSCUWDT_ISR_EVENT_FLAG_MASK 0x00000001U /**< Event flag */ +/*@}*/ + +/** @name Reset Status register + * This register indicates the Counter register has reached zero in Watchdog + * mode and a reset request is sent. + * @{ + */ + +#define XSCUWDT_RST_STS_RESET_FLAG_MASK 0x00000001U /**< Time out occurred */ +/*@}*/ + +/** @name Disable register + * This register is used to switch from watchdog mode to timer mode. + * The software must write 0x12345678 and 0x87654321 successively to the + * Watchdog Disable Register so that the watchdog mode bit in the Watchdog + * Control Register is set to zero. + * @{ + */ +#define XSCUWDT_DISABLE_VALUE1 0x12345678U /**< Watchdog mode disable + value 1 */ +#define XSCUWDT_DISABLE_VALUE2 0x87654321U /**< Watchdog mode disable + value 2 */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XScuWdt_ReadReg(u32 BaseAddr, u32 RegOffset) +* +*****************************************************************************/ +#define XScuWdt_ReadReg(BaseAddr, RegOffset) \ + Xil_In32((BaseAddr) + ((u32)RegOffset)) + +/****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddr is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XScuWdt_WriteReg(u32 BaseAddr, u32 RegOffset, u32 Data) +* +*****************************************************************************/ +#define XScuWdt_WriteReg(BaseAddr, RegOffset, Data) \ + Xil_Out32((BaseAddr) + ((u32)RegOffset), ((u32)Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_selftest.c b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_selftest.c new file mode 100644 index 0000000..4b5c4cd --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_selftest.c @@ -0,0 +1,105 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xscuwdt_selftest.c +* @addtogroup scuwdt_v2_4 +* @{ +* +* Contains diagnostic self-test functions for the XScuWdt driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscuwdt.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* Run a self-test on the WDT. This test stops the watchdog, writes a value to +* the watchdog load register, starts the watchdog and verifies that the value +* read from the counter register is less that the value written to the load +* register. It then restores the control register and the watchdog load +* register. +* +* @param InstancePtr is a pointer to the XScuWdt instance. +* +* @return +* - XST_SUCCESS if self-test was successful. +* - XST_FAILURE if the WDT is not decrementing. +* +* @note None. +* +******************************************************************************/ +s32 XScuWdt_SelfTest(XScuWdt *InstancePtr) +{ + s32 SelfTestStatus; + u32 Register; + u32 CtrlOrig; + u32 LoadOrig; + + /* + * Assert to ensure the inputs are valid and the instance has been + * initialized. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Stop the watchdog timer. + */ + CtrlOrig = XScuWdt_GetControlReg(InstancePtr); + XScuWdt_SetControlReg(InstancePtr, + CtrlOrig & (~(u32)XSCUWDT_CONTROL_WD_ENABLE_MASK)); + + LoadOrig = XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUWDT_LOAD_OFFSET); + XScuWdt_LoadWdt(InstancePtr, 0xFFFFFFFFU); + + /* + * Start the watchdog timer and check if the watchdog counter is + * decrementing. + */ + XScuWdt_SetControlReg(InstancePtr, + CtrlOrig | (u32)XSCUWDT_CONTROL_WD_ENABLE_MASK); + + Register = XScuWdt_ReadReg((InstancePtr)->Config.BaseAddr, + XSCUWDT_COUNTER_OFFSET); + + XScuWdt_LoadWdt(InstancePtr, LoadOrig); + XScuWdt_SetControlReg(InstancePtr, CtrlOrig); + + if (Register == 0xFFFFFFFFU) { + SelfTestStatus = (s32)XST_FAILURE; + } + else { + SelfTestStatus = (s32)XST_SUCCESS; + } + + return SelfTestStatus; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_sinit.c new file mode 100644 index 0000000..a46afa7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/scuwdt/src/xscuwdt_sinit.c @@ -0,0 +1,66 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xscuwdt_sinit.c +* @addtogroup scuwdt_v2_4 +* @{ +* +* This file contains method for static initialization (compile-time) of the +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- ---------------------------------------------
+* 1.00a sdm 01/15/10 First release
+* 2.1 	sk  02/26/15 Modified the code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xscuwdt.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* Lookup the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found. +* +* @note None. +* +******************************************************************************/ +XScuWdt_Config *XScuWdt_LookupConfig(u16 DeviceId) +{ + XScuWdt_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_XSCUWDT_NUM_INSTANCES; Index++) { + if (XScuWdt_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XScuWdt_ConfigTable[Index]; + break; + } + } + + return (XScuWdt_Config *)CfgPtr; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/Makefile new file mode 100644 index 0000000..5feeb49 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/Makefile @@ -0,0 +1,39 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf $(DEPFILES) diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps.c b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps.c new file mode 100644 index 0000000..c4a23e8 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps.c @@ -0,0 +1,548 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps.c +* @addtogroup sdps Overview +* @{ +* +* Contains the interface functions of the XSdPs driver. +* See xsdps.h for a detailed description of the device and driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 1.00a hk/sg  10/17/13 Initial release
+* 2.0   hk     12/13/13 Added check for arm to use sleep.h and its API's
+* 2.1   hk     04/18/14 Add sleep for microblaze designs. CR# 781117.
+* 2.2   hk     07/28/14 Make changes to enable use of data cache.
+* 2.3   sk     09/23/14 Send command for relative card address
+*                       when re-initialization is done.CR# 819614.
+*						Use XSdPs_Change_ClkFreq API whenever changing
+*						clock.CR# 816586.
+* 2.4	sk	   12/04/14 Added support for micro SD without
+* 						WP/CD. CR# 810655.
+*						Checked for DAT Inhibit mask instead of CMD
+* 						Inhibit mask in Cmd Transfer API.
+*						Added Support for SD Card v1.0
+* 2.5 	sg	   07/09/15 Added SD 3.0 features
+*       kvn    07/15/15 Modified the code according to MISRAC-2012.
+* 2.6   sk     10/12/15 Added support for SD card v1.0 CR# 840601.
+* 2.7   sk     11/24/15 Considered the slot type befoe checking CD/WP pins.
+*       sk     12/10/15 Added support for MMC cards.
+*       sk     02/16/16 Corrected the Tuning logic.
+*       sk     03/01/16 Removed Bus Width check for eMMC. CR# 938311.
+* 2.8   sk     05/03/16 Standard Speed for SD to 19MHz in ZynqMPSoC. CR#951024
+* 3.0   sk     06/09/16 Added support for mkfs to calculate sector count.
+*       sk     07/16/16 Added support for UHS modes.
+*       sk     07/07/16 Used usleep API for both arm and microblaze.
+*       sk     07/16/16 Added Tap delays accordingly to different SD/eMMC
+*                       operating modes.
+* 3.1   mi     09/07/16 Removed compilation warnings with extra compiler flags.
+*       sk     10/13/16 Reduced the delay during power cycle to 1ms as per spec
+*       sk     10/19/16 Used emmc_hwreset pin to reset eMMC.
+*       sk     11/07/16 Enable Rst_n bit in ext_csd reg if not enabled.
+* 3.2   sk     11/30/16 Modified the voltage switching sequence as per spec.
+*       sk     02/01/17 Added HSD and DDR mode support for eMMC.
+*       vns    02/09/17 Added ARMA53_32 support for ZynqMP CR#968397
+*       sk     03/20/17 Add support for EL1 non-secure mode.
+* 3.3   mn     05/17/17 Add support for 64bit DMA addressing
+*       mn     07/17/17 Add support for running SD at 200MHz
+*       mn     07/26/17 Fixed compilation warnings
+*       mn     08/07/17 Modify driver to support 64-bit DMA in arm64 only
+*       mn     08/17/17 Added CCI support for A53 and disabled data cache
+*                       operations when it is enabled.
+*       mn     08/22/17 Updated for Word Access System support
+*       mn     09/06/17 Resolved compilation errors with IAR toolchain
+*       mn     09/26/17 Added UHS_MODE_ENABLE macro to enable UHS mode
+* 3.4   mn     10/17/17 Use different commands for single and multi block
+*                       transfers
+*       mn     03/02/18 Move UHS macro check to SD card initialization routine
+* 3.5   mn     04/18/18 Resolve compilation warnings for sdps driver
+* 3.6   mn     07/06/18 Fix Cppcheck and Doxygen warnings for sdps driver
+*       mn     08/01/18 Add support for using 64Bit DMA with 32-Bit Processor
+*       mn     08/01/18 Add cache invalidation call before returning from
+*                       ReadPolled API
+*       mn     08/14/18 Resolve compilation warnings for ARMCC toolchain
+*       mn     10/01/18 Change Expected Response for CMD3 to R1 for MMC
+*       mus    11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
+* 3.7   mn     02/01/19 Add support for idling of SDIO
+*       aru    03/12/19 Modified the code according to MISRAC-2012.
+* 3.8   mn     04/12/19 Modified TapDelay code for supporting ZynqMP and Versal
+*       mn     09/17/19 Modified ADMA handling API for 32bit and 64bit addresses
+* 3.9   sd     02/07/20 Added clock support
+*       mn     03/03/20 Restructured the code for more readability and modularity
+*       mn     03/30/20 Return XST_DEVICE_IS_STARTED when host is already started
+*       mn     03/30/20 Move Clock enabling before checking for Host already started
+* 3.10  mn     06/05/20 Check Transfer completion separately from XSdPs_Read and
+*                       XSdPs_Write APIs
+*       mn     06/05/20 Modified code for SD Non-Blocking Read support
+* 3.14  sk     10/22/21 Add support for Erase feature.
+*       mn     11/28/21 Fix MISRA-C violations.
+*       sk     01/10/22 Add support to read slot_type parameter.
+* 4.0   sk     02/25/22 Add support for eMMC5.1.
+*       sk     04/07/22 Add support to read custom tap delay values from design
+*                       for SD/eMMC.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xsdps_core.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +/*****************************************************************************/ +/** +* +* @brief +* Initializes a specific XSdPs instance such that the driver is ready to use. +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param ConfigPtr is a reference to a structure containing information +* about a specific SD device. This function initializes an +* InstancePtr object for a specific device specified by the +* contents of Config. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, use +* ConfigPtr->Config.BaseAddress for this device. +* +* @return +* - XST_SUCCESS if successful. +* - XST_DEVICE_IS_STARTED if the device is already started. +* It must be stopped to re-initialize. +* +* @note This function initializes the host controller. +* Initial clock of 400KHz is set. +* Voltage of 3.3V is selected as that is supported by host. +* Interrupts status is enabled and signal disabled by default. +* Default data direction is card to host and +* 32 bit ADMA2 is selected. Default Block size is 512 bytes. +* +******************************************************************************/ +s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + +#if defined (XCLOCKING) + InstancePtr->Config.RefClk = ConfigPtr->RefClk; + Xil_ClockEnable(InstancePtr->Config.RefClk); +#endif + /* If this API is getting called twice, return value accordingly */ + if (InstancePtr->IsReady == XIL_COMPONENT_IS_READY) { + Status = (s32)XST_DEVICE_IS_STARTED; + goto RETURN_PATH ; + } + + /* Set some default values. */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz; + InstancePtr->Config.CardDetect = ConfigPtr->CardDetect; + InstancePtr->Config.WriteProtect = ConfigPtr->WriteProtect; + InstancePtr->Config.BusWidth = ConfigPtr->BusWidth; + InstancePtr->Config.BankNumber = ConfigPtr->BankNumber; + InstancePtr->Config.HasEMIO = ConfigPtr->HasEMIO; + InstancePtr->Config.SlotType = ConfigPtr->SlotType; + InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent; + InstancePtr->Config.ITapDly_SDR_Clk50 = ConfigPtr->ITapDly_SDR_Clk50; + InstancePtr->Config.OTapDly_SDR_Clk50 = ConfigPtr->OTapDly_SDR_Clk50; + InstancePtr->Config.ITapDly_DDR_Clk50 = ConfigPtr->ITapDly_DDR_Clk50; + InstancePtr->Config.OTapDly_DDR_Clk50 = ConfigPtr->OTapDly_DDR_Clk50; + InstancePtr->Config.OTapDly_SDR_Clk100 = ConfigPtr->OTapDly_SDR_Clk100; + InstancePtr->Config.OTapDly_SDR_Clk200 = ConfigPtr->OTapDly_SDR_Clk200; + InstancePtr->SectorCount = 0U; + InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE; + InstancePtr->OTapDelay = 0U; + InstancePtr->ITapDelay = 0U; + InstancePtr->Dma64BitAddr = 0U; + InstancePtr->SlcrBaseAddr = XPS_SYS_CTRL_BASEADDR; + InstancePtr->IsBusy = FALSE; + InstancePtr->BlkSize = 0U; + InstancePtr->IsTuningDone = 0U; + + /* Host Controller version is read. */ + InstancePtr->HC_Version = + (u8)(XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK); + + /* + * Read capabilities register and update it in Instance pointer. + * It is sufficient to read this once on power on. + */ + InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_CAPS_OFFSET); + + /* Reset the SD bus lines */ + Status = XSdPs_ResetConfig(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + /* Configure the SD Host Controller */ + XSdPs_HostConfig(InstancePtr); + + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + +RETURN_PATH: +#if defined (XCLOCKING) + Xil_ClockDisable(InstancePtr->Config.RefClk); +#endif + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief +* Initialize Card with Identification mode sequence +* +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure - could be because +* a) SD is already initialized +* b) There is no card inserted +* c) One of the steps (commands) in the +* initialization cycle failed +* +* +******************************************************************************/ +s32 XSdPs_CardInitialize(XSdPs *InstancePtr) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Default settings */ + InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH; + InstancePtr->CardType = XSDPS_CARD_SD; + InstancePtr->Switch1v8 = 0U; + InstancePtr->BusSpeed = XSDPS_CLK_400_KHZ; + +#if defined (XCLOCKING) + Xil_ClockEnable(InstancePtr->Config.RefClk); +#endif + + /* Change the clock frequency to 400 KHz */ + Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + /* Identify the Card whether it is SD, MMC or eMMC */ + Status = XSdPs_IdentifyCard(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Initialize the identified card */ + if (InstancePtr->CardType == XSDPS_CARD_SD) { + Status = XSdPs_SdCardInitialize(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else { + Status = XSdPs_MmcCardInitialize(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + +RETURN_PATH: +#if defined (XCLOCKING) + Xil_ClockDisable(InstancePtr->Config.RefClk); +#endif + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function performs SD read in polled mode. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Arg is the address passed by the user that is to be sent as +* argument along with the command. +* @param BlkCnt - Block count passed by the user. +* @param Buff - Pointer to the data buffer for a DMA transfer. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure - could be because another transfer +* is in progress or command or data inhibit is set +* +******************************************************************************/ +s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (InstancePtr->IsBusy == TRUE) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + +#if defined (XCLOCKING) + Xil_ClockEnable(InstancePtr->Config.RefClk); +#endif + + /* Setup the Read Transfer */ + Status = XSdPs_SetupTransfer(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Read from the card */ + Status = XSdPs_Read(InstancePtr, Arg, BlkCnt, Buff); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check for transfer done */ + Status = XSdps_CheckTransferDone(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (InstancePtr->Config.IsCacheCoherent == 0U) { + Xil_DCacheInvalidateRange((INTPTR)Buff, + ((INTPTR)BlkCnt * (INTPTR)InstancePtr->BlkSize)); + } + +RETURN_PATH: +#if defined (XCLOCKING) + Xil_ClockDisable(InstancePtr->Config.RefClk); +#endif + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function performs SD write in polled mode. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Arg is the address passed by the user that is to be sent as +* argument along with the command. +* @param BlkCnt - Block count passed by the user. +* @param Buff - Pointer to the data buffer for a DMA transfer. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure - could be because another transfer +* is in progress or command or data inhibit is set +* +******************************************************************************/ +s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (InstancePtr->IsBusy == TRUE) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + +#if defined (XCLOCKING) + Xil_ClockEnable(InstancePtr->Config.RefClk); +#endif + + /* Setup the Write Transfer */ + Status = XSdPs_SetupTransfer(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Write to the card */ + Status = XSdPs_Write(InstancePtr, Arg, BlkCnt, Buff); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check for transfer done */ + Status = XSdps_CheckTransferDone(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + +RETURN_PATH: +#if defined (XCLOCKING) + Xil_ClockDisable(InstancePtr->Config.RefClk); +#endif + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief +* API to idle the SDIO Interface +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +* @return None +* +* @note None. +* +******************************************************************************/ +s32 XSdPs_Idle(XSdPs *InstancePtr) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#if defined (XCLOCKING) + Xil_ClockEnable(InstancePtr->Config.RefClk); +#endif + + /* Check if the bus is idle */ + Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK + | XSDPS_PSR_INHIBIT_DAT_MASK + | XSDPS_PSR_DAT_ACTIVE_MASK); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + /* Disable the Bus Power */ + XSdPs_DisableBusPower(InstancePtr); + + /* Reset Command and Data Lines */ + Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + Status = XST_SUCCESS; + +RETURN_PATH: +#if defined (XCLOCKING) + Xil_ClockDisable(InstancePtr->Config.RefClk); +#endif + return Status; +} +/*****************************************************************************/ +/** +* @brief +* This function performs Erase operation on the given address range. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param StartAddr is the address of the first write block to be erased. +* @param EndAddr is the address of the last write block of the continuous +* range to be erased. +* +* @return +* - XST_SUCCESS if erase is successful +* - XST_FAILURE if failure - could be because another transfer +* is in progress or card not present or erase operation failure. +* +******************************************************************************/ +s32 XSdPs_Erase(XSdPs *InstancePtr, u32 StartAddr, u32 EndAddr) +{ + s32 Status; + u16 CardCC; + u32 PresentStateReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#if defined (XCLOCKING) + Xil_ClockEnable(InstancePtr->Config.RefClk); +#endif + + if (InstancePtr->IsBusy == TRUE) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if ((InstancePtr->HC_Version != XSDPS_HC_SPEC_V3) || + ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK) + != XSDPS_CAPS_EMB_SLOT)) { + if(InstancePtr->Config.CardDetect != 0U) { + /* Check status to ensure card is present */ + PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_PRES_STATE_OFFSET); + if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + } + + /* Check for CCC */ + CardCC = (u16)((InstancePtr->CardSpecData[2] & CSD_CCC_MASK) >> CSD_CCC_SHIFT); + if ((CardCC & CSD_CCC_CLASS5_MASK) == 0U) { + Status = XST_SUCCESS; + goto RETURN_PATH; + } + + InstancePtr->TransferMode = XSDPS_TM_DAT_DIR_SEL_MASK; + + Status = XSdPs_SetStartAddr(InstancePtr, StartAddr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_SetEndAddr(InstancePtr, EndAddr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_SendErase(InstancePtr); + +RETURN_PATH: +#if defined (XCLOCKING) + Xil_ClockDisable(InstancePtr->Config.RefClk); +#endif + + return Status; +} + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps.h b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps.h new file mode 100644 index 0000000..77aa9c6 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps.h @@ -0,0 +1,389 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps.h +* @addtogroup sdps Overview +* @{ +* @details +* +* This section explains the implementation of the XSdPs driver. +* See xsdps.h for a detailed description of the device and driver. +* +* This driver is used initialize read from and write to the SD card. +* Features such as switching bus width to 4-bit and switching to high speed, +* changing clock frequency, block size etc. are supported. +* SD 2.0 uses 1/4 bus width and speeds of 25/50KHz. Initialization, however +* is done using 1-bit bus width and 400KHz clock frequency. +* SD commands are classified as broadcast and addressed. Commands can be +* those with response only (using only command line) or +* response + data (using command and data lines). +* Only one command can be sent at a time. During a data transfer however, +* when dsta lines are in use, certain commands (which use only the command +* line) can be sent, most often to obtain status. +* This driver does not support multi card slots at present. +* +* Initialization & Configuration +* +* This includes initialization on the host controller side to select +* clock frequency, bus power and default transfer related parameters. +* The default voltage is 3.3V. +* On the SD card side, the initialization and identification state diagram is +* implemented. This resets the card, gives it a unique address/ID and +* identifies key card related specifications. +* +* Data transfer +* +* The SD card is put in transfer state to read from or write to it. +* The default block size is 512 bytes and if supported, +* default bus width is 4-bit and bus speed is High speed. +* The read and write functions are implemented in polled mode using ADMA2. +* +* At any point, when key parameters such as block size or +* clock/speed or bus width are modified, this driver takes care of +* maintaining the same selection on host and card. +* All error bits in host controller are monitored by the driver and in the +* event one of them is set, driver will clear the interrupt status and +* communicate failure to the upper layer. +* +* File system use +* +* This driver can be used with xilffs library to read and write files to SD. +* (Please refer to procedure in diskio.c). The file system read/write example +* in polled mode can used for reference. +* +* There is no example for using SD driver without file system at present. +* However, the driver can be used without the file system. The glue layer +* in filesystem can be used as reference for the same. The block count +* passed to the read/write function in one call is limited by the ADMA2 +* descriptor table and hence care will have to be taken to call read/write +* API's in a loop for large file sizes. +* +* Interrupt mode is not supported because it offers no improvement when used +* with file system. +* +* eMMC support +* +* SD driver supports SD and eMMC based on the "enable MMC" parameter in SDK. +* The features of eMMC supported by the driver will depend on those supported +* by the host controller. The current driver supports read/write on eMMC card +* using 4-bit and high speed mode currently. +* +* Features not supported include - card write protect, password setting, +* lock/unlock, interrupts, SDMA mode, programmed I/O mode and +* 64-bit addressed ADMA2, erase/pre-erase commands. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 1.00a hk/sg  10/17/13 Initial release
+* 2.0   hk      03/07/14 Version number revised.
+* 2.1   hk     04/18/14 Increase sleep for eMMC switch command.
+*                       Add sleep for microblaze designs. CR# 781117.
+* 2.2   hk     07/28/14 Make changes to enable use of data cache.
+* 2.3   sk     09/23/14 Send command for relative card address
+*                       when re-initialization is done.CR# 819614.
+*						Use XSdPs_Change_ClkFreq API whenever changing
+*						clock.CR# 816586.
+* 2.4	sk	   12/04/14 Added support for micro SD without
+* 						WP/CD. CR# 810655.
+*						Checked for DAT Inhibit mask instead of CMD
+* 						Inhibit mask in Cmd Transfer API.
+*						Added Support for SD Card v1.0
+* 2.5 	sg		07/09/15 Added SD 3.0 features
+*       kvn     07/15/15 Modified the code according to MISRAC-2012.
+* 2.6   sk     10/12/15 Added support for SD card v1.0 CR# 840601.
+* 2.7   sk     11/24/15 Considered the slot type befoe checking CD/WP pins.
+*       sk     12/10/15 Added support for MMC cards.
+*              01/08/16 Added workaround for issue in auto tuning mode
+*                       of SDR50, SDR104 and HS200.
+*       sk     02/16/16 Corrected the Tuning logic.
+*       sk     03/01/16 Removed Bus Width check for eMMC. CR# 938311.
+* 2.8   sk     04/20/16 Added new workaround for auto tuning.
+*              05/03/16 Standard Speed for SD to 19MHz in ZynqMPSoC. CR#951024
+* 3.0   sk     06/09/16 Added support for mkfs to calculate sector count.
+*       sk     07/16/16 Added support for UHS modes.
+*       sk     07/07/16 Used usleep API for both arm and microblaze.
+*       sk     07/16/16 Added Tap delays accordingly to different SD/eMMC
+*                       operating modes.
+*       sk     08/13/16 Removed sleep.h from xsdps.h as a temporary fix for
+*                       CR#956899.
+* 3.1   mi     09/07/16 Removed compilation warnings with extra compiler flags.
+*       sk     10/13/16 Reduced the delay during power cycle to 1ms as per spec
+*       sk     10/19/16 Used emmc_hwreset pin to reset eMMC.
+*       sk     11/07/16 Enable Rst_n bit in ext_csd reg if not enabled.
+*       sk     11/16/16 Issue DLL reset at 31 iteration to load new zero value.
+* 3.2   sk     11/30/16 Modified the voltage switching sequence as per spec.
+*       sk     02/01/17 Added HSD and DDR mode support for eMMC.
+*       sk     02/01/17 Consider bus width parameter from design for switching
+*       vns    02/09/17 Added ARMA53_32 support for ZynqMP CR#968397
+*       sk     03/20/17 Add support for EL1 non-secure mode.
+* 3.3   mn     05/17/17 Add support for 64bit DMA addressing
+* 	mn     08/07/17 Modify driver to support 64-bit DMA in arm64 only
+*       mn     08/17/17 Enabled CCI support for A53 by adding cache coherency
+*                       information.
+*       mn     09/06/17 Resolved compilation errors with IAR toolchain
+* 3.6   mn     08/01/18 Add support for using 64Bit DMA with 32-Bit Processor
+* 3.7   mn     02/01/19 Add support for idling of SDIO
+* 3.8   mn     04/12/19 Modified TapDelay code for supporting ZynqMP and Versal
+*       mn     09/17/19 Modified ADMA handling API for 32bit and 64bit addresses
+* 3.9   mn     03/03/20 Restructured the code for more readability and modularity
+*       mn     03/16/20 Move XSdPs_Select_Card API to User APIs
+* 3.10  mn     06/05/20 Check Transfer completion separately from XSdPs_Read and
+*                       XSdPs_Write APIs
+*       mn     06/05/20 Modified code for SD Non-Blocking Read support
+* 3.11  sk     12/01/20 Tap programming sequence updates like disable OTAPEN
+*                       always, write zero to tap register for zero tap value.
+*       sk     12/07/20 Fix eMMC DDR52 mode write/read issue.
+*       sk     12/17/20 Removed checking platform specific SD macros and used
+*                       Baseaddress instead.
+* 3.12  sk     01/28/21 Added support for non-blocking write.
+*       sk     02/12/21 Fix the issue in reading CID and CSD.
+*       sk     04/08/21 Fixed doxygen warnings in all source files.
+*       sk     05/25/21 Fix the compilation issue in Cortex-A72 + EL1_NS by
+*                       removing the DLL reset logic (Dead code for Versal).
+* 3.13  sk     08/10/21 Limit the SD operating frequency to 19MHz for Versal.
+* 3.14  sk     10/22/21 Add support for Erase feature.
+*       sk     11/29/21 Fix compilation warnings reported with "-Wundef" flag.
+*       sk     01/10/22 Add support to read slot_type parameter.
+* 4.0   sk     02/25/22 Add support for eMMC5.1.
+*       sk     04/07/22 Add support to read custom tap delay values from design
+*                       for SD/eMMC.
+*       sk     06/03/22 Fix issue in internal clock divider calculation logic.
+* 4.1   sk     11/10/22 Add SD/eMMC Tap delay support for Versal Net.
+* 4.1   sa     01/03/23 Report error if Transfer size is greater than 2MB.
+* 4.1	sa     12/19/22 Enable eMMC HS400 mode for Versal Net.
+* 	sa     01/25/23	Use instance structure to store DMA descriptor tables.
+*
+* 
+* +******************************************************************************/ + + +#ifndef SDPS_H_ +#define SDPS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_printf.h" +#include "xil_cache.h" +#include "xstatus.h" +#include "xsdps_hw.h" +#include "xplatform_info.h" +#include "sleep.h" +#include +#if defined (XCLOCKING) +#include "xil_clocking.h" +#endif + +/************************** Constant Definitions *****************************/ + +#define XSDPS_CT_ERROR 0x2L /**< Command timeout flag */ +#define MAX_TUNING_COUNT 40U /**< Maximum Tuning count */ +#define MAX_TIMEOUT 0x1FFFFFFFU /**< Maximum Timeout */ +#define XSDPS_CMD8_VOL_PATTERN 0x1AAU /**< CMD8 voltage pattern */ +#define XSDPS_RESPOCR_READY 0x80000000U /**< Ready response */ +#define XSDPS_ACMD41_HCS 0x40000000U /**< High Capacity Support */ +#define XSDPS_ACMD41_3V3 0x00300000U /**< 3.3 voltage support */ +#define XSDPS_CMD1_HIGH_VOL 0x00FF8000U /**< CMD1 for High voltage */ +#define XSDPS_CMD1_DUAL_VOL 0x00FF8010U /**< CMD1 for Dual voltage */ +#define HIGH_SPEED_SUPPORT 0x2U /**< High Speed support */ +#define UHS_SDR12_SUPPORT 0x1U /**< SDR12 support */ +#define UHS_SDR25_SUPPORT 0x2U /**< SDR25 support */ +#define UHS_SDR50_SUPPORT 0x4U /**< SDR50 support */ +#define UHS_SDR104_SUPPORT 0x8U /**< SDR104 support */ +#define UHS_DDR50_SUPPORT 0x10U /**< DDR50 support */ +#define WIDTH_4_BIT_SUPPORT 0x4U /**< 4-bit width support */ +#define SD_CLK_25_MHZ 25000000U /**< 25MHz clock */ +#define SD_CLK_19_MHZ 19000000U /**< 19MHz clock */ +#define SD_CLK_26_MHZ 26000000U /**< 26MHz clock */ +#define EXT_CSD_DEVICE_TYPE_BYTE 196U /**< CSD Device Type byte number */ +#define EXT_CSD_SEC_COUNT_BYTE1 212U /**< CSD Sector count byte 1 */ +#define EXT_CSD_SEC_COUNT_BYTE2 213U /**< CSD Sector count byte 2 */ +#define EXT_CSD_SEC_COUNT_BYTE3 214U /**< CSD Sector count byte 3 */ +#define EXT_CSD_SEC_COUNT_BYTE4 215U /**< CSD Sector count byte 4 */ +#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED 0x2U /**< CSD Device type HS */ +#define EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED 0x4U /**< CSD Dev type DDR 1.8v speed */ +#define EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED 0x8U /**< CSD Dev type DDR 1.2v speed */ +#define EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 0x10U /**< CSD SDR 1.8v HS200 */ +#define EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200 0x20U /**< CSD SDR 1.2v HS200 */ +#define EXT_CSD_DEVICE_TYPE_DDR_1V8_HS400 0x40U /**< CSD SDR 1.8v HS400 */ +#define EXT_CSD_DEVICE_TYPE_DDR_1V2_HS400 0x80U /**< CSD SDR 1.2v HS400 */ +#define CSD_SPEC_VER_3 0x3U /**< CSD card spec ver 3 */ +#define SCR_SPEC_VER_3 0x80U /**< SCR spec ver 3 */ +#define ADDRESS_BEYOND_32BIT 0x100000000U /**< Macro used for beyond 32-bit addr */ + +#define XSDPS_ZYNQMP_SD0_BASE 0xFF160000U /**< ZynqMP SD0 Baseaddress */ +#define XSDPS_ZYNQMP_SD1_BASE 0xFF170000U /**< ZynqMP SD1 Baseaddress */ +#define XSDPS_VERSAL_SD0_BASE 0xF1040000U /**< Versal SD0 Baseaddress */ +#define XSDPS_VERSAL_SD1_BASE 0xF1050000U /**< Versal SD1 Baseaddress */ + +/** @name Block size mask for 512 bytes + * + * Block size mask for 512 bytes - This is the default block size. + * @{ + */ + +#define XSDPS_BLK_SIZE_512_MASK 0x200U /**< Blk Size 512 */ + +/** @} */ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of the device */ + u32 InputClockHz; /**< Input clock frequency */ + u32 CardDetect; /**< Card Detect */ + u32 WriteProtect; /**< Write Protect */ + u32 BusWidth; /**< Bus Width */ + u32 BankNumber; /**< MIO Bank selection for SD */ + u32 HasEMIO; /**< If SD is connected to EMIO */ + u8 SlotType; /**< Slot type */ + u8 IsCacheCoherent; /**< If SD is Cache Coherent or not */ +#if defined (XCLOCKING) + u32 RefClk; /**< Input clocks */ +#endif + u32 ITapDly_SDR_Clk50; /**< Input Tap delay for HSD/SDR25 modes */ + u32 OTapDly_SDR_Clk50; /**< Output Tap delay for HSD/SDR25 modes */ + u32 ITapDly_DDR_Clk50; /**< Input Tap delay for DDR50 modes */ + u32 OTapDly_DDR_Clk50; /**< Output Tap delay for DDR50 modes */ + u32 OTapDly_SDR_Clk100; /**< Input Tap delay for SDR50 modes */ + u32 OTapDly_SDR_Clk200; /**< Input Tap delay for SDR104/HS200 modes */ +} XSdPs_Config; + +/** + * ADMA2 32-Bit descriptor table + */ +typedef struct { + u16 Attribute; /**< Attributes of descriptor */ + u16 Length; /**< Length of current dma transfer */ + u32 Address; /**< Address of current dma transfer */ +#ifdef __ICCARM__ +#pragma data_alignment = 32 +} XSdPs_Adma2Descriptor32; +#else +} __attribute__((__packed__))XSdPs_Adma2Descriptor32; +#endif + +/** + * ADMA2 64-Bit descriptor table + */ +typedef struct { + u16 Attribute; /**< Attributes of descriptor */ + u16 Length; /**< Length of current dma transfer */ + u64 Address; /**< Address of current dma transfer */ +#ifdef __ICCARM__ +#pragma data_alignment = 32 +} XSdPs_Adma2Descriptor64; +#else +} __attribute__((__packed__))XSdPs_Adma2Descriptor64; +#endif + +/** + * The XSdPs driver instance data. The user is required to allocate a + * variable of this type for every SD device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XSdPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + u32 Host_Caps; /**< Capabilities of host controller */ + u32 Host_CapsExt; /**< Extended Capabilities */ + u32 HCS; /**< High capacity support in card */ + u8 CardType; /**< Type of card - SD/MMC/eMMC */ + u8 Card_Version; /**< Card version */ + u8 HC_Version; /**< Host controller version */ + u8 BusWidth; /**< Current operating bus width */ + u32 BusSpeed; /**< Current operating bus speed */ + u8 Switch1v8; /**< 1.8V Switch support */ + u32 CardID[4]; /**< Card ID Register */ + u32 RelCardAddr; /**< Relative Card Address */ + u32 CardSpecData[4]; /**< Card Specific Data Register */ + u32 SectorCount; /**< Sector Count */ + u32 SdCardConfig; /**< Sd Card Configuration Register */ + u32 Mode; /**< Bus Speed Mode */ + u32 OTapDelay; /**< Output Tap Delay */ + u32 ITapDelay; /**< Input Tap Delay */ + u64 Dma64BitAddr; /**< 64 Bit DMA Address */ + u16 TransferMode; /**< Transfer Mode */ + u32 SlcrBaseAddr; /**< SLCR base address*/ + u8 IsBusy; /**< Busy Flag*/ + u32 BlkSize; /**< Block Size*/ + u8 IsTuningDone; /**< Flag to indicate HS200 tuning complete */ +#ifdef __ICCARM__ +#pragma data_alignment = 32 + XSdPs_Adma2Descriptor32 Adma2_DescrTbl32[32]; + XSdPs_Adma2Descriptor64 Adma2_DescrTbl64[32]; +#else + XSdPs_Adma2Descriptor32 Adma2_DescrTbl32[32] __attribute__ ((aligned(32))); + XSdPs_Adma2Descriptor64 Adma2_DescrTbl64[32] __attribute__ ((aligned(32))); +#endif +} XSdPs; + +/***************** Macros (Inline Functions) Definitions *********************/ +/** + * @name SD High Speed mode configuration options + * @{ + */ +/** + * User configuration option to enable or disable SD HS mode. + * By default SD HS mode is disabled for Versal and enabled for + * other platforms. + */ +#ifdef versal +#define SD_HS_MODE_ENABLE 0 +#else +#define SD_HS_MODE_ENABLE 1 +#endif +/** @} */ + +/** + * Enable eMMC HS400 mode for Versal Net platform + */ +#define ENABLE_HS400_MODE + +/************************** Function Prototypes ******************************/ +XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId); +s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr, + u32 EffectiveAddr); +s32 XSdPs_CardInitialize(XSdPs *InstancePtr); +s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff); +s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff); +s32 XSdPs_Idle(XSdPs *InstancePtr); + +s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr); +s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq); +s32 XSdPs_Pullup(XSdPs *InstancePtr); +s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff); +s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr); +s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff); +s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff); +s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg); +s32 XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize); +s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg); +s32 XSdPs_Select_Card(XSdPs *InstancePtr); +s32 XSdPs_StartReadTransfer(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff); +s32 XSdPs_CheckReadTransfer(XSdPs *InstancePtr); +s32 XSdPs_StartWriteTransfer(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff); +s32 XSdPs_CheckWriteTransfer(XSdPs *InstancePtr); +s32 XSdPs_Erase(XSdPs *InstancePtr, u32 StartAddr, u32 EndAddr); + +#ifdef __cplusplus +} +#endif + +#endif /* SD_H_ */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_card.c b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_card.c new file mode 100644 index 0000000..52c5424 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_card.c @@ -0,0 +1,1782 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps_card.c +* @addtogroup sdps Overview +* @{ +* +* The xsdps_card.c file contains the interface functions of the XSdPs driver. +* See xsdps.h for a detailed description of the device and driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 3.9   mn     03/03/20 Restructured the code for more readability and modularity
+*       mn     03/16/20 Move XSdPs_Select_Card API to User APIs
+* 3.10  mn     06/05/20 Check Transfer completion separately from XSdPs_Read and
+*                       XSdPs_Write APIs
+*       mn     10/15/20 Modify power cycle API to poll for SD bus lines to go
+*                       low for versal platform
+* 3.12  sk     01/28/21 Added support for non-blocking write.
+*       sk     02/12/21 Fix the issue in reading CID and CSD.
+* 3.14  sk     10/22/21 Add support for Erase feature.
+*       mn     11/28/21 Fix MISRA-C violations.
+*       sk     01/10/22 Add support to read slot_type parameter.
+* 4.0   sk     02/25/22 Add support for eMMC5.1.
+*       sk     04/07/22 Add support to read custom tap delay values from design
+*                       for SD/eMMC.
+* 4.1   sk     11/10/22 Add SD/eMMC Tap delay support for Versal Net.
+* 4.1   sa     01/03/23	Report error if Transfer size is greater than 2MB.
+* 	sa     01/04/23 Update register bit polling logic to use Xil_WaitForEvent/
+* 			Xil_WaitForEvents API.
+* 	sa     01/25/23 Use instance structure to store DMA descriptor tables.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xsdps_core.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* @brief +* This function performs SD read in polled mode. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Arg is the address passed by the user that is to be sent as +* argument along with the command. +* @param BlkCnt - Block count passed by the user. +* @param Buff - Pointer to the data buffer for a DMA transfer. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure - could be because another transfer +* is in progress or command or data inhibit is set +* +******************************************************************************/ +s32 XSdPs_Read(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff) +{ + s32 Status; + + if ((BlkCnt * InstancePtr->BlkSize) > (32U * XSDPS_DESC_MAX_LENGTH)) { +#ifdef XSDPS_DEBUG + xil_printf("Max transfer length supported is 2MB\n"); +#endif + return XST_FAILURE; + } + + XSdPs_SetupReadDma(InstancePtr, (u16)BlkCnt, (u16)InstancePtr->BlkSize, Buff); + + if (BlkCnt == 1U) { + /* Send single block read command */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD17, Arg, BlkCnt); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + } else { + /* Send multiple blocks read command */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD18, Arg, BlkCnt); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + } + + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function performs SD write in polled mode. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Arg is the address passed by the user that is to be sent as +* argument along with the command. +* @param BlkCnt - Block count passed by the user. +* @param Buff - Pointer to the data buffer for a DMA transfer. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure - could be because another transfer +* is in progress or command or data inhibit is set +* +******************************************************************************/ +s32 XSdPs_Write(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff) +{ + s32 Status; + + if ((BlkCnt * InstancePtr->BlkSize) > (32U * XSDPS_DESC_MAX_LENGTH)) { +#ifdef XSDPS_DEBUG + xil_printf("Max transfer length supported is 2MB\n"); +#endif + return XST_FAILURE; + } + + XSdPs_SetupWriteDma(InstancePtr, (u16)BlkCnt, (u16)InstancePtr->BlkSize, Buff); + + if (BlkCnt == 1U) { + /* Send single block write command */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD24, Arg, BlkCnt); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + } else { + /* Send multiple blocks write command */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + } + + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to check for the transfer complete. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if transfer was successful +* - XST_FAILURE if failure +* - XST_DEVICE_BUSY - if the transfer is still in progress +* +******************************************************************************/ +s32 XSdPs_CheckTransferComplete(XSdPs *InstancePtr) +{ + u16 StatusReg; + s32 Status; + + if (InstancePtr->IsBusy == FALSE) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* + * Check for transfer complete + */ + StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_NORM_INTR_STS_OFFSET); + if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) { + /* Write to clear error bits */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_ERR_INTR_STS_OFFSET, + XSDPS_ERROR_INTR_ALL_MASK); + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if ((StatusReg & XSDPS_INTR_TC_MASK) == 0U) { + Status = XST_DEVICE_BUSY; + goto RETURN_PATH; + } + + /* Write to clear bit */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK); + + InstancePtr->IsBusy = FALSE; + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief +* Identify type of card using CMD0 + CMD1 sequence +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +******************************************************************************/ +s32 XSdPs_IdentifyCard(XSdPs *InstancePtr) +{ + s32 Status; + + if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) && + ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK) + == XSDPS_CAPS_EMB_SLOT)) { + InstancePtr->CardType = XSDPS_CHIP_EMMC; + Status = XST_SUCCESS; + goto RETURN_PATH; + } + + /* 74 CLK delay after card is powered up, before the first command. */ + usleep(XSDPS_INIT_DELAY); + + /* CMD0 no response expected */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0U, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Host High Capacity support & High voltage window */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD1, + XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U); + if (Status != XST_SUCCESS) { + InstancePtr->CardType = XSDPS_CARD_SD; + } else { + InstancePtr->CardType = XSDPS_CARD_MMC; + } + + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK); + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); + + Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_CMD_LINE_MASK); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* SD initialization is done in this function +* +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure - could be because +* a) SD is already initialized +* b) There is no card inserted +* c) One of the steps (commands) in the + initialization cycle failed +* +* @note This function initializes the SD card by following its +* initialization and identification state diagram. +* CMD0 is sent to reset card. +* CMD8 and ACDM41 are sent to identify voltage and +* high capacity support +* CMD2 and CMD3 are sent to obtain Card ID and +* Relative card address respectively. +* CMD9 is sent to read the card specific data. +* +******************************************************************************/ +s32 XSdPs_SdCardInitialize(XSdPs *InstancePtr) +{ + s32 Status; + +#ifndef UHS_MODE_ENABLE + InstancePtr->Config.BusWidth = XSDPS_WIDTH_4; +#endif + + Status = XSdPs_SdCardEnum(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_SdModeInit(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* @brief +* Mmc initialization is done in this function +* +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure - could be because +* a) MMC is already initialized +* b) There is no card inserted +* c) One of the steps (commands) in the initialization +* cycle failed +* @note This function initializes the SD card by following its +* initialization and identification state diagram. +* CMD0 is sent to reset card. +* CMD1 sent to identify voltage and high capacity support +* CMD2 and CMD3 are sent to obtain Card ID and +* Relative card address respectively. +* CMD9 is sent to read the card specific data. +* +******************************************************************************/ +s32 XSdPs_MmcCardInitialize(XSdPs *InstancePtr) +{ + s32 Status; + + Status = XSdPs_MmcCardEnum(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (((InstancePtr->CardType == XSDPS_CARD_MMC) && + (InstancePtr->Card_Version > CSD_SPEC_VER_3)) && + (InstancePtr->HC_Version == XSDPS_HC_SPEC_V2)) { + Status = XSdPs_MmcModeInit(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else if (InstancePtr->CardType == XSDPS_CHIP_EMMC) { + Status = XSdPs_EmmcModeInit(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else { + Status = XST_FAILURE; + goto RETURN_PATH; + + } + + if (InstancePtr->Mode != XSDPS_DDR52_MODE && InstancePtr->Mode != XSDPS_HS400_MODE) { + Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else { + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK); + InstancePtr->BlkSize = XSDPS_BLK_SIZE_512_MASK; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function checks if the card is present or not. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_CheckCardDetect(XSdPs *InstancePtr) +{ + u32 PresentStateReg; + s32 Status; + + if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) && + ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK) + == XSDPS_CAPS_EMB_SLOT)) { + Status = XST_SUCCESS; + goto RETURN_PATH; + } + + if(InstancePtr->Config.CardDetect != 0U) { + /* + * Check the present state register to make sure + * card is inserted and detected by host controller + */ + PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_PRES_STATE_OFFSET); + if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function sends CMD0 to reset the card. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_CardReset(XSdPs *InstancePtr) +{ + s32 Status; + + /* CMD0 no response expected */ + Status = XSdPs_CmdTransfer(InstancePtr, (u32)CMD0, 0U, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function sends command to get the card interface details. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_CardIfCond(XSdPs *InstancePtr) +{ + u32 RespOCR; + s32 Status; + + /* + * CMD8; response expected + * 0x1AA - Supply Voltage 2.7 - 3.6V and AA is pattern + */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD8, + XSDPS_CMD8_VOL_PATTERN, 0U); + if ((Status != XST_SUCCESS) && (Status != XSDPS_CT_ERROR)) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (Status == XSDPS_CT_ERROR) { + Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_CMD_LINE_MASK); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + } + + RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_RESP0_OFFSET); + if (RespOCR != XSDPS_CMD8_VOL_PATTERN) { + InstancePtr->Card_Version = XSDPS_SD_VER_1_0; + } else { + InstancePtr->Card_Version = XSDPS_SD_VER_2_0; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function sends command to get the card operating condition. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_CardOpCond(XSdPs *InstancePtr) +{ + u32 RespOCR; + s32 Status; + u32 Arg; + u32 Count = 10000U; + + /* Send ACMD41 while card is still busy with power up */ + do { + if (InstancePtr->CardType == XSDPS_CARD_SD) { + Status = XSdPs_CmdTransfer(InstancePtr, CMD55, 0U, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Arg = XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3 | (0x1FFU << 15U); + if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) && + (InstancePtr->Config.BusWidth == XSDPS_WIDTH_8)) { + Arg |= XSDPS_OCR_S18; + } + + /* 0x40300000 - Host High Capacity support & 3.3V window */ + Status = XSdPs_CmdTransfer(InstancePtr, ACMD41, + Arg, 0U); + } else { + /* Send CMD1 while card is still busy with power up */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD1, + XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U); + } + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Response with card capacity */ + Status = Xil_WaitForEvent(InstancePtr->Config.BaseAddress + XSDPS_RESP0_OFFSET, XSDPS_RESPOCR_READY, XSDPS_RESPOCR_READY, 1U); + if (Status == XST_SUCCESS) { + RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET); + break; + } + Count = Count - 1U; + } while (Count != 0U); + + if (Count == 0U) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Update HCS support flag based on card capacity response */ + if ((RespOCR & XSDPS_ACMD41_HCS) != 0U) { + InstancePtr->HCS = 1U; + } + + if ((RespOCR & XSDPS_OCR_S18) != 0U) { + InstancePtr->Switch1v8 = 1U; + Status = XSdPs_Switch_Voltage(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to get the card ID. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_GetCardId(XSdPs *InstancePtr) +{ + s32 Status; + u32 Count = 50U; + + /* CMD2 for Card ID */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0U, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + InstancePtr->CardID[0] = + XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_RESP0_OFFSET); + InstancePtr->CardID[1] = + XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_RESP1_OFFSET); + InstancePtr->CardID[2] = + XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_RESP2_OFFSET); + InstancePtr->CardID[3] = + XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_RESP3_OFFSET); + + if(InstancePtr->CardType == XSDPS_CARD_SD) { + do { + Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0U, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* + * Relative card address is stored as the upper 16 bits + * This is to avoid shifting when sending commands + */ + Status = Xil_WaitForEvent(InstancePtr->Config.BaseAddress + XSDPS_RESP0_OFFSET, 0xFFFF0000, 0U, 1U); + if (Status != XST_SUCCESS) { + InstancePtr->RelCardAddr = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_RESP0_OFFSET) & 0xFFFF0000U; + break; + } + Count = Count - 1U; + } while (Count != 0U); + } else { + /* Set relative card address */ + InstancePtr->RelCardAddr = 0x12340000U; + Status = XSdPs_CmdTransfer(InstancePtr, CMD3, (InstancePtr->RelCardAddr), 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + if (Count == 0U) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to get the CSD register from the card. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_GetCsd(XSdPs *InstancePtr) +{ + s32 Status; + u32 CSD[4]; + u32 BlkLen; + u32 DeviceSize; + u32 Mult; + + Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* + * Card specific data is read. + * Currently not used for any operation. + */ + CSD[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_RESP0_OFFSET); + CSD[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_RESP1_OFFSET); + CSD[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_RESP2_OFFSET); + CSD[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_RESP3_OFFSET); + + InstancePtr->CardSpecData[0] = CSD[0]; + InstancePtr->CardSpecData[1] = CSD[1]; + InstancePtr->CardSpecData[2] = CSD[2]; + InstancePtr->CardSpecData[3] = CSD[3]; + + if (InstancePtr->CardType != XSDPS_CARD_SD) { + InstancePtr->Card_Version = (u8)((u32)(CSD[3] & CSD_SPEC_VER_MASK) >>18U); + Status = XST_SUCCESS; + goto RETURN_PATH; + } + + if (((CSD[3] & CSD_STRUCT_MASK) >> 22U) == 0U) { + BlkLen = (u32)1U << ((u32)(CSD[2] & READ_BLK_LEN_MASK) >> 8U); + Mult = (u32)1U << ((u32)((CSD[1] & C_SIZE_MULT_MASK) >> 7U) + (u32)2U); + DeviceSize = (CSD[1] & C_SIZE_LOWER_MASK) >> 22U; + DeviceSize |= (CSD[2] & C_SIZE_UPPER_MASK) << 10U; + DeviceSize = (DeviceSize + 1U) * Mult; + DeviceSize = DeviceSize * BlkLen; + InstancePtr->SectorCount = (DeviceSize/XSDPS_BLK_SIZE_512_MASK); + } else if (((CSD[3] & CSD_STRUCT_MASK) >> 22U) == 1U) { + InstancePtr->SectorCount = (((CSD[1] & CSD_V2_C_SIZE_MASK) >> 8U) + + 1U) * 1024U; + } else { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to set the card voltage to 1.8V. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_CardSetVoltage18(XSdPs *InstancePtr) +{ + s32 Status; + u16 CtrlReg; + u16 ClockReg; + + /* Stop the clock */ + CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_CLK_CTRL_OFFSET); + CtrlReg &= (u16)(~(XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_CLK_EN_MASK)); + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET, + CtrlReg); + + /* Check for 1.8V signal enable bit is cleared by Host */ + Status = XSdPs_SetVoltage18(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_CLK_CTRL_OFFSET); + /* Enable the clock in the controller */ + Status = XSdPs_EnableClock(InstancePtr, ClockReg); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Wait for 1mSec */ + (void)usleep(1000U); + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to do initial Reset Configuration. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_ResetConfig(XSdPs *InstancePtr) +{ + s32 Status; + + XSdPs_DisableBusPower(InstancePtr); + +#ifdef versal + if ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK) + != XSDPS_CAPS_EMB_SLOT) { + u32 Timeout = 200000U; + + /* Check for SD Bus Lines low */ + Status = Xil_WaitForEvent(InstancePtr->Config.BaseAddress + XSDPS_PRES_STATE_OFFSET, XSDPS_PSR_DAT30_SG_LVL_MASK, 0U, Timeout); + } +#endif + + Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + XSdPs_EnableBusPower(InstancePtr); + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to do initial Host Configuration. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +void XSdPs_HostConfig(XSdPs *InstancePtr) +{ + XSdPs_ConfigPower(InstancePtr); + + XSdPs_ConfigDma(InstancePtr); + + XSdPs_ConfigInterrupt(InstancePtr); + + /* + * Transfer mode register - default value + * DMA enabled, block count enabled, data direction card to host(read) + */ + InstancePtr->TransferMode = XSDPS_TM_DMA_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK | + XSDPS_TM_DAT_DIR_SEL_MASK; + + /* Set block size to 512 by default */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK); +} + +/*****************************************************************************/ +/** +* @brief +* This function checks for Reset Done bits to be cleared after a reset assert. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Value is the bits to be checked to be cleared. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_CheckResetDone(XSdPs *InstancePtr, u8 Value) +{ + u32 Timeout = 1000000U; + s32 Status; + + /* Proceed with initialization only after reset is complete */ + /* Using XSDPS_CLK_CTRL_OFFSET(0x2C) in place of XSDPS_SW_RST_OFFSET(0x2F) for 32bit address aligned reading */ + Status = Xil_WaitForEvent(InstancePtr->Config.BaseAddress + XSDPS_CLK_CTRL_OFFSET, + Value << 24, 0U, Timeout); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to setup the voltage switch. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_SetupVoltageSwitch(XSdPs *InstancePtr) +{ + u32 Timeout = 10000; + s32 Status; + + /* Send switch voltage command */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD11, 0U, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Wait for CMD and DATA line to go low */ + Status = Xil_WaitForEvent(InstancePtr->Config.BaseAddress + XSDPS_PRES_STATE_OFFSET, + XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK, 0U, Timeout); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to check if the Cmd and Dat buses are high. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_CheckBusHigh(XSdPs *InstancePtr) +{ + u32 Timeout = MAX_TIMEOUT; + s32 Status; + + /* Wait for CMD and DATA line to go high */ + Status = Xil_WaitForEvent(InstancePtr->Config.BaseAddress + XSDPS_PRES_STATE_OFFSET, + XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK, + XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK, Timeout); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief +* API to Identify the supported UHS mode. This API will assign the +* corresponding tap delay API to the Config_TapDelay pointer based on the +* supported bus speed. +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param ReadBuff contains the response for CMD6 +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XSdPs_Identify_UhsMode(XSdPs *InstancePtr, u8 *ReadBuff) +{ + if (((ReadBuff[13] & UHS_SDR104_SUPPORT) != 0U) && + (InstancePtr->Config.InputClockHz >= XSDPS_SD_INPUT_MAX_CLK)) { + InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR104; + if (InstancePtr->Config.OTapDly_SDR_Clk200) { + InstancePtr->OTapDelay = InstancePtr->Config.OTapDly_SDR_Clk200; + } else if (InstancePtr->Config.BankNumber == 2U) { + InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2; + } else { + InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0; + } + } else if (((ReadBuff[13] & UHS_SDR50_SUPPORT) != 0U) && + (InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR50_MAX_CLK)) { + InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR50; + if (InstancePtr->Config.OTapDly_SDR_Clk100) { + InstancePtr->OTapDelay = InstancePtr->Config.OTapDly_SDR_Clk100; + } else { + InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD50; + } + } else if (((ReadBuff[13] & UHS_DDR50_SUPPORT) != 0U) && + (InstancePtr->Config.InputClockHz >= XSDPS_SD_DDR50_MAX_CLK)) { + InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_DDR50; + if (InstancePtr->Config.OTapDly_DDR_Clk50 && + InstancePtr->Config.ITapDly_DDR_Clk50) { + InstancePtr->OTapDelay = InstancePtr->Config.OTapDly_DDR_Clk50; + InstancePtr->ITapDelay = InstancePtr->Config.ITapDly_DDR_Clk50; + if ((InstancePtr->Config.SlotType == XSDPS_SLOTTYPE_SDADIR) && + (InstancePtr->ITapDelay == SD_ITAPDLYSEL_SD_DDR50)) { + InstancePtr->ITapDelay = SD_AUTODIR_ITAPDLYSEL_DDR50; + } + } else if (InstancePtr->Config.SlotType == XSDPS_SLOTTYPE_SDADIR) { + InstancePtr->ITapDelay = SD_AUTODIR_ITAPDLYSEL_DDR50; + InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_DDR50; + } else { + InstancePtr->ITapDelay = SD_ITAPDLYSEL_SD_DDR50; + InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_DDR50; + } + } else if (((ReadBuff[13] & UHS_SDR25_SUPPORT) != 0U) && + (InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR25_MAX_CLK)) { + InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR25; + if (InstancePtr->Config.OTapDly_SDR_Clk50 && + InstancePtr->Config.ITapDly_SDR_Clk50) { + InstancePtr->OTapDelay = InstancePtr->Config.OTapDly_SDR_Clk50; + InstancePtr->ITapDelay = InstancePtr->Config.ITapDly_SDR_Clk50; + if ((InstancePtr->Config.SlotType == XSDPS_SLOTTYPE_SDADIR) && + (InstancePtr->ITapDelay == SD_ITAPDLYSEL_HSD)) { + InstancePtr->ITapDelay = SD_AUTODIR_ITAPDLYSEL_SDR25; + } + } else if (InstancePtr->Config.SlotType == XSDPS_SLOTTYPE_SDADIR) { + InstancePtr->ITapDelay = SD_AUTODIR_ITAPDLYSEL_SDR25; + InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD; + } else { + InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD; + InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD; + } + } else { + InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR12; + } +} + +/*****************************************************************************/ +/** +* +* @brief +* API to set Tap Delay w.r.t speed modes +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XSdPs_SetTapDelay(XSdPs *InstancePtr) +{ + if ((InstancePtr->Mode == XSDPS_DEFAULT_SPEED_MODE) || + (InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR12)) { + return; + } + +#ifndef versal + /* Issue DLL Reset */ + XSdPs_DllRstCtrl(InstancePtr, 1U); +#endif + + /* Configure the Tap Delay Registers */ + XSdPs_ConfigTapDelay(InstancePtr); + +#ifndef versal + /* Release the DLL out of reset */ + XSdPs_DllRstCtrl(InstancePtr, 0U); +#endif +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to change the SD Bus Speed. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_Change_SdBusSpeed(XSdPs *InstancePtr) +{ + s32 Status; + u32 Arg; + u16 BlkCnt; + u16 BlkSize; + u16 CtrlReg; + u8 ReadBuff[64] = {0U}; + + Status = XSdPs_CalcBusSpeed(InstancePtr, &Arg); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + BlkCnt = XSDPS_SWITCH_CMD_BLKCNT; + BlkSize = XSDPS_SWITCH_CMD_BLKSIZE; + + XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff); + + Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, BlkCnt); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check for transfer done */ + Status = XSdps_CheckTransferDone(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (InstancePtr->Switch1v8 != 0U) { + /* Set UHS mode in controller */ + CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET); + CtrlReg &= (~(u16)XSDPS_HC2_UHS_MODE_MASK); + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET, + CtrlReg | (u16)InstancePtr->Mode); + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to change the eMMC bus speed. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_Change_MmcBusSpeed(XSdPs *InstancePtr) +{ + s32 Status; + u32 Arg; + + Status = XSdPs_CalcBusSpeed(InstancePtr, &Arg); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check for transfer done */ + Status = XSdps_CheckTransferDone(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to do the Auto tuning. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_AutoTuning(XSdPs *InstancePtr) +{ + s32 Status; + u16 BlkSize; + u8 TuningCount; + + BlkSize = XSDPS_TUNING_CMD_BLKSIZE; + if(InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) + { + BlkSize = BlkSize*2U; + } + BlkSize &= XSDPS_BLK_SIZE_MASK; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET, + BlkSize); + + InstancePtr->TransferMode = XSDPS_TM_DAT_DIR_SEL_MASK; + + XSdPs_SetExecTuning(InstancePtr); + /* + * workaround which can work for 1.0/2.0 silicon for auto tuning. + * This can be revisited for 3.0 silicon if necessary. + */ + /* Wait for ~60 clock cycles to reset the tap values */ + (void)usleep(1U); + + for (TuningCount = 0U; TuningCount < MAX_TUNING_COUNT; TuningCount++) { + + if (InstancePtr->CardType == XSDPS_CARD_SD) { + Status = XSdPs_CmdTransfer(InstancePtr, CMD19, 0U, 1U); + } else { + Status = XSdPs_CmdTransfer(InstancePtr, CMD21, 0U, 1U); + } + + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_EXEC_TNG_MASK) == 0U) { + break; + } + } + + if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_SAMP_CLK_SEL_MASK) == 0U) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Wait for ~12 clock cycles to synchronize the new tap values */ + (void)usleep(1U); + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief +* API to setup ADMA2 descriptor table +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param BlkCnt - block count. +* @param Buff pointer to data buffer. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff) +{ + if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) { + XSdPs_Setup64ADMA2DescTbl(InstancePtr, BlkCnt, Buff); + } else { + XSdPs_Setup32ADMA2DescTbl(InstancePtr, BlkCnt, Buff); + } +} + +/*****************************************************************************/ +/** +* +* @brief +* API to setup ADMA2 descriptor table for 64 Bit DMA +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param BlkCnt - block count. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XSdPs_SetupADMA2DescTbl64Bit(XSdPs *InstancePtr, u32 BlkCnt) +{ + u32 TotalDescLines; + u32 DescNum; + u32 BlkSize; + + /* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */ + BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_BLK_SIZE_OFFSET) & + XSDPS_BLK_SIZE_MASK; + + if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) { + + TotalDescLines = 1U; + + } else { + + TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH); + if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) { + TotalDescLines += 1U; + } + + } + + for (DescNum = 0U; DescNum < (TotalDescLines - 1U); DescNum++) { + InstancePtr->Adma2_DescrTbl64[DescNum].Address = + InstancePtr->Dma64BitAddr + + ((u64)DescNum*XSDPS_DESC_MAX_LENGTH); + InstancePtr->Adma2_DescrTbl64[DescNum].Attribute = + XSDPS_DESC_TRAN | XSDPS_DESC_VALID; + InstancePtr->Adma2_DescrTbl64[DescNum].Length = 0U; + } + + InstancePtr->Adma2_DescrTbl64[TotalDescLines - 1U].Address = + InstancePtr->Dma64BitAddr + + ((u64)DescNum*XSDPS_DESC_MAX_LENGTH); + + InstancePtr->Adma2_DescrTbl64[TotalDescLines - 1U].Attribute = + XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID; + + InstancePtr->Adma2_DescrTbl64[TotalDescLines - 1U].Length = + (u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH)); + + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET, + (u32)((UINTPTR)&(InstancePtr->Adma2_DescrTbl64[0]) & ~(u32)0x0U)); + + if (InstancePtr->Config.IsCacheCoherent == 0U) { + Xil_DCacheFlushRange((INTPTR)&(InstancePtr->Adma2_DescrTbl64[0]), + (INTPTR)sizeof(XSdPs_Adma2Descriptor64) * (INTPTR)32U); + } + + /* Clear the 64-Bit Address variable */ + InstancePtr->Dma64BitAddr = 0U; + +} + +/*****************************************************************************/ +/** +* +* @brief +* API to reset the DLL +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +* @return None +* +* @note None. +* +******************************************************************************/ +s32 XSdPs_DllReset(XSdPs *InstancePtr) +{ + u32 ClockReg; + s32 Status; + + /* Disable clock */ + ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_CLK_CTRL_OFFSET); + ClockReg &= ~XSDPS_CC_SD_CLK_EN_MASK; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_CLK_CTRL_OFFSET, (u16)ClockReg); + + /* Issue DLL Reset to load zero tap values */ + XSdPs_DllRstCtrl(InstancePtr, 1U); + + /* Wait for 2 micro seconds */ + (void)usleep(2U); + + XSdPs_DllRstCtrl(InstancePtr, 0U); + + ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_CLK_CTRL_OFFSET); + /* Enable the clock in the controller */ + Status = XSdPs_EnableClock(InstancePtr, (u16)ClockReg); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to identify the eMMC speed mode. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param ExtCsd is the extended CSD register from the card +* +* @return None +* +******************************************************************************/ +void XSdPs_IdentifyEmmcMode(XSdPs *InstancePtr, const u8 *ExtCsd) +{ + if (InstancePtr->BusWidth < XSDPS_4_BIT_WIDTH) { + InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE; + } else { + /* Check for card supported speed */ +#if defined (VERSAL_NET) && defined (ENABLE_HS400_MODE) + if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] & + (EXT_CSD_DEVICE_TYPE_DDR_1V8_HS400 | + EXT_CSD_DEVICE_TYPE_DDR_1V2_HS400)) != 0U) { + InstancePtr->Mode = XSDPS_HS400_MODE; + InstancePtr->IsTuningDone = 0U; + InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0; + } else { +#endif + if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] & + (EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 | + EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200)) != 0U) { + InstancePtr->Mode = XSDPS_HS200_MODE; + if (InstancePtr->Config.OTapDly_SDR_Clk200) { + InstancePtr->OTapDelay = InstancePtr->Config.OTapDly_SDR_Clk200; + } else if (InstancePtr->Config.BankNumber == 2U) { + InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2; + } else { + InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0; + } + } else if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] & + (EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED | + EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED)) != 0U) { + InstancePtr->Mode = XSDPS_DDR52_MODE; + if (InstancePtr->Config.OTapDly_DDR_Clk50 && + InstancePtr->Config.ITapDly_DDR_Clk50) { + InstancePtr->OTapDelay = InstancePtr->Config.OTapDly_DDR_Clk50; + InstancePtr->ITapDelay = InstancePtr->Config.ITapDly_DDR_Clk50; + } else { + InstancePtr->OTapDelay = SD_OTAPDLYSEL_EMMC_DDR50; + InstancePtr->ITapDelay = SD_ITAPDLYSEL_EMMC_DDR50; + } + } else if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] & + EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) { + InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE; + if (InstancePtr->Config.OTapDly_SDR_Clk50 && + InstancePtr->Config.ITapDly_SDR_Clk50) { + InstancePtr->OTapDelay = InstancePtr->Config.OTapDly_SDR_Clk50; + InstancePtr->ITapDelay = InstancePtr->Config.ITapDly_SDR_Clk50; + } else { + InstancePtr->OTapDelay = SD_OTAPDLYSEL_EMMC_HSD; + InstancePtr->ITapDelay = SD_ITAPDLYSEL_EMMC_HSD; + } + } else { + InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE; + } +#if defined (VERSAL_NET) && defined (ENABLE_HS400_MODE) + } +#endif + } +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to check the eMMC timing. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param ExtCsd is the extended CSD register from the card +* +* @return None +* +******************************************************************************/ +s32 XSdPs_CheckEmmcTiming(XSdPs *InstancePtr, u8 *ExtCsd) +{ + s32 Status; + + Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + +#ifdef VERSAL_NET + if (InstancePtr->Mode == XSDPS_HS400_MODE) { + if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HS400) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else { +#endif + if (InstancePtr->Mode == XSDPS_HS200_MODE) { + if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HS200) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else if ((InstancePtr->Mode == XSDPS_HIGH_SPEED_MODE) || + (InstancePtr->Mode == XSDPS_DDR52_MODE)) { + if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else { + Status = XST_FAILURE; + } +#ifdef VERSAL_NET + } +#endif + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to set the clock to the passed frequency. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param SelFreq is the selected frequency +* +* @return None +* +******************************************************************************/ +s32 XSdPs_SetClock(XSdPs *InstancePtr, u32 SelFreq) +{ + u16 ClockReg; + s32 Status; + u32 Reg; + u32 Timeout = 1000U; + + /* Disable clock */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_CLK_CTRL_OFFSET, 0U); + + /* If selected frequency is zero, return from here */ + if (SelFreq == 0U) { + Status = XST_SUCCESS; + goto RETURN_PATH ; + } + +#ifdef VERSAL_NET + if (InstancePtr->CardType == XSDPS_CHIP_EMMC) { + Reg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_PHYCTRLREG2_OFFSET); + Reg &= ~XSDPS_PHYREG2_DLL_EN_MASK; + if ((InstancePtr->Mode != XSDPS_DEFAULT_SPEED_MODE) && + (SelFreq > XSDPD_MIN_DLL_MODE_CLK)) { + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, + XSDPS_PHYCTRLREG2_OFFSET, Reg); + Reg &= ~XSDPS_PHYREG2_FREQ_SEL_MASK; + Reg &= ~XSDPS_PHYREG2_TRIM_ICP_MASK; + Reg &= ~XSDPS_PHYREG2_DLYTX_SEL_MASK; + Reg &= ~XSDPS_PHYREG2_DLYRX_SEL_MASK; + Reg |= (XSDPS_PHYREG2_TRIM_ICP_DEF_VAL << + XSDPS_PHYREG2_TRIM_ICP_SHIFT); + if (SelFreq == XSDPS_MMC_DDR_MAX_CLK) { + Reg |= (XSDPS_FREQ_SEL_50MHZ_79MHz << + XSDPS_PHYREG2_FREQ_SEL_SHIFT); + } + + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, + XSDPS_PHYCTRLREG2_OFFSET, Reg); + } else { + Reg |= XSDPS_PHYREG2_DLYTX_SEL_MASK; + Reg |= XSDPS_PHYREG2_DLYRX_SEL_MASK; + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, + XSDPS_PHYCTRLREG2_OFFSET, Reg); + } + } +#endif + + /* Calculate the clock */ + ClockReg = (u16)XSdPs_CalcClock(InstancePtr, SelFreq); + + /* Enable the clock in the controller */ + Status = XSdPs_EnableClock(InstancePtr, ClockReg); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + +#ifdef VERSAL_NET + if ((InstancePtr->CardType == XSDPS_CHIP_EMMC) && + (InstancePtr->Mode != XSDPS_DEFAULT_SPEED_MODE) && + (SelFreq > XSDPD_MIN_DLL_MODE_CLK)) { + Reg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_PHYCTRLREG2_OFFSET); + Reg |= XSDPS_PHYREG2_DLL_EN_MASK; + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, + XSDPS_PHYCTRLREG2_OFFSET, Reg); + + /* Wait for 1000 micro sec for DLL READY */ + Status = Xil_WaitForEvent(InstancePtr->Config.BaseAddress + XSDPS_PHYCTRLREG2_OFFSET, + XSDPS_PHYREG2_DLL_RDY_MASK, XSDPS_PHYREG2_DLL_RDY_MASK, Timeout); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + } +#else + (void)Reg; + (void)Timeout; +#endif + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function checks if the voltage is set to 1.8V or not. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if voltage is 1.8V +* - XST_FAILURE if voltage is not 1.8V +* +******************************************************************************/ +s32 XSdPs_CheckVoltage18(XSdPs *InstancePtr) +{ + u32 Status; + + if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_1V8_EN_MASK) == 0U) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function initializes the command sequence. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Arg is the address passed by the user that is to be sent as +* argument along with the command. +* @param BlkCnt - Block count passed by the user. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_SetupCmd(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt) +{ + s32 Status; + + /* + * Check the command inhibit to make sure no other + * command transfer is in progress + */ + Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + /* Write block count register */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_BLK_CNT_OFFSET, (u16)BlkCnt); + + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_TIMEOUT_CTRL_OFFSET, 0xEU); + + /* Write argument register */ + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, + XSDPS_ARGMT_OFFSET, Arg); + + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK); + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function initiates the Cmd transfer to SD card. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cmd is the command to be sent +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure +* +******************************************************************************/ +s32 XSdPs_SendCmd(XSdPs *InstancePtr, u32 Cmd) +{ + u32 PresentStateReg; + u32 CommandReg; + s32 Status; + + /* Command register is set to trigger transfer of command */ + CommandReg = XSdPs_FrameCmd(InstancePtr, Cmd); + + /* + * Mask to avoid writing to reserved bits 31-30 + * This is necessary because 0x8000 is used by this software to + * distinguish between ACMD and CMD of same number + */ + CommandReg = CommandReg & 0x3FFFU; + + /* + * Check for data inhibit in case of command using DAT lines. + * For Tuning Commands DAT lines check can be ignored. + */ + if ((Cmd != CMD21) && (Cmd != CMD19)) { + PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_PRES_STATE_OFFSET); + if (((PresentStateReg & XSDPS_PSR_INHIBIT_DAT_MASK) != 0U) && + ((CommandReg & XSDPS_DAT_PRESENT_SEL_MASK) != 0U)) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET, + (CommandReg << 16) | InstancePtr->TransferMode); + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* @brief +* This function performs Set the address of the first write block to be erased. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param StartAddr is the address of the first write block. +* +* @return +* - XST_SUCCESS if Set start Address is successful +* - XST_FAILURE if failure - could be because failed to set EndAddr. +* +******************************************************************************/ +s32 XSdPs_SetStartAddr(XSdPs *InstancePtr, u32 StartAddr) +{ + s32 Status; + + if (InstancePtr->CardType == XSDPS_CARD_SD) { + Status = XSdPs_CmdTransfer(InstancePtr, CMD32, StartAddr, 0U); + } else { + Status = XSdPs_CmdTransfer(InstancePtr, CMD35, StartAddr, 0U); + } + + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function performs Set the address of the last write block to be erased. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param EndAddr is the address of the last write block. +* +* @return +* - XST_SUCCESS if Set End Address is successful. +* - XST_FAILURE if failure - could be because failed to set EndAddr. +* +******************************************************************************/ +s32 XSdPs_SetEndAddr(XSdPs *InstancePtr, u32 EndAddr) +{ + s32 Status; + + if (InstancePtr->CardType == XSDPS_CARD_SD) { + Status = XSdPs_CmdTransfer(InstancePtr, CMD33, EndAddr, 0U); + } else { + Status = XSdPs_CmdTransfer(InstancePtr, CMD36, EndAddr, 0U); + } + + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function send Erase command to the device and wait for transfer complete +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if erase operation is successful +* - XST_FAILURE if failure - could be because erase operation failed. +* +******************************************************************************/ +s32 XSdPs_SendErase(XSdPs *InstancePtr) +{ + s32 Status; + + Status = XSdPs_CmdTransfer(InstancePtr, CMD38, 0U, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + /* Check for transfer done */ + Status = XSdps_CheckTransferDone(InstancePtr); + +RETURN_PATH: + return Status; +} + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_core.h b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_core.h new file mode 100644 index 0000000..239c2f1 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_core.h @@ -0,0 +1,127 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps_core.h +* @addtogroup sdps Overview +* @{ +* +* The xsdps_core.h header file contains the identifiers and basic HW access driver +* functions (or macros) that can be used to access the device. Other driver +* functions are defined in xsdps.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 3.9   mn     03/03/20 Restructured the code for more readability and modularity
+*       mn     03/16/20 Move XSdPs_Select_Card API to User APIs
+* 3.12  sk     01/28/21 Added support for non-blocking write.
+* 3.14  sk     10/22/21 Add support for Erase feature.
+*       mn     11/28/21 Fix MISRA-C violations.
+* 4.0   sk     02/25/22 Add support for eMMC5.1.
+* 4.1   sa     01/06/23 Include xil_util.h in this file.
+* 
+* +******************************************************************************/ + +/** @cond INTERNAL */ +#ifndef SDPS_INCLUDE_H_ +#define SDPS_INCLUDE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xsdps.h" +#if defined (__aarch64__) +#include "xil_smc.h" +#endif + +#include "xil_util.h" + +s32 XSdPs_SdCardInitialize(XSdPs *InstancePtr); +s32 XSdPs_MmcCardInitialize(XSdPs *InstancePtr); +s32 XSdPs_IdentifyCard(XSdPs *InstancePtr); +s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt); +s32 XSdPs_SetupTransfer(XSdPs *InstancePtr); +s32 XSdPs_Read(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff); +s32 XSdPs_Write(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff); +s32 XSdPs_CheckTransferComplete(XSdPs *InstancePtr); +void XSdPs_Identify_UhsMode(XSdPs *InstancePtr, u8 *ReadBuff); +s32 XSdPs_DllReset(XSdPs *InstancePtr); +s32 XSdPs_Switch_Voltage(XSdPs *InstancePtr); +void XSdPs_SetupADMA2DescTbl64Bit(XSdPs *InstancePtr, u32 BlkCnt); +void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff); +void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst); +void XSdPs_ConfigTapDelay(XSdPs *InstancePtr); +s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr); +void XSdPs_Setup32ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff); +void XSdPs_Setup64ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff); +u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd); +void XSdPs_SetTapDelay(XSdPs *InstancePtr); +s32 XSdPs_CheckResetDone(XSdPs *InstancePtr, u8 Value); +s32 XSdPs_CheckVoltage18(XSdPs *InstancePtr); +s32 XSdPs_SetupCmd(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt); +void XSdPs_SetExecTuning(XSdPs *InstancePtr); +s32 XSdPs_CheckCardDetect(XSdPs *InstancePtr); +s32 XSdPs_CardReset(XSdPs *InstancePtr); +s32 XSdPs_CardIfCond(XSdPs *InstancePtr); +s32 XSdPs_CardOpCond(XSdPs *InstancePtr); +s32 XSdPs_GetCardId(XSdPs *InstancePtr); +s32 XSdPs_GetCsd(XSdPs *InstancePtr); +s32 XSdPs_CardSetVoltage18(XSdPs *InstancePtr); +s32 XSdPs_SdModeInit(XSdPs *InstancePtr); +s32 XSdPs_SdCardEnum(XSdPs *InstancePtr); +s32 XSdPs_MmcCardEnum(XSdPs *InstancePtr); +s32 XSdPs_MmcModeInit(XSdPs *InstancePtr); +s32 XSdPs_EmmcModeInit(XSdPs *InstancePtr); +s32 XSdPs_ResetConfig(XSdPs *InstancePtr); +void XSdPs_HostConfig(XSdPs *InstancePtr); +s32 XSdPs_Reset(XSdPs *InstancePtr, u8 Value); +void XSdPs_DisableBusPower(XSdPs *InstancePtr); +void XSdPs_EnableBusPower(XSdPs *InstancePtr); +s32 XSdPs_CheckBusIdle(XSdPs *InstancePtr, u32 Value); +s32 XSdPs_CheckBusHigh(XSdPs *InstancePtr); +s32 XSdPs_SetupVoltageSwitch(XSdPs *InstancePtr); +s32 XSdPs_AutoTuning(XSdPs *InstancePtr); +s32 XSdPs_SetClock(XSdPs *InstancePtr, u32 SelFreq); +u32 XSdPs_CalcClock(XSdPs *InstancePtr, u32 SelFreq); +s32 XSdPs_EnableClock(XSdPs *InstancePtr, u16 ClockReg); +s32 XSdps_CheckTransferDone(XSdPs *InstancePtr); +s32 XSdPs_Change_SdBusSpeed(XSdPs *InstancePtr); +s32 XSdPs_Change_MmcBusSpeed(XSdPs *InstancePtr); +s32 XSdPs_CalcBusSpeed(XSdPs *InstancePtr, u32 *Arg); +void XSdPs_SetupReadDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, u8 *Buff); +void XSdPs_SetupWriteDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, const u8 *Buff); +s32 XSdPs_SetVoltage18(XSdPs *InstancePtr); +s32 XSdPs_SendCmd(XSdPs *InstancePtr, u32 Cmd); +void XSdPs_IdentifyEmmcMode(XSdPs *InstancePtr, const u8 *ExtCsd); +s32 XSdPs_CheckEmmcTiming(XSdPs *InstancePtr, u8 *ExtCsd); +void XSdPs_ConfigPower(XSdPs *InstancePtr); +void XSdPs_ConfigDma(XSdPs *InstancePtr); +void XSdPs_ConfigInterrupt(XSdPs *InstancePtr); +s32 XSdPs_SendErase(XSdPs *InstancePtr); +s32 XSdPs_SetEndAddr(XSdPs *InstancePtr, u32 EndAddr); +s32 XSdPs_SetStartAddr(XSdPs *InstancePtr, u32 StartAddr); +#ifdef VERSAL_NET +u32 XSdPs_Select_HS400(XSdPs *InstancePtr); +#endif + +#if defined (__aarch64__) && (EL1_NONSECURE == 1) +void XSdps_Smc(XSdPs *InstancePtr, u32 RegOffset, u32 Mask, u32 Val); +#endif + +#ifdef __cplusplus +} +#endif + +#endif +/** @endcond */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_g.c new file mode 100644 index 0000000..8c533f0 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_g.c @@ -0,0 +1,60 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps_g.c +* @addtogroup sdps Overview +* @{ +* +* The xsdps_g.c file contains a configuration table that specifies the +* configuration of SD devices in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 1.00a hk/sg  10/17/13 Initial release
+* 3.6   mn     07/06/18 Add initialization macros in sdps
+*       mn     07/13/18 Add initializer macro for HasEMIO
+*
+* 
+* +******************************************************************************/ + + + +#include "xparameters.h" +#include "xsdps.h" + +/** + * The configuration table for devices + */ + +XSdPs_Config XSdPs_ConfigTable[] = +{ + { + XPAR_XSDPS_0_DEVICE_ID, + XPAR_XSDPS_0_BASEADDR, + XPAR_XSDPS_0_SDIO_CLK_FREQ_HZ, + XPAR_XSDPS_0_HAS_CD, + XPAR_XSDPS_0_HAS_WP, + XPAR_XSDPS_0_BUS_WIDTH, + XPAR_XSDPS_0_MIO_BANK, + XPAR_XSDPS_0_HAS_EMIO, + XPAR_XSDPS_0_SLOT_TYPE, + XPAR_XSDPS_0_IS_CACHE_COHERENT, + XPAR_XSDPS_0_CLK_50_SDR_ITAP_DLY, + XPAR_XSDPS_0_CLK_50_SDR_OTAP_DLY, + XPAR_XSDPS_0_CLK_50_DDR_ITAP_DLY, + XPAR_XSDPS_0_CLK_50_DDR_OTAP_DLY, + XPAR_XSDPS_0_CLK_100_SDR_OTAP_DLY, + XPAR_XSDPS_0_CLK_200_SDR_OTAP_DLY + } +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_host.c b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_host.c new file mode 100644 index 0000000..5f4165c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_host.c @@ -0,0 +1,1795 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps_host.c +* @addtogroup sdps Overview +* @{ +* +* The xsdps_host.c file contains the interface functions of the XSdPs driver. +* See xsdps.h for a detailed description of the device and driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 3.9   mn     03/03/20 Restructured the code for more readability and modularity
+*       mn     03/16/20 Add code to get card ID for MMC/eMMC
+* 3.10  mn     07/09/20 Modified code to prevent removing pull up on D3 line
+*       mn     07/30/20 Read 16Bit value for Block Size Register
+* 3.11  sk     12/01/20 Tap programming sequence updates like disable OTAPEN
+*                       always, write zero to tap register for zero tap value.
+*       sk     12/17/20 Removed checking platform specific SD macros and used
+*                       Baseaddress instead.
+* 3.13  sk     08/10/21 Limit the SD operating frequency to 19MHz for Versal.
+* 3.14  sk     10/22/21 Add support for Erase feature.
+*       mn     11/28/21 Fix MISRA-C violations.
+*       sk     01/10/22 Add support to read slot_type parameter.
+* 4.0   sk     02/25/22 Add support for eMMC5.1.
+*       sk     04/07/22 Add support to read custom tap delay values from design
+*                       for SD/eMMC.
+*       sk     06/03/22 Fix issue in internal clock divider calculation logic.
+* 4.1   sk     11/10/22 Add SD/eMMC Tap delay support for Versal Net.
+* 	sa     01/04/23	Update register bit polling logic to use Xil_WaitForEvent/
+* 			Xil_WaitForEvents API.
+* 	sa     01/25/23 Use instance structure to store DMA descriptor tables.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xsdps_core.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +#if defined (__aarch64__) && (EL1_NONSECURE == 1) +void XSdps_Smc(XSdPs *InstancePtr, u32 RegOffset, u32 Mask, u32 Val) +{ + (void)Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(InstancePtr->SlcrBaseAddr + + RegOffset) | ((u64)Mask << 32), + (u64)Val, 0, 0, 0, 0, 0); +} +#endif + +/*****************************************************************************/ +/** +* +* @brief +* Switches the SD card voltage from 3v3 to 1v8 +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +******************************************************************************/ +s32 XSdPs_Switch_Voltage(XSdPs *InstancePtr) +{ + s32 Status; + + /* Setup the voltage switching sequence */ + Status = XSdPs_SetupVoltageSwitch(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Set the card voltage to 1.8V */ + Status = XSdPs_CardSetVoltage18(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check if the bus is high */ + Status = XSdPs_CheckBusHigh(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function initiates the transfer to or from SD card. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure +* +******************************************************************************/ +s32 XSdPs_SetupTransfer(XSdPs *InstancePtr) +{ + u32 PresentStateReg; + s32 Status; + + if ((InstancePtr->HC_Version != XSDPS_HC_SPEC_V3) || + ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK) + != XSDPS_CAPS_EMB_SLOT)) { + if(InstancePtr->Config.CardDetect != 0U) { + /* Check status to ensure card is initialized */ + PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_PRES_STATE_OFFSET); + if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + } + + /* Set block size to 512 if not already set */ + if(XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) { + Status = XSdPs_SetBlkSize(InstancePtr, + XSDPS_BLK_SIZE_512_MASK); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* @brief +* This function resets the SD card. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Value is the type of reset +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure +* +******************************************************************************/ +s32 XSdPs_Reset(XSdPs *InstancePtr, u8 Value) +{ + s32 Status; + + /* "Software reset for all" is initiated */ + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET, + Value); + + Status = XSdPs_CheckResetDone(InstancePtr, Value); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function sets bit to start execution of tuning. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +void XSdPs_SetExecTuning(XSdPs *InstancePtr) +{ + u16 CtrlReg; + + CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET); + CtrlReg |= XSDPS_HC2_EXEC_TNG_MASK; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET, CtrlReg); +} + +/*****************************************************************************/ +/** +* @brief +* This function does SD mode initialization. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if initialization is successful +* - XST_FAILURE if failure +* +******************************************************************************/ +s32 XSdPs_SdModeInit(XSdPs *InstancePtr) +{ + s32 Status; +#ifdef __ICCARM__ +#pragma data_alignment = 32 + static u8 SCR[8] = { 0U }; +#else + static u8 SCR[8] __attribute__ ((aligned(32))) = { 0U }; +#endif +#if SD_HS_MODE_ENABLE + u8 ReadBuff[64] = { 0U }; +#endif + + Status = XSdPs_Get_BusWidth(InstancePtr, SCR); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if ((SCR[1] & WIDTH_4_BIT_SUPPORT) != 0U) { + InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH; + Status = XSdPs_Change_BusWidth(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + +#if SD_HS_MODE_ENABLE + /* Get speed supported by device */ + Status = XSdPs_Get_BusSpeed(InstancePtr, ReadBuff); + if (Status != XST_SUCCESS) { + goto RETURN_PATH; + } + + if (((SCR[2] & SCR_SPEC_VER_3) != 0U) && + (ReadBuff[13] >= UHS_SDR50_SUPPORT) && + (InstancePtr->Config.BusWidth == XSDPS_WIDTH_8) && + (InstancePtr->Switch1v8 == 0U)) { + + InstancePtr->Switch1v8 = 1U; + + Status = XSdPs_CardSetVoltage18(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + if (InstancePtr->Switch1v8 != 0U) { + + /* Identify the UHS mode supported by card */ + XSdPs_Identify_UhsMode(InstancePtr, ReadBuff); + + Status = XSdPs_Change_BusSpeed(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else { + /* + * card supports CMD6 when SD_SPEC field in SCR register + * indicates that the Physical Layer Specification Version + * is 1.10 or later. So for SD v1.0 cmd6 is not supported. + */ + if (SCR[0] != 0U) { + /* Check for high speed support */ + if (((ReadBuff[13] & HIGH_SPEED_SUPPORT) != 0U) && + (InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH)) { + InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE; + if (InstancePtr->Config.OTapDly_SDR_Clk50 && + InstancePtr->Config.ITapDly_SDR_Clk50) { + InstancePtr->OTapDelay = InstancePtr->Config.OTapDly_SDR_Clk50; + InstancePtr->ITapDelay = InstancePtr->Config.ITapDly_SDR_Clk50; + if ((InstancePtr->Config.SlotType == XSDPS_SLOTTYPE_SDADIR) && + (InstancePtr->ITapDelay == SD_ITAPDLYSEL_HSD)) { + InstancePtr->ITapDelay = SD_AUTODIR_ITAPDLYSEL_HSD; + } + } else if (InstancePtr->Config.SlotType == XSDPS_SLOTTYPE_SDADIR) { + InstancePtr->ITapDelay = SD_AUTODIR_ITAPDLYSEL_HSD; + InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD; + } else { + InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD; + InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD; + } + + Status = XSdPs_Change_BusSpeed(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + } + } +#endif + + Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function does MMC mode initialization. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if initialization is successful +* - XST_FAILURE if failure +* +******************************************************************************/ +s32 XSdPs_MmcModeInit(XSdPs *InstancePtr) +{ + s32 Status; +#ifdef __ICCARM__ +#pragma data_alignment = 32 + static u8 ExtCsd[512]; +#else + static u8 ExtCsd[512] __attribute__ ((aligned(32))); +#endif + + InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH; + Status = XSdPs_Change_BusWidth(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + InstancePtr->SectorCount = ((u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE4]) << 24; + InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE3] << 16; + InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE2] << 8; + InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE1]; + + if (((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] & + EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) && + (InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH)) { + InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE; + Status = XSdPs_Change_BusSpeed(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function does eMMC mode initialization. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if initialization is successful +* - XST_FAILURE if failure +* +******************************************************************************/ +s32 XSdPs_EmmcModeInit(XSdPs *InstancePtr) +{ + s32 Status; + +#ifdef __ICCARM__ +#pragma data_alignment = 32 + static u8 ExtCsd[512]; +#else + static u8 ExtCsd[512] __attribute__ ((aligned(32))); +#endif + + if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) && + (InstancePtr->Config.BusWidth == XSDPS_WIDTH_8)) { + /* in case of eMMC data width 8-bit */ + InstancePtr->BusWidth = XSDPS_8_BIT_WIDTH; + } else if (InstancePtr->Config.BusWidth == XSDPS_WIDTH_4) { + /* in case of eMMC data width 4-bit */ + InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH; + } else { + /* in case of eMMC data width 1-bit */ + InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH; + } + + Status = XSdPs_Change_BusWidth(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Get Extended CSD */ + Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + InstancePtr->SectorCount = ((u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE4]) << 24; + InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE3] << 16; + InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE2] << 8; + InstancePtr->SectorCount |= (u32)ExtCsd[EXT_CSD_SEC_COUNT_BYTE1]; + + XSdPs_IdentifyEmmcMode(InstancePtr, ExtCsd); + + if (InstancePtr->Mode != XSDPS_DEFAULT_SPEED_MODE) { + Status = XSdPs_Change_BusSpeed(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_CheckEmmcTiming(InstancePtr, ExtCsd); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (InstancePtr->Mode == XSDPS_DDR52_MODE) { + Status = XSdPs_Change_BusWidth(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + } + + /* Enable Rst_n_Fun bit if it is disabled */ + if(ExtCsd[EXT_CSD_RST_N_FUN_BYTE] == EXT_CSD_RST_N_FUN_TEMP_DIS) { + Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, XSDPS_MMC_RST_FUN_EN_ARG); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function disables the bus power. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +void XSdPs_DisableBusPower(XSdPs *InstancePtr) +{ + /* Disable SD bus power and issue eMMC HW reset */ + if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) { + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_POWER_CTRL_OFFSET, XSDPS_PC_EMMC_HW_RST_MASK); + } else { + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_POWER_CTRL_OFFSET, 0x0); + } + + /* 1ms delay to poweroff card */ + (void)usleep(1000U); +} + +/*****************************************************************************/ +/** +* @brief +* This function enables the bus power. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +void XSdPs_EnableBusPower(XSdPs *InstancePtr) +{ + /* Select voltage and enable bus power. */ + if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) { + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_POWER_CTRL_OFFSET, + (XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK) & + ~XSDPS_PC_EMMC_HW_RST_MASK); + } else { + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_POWER_CTRL_OFFSET, + XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK); + } + + /* 0.2ms Delay after bus power on*/ + usleep(200); +} + +/*****************************************************************************/ +/** +* @brief +* This function enumerates the SD card. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_SdCardEnum(XSdPs *InstancePtr) +{ + s32 Status; + + /* Check if the card is present */ + Status = XSdPs_CheckCardDetect(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Reset the SD card */ + Status = XSdPs_CardReset(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Get the card interface condition */ + Status = XSdPs_CardIfCond(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Get the card operating condition */ + Status = XSdPs_CardOpCond(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Get the card ID */ + Status = XSdPs_GetCardId(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Get the CSD register */ + Status = XSdPs_GetCsd(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Change clock to default clock 25MHz */ + /* + * SD default speed mode timing should be closed at 19 MHz. + * The reason for this is SD requires a voltage level shifter. + * This limitation applies to ZynqMPSoC. + */ + if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) { + InstancePtr->BusSpeed = SD_CLK_19_MHZ; + } else { + InstancePtr->BusSpeed = SD_CLK_25_MHZ; + } + Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Select the card to transition to transfer state */ + Status = XSdPs_Select_Card(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XST_SUCCESS; + + RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function enumerates the MMC card. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_MmcCardEnum(XSdPs *InstancePtr) +{ + s32 Status; + + /* Check if the card is preset */ + Status = XSdPs_CheckCardDetect(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Reset the card */ + Status = XSdPs_CardReset(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Get the card operating condition */ + Status = XSdPs_CardOpCond(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Get the card ID */ + Status = XSdPs_GetCardId(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Get the CSD register */ + Status = XSdPs_GetCsd(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Change clock to default clock 26MHz */ + InstancePtr->BusSpeed = SD_CLK_26_MHZ; + Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Send select card command to transition to transfer state */ + Status = XSdPs_Select_Card(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function performs SD tuning. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr) +{ + s32 Status; + +#if !defined (versal) && !defined (VERSAL_NET) + /* Issue DLL Reset to load new SDHC tuned tap values */ + Status = XSdPs_DllReset(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + +#endif + + /* Perform the auto tuning */ + Status = XSdPs_AutoTuning(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + +#if !defined (versal) && !defined (VERSAL_NET) + /* Issue DLL Reset to load new SDHC tuned tap values */ + Status = XSdPs_DllReset(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + +#endif + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to enable the clock. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param ClockReg is the clock value to be set. +* +* @return +* - XST_SUCCESS if success +* - XST_FAILURE if failure +* +******************************************************************************/ +s32 XSdPs_EnableClock(XSdPs *InstancePtr, u16 ClockReg) +{ + u32 Timeout = 150000U; + s32 Status; + u16 ClkReg = ClockReg; + + ClkReg |= (u16)XSDPS_CC_INT_CLK_EN_MASK; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_CLK_CTRL_OFFSET, ClkReg); + + /* Wait for 150ms for internal clock to stabilize */ + Status = Xil_WaitForEvent(InstancePtr->Config.BaseAddress + XSDPS_CLK_CTRL_OFFSET, + XSDPS_CC_INT_CLK_STABLE_MASK, XSDPS_CC_INT_CLK_STABLE_MASK, Timeout); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + /* Enable SD clock */ + ClkReg |= XSDPS_CC_SD_CLK_EN_MASK; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_CLK_CTRL_OFFSET, ClkReg); + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to calculate the bus speed. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Arg is the argument to be sent along with the command. +* This could be address or any other information +* +* @return +* - XST_SUCCESS if success +* - XST_FAILURE if failure +* +******************************************************************************/ +s32 XSdPs_CalcBusSpeed(XSdPs *InstancePtr, u32 *Arg) +{ + s32 Status = XST_SUCCESS; + + if (InstancePtr->CardType == XSDPS_CARD_SD) { + switch (InstancePtr->Mode) { + case XSDPS_UHS_SPEED_MODE_SDR12: + *Arg = XSDPS_SWITCH_CMD_SDR12_SET; + InstancePtr->BusSpeed = XSDPS_SD_SDR12_MAX_CLK; + break; + case XSDPS_UHS_SPEED_MODE_SDR25: + *Arg = XSDPS_SWITCH_CMD_SDR25_SET; + InstancePtr->BusSpeed = XSDPS_SD_SDR25_MAX_CLK; + break; + case XSDPS_UHS_SPEED_MODE_SDR50: + *Arg = XSDPS_SWITCH_CMD_SDR50_SET; + InstancePtr->BusSpeed = XSDPS_SD_SDR50_MAX_CLK; + break; + case XSDPS_UHS_SPEED_MODE_SDR104: + *Arg = XSDPS_SWITCH_CMD_SDR104_SET; + InstancePtr->BusSpeed = XSDPS_SD_SDR104_MAX_CLK; + break; + case XSDPS_UHS_SPEED_MODE_DDR50: + *Arg = XSDPS_SWITCH_CMD_DDR50_SET; + InstancePtr->BusSpeed = XSDPS_SD_DDR50_MAX_CLK; + break; + case XSDPS_HIGH_SPEED_MODE: + *Arg = XSDPS_SWITCH_CMD_HS_SET; + InstancePtr->BusSpeed = XSDPS_CLK_50_MHZ; + break; + default: + Status = XST_FAILURE; + break; + } + } else { + switch (InstancePtr->Mode) { +#ifdef VERSAL_NET + case XSDPS_HS400_MODE: + if (InstancePtr->IsTuningDone == 0U) { + *Arg = XSDPS_MMC_HS200_ARG; + } else { + *Arg = XSDPS_MMC_HS400_ARG; + } + InstancePtr->BusSpeed = XSDPS_MMC_HS200_MAX_CLK; + break; +#endif + case XSDPS_HS200_MODE: + *Arg = XSDPS_MMC_HS200_ARG; + InstancePtr->BusSpeed = XSDPS_MMC_HS200_MAX_CLK; + break; + case XSDPS_DDR52_MODE: + *Arg = XSDPS_MMC_HIGH_SPEED_ARG; + InstancePtr->BusSpeed = XSDPS_MMC_DDR_MAX_CLK; + break; + case XSDPS_HIGH_SPEED_MODE: + *Arg = XSDPS_MMC_HIGH_SPEED_ARG; + InstancePtr->BusSpeed = XSDPS_MMC_HSD_MAX_CLK; + break; + default: + Status = XST_FAILURE; + break; + } + } + + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to do the DMA transfer to or from SD card. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param BlkCnt - Block count passed by the user. +* @param BlkSize - Block size passed by the user. +* @param Buff - Pointer to the data buffer for a DMA transfer. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure - could be because another transfer +* is in progress or command or data inhibit is set +* +******************************************************************************/ +void XSdPs_SetupReadDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, u8 *Buff) +{ + BlkSize &= XSDPS_BLK_SIZE_MASK; + + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_BLK_SIZE_OFFSET, BlkSize); + + if (InstancePtr->Dma64BitAddr >= ADDRESS_BEYOND_32BIT) { + XSdPs_SetupADMA2DescTbl64Bit(InstancePtr, BlkCnt); + } else { + XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff); + if (InstancePtr->Config.IsCacheCoherent == 0U) { + Xil_DCacheInvalidateRange((INTPTR)Buff, + ((INTPTR)BlkCnt * (INTPTR)BlkSize)); + } + } + + if (BlkCnt == 1U) { + InstancePtr->TransferMode = XSDPS_TM_BLK_CNT_EN_MASK | + XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK; + } else { + InstancePtr->TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK | + XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DAT_DIR_SEL_MASK | + XSDPS_TM_DMA_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK; + } +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to do the DMA transfer to or from SD card. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param BlkCnt - Block count passed by the user. +* @param BlkSize - Block size passed by the user. +* @param Buff - Pointer to the data buffer for a DMA transfer. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure - could be because another transfer +* is in progress or command or data inhibit is set +* +******************************************************************************/ +void XSdPs_SetupWriteDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, const u8 *Buff) +{ + BlkSize &= XSDPS_BLK_SIZE_MASK; + + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_BLK_SIZE_OFFSET, BlkSize); + + if (InstancePtr->Dma64BitAddr >= ADDRESS_BEYOND_32BIT) { + XSdPs_SetupADMA2DescTbl64Bit(InstancePtr, BlkCnt); + } else { + XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff); + if (InstancePtr->Config.IsCacheCoherent == 0U) { + Xil_DCacheFlushRange((INTPTR)Buff, + ((INTPTR)BlkCnt * (INTPTR)BlkSize)); + } + } + + if (BlkCnt == 1U) { + InstancePtr->TransferMode = XSDPS_TM_BLK_CNT_EN_MASK | + XSDPS_TM_DMA_EN_MASK; + } else { + InstancePtr->TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK | + XSDPS_TM_BLK_CNT_EN_MASK | + XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK; + } +} + +/*****************************************************************************/ +/** +* +* @brief +* API to setup ADMA2 descriptor table for 32-bit DMA +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param BlkCnt - block count. +* @param Buff pointer to data buffer. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XSdPs_Setup32ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff) +{ + u32 TotalDescLines; + u32 DescNum; + u32 BlkSize; + + /* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */ + BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_BLK_SIZE_OFFSET) & + XSDPS_BLK_SIZE_MASK; + + if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) { + TotalDescLines = 1U; + } else { + TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH); + if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) { + TotalDescLines += 1U; + } + } + + for (DescNum = 0U; DescNum < (TotalDescLines - 1U); DescNum++) { + InstancePtr->Adma2_DescrTbl32[DescNum].Address = + (u32)((UINTPTR)Buff + ((UINTPTR)DescNum*XSDPS_DESC_MAX_LENGTH)); + InstancePtr->Adma2_DescrTbl32[DescNum].Attribute = + XSDPS_DESC_TRAN | XSDPS_DESC_VALID; + InstancePtr->Adma2_DescrTbl32[DescNum].Length = 0U; + } + + InstancePtr->Adma2_DescrTbl32[TotalDescLines - 1U].Address = + (u32)((UINTPTR)Buff + ((UINTPTR)DescNum*XSDPS_DESC_MAX_LENGTH)); + + InstancePtr->Adma2_DescrTbl32[TotalDescLines - 1U].Attribute = + XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID; + + InstancePtr->Adma2_DescrTbl32[TotalDescLines - 1U].Length = + (u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH)); + + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET, + (u32)((UINTPTR)&(InstancePtr->Adma2_DescrTbl32[0]) & ~(u32)0x0U)); + + if (InstancePtr->Config.IsCacheCoherent == 0U) { + Xil_DCacheFlushRange((INTPTR)&(InstancePtr->Adma2_DescrTbl32[0]), + (INTPTR)sizeof(XSdPs_Adma2Descriptor32) * (INTPTR)32U); + } +} + +/*****************************************************************************/ +/** +* +* @brief +* API to setup ADMA2 descriptor table for 64-bit DMA +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param BlkCnt - block count. +* @param Buff pointer to data buffer. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XSdPs_Setup64ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff) +{ + u32 TotalDescLines; + u32 DescNum; + u32 BlkSize; + + /* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */ + BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_BLK_SIZE_OFFSET) & + XSDPS_BLK_SIZE_MASK; + + if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) { + TotalDescLines = 1U; + } else { + TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH); + if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) { + TotalDescLines += 1U; + } + } + + for (DescNum = 0U; DescNum < (TotalDescLines - 1U); DescNum++) { + InstancePtr->Adma2_DescrTbl64[DescNum].Address = + ((UINTPTR)Buff + ((UINTPTR)DescNum*XSDPS_DESC_MAX_LENGTH)); + InstancePtr->Adma2_DescrTbl64[DescNum].Attribute = + XSDPS_DESC_TRAN | XSDPS_DESC_VALID; + InstancePtr->Adma2_DescrTbl64[DescNum].Length = 0U; + } + + InstancePtr->Adma2_DescrTbl64[TotalDescLines - 1U].Address = + (u64)((UINTPTR)Buff + ((UINTPTR)DescNum*XSDPS_DESC_MAX_LENGTH)); + + InstancePtr->Adma2_DescrTbl64[TotalDescLines - 1U].Attribute = + XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID; + + InstancePtr->Adma2_DescrTbl64[TotalDescLines - 1U].Length = + (u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH)); + +#if defined(__aarch64__) || defined(__arch64__) + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_EXT_OFFSET, + (u32)((UINTPTR)(InstancePtr->Adma2_DescrTbl64)>>32U)); +#endif + + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET, + (u32)((UINTPTR)&(InstancePtr->Adma2_DescrTbl64[0]) & ~(u32)0x0U)); + + if (InstancePtr->Config.IsCacheCoherent == 0U) { + Xil_DCacheFlushRange((INTPTR)&(InstancePtr->Adma2_DescrTbl64[0]), + (INTPTR)sizeof(XSdPs_Adma2Descriptor64) * (INTPTR)32U); + } +} + +/*****************************************************************************/ +/** +* @brief +* This function is used calculate the clock divisor value. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param SelFreq is the selected frequency +* +* @return Clock divisor value +* +******************************************************************************/ +u32 XSdPs_CalcClock(XSdPs *InstancePtr, u32 SelFreq) +{ + u16 ClockVal = 0U; + u16 DivCnt; + u16 Divisor = 0U; + + if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) { + /* Calculate divisor */ + if (InstancePtr->Config.InputClockHz <= SelFreq) { + Divisor = 0U; + } else { + for (DivCnt = 2U; DivCnt <= XSDPS_CC_EXT_MAX_DIV_CNT; DivCnt += 2U) { + if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) { + Divisor = DivCnt >> 1; + break; + } + } + } + } else { + /* Calculate divisor */ + for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_MAX_DIV_CNT; DivCnt <<= 1U) { + if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) { + Divisor = DivCnt / 2U; + break; + } + } + } + + ClockVal |= (Divisor & XSDPS_CC_SDCLK_FREQ_SEL_MASK) << XSDPS_CC_DIV_SHIFT; + ClockVal |= ((Divisor >> 8U) & XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK) << XSDPS_CC_EXT_DIV_SHIFT; + + return ClockVal; +} + +/*****************************************************************************/ +/** +* +* @brief +* API to Set or Reset the DLL +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param EnRst is a flag indicating whether to Assert or De-assert Reset. +* +* @return None +* +* @note This API is specific to ZynqMP platform. +* +******************************************************************************/ +void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst) +{ +#ifndef versal + u32 BaseAddress; + u32 DllCtrl; + + BaseAddress = InstancePtr->Config.BaseAddress; + if (BaseAddress == XSDPS_ZYNQMP_SD0_BASE) { +#if defined (__aarch64__) && (EL1_NONSECURE == 1) + (void)DllCtrl; + + XSdps_Smc(InstancePtr, SD_DLL_CTRL, SD0_DLL_RST, (EnRst == 1U) ? SD0_DLL_RST : 0U); +#else + DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL); + if (EnRst == 1U) { + DllCtrl |= SD0_DLL_RST; + } else { + DllCtrl &= ~SD0_DLL_RST; + } + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL, DllCtrl); +#endif + } else { +#if defined (__aarch64__) && (EL1_NONSECURE == 1) + (void)DllCtrl; + + XSdps_Smc(InstancePtr, SD_DLL_CTRL, SD1_DLL_RST, (EnRst == 1U) ? SD1_DLL_RST : 0U); +#else + DllCtrl = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL); + if (EnRst == 1U) { + DllCtrl |= SD1_DLL_RST; + } else { + DllCtrl &= ~SD1_DLL_RST; + } + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_DLL_CTRL, DllCtrl); +#endif + } +#else + (void)InstancePtr; + (void)EnRst; +#endif +} + +/*****************************************************************************/ +/** +* +* @brief +* Function to configure the Tap Delays. +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XSdPs_ConfigTapDelay(XSdPs *InstancePtr) +{ + u32 BaseAddress; + u32 TapDelay; + u32 ITapDelay; + u32 OTapDelay; + + BaseAddress = InstancePtr->Config.BaseAddress; + TapDelay = 0U; + ITapDelay = InstancePtr->ITapDelay; + OTapDelay = InstancePtr->OTapDelay; + +#ifdef versal + (void) BaseAddress; + if (ITapDelay != 0U) { + TapDelay = SD_ITAPCHGWIN; + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay); + /* Program the ITAPDLY */ + TapDelay |= SD_ITAPDLYENA; + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay); + TapDelay |= ITapDelay; + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay); + TapDelay &= ~SD_ITAPCHGWIN; + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, TapDelay); + } else { + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_ITAPDLY, 0x0); + } + + /* Program the OTAPDLY */ + if (OTapDelay != 0U) { + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_OTAPDLY, OTapDelay); + } else { + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, SD_OTAPDLY, 0x0); + } +#else + if (BaseAddress == XSDPS_ZYNQMP_SD0_BASE) { +#if defined (__aarch64__) && (EL1_NONSECURE == 1) + (void)TapDelay; + if (ITapDelay != 0U) { + XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPCHGWIN, SD0_ITAPCHGWIN); + XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPDLYENA, SD0_ITAPDLYENA); + XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPDLY_SEL_MASK, ITapDelay); + XSdps_Smc(InstancePtr, SD_ITAPDLY, SD0_ITAPCHGWIN, 0U); + } else { + XSdps_Smc(InstancePtr, SD_ITAPDLY, (SD0_ITAPDLY_SEL_MASK | + SD0_ITAPCHGWIN | SD0_ITAPDLYENA), 0x0); + } + if (OTapDelay != 0U) { + XSdps_Smc(InstancePtr, SD_OTAPDLY, SD0_OTAPDLY_SEL_MASK, OTapDelay); + } else { + XSdps_Smc(InstancePtr, SD_OTAPDLY, SD0_OTAPDLY_SEL_MASK, 0x0); + } +#else + if (ITapDelay != 0U) { + TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY); + TapDelay |= SD0_ITAPCHGWIN; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay); + /* Program the ITAPDLY */ + TapDelay |= SD0_ITAPDLYENA; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay); + TapDelay &= ~SD0_ITAPDLY_SEL_MASK; + TapDelay |= ITapDelay; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay); + TapDelay &= ~SD0_ITAPCHGWIN; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay); + } else { + TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY); + TapDelay &= ~((u32)SD0_ITAPDLY_SEL_MASK | (u32)SD0_ITAPCHGWIN | (u32)SD0_ITAPDLYENA); + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay); + } + if (OTapDelay != 0U) { + /* Program the OTAPDLY */ + TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY); + TapDelay &= ~SD0_OTAPDLY_SEL_MASK; + TapDelay |= OTapDelay; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay); + } else { + TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY); + TapDelay &= ~SD0_OTAPDLY_SEL_MASK; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay); + } +#endif + } else { + ITapDelay = ITapDelay << 16U; + OTapDelay = OTapDelay << 16U; +#if defined (__aarch64__) && (EL1_NONSECURE == 1) + (void)TapDelay; + if (ITapDelay != 0U) { + XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPCHGWIN, SD1_ITAPCHGWIN); + XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPDLYENA, SD1_ITAPDLYENA); + XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPDLY_SEL_MASK, ITapDelay); + XSdps_Smc(InstancePtr, SD_ITAPDLY, SD1_ITAPCHGWIN, 0U); + } else { + XSdps_Smc(InstancePtr, SD_ITAPDLY, (SD1_ITAPDLY_SEL_MASK | + SD1_ITAPCHGWIN | SD1_ITAPDLYENA), 0x0); + } + if (OTapDelay != 0U) { + XSdps_Smc(InstancePtr, SD_OTAPDLY, SD1_OTAPDLY_SEL_MASK, OTapDelay); + } else { + XSdps_Smc(InstancePtr, SD_OTAPDLY, SD1_OTAPDLY_SEL_MASK, 0x0); + } +#else + if (ITapDelay != 0U) { + TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY); + TapDelay |= SD1_ITAPCHGWIN; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay); + /* Program the ITAPDLY */ + TapDelay |= SD1_ITAPDLYENA; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay); + TapDelay &= ~SD1_ITAPDLY_SEL_MASK; + TapDelay |= ITapDelay; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay); + TapDelay &= ~SD1_ITAPCHGWIN; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay); + } else { + TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY); + TapDelay &= ~(u32)(SD1_ITAPDLY_SEL_MASK | SD1_ITAPCHGWIN | SD1_ITAPDLYENA); + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_ITAPDLY, TapDelay); + } + if (OTapDelay != 0U) { + /* Program the OTAPDLY */ + TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY); + TapDelay &= ~SD1_OTAPDLY_SEL_MASK; + TapDelay |= OTapDelay; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay); + } else { + TapDelay = XSdPs_ReadReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY); + TapDelay &= ~SD1_OTAPDLY_SEL_MASK; + XSdPs_WriteReg(InstancePtr->SlcrBaseAddr, SD_OTAPDLY, TapDelay); + } +#endif + } +#endif /* versal */ +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to set voltage to 1.8V. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if successful +* - XST_FAILURE if failure +* +******************************************************************************/ +s32 XSdPs_SetVoltage18(XSdPs *InstancePtr) +{ + s32 Status; + u16 CtrlReg; + + /* Enabling 1.8V in controller */ + CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET); + CtrlReg |= XSDPS_HC2_1V8_EN_MASK; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_HOST_CTRL2_OFFSET, + CtrlReg); + + /* Wait minimum 5mSec */ + (void)usleep(5000U); + + /* Check for 1.8V signal enable bit is cleared by Host */ + Status = XSdPs_CheckVoltage18(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used configure the Power Level. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +void XSdPs_ConfigPower(XSdPs *InstancePtr) +{ + u8 PowerLevel; + + if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V3_MASK) != 0U) { + PowerLevel = XSDPS_PC_BUS_VSEL_3V3_MASK; + } else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V0_MASK) != 0U) { + PowerLevel = XSDPS_PC_BUS_VSEL_3V0_MASK; + } else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_1V8_MASK) != 0U) { + PowerLevel = XSDPS_PC_BUS_VSEL_1V8_MASK; + } else { + PowerLevel = 0U; + } + + /* Select voltage based on capability and enable bus power. */ + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_POWER_CTRL_OFFSET, + PowerLevel | XSDPS_PC_BUS_PWR_MASK); +} + +/*****************************************************************************/ +/** +* @brief +* This function is used configure the DMA. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +void XSdPs_ConfigDma(XSdPs *InstancePtr) +{ + if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) { + /* Enable ADMA2 in 64bit mode. */ + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL1_OFFSET, + XSDPS_HC_DMA_ADMA2_64_MASK); + } else { + /* Enable ADMA2 in 32bit mode. */ + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL1_OFFSET, + XSDPS_HC_DMA_ADMA2_32_MASK); + } +} + +/*****************************************************************************/ +/** +* @brief +* This function is used configure the Interrupts. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +void XSdPs_ConfigInterrupt(XSdPs *InstancePtr) +{ + /* Enable all interrupt status except card interrupt initially */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_NORM_INTR_STS_EN_OFFSET, + XSDPS_NORM_INTR_ALL_MASK & (~XSDPS_INTR_CARD_MASK)); + + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_ERR_INTR_STS_EN_OFFSET, + XSDPS_ERROR_INTR_ALL_MASK); + + /* Disable all interrupt signals by default. */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_NORM_INTR_SIG_EN_OFFSET, 0x0U); + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_ERR_INTR_SIG_EN_OFFSET, 0x0U); + +} + +/*****************************************************************************/ +/** +* This function does SD command generation. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cmd is the command to be sent. +* @param Arg is the argument to be sent along with the command. +* This could be address or any other information +* @param BlkCnt - Block count passed by the user. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_FAILURE if failure - could be because another transfer +* is in progress or command or data inhibit is set +* +******************************************************************************/ +s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt) +{ + u32 Timeout = 10000000U; + u32 StatusReg; + s32 Status; + u32 Mask; + + Status = XSdPs_SetupCmd(InstancePtr, Arg, BlkCnt); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_SendCmd(InstancePtr, Cmd); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Polling for response for now */ + Mask = XSDPS_INTR_ERR_MASK | XSDPS_INTR_CC_MASK; + if ((Cmd == CMD21) || (Cmd == CMD19)) + Mask |= XSDPS_INTR_BRR_MASK; + + Status = Xil_WaitForEvents(InstancePtr->Config.BaseAddress + XSDPS_NORM_INTR_STS_OFFSET, + Mask, Mask, Timeout, &StatusReg); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (((Cmd == CMD21) || (Cmd == CMD19)) && (StatusReg & XSDPS_INTR_BRR_MASK)) { + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_BRR_MASK); + } + if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0) { + Status = (s32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_ERR_INTR_STS_OFFSET); + if (((u32)Status & ~XSDPS_INTR_ERR_CT_MASK) == 0U) { + Status = XSDPS_CT_ERROR; + } + /* Write to clear error bits */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_ERR_INTR_STS_OFFSET, + XSDPS_ERROR_INTR_ALL_MASK); + goto RETURN_PATH; + } + + /* Write to clear bit */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_NORM_INTR_STS_OFFSET, + XSDPS_INTR_CC_MASK); + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* This function is used to check if the transfer is completed successfully. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return None +* +******************************************************************************/ +s32 XSdps_CheckTransferDone(XSdPs *InstancePtr) +{ + u32 Timeout = 5000000U; + u32 StatusReg; + s32 Status; + u32 Mask; + + /* + * Check for transfer complete + * Polling for response for now + */ + Mask = XSDPS_INTR_ERR_MASK | XSDPS_INTR_TC_MASK; + Status = Xil_WaitForEvents(InstancePtr->Config.BaseAddress + XSDPS_NORM_INTR_STS_OFFSET, + Mask, Mask, Timeout, &StatusReg); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0) { + /* Write to clear error bits */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_ERR_INTR_STS_OFFSET, + XSDPS_ERROR_INTR_ALL_MASK); + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Write to clear bit */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK); + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to check if the CMD/DATA bus is idle or not. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Value is to selct Cmd bus or Dat bus +* +* @return None +* +******************************************************************************/ +s32 XSdPs_CheckBusIdle(XSdPs *InstancePtr, u32 Value) +{ + u32 Timeout = 10000000U; + u32 PresentStateReg; + s32 Status; + + PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_PRES_STATE_OFFSET); + /* Check for Card Present */ + if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) != 0U) { + /* Check for SD idle */ + Status = Xil_WaitForEvent(InstancePtr->Config.BaseAddress + XSDPS_PRES_STATE_OFFSET, + Value, 0U, Timeout); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + } + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function frames the Command register for a particular command. +* Note that this generates only the command register value i.e. +* the upper 16 bits of the transfer mode and command register. +* This value is already shifted to be upper 16 bits and can be directly +* OR'ed with transfer mode register value. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Cmd is the Command to be sent. +* +* @return Command register value complete with response type and +* data, CRC and index related flags. +* +******************************************************************************/ +u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd) +{ + u32 RetVal; + + RetVal = Cmd; + + switch(Cmd) { + case CMD0: + RetVal |= RESP_NONE; + break; + case CMD1: + RetVal |= RESP_R3; + break; + case CMD2: + RetVal |= RESP_R2; + break; + case CMD3: + if (InstancePtr->CardType == XSDPS_CARD_SD) { + RetVal |= RESP_R6; + } else { + RetVal |= RESP_R1; + } + break; + case CMD4: + RetVal |= RESP_NONE; + break; + case CMD5: + RetVal |= RESP_R1B; + break; + case CMD6: + if (InstancePtr->CardType == XSDPS_CARD_SD) { + RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK; + } else { + RetVal |= RESP_R1B; + } + break; + case ACMD6: + RetVal |= RESP_R1; + break; + case CMD7: + RetVal |= RESP_R1; + break; + case CMD8: + if (InstancePtr->CardType == XSDPS_CARD_SD) { + RetVal |= RESP_R1; + } else { + RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK; + } + break; + case CMD9: + RetVal |= RESP_R2; + break; + case CMD11: + case CMD10: + case CMD12: + RetVal |= RESP_R1; + break; + case ACMD13: + RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK; + break; + case CMD16: + RetVal |= RESP_R1; + break; + case CMD17: + case CMD18: + case CMD19: + case CMD21: + RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK; + break; + case CMD23: + case ACMD23: + case CMD24: + case CMD25: + RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK; + break; + case CMD32: + case CMD33: + case CMD35: + case CMD36: + RetVal |= RESP_R1; + break; + case CMD38: + RetVal |= RESP_R1B; + break; + case ACMD41: + RetVal |= RESP_R3; + break; + case ACMD42: + RetVal |= RESP_R1; + break; + case ACMD51: + RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK; + break; + case CMD52: + case CMD55: + RetVal |= RESP_R1; + break; + case CMD58: + break; + default : + RetVal |= Cmd; + break; + } + + return RetVal; +} + +#ifdef VERSAL_NET +/*****************************************************************************/ +/** +* @brief +* This function selects the HS400 timing mode. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return - XST_SUCCESS if successful +* - XST_FAILURE if failure occurred. +* +******************************************************************************/ +u32 XSdPs_Select_HS400(XSdPs *InstancePtr) +{ + u32 Status; + u32 StatusReg; + + InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE; + Status = XSdPs_Change_MmcBusSpeed(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + InstancePtr->OTapDelay = SD_OTAPDLYSEL_EMMC_HSD; + Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + InstancePtr->Mode = XSDPS_HS400_MODE; + Status = XSdPs_Change_BusWidth(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_Change_MmcBusSpeed(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS400; + Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET); + StatusReg &= (~(u32)XSDPS_HC2_UHS_MODE_MASK); + StatusReg |= XSDPS_HC2_HS400_MASK; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET, (u16)StatusReg); + +RETURN_PATH: + return Status; +} +#endif + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_hw.h new file mode 100644 index 0000000..7ee7774 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_hw.h @@ -0,0 +1,1507 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps_hw.h +* @addtogroup sdps Overview +* @{{ +* +* The xsdps_hw.h header file contains the identifiers and basic HW access driver +* functions (or macros) that can be used to access the device. Other driver +* functions are defined in xsdps.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 1.00a hk/sg  10/17/13 Initial release
+* 2.5 	sg	   07/09/15 Added SD 3.0 features
+*       kvn    07/15/15 Modified the code according to MISRAC-2012.
+* 2.7   sk     12/10/15 Added support for MMC cards.
+*       sk     03/02/16 Configured the Tap Delay values for eMMC HS200 mode.
+* 2.8   sk     04/20/16 Added new workaround for auto tuning.
+* 3.0   sk     06/09/16 Added support for mkfs to calculate sector count.
+*       sk     07/16/16 Added support for UHS modes.
+*       sk     07/16/16 Added Tap delays accordingly to different SD/eMMC
+*                       operating modes.
+* 3.1   sk     11/07/16 Enable Rst_n bit in ext_csd reg if not enabled.
+* 3.2   sk     03/20/17 Add support for EL1 non-secure mode.
+* 3.3   mn     08/22/17 Updated for Word Access System support
+*       mn     09/06/17 Added support for ARMCC toolchain
+* 3.4   mn     01/22/18 Separated out SDR104 and HS200 clock defines
+* 3.6   mn     07/06/18 Fix Doxygen warnings for sdps driver
+* 3.8   mn     04/12/19 Modified TapDelay code for supporting ZynqMP and Versal
+*       mn     05/21/19 Set correct tap delays for Versal
+*       mn     05/21/19 Disable DLL Reset code for Versal
+*       mn     07/03/19 Update Input Tap Delays for Versal
+* 3.9   mn     03/03/20 Restructured the code for more readability and modularity
+* 3.14  mn     11/28/21 Fix MISRA-C violations.
+* 4.0   sk     02/25/22 Add support for eMMC5.1.
+*       sk     04/07/22 Fix typo in 'XSDPS_MMC_1_BIT_BUS_ARG' macro definition.
+* 4.1   sk     11/10/22 Add SD/eMMC Tap delay support for Versal Net.
+*
+* 
+* +******************************************************************************/ + +/** @cond INTERNAL */ +#ifndef SD_HW_H_ +#define SD_HW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets from the base address of an SD device. + * @{ + */ + +#define XSDPS_SDMA_SYS_ADDR_OFFSET 0x00U /**< SDMA System Address + Register */ +#define XSDPS_SDMA_SYS_ADDR_LO_OFFSET XSDPS_SDMA_SYS_ADDR_OFFSET + /**< SDMA System Address + Low Register */ +#define XSDPS_ARGMT2_LO_OFFSET 0x00U /**< Argument2 Low Register */ +#define XSDPS_SDMA_SYS_ADDR_HI_OFFSET 0x02U /**< SDMA System Address + High Register */ +#define XSDPS_ARGMT2_HI_OFFSET 0x02U /**< Argument2 High Register */ + +#define XSDPS_BLK_SIZE_OFFSET 0x04U /**< Block Size Register */ +#define XSDPS_BLK_CNT_OFFSET 0x06U /**< Block Count Register */ +#define XSDPS_ARGMT_OFFSET 0x08U /**< Argument Register */ +#define XSDPS_ARGMT1_LO_OFFSET XSDPS_ARGMT_OFFSET + /**< Argument1 Register */ +#define XSDPS_ARGMT1_HI_OFFSET 0x0AU /**< Argument1 Register */ + +#define XSDPS_XFER_MODE_OFFSET 0x0CU /**< Transfer Mode Register */ +#define XSDPS_CMD_OFFSET 0x0EU /**< Command Register */ +#define XSDPS_RESP0_OFFSET 0x10U /**< Response0 Register */ +#define XSDPS_RESP1_OFFSET 0x14U /**< Response1 Register */ +#define XSDPS_RESP2_OFFSET 0x18U /**< Response2 Register */ +#define XSDPS_RESP3_OFFSET 0x1CU /**< Response3 Register */ +#define XSDPS_BUF_DAT_PORT_OFFSET 0x20U /**< Buffer Data Port */ +#define XSDPS_PRES_STATE_OFFSET 0x24U /**< Present State */ +#define XSDPS_HOST_CTRL1_OFFSET 0x28U /**< Host Control 1 */ +#define XSDPS_POWER_CTRL_OFFSET 0x29U /**< Power Control */ +#define XSDPS_BLK_GAP_CTRL_OFFSET 0x2AU /**< Block Gap Control */ +#define XSDPS_WAKE_UP_CTRL_OFFSET 0x2BU /**< Wake Up Control */ +#define XSDPS_CLK_CTRL_OFFSET 0x2CU /**< Clock Control */ +#define XSDPS_TIMEOUT_CTRL_OFFSET 0x2EU /**< Timeout Control */ +#define XSDPS_SW_RST_OFFSET 0x2FU /**< Software Reset */ +#define XSDPS_NORM_INTR_STS_OFFSET 0x30U /**< Normal Interrupt + Status Register */ +#define XSDPS_ERR_INTR_STS_OFFSET 0x32U /**< Error Interrupt + Status Register */ +#define XSDPS_NORM_INTR_STS_EN_OFFSET 0x34U /**< Normal Interrupt + Status Enable Register */ +#define XSDPS_ERR_INTR_STS_EN_OFFSET 0x36U /**< Error Interrupt + Status Enable Register */ +#define XSDPS_NORM_INTR_SIG_EN_OFFSET 0x38U /**< Normal Interrupt + Signal Enable Register */ +#define XSDPS_ERR_INTR_SIG_EN_OFFSET 0x3AU /**< Error Interrupt + Signal Enable Register */ + +#define XSDPS_AUTO_CMD12_ERR_STS_OFFSET 0x3CU /**< Auto CMD12 Error Status + Register */ +#define XSDPS_HOST_CTRL2_OFFSET 0x3EU /**< Host Control2 Register */ +#define XSDPS_CAPS_OFFSET 0x40U /**< Capabilities Register */ +#define XSDPS_CAPS_EXT_OFFSET 0x44U /**< Capabilities Extended */ +#define XSDPS_MAX_CURR_CAPS_OFFSET 0x48U /**< Maximum Current + Capabilities Register */ +#define XSDPS_MAX_CURR_CAPS_EXT_OFFSET 0x4CU /**< Maximum Current + Capabilities Ext Register */ +#define XSDPS_FE_ERR_INT_STS_OFFSET 0x52U /**< Force Event for + Error Interrupt Status */ +#define XSDPS_FE_AUTO_CMD12_EIS_OFFSET 0x50U /**< Auto CM12 Error Interrupt + Status Register */ +#define XSDPS_ADMA_ERR_STS_OFFSET 0x54U /**< ADMA Error Status + Register */ +#define XSDPS_ADMA_SAR_OFFSET 0x58U /**< ADMA System Address + Register */ +#define XSDPS_ADMA_SAR_EXT_OFFSET 0x5CU /**< ADMA System Address + Extended Register */ +#define XSDPS_PRE_VAL_1_OFFSET 0x60U /**< Preset Value Register */ +#define XSDPS_PRE_VAL_2_OFFSET 0x64U /**< Preset Value Register */ +#define XSDPS_PRE_VAL_3_OFFSET 0x68U /**< Preset Value Register */ +#define XSDPS_PRE_VAL_4_OFFSET 0x6CU /**< Preset Value Register */ +#define XSDPS_BOOT_TOUT_CTRL_OFFSET 0x70U /**< Boot timeout control + register */ + +#define XSDPS_SHARED_BUS_CTRL_OFFSET 0xE0U /**< Shared Bus Control + Register */ +#define XSDPS_SLOT_INTR_STS_OFFSET 0xFCU /**< Slot Interrupt Status + Register */ +#define XSDPS_HOST_CTRL_VER_OFFSET 0xFEU /**< Host Controller Version + Register */ +#ifdef VERSAL_NET +#define XSDPS_PHYCTRLREG1_OFFSET 0x270U /**< PHY Control register2 */ +#define XSDPS_PHYCTRLREG2_OFFSET 0x274U /**< PHY Control register2 */ +#endif + +/** @} */ + +/** @name Control Register - Host control, Power control, + * Block Gap control and Wakeup control + * + * This register contains bits for various configuration options of + * the SD host controller. Read/Write apart from the reserved bits. + * @{ + */ + +#define XSDPS_HC_LED_MASK 0x00000001U /**< LED Control */ +#define XSDPS_HC_WIDTH_MASK 0x00000002U /**< Bus width */ +#define XSDPS_HC_BUS_WIDTH_4 0x00000002U +#define XSDPS_HC_SPEED_MASK 0x00000004U /**< High Speed */ +#define XSDPS_HC_DMA_MASK 0x00000018U /**< DMA Mode Select */ +#define XSDPS_HC_DMA_SDMA_MASK 0x00000000U /**< SDMA Mode */ +#define XSDPS_HC_DMA_ADMA1_MASK 0x00000008U /**< ADMA1 Mode */ +#define XSDPS_HC_DMA_ADMA2_32_MASK 0x00000010U /**< ADMA2 Mode - 32 bit */ +#define XSDPS_HC_DMA_ADMA2_64_MASK 0x00000018U /**< ADMA2 Mode - 64 bit */ +#define XSDPS_HC_EXT_BUS_WIDTH 0x00000020U /**< Bus width - 8 bit */ +#define XSDPS_HC_CARD_DET_TL_MASK 0x00000040U /**< Card Detect Tst Lvl */ +#define XSDPS_HC_CARD_DET_SD_MASK 0x00000080U /**< Card Detect Sig Det */ + +#define XSDPS_PC_BUS_PWR_MASK 0x00000001U /**< Bus Power Control */ +#define XSDPS_PC_BUS_VSEL_MASK 0x0000000EU /**< Bus Voltage Select */ +#define XSDPS_PC_BUS_VSEL_3V3_MASK 0x0000000EU /**< Bus Voltage 3.3V */ +#define XSDPS_PC_BUS_VSEL_3V0_MASK 0x0000000CU /**< Bus Voltage 3.0V */ +#define XSDPS_PC_BUS_VSEL_1V8_MASK 0x0000000AU /**< Bus Voltage 1.8V */ +#define XSDPS_PC_EMMC_HW_RST_MASK 0x00000010U /**< HW reset for eMMC */ + +#define XSDPS_BGC_STP_REQ_MASK 0x00000001U /**< Block Gap Stop Req */ +#define XSDPS_BGC_CNT_REQ_MASK 0x00000002U /**< Block Gap Cont Req */ +#define XSDPS_BGC_RWC_MASK 0x00000004U /**< Block Gap Rd Wait */ +#define XSDPS_BGC_INTR_MASK 0x00000008U /**< Block Gap Intr */ +#define XSDPS_BGC_SPI_MODE_MASK 0x00000010U /**< Block Gap SPI Mode */ +#define XSDPS_BGC_BOOT_EN_MASK 0x00000020U /**< Block Gap Boot Enb */ +#define XSDPS_BGC_ALT_BOOT_EN_MASK 0x00000040U /**< Block Gap Alt BootEn */ +#define XSDPS_BGC_BOOT_ACK_MASK 0x00000080U /**< Block Gap Boot Ack */ + +#define XSDPS_WC_WUP_ON_INTR_MASK 0x00000001U /**< Wakeup Card Intr */ +#define XSDPS_WC_WUP_ON_INSRT_MASK 0x00000002U /**< Wakeup Card Insert */ +#define XSDPS_WC_WUP_ON_REM_MASK 0x00000004U /**< Wakeup Card Removal */ + +/** @} */ + +/** @name Control Register - Clock control, Timeout control & Software reset + * + * This register contains bits for configuration options of clock, timeout and + * software reset. + * Read/Write except for Inter_Clock_Stable bit (read only) and reserved bits. + * @{ + */ + +#define XSDPS_CC_INT_CLK_EN_MASK 0x00000001U /**< INT clk enable */ +#define XSDPS_CC_INT_CLK_STABLE_MASK 0x00000002U /**< INT clk stable */ +#define XSDPS_CC_SD_CLK_EN_MASK 0x00000004U /**< SD clk enable */ +#define XSDPS_CC_SD_CLK_GEN_SEL_MASK 0x00000020U /**< SD clk gen selection */ +#define XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK 0x00000003U /**< SD clk freq sel upper */ +#define XSDPS_CC_SDCLK_FREQ_SEL_MASK 0x000000FFU /**< SD clk freq sel */ +#define XSDPS_CC_SDCLK_FREQ_D256_MASK 0x00008000U /**< Divider 256 */ +#define XSDPS_CC_SDCLK_FREQ_D128_MASK 0x00004000U /**< Divider 128 */ +#define XSDPS_CC_SDCLK_FREQ_D64_MASK 0x00002000U /**< Divider 64 */ +#define XSDPS_CC_SDCLK_FREQ_D32_MASK 0x00001000U /**< Divider 32 */ +#define XSDPS_CC_SDCLK_FREQ_D16_MASK 0x00000800U /**< Divider 16 */ +#define XSDPS_CC_SDCLK_FREQ_D8_MASK 0x00000400U /**< Divider 8 */ +#define XSDPS_CC_SDCLK_FREQ_D4_MASK 0x00000200U /**< Divider 4 */ +#define XSDPS_CC_SDCLK_FREQ_D2_MASK 0x00000100U /**< Divider 2 */ +#define XSDPS_CC_SDCLK_FREQ_BASE_MASK 0x00000000U /**< Base clock */ +#define XSDPS_CC_MAX_DIV_CNT 256U /**< Max divider count */ +#define XSDPS_CC_EXT_MAX_DIV_CNT 2046U /**< Max extended divider count */ +#define XSDPS_CC_EXT_DIV_SHIFT 6U /**< Ext divider shift */ + +#define XSDPS_TC_CNTR_VAL_MASK 0x0000000FU /**< Data timeout counter */ + +#define XSDPS_SWRST_ALL_MASK 0x00000001U /**< Software Reset All */ +#define XSDPS_SWRST_CMD_LINE_MASK 0x00000002U /**< Software reset for CMD line */ +#define XSDPS_SWRST_DAT_LINE_MASK 0x00000004U /**< Software reset for DAT line */ + +#define XSDPS_CC_MAX_NUM_OF_DIV 9U /**< Max number of Clock dividers */ +#define XSDPS_CC_DIV_SHIFT 8U /**< Clock Divider shift */ + +/** @} */ + +/** @name SD Interrupt Registers + * + * Normal and Error Interrupt Status Register + * This register shows the normal and error interrupt status. + * Status enable register affects reads of this register. + * If Signal enable register is set and the corresponding status bit is set, + * interrupt is generated. + * Write to clear except + * Error_interrupt and Card_Interrupt bits - Read only + * + * Normal and Error Interrupt Status Enable Register + * Setting this register bits enables Interrupt status. + * Read/Write except Fixed_to_0 bit (Read only) + * + * Normal and Error Interrupt Signal Enable Register + * This register is used to select which interrupt status is + * indicated to the Host System as the interrupt. + * Read/Write except Fixed_to_0 bit (Read only) + * + * All three registers have same bit definitions + * @{ + */ + +#define XSDPS_INTR_CC_MASK 0x00000001U /**< Command Complete */ +#define XSDPS_INTR_TC_MASK 0x00000002U /**< Transfer Complete */ +#define XSDPS_INTR_BGE_MASK 0x00000004U /**< Block Gap Event */ +#define XSDPS_INTR_DMA_MASK 0x00000008U /**< DMA Interrupt */ +#define XSDPS_INTR_BWR_MASK 0x00000010U /**< Buffer Write Ready */ +#define XSDPS_INTR_BRR_MASK 0x00000020U /**< Buffer Read Ready */ +#define XSDPS_INTR_CARD_INSRT_MASK 0x00000040U /**< Card Insert */ +#define XSDPS_INTR_CARD_REM_MASK 0x00000080U /**< Card Remove */ +#define XSDPS_INTR_CARD_MASK 0x00000100U /**< Card Interrupt */ +#define XSDPS_INTR_INT_A_MASK 0x00000200U /**< INT A Interrupt */ +#define XSDPS_INTR_INT_B_MASK 0x00000400U /**< INT B Interrupt */ +#define XSDPS_INTR_INT_C_MASK 0x00000800U /**< INT C Interrupt */ +#define XSDPS_INTR_RE_TUNING_MASK 0x00001000U /**< Re-Tuning Interrupt */ +#define XSDPS_INTR_BOOT_ACK_RECV_MASK 0x00002000U /**< Boot Ack Recv + Interrupt */ +#define XSDPS_INTR_BOOT_TERM_MASK 0x00004000U /**< Boot Terminate + Interrupt */ +#define XSDPS_INTR_ERR_MASK 0x00008000U /**< Error Interrupt */ +#define XSDPS_NORM_INTR_ALL_MASK 0x0000FFFFU + +#define XSDPS_INTR_ERR_CT_MASK 0x00000001U /**< Command Timeout + Error */ +#define XSDPS_INTR_ERR_CCRC_MASK 0x00000002U /**< Command CRC Error */ +#define XSDPS_INTR_ERR_CEB_MASK 0x00000004U /**< Command End Bit + Error */ +#define XSDPS_INTR_ERR_CI_MASK 0x00000008U /**< Command Index Error */ +#define XSDPS_INTR_ERR_DT_MASK 0x00000010U /**< Data Timeout Error */ +#define XSDPS_INTR_ERR_DCRC_MASK 0x00000020U /**< Data CRC Error */ +#define XSDPS_INTR_ERR_DEB_MASK 0x00000040U /**< Data End Bit Error */ +#define XSDPS_INTR_ERR_CUR_LMT_MASK 0x00000080U /**< Current Limit Error */ +#define XSDPS_INTR_ERR_AUTO_CMD12_MASK 0x00000100U /**< Auto CMD12 Error */ +#define XSDPS_INTR_ERR_ADMA_MASK 0x00000200U /**< ADMA Error */ +#define XSDPS_INTR_ERR_TR_MASK 0x00001000U /**< Tuning Error */ +#define XSDPS_INTR_VEND_SPF_ERR_MASK 0x0000E000U /**< Vendor Specific + Error */ +#define XSDPS_ERROR_INTR_ALL_MASK 0x0000F3FFU /**< Mask for error bits */ +/** @} */ + +/** @name Block Size and Block Count Register + * + * This register contains the block count for current transfer, + * block size and SDMA buffer size. + * Read/Write except for reserved bits. + * @{ + */ + +#define XSDPS_BLK_SIZE_MASK 0x00000FFFU /**< Transfer Block Size */ +#define XSDPS_SDMA_BUFF_SIZE_MASK 0x00007000U /**< Host SDMA Buffer Size */ +#define XSDPS_BLK_SIZE_1024 0x400U +#define XSDPS_BLK_SIZE_2048 0x800U +#define XSDPS_BLK_CNT_MASK 0x0000FFFFU /**< Block Count for + Current Transfer */ + +/** @} */ + +/** @name Transfer Mode and Command Register + * + * The Transfer Mode register is used to control the data transfers and + * Command register is used for command generation + * Read/Write except for reserved bits. + * @{ + */ + +#define XSDPS_TM_DMA_EN_MASK 0x00000001U /**< DMA Enable */ +#define XSDPS_TM_BLK_CNT_EN_MASK 0x00000002U /**< Block Count Enable */ +#define XSDPS_TM_AUTO_CMD12_EN_MASK 0x00000004U /**< Auto CMD12 Enable */ +#define XSDPS_TM_DAT_DIR_SEL_MASK 0x00000010U /**< Data Transfer + Direction Select */ +#define XSDPS_TM_MUL_SIN_BLK_SEL_MASK 0x00000020U /**< Multi/Single + Block Select */ + +#define XSDPS_CMD_RESP_SEL_MASK 0x00000003U /**< Response Type + Select */ +#define XSDPS_CMD_RESP_NONE_MASK 0x00000000U /**< No Response */ +#define XSDPS_CMD_RESP_L136_MASK 0x00000001U /**< Response length 138 */ +#define XSDPS_CMD_RESP_L48_MASK 0x00000002U /**< Response length 48 */ +#define XSDPS_CMD_RESP_L48_BSY_CHK_MASK 0x00000003U /**< Response length 48 & + check busy after + response */ +#define XSDPS_CMD_CRC_CHK_EN_MASK 0x00000008U /**< Command CRC Check + Enable */ +#define XSDPS_CMD_INX_CHK_EN_MASK 0x00000010U /**< Command Index Check + Enable */ +#define XSDPS_DAT_PRESENT_SEL_MASK 0x00000020U /**< Data Present Select */ +#define XSDPS_CMD_TYPE_MASK 0x000000C0U /**< Command Type */ +#define XSDPS_CMD_TYPE_NORM_MASK 0x00000000U /**< CMD Type - Normal */ +#define XSDPS_CMD_TYPE_SUSPEND_MASK 0x00000040U /**< CMD Type - Suspend */ +#define XSDPS_CMD_TYPE_RESUME_MASK 0x00000080U /**< CMD Type - Resume */ +#define XSDPS_CMD_TYPE_ABORT_MASK 0x000000C0U /**< CMD Type - Abort */ +#define XSDPS_CMD_MASK 0x00003F00U /**< Command Index Mask - + Set to CMD0-63, + AMCD0-63 */ + +/** @} */ + +/** @name Auto CMD Error Status Register + * + * This register is read only register which contains + * information about the error status of Auto CMD 12 and 23. + * Read Only + * @{ + */ +#define XSDPS_AUTO_CMD12_NT_EX_MASK 0x0001U /**< Auto CMD12 Not + executed */ +#define XSDPS_AUTO_CMD_TOUT_MASK 0x0002U /**< Auto CMD Timeout + Error */ +#define XSDPS_AUTO_CMD_CRC_MASK 0x0004U /**< Auto CMD CRC Error */ +#define XSDPS_AUTO_CMD_EB_MASK 0x0008U /**< Auto CMD End Bit + Error */ +#define XSDPS_AUTO_CMD_IND_MASK 0x0010U /**< Auto CMD Index Error */ +#define XSDPS_AUTO_CMD_CNI_ERR_MASK 0x0080U /**< Command not issued by + Auto CMD12 Error */ +/** @} */ + +/** @name Host Control2 Register + * + * This register contains extended configuration bits. + * Read Write + * @{ + */ +#define XSDPS_HC2_UHS_MODE_MASK 0x0007U /**< UHS Mode select bits */ +#define XSDPS_HC2_UHS_MODE_SDR12_MASK 0x0000U /**< SDR12 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_SDR25_MASK 0x0001U /**< SDR25 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_SDR50_MASK 0x0002U /**< SDR50 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_SDR104_MASK 0x0003U /**< SDR104 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_DDR50_MASK 0x0004U /**< DDR50 UHS Mode */ +#define XSDPS_HC2_HS400_MASK 0x0005U /**< HS400 Mode */ +#define XSDPS_HC2_1V8_EN_MASK 0x0008U /**< 1.8V Signal Enable */ +#define XSDPS_HC2_DRV_STR_SEL_MASK 0x0030U /**< Driver Strength + Selection */ +#define XSDPS_HC2_DRV_STR_B_MASK 0x0000U /**< Driver Strength B */ +#define XSDPS_HC2_DRV_STR_A_MASK 0x0010U /**< Driver Strength A */ +#define XSDPS_HC2_DRV_STR_C_MASK 0x0020U /**< Driver Strength C */ +#define XSDPS_HC2_DRV_STR_D_MASK 0x0030U /**< Driver Strength D */ +#define XSDPS_HC2_EXEC_TNG_MASK 0x0040U /**< Execute Tuning */ +#define XSDPS_HC2_SAMP_CLK_SEL_MASK 0x0080U /**< Sampling Clock + Selection */ +#define XSDPS_HC2_ASYNC_INTR_EN_MASK 0x4000U /**< Asynchronous Interrupt + Enable */ +#define XSDPS_HC2_PRE_VAL_EN_MASK 0x8000U /**< Preset Value Enable */ + +/** @} */ + +/** @name Capabilities Register + * + * Capabilities register is a read only register which contains + * information about the host controller. + * Sufficient if read once after power on. + * Read Only + * @{ + */ +#define XSDPS_CAP_TOUT_CLK_FREQ_MASK 0x0000003FU /**< Timeout clock freq + select */ +#define XSDPS_CAP_TOUT_CLK_UNIT_MASK 0x00000080U /**< Timeout clock unit - + MHz/KHz */ +#define XSDPS_CAP_MAX_BLK_LEN_MASK 0x00030000U /**< Max block length */ +#define XSDPS_CAP_MAX_BLK_LEN_512B_MASK 0x00000000U /**< Max block 512 bytes */ +#define XSDPS_CAP_MAX_BL_LN_1024_MASK 0x00010000U /**< Max block 1024 bytes */ +#define XSDPS_CAP_MAX_BL_LN_2048_MASK 0x00020000U /**< Max block 2048 bytes */ +#define XSDPS_CAP_MAX_BL_LN_4096_MASK 0x00030000U /**< Max block 4096 bytes */ + +#define XSDPS_CAP_EXT_MEDIA_BUS_MASK 0x00040000U /**< Extended media bus */ +#define XSDPS_CAP_ADMA2_MASK 0x00080000U /**< ADMA2 support */ +#define XSDPS_CAP_HIGH_SPEED_MASK 0x00200000U /**< High speed support */ +#define XSDPS_CAP_SDMA_MASK 0x00400000U /**< SDMA support */ +#define XSDPS_CAP_SUSP_RESUME_MASK 0x00800000U /**< Suspend/Resume + support */ +#define XSDPS_CAP_VOLT_3V3_MASK 0x01000000U /**< 3.3V support */ +#define XSDPS_CAP_VOLT_3V0_MASK 0x02000000U /**< 3.0V support */ +#define XSDPS_CAP_VOLT_1V8_MASK 0x04000000U /**< 1.8V support */ + +#define XSDPS_CAP_SYS_BUS_64_MASK 0x10000000U /**< 64 bit system bus + support */ +/* Spec 2.0 */ +#define XSDPS_CAP_INTR_MODE_MASK 0x08000000U /**< Interrupt mode + support */ +#define XSDPS_CAP_SPI_MODE_MASK 0x20000000U /**< SPI mode */ +#define XSDPS_CAP_SPI_BLOCK_MODE_MASK 0x40000000U /**< SPI block mode */ + + +/* Spec 3.0 */ +#define XSDPS_CAPS_ASYNC_INTR_MASK 0x20000000U /**< Async Interrupt + support */ +#define XSDPS_CAPS_SLOT_TYPE_MASK 0xC0000000U /**< Slot Type */ +#define XSDPS_CAPS_REM_CARD 0x00000000U /**< Removable Slot */ +#define XSDPS_CAPS_EMB_SLOT 0x40000000U /**< Embedded Slot */ +#define XSDPS_CAPS_SHR_BUS 0x80000000U /**< Shared Bus Slot */ + +#define XSDPS_ECAPS_SDR50_MASK 0x00000001U /**< SDR50 Mode support */ +#define XSDPS_ECAPS_SDR104_MASK 0x00000002U /**< SDR104 Mode support */ +#define XSDPS_ECAPS_DDR50_MASK 0x00000004U /**< DDR50 Mode support */ +#define XSDPS_ECAPS_DRV_TYPE_A_MASK 0x00000010U /**< DriverType A support */ +#define XSDPS_ECAPS_DRV_TYPE_C_MASK 0x00000020U /**< DriverType C support */ +#define XSDPS_ECAPS_DRV_TYPE_D_MASK 0x00000040U /**< DriverType D support */ +#define XSDPS_ECAPS_TMR_CNT_MASK 0x00000F00U /**< Timer Count for + Re-tuning */ +#define XSDPS_ECAPS_USE_TNG_SDR50_MASK 0x00002000U /**< SDR50 Mode needs + tuning */ +#define XSDPS_ECAPS_RE_TNG_MODES_MASK 0x0000C000U /**< Re-tuning modes + support */ +#define XSDPS_ECAPS_RE_TNG_MODE1_MASK 0x00000000U /**< Re-tuning mode 1 */ +#define XSDPS_ECAPS_RE_TNG_MODE2_MASK 0x00004000U /**< Re-tuning mode 2 */ +#define XSDPS_ECAPS_RE_TNG_MODE3_MASK 0x00008000U /**< Re-tuning mode 3 */ +#define XSDPS_ECAPS_CLK_MULT_MASK 0x00FF0000U /**< Clock Multiplier value + for Programmable clock + mode */ +#define XSDPS_ECAPS_SPI_MODE_MASK 0x01000000U /**< SPI mode */ +#define XSDPS_ECAPS_SPI_BLK_MODE_MASK 0x02000000U /**< SPI block mode */ + +/** @} */ + +/** @name Present State Register + * + * Gives the current status of the host controller + * Read Only + * @{ + */ + +#define XSDPS_PSR_INHIBIT_CMD_MASK 0x00000001U /**< Command inhibit - CMD */ +#define XSDPS_PSR_INHIBIT_DAT_MASK 0x00000002U /**< Command Inhibit - DAT */ +#define XSDPS_PSR_DAT_ACTIVE_MASK 0x00000004U /**< DAT line active */ +#define XSDPS_PSR_RE_TUNING_REQ_MASK 0x00000008U /**< Re-tuning request */ +#define XSDPS_PSR_WR_ACTIVE_MASK 0x00000100U /**< Write transfer active */ +#define XSDPS_PSR_RD_ACTIVE_MASK 0x00000200U /**< Read transfer active */ +#define XSDPS_PSR_BUFF_WR_EN_MASK 0x00000400U /**< Buffer write enable */ +#define XSDPS_PSR_BUFF_RD_EN_MASK 0x00000800U /**< Buffer read enable */ +#define XSDPS_PSR_CARD_INSRT_MASK 0x00010000U /**< Card inserted */ +#define XSDPS_PSR_CARD_STABLE_MASK 0x00020000U /**< Card state stable */ +#define XSDPS_PSR_CARD_DPL_MASK 0x00040000U /**< Card detect pin level */ +#define XSDPS_PSR_WPS_PL_MASK 0x00080000U /**< Write protect switch + pin level */ +#define XSDPS_PSR_DAT30_SG_LVL_MASK 0x00F00000U /**< Data 3:0 signal lvl */ +#define XSDPS_PSR_CMD_SG_LVL_MASK 0x01000000U /**< Cmd Line signal lvl */ +#define XSDPS_PSR_DAT74_SG_LVL_MASK 0x1E000000U /**< Data 7:4 signal lvl */ + +/** @} */ + +/** @name Maximum Current Capabilities Register + * + * This register is read only register which contains + * information about current capabilities at each voltage levels. + * Read Only + * @{ + */ +#define XSDPS_MAX_CUR_CAPS_1V8_MASK 0x00000F00U /**< Maximum Current + Capability at 1.8V */ +#define XSDPS_MAX_CUR_CAPS_3V0_MASK 0x000000F0U /**< Maximum Current + Capability at 3.0V */ +#define XSDPS_MAX_CUR_CAPS_3V3_MASK 0x0000000FU /**< Maximum Current + Capability at 3.3V */ +/** @} */ + + +/** @name Force Event for Auto CMD Error Status Register + * + * This register is write only register which contains + * control bits to generate events for Auto CMD error status. + * Write Only + * @{ + */ +#define XSDPS_FE_AUTO_CMD12_NT_EX_MASK 0x0001U /**< Auto CMD12 Not + executed */ +#define XSDPS_FE_AUTO_CMD_TOUT_MASK 0x0002U /**< Auto CMD Timeout + Error */ +#define XSDPS_FE_AUTO_CMD_CRC_MASK 0x0004U /**< Auto CMD CRC Error */ +#define XSDPS_FE_AUTO_CMD_EB_MASK 0x0008U /**< Auto CMD End Bit + Error */ +#define XSDPS_FE_AUTO_CMD_IND_MASK 0x0010U /**< Auto CMD Index Error */ +#define XSDPS_FE_AUTO_CMD_CNI_ERR_MASK 0x0080U /**< Command not issued by + Auto CMD12 Error */ +/** @} */ + + + +/** @name Force Event for Error Interrupt Status Register + * + * This register is write only register which contains + * control bits to generate events of error interrupt status register. + * Write Only + * @{ + */ +#define XSDPS_FE_INTR_ERR_CT_MASK 0x0001U /**< Command Timeout + Error */ +#define XSDPS_FE_INTR_ERR_CCRC_MASK 0x0002U /**< Command CRC Error */ +#define XSDPS_FE_INTR_ERR_CEB_MASK 0x0004U /**< Command End Bit + Error */ +#define XSDPS_FE_INTR_ERR_CI_MASK 0x0008U /**< Command Index Error */ +#define XSDPS_FE_INTR_ERR_DT_MASK 0x0010U /**< Data Timeout Error */ +#define XSDPS_FE_INTR_ERR_DCRC_MASK 0x0020U /**< Data CRC Error */ +#define XSDPS_FE_INTR_ERR_DEB_MASK 0x0040U /**< Data End Bit Error */ +#define XSDPS_FE_INTR_ERR_CUR_LMT_MASK 0x0080U /**< Current Limit Error */ +#define XSDPS_FE_INTR_ERR_AUTO_CMD_MASK 0x0100U /**< Auto CMD Error */ +#define XSDPS_FE_INTR_ERR_ADMA_MASK 0x0200U /**< ADMA Error */ +#define XSDPS_FE_INTR_ERR_TR_MASK 0x1000U /**< Target Response */ +#define XSDPS_FE_INTR_VEND_SPF_ERR_MASK 0xE000U /**< Vendor Specific + Error */ + +/** @} */ + +/** @name ADMA Error Status Register + * + * This register is read only register which contains + * status information about ADMA errors. + * Read Only + * @{ + */ +#define XSDPS_ADMA_ERR_MM_LEN_MASK 0x04U /**< ADMA Length Mismatch + Error */ +#define XSDPS_ADMA_ERR_STATE_MASK 0x03U /**< ADMA Error State */ +#define XSDPS_ADMA_ERR_STATE_STOP_MASK 0x00U /**< ADMA Error State + STOP */ +#define XSDPS_ADMA_ERR_STATE_FDS_MASK 0x01U /**< ADMA Error State + FDS */ +#define XSDPS_ADMA_ERR_STATE_TFR_MASK 0x03U /**< ADMA Error State + TFR */ +/** @} */ + +/** @name Preset Values Register + * + * This register is read only register which contains + * preset values for each of speed modes. + * Read Only + * @{ + */ +#define XSDPS_PRE_VAL_SDCLK_FSEL_MASK 0x03FFU /**< SDCLK Frequency + Select Value */ +#define XSDPS_PRE_VAL_CLK_GEN_SEL_MASK 0x0400U /**< Clock Generator + Mode Select */ +#define XSDPS_PRE_VAL_DRV_STR_SEL_MASK 0xC000U /**< Driver Strength + Select Value */ + +/** @} */ + +/** @name Slot Interrupt Status Register + * + * This register is read only register which contains + * interrupt slot signal for each slot. + * Read Only + * @{ + */ +#define XSDPS_SLOT_INTR_STS_INT_MASK 0x0007U /**< Interrupt Signal + mask */ + +/** @} */ + +/** @name Host Controller Version Register + * + * This register is read only register which contains + * Host Controller and Vendor Specific version. + * Read Only + * @{ + */ +#define XSDPS_HC_VENDOR_VER 0xFF00U /**< Vendor + Specification + version mask */ +#define XSDPS_HC_SPEC_VER_MASK 0x00FFU /**< Host + Specification + version mask */ +#define XSDPS_HC_SPEC_V3 0x0002U /**< HC spec version 3 */ +#define XSDPS_HC_SPEC_V2 0x0001U /**< HC spec version 2 */ +#define XSDPS_HC_SPEC_V1 0x0000U /**< HC spec version 1 */ +/** @} */ + +/** @name PHYCTRL Register1 - OTAP, ITAP and SROBE SEL + * + * This register contains bits for input tap, output tap and strobe sel. + * @{ + */ + +#define XSDPS_PHYREG1_STROBE_SEL_MASK 0xFF0000U /**< STROBE Sel Mask */ +#define XSDPS_PHYREG1_STROBE_SEL_SHIFT 16U /**< STROBE Sel Shift */ +#define XSDPS_PHYREG1_ITAP_CHGWIN_MASK 0x40U /**< Input Tap Change Window */ +#define XSDPS_PHYREG1_ITAP_EN_MASK 0x1U /**< Input Tap Enable Mask */ +#define XSDPS_PHYREG1_ITAP_DLY_MASK 0x2EU /**< Input Tap Delay Mask */ +#define XSDPS_PHYREG1_ITAP_DLY_SHIFT 1U /**< Input Tap Delay Shift */ +#define XSDPS_PHYREG1_OTAP_EN_MASK 0x100U /**< Output Tap Enable Mask */ +#define XSDPS_PHYREG1_OTAP_DLY_MASK 0xF000U /**< Output Tap Delay Mask */ +#define XSDPS_PHYREG1_OTAP_DLY_SHIFT 12U /**< Output Tap Delay Shift */ + +/** @} */ + +/** @name PHYCTRL Register2 - DLL enable, FREQ_SEL, Tx and Rx Dly Chain Sel + * + * This register contains bits for cDLL enable, FREQ_SEL, Tx and Rx Dly Chain Sel + * and DLL Ready. + * @{ + */ + +#define XSDPS_PHYREG2_DLL_EN_MASK 0x00000001U /**< DLL enable */ +#define XSDPS_PHYREG2_DLL_RDY_MASK 0x00000002U /**< DLL Ready */ +#define XSDPS_PHYREG2_FREQ_SEL_MASK 0x00000070U /**< Freq selection */ +#define XSDPS_PHYREG2_FREQ_SEL_SHIFT 4U /**< Freq selection shift */ +#define XSDPS_FREQ_SEL_170MHZ_200MHz 0U /**< Macro to select between 170MHz to 200MHz */ +#define XSDPS_FREQ_SEL_140MHZ_169MHz 1U /**< Macro to select between 140MHz to 169MHz */ +#define XSDPS_FREQ_SEL_110MHZ_139MHz 2U /**< Macro to select between 110MHz to 139MHz */ +#define XSDPS_FREQ_SEL_80MHZ_109MHz 3U /**< Macro to select between 80MHz to 109MHz */ +#define XSDPS_FREQ_SEL_50MHZ_79MHz 4U /**< Macro to select between 50MHz to 79MHz */ +#define XSDPS_PHYREG2_TRIM_ICP_MASK 0x00000F00U /**< DLL TRIM ICP */ +#define XSDPS_PHYREG2_TRIM_ICP_DEF_VAL 8U /**< DLL TRIM ICP default value */ +#define XSDPS_PHYREG2_TRIM_ICP_SHIFT 8U /**< DLL TRIM ICP shift */ +#define XSDPS_PHYREG2_DLYTX_SEL_MASK 0x00010000U /**< Delay Chain based Tx Clk */ +#define XSDPS_PHYREG2_DLYRX_SEL_MASK 0x00020000U /**< Delay Chain based Rx Clk */ +/** @} */ + +/** @name Commands + * + * Constant definitions for commands and response related to SD + * @{ + */ +/** + * Command/Response related to SD/eMMC + */ + +#define XSDPS_APP_CMD_PREFIX 0x8000U +#define CMD0 0x0000U +#define CMD1 0x0100U +#define CMD2 0x0200U +#define CMD3 0x0300U +#define CMD4 0x0400U +#define CMD5 0x0500U +#define CMD6 0x0600U +#define ACMD6 (XSDPS_APP_CMD_PREFIX + 0x0600U) +#define CMD7 0x0700U +#define CMD8 0x0800U +#define CMD9 0x0900U +#define CMD10 0x0A00U +#define CMD11 0x0B00U +#define CMD12 0x0C00U +#define ACMD13 (XSDPS_APP_CMD_PREFIX + 0x0D00U) +#define CMD16 0x1000U +#define CMD17 0x1100U +#define CMD18 0x1200U +#define CMD19 0x1300U +#define CMD21 0x1500U +#define CMD23 0x1700U +#define ACMD23 (XSDPS_APP_CMD_PREFIX + 0x1700U) +#define CMD24 0x1800U +#define CMD25 0x1900U +#define CMD32 0x2000U +#define CMD33 0x2100U +#define CMD35 0x2300U +#define CMD36 0x2400U +#define CMD38 0x2600U +#define CMD41 0x2900U +#define ACMD41 (XSDPS_APP_CMD_PREFIX + 0x2900U) +#define ACMD42 (XSDPS_APP_CMD_PREFIX + 0x2A00U) +#define ACMD51 (XSDPS_APP_CMD_PREFIX + 0x3300U) +#define CMD52 0x3400U +#define CMD55 0x3700U +#define CMD58 0x3A00U + +#define RESP_NONE (u32)XSDPS_CMD_RESP_NONE_MASK +#define RESP_R1 (u32)XSDPS_CMD_RESP_L48_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK | \ + (u32)XSDPS_CMD_INX_CHK_EN_MASK + +#define RESP_R1B (u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \ + (u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK + +#define RESP_R2 (u32)XSDPS_CMD_RESP_L136_MASK | (u32)XSDPS_CMD_CRC_CHK_EN_MASK +#define RESP_R3 (u32)XSDPS_CMD_RESP_L48_MASK + +#define RESP_R6 (u32)XSDPS_CMD_RESP_L48_BSY_CHK_MASK | \ + (u32)XSDPS_CMD_CRC_CHK_EN_MASK | (u32)XSDPS_CMD_INX_CHK_EN_MASK + +/** @} */ + +/** + * @name Card Interface + * @{ + */ +/** + * Card Interface Conditions Definitions + */ +#define XSDPS_CIC_CHK_PATTERN 0xAAU +#define XSDPS_CIC_VOLT_MASK (0xFU<<8) +#define XSDPS_CIC_VOLT_2V7_3V6 (1U<<8) +#define XSDPS_CIC_VOLT_LOW (1U<<9) +/** @} */ + +/** + * @name OCR + * @{ + */ +/** + * Operation Conditions Register Definitions + */ +#define XSDPS_OCR_PWRUP_STS (0x00000001U << 31) +#define XSDPS_OCR_CC_STS (0x00000001U << 30) +#define XSDPS_OCR_S18 (0x00000001U << 24) +#define XSDPS_OCR_3V5_3V6 (0x00000001U << 23) +#define XSDPS_OCR_3V4_3V5 (0x00000001U << 22) +#define XSDPS_OCR_3V3_3V4 (0x00000001U << 21) +#define XSDPS_OCR_3V2_3V3 (0x00000001U << 20) +#define XSDPS_OCR_3V1_3V2 (0x00000001U << 19) +#define XSDPS_OCR_3V0_3V1 (0x00000001U << 18) +#define XSDPS_OCR_2V9_3V0 (0x00000001U << 17) +#define XSDPS_OCR_2V8_2V9 (0x00000001U << 16) +#define XSDPS_OCR_2V7_2V8 (0x00000001U << 15) +#define XSDPS_OCR_1V7_1V95 (0x00000001U << 7) +#define XSDPS_OCR_HIGH_VOL 0x00FF8000U +#define XSDPS_OCR_LOW_VOL 0x00000080U +/** @} */ + +/** + * @name Card Configuration + * @{ + */ +/** + * SD Card Configuration Register Definitions + */ +#define XSDPS_SCR_REG_LEN 8U +#define XSDPS_SCR_STRUCT_MASK (0xFU<<28) +#define XSDPS_SCR_SPEC_MASK (0xFU<<24) +#define XSDPS_SCR_SPEC_1V0 0U +#define XSDPS_SCR_SPEC_1V1 (1U<<24) +#define XSDPS_SCR_SPEC_2V0_3V0 (2U<<24) +#define XSDPS_SCR_MEM_VAL_AF_ERASE (1U<<23) +#define XSDPS_SCR_SEC_SUPP_MASK (7U<<20) +#define XSDPS_SCR_SEC_SUPP_NONE 0U +#define XSDPS_SCR_SEC_SUPP_1V1 (2U<<20) +#define XSDPS_SCR_SEC_SUPP_2V0 (3U<<20) +#define XSDPS_SCR_SEC_SUPP_3V0 (4U<<20) +#define XSDPS_SCR_BUS_WIDTH_MASK (0xFU<<16) +#define XSDPS_SCR_BUS_WIDTH_1 (1U<<16) +#define XSDPS_SCR_BUS_WIDTH_4 (4U<<16) +#define XSDPS_SCR_SPEC3_MASK (1U<<12) +#define XSDPS_SCR_SPEC3_2V0 0U +#define XSDPS_SCR_SPEC3_3V0 (1U<<12) +#define XSDPS_SCR_CMD_SUPP_MASK 0x3U +#define XSDPS_SCR_CMD23_SUPP (1U<<1) +#define XSDPS_SCR_CMD20_SUPP (1U<<0) +/** @} */ + +/** + * @name Card Status + * @{ + */ +/** + * Card Status Register Definitions + */ +#define XSDPS_CD_STS_OUT_OF_RANGE (1U<<31) +#define XSDPS_CD_STS_ADDR_ERR (1U<<30) +#define XSDPS_CD_STS_BLK_LEN_ERR (1U<<29) +#define XSDPS_CD_STS_ER_SEQ_ERR (1U<<28) +#define XSDPS_CD_STS_ER_PRM_ERR (1U<<27) +#define XSDPS_CD_STS_WP_VIO (1U<<26) +#define XSDPS_CD_STS_IS_LOCKED (1U<<25) +#define XSDPS_CD_STS_LOCK_UNLOCK_FAIL (1U<<24) +#define XSDPS_CD_STS_CMD_CRC_ERR (1U<<23) +#define XSDPS_CD_STS_ILGL_CMD (1U<<22) +#define XSDPS_CD_STS_CARD_ECC_FAIL (1U<<21) +#define XSDPS_CD_STS_CC_ERR (1U<<20) +#define XSDPS_CD_STS_ERR (1U<<19) +#define XSDPS_CD_STS_CSD_OVRWR (1U<<16) +#define XSDPS_CD_STS_WP_ER_SKIP (1U<<15) +#define XSDPS_CD_STS_CARD_ECC_DIS (1U<<14) +#define XSDPS_CD_STS_ER_RST (1U<<13) +#define XSDPS_CD_STS_CUR_STATE (0xFU<<9) +#define XSDPS_CD_STS_RDY_FOR_DATA (1U<<8) +#define XSDPS_CD_STS_APP_CMD (1U<<5) +#define XSDPS_CD_STS_AKE_SEQ_ERR (1U<<2) +/** @} */ + +/** + * @name Switch function + * @{ + */ +/** + * Switch Function Definitions CMD6 + */ +#define XSDPS_SWITCH_SD_RESP_LEN 64U + +#define XSDPS_SWITCH_FUNC_SWITCH (1U<<31) +#define XSDPS_SWITCH_FUNC_CHECK 0U +/** @} */ + +/** + * @name Mode Function + * @{ + */ +/** + * Mode function groups definitions. + */ +#define XSDPS_MODE_FUNC_GRP1 1U +#define XSDPS_MODE_FUNC_GRP2 2U +#define XSDPS_MODE_FUNC_GRP3 3U +#define XSDPS_MODE_FUNC_GRP4 4U +#define XSDPS_MODE_FUNC_GRP5 5U +#define XSDPS_MODE_FUNC_GRP6 6U + +#define XSDPS_FUNC_GRP_DEF_VAL 0xFU +#define XSDPS_FUNC_ALL_GRP_DEF_VAL 0xFFFFFFU +/** @} */ + +/** + * @name Operating modes + * @{ + */ +/** + * SD operating modes in UHS. + */ +#define XSDPS_ACC_MODE_DEF_SDR12 0U +#define XSDPS_ACC_MODE_HS_SDR25 1U +#define XSDPS_ACC_MODE_SDR50 2U +#define XSDPS_ACC_MODE_SDR104 3U +#define XSDPS_ACC_MODE_DDR50 4U +/** @} */ + +/** + * @name General definitions + * @{ + */ +/** + * Definitions related to Driver strength, Current limit and + * CSD specific data. + */ +#define XSDPS_CMD_SYS_ARG_SHIFT 4U +#define XSDPS_CMD_SYS_DEF 0U +#define XSDPS_CMD_SYS_eC 1U +#define XSDPS_CMD_SYS_OTP 3U +#define XSDPS_CMD_SYS_ASSD 4U +#define XSDPS_CMD_SYS_VEND 5U + +#define XSDPS_DRV_TYPE_ARG_SHIFT 8U +#define XSDPS_DRV_TYPE_B 0U +#define XSDPS_DRV_TYPE_A 1U +#define XSDPS_DRV_TYPE_C 2U +#define XSDPS_DRV_TYPE_D 3U + +#define XSDPS_CUR_LIM_ARG_SHIFT 12U +#define XSDPS_CUR_LIM_200 0U +#define XSDPS_CUR_LIM_400 1U +#define XSDPS_CUR_LIM_600 2U +#define XSDPS_CUR_LIM_800 3U + +#define CSD_SPEC_VER_MASK 0x3C0000U +#define READ_BLK_LEN_MASK 0x00000F00U +#define C_SIZE_MULT_MASK 0x00000380U +#define C_SIZE_LOWER_MASK 0xFFC00000U +#define C_SIZE_UPPER_MASK 0x00000003U +#define CSD_STRUCT_MASK 0x00C00000U +#define CSD_V2_C_SIZE_MASK 0x3FFFFF00U +#define CSD_CCC_MASK 0xFFF00000U +#define CSD_CCC_SHIFT 20U +#define CSD_CCC_CLASS5_MASK 0x20U +/** @} */ + +/** + * @name Extended Card Specific Data + * @{ + */ +/** + * EXT_CSD field definitions + */ +#define XSDPS_EXT_CSD_SIZE 512U + +#define EXT_CSD_WR_REL_PARAM_EN (1U<<2) + +#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40U) +#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10U) +#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04U) +#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01U) + +#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7U) +#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1U) +#define EXT_CSD_PART_CONFIG_ACC_BOOT1 (0x2U) +#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3U) +#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4U) +#define EXT_CSD_PART_CONFIG_BYTE (179U) +#define XSDPS_MMC_PART_CFG_0_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24U) \ + | ((u32)EXT_CSD_PART_CONFIG_BYTE << 16U) \ + | ((u32)(0U) << 8U)) + +#define XSDPS_MMC_PART_CFG_1_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24U) \ + | ((u32)EXT_CSD_PART_CONFIG_BYTE << 16U) \ + | ((u32)EXT_CSD_PART_CONFIG_ACC_BOOT0 << 8U)) + +#define XSDPS_MMC_PART_CFG_2_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24U) \ + | ((u32)EXT_CSD_PART_CONFIG_BYTE << 16U) \ + | ((u32)EXT_CSD_PART_CONFIG_ACC_BOOT1 << 8U)) + +#define EXT_CSD_PART_SUPPORT_PART_EN (0x1U) + +#define EXT_CSD_CMD_SET_NORMAL (1U<<0) +#define EXT_CSD_CMD_SET_SECURE (1U<<1) +#define EXT_CSD_CMD_SET_CPSECURE (1U<<2) + +#define EXT_CSD_CARD_TYPE_26 (1U<<0) /* Card can run at 26MHz */ +#define EXT_CSD_CARD_TYPE_52 (1U<<1) /* Card can run at 52MHz */ +#define EXT_CSD_CARD_TYPE_MASK 0x3FU /* Mask out reserved bits */ +#define EXT_CSD_CARD_TYPE_DDR_1_8V (1U<<2) /* Card can run at 52MHz */ + /* DDR mode @1.8V or 3V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_1_2V (1U<<3) /* Card can run at 52MHz */ + /* DDR mode @1.2V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ + | EXT_CSD_CARD_TYPE_DDR_1_2V) +#define EXT_CSD_CARD_TYPE_SDR_1_8V (1U<<4) /* Card can run at 200MHz */ +#define EXT_CSD_CARD_TYPE_SDR_1_2V (1U<<5) /* Card can run at 200MHz */ + /* SDR mode @1.2V I/O */ +#define EXT_CSD_BUS_WIDTH_BYTE 183U +#define EXT_CSD_BUS_WIDTH_1_BIT 0U /* Card is in 1 bit mode */ +#define EXT_CSD_BUS_WIDTH_4_BIT 1U /* Card is in 4 bit mode */ +#define EXT_CSD_BUS_WIDTH_8_BIT 2U /* Card is in 8 bit mode */ +#define EXT_CSD_BUS_WIDTH_DDR_4_BIT 5U /* Card is in 4 bit DDR mode */ +#define EXT_CSD_BUS_WIDTH_DDR_8_BIT 6U /* Card is in 8 bit DDR mode */ + +#define EXT_CSD_HS_TIMING_BYTE 185U +#define EXT_CSD_HS_TIMING_DEF 0U +#define EXT_CSD_HS_TIMING_HIGH 1U /* Card is in high speed mode */ +#define EXT_CSD_HS_TIMING_HS200 2U /* Card is in HS200 mode */ +#define EXT_CSD_HS_TIMING_HS400 3U /* Card is in HS200 mode */ + +#define EXT_CSD_RST_N_FUN_BYTE 162U +#define EXT_CSD_RST_N_FUN_TEMP_DIS 0U /* RST_n signal is temporarily disabled */ +#define EXT_CSD_RST_N_FUN_PERM_EN 1U /* RST_n signal is permanently enabled */ +#define EXT_CSD_RST_N_FUN_PERM_DIS 2U /* RST_n signal is permanently disabled */ + +#define XSDPS_EXT_CSD_CMD_SET 0U +#define XSDPS_EXT_CSD_SET_BITS 1U +#define XSDPS_EXT_CSD_CLR_BITS 2U +#define XSDPS_EXT_CSD_WRITE_BYTE 3U +/** @} */ + +/** + * @name SD/eMMC Bus Speed and Bus Width Arguments + * @{ + */ +/** + * SD/MMC Arguments for Bus Speed and Bus Width. + */ +#define XSDPS_MMC_DEF_SPEED_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \ + | ((u32)EXT_CSD_HS_TIMING_DEF << 8)) + +#define XSDPS_MMC_HIGH_SPEED_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \ + | ((u32)EXT_CSD_HS_TIMING_HIGH << 8)) + +#define XSDPS_MMC_HS200_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \ + | ((u32)EXT_CSD_HS_TIMING_HS200 << 8)) + +#define XSDPS_MMC_HS400_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_HS_TIMING_BYTE << 16) \ + | ((u32)EXT_CSD_HS_TIMING_HS400 << 8)) + +#define XSDPS_MMC_1_BIT_BUS_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | ((u32)EXT_CSD_BUS_WIDTH_1_BIT << 8)) + +#define XSDPS_MMC_4_BIT_BUS_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | ((u32)EXT_CSD_BUS_WIDTH_4_BIT << 8)) + +#define XSDPS_MMC_8_BIT_BUS_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | ((u32)EXT_CSD_BUS_WIDTH_8_BIT << 8)) + +#define XSDPS_MMC_DDR_4_BIT_BUS_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | ((u32)EXT_CSD_BUS_WIDTH_DDR_4_BIT << 8)) + +#define XSDPS_MMC_DDR_8_BIT_BUS_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | ((u32)EXT_CSD_BUS_WIDTH_DDR_8_BIT << 8)) + +#define XSDPS_MMC_RST_FUN_EN_ARG (((u32)XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | ((u32)EXT_CSD_RST_N_FUN_BYTE << 16) \ + | ((u32)EXT_CSD_RST_N_FUN_PERM_EN << 8)) + +#define XSDPS_MMC_DELAY_FOR_SWITCH 1000U + +/** @} */ + +/** + * @name General Delay definitions + * @{ + */ +/** + * @400KHz, in usec + */ +#define XSDPS_74CLK_DELAY 2960U +#define XSDPS_100CLK_DELAY 4000U +#define XSDPS_INIT_DELAY 10000U +/** @} */ + +#define XSDPS_DEF_VOLT_LVL XSDPS_PC_BUS_VSEL_3V0_MASK /**< Default voltage level */ +#define XSDPS_CARD_DEF_ADDR 0x1234U /**< Card Default address */ + +#define XSDPS_CARD_SD 1U /**< SD card */ +#define XSDPS_CARD_MMC 2U /**< MMC card */ +#define XSDPS_CARD_SDIO 3U /**< SDIO card */ +#define XSDPS_CARD_SDCOMBO 4U /**< SDCOMBO card */ +#define XSDPS_CHIP_EMMC 5U /**< EMMC chip */ + + +/** + *@name ADMA2 Descriptor related definitions + * @{ + */ +/** + * ADMA2 Descriptor related definitions + */ +#define XSDPS_DESC_MAX_LENGTH 65536U + +#define XSDPS_DESC_VALID (0x1U << 0) +#define XSDPS_DESC_END (0x1U << 1) +#define XSDPS_DESC_INT (0x1U << 2) +#define XSDPS_DESC_TRAN (0x2U << 4) + +/** @} */ + +/* For changing clock frequencies */ +#define XSDPS_CLK_400_KHZ 400000U /**< 400 KHZ */ +#define XSDPS_CLK_50_MHZ 50000000U /**< 50 MHZ */ +#define XSDPS_CLK_52_MHZ 52000000U /**< 52 MHZ */ +#define XSDPS_SD_VER_1_0 0x1U /**< SD ver 1 */ +#define XSDPS_SD_VER_2_0 0x2U /**< SD ver 2 */ +#define XSDPS_SCR_BLKCNT 1U /**< SCR Block Count */ +#define XSDPS_SCR_BLKSIZE 8U /**< SCR Block Size */ +#define XSDPS_1_BIT_WIDTH 0x1U /**< Bus Width 1 */ +#define XSDPS_4_BIT_WIDTH 0x2U /**< Bus Width 4 */ +#define XSDPS_8_BIT_WIDTH 0x3U /**< Bus Width 8 */ +#define XSDPS_UHS_SPEED_MODE_SDR12 0x0U /**< SDR12 mode */ +#define XSDPS_UHS_SPEED_MODE_SDR25 0x1U /**< SDR25 mode */ +#define XSDPS_UHS_SPEED_MODE_SDR50 0x2U /**< SDR50 mode */ +#define XSDPS_UHS_SPEED_MODE_SDR104 0x3U /**< SDR104 mode */ +#define XSDPS_UHS_SPEED_MODE_DDR50 0x4U /**< DDR50 mode */ +#define XSDPS_HIGH_SPEED_MODE 0x5U /**< High Speed mode */ +#define XSDPS_DEFAULT_SPEED_MODE 0x6U /**< Default speed mode */ +#define XSDPS_HS200_MODE 0x7U /**< eMMC HS200 mode */ +#define XSDPS_HS400_MODE 0x8U /**< eMMC HS400 mode */ +#define XSDPS_DDR52_MODE 0x4U /**< eMMC DDR52 mode */ +#define XSDPS_SWITCH_CMD_BLKCNT 1U /**< Blk cnt for SWITCH cmd */ +#define XSDPS_SWITCH_CMD_BLKSIZE 64U /**< Blk sz for SWITCH cmd */ +#define XSDPS_SWITCH_CMD_HS_GET 0x00FFFFF0U /**< SWITCH cmd to Get HS */ +#define XSDPS_SWITCH_CMD_HS_SET 0x80FFFFF1U /**< SWITCH cmd to Set HS */ +#define XSDPS_SWITCH_CMD_SDR12_SET 0x80FFFFF0U /**< SWITCH cmd to Set SDR12 */ +#define XSDPS_SWITCH_CMD_SDR25_SET 0x80FFFFF1U /**< SWITCH cmd to Set SDR25 */ +#define XSDPS_SWITCH_CMD_SDR50_SET 0x80FFFFF2U /**< SWITCH cmd to Set SDR50 */ +#define XSDPS_SWITCH_CMD_SDR104_SET 0x80FFFFF3U /**< SWITCH cmd to Set SDR104 */ +#define XSDPS_SWITCH_CMD_DDR50_SET 0x80FFFFF4U /**< SWITCH cmd to Set DDR50 */ +#define XSDPS_EXT_CSD_CMD_BLKCNT 1U /**< Blk Cnt for EXT CSD */ +#define XSDPS_EXT_CSD_CMD_BLKSIZE 512U /**< Blk Sz for EXT CSD */ +#define XSDPS_TUNING_CMD_BLKCNT 1U /**< Blk Cnt for Tuning cmd */ +#define XSDPS_TUNING_CMD_BLKSIZE 64U /**< Blk Sz for Tuning cmd */ +#define XSDPS_SD_STATUS_BLKCNT 1U /**< Blk Cnt for SD status */ +#define XSDPS_SD_STATUS_BLKSIZE 64U /**< Blk Sz for SD status */ + +#define XSDPS_HIGH_SPEED_MAX_CLK 50000000U /**< Max clk for HS mode */ +#define XSDPS_UHS_SDR104_MAX_CLK 208000000U /**< Max clk for SDR104 mode */ +#define XSDPS_UHS_SDR50_MAX_CLK 100000000U /**< Max clk for SDR50 mode */ +#define XSDPS_UHS_DDR50_MAX_CLK 50000000U /**< Max clk for DDR50 mode */ +#define XSDPS_UHS_SDR25_MAX_CLK 50000000U /**< Max clk for SDR25 mode */ +#define XSDPS_UHS_SDR12_MAX_CLK 25000000U /**< Max clk for SDR12 mode */ + +#define SD_DRIVER_TYPE_B 0x01U /**< Driver Type B */ +#define SD_DRIVER_TYPE_A 0x02U /**< Driver Type A */ +#define SD_DRIVER_TYPE_C 0x04U /**< Driver Type C */ +#define SD_DRIVER_TYPE_D 0x08U /**< Driver Type D */ +#define SD_SET_CURRENT_LIMIT_200 0U /**< Current limit 200mA */ +#define SD_SET_CURRENT_LIMIT_400 1U /**< Current limit 400mA */ +#define SD_SET_CURRENT_LIMIT_600 2U /**< Current limit 600mA */ +#define SD_SET_CURRENT_LIMIT_800 3U /**< Current limit 800mA */ + +#define SD_MAX_CURRENT_200 (1U << SD_SET_CURRENT_LIMIT_200) /**< Current limit 200mA Arg */ +#define SD_MAX_CURRENT_400 (1U << SD_SET_CURRENT_LIMIT_400) /**< Current limit 400mA Arg */ +#define SD_MAX_CURRENT_600 (1U << SD_SET_CURRENT_LIMIT_600) /**< Current limit 600mA Arg */ +#define SD_MAX_CURRENT_800 (1U << SD_SET_CURRENT_LIMIT_800) /**< Current limit 800mA Arg */ + +#define XSDPS_SD_SDR12_MAX_CLK 25000000U /**< Max clk for SDR12 mode */ +#define XSDPS_SD_SDR25_MAX_CLK 50000000U /**< Max clk for SDR25 mode */ +#define XSDPS_SD_SDR50_MAX_CLK 100000000U /**< Max clk for SDR50 mode */ +#define XSDPS_SD_DDR50_MAX_CLK 50000000U /**< Max clk for DDR50 mode */ +#define XSDPS_SD_SDR104_MAX_CLK 208000000U /**< Max clk for SDR104 mode */ +/** + * XSDPS_SD_INPUT_MAX_CLK is set to 175000000 in order to keep it smaller + * than the clock value coming from the core. This value is kept to safely + * switch to SDR104 mode if the SD card supports it. + */ +#define XSDPS_SD_INPUT_MAX_CLK 175000000U + +#define XSDPS_MMC_HS200_MAX_CLK 200000000U /**< Max clk for MMC HS200 mode */ +#define XSDPS_MMC_HSD_MAX_CLK 52000000U /**< Max clk for MMC HSD mode */ +#define XSDPS_MMC_DDR_MAX_CLK 52000000U /**< Max clk for MMC DDR52 mode */ + +#define XSDPD_MIN_DLL_MODE_CLK 50000000U /**< Min clk for DLL mode */ + +/** + * @name Card states + * @{ + */ +/** + * Definition for Card state. + */ +#define XSDPS_CARD_STATE_IDLE 0U +#define XSDPS_CARD_STATE_RDY 1U +#define XSDPS_CARD_STATE_IDEN 2U +#define XSDPS_CARD_STATE_STBY 3U +#define XSDPS_CARD_STATE_TRAN 4U +#define XSDPS_CARD_STATE_DATA 5U +#define XSDPS_CARD_STATE_RCV 6U +#define XSDPS_CARD_STATE_PROG 7U +#define XSDPS_CARD_STATE_DIS 8U +#define XSDPS_CARD_STATE_BTST 9U +#define XSDPS_CARD_STATE_SLP 10U +/** @} */ + +#define XSDPS_SLOT_REM 0U /**< Removable slot */ +#define XSDPS_SLOT_EMB 1U /**< Embedded slot */ + +#define XSDPS_WIDTH_8 8U /**< Bus width 8 */ +#define XSDPS_WIDTH_4 4U /**< Bus width 4 */ + +#define XSDPS_SLOTTYPE_SDADIR 4U /**< SD3.0 Auto Direction */ + +/** + * @name Tap delays + * @{ + */ +/** + * SD/eMMC ITAP and OTAP delays for different operating modes + * for both Versal and ZynqMP platforms. + */ +#ifdef VERSAL_NET +#define SD_ITAPDLY_SEL_MASK 0x000000FFU +#define SD_OTAPDLY_SEL_MASK 0x0000003FU +#define SD_ITAPDLY 0x0000F0F8U +#define SD_OTAPDLY 0x0000F0FCU +#define SD0_DLL_CTRL 0x00000448U +#define SD1_DLL_CTRL 0x000004C8U +#define SD_DLL_RST 0x00000004U +#define SD_ITAPCHGWIN 0x00000200U +#define SD_ITAPDLYENA 0x00000100U +#define SD_OTAPDLYENA 0x00000040U +#define SD_OTAPDLYSEL_HS200_B0 0x00000007U +#define SD_OTAPDLYSEL_HS200_B2 0x00000007U +#define SD_OTAPDLYSEL_HS400 0x00000004U +#define SD_ITAPDLYSEL_SD50 0x0000000EU +#define SD_OTAPDLYSEL_SD50 0x00000003U +#define SD_ITAPDLYSEL_SD_DDR50 0x00000036U +#define SD_ITAPDLYSEL_EMMC_DDR50 0x00000003U +#define SD_OTAPDLYSEL_SD_DDR50 0x00000003U +#define SD_OTAPDLYSEL_EMMC_DDR50 0x00000005U +#define SD_ITAPDLYSEL_HSD 0x0000002CU +#define SD_ITAPDLYSEL_EMMC_HSD 0x00000000U +#define SD_OTAPDLYSEL_SD_HSD 0x00000004U +#define SD_OTAPDLYSEL_EMMC_HSD 0x00000005U +#define SD_AUTODIR_ITAPDLYSEL_HSD 0x00000025U +#define SD_AUTODIR_ITAPDLYSEL_SDR25 0x00000026U +#define SD_AUTODIR_ITAPDLYSEL_DDR50 0x0000002AU +#define PHY_STRB_SEL_SIG 0x00000077U +#elif defined (versal) +#define SD_ITAPDLY_SEL_MASK 0x000000FFU +#define SD_OTAPDLY_SEL_MASK 0x0000003FU +#define SD_ITAPDLY 0x0000F0F8U +#define SD_OTAPDLY 0x0000F0FCU +#define SD0_DLL_CTRL 0x00000448U +#define SD1_DLL_CTRL 0x000004C8U +#define SD_DLL_RST 0x00000004U +#define SD_ITAPCHGWIN 0x00000200U +#define SD_ITAPDLYENA 0x00000100U +#define SD_OTAPDLYENA 0x00000040U +#define SD_OTAPDLYSEL_HS200_B0 0x00000002U +#define SD_OTAPDLYSEL_HS200_B2 0x00000002U +#define SD_ITAPDLYSEL_SD50 0x0000000EU +#define SD_OTAPDLYSEL_SD50 0x00000003U +#define SD_ITAPDLYSEL_SD_DDR50 0x00000036U +#define SD_ITAPDLYSEL_EMMC_DDR50 0x0000001EU +#define SD_OTAPDLYSEL_SD_DDR50 0x00000003U +#define SD_OTAPDLYSEL_EMMC_DDR50 0x00000005U +#define SD_ITAPDLYSEL_HSD 0x0000002CU +#define SD_ITAPDLYSEL_EMMC_HSD 0x0000002CU +#define SD_OTAPDLYSEL_SD_HSD 0x00000004U +#define SD_OTAPDLYSEL_EMMC_HSD 0x00000005U +#define SD_AUTODIR_ITAPDLYSEL_HSD 0x00000025U +#define SD_AUTODIR_ITAPDLYSEL_SDR25 0x00000026U +#define SD_AUTODIR_ITAPDLYSEL_DDR50 0x0000002AU +#else +#define SD0_ITAPDLY_SEL_MASK 0x000000FFU +#define SD0_OTAPDLY_SEL_MASK 0x0000003FU +#define SD1_ITAPDLY_SEL_MASK 0x00FF0000U +#define SD1_OTAPDLY_SEL_MASK 0x003F0000U +#define SD_DLL_CTRL 0x00000358U +#define SD_ITAPDLY 0x00000314U +#define SD_OTAPDLY 0x00000318U +#define SD0_DLL_RST 0x00000004U +#define SD1_DLL_RST 0x00040000U +#define SD0_ITAPCHGWIN 0x00000200U +#define SD0_ITAPDLYENA 0x00000100U +#define SD0_OTAPDLYENA 0x00000040U +#define SD1_ITAPCHGWIN 0x02000000U +#define SD1_ITAPDLYENA 0x01000000U +#define SD1_OTAPDLYENA 0x00400000U +#define SD_OTAPDLYSEL_HS200_B0 0x00000003U +#define SD_OTAPDLYSEL_HS200_B2 0x00000002U +#define SD_ITAPDLYSEL_SD50 0x00000014U +#define SD_OTAPDLYSEL_SD50 0x00000003U +#define SD_ITAPDLYSEL_SD_DDR50 0x0000003DU +#define SD_ITAPDLYSEL_EMMC_DDR50 0x00000012U +#define SD_OTAPDLYSEL_SD_DDR50 0x00000004U +#define SD_OTAPDLYSEL_EMMC_DDR50 0x00000006U +#define SD_ITAPDLYSEL_HSD 0x00000015U +#define SD_ITAPDLYSEL_EMMC_HSD 0x00000015U +#define SD_OTAPDLYSEL_SD_HSD 0x00000005U +#define SD_OTAPDLYSEL_EMMC_HSD 0x00000006U +#define SD_AUTODIR_ITAPDLYSEL_HSD 0x00000028U +#define SD_AUTODIR_ITAPDLYSEL_SDR25 0x0000002CU +#define SD_AUTODIR_ITAPDLYSEL_DDR50 0x00000033U +#endif +/** @} */ + +#ifdef __MICROBLAZE__ +#define XPS_SYS_CTRL_BASEADDR 0xFF180000U /**< System controller Baseaddress */ +#endif + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +#define XSdPs_In64 Xil_In64 /**< Low level 64-bit data read */ +#define XSdPs_Out64 Xil_Out64 /**< Low level 64-bit data write */ + +#define XSdPs_In32 Xil_In32 /**< Low level 32-bit data read */ +#define XSdPs_Out32 Xil_Out32 /**< Low level 32-bit data write */ + +#define XSdPs_In16 Xil_In16 /**< Low level 16-bit data read */ +#define XSdPs_Out16 Xil_Out16 /**< Low level 16-bit data write */ + +#define XSdPs_In8 Xil_In8 /**< Low level 8-bit data read */ +#define XSdPs_Out8 Xil_Out8 /**< Low level 8-bit data write */ + +/****************************************************************************/ +/** +* Read a register. +* +* @param InstancePtr is the pointer to the sdps instance. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XSdPs_ReadReg(XSdPs *InstancePtr. s32 RegOffset) +* +******************************************************************************/ +#define XSdPs_ReadReg64(InstancePtr, RegOffset) \ + XSdPs_In64((InstancePtr->Config.BaseAddress) + RegOffset) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param InstancePtr is the pointer to the sdps instance. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XSdPs_WriteReg(XSdPs *InstancePtr, s32 RegOffset, +* u64 RegisterValue) +* +******************************************************************************/ +#define XSdPs_WriteReg64(InstancePtr, RegOffset, RegisterValue) \ + XSdPs_Out64((InstancePtr->Config.BaseAddress) + (RegOffset), \ + (RegisterValue)) + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XSdPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +#define XSdPs_ReadReg(BaseAddress, RegOffset) \ + XSdPs_In32((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset)) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XSdPs_WriteReg(u32 BaseAddress, int RegOffset, +* u32 RegisterValue) +* +******************************************************************************/ +#define XSdPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XSdPs_Out32((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset), (RegisterValue)) + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u16 XSdPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +static INLINE u16 XSdPs_ReadReg16(u32 BaseAddress, u8 RegOffset) +{ +#if defined (__MICROBLAZE__) + u32 Reg; + BaseAddress += RegOffset & 0xFC; + Reg = XSdPs_In32(BaseAddress); + Reg >>= ((RegOffset & 0x3)*8); + return (u16)Reg; +#else + return XSdPs_In16((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset)); +#endif +} + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XSdPs_WriteReg(u32 BaseAddress, int RegOffset, +* u16 RegisterValue) +* +******************************************************************************/ + +static INLINE void XSdPs_WriteReg16(u32 BaseAddress, u8 RegOffset, u16 RegisterValue) +{ +#if defined (__MICROBLAZE__) + u32 Reg; + BaseAddress += RegOffset & 0xFC; + Reg = XSdPs_In32(BaseAddress); + Reg &= ~(0xFFFFU<<((RegOffset & 0x3)*8)); + Reg |= RegisterValue <<((RegOffset & 0x3)*8); + XSdPs_Out32(BaseAddress, Reg); +#else + XSdPs_Out16((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset), (RegisterValue)); +#endif +} + +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u8 XSdPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +static INLINE u8 XSdPs_ReadReg8(u32 BaseAddress, u8 RegOffset) +{ +#if defined (__MICROBLAZE__) + u32 Reg; + BaseAddress += RegOffset & 0xFC; + Reg = XSdPs_In32(BaseAddress); + Reg >>= ((RegOffset & 0x3)*8); + return (u8)Reg; +#else + return XSdPs_In8((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset)); +#endif +} +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XSdPs_WriteReg(u32 BaseAddress, int RegOffset, +* u8 RegisterValue) +* +******************************************************************************/ +static INLINE void XSdPs_WriteReg8(u32 BaseAddress, u8 RegOffset, u8 RegisterValue) +{ +#if defined (__MICROBLAZE__) + u32 Reg; + BaseAddress += RegOffset & 0xFC; + Reg = XSdPs_In32(BaseAddress); + Reg &= ~(0xFFU<<((RegOffset & 0x3)*8)); + Reg |= RegisterValue <<((RegOffset & 0x3)*8); + XSdPs_Out32(BaseAddress, Reg); +#else + XSdPs_Out8((UINTPTR)(BaseAddress) + (UINTPTR)(RegOffset), (RegisterValue)); +#endif +} +/***************************************************************************/ +/** +* Macro to get present status register +* +* @param BaseAddress contains the base address of the device. +* +* @return None. +* +* @note C-Style signature: +* void XSdPs_WriteReg(u32 BaseAddress, int RegOffset, +* u8 RegisterValue) +* +******************************************************************************/ +#define XSdPs_GetPresentStatusReg(BaseAddress) \ + XSdPs_In32((BaseAddress) + (XSDPS_PRES_STATE_OFFSET)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* SD_HW_H_ */ +/** @endcond */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_options.c b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_options.c new file mode 100644 index 0000000..fa9a421 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_options.c @@ -0,0 +1,901 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps_options.c +* @addtogroup sdps Overview +* @{ +* +* The xsdps_options.c file ontains APIs for changing the various options in host and card. +* See xsdps.h for a detailed description of the device and driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 1.00a hk/sg  10/17/13 Initial release
+* 2.1   hk     04/18/14 Increase sleep for eMMC switch command.
+*                       Add sleep for microblaze designs. CR# 781117.
+* 2.3   sk     09/23/14 Use XSdPs_Change_ClkFreq API whenever changing
+*						clock.CR# 816586.
+* 2.5 	sg	   07/09/15 Added SD 3.0 features
+*       kvn    07/15/15 Modified the code according to MISRAC-2012.
+* 2.7   sk     01/08/16 Added workaround for issue in auto tuning mode
+*                       of SDR50, SDR104 and HS200.
+*       sk     02/16/16 Corrected the Tuning logic.
+*       sk     03/02/16 Configured the Tap Delay values for eMMC HS200 mode.
+* 2.8   sk     04/20/16 Added new workaround for auto tuning.
+* 3.0   sk     07/07/16 Used usleep API for both arm and microblaze.
+*       sk     07/16/16 Added support for UHS modes.
+*       sk     07/16/16 Added Tap delays accordingly to different SD/eMMC
+*                       operating modes.
+* 3.1   mi     09/07/16 Removed compilation warnings with extra compiler flags.
+*       sk     11/07/16 Enable Rst_n bit in ext_csd reg if not enabled.
+*       sk     11/16/16 Issue DLL reset at 31 iteration to load new zero value.
+* 3.2   sk     02/01/17 Added HSD and DDR mode support for eMMC.
+*       sk     02/01/17 Consider bus width parameter from design for switching
+*       vns    02/09/17 Added ARMA53_32 support for ZynqMP CR#968397
+*       vns    03/13/17 Fixed MISRAC mandatory violation
+*       sk     03/20/17 Add support for EL1 non-secure mode.
+* 3.3   mn     07/25/17 Removed SD0_OTAPDLYENA and SD1_OTAPDLYENA bits
+*       mn     08/07/17	Properly set OTAPDLY value by clearing previous bit
+* 			settings
+*       mn     08/17/17 Added CCI support for A53 and disabled data cache
+*                       operations when it is enabled.
+*       mn     08/22/17 Updated for Word Access System support
+* 3.4   mn     01/22/18 Separated out SDR104 and HS200 clock defines
+* 3.6   mn     07/06/18 Fix Cppcheck warnings for sdps driver
+* 3.7   aru    03/12/19 Modified the code according to MISRAC-2012.
+*       mn     03/27/19 Disable calls to dll_reset API for versal SPP Platforms
+* 3.8   mn     04/12/19 Modified TapDelay code for supporting ZynqMP and Versal
+*       mn     05/21/19 Set correct tap delays for Versal
+*       mn     05/21/19 Disable DLL Reset code for Versal
+*       mn     08/29/19 Add call to Cache Invalidation API in XSdPs_Get_BusWidth
+* 3.9   mn     03/03/20 Restructured the code for more readability and modularity
+*       mn     03/16/20 Move XSdPs_Select_Card API to User APIs
+* 3.10  mn     06/05/20 Modified code for SD Non-Blocking Read support
+* 3.12  sk     01/28/21 Added support for non-blocking write.
+* 3.14  mn     11/28/21 Fix MISRA-C violations.
+* 4.0   sk     02/25/22 Add support for eMMC5.1.
+* 4.1   sk     11/10/22 Add SD/eMMC Tap delay support for Versal Net.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xsdps_core.h" +/************************** Constant Definitions *****************************/ +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* @brief +* API to change clock freq to given value. +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param SelFreq - Clock frequency in Hz. +* +* @return None +* +* @note This API will change clock frequency to the value less than +* or equal to the given value using the permissible dividors. +* +******************************************************************************/ +s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq) +{ + s32 Status; +#ifdef VERSAL_NET + u32 Reg; +#endif + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#ifndef VERSAL_NET + if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) { + /* Program the Tap delays */ + XSdPs_SetTapDelay(InstancePtr); + } +#else + if (InstancePtr->CardType == XSDPS_CARD_SD) { + XSdPs_SetTapDelay(InstancePtr); + } else { + Reg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_PHYCTRLREG1_OFFSET); + Reg &= ~(XSDPS_PHYREG1_STROBE_SEL_MASK | XSDPS_PHYREG1_OTAP_DLY_MASK | + XSDPS_PHYREG1_OTAP_EN_MASK | XSDPS_PHYREG1_ITAP_EN_MASK | + XSDPS_PHYREG1_ITAP_DLY_MASK); + if (InstancePtr->OTapDelay != 0U) { + Reg |= (InstancePtr->OTapDelay << XSDPS_PHYREG1_OTAP_DLY_SHIFT); + Reg |= XSDPS_PHYREG1_OTAP_EN_MASK; + } + + Reg |= XSDPS_PHYREG1_ITAP_CHGWIN_MASK; + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_PHYCTRLREG1_OFFSET, Reg); + if (InstancePtr->ITapDelay != 0U) { + Reg |= (InstancePtr->ITapDelay << XSDPS_PHYREG1_ITAP_DLY_SHIFT); + Reg |= XSDPS_PHYREG1_ITAP_EN_MASK; + } + + Reg &= ~XSDPS_PHYREG1_ITAP_CHGWIN_MASK; + if (InstancePtr->Mode == XSDPS_HS400_MODE) + Reg |= (PHY_STRB_SEL_SIG | PHY_STRB_SEL_SIG) << XSDPS_PHYREG1_STROBE_SEL_SHIFT; + + XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_PHYCTRLREG1_OFFSET, Reg); + } +#endif + + Status = XSdPs_SetClock(InstancePtr, SelFreq); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* Update Block size for read/write operations. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param BlkSize - Block size passed by the user. +* +* @return None +* +******************************************************************************/ +s32 XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Status = XSdPs_CheckBusIdle(InstancePtr, (XSDPS_PSR_INHIBIT_CMD_MASK + | XSDPS_PSR_INHIBIT_DAT_MASK + | XSDPS_PSR_WR_ACTIVE_MASK + | XSDPS_PSR_RD_ACTIVE_MASK)); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH ; + } + + /* Send block write command */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Set block size to the value passed */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET, + BlkSize & XSDPS_BLK_SIZE_MASK); + + InstancePtr->BlkSize = BlkSize; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief +* API to get bus width support by card. +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param ReadBuff - buffer to store SCR register returned by card. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note None. +* +******************************************************************************/ +s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff) +{ + s32 Status; + u16 BlkCnt; + u16 BlkSize; + s32 LoopCnt; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + for (LoopCnt = 0; LoopCnt < 8; LoopCnt++) { + ReadBuff[LoopCnt] = 0U; + } + + /* Send block write command */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD55, + InstancePtr->RelCardAddr, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + BlkCnt = XSDPS_SCR_BLKCNT; + BlkSize = XSDPS_SCR_BLKSIZE; + + XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff); + + Status = XSdPs_CmdTransfer(InstancePtr, ACMD51, 0U, BlkCnt); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check for transfer done */ + Status = XSdps_CheckTransferDone(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (InstancePtr->Config.IsCacheCoherent == 0U) { + Xil_DCacheInvalidateRange((INTPTR)ReadBuff, + ((INTPTR)BlkCnt * (INTPTR)BlkSize)); + } + + Status = XST_SUCCESS; + + RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief +* API to set bus width to 4-bit in card and host +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note None. +* +******************************************************************************/ +s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr) +{ + s32 Status; + u32 StatusReg; + u32 Arg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * check for bus width for 3.0 controller and return if + * bus width is <4 + */ + if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) && + (InstancePtr->Config.BusWidth < XSDPS_WIDTH_4)) { + Status = XST_SUCCESS; + goto RETURN_PATH; + } + + if (InstancePtr->CardType == XSDPS_CARD_SD) { + + Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr, + 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, (u32)InstancePtr->BusWidth, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else { + if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) { + if ((InstancePtr->Mode == XSDPS_DDR52_MODE) || + (InstancePtr->Mode == XSDPS_HS400_MODE)) { + Arg = XSDPS_MMC_DDR_8_BIT_BUS_ARG; + } else { + Arg = XSDPS_MMC_8_BIT_BUS_ARG; + } + } else { + if (InstancePtr->Mode == XSDPS_DDR52_MODE) { + Arg = XSDPS_MMC_DDR_4_BIT_BUS_ARG; + } else { + Arg = XSDPS_MMC_4_BIT_BUS_ARG; + } + } + + Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, Arg); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + usleep(XSDPS_MMC_DELAY_FOR_SWITCH); + + StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL1_OFFSET); + + /* Width setting in controller */ + if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) { + StatusReg |= XSDPS_HC_EXT_BUS_WIDTH; + } else { + StatusReg |= XSDPS_HC_WIDTH_MASK; + } + + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL1_OFFSET, + (u8)StatusReg); + + if (InstancePtr->Mode == XSDPS_DDR52_MODE) { + StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET); + StatusReg &= (~(u32)XSDPS_HC2_UHS_MODE_MASK); + StatusReg |= InstancePtr->Mode; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET, (u16)StatusReg); + } + + Status = XST_SUCCESS; + + RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief +* API to get bus speed supported by card. +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param ReadBuff - buffer to store function group support data +* returned by card. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note None. +* +******************************************************************************/ +s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff) +{ + s32 Status; + u32 Arg; + u16 BlkCnt; + u16 BlkSize; + s32 LoopCnt; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + for (LoopCnt = 0; LoopCnt < 64; LoopCnt++) { + ReadBuff[LoopCnt] = 0U; + } + + BlkCnt = XSDPS_SWITCH_CMD_BLKCNT; + BlkSize = XSDPS_SWITCH_CMD_BLKSIZE; + + XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff); + + Arg = XSDPS_SWITCH_CMD_HS_GET; + + Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check for transfer done */ + Status = XSdps_CheckTransferDone(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (InstancePtr->Config.IsCacheCoherent == 0U) { + Xil_DCacheInvalidateRange((INTPTR)ReadBuff, + ((INTPTR)BlkCnt * (INTPTR)BlkSize)); + } + + Status = XST_SUCCESS; + + RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief +* API to get SD card status information. +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param SdStatReg - buffer to store status data returned by card. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note None. +* +******************************************************************************/ +s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg) +{ + s32 Status; + u16 BlkCnt; + u16 BlkSize; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Send block write command */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD55, + InstancePtr->RelCardAddr, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + BlkCnt = XSDPS_SD_STATUS_BLKCNT; + BlkSize = XSDPS_SD_STATUS_BLKSIZE; + + XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, SdStatReg); + + Status = XSdPs_CmdTransfer(InstancePtr, ACMD13, 0U, BlkCnt); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check for transfer done */ + Status = XSdps_CheckTransferDone(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (InstancePtr->Config.IsCacheCoherent == 0U) { + Xil_DCacheInvalidateRange((INTPTR)SdStatReg, + ((INTPTR)BlkCnt * (INTPTR)BlkSize)); + } + + Status = XST_SUCCESS; + + RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief +* API to set high speed in card and host. Changes clock in host accordingly. +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note None. +* +******************************************************************************/ +s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr) +{ + s32 Status; + u32 StatusReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (InstancePtr->CardType == XSDPS_CARD_SD) { + Status = XSdPs_Change_SdBusSpeed(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else { + Status = XSdPs_Change_MmcBusSpeed(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if ((InstancePtr->Mode == XSDPS_HS400_MODE) || + (InstancePtr->Mode == XSDPS_HS200_MODE) || + (InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR104) || + (InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR50)) { + Status = XSdPs_Execute_Tuning(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + usleep(XSDPS_MMC_DELAY_FOR_SWITCH); + + StatusReg = (u32)XSdPs_ReadReg8(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL1_OFFSET); + StatusReg |= XSDPS_HC_SPEED_MASK; + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL1_OFFSET, (u8)StatusReg); + +#ifdef VERSAL_NET + if (InstancePtr->Mode == XSDPS_HS400_MODE) { + InstancePtr->IsTuningDone = 1U; + Status = XSdPs_Select_HS400(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } +#endif + + Status = XST_SUCCESS; + + RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief +* API to get EXT_CSD register of eMMC. +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param ReadBuff - buffer to store EXT_CSD +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note None. +* +******************************************************************************/ +s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff) +{ + s32 Status; + u32 Arg = 0U; + u16 BlkCnt; + u16 BlkSize; + s32 LoopCnt; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + for (LoopCnt = 0; LoopCnt < 512; LoopCnt++) { + ReadBuff[LoopCnt] = 0U; + } + + BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT; + BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE; + + XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff); + + /* Send SEND_EXT_CSD command */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check for transfer done */ + Status = XSdps_CheckTransferDone(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (InstancePtr->Config.IsCacheCoherent == 0U) { + Xil_DCacheInvalidateRange((INTPTR)ReadBuff, + ((INTPTR)BlkCnt * (INTPTR)BlkSize)); + } + + Status = XST_SUCCESS; + + RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief +* API to write EXT_CSD register of eMMC. +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param Arg is the argument to be sent along with the command +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note None. +* +******************************************************************************/ +s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check for transfer done */ + Status = XSdps_CheckTransferDone(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XST_SUCCESS; + + RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief +* API to send pullup command to card before using DAT line 3(using 4-bit bus) +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note None. +* +******************************************************************************/ +s32 XSdPs_Pullup(XSdPs *InstancePtr) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Status = XSdPs_CmdTransfer(InstancePtr, CMD55, + InstancePtr->RelCardAddr, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0U, 0U); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XST_SUCCESS; + + RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief +* Selects card and sets default block size +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* - XSDPS_CT_ERROR if Command Transfer fail. +* +* @note None. +* +******************************************************************************/ +s32 XSdPs_Select_Card (XSdPs *InstancePtr) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Send CMD7 - Select card */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD7, + InstancePtr->RelCardAddr, 0U); + + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function performs SD read in polled mode. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Arg is the address passed by the user that is to be sent as +* argument along with the command. +* @param BlkCnt - Block count passed by the user. +* @param Buff - Pointer to the data buffer for a DMA transfer. +* +* @return +* - XST_SUCCESS if Transfer initialization was successful +* - XST_FAILURE if failure - could be because another transfer +* is in progress or command or data inhibit is set +* +******************************************************************************/ +s32 XSdPs_StartReadTransfer(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (InstancePtr->IsBusy == TRUE) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Setup the Read Transfer */ + Status = XSdPs_SetupTransfer(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Read from the card */ + Status = XSdPs_Read(InstancePtr, Arg, BlkCnt, Buff); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + + InstancePtr->IsBusy = TRUE; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function start SD write transfer. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* @param Arg is the address passed by the user that is to be sent as +* argument along with the command. +* @param BlkCnt - Block count passed by the user. +* @param Buff - Pointer to the data buffer for a DMA transfer. +* +* @return +* - XST_SUCCESS if Transfer initialization was successful +* - XST_FAILURE if failure - could be because another transfer +* is in progress or command or data inhibit is set +* +******************************************************************************/ +s32 XSdPs_StartWriteTransfer(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (InstancePtr->IsBusy == TRUE) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Setup the Write Transfer */ + Status = XSdPs_SetupTransfer(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* write to the card */ + Status = XSdPs_Write(InstancePtr, Arg, BlkCnt, Buff); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + + InstancePtr->IsBusy = TRUE; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to check if the transfer is completed successfully. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if transfer was successful +* - XST_FAILURE if failure +* - XST_DEVICE_BUSY - if the transfer is still in progress +* +******************************************************************************/ +s32 XSdPs_CheckReadTransfer(XSdPs *InstancePtr) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Status = XSdPs_CheckTransferComplete(InstancePtr); + + return Status; +} + +/*****************************************************************************/ +/** +* @brief +* This function is used to check for the write transfer completed. +* +* @param InstancePtr is a pointer to the instance to be worked on. +* +* @return +* - XST_SUCCESS if transfer was successful +* - XST_FAILURE if failure +* - XST_DEVICE_BUSY - if the transfer is still in progress +* +******************************************************************************/ +s32 XSdPs_CheckWriteTransfer(XSdPs *InstancePtr) +{ + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Status = XSdPs_CheckTransferComplete(InstancePtr); + + return Status; +} + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_sinit.c new file mode 100644 index 0000000..22a4b7f --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/sdps/src/xsdps_sinit.c @@ -0,0 +1,79 @@ +/****************************************************************************** +* Copyright (C) 2013 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xsdps_sinit.c +* @addtogroup sdps Overview +* @{ +* +* The implementation of the XSdPs component's static initialization +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 1.00a hk/sg  10/17/13 Initial release
+*       kvn    07/15/15 Modified the code according to MISRAC-2012.
+* 3.7   aru    03/12/19 Modified the code according to MISRAC-2012.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xstatus.h" +#include "xsdps.h" +#include "xparameters.h" +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +/** + * XSdPs Configuration Table + */ +extern XSdPs_Config XSdPs_ConfigTable[XPAR_XSDPS_NUM_INSTANCES]; + +/*****************************************************************************/ +/** +* +* @brief +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the ID of the device to look up the +* configuration for. +* +* @return +* +* A pointer to the configuration found or NULL if the specified device ID was +* not found. See xsdps.h for the definition of XSdPs_Config. +* +* @note None. +* +******************************************************************************/ +XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId) +{ + XSdPs_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_XSDPS_NUM_INSTANCES; Index++) { + if (XSdPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XSdPs_ConfigTable[Index]; + break; + } + } + return (XSdPs_Config *)CfgPtr; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/Makefile new file mode 100644 index 0000000..d90ef88 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/Makefile @@ -0,0 +1,83 @@ +############################################################################### +# Copyright (c) 2011 - 2020 Xilinx, Inc. All rights reserved. +# SPDX-License-Identifier: MIT +############################################################################### +DRIVER_LIB_VERSION = v1.0 + +include config.make + +CC=$(COMPILER) +AR=$(ARCHIVER) +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(subst -pg, -DPROFILING, $(COMPILER_FLAGS)) +ECC_FLAGS = $(subst -pg, -DPROFILING, $(EXTRA_COMPILER_FLAGS)) + +ifeq (($(notdir $(CC))) , arm-xilinx-eabi-gcc) +ECC_FLAGS += -nostartfiles\ + -march=armv7-a \ + -mfloat-abi=soft \ + -mfpu=neon +endif + +ifeq (($(notdir $(CC))) , arm-none-eabi-gcc) +ECC_FLAGS += -nostartfiles +endif + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I${INCLUDEDIR} + +SRCFILES:=$(wildcard *.c) + +ASSEMBLY_SRCFILES:=$(wildcard *.S) + +OBJECTS = $(addprefix $(RELEASEDIR),$(addsuffix .o, $(basename $(wildcard *.c)))) + +ASSEMBLY_OBJECTS = $(addprefix $(RELEASEDIR),$(addsuffix .o, $(basename $(wildcard *.S)))) + +INCLUDEFILES=*.h + +libs: $(LIBS) + +standalone_libs: $(OBJECTS) $(ASSEMBLY_OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +ASSEMBLY_DEPFILES := $(ASSEMBLY_SRCFILES:%.S=$(RELEASEDIR)%.d) + +include $(wildcard $(ASSEMBLY_DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.S + $(CC) $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) -o $@ $< + +$(RELEASEDIR)%.o: %.c + $(CC) $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) -o $@ $< + +profile_libs: + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" libs + +.PHONY: include +include: standalone_includes profile_includes + +standalone_includes: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +profile_includes: + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" include + +clean: + rm -rf ${OBJECTS} + rm -rf ${ASSEMBLY_OBJECTS} + rm -rf $(DEPFILES) + rm -rf $(ASSEMBLY_DEPFILES) + $(MAKE) -C profile COMPILER_FLAGS="$(COMPILER_FLAGS)" EXTRA_COMPILER_FLAGS="$(EXTRA_COMPILER_FLAGS)" COMPILER="$(CC)" ARCHIVER="$(AR)" clean diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_exit.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_exit.c new file mode 100644 index 0000000..4c55bbd --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_exit.c @@ -0,0 +1,18 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include +#include "xil_types.h" + +/* _exit - Simple implementation. Does not return. +*/ +__attribute__((weak)) void _exit (sint32 status) +{ + (void)status; + while (1) { + ; + } +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_open.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_open.c new file mode 100644 index 0000000..df9d192 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_open.c @@ -0,0 +1,32 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +#ifndef UNDEFINE_FILE_OPS +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) s32 _open(const char8 *buf, s32 flags, s32 mode); + +#ifdef __cplusplus +} +#endif + +/* + * _open -- open a file descriptor. We don't have a filesystem, so + * we return an error. + */ +__attribute__((weak)) s32 _open(const char8 *buf, s32 flags, s32 mode) +{ + (void)buf; + (void)flags; + (void)mode; + errno = EIO; + return (-1); +} +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_sbrk.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_sbrk.c new file mode 100644 index 0000000..c3010ea --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/_sbrk.c @@ -0,0 +1,43 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include +#include "xil_types.h" + +extern u8 _heap_start[]; +extern u8 _heap_end[]; + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) caddr_t _sbrk ( s32 incr ); + +#ifdef __cplusplus +} +#endif + +__attribute__((weak)) caddr_t _sbrk ( s32 incr ) +{ + static u8 *heap = NULL; + u8 *prev_heap; + static u8 *HeapEndPtr = (u8 *)&_heap_end; + caddr_t Status; + + if (heap == NULL) { + heap = (u8 *)&_heap_start; + } + prev_heap = heap; + + if (((heap + incr) <= HeapEndPtr) && (prev_heap != NULL)) { + heap += incr; + Status = (caddr_t) ((void *)prev_heap); + } else { + Status = (caddr_t) -1; + } + + return Status; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/abort.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/abort.c new file mode 100644 index 0000000..4c9faef --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/abort.c @@ -0,0 +1,16 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include +#include + +/* + * abort -- go out via exit... + */ +__attribute__((weak)) void abort(void) +{ + _exit(1); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/asm_vectors.S b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/asm_vectors.S new file mode 100644 index 0000000..9be0b25 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/asm_vectors.S @@ -0,0 +1,176 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +/*****************************************************************************/ +/** +* @file asm_vectors.S +* +* This file contains the initial vector table for the Cortex A9 processor +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 10/20/09 Initial version
+* 3.05a sdm	02/02/12 Save lr when profiling is enabled
+* 3.10a srt     04/18/13 Implemented ARM Erratas. Please refer to file
+*			 'xil_errata.h' for errata description
+* 4.00a pkp	22/01/14 Modified return addresses for interrupt
+*			 handlers (DataAbortHandler and SVCHandler)
+*			 to fix CR#767251
+* 5.1	pkp	05/13/15 Saved the addresses of instruction causing data
+*			 abort and prefetch abort into DataAbortAddr and
+*			 PrefetchAbortAddr for further use to fix CR#854523
+* 5.4	pkp	12/03/15 Added handler for undefined exception
+* 6.8	mus	04/27/18 Removed __ARM_NEON__ flag definition. Now,
+*			 saving/restoring of of HW floating point register
+*			 would be done through newly introduced flag
+*			 FPU_HARD_FLOAT_ABI_ENABLED. This new flag will be
+*			 configured based on the -mfpu-abi option in extra
+*			 compiler flags.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ +#include "xil_errata.h" +#include "bspconfig.h" + +.org 0 +.text + +.globl _vector_table + +.section .vectors +_vector_table: + B _boot + B Undefined + B SVCHandler + B PrefetchAbortHandler + B DataAbortHandler + NOP /* Placeholder for address exception vector*/ + B IRQHandler + B FIQHandler + + +IRQHandler: /* IRQ vector handler */ + + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code*/ +#if FPU_HARD_FLOAT_ABI_ENABLED + vpush {d0-d7} + vpush {d16-d31} + vmrs r1, FPSCR + push {r1} + vmrs r1, FPEXC + push {r1} +#endif + +#ifdef PROFILING + ldr r2, =prof_pc + subs r3, lr, #0 + str r3, [r2] +#endif + + bl IRQInterrupt /* IRQ vector */ + +#if FPU_HARD_FLOAT_ABI_ENABLED + pop {r1} + vmsr FPEXC, r1 + pop {r1} + vmsr FPSCR, r1 + vpop {d16-d31} + vpop {d0-d7} +#endif + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + + subs pc, lr, #4 /* adjust return */ + + +FIQHandler: /* FIQ vector handler */ + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ +#if FPU_HARD_FLOAT_ABI_ENABLED + vpush {d0-d7} + vpush {d16-d31} + vmrs r1, FPSCR + push {r1} + vmrs r1, FPEXC + push {r1} +#endif + +FIQLoop: + bl FIQInterrupt /* FIQ vector */ + +#if FPU_HARD_FLOAT_ABI_ENABLED + pop {r1} + vmsr FPEXC, r1 + pop {r1} + vmsr FPSCR, r1 + vpop {d16-d31} + vpop {d0-d7} +#endif + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + subs pc, lr, #4 /* adjust return */ + + +Undefined: /* Undefined handler */ + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + ldr r0, =UndefinedExceptionAddr + sub r1, lr, #4 + str r1, [r0] /* Store address of instruction causing undefined exception */ + + bl UndefinedException /* UndefinedException: call C function here */ + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + movs pc, lr + +SVCHandler: /* SWI handler */ + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + + tst r0, #0x20 /* check the T bit */ + ldrneh r0, [lr,#-2] /* Thumb mode */ + bicne r0, r0, #0xff00 /* Thumb mode */ + ldreq r0, [lr,#-4] /* ARM mode */ + biceq r0, r0, #0xff000000 /* ARM mode */ + + bl SWInterrupt /* SWInterrupt: call C function here */ + + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + movs pc, lr /*return to the next instruction after the SWI instruction */ + + +DataAbortHandler: /* Data Abort handler */ +#ifdef CONFIG_ARM_ERRATA_775420 + dsb +#endif + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + ldr r0, =DataAbortAddr + sub r1, lr, #8 + str r1, [r0] /* Stores instruction causing data abort */ + + bl DataAbortInterrupt /*DataAbortInterrupt :call C function here */ + + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + subs pc, lr, #8 /* points to the instruction that caused the Data Abort exception */ + +PrefetchAbortHandler: /* Prefetch Abort handler */ +#ifdef CONFIG_ARM_ERRATA_775420 + dsb +#endif + stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */ + ldr r0, =PrefetchAbortAddr + sub r1, lr, #4 + str r1, [r0] /* Stores instruction causing prefetch abort */ + + bl PrefetchAbortInterrupt /* PrefetchAbortInterrupt: call C function here */ + + ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */ + + subs pc, lr, #4 /* points to the instruction that caused the Prefetch Abort exception */ + +.end diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/boot.S b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/boot.S new file mode 100644 index 0000000..1beda67 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/boot.S @@ -0,0 +1,463 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +/*****************************************************************************/ +/** +* @file boot.S +* +* @addtogroup a9_boot_code Cortex A9 Processor Boot Code +* @{ +*

boot.S

+* The boot code performs minimum configuration which is required for an +* application to run starting from processor reset state of the processor. Below is a +* sequence illustrating what all configuration is performed before control +* reaches to main function. +* +* 1. Program vector table base for exception handling +* 2. Invalidate instruction cache, data cache and TLBs +* 3. Program stack pointer for various modes (IRQ, FIQ, supervisor, undefine, +* abort, system) +* 4. Configure MMU with short descriptor translation table format and program +* base address of translation table +* 5. Enable data cache, instruction cache and MMU +* 6. Enable Floating point unit +* 7. Transfer control to _start which clears BSS sections, initializes +* global timer and runs global constructor before jumping to main +* application +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 10/20/09 Initial version
+* 3.06a sgd     05/15/12 Updated L2CC Auxiliary and Tag RAM Latency control
+*			 register settings.
+* 3.06a asa 	06/17/12 Modified the TTBR settings and L2 Cache auxiliary
+*		         register settings.
+* 3.07a asa     07/16/12 Modified the L2 Cache controller settings to improve
+*			 performance. Changed the property of the ".boot"
+*			 section.
+* 3.07a sgd     08/21/12 Modified the L2 Cache controller and cp15 Aux Control
+*               Register settings
+* 3.09a sgd     02/06/13 Updated SLCR l2c Ram Control register to a
+*               value of 0x00020202. Fix for CR 697094 (SI#687034).
+* 3.10a srt     04/18/13 Implemented ARM Erratas. Please refer to file
+*			 'xil_errata.h' for errata description
+* 4.2   pkp	06/19/14 Enabled asynchronous abort exception
+* 5.0	pkp	16/15/14 Modified initialization code to enable scu after
+*			 MMU is enabled
+* 5.1   pkp	05/13/15 Changed the initialization order so to first invalidate
+*			 caches and TLB, enable MMU and caches, then enable SMP
+*			 bit in ACTLR. L2Cache invalidation and enabling of L2Cache
+*			 is done later.
+* 5.4   asa     12/6/15  Added code to initialize SPSR for all relevant modes.
+* 6.0   mus     08/04/16 Added code to detect zynq-7000 base silicon configuration and
+*                        attempt to enable dual core behavior on single cpu zynq-7000s
+*                        devices is prevented from corrupting system behavior.
+* 6.0   mus     08/24/16 Check CPU core before putting cpu1 to reset for single core
+*                        zynq-7000s devices
+* 7.6   mus     09/02/21 SCU invalidation should be done only from primary CPU, so
+*                        skipping it when USE_AMP is set to 1. It fixes CR#1109723
+* 7.7   asa     01/06/22 Removed Cortex-A9 errata handling for errata
+* 			 742230 and 743622. These do not apply to
+* 			 Cortex-A9 revision r3p0 being used in Zynq
+* 			 platforms.
+*
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#include "xparameters.h" +#include "xil_errata.h" + +.globl MMUTable +.global _prestart +.global _boot +.global __stack +.global __irq_stack +.global __supervisor_stack +.global __abort_stack +.global __fiq_stack +.global __undef_stack +.global _vector_table + +.set PSS_L2CC_BASE_ADDR, 0xF8F02000 +.set PSS_SLCR_BASE_ADDR, 0xF8000000 + +.set RESERVED, 0x0fffff00 +.set TblBase , MMUTable +.set LRemap, 0xFE00000F /* set the base address of the peripheral block as not shared */ +.set L2CCWay, (PSS_L2CC_BASE_ADDR + 0x077C) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_INVLD_WAY_OFFSET)*/ +.set L2CCSync, (PSS_L2CC_BASE_ADDR + 0x0730) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_SYNC_OFFSET)*/ +.set L2CCCrtl, (PSS_L2CC_BASE_ADDR + 0x0100) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CNTRL_OFFSET)*/ +.set L2CCAuxCrtl, (PSS_L2CC_BASE_ADDR + 0x0104) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_AUX_CNTRL_OFFSET)*/ +.set L2CCTAGLatReg, (PSS_L2CC_BASE_ADDR + 0x0108) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_TAG_RAM_CNTRL_OFFSET)*/ +.set L2CCDataLatReg, (PSS_L2CC_BASE_ADDR + 0x010C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_DATA_RAM_CNTRL_OFFSET)*/ +.set L2CCIntClear, (PSS_L2CC_BASE_ADDR + 0x0220) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_IAR_OFFSET)*/ +.set L2CCIntRaw, (PSS_L2CC_BASE_ADDR + 0x021C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_ISR_OFFSET)*/ + +.set SLCRlockReg, (PSS_SLCR_BASE_ADDR + 0x04) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_LOCK_OFFSET)*/ +.set SLCRUnlockReg, (PSS_SLCR_BASE_ADDR + 0x08) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_UNLOCK_OFFSET)*/ +.set SLCRL2cRamReg, (PSS_SLCR_BASE_ADDR + 0xA1C) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_L2C_RAM_OFFSET)*/ +.set SLCRCPURSTReg, (0xF8000000 + 0x244) /*(XPS_SYS_CTRL_BASEADDR + A9_CPU_RST_CTRL_OFFSET)*/ +.set EFUSEStaus, (0xF800D000 + 0x10) /*(XPS_EFUSE_BASEADDR + EFUSE_STATUS_OFFSET)*/ + +/* workaround for simulation not working when L1 D and I caches,MMU and L2 cache enabled - DT568997 */ +.if SIM_MODE == 1 +.set CRValMmuCac, 0b00000000000000 /* Disable IDC, and MMU */ +.else +.set CRValMmuCac, 0b01000000000101 /* Enable IDC, and MMU */ +.endif + +.set CRValHiVectorAddr, 0b10000000000000 /* Set the Vector address to high, 0xFFFF0000 */ + +.set L2CCAuxControl, 0x72360000 /* Enable all prefetching, Cache replacement policy, Parity enable, + Event monitor bus enable and Way Size (64 KB) */ +.set L2CCControl, 0x01 /* Enable L2CC */ +.set L2CCTAGLatency, 0x0111 /* latency for TAG RAM */ +.set L2CCDataLatency, 0x0121 /* latency for DATA RAM */ + +.set SLCRlockKey, 0x767B /* SLCR lock key */ +.set SLCRUnlockKey, 0xDF0D /* SLCR unlock key */ +.set SLCRL2cRamConfig, 0x00020202 /* SLCR L2C ram configuration */ + +/* Stack Pointer locations for boot code */ +.set Undef_stack, __undef_stack +.set FIQ_stack, __fiq_stack +.set Abort_stack, __abort_stack +.set SPV_stack, __supervisor_stack +.set IRQ_stack, __irq_stack +.set SYS_stack, __stack + +.set vector_base, _vector_table + +.set FPEXC_EN, 0x40000000 /* FPU enable bit, (1 << 30) */ + +.section .boot,"ax" + + +/* this initializes the various processor modes */ + +_prestart: +_boot: + +#if XPAR_CPU_ID==0 + /* only allow cpu0 through */ + mrc p15,0,r1,c0,c0,5 + and r1, r1, #0xf + cmp r1, #0 + beq CheckEFUSE + EndlessLoop0: + wfe + b EndlessLoop0 + +CheckEFUSE: + ldr r0,=EFUSEStaus + ldr r1,[r0] /* Read eFuse setting */ + ands r1,r1,#0x80 /* Check whether device is having single core */ + beq OKToRun + + /* single core device, reset cpu1 */ + ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */ + ldr r1,=SLCRUnlockKey /* set unlock key */ + str r1, [r0] /* Unlock SLCR */ + + ldr r0,=SLCRCPURSTReg + ldr r1,[r0] /* Read CPU Software Reset Control register */ + orr r1,r1,#0x22 + str r1,[r0] /* Reset CPU1 */ + + ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */ + ldr r1,=SLCRlockKey /* set lock key */ + str r1, [r0] /* lock SLCR */ + +#elif XPAR_CPU_ID==1 + /* only allow cpu1 through */ + mrc p15,0,r1,c0,c0,5 + and r1, r1, #0xf + cmp r1, #1 + beq CheckEFUSE1 + b EndlessLoop1 + +CheckEFUSE1: + ldr r0,=EFUSEStaus + ldr r1,[r0] /* Read eFuse setting */ + ands r1,r1,#0x80 /* Check whether device is having single core */ + beq OKToRun + EndlessLoop1: + wfe + b EndlessLoop1 +#endif + +OKToRun: + mrc p15, 0, r0, c0, c0, 0 /* Get the revision */ + and r5, r0, #0x00f00000 + and r6, r0, #0x0000000f + orr r6, r6, r5, lsr #20-4 + + /* set VBAR to the _vector_table address in linker script */ + ldr r0, =vector_base + mcr p15, 0, r0, c12, c0, 0 + + /*invalidate scu*/ +#if USE_AMP!=1 + ldr r7, =0xf8f0000c + ldr r6, =0xffff + str r6, [r7] +#endif + + /* Invalidate caches and TLBs */ + mov r0,#0 /* r0 = 0 */ + mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */ + mcr p15, 0, r0, c7, c5, 0 /* invalidate icache */ + mcr p15, 0, r0, c7, c5, 6 /* Invalidate branch predictor array */ + bl invalidate_dcache /* invalidate dcache */ + + /* Disable MMU, if enabled */ + mrc p15, 0, r0, c1, c0, 0 /* read CP15 register 1 */ + bic r0, r0, #0x1 /* clear bit 0 */ + mcr p15, 0, r0, c1, c0, 0 /* write value back */ + +#ifdef SHAREABLE_DDR + /* Mark the entire DDR memory as shareable */ + ldr r3, =0x3ff /* 1024 entries to cover 1G DDR */ + ldr r0, =TblBase /* MMU Table address in memory */ + ldr r2, =0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ +shareable_loop: + str r2, [r0] /* write the entry to MMU table */ + add r0, r0, #0x4 /* next entry in the table */ + add r2, r2, #0x100000 /* next section */ + subs r3, r3, #1 + bge shareable_loop /* loop till 1G is covered */ +#endif + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the irq stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x12 /* IRQ mode */ + msr cpsr, r2 + ldr r13,=IRQ_stack /* IRQ stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the supervisor stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x13 /* supervisor mode */ + msr cpsr, r2 + ldr r13,=SPV_stack /* Supervisor stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the Abort stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x17 /* Abort mode */ + msr cpsr, r2 + ldr r13,=Abort_stack /* Abort stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the FIQ stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x11 /* FIQ mode */ + msr cpsr, r2 + ldr r13,=FIQ_stack /* FIQ stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the Undefine stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x1b /* Undefine mode */ + msr cpsr, r2 + ldr r13,=Undef_stack /* Undefine stack pointer */ + bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */ + msr spsr_fsxc,r2 + + mrs r0, cpsr /* get the current PSR */ + mvn r1, #0x1f /* set up the system stack pointer */ + and r2, r1, r0 + orr r2, r2, #0x1F /* SYS mode */ + msr cpsr, r2 + ldr r13,=SYS_stack /* SYS stack pointer */ + + /*set scu enable bit in scu*/ + ldr r7, =0xf8f00000 + ldr r0, [r7] + orr r0, r0, #0x1 + str r0, [r7] + + /* enable MMU and cache */ + + ldr r0,=TblBase /* Load MMU translation table base */ + orr r0, r0, #0x5B /* Outer-cacheable, WB */ + mcr 15, 0, r0, c2, c0, 0 /* TTB0 */ + + mvn r0,#0 /* Load MMU domains -- all ones=manager */ + mcr p15,0,r0,c3,c0,0 + + /* Enable mmu, icahce and dcache */ + ldr r0,=CRValMmuCac + mcr p15,0,r0,c1,c0,0 /* Enable cache and MMU */ + dsb /* dsb allow the MMU to start up */ + isb /* isb flush prefetch buffer */ + + /* Write to ACTLR */ + mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR*/ + orr r0, r0, #(0x01 << 6) /* set SMP bit */ + orr r0, r0, #(0x01 ) /* Cache/TLB maintenance broadcast */ + mcr p15, 0, r0, c1, c0, 1 /* Write ACTLR*/ + +/* Invalidate L2 Cache and enable L2 Cache*/ +/* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */ +#if USE_AMP!=1 + ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */ + mov r1, #0 /* force the disable bit */ + str r1, [r0] /* disable the L2 Caches */ + + ldr r0,=L2CCAuxCrtl /* Load L2CC base address base + Aux control register */ + ldr r1,[r0] /* read the register */ + ldr r2,=L2CCAuxControl /* set the default bits */ + orr r1,r1,r2 + str r1, [r0] /* store the Aux Control Register */ + + ldr r0,=L2CCTAGLatReg /* Load L2CC base address base + TAG Latency address */ + ldr r1,=L2CCTAGLatency /* set the latencies for the TAG*/ + str r1, [r0] /* store the TAG Latency register Register */ + + ldr r0,=L2CCDataLatReg /* Load L2CC base address base + Data Latency address */ + ldr r1,=L2CCDataLatency /* set the latencies for the Data*/ + str r1, [r0] /* store the Data Latency register Register */ + + ldr r0,=L2CCWay /* Load L2CC base address base + way register*/ + ldr r2, =0xFFFF + str r2, [r0] /* force invalidate */ + + ldr r0,=L2CCSync /* need to poll 0x730, PSS_L2CC_CACHE_SYNC_OFFSET */ + /* Load L2CC base address base + sync register*/ + /* poll for completion */ +Sync: ldr r1, [r0] + cmp r1, #0 + bne Sync + + ldr r0,=L2CCIntRaw /* clear pending interrupts */ + ldr r1,[r0] + ldr r0,=L2CCIntClear + str r1,[r0] + + ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */ + ldr r1,=SLCRUnlockKey /* set unlock key */ + str r1, [r0] /* Unlock SLCR */ + + ldr r0,=SLCRL2cRamReg /* Load SLCR base address base + l2c Ram Control register */ + ldr r1,=SLCRL2cRamConfig /* set the configuration value */ + str r1, [r0] /* store the L2c Ram Control Register */ + + ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */ + ldr r1,=SLCRlockKey /* set lock key */ + str r1, [r0] /* lock SLCR */ + + ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */ + ldr r1,[r0] /* read the register */ + mov r2, #L2CCControl /* set the enable bit */ + orr r1,r1,r2 + str r1, [r0] /* enable the L2 Caches */ +#endif + + mov r0, r0 + mrc p15, 0, r1, c1, c0, 2 /* read cp access control register (CACR) into r1 */ + orr r1, r1, #(0xf << 20) /* enable full access for p10 & p11 */ + mcr p15, 0, r1, c1, c0, 2 /* write back into CACR */ + + /* enable vfp */ + fmrx r1, FPEXC /* read the exception register */ + orr r1,r1, #FPEXC_EN /* set VFP enable bit, leave the others in orig state */ + fmxr FPEXC, r1 /* write back the exception register */ + + mrc p15,0,r0,c1,c0,0 /* flow prediction enable */ + orr r0, r0, #(0x01 << 11) /* #0x8000 */ + mcr p15,0,r0,c1,c0,0 + + mrc p15,0,r0,c1,c0,1 /* read Auxiliary Control Register */ + orr r0, r0, #(0x1 << 2) /* enable Dside prefetch */ + orr r0, r0, #(0x1 << 1) /* enable L2 Prefetch hint */ + mcr p15,0,r0,c1,c0,1 /* write Auxiliary Control Register */ + + mrs r0, cpsr /* get the current PSR */ + bic r0, r0, #0x100 /* enable asynchronous abort exception */ + msr cpsr_xsf, r0 + + + b _start /* jump to C startup code */ + and r0, r0, r0 /* no op */ + +.Ldone: b .Ldone /* Paranoia: we should never get here */ + + +/* + ************************************************************************* + * + * invalidate_dcache - invalidate the entire d-cache by set/way + * + * Note: for Cortex-A9, there is no cp instruction for invalidating + * the whole D-cache. Need to invalidate each line. + * + ************************************************************************* + */ +invalidate_dcache: + mrc p15, 1, r0, c0, c0, 1 /* read CLIDR */ + ands r3, r0, #0x7000000 + mov r3, r3, lsr #23 /* cache level value (naturally aligned) */ + beq finished + mov r10, #0 /* start with level 0 */ +loop1: + add r2, r10, r10, lsr #1 /* work out 3xcachelevel */ + mov r1, r0, lsr r2 /* bottom 3 bits are the Cache type for this level */ + and r1, r1, #7 /* get those 3 bits alone */ + cmp r1, #2 + blt skip /* no cache or only instruction cache at this level */ + mcr p15, 2, r10, c0, c0, 0 /* write the Cache Size selection register */ + isb /* isb to sync the change to the CacheSizeID reg */ + mrc p15, 1, r1, c0, c0, 0 /* reads current Cache Size ID register */ + and r2, r1, #7 /* extract the line length field */ + add r2, r2, #4 /* add 4 for the line length offset (log2 16 bytes) */ + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 /* r4 is the max number on the way size (right aligned) */ + clz r5, r4 /* r5 is the bit position of the way size increment */ + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 /* r7 is the max number of the index size (right aligned) */ +loop2: + mov r9, r4 /* r9 working copy of the max way size (right aligned) */ +loop3: + orr r11, r10, r9, lsl r5 /* factor in the way number and cache number into r11 */ + orr r11, r11, r7, lsl r2 /* factor in the index number */ + mcr p15, 0, r11, c7, c6, 2 /* invalidate by set/way */ + subs r9, r9, #1 /* decrement the way number */ + bge loop3 + subs r7, r7, #1 /* decrement the index */ + bge loop2 +skip: + add r10, r10, #2 /* increment the cache number */ + cmp r3, r10 + bgt loop1 + +finished: + mov r10, #0 /* switch back to cache level 0 */ + mcr p15, 2, r10, c0, c0, 0 /* select current cache level in cssr */ + dsb + isb + + bx lr + +.end +/** +* @} End of "addtogroup a9_boot_code". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/close.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/close.c new file mode 100644 index 0000000..50f10a0 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/close.c @@ -0,0 +1,27 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +#ifndef UNDEFINE_FILE_OPS +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) s32 _close(s32 fd); + +#ifdef __cplusplus +} +#endif + +/* + * close -- We don't need to do anything, but pretend we did. + */ + +__attribute__((weak)) s32 _close(s32 fd) +{ + (void)fd; + return (0); +} +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/config.make b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/config.make new file mode 100644 index 0000000..4594226 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/config.make @@ -0,0 +1,8 @@ +#/****************************************************************************** +#* Copyright (c) 2021 Xilinx, Inc. All rights reserved. +#* SPDX-License-Identifier: MIT +#******************************************************************************/ + +LIBSOURCES = *.c *.S +PROFILE_ARCH_OBJS = profile_mcount_arm.o +LIBS = standalone_libs diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/cpputest_time.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/cpputest_time.c new file mode 100644 index 0000000..77ea3bc --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/cpputest_time.c @@ -0,0 +1,31 @@ +/****************************************************************************** +* Copyright (c) 2019 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#ifndef UNDEFINE_FILE_OPS +#include +#include "xil_types.h" +#include +struct tms* tms; +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) clock_t _times(struct tms* tms); + +#ifdef __cplusplus +} +#endif + +__attribute__((weak)) clock_t _times(struct tms* tms) +{ + (void)tms; + + errno = EIO; + return (-1); +} + + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/cpu_init.S b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/cpu_init.S new file mode 100644 index 0000000..48dcec3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/cpu_init.S @@ -0,0 +1,53 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +/*****************************************************************************/ +/** +* @file cpu_init.S +* +* This file contains CPU specific initialization. Invoked from main CRT +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 10/20/09 Initial version
+* 3.04a sdm	01/02/12 Updated to clear cp15 regs with unknown reset values
+* 5.0   pkp	12/16/14 removed incorrect initialization of TLB lockdown
+*			 register to fix CR#830580
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + + .text + .global __cpu_init + .align 2 +__cpu_init: + +/* Clear cp15 regs with unknown reset values */ + mov r0, #0x0 + mcr p15, 0, r0, c5, c0, 0 /* DFSR */ + mcr p15, 0, r0, c5, c0, 1 /* IFSR */ + mcr p15, 0, r0, c6, c0, 0 /* DFAR */ + mcr p15, 0, r0, c6, c0, 2 /* IFAR */ + mcr p15, 0, r0, c9, c13, 2 /* PMXEVCNTR */ + mcr p15, 0, r0, c13, c0, 2 /* TPIDRURW */ + mcr p15, 0, r0, c13, c0, 3 /* TPIDRURO */ + +/* Reset and start Cycle Counter */ + mov r2, #0x80000000 /* clear overflow */ + mcr p15, 0, r2, c9, c12, 3 + mov r2, #0xd /* D, C, E */ + mcr p15, 0, r2, c9, c12, 0 + mov r2, #0x80000000 /* enable cycle counter */ + mcr p15, 0, r2, c9, c12, 1 + + bx lr + +.end diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/errno.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/errno.c new file mode 100644 index 0000000..3d12021 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/errno.c @@ -0,0 +1,29 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +/* The errno variable is stored in the reentrancy structure. This + function returns its address for use by the macro errno defined in + errno.h. */ + +#include +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) sint32 * __errno (void); + +#ifdef __cplusplus +} +#endif + +__attribute__((weak)) sint32 * +__errno (void) +{ + return &_REENT->_errno; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/fcntl.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/fcntl.c new file mode 100644 index 0000000..40e2729 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/fcntl.c @@ -0,0 +1,22 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include +#include "xil_types.h" + +__attribute__((weak)) sint32 fcntl (sint32 fd, sint32 cmd, LONG arg); + +/* + * fcntl -- Manipulate a file descriptor. + * We don't have a filesystem, so we do nothing. + */ +__attribute__((weak)) sint32 fcntl (sint32 fd, sint32 cmd, LONG arg) +{ + (void)fd; + (void)cmd; + (void)arg; + return 0; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/fstat.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/fstat.c new file mode 100644 index 0000000..0faffb8 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/fstat.c @@ -0,0 +1,28 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) s32 _fstat(s32 fd, struct stat *buf); + +#ifdef __cplusplus +} +#endif +/* + * fstat -- Since we have no file system, we just return an error. + */ +__attribute__((weak)) s32 _fstat(s32 fd, struct stat *buf) +{ + (void)fd; + buf->st_mode = S_IFCHR; /* Always pretend to be a tty */ + + return (0); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/getentropy.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/getentropy.c new file mode 100644 index 0000000..344325c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/getentropy.c @@ -0,0 +1,26 @@ +/****************************************************************************** +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) sint32 getentropy(void *buffer, sint32 length); + +#ifdef __cplusplus +} +#endif + +__attribute__((weak)) sint32 getentropy(void *buffer, sint32 length) +{ + (void)buffer; + (void)length; + + return 0; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/getpid.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/getpid.c new file mode 100644 index 0000000..c657e1c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/getpid.c @@ -0,0 +1,30 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include "xil_types.h" +/* + * getpid -- only one process, so just return 1. + */ +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) s32 _getpid(void); +__attribute__((weak)) s32 getpid(void); + +#ifdef __cplusplus +} +#endif + +__attribute__((weak)) s32 getpid(void) +{ + return 1; +} + +__attribute__((weak)) s32 _getpid(void) +{ + return 1; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/inbyte.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/inbyte.c new file mode 100644 index 0000000..3b662d2 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/inbyte.c @@ -0,0 +1,18 @@ +/****************************************************************************** +* Copyright (c) 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +#include "xparameters.h" +#include "xuartps_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif +char inbyte(void); +#ifdef __cplusplus +} +#endif + +char inbyte(void) { + return XUartPs_RecvByte(STDIN_BASEADDRESS); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/isatty.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/isatty.c new file mode 100644 index 0000000..a513bf6 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/isatty.c @@ -0,0 +1,34 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) sint32 _isatty(sint32 fd); + +#ifdef __cplusplus +} +#endif + +/* + * isatty -- returns 1 if connected to a terminal device, + * returns 0 if not. Since we're hooked up to a + * serial port, we'll say yes _AND return a 1. + */ +__attribute__((weak)) sint32 isatty(sint32 fd) +{ + (void)fd; + return (1); +} + +__attribute__((weak)) sint32 _isatty(sint32 fd) +{ + (void)fd; + return (1); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/kill.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/kill.c new file mode 100644 index 0000000..5181c02 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/kill.c @@ -0,0 +1,38 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +#include +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) s32 _kill(pid_t pid, s32 sig); + +#ifdef __cplusplus +} +#endif + +/* + * kill -- go out via exit... + */ + +__attribute__((weak)) int kill(pid_t pid, int sig) +{ + if(pid == 1) { + _exit(sig); + } + return 0; +} + +__attribute__((weak)) s32 _kill(pid_t pid, s32 sig) +{ + if(pid == 1) { + _exit(sig); + } + return 0; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/lseek.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/lseek.c new file mode 100644 index 0000000..7b2c126 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/lseek.c @@ -0,0 +1,40 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) off_t _lseek(s32 fd, off_t offset, s32 whence); +__attribute__((weak)) off_t lseek(s32 fd, off_t offset, s32 whence); + +#ifdef __cplusplus +} +#endif +/* + * lseek -- Since a serial port is non-seekable, we return an error. + */ +__attribute__((weak)) off_t lseek(s32 fd, off_t offset, s32 whence) +{ + (void)fd; + (void)offset; + (void)whence; + errno = ESPIPE; + return ((off_t)-1); +} + +__attribute__((weak)) off_t _lseek(s32 fd, off_t offset, s32 whence) +{ + (void)fd; + (void)offset; + (void)whence; + errno = ESPIPE; + return ((off_t)-1); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/open.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/open.c new file mode 100644 index 0000000..c5a33d7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/open.c @@ -0,0 +1,31 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +#ifndef UNDEFINE_FILE_OPS +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) s32 open(char8 *buf, s32 flags, s32 mode); + +#ifdef __cplusplus +} +#endif +/* + * open -- open a file descriptor. We don't have a filesystem, so + * we return an error. + */ +__attribute__((weak)) s32 open(char8 *buf, s32 flags, s32 mode) +{ + (void)buf; + (void)flags; + (void)mode; + errno = EIO; + return (-1); +} +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/outbyte.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/outbyte.c new file mode 100644 index 0000000..db60e6d --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/outbyte.c @@ -0,0 +1,19 @@ +/****************************************************************************** +* Copyright (c) 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +#include "xparameters.h" +#include "xuartps_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif +void outbyte(char c); + +#ifdef __cplusplus +} +#endif + +void outbyte(char c) { + XUartPs_SendByte(STDOUT_BASEADDRESS, c); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/print.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/print.c new file mode 100644 index 0000000..e8ac3d4 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/print.c @@ -0,0 +1,36 @@ +/* print.c -- print a string on the output device. + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + * + */ + +/* + * print -- do a raw print of a string + */ +#include "xil_printf.h" + +void print(const char8 *ptr) +{ +#if defined (__aarch64__) && (HYP_GUEST == 1) && (EL1_NONSECURE == 1) && defined (XEN_USE_PV_CONSOLE) + XPVXenConsole_Write(ptr); +#else +#ifdef STDOUT_BASEADDRESS + while (*ptr != (char8)0) { + outbyte (*ptr); + ptr++; + } +#else +(void)ptr; +#endif +#endif +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/Makefile new file mode 100644 index 0000000..15c4254 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/Makefile @@ -0,0 +1,51 @@ +############################################################################### +# Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +# SPDX-License-Identifier: MIT +############################################################################### +# +# Makefile for profiler +# +####################################################################### + +# PROFILE_ARCH_OBJS - Processor Architecture Dependent files defined here +include ../config.make + +AS=mb-as +COMPILER = mb-gcc +ARCHIVER = mb-ar +CP = cp +COMPILER_FLAGS=-O2 +EXTRA_COMPILER_FLAGS= +LIB = libxil.a +DUMMYLIB = libxilprofile.a + +CC_FLAGS = $(subst -pg, , $(COMPILER_FLAGS)) +ECC_FLAGS = $(subst -pg, , $(EXTRA_COMPILER_FLAGS)) + +RELEASEDIR = ../../../../lib +INCLUDEDIR = ../../../../include +INCLUDES = -I./. -I${INCLUDEDIR} + +OBJS = _profile_init.o _profile_clean.o _profile_timer_hw.o profile_hist.o profile_cg.o +DUMMYOBJ = dummy.o +INCLUDEFILES = profile.h mblaze_nt_types.h _profile_timer_hw.h + +libs : reallibs dummylibs + +reallibs : $(OBJS) $(PROFILE_ARCH_OBJS) + $(ARCHIVER) -r $(RELEASEDIR)/$(LIB) $(OBJS) $(PROFILE_ARCH_OBJS) + +dummylibs : $(DUMMYOBJ) + $(ARCHIVER) -r $(RELEASEDIR)/$(DUMMYLIB) $(DUMMYOBJ) + +%.o:%.c + $(COMPILER) $(CC_FLAGS) $(ECC_FLAGS) -c $< -o $@ $(INCLUDES) + +%.o:%.S + $(COMPILER) $(CC_FLAGS) $(ECC_FLAGS) -c $< -o $@ $(INCLUDES) + +include: + $(CP) -rf $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -f $(OBJS) $(PROFILE_ARCH_OBJS) $(LIB) diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_clean.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_clean.c new file mode 100644 index 0000000..926da80 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_clean.c @@ -0,0 +1,21 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include "profile.h" +#include "_profile_timer_hw.h" +#include "xil_exception.h" + +void _profile_clean( void ); + +/* + * This function is the exit routine and is called by the crtinit, when the + * program terminates. The name needs to be changed later.. + */ +void _profile_clean( void ) +{ + Xil_ExceptionDisable(); + disable_timer(); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_init.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_init.c new file mode 100644 index 0000000..13d2cc5 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_init.c @@ -0,0 +1,59 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include "profile.h" + +/* XMD Initializes the following Global Variables Value during Program + * Download with appropriate values. */ + +#ifdef PROC_MICROBLAZE + +extern s32 microblaze_init(void); + +#elif defined PROC_PPC + +extern s32 powerpc405_init(void); + +#else + +extern s32 cortexa9_init(void); + +#endif + +s32 profile_version = 1; /* Version of S/W Intrusive Profiling library */ + +u32 binsize = (u32)BINSIZE; /* Histogram Bin Size */ +u32 cpu_clk_freq = (u32)CPU_FREQ_HZ ; /* CPU Clock Frequency */ +u32 sample_freq_hz = (u32)SAMPLE_FREQ_HZ ; /* Histogram Sampling Frequency */ +u32 timer_clk_ticks = (u32)TIMER_CLK_TICKS ;/* Timer Clock Ticks for the Timer */ + +/* Structure for Storing the Profiling Data */ +struct gmonparam *_gmonparam = (struct gmonparam *)(0xffffffffU); +s32 n_gmon_sections = 1; + +/* This is the initialization code, which is called from the crtinit. */ + +void _profile_init( void ) +{ +/* print("Gmon Init called....\r\n") */ +/* putnum(n_gmon_sections) , print("\r\n") */ +/* if( _gmonparam == 0xffffffff ) */ +/* printf("Gmonparam is NULL !!\r\n") */ +/* for( i = 0, i < n_gmon_sections, i++ )[ */ +/* putnum( _gmonparam[i].lowpc) , print("\t") */ +/* putnum( _gmonparam[i].highpc) , print("\r\n") */ +/* putnum( _gmonparam[i].textsize ), print("\r\n") */ +/* putnum( _gmonparam[i].kcountsize * sizeof(unsigned short)), print("\r\n") */ +/* ] */ + +#ifdef PROC_MICROBLAZE + (void)microblaze_init(); +#elif defined PROC_PPC + powerpc405_init(); +#else + (void)cortexa9_init(); +#endif +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_timer_hw.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_timer_hw.c new file mode 100644 index 0000000..92d7005 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_timer_hw.c @@ -0,0 +1,356 @@ +/****************************************************************************** +* Copyright (c) 2004 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include "profile.h" +#include "_profile_timer_hw.h" + +#include "xil_exception.h" + +#ifdef PROC_PPC +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +/* #ifndef PPC_PIT_INTERRUPT */ +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +/* extern u32 timer_clk_ticks, */ + +#ifdef PROC_PPC405 +#ifdef PPC_PIT_INTERRUPT +s32 ppc_pit_init( void ); +#endif +s32 powerpc405_init() +#endif /* PROC_CORTEXA9 */ + +#ifdef PROC_PPC440 +#ifdef PPC_PIT_INTERRUPT +s32 ppc_dec_init( void ); +#endif +s32 powerpc405_init(void); +#endif /* PROC_PPC440 */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +s32 opb_timer_init( void ); +#endif + +#ifdef PROC_MICROBLAZE +s32 microblaze_init(void); +#endif /* PROC_MICROBLAZE */ + +#ifdef PROC_CORTEXA9 +s32 scu_timer_init( void ); +s32 cortexa9_init(void); +#endif /* PROC_CORTEXA9 */ + + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC405 + + +/*-------------------------------------------------------------------- +* PowerPC PIT Timer Init. +* Defined only if PIT Timer is used for Profiling +* +*-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +int ppc_pit_init( void ) +{ + /* 1. Register Profile_intr_handler as Interrupt handler */ + /* 2. Set PIT Timer Interrupt and Enable it. */ + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_PIT_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + XTime_PITSetInterval( timer_clk_ticks ) ; + XTime_PITEnableAutoReload() ; + return 0; +} +#endif + + +/* -------------------------------------------------------------------- +* PowerPC Timer Initialization functions. +* For PowerPC, PIT and opb_timer can be used for Profiling. This +* is selected by the user in standalone BSP +* +*-------------------------------------------------------------------- */ +s32 powerpc405_init() +{ + Xil_ExceptionInit() ; + Xil_ExceptionDisableMask( XIL_EXCEPTION_NON_CRITICAL ) ; + + /* Initialize the Timer. + * 1. If PowerPC PIT Timer has to be used, initialize PIT timer. + * 2. Else use opb_timer. It can be directly connected or through intc to PowerPC */ +#ifdef PPC_PIT_INTERRUPT + ppc_pit_init(); +#else +#ifdef TIMER_CONNECT_INTC + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); +#endif + /* Initialize the timer with Timer Ticks */ + opb_timer_init() ; +#endif + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef PPC_PIT_INTERRUPT + XTime_PITEnableInterrupt() ; +#elif TIMER_CONNECT_INTC + XIntc_MasterEnable( INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); +#endif + Xil_ExceptionEnableMask( XIL_EXCEPTION_NON_CRITICAL ) ; +#endif + return 0; +} + +#endif /* PROC_PPC */ + + + +/*-------------------------------------------------------------------- + * PowerPC440 Target - Timer related functions + * -------------------------------------------------------------------- */ +#ifdef PROC_PPC440 + + +/*-------------------------------------------------------------------- + * PowerPC DEC Timer Init. + * Defined only if DEC Timer is used for Profiling + * + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +s32 ppc_dec_init( void ) +{ + /* 1. Register Profile_intr_handler as Interrupt handler */ + /* 2. Set DEC Timer Interrupt and Enable it. */ + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_DEC_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + XTime_DECSetInterval( timer_clk_ticks ) ; + XTime_DECEnableAutoReload() ; + return 0; +} +#endif + + +/*-------------------------------------------------------------------- + * PowerPC Timer Initialization functions. + * For PowerPC, DEC and opb_timer can be used for Profiling. This + * is selected by the user in standalone BSP + * + *-------------------------------------------------------------------- */ +s32 powerpc405_init(void) +{ + Xil_ExceptionInit(); + Xil_ExceptionDisableMask( XIL_EXCEPTION_NON_CRITICAL ) ; + + /* Initialize the Timer. + * 1. If PowerPC DEC Timer has to be used, initialize DEC timer. + * 2. Else use opb_timer. It can be directly connected or through intc to PowerPC */ +#ifdef PPC_PIT_INTERRUPT + ppc_dec_init(); +#else +#ifdef TIMER_CONNECT_INTC + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); + + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); + Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_NON_CRITICAL_INT, + (Xil_ExceptionHandler)profile_intr_handler,NULL); +#endif + /* Initialize the timer with Timer Ticks */ + opb_timer_init() ; +#endif + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef PPC_PIT_INTERRUPT + XTime_DECEnableInterrupt() ; +#elif TIMER_CONNECT_INTC + XIntc_MasterEnable( INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); +#endif + Xil_ExceptionEnableMask( XEXC_NON_CRITICAL ) ; +#endif + return 0; +} + +#endif /* PROC_PPC440 */ + +/* -------------------------------------------------------------------- + * opb_timer Initialization for PowerPC and MicroBlaze. This function + * is not needed if DEC timer is used in PowerPC + * + *-------------------------------------------------------------------- */ +/* #ifndef PPC_PIT_INTERRUPT */ +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +s32 opb_timer_init( void ) +{ + /* set the number of cycles the timer counts before interrupting */ + XTmrCtr_SetLoadReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)timer_clk_ticks); + + /* reset the timers, and clear interrupts */ + XTmrCtr_SetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, + (u32)XTC_CSR_INT_OCCURED_MASK | (u32)XTC_CSR_LOAD_MASK ); + + /* start the timers */ + XTmrCtr_SetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)XTC_CSR_ENABLE_TMR_MASK + | (u32)XTC_CSR_ENABLE_INT_MASK | (u32)XTC_CSR_AUTO_RELOAD_MASK | (u32)XTC_CSR_DOWN_COUNT_MASK); + return 0; +} +#endif + + +/*-------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Initialize the Profile Timer for MicroBlaze Target. + * For MicroBlaze, opb_timer is used. The opb_timer can be directly + * connected to MicroBlaze or connected through Interrupt Controller. + * + *-------------------------------------------------------------------- */ +s32 microblaze_init(void) +{ + /* Register profile_intr_handler + * 1. If timer is connected to Interrupt Controller, register the handler + * to Interrupt Controllers vector table. + * 2. If timer is directly connected to MicroBlaze, register the handler + * as Interrupt handler */ + Xil_ExceptionInit(); + +#ifdef TIMER_CONNECT_INTC + XIntc_RegisterHandler( INTC_BASEADDR, PROFILE_TIMER_INTR_ID, + (XInterruptHandler)profile_intr_handler,NULL); +#else + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)profile_intr_handler, + NULL) ; +#endif + + /* Initialize the timer with Timer Ticks */ + (void)opb_timer_init() ; + + /* Enable Interrupts in the System, if Profile Timer is the only Interrupt + * in the System. */ +#ifdef ENABLE_SYS_INTR +#ifdef TIMER_CONNECT_INTC + XIntc_MasterEnable((u32)INTC_BASEADDR ); + XIntc_SetIntrSvcOption( INTC_BASEADDR, XIN_SVC_ALL_ISRS_OPTION); + XIntc_EnableIntr( (u32)INTC_BASEADDR, PROFILE_TIMER_INTR_MASK ); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler,NULL); +#endif + +#endif + + Xil_ExceptionEnable(); + + return 0; + +} + +#endif /* PROC_MICROBLAZE */ + + + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Initialize the Profile Timer for Cortex A9 Target. + * The scu private timer is connected to the Scu GIC controller. + * + *-------------------------------------------------------------------- */ +s32 scu_timer_init( void ) +{ + /* set the number of cycles the timer counts before interrupting + * scu timer runs at half the cpu clock */ + XScuTimer_SetLoadReg(PROFILE_TIMER_BASEADDR, timer_clk_ticks/2U); + + /* clear any pending interrupts */ + XScuTimer_SetIntrReg(PROFILE_TIMER_BASEADDR, 1U); + + /* enable interrupts, auto-reload mode and start the timer */ + XScuTimer_SetControlReg(PROFILE_TIMER_BASEADDR, XSCUTIMER_CONTROL_IRQ_ENABLE_MASK | + XSCUTIMER_CONTROL_AUTO_RELOAD_MASK | XSCUTIMER_CONTROL_ENABLE_MASK); + + return 0; +} + +s32 cortexa9_init(void) +{ + + Xil_ExceptionInit(); + + XScuGic_DeviceInitialize(0); + + /* + * Connect the interrupt controller interrupt handler to the hardware + * interrupt handling logic in the processor. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, + (Xil_ExceptionHandler)XScuGic_DeviceInterruptHandler, + NULL); + + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + XScuGic_RegisterHandler(SCUGIC_CPU_BASEADDR, + PROFILE_TIMER_INTR_ID, + (Xil_ExceptionHandler)profile_intr_handler, + NULL); + + /* + * Enable the interrupt for scu timer. + */ + XScuGic_EnableIntr(SCUGIC_DIST_BASEADDR, PROFILE_TIMER_INTR_ID); + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); + + /* + * Initialize the timer with Timer Ticks + */ + (void)scu_timer_init() ; + + Xil_ExceptionEnable(); + + return 0; +} + +#endif /* PROC_CORTEXA9 */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_timer_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_timer_hw.h new file mode 100644 index 0000000..b80c577 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/_profile_timer_hw.h @@ -0,0 +1,281 @@ +/****************************************************************************** +* Copyright (c) 2004 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#ifndef PROFILE_TIMER_HW_H +#define PROFILE_TIMER_HW_H + +#include "profile.h" + +#ifdef PROC_PPC +#if defined __GNUC__ +# define SYNCHRONIZE_IO __asm__ volatile ("eieio") +#elif defined __DCC__ +# define SYNCHRONIZE_IO __asm volatile(" eieio") +#else +# define SYNCHRONIZE_IO +#endif +#endif + +#ifdef PROC_PPC +#define ProfIo_In32(InputPtr) { (*(volatile u32 *)(InputPtr)); SYNCHRONIZE_IO; } +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = Value); SYNCHRONIZE_IO; } +#else +#define ProfIo_In32(InputPtr) (*(volatile u32 *)(InputPtr)); +#define ProfIo_Out32(OutputPtr, Value) { (*(volatile u32 *)(OutputPtr) = (Value)); } +#endif + +#define ProfTmrCtr_mWriteReg(BaseAddress, TmrCtrNumber, RegOffset, ValueToWrite)\ + ProfIo_Out32(((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + \ + (u32)(RegOffset)), (u32)(ValueToWrite)) + +#define ProfTimerCtr_mReadReg(BaseAddress, TmrCtrNumber, RegOffset) \ + ProfIo_In32((u32)(BaseAddress) + (u32)XTmrCtr_Offsets[(TmrCtrNumber)] + (u32)(RegOffset)) + +#define ProfTmrCtr_mSetControlStatusReg(BaseAddress, TmrCtrNumber, RegisterValue)\ + ProfTmrCtr_mWriteReg((BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET, \ + (RegisterValue)) + +#define ProfTmrCtr_mGetControlStatusReg(BaseAddress, TmrCtrNumber) \ + ProfTimerCtr_mReadReg((u32)(BaseAddress), (TmrCtrNumber), XTC_TCSR_OFFSET) + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PROC_PPC +#include "xexception_l.h" +#include "xtime_l.h" +#include "xpseudo_asm.h" +#endif + +#ifdef TIMER_CONNECT_INTC +#include "xintc_l.h" +#include "xintc.h" +#endif /* TIMER_CONNECT_INTC */ + +#if (!defined PPC_PIT_INTERRUPT && !defined PROC_CORTEXA9) +#include "xtmrctr_l.h" +#endif + +#ifdef PROC_CORTEXA9 +#include "xscutimer_hw.h" +#include "xscugic.h" +#endif + +extern u32 timer_clk_ticks ; + +/*-------------------------------------------------------------------- + * PowerPC Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_PPC + +#ifdef PPC_PIT_INTERRUPT +u32 timer_lo_clk_ticks ; /* Clk ticks when Timer is disabled in CG */ +#endif + +#ifdef PROC_PPC440 +#define XREG_TCR_PIT_INTERRUPT_ENABLE XREG_TCR_DEC_INTERRUPT_ENABLE +#define XREG_TSR_PIT_INTERRUPT_STATUS XREG_TSR_DEC_INTERRUPT_STATUS +#define XREG_SPR_PIT XREG_SPR_DEC +#define XEXC_ID_PIT_INT XEXC_ID_DEC_INT +#endif + +/* -------------------------------------------------------------------- + * Disable the Timer - During Profiling + * + * For PIT Timer - + * 1. XTime_PITDisableInterrupt() ; + * 2. Store the remaining timer clk tick + * 3. Stop the PIT Timer + *-------------------------------------------------------------------- */ + +#ifdef PPC_PIT_INTERRUPT +#define disable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val & (~XREG_TCR_PIT_INTERRUPT_ENABLE)); \ + timer_lo_clk_ticks = mfspr(XREG_SPR_PIT); \ + mtspr(XREG_SPR_PIT, 0); \ + } +#else +#define disable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v & (~XTC_CSR_ENABLE_TMR_MASK); \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Enable the Timer + * + * For PIT Timer - + * 1. Load the remaining timer clk ticks + * 2. XTime_PITEnableInterrupt() ; + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define enable_timer() \ + { \ + u32 val; \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_PIT, timer_lo_clk_ticks); \ + mtspr(XREG_SPR_TCR, val | XREG_TCR_PIT_INTERRUPT_ENABLE); \ + } +#else +#define enable_timer() \ + { \ + u32 addr = (PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(addr); \ + tmp_v = tmp_v | XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((PROFILE_TIMER_BASEADDR) + XTmrCtr_Offsets[(0)] + XTC_TCSR_OFFSET, tmp_v); \ + } +#endif + + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + * For PIT Timer - + * 1. Load the timer clk ticks + * 2. Enable AutoReload and Interrupt + * 3. Clear PIT Timer Status bits + *-------------------------------------------------------------------- */ +#ifdef PPC_PIT_INTERRUPT +#define timer_ack() \ + { \ + u32 val; \ + mtspr(XREG_SPR_PIT, timer_clk_ticks); \ + mtspr(XREG_SPR_TSR, XREG_TSR_PIT_INTERRUPT_STATUS); \ + val=mfspr(XREG_SPR_TCR); \ + mtspr(XREG_SPR_TCR, val| XREG_TCR_PIT_INTERRUPT_ENABLE| XREG_TCR_AUTORELOAD_ENABLE); \ + } +#else +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg(PROFILE_TIMER_BASEADDR, 0); \ + ProfTmrCtr_mSetControlStatusReg(PROFILE_TIMER_BASEADDR, 0, csr); \ + } +#endif + +/*-------------------------------------------------------------------- */ +#endif /* PROC_PPC */ +/* -------------------------------------------------------------------- */ + + + + +/* -------------------------------------------------------------------- + * MicroBlaze Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_MICROBLAZE + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = ProfIo_In32(Addr); \ + tmp_v = tmp_v & (u32)(~XTC_CSR_ENABLE_TMR_MASK); \ + u32 OutAddr = (u32)PROFILE_TIMER_BASEADDR; \ + OutAddr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + OutAddr += (u32)XTC_TCSR_OFFSET; \ + ProfIo_Out32(OutAddr, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ + { \ + u32 Addr = ((u32)PROFILE_TIMER_BASEADDR); \ + Addr += (u32)XTmrCtr_Offsets[(u16)(0)]; \ + Addr += (u32)XTC_TCSR_OFFSET; \ + u32 tmp_v = (u32)ProfIo_In32(Addr); \ + tmp_v = tmp_v | (u32)XTC_CSR_ENABLE_TMR_MASK; \ + ProfIo_Out32((u32)(PROFILE_TIMER_BASEADDR) + (u32)XTmrCtr_Offsets[(u16)(0)] + (u32)XTC_TCSR_OFFSET, (u32)tmp_v); \ + } + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ + { \ + u32 csr; \ + csr = ProfTmrCtr_mGetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0); \ + ProfTmrCtr_mSetControlStatusReg((u32)PROFILE_TIMER_BASEADDR, (u16)0, (u32)csr); \ + } + +/*-------------------------------------------------------------------- */ +#endif /* PROC_MICROBLAZE */ +/*-------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------- + * Cortex A9 Target - Timer related functions + *-------------------------------------------------------------------- */ +#ifdef PROC_CORTEXA9 + +/* -------------------------------------------------------------------- + * Disable the Timer during Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define disable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg &= (~XSCUTIMER_CONTROL_ENABLE_MASK);\ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Enable the Timer after Call-Graph Data collection + * + *-------------------------------------------------------------------- */ +#define enable_timer() \ +{ \ + u32 Reg; \ + Reg = Xil_In32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET); \ + Reg |= XSCUTIMER_CONTROL_ENABLE_MASK; \ + Xil_Out32(PROFILE_TIMER_BASEADDR + XSCUTIMER_CONTROL_OFFSET, Reg);\ +} + + +/* -------------------------------------------------------------------- + * Send Ack to Timer Interrupt + * + *-------------------------------------------------------------------- */ +#define timer_ack() \ +{ \ + Xil_Out32((u32)PROFILE_TIMER_BASEADDR + (u32)XSCUTIMER_ISR_OFFSET, \ + (u32)XSCUTIMER_ISR_EVENT_FLAG_MASK);\ +} + +/*-------------------------------------------------------------------- */ +#endif /* PROC_CORTEXA9 */ +/*-------------------------------------------------------------------- */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/dummy.S b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/dummy.S new file mode 100644 index 0000000..85fb264 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/dummy.S @@ -0,0 +1,37 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + .globl dummy_f + +#ifdef PROC_MICROBLAZE + .text + .align 2 + .ent dummy_f + +dummy_f: + nop + + .end dummy_f +#endif + +#ifdef PROC_PPC + .section .text + .align 2 + .type dummy_f@function + +dummy_f: + b dummy_f + +#endif + +#ifdef PROC_CORTEXA9 + .section .text + .align 2 + .type dummy_f, %function + +dummy_f: + b dummy_f + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/mblaze_nt_types.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/mblaze_nt_types.h new file mode 100644 index 0000000..6b51ea9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/mblaze_nt_types.h @@ -0,0 +1,28 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + + +#ifndef _MBLAZE_NT_TYPES_H +#define _MBLAZE_NT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char byte; +typedef short half; +typedef int word; +typedef unsigned char ubyte; +typedef unsigned short uhalf; +typedef unsigned int uword; +typedef ubyte boolean; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile.h new file mode 100644 index 0000000..27b3df1 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile.h @@ -0,0 +1,105 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#ifndef PROFILE_H +#define PROFILE_H 1 + +#include +#include "xil_types.h" +#include "profile_config.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void _system_init( void ) ; +void _system_clean( void ) ; +void mcount(u32 frompc, u32 selfpc); +void profile_intr_handler( void ) ; +void _profile_init( void ); + + + +/**************************************************************************** + * Profiling on hardware - Hash table maintained on hardware and data sent + * to xmd for gmon.out generation. + ****************************************************************************/ +/* + * histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER u16 + +struct tostruct { + u32 selfpc; + s32 count; + s16 link; + u16 pad; +}; + +struct fromstruct { + u32 frompc ; + s16 link ; + u16 pad ; +} ; + +/* + * general rounding functions. + */ +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) + +/* + * The profiling data structures are housed in this structure. + */ +struct gmonparam { + s32 state; + + /* Histogram Information */ + u16 *kcount; /* No. of bins in histogram */ + u32 kcountsize; /* Histogram samples */ + + /* Call-graph Information */ + struct fromstruct *froms; + u32 fromssize; + struct tostruct *tos; + u32 tossize; + + /* Initialization I/Ps */ + u32 lowpc; + u32 highpc; + u32 textsize; + /* u32 cg_froms, */ + /* u32 cg_tos, */ +}; +extern struct gmonparam *_gmonparam; +extern s32 n_gmon_sections; + +/* + * Possible states of profiling. + */ +#define GMON_PROF_ON 0 +#define GMON_PROF_BUSY 1 +#define GMON_PROF_ERROR 2 +#define GMON_PROF_OFF 3 + +/* + * Sysctl definitions for extracting profiling information from the kernel. + */ +#define GPROF_STATE 0 /* int: profiling enabling variable */ +#define GPROF_COUNT 1 /* struct: profile tick count buffer */ +#define GPROF_FROMS 2 /* struct: from location hash bucket */ +#define GPROF_TOS 3 /* struct: destination/count structure */ +#define GPROF_GMONPARAM 4 /* struct: profiling parameters (see above) */ + +#ifdef __cplusplus +} +#endif + +#endif /* PROFILE_H */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_cg.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_cg.c new file mode 100644 index 0000000..4e3a872 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_cg.c @@ -0,0 +1,145 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include "profile.h" +#include "_profile_timer_hw.h" +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +/* + * The mcount function is excluded from the library, if the user defines + * PROFILE_NO_GRAPH. + */ +#ifndef PROFILE_NO_GRAPH + +#include +#include +#include + +#ifdef PROFILE_NO_FUNCPTR +s32 searchpc(const struct fromto_struct *cgtable, s32 cgtable_size, u32 frompc ); +#else +s32 searchpc(const struct fromstruct *froms, s32 fromssize, u32 frompc ); +#endif + +/*extern struct gmonparam *_gmonparam, */ + +#ifdef PROFILE_NO_FUNCPTR +s32 searchpc(const struct fromto_struct *cgtable, s32 cgtable_size, u32 frompc ) +{ + s32 index = 0 ; + + while( (index < cgtable_size) && (cgtable[index].frompc != frompc) ){ + index++ ; + } + if( index == cgtable_size ) { + return -1 ; + } else { + return index ; + } +} +#else +s32 searchpc(const struct fromstruct *froms, s32 fromssize, u32 frompc ) +{ + s32 index = 0 ; + s32 Status; + + while( (index < fromssize) && (froms[index].frompc != frompc) ){ + index++ ; + } + if( index == fromssize ) { + Status = -1 ; + } else { + Status = index ; + } + return Status; +} +#endif /* PROFILE_NO_FUNCPTR */ + + +void mcount( u32 frompc, u32 selfpc ) +{ + register struct gmonparam *p = NULL; + register s32 toindex, fromindex; + s32 j; + + disable_timer(); + + /*print("CG: "), putnum(frompc), print("->"), putnum(selfpc), print("\r\n") , + * check that frompcindex is a reasonable pc value. + * for example: signal catchers get called from the stack, + * not from text space. too bad. + */ + for(j = 0; j < n_gmon_sections; j++ ){ + if((frompc >= _gmonparam[j].lowpc) && (frompc < _gmonparam[j].highpc)) { + p = &_gmonparam[j]; + break; + } + } + if( j == n_gmon_sections ) { + goto done; + } + +#ifdef PROFILE_NO_FUNCPTR + fromindex = searchpc( p->cgtable, p->cgtable_size, frompc ) ; + if( fromindex == -1 ) { + fromindex = p->cgtable_size ; + p->cgtable_size++ ; + p->cgtable[fromindex].frompc = frompc ; + p->cgtable[fromindex].selfpc = selfpc ; + p->cgtable[fromindex].count = 1 ; + goto done ; + } + p->cgtable[fromindex].count++ ; +#else + fromindex = (s32)searchpc( p->froms, ((s32)p->fromssize), frompc ) ; + if( fromindex == -1 ) { + fromindex = (s32)p->fromssize ; + p->fromssize++ ; + /*if( fromindex >= N_FROMS ) { + * print("Error : From PC table overflow\r\n") + * goto overflow + *}*/ + p->froms[fromindex].frompc = frompc ; + p->froms[fromindex].link = -1 ; + }else { + toindex = ((s32)(p->froms[fromindex].link)); + while(toindex != -1) { + toindex = (((s32)p->tossize) - toindex)-1 ; + if( p->tos[toindex].selfpc == selfpc ) { + p->tos[toindex].count++ ; + goto done ; + } + toindex = ((s32)(p->tos[toindex].link)) ; + } + } + + /*if( toindex == -1 ) { */ + p->tos-- ; + p->tossize++ ; + /* if( toindex >= N_TOS ) { + * print("Error : To PC table overflow\r\n") + * goto overflow + *} */ + p->tos[0].selfpc = selfpc ; + p->tos[0].count = 1 ; + p->tos[0].link = p->froms[fromindex].link ; + p->froms[fromindex].link = ((s32)(p->tossize))-((s32)1); +#endif + + done: + p->state = GMON_PROF_ON; + goto enable_timer_label ; + /* overflow: */ + /*p->state = GMON_PROF_ERROR */ + enable_timer_label: + enable_timer(); + return ; +} + + +#endif /* PROFILE_NO_GRAPH */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_config.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_config.h new file mode 100644 index 0000000..3f171b9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_config.h @@ -0,0 +1,30 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + + +#ifndef _PROFILE_CONFIG_H +#define _PROFILE_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define BINSIZE 4U +#define SAMPLE_FREQ_HZ 100000U +#define TIMER_CLK_TICKS 1000U + +#define PROFILE_NO_FUNCPTR_FLAG 0 + +#define PROFILE_TIMER_BASEADDR 0x00608000U +#define PROFILE_TIMER_INTR_ID 0U + +#define TIMER_CONNECT_INTC + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_hist.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_hist.c new file mode 100644 index 0000000..761e084 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_hist.c @@ -0,0 +1,45 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include "profile.h" +#include "_profile_timer_hw.h" + +#ifdef PROC_MICROBLAZE +#include "mblaze_nt_types.h" +#endif + +#ifdef PROC_PPC +#include "xpseudo_asm.h" +#define SPR_SRR0 0x01A +#endif + +#include "xil_types.h" + +extern u32 binsize ; +u32 prof_pc ; + +void profile_intr_handler( void ) +{ + + s32 j; + +#ifdef PROC_MICROBLAZE + asm( "swi r14, r0, prof_pc" ) ; +#elif defined PROC_PPC + prof_pc = mfspr(SPR_SRR0); +#else + /* for cortexa9, lr is saved in asm interrupt handler */ +#endif + /* print("PC: "), putnum(prof_pc), print("\r\n"), */ + for(j = 0; j < n_gmon_sections; j++ ){ + if((prof_pc >= ((u32)_gmonparam[j].lowpc)) && (prof_pc < ((u32)_gmonparam[j].highpc))) { + _gmonparam[j].kcount[(prof_pc-_gmonparam[j].lowpc)/((u32)4 * binsize)]++; + break; + } + } + /* Ack the Timer Interrupt */ + timer_ack(); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_arm.S b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_arm.S new file mode 100644 index 0000000..46c83f2 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_arm.S @@ -0,0 +1,18 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +// based on "ARM Profiling Implementation" from Sourcery G++ Lite for ARM EABI + +.globl __gnu_mcount_nc +.type __gnu_mcount_nc, %function + +__gnu_mcount_nc: + push {r0, r1, r2, r3, lr} + subs r1, lr, #0 /* callee - current lr */ + ldr r0, [sp, #20] /* caller - at the top of the stack */ + bl mcount /* when __gnu_mcount_nc is called */ + pop {r0, r1, r2, r3, ip, lr} + bx ip + + .end __gnu_mcount_nc diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_mb.S b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_mb.S new file mode 100644 index 0000000..20f0886 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_mb.S @@ -0,0 +1,42 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + .globl _mcount + .text + .align 2 + .ent _mcount + + #ifndef PROFILE_NO_GRAPH + +_mcount: + addi r1, r1, -48 + swi r11, r1, 44 + swi r12, r1, 40 + swi r5, r1, 36 + swi r6, r1, 32 + swi r7, r1, 28 + swi r8, r1, 24 + swi r9, r1, 20 + swi r10, r1, 16 + swi r15, r1, 12 + add r5, r0, r15 + brlid r15, mcount + add r6, r0, r16 + + lwi r11, r1, 44 + lwi r12, r1, 40 + lwi r5, r1, 36 + lwi r6, r1, 32 + lwi r7, r1, 28 + lwi r8, r1, 24 + lwi r9, r1, 20 + lwi r10, r1, 16 + lwi r15, r1, 12 + rtsd r15, 4 + addi r1, r1, 48 + + #endif /* PROFILE_NO_GRAPH */ + + .end _mcount diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_ppc.S b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_ppc.S new file mode 100644 index 0000000..6be38d9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/profile/profile_mcount_ppc.S @@ -0,0 +1,44 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + .globl _mcount + + #define _MCOUNT_STACK_FRAME 48 + .section .text + .align 2 + .type _mcount@function + + +_mcount: + stwu 1, -_MCOUNT_STACK_FRAME(1) + stw 3, 8(1) + stw 4, 12(1) + stw 5, 16(1) + stw 6, 20(1) + stw 7, 24(1) + stw 8, 28(1) + stw 9, 32(1) + stw 10, 36(1) + stw 11, 40(1) + stw 12, 44(1) + mflr 4 + stw 4, (_MCOUNT_STACK_FRAME+4)(1) + lwz 3, (_MCOUNT_STACK_FRAME)(1) + lwz 3, 4(3) + bl mcount + lwz 4, (_MCOUNT_STACK_FRAME+4)(1) + mtlr 4 + lwz 12, 44(1) + lwz 11, 40(1) + lwz 10, 36(1) + lwz 9, 32(1) + lwz 8, 28(1) + lwz 7, 24(1) + lwz 6, 20(1) + lwz 5, 16(1) + lwz 4, 12(1) + lwz 3, 8(1) + addi 1,1, _MCOUNT_STACK_FRAME + blr diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/putnum.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/putnum.c new file mode 100644 index 0000000..a4c5e47 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/putnum.c @@ -0,0 +1,55 @@ +/* putnum.c -- put a hex number on the output device. + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + +/* + * putnum -- print a 32 bit number in hex + */ + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_printf.h" + +/************************** Function Prototypes ******************************/ +void putnum(u32 num); + +void putnum(u32 num) +{ + char8 buf[9]; + s32 cnt, val=7; + s32 i; + char8 *ptr; + u32 digit; + for(i = 0; i<9; i++) { + buf[i] = '0'; + } + + ptr = buf; + for (cnt = 0 ; cnt <= 7 ; cnt++) { + digit = (num >> ((u32)val * 4U)) & 0x0000000fU; + + if (digit <= 9U) { + digit += (u32)'0'; + *ptr = ((char8) digit); + ptr += 1; + } else { + digit += ((u32)'a' - (u32)10); + *ptr = ((char8)digit); + ptr += 1; + } + val--; + } + + print (buf); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/read.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/read.c new file mode 100644 index 0000000..eb81317 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/read.c @@ -0,0 +1,83 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +/* read.c -- read bytes from a input device. + */ +#ifndef UNDEFINE_FILE_OPS +#include "xil_printf.h" +#include "xparameters.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) s32 _read (s32 fd, char8* buf, s32 nbytes); +__attribute__((weak)) s32 read (s32 fd, char8* buf, s32 nbytes); + +#ifdef __cplusplus +} +#endif + +/* + * read -- read bytes from the serial port. Ignore fd, since + * we only have stdin. + */ +__attribute__((weak)) s32 +read (s32 fd, char8* buf, s32 nbytes) +{ +#ifdef STDIN_BASEADDRESS + s32 i; + s32 numbytes = 0; + char8* LocalBuf = buf; + + (void)fd; + if(LocalBuf != NULL) { + for (i = 0; i < nbytes; i++) { + numbytes++; + LocalBuf[i] = inbyte(); + if ((LocalBuf[i] == '\n' )|| (LocalBuf[i] == '\r')) { + break; + } + } + } + + return numbytes; +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +} + +__attribute__((weak)) s32 +_read (s32 fd, char8* buf, s32 nbytes) +{ +#ifdef STDIN_BASEADDRESS + s32 i; + s32 numbytes = 0; + char8* LocalBuf = buf; + + (void)fd; + if(LocalBuf != NULL) { + for (i = 0; i < nbytes; i++) { + numbytes++; + LocalBuf[i] = inbyte(); + if ((LocalBuf[i] == '\n' )|| (LocalBuf[i] == '\r')) { + break; + } + } + } + + return numbytes; +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +} +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sbrk.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sbrk.c new file mode 100644 index 0000000..fd00c99 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sbrk.c @@ -0,0 +1,39 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) char8 *sbrk (s32 nbytes); + +#ifdef __cplusplus +} +#endif + +extern u8 _heap_start[]; +extern u8 _heap_end[]; +extern char8 HeapBase[]; +extern char8 HeapLimit[]; + + + +__attribute__((weak)) char8 *sbrk (s32 nbytes) +{ + char8 *base; + static char8 *heap_ptr = HeapBase; + + base = heap_ptr; + if((heap_ptr != NULL) && ((heap_ptr + nbytes) <= ((char8 *)&HeapLimit + 1))) { + heap_ptr += nbytes; + return base; + } else { + errno = ENOMEM; + return ((char8 *)-1); + } +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sleep.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sleep.c new file mode 100644 index 0000000..efa60da --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sleep.c @@ -0,0 +1,66 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/***************************************************************************** +* +* @file sleep.c +* +* This function provides a second delay using the Global Timer register in +* the ARM Cortex A9 MP core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  11/11/09 First release
+* 3.07a sgd      07/05/12 Updated sleep function to make use Global
+* 6.0   asa      08/15/16 Updated the sleep signature. Fix for CR#956899.
+* 6.6	srm      10/18/17 Updated sleep routines to support user configurable
+*			  implementation. Now sleep routines will use Timer
+*                         specified by the user (i.e. Global timer/TTC timer)
+*
+* 
+* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "sleep.h" +#include "xtime_l.h" +#include "xparameters.h" + +#if defined (SLEEP_TIMER_BASEADDR) +#include "xil_sleeptimer.h" +#endif + +/*****************************************************************************/ +/* +* +* This API is used to provide delays in seconds +* +* @param seconds requested +* +* @return 0 always +* +* @note None. +* +****************************************************************************/ +unsigned sleep_A9(unsigned int seconds) +{ +#if defined (SLEEP_TIMER_BASEADDR) + Xil_SleepTTCCommon(seconds, COUNTS_PER_SECOND); +#else + XTime tEnd, tCur; + + XTime_GetTime(&tCur); + tEnd = tCur + (((XTime) seconds) * COUNTS_PER_SECOND); + do + { + XTime_GetTime(&tCur); + } while (tCur < tEnd); +#endif + + return 0; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sleep.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sleep.h new file mode 100644 index 0000000..3c9c788 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/sleep.h @@ -0,0 +1,105 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +/*****************************************************************************/ +/** +* @file sleep.h +* +* This header file contains ARM Cortex A53,A9,R5,Microblaze specific sleep +* related APIs. +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6   srm  11/02/17 Added processor specific sleep routines
+*								 function prototypes.
+* 7.7	sk   01/10/22 Typecast sleep declaration argument from unsigned int to
+* 		      u32 to fix misra_c_2012_directive_4_6 violation.
+* 7.7	sk   01/10/22 Modify the return type of sleep_R5 and usleep_R5 from
+* 		      unsigned to void to fix misra_c_2012_rule_17_7 violation.
+* 8.0	sk   03/02/22 Update usleep_R5 and usleep parameter types to fix misra_
+*		      c_2012_directive_4_6 violation.
+* 8.0	sk   03/17/22 Modify the return type of usleep_MB from int to void and
+*		      sleep_MB from unsigned to void to fix misra_c_2012_rule_
+*		      17_7 violation.
+* 8.0	sk   03/17/22 Modify sleep_MB parameter type from unsigned int to
+*		      u32 and usleep_MB parameter type from unsigned long to
+*		      ULONG to fix misra_c_2012_rule_4_6 violation.
+*
+* 
+* +******************************************************************************/ + +#ifndef SLEEP_H +#define SLEEP_H + +#include "xil_types.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/** +* +* This macro polls an address periodically until a condition is met or till the +* timeout occurs. +* The minimum timeout for calling this macro is 100us. If the timeout is less +* than 100us, it still waits for 100us. Also the unit for the timeout is 100us. +* If the timeout is not a multiple of 100us, it waits for a timeout of +* the next usec value which is a multiple of 100us. +* +* @param IO_func - accessor function to read the register contents. +* Depends on the register width. +* @param ADDR - Address to be polled +* @param VALUE - variable to read the value +* @param COND - Condition to checked (usually involves VALUE) +* @param TIMEOUT_US - timeout in micro seconds +* +* @return 0 - when the condition is met +* -1 - when the condition is not met till the timeout period +* +* @note none +* +*****************************************************************************/ +#define Xil_poll_timeout(IO_func, ADDR, VALUE, COND, TIMEOUT_US) \ + ( { \ + u64 timeout = TIMEOUT_US/100; \ + if(TIMEOUT_US%100!=0) \ + timeout++; \ + for(;;) { \ + VALUE = IO_func(ADDR); \ + if(COND) \ + break; \ + else { \ + usleep(100); \ + timeout--; \ + if(timeout==0) \ + break; \ + } \ + } \ + (timeout>0) ? 0 : -1; \ + } ) + +void usleep(ULONG useconds); +void sleep(u32 seconds); +void usleep_R5(ULONG useconds); +void sleep_R5(u32 seconds); +void usleep_MB(ULONG useconds); +void sleep_MB(u32 seconds); +int usleep_A53(unsigned long useconds); +unsigned sleep_A53(unsigned int seconds); +int usleep_A9(unsigned long useconds); +unsigned sleep_A9(unsigned int seconds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/smc.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/smc.h new file mode 100644 index 0000000..b4fa9d3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/smc.h @@ -0,0 +1,97 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file smc.h +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  11/03/09 Initial release.
+* 4.2	pkp	 08/04/14 Removed function definition of XSmc_NorInit and XSmc_NorInit
+*					  as smc.c is removed
+* 
+* +* @note None. +* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef SMC_H /* prevent circular inclusions */ +#define SMC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xil_io.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory controller configuration register offset */ +#define XSMCPSS_MC_STATUS 0x000U /* Controller status reg, RO */ +#define XSMCPSS_MC_INTERFACE_CONFIG 0x004U /* Interface config reg, RO */ +#define XSMCPSS_MC_SET_CONFIG 0x008U /* Set configuration reg, WO */ +#define XSMCPSS_MC_CLR_CONFIG 0x00CU /* Clear config reg, WO */ +#define XSMCPSS_MC_DIRECT_CMD 0x010U /* Direct command reg, WO */ +#define XSMCPSS_MC_SET_CYCLES 0x014U /* Set cycles register, WO */ +#define XSMCPSS_MC_SET_OPMODE 0x018U /* Set opmode register, WO */ +#define XSMCPSS_MC_REFRESH_PERIOD_0 0x020U /* Refresh period_0 reg, RW */ +#define XSMCPSS_MC_REFRESH_PERIOD_1 0x024U /* Refresh period_1 reg, RW */ + +/* Chip select configuration register offset */ +#define XSMCPSS_CS_IF0_CHIP_0_OFFSET 0x100U /* Interface 0 chip 0 config */ +#define XSMCPSS_CS_IF0_CHIP_1_OFFSET 0x120U /* Interface 0 chip 1 config */ +#define XSMCPSS_CS_IF0_CHIP_2_OFFSET 0x140U /* Interface 0 chip 2 config */ +#define XSMCPSS_CS_IF0_CHIP_3_OFFSET 0x160U /* Interface 0 chip 3 config */ +#define XSMCPSS_CS_IF1_CHIP_0_OFFSET 0x180U /* Interface 1 chip 0 config */ +#define XSMCPSS_CS_IF1_CHIP_1_OFFSET 0x1A0U /* Interface 1 chip 1 config */ +#define XSMCPSS_CS_IF1_CHIP_2_OFFSET 0x1C0U /* Interface 1 chip 2 config */ +#define XSMCPSS_CS_IF1_CHIP_3_OFFSET 0x1E0U /* Interface 1 chip 3 config */ + +/* User configuration register offset */ +#define XSMCPSS_UC_STATUS_OFFSET 0x200U /* User status reg, RO */ +#define XSMCPSS_UC_CONFIG_OFFSET 0x204U /* User config reg, WO */ + +/* Integration test register offset */ +#define XSMCPSS_IT_OFFSET 0xE00U + +/* ID configuration register offset */ +#define XSMCPSS_ID_PERIP_0_OFFSET 0xFE0U +#define XSMCPSS_ID_PERIP_1_OFFSET 0xFE4U +#define XSMCPSS_ID_PERIP_2_OFFSET 0xFE8U +#define XSMCPSS_ID_PERIP_3_OFFSET 0xFECU +#define XSMCPSS_ID_PCELL_0_OFFSET 0xFF0U +#define XSMCPSS_ID_PCELL_1_OFFSET 0xFF4U +#define XSMCPSS_ID_PCELL_2_OFFSET 0xFF8U +#define XSMCPSS_ID_PCELL_3_OFFSET 0xFFCU + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SMC_H */ + +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/time.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/time.c new file mode 100644 index 0000000..541b0e3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/time.c @@ -0,0 +1,27 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) clock_t clock(void); + +#ifdef __cplusplus +} +#endif +/* + * clock -- It supposed to return processor time. We are not implementing + * this function, as timekeeping is tightly coupled with system, hence + * always returning 0. Users can override this with their system + * specific implementation. + * + */ +__attribute__((weak)) clock_t clock(void) +{ + return (0); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/translation_table.S b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/translation_table.S new file mode 100644 index 0000000..125fe7f --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/translation_table.S @@ -0,0 +1,202 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +/*****************************************************************************/ +/** +* @file translation_table.S +* +* @addtogroup a9_boot_code +* @{ +*

translation_table.S

+* The translation_table.S contains a static page table required by MMU for +* cortex-A9. This translation table is flat mapped (input address = output +* address) with default memory attributes defined for zynq architecture. It +* utilizes short descriptor translation table format with each section defining +* 1 MB of memory. +* +* The overview of translation table memory attributes is described below. +* +*| | Memory Range | Definition in Translation Table | +*|-----------------------|-------------------------|-----------------------------------| +*| DDR | 0x00000000 - 0x3FFFFFFF | Normal write-back Cacheable | +*| PL | 0x40000000 - 0xBFFFFFFF | Strongly Ordered | +*| Reserved | 0xC0000000 - 0xDFFFFFFF | Unassigned | +*| Memory mapped devices | 0xE0000000 - 0xE02FFFFF | Device Memory | +*| Reserved | 0xE0300000 - 0xE0FFFFFF | Unassigned | +*| NAND, NOR | 0xE1000000 - 0xE3FFFFFF | Device memory | +*| SRAM | 0xE4000000 - 0xE5FFFFFF | Normal write-back Cacheable | +*| Reserved | 0xE6000000 - 0xF7FFFFFF | Unassigned | +*| AMBA APB Peripherals | 0xF8000000 - 0xF8FFFFFF | Device Memory | +*| Reserved | 0xF9000000 - 0xFBFFFFFF | Unassigned | +*| Linear QSPI - XIP | 0xFC000000 - 0xFDFFFFFF | Normal write-through cacheable | +*| Reserved | 0xFE000000 - 0xFFEFFFFF | Unassigned | +*| OCM | 0xFFF00000 - 0xFFFFFFFF | Normal inner write-back cacheable | +* +* For region 0x00000000 - 0x3FFFFFFF, a system where DDR is less than 1 GB, +* region after DDR and before PL is marked as undefined/reserved in translation +* table. In 0xF8000000 - 0xF8FFFFFF, 0xF8000C00 - 0xF8000FFF, 0xF8010000 - +* 0xF88FFFFF and 0xF8F03000 to 0xF8FFFFFF are reserved but due to granual size +* of 1 MB, it is not possible to define separate regions for them. For region +* 0xFFF00000 - 0xFFFFFFFF, 0xFFF00000 to 0xFFFB0000 is reserved but due to 1MB +* granual size, it is not possible to define separate region for it. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/09 Initial version
+* 3.04a sdm  01/13/12 Updated MMU table to mark DDR memory as Shareable
+* 3.07a sgd  07/05/2012 Configuring device address spaces as shareable device
+*		       instead of strongly-ordered.
+* 3.07a asa  07/17/2012 Changed the property of the ".mmu_tbl" section.
+* 4.2	pkp  09/02/2014 added entries for 0xfe000000 to 0xffefffff as reserved
+*			and  0xe0000000 - 0xe1ffffff is broken down into
+*			0xe0000000 - 0xe02fffff (memory mapped divides)
+*			0xe0300000 - 0xe0ffffff (reserved) and
+*			0xe1000000 - 0xe1ffffff (NAND)
+* 5.2	pkp  06/08/2015 put a check for XPAR_PS7_DDR_0_S_AXI_BASEADDR to confirm
+*			if DDR is present or not and accordingly generate the
+*			translation table
+* 6.1	pkp  07/11/2016 Corrected comments for memory attributes
+* 6.8   mus  07/12/2018 Mark DDR memory as inner cacheable, if BSP is built
+*			with the USE_AMP flag.
+* 
+* +* +******************************************************************************/ +#include "xparameters.h" + .globl MMUTable + + .section .mmu_tbl,"a" + +MMUTable: + /* Each table entry occupies one 32-bit word and there are + * 4096 entries, so the entire table takes up 16KB. + * Each entry covers a 1MB section. + */ +.set SECT, 0 + +#ifdef XPAR_PS7_DDR_0_S_AXI_BASEADDR +.set DDR_START, XPAR_PS7_DDR_0_S_AXI_BASEADDR +.set DDR_END, XPAR_PS7_DDR_0_S_AXI_HIGHADDR +.set DDR_SIZE, (DDR_END - DDR_START)+1 +.set DDR_REG, DDR_SIZE/0x100000 +#else +.set DDR_REG, 0 +#endif + +.set UNDEF_REG, 0x3FF - DDR_REG + +#ifndef USE_AMP + /*0x00000000 - 0x00100000 (inner and outer cacheable )*/ +.word SECT + 0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ +#else + /*0x00000000 - 0x00100000 (inner cacheable )*/ +.word SECT + 0x14de6 /* S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b1 */ +#endif +.set SECT, SECT+0x100000 + +.rept DDR_REG /* (DDR Cacheable) */ +.word SECT + 0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept UNDEF_REG /* (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + + +.rept 0x0400 /* 0x40000000 - 0x7fffffff (FPGA slave0) */ +.word SECT + 0xc02 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0400 /* 0x80000000 - 0xbfffffff (FPGA slave1) */ +.word SECT + 0xc02 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0200 /* 0xc0000000 - 0xdfffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x003 /* 0xe0000000 - 0xe02fffff (Memory mapped devices) + * UART/USB/IIC/SPI/CAN/GEM/GPIO/QSPI/SD/NAND */ +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0D /* 0xe0300000 - 0xe0ffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0010 /* 0xe1000000 - 0xe1ffffff (NAND) */ +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0020 /* 0xe2000000 - 0xe3ffffff (NOR) */ +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0020 /* 0xe4000000 - 0xe5ffffff (SRAM) */ +.word SECT + 0xc0e /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b1, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0120 /* 0xe6000000 - 0xf7ffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +/* 0xf8000c00 to 0xf8000fff, 0xf8010000 to 0xf88fffff and + 0xf8f03000 to 0xf8ffffff are reserved but due to granual size of + 1MB, it is not possible to define separate regions for them */ + +.rept 0x0010 /* 0xf8000000 - 0xf8ffffff (AMBA APB Peripherals) */ + +.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0030 /* 0xf9000000 - 0xfbffffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x0020 /* 0xfc000000 - 0xfdffffff (Linear QSPI - XIP) */ +.word SECT + 0xc0a /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b1, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +.rept 0x001F /* 0xfe000000 - 0xffefffff (unassigned/reserved). + * Generates a translation fault if accessed */ +.word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ +.set SECT, SECT+0x100000 +.endr + +/* 0xfff00000 to 0xfffb0000 is reserved but due to granual size of + 1MB, it is not possible to define separate region for it + + 0xfff00000 - 0xffffffff + 256K OCM when mapped to high address space + inner-cacheable */ +.word SECT + 0x4c0e /* S=b0 TEX=b100 AP=b11, Domain=b0, C=b1, B=b1 */ +.set SECT, SECT+0x100000 + +.end +/** +* @} End of "addtogroup a9_boot_code". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/unlink.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/unlink.c new file mode 100644 index 0000000..5092095 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/unlink.c @@ -0,0 +1,28 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#include +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) sint32 unlink(char8 *path); + +#ifdef __cplusplus +} +#endif +/* + * unlink -- since we have no file system, + * we just return an error. + */ +__attribute__((weak)) sint32 unlink(char8 *path) +{ + (void) path; + errno = EIO; + return (-1); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/usleep.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/usleep.c new file mode 100644 index 0000000..26966bf --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/usleep.c @@ -0,0 +1,81 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file usleep.c +* +* This function provides a microsecond delay using the Global Timer register in +* the ARM Cortex A9 MP core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  11/11/09 First release
+* 3.07a sgd      07/05/12 Updated micro sleep function to make use Global Timer
+* 4.2	pkp		 08/04/14 Removed unimplemented nanosleep routine as it is not
+*						  possible to generate timer in nanosecond due to
+*						  limited cpu frequency
+* 6.0   asa      08/15/16 Updated the usleep signature. Fix for CR#956899.
+* 6.6	srm	 10/18/17 Updated sleep routines to support user configurable
+*			  implementation. Now sleep routines will use Timer
+*                         specified by the user (i.e. Global timer/TTC timer)
+* 
+* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "sleep.h" +#include "xtime_l.h" +#include "xparameters.h" +#include "xil_types.h" +#include "xpseudo_asm.h" +#include "xreg_cortexa9.h" + +#if defined (SLEEP_TIMER_BASEADDR) +#include "xil_sleeptimer.h" +#endif + +/**************************** Constant Definitions ************************/ +#if defined (SLEEP_TIMER_BASEADDR) +#define COUNTS_PER_USECOND (SLEEP_TIMER_FREQUENCY / 1000000) +#else +/* Global Timer is always clocked at half of the CPU frequency */ +#define COUNTS_PER_USECOND (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ / (2U*1000000U)) +#endif + +/*****************************************************************************/ +/** +* +* This API gives a delay in microseconds +* +* @param useconds requested +* +* @return 0 if the delay can be achieved, -1 if the requested delay +* is out of range +* +* @note None. +* +****************************************************************************/ +int usleep_A9(unsigned long useconds) +{ +#if defined (SLEEP_TIMER_BASEADDR) + Xil_SleepTTCCommon(useconds, COUNTS_PER_USECOND); +#else + XTime tEnd, tCur; + + XTime_GetTime(&tCur); + tEnd = tCur + (((XTime) useconds) * COUNTS_PER_USECOND); + do + { + XTime_GetTime(&tCur); + } while (tCur < tEnd); +#endif + + return 0; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/vectors.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/vectors.c new file mode 100644 index 0000000..91ddaa9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/vectors.c @@ -0,0 +1,166 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file vectors.c +* +* This file contains the C level vectors for the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/09 Initial version, moved over from bsp area
+* 6.0   mus  27/07/16 Consolidated vectors for a53,a9 and r5 processor
+*                     and added UndefinedException for a53 32 bit and r5
+*                     processor
+* 8.0	sk   03/02/22 Move XExc_VectorTableEntry structure to xil_exception.h
+* 		      header file to fix misra_c_2012_rule_5_6 violation.
+* 8.0	sk   03/02/22 Move XExc_VectorTableEntry declaration to xil_exception.h
+* 		      header file to fix misra_c_2012_rule_8_4 violation.
+* 
+* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "xil_exception.h" +#include "vectors.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the FIQ interrupt called from the vectors.s +* file. +* +* @return None. +* +******************************************************************************/ +void FIQInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_FIQ_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_FIQ_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the IRQ interrupt called from the vectors.s +* file. +* +* @return None. +* +******************************************************************************/ +void IRQInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_IRQ_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_IRQ_INT].Data); +} + +#if !defined (__aarch64__) +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the Undefined exception called from the +* vectors.s file. +* +* @return None. +* +******************************************************************************/ +void UndefinedException(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_UNDEFINED_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_UNDEFINED_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the SW Interrupt called from the vectors.s +* file. +* +* @return None. +* +******************************************************************************/ +void SWInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_SWI_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_SWI_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the DataAbort Interrupt called from the +* vectors.s file. +* +* @return None. +* +******************************************************************************/ +void DataAbortInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_DATA_ABORT_INT].Handler( + XExc_VectorTable[XIL_EXCEPTION_ID_DATA_ABORT_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the PrefetchAbort Interrupt called from the +* vectors.s file. +* +* @return None. +* +******************************************************************************/ +void PrefetchAbortInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_PREFETCH_ABORT_INT].Handler( + XExc_VectorTable[XIL_EXCEPTION_ID_PREFETCH_ABORT_INT].Data); +} +#else + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the Synchronous Interrupt called from the vectors.s +* file. +* +* @return None. +* +******************************************************************************/ +void SynchronousInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_SYNC_INT].Handler(XExc_VectorTable[ + XIL_EXCEPTION_ID_SYNC_INT].Data); +} + +/*****************************************************************************/ +/** +* +* This is the C level wrapper for the SError Interrupt called from the +* vectors.s file. +* +* @return None. +* +******************************************************************************/ +void SErrorInterrupt(void) +{ + XExc_VectorTable[XIL_EXCEPTION_ID_SERROR_ABORT_INT].Handler( + XExc_VectorTable[XIL_EXCEPTION_ID_SERROR_ABORT_INT].Data); +} + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/vectors.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/vectors.h new file mode 100644 index 0000000..f9747c7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/vectors.h @@ -0,0 +1,64 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file vectors.h +* +* This file contains the C level vector prototypes for the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/10 Initial version, moved over from bsp area
+* 6.0   mus  07/27/16 Consolidated vectors for a9,a53 and r5 processors
+* 8.0	sk   03/02/22 Update _VECTORS_H_ with VECTORS_H_ to fix misra_c_
+* 		      2012_rule_21_1 violation.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef VECTORS_H_ +#define VECTORS_H_ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void FIQInterrupt(void); +void IRQInterrupt(void); +#if !defined (__aarch64__) +void SWInterrupt(void); +void DataAbortInterrupt(void); +void PrefetchAbortInterrupt(void); +void UndefinedException(void); +#else +void SynchronousInterrupt(void); +void SErrorInterrupt(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/write.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/write.c new file mode 100644 index 0000000..cf1d35e --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/write.c @@ -0,0 +1,100 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +/* write.c -- write bytes to an output device. + */ +#ifndef UNDEFINE_FILE_OPS +#include "xil_printf.h" +#include "xparameters.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((weak)) sint32 _write (sint32 fd, char8* buf, sint32 nbytes); +__attribute__((weak)) sint32 write (sint32 fd, char8* buf, sint32 nbytes); + +#ifdef __cplusplus +} +#endif + +/* + * write -- write bytes to the serial port. Ignore fd, since + * stdout and stderr are the same. Since we have no filesystem, + * open will only return an error. + */ +__attribute__((weak)) sint32 +write (sint32 fd, char8* buf, sint32 nbytes) + +{ +#ifdef STDOUT_BASEADDRESS + s32 i; + char8* LocalBuf = buf; + + (void)fd; + for (i = 0; i < nbytes; i++) { + if(LocalBuf != NULL) { + LocalBuf += i; + } + if(LocalBuf != NULL) { + if (*LocalBuf == '\n') { + outbyte ('\r'); + } + outbyte (*LocalBuf); + } + if(LocalBuf != NULL) { + LocalBuf -= i; + } + } + return (nbytes); +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +} + +__attribute__((weak)) sint32 +_write (sint32 fd, char8* buf, sint32 nbytes) +{ +#if defined (__aarch64__) && (HYP_GUEST == 1) && (EL1_NONSECURE == 1) && defined (XEN_USE_PV_CONSOLE) + sint32 length; + + (void)fd; + (void)nbytes; + length = XPVXenConsole_Write(buf); + return length; +#else +#ifdef STDOUT_BASEADDRESS + s32 i; + char8* LocalBuf = buf; + + (void)fd; + for (i = 0; i < nbytes; i++) { + if(LocalBuf != NULL) { + LocalBuf += i; + } + if(LocalBuf != NULL) { + if (*LocalBuf == '\n') { + outbyte ('\r'); + } + outbyte (*LocalBuf); + } + if(LocalBuf != NULL) { + LocalBuf -= i; + } + } + return (nbytes); +#else + (void)fd; + (void)buf; + (void)nbytes; + return 0; +#endif +#endif +} +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xbasic_types.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xbasic_types.h new file mode 100644 index 0000000..99b1375 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xbasic_types.h @@ -0,0 +1,113 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xbasic_types.h +* +* +* @note Dummy File for backwards compatibility +* + +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a adk   1/31/14  Added in bsp common folder for backward compatibility
+* 7.0   aru   01/21/19 Modified the typedef of u32,u16,u8
+* 7.0 	aru   02/06/19 Included stdint.h and stddef.h
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XBASIC_TYPES_H /* prevent circular inclusions */ +#define XBASIC_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** @name Legacy types + * Deprecated legacy types. + * @{ + */ +typedef uint8_t Xuint8; /**< unsigned 8-bit */ +typedef char Xint8; /**< signed 8-bit */ +typedef uint16_t Xuint16; /**< unsigned 16-bit */ +typedef short Xint16; /**< signed 16-bit */ +typedef uint32_t Xuint32; /**< unsigned 32-bit */ +typedef long Xint32; /**< signed 32-bit */ +typedef float Xfloat32; /**< 32-bit floating point */ +typedef double Xfloat64; /**< 64-bit double precision FP */ +typedef unsigned long Xboolean; /**< boolean (XTRUE or XFALSE) */ + +#if !defined __XUINT64__ +typedef struct +{ + Xuint32 Upper; + Xuint32 Lower; +} Xuint64; +#endif + +/** @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XIL_TYPES_H +typedef Xuint32 u32; +typedef Xuint16 u16; +typedef Xuint8 u8; +#endif +#else +#include +#endif + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +/* + * Xilinx NULL, TRUE and FALSE legacy support. Deprecated. + * Please use NULL, TRUE and FALSE + */ +#define XNULL NULL +#define XTRUE TRUE +#define XFALSE FALSE + +/* + * This file is deprecated and users + * should use xil_types.h and xil_assert.h\n\r + */ +#warning The xbasics_type.h file is deprecated and users should use xil_types.h and xil_assert. +#warning Please refer the Standalone BSP UG647 for further details + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ + +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xdebug.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xdebug.h new file mode 100644 index 0000000..8e6b3ef --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xdebug.h @@ -0,0 +1,78 @@ +/****************************************************************************** +* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +#ifndef XDEBUG +#define XDEBUG + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_printf.h" + +#if defined(DEBUG) && !defined(NDEBUG) + +#ifndef XDEBUG_WARNING +#define XDEBUG_WARNING +#warning DEBUG is enabled +#endif + +int printf(const char *format, ...); + +#define XDBG_DEBUG_ERROR 0x00000001U /* error condition messages */ +#define XDBG_DEBUG_GENERAL 0x00000002U /* general debug messages */ +#define XDBG_DEBUG_ALL 0xFFFFFFFFU /* all debugging data */ + +#define XDBG_DEBUG_FIFO_REG 0x00000100U /* display register reads/writes */ +#define XDBG_DEBUG_FIFO_RX 0x00000101U /* receive debug messages */ +#define XDBG_DEBUG_FIFO_TX 0x00000102U /* transmit debug messages */ +#define XDBG_DEBUG_FIFO_ALL 0x0000010FU /* all fifo debug messages */ + +#define XDBG_DEBUG_TEMAC_REG 0x00000400U /* display register reads/writes */ +#define XDBG_DEBUG_TEMAC_RX 0x00000401U /* receive debug messages */ +#define XDBG_DEBUG_TEMAC_TX 0x00000402U /* transmit debug messages */ +#define XDBG_DEBUG_TEMAC_ALL 0x0000040FU /* all temac debug messages */ + +#define XDBG_DEBUG_TEMAC_ADPT_RX 0x00000800U /* receive debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_TX 0x00000801U /* transmit debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_IOCTL 0x00000802U /* ioctl debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_MISC 0x00000803U /* debug msg for other routines */ +#define XDBG_DEBUG_TEMAC_ADPT_ALL 0x0000080FU /* all temac adapter debug messages */ + + +#define xdbg_current_types (XDBG_DEBUG_GENERAL | XDBG_DEBUG_ERROR | XDBG_DEBUG_TEMAC_REG | XDBG_DEBUG_FIFO_RX | XDBG_DEBUG_FIFO_TX | XDBG_DEBUG_FIFO_REG) + +#define xdbg_stmnt(x) x + +/* In VxWorks, if _WRS_GNU_VAR_MACROS is defined, special syntax is needed for + * macros that accept variable number of arguments + */ +#if defined(XENV_VXWORKS) && defined(_WRS_GNU_VAR_MACROS) +#define xdbg_printf(type, args...) (((type) & xdbg_current_types) ? printf (## args) : 0) +#else /* ANSI Syntax */ +#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) +#endif + +#define xdbg_exception_printf(type, ...) (((type) & xdbg_current_types) ? xil_printf (__VA_ARGS__) : 0) + +#else /* defined(DEBUG) && !defined(NDEBUG) */ + +#define xdbg_stmnt(x) + +/* See VxWorks comments above */ +#if defined(XENV_VXWORKS) && defined(_WRS_GNU_VAR_MACROS) +#define xdbg_printf(type, args...) +#else /* ANSI Syntax */ +#define xdbg_printf(...) +#endif +#endif /* defined(DEBUG) && !defined(NDEBUG) */ + +#ifdef __cplusplus +} +#endif + +#endif /* XDEBUG */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xenv.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xenv.h new file mode 100644 index 0000000..d8aef59 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xenv.h @@ -0,0 +1,169 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xenv.h +* +* Defines common services that are typically found in a host operating. +* environment. This include file simply includes an OS specific file based +* on the compile-time constant BUILD_ENV_*, where * is the name of the target +* environment. +* +* All services are defined as macros. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b ch   10/24/02 Added XENV_LINUX
+* 1.00a rmm  04/17/02 First release
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XENV_H /* prevent circular inclusions */ +#define XENV_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Select which target environment we are operating under + */ + +/* VxWorks target environment */ +#if defined XENV_VXWORKS +#include "xenv_vxworks.h" + +/* Linux target environment */ +#elif defined XENV_LINUX +#include "xenv_linux.h" + +/* Unit test environment */ +#elif defined XENV_UNITTEST +#include "ut_xenv.h" + +/* Integration test environment */ +#elif defined XENV_INTTEST +#include "int_xenv.h" + +/* Standalone environment selected */ +#else +#include "xenv_standalone.h" +#endif + + +/* + * The following comments specify the types and macro wrappers that are + * expected to be defined by the target specific header files + */ + +/**************************** Type Definitions *******************************/ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP + * + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * + * XENV_MEM_COPY(void *DestPtr, void *SrcPtr, unsigned Bytes) + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr is the destination address to copy data to. + * @param SrcPtr is the source address to copy data from. + * @param Bytes is the number of bytes to copy. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_MEM_FILL(void *DestPtr, char Data, unsigned Bytes) + * + * Fills an area of memory with constant data. + * + * @param DestPtr is the destination address to set. + * @param Data contains the value to set. + * @param Bytes is the number of bytes to set. + * + * @return None + */ +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + * + * Samples the processor's or external timer's time base counter. + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_US(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of microseconds. + */ + +/*****************************************************************************/ +/** + * + * XENV_TIME_STAMP_DELTA_MS(XTIME_STAMP *Stamp1Ptr, XTIME_STAMP* Stamp2Ptr) + * + * Computes the delta between the two time stamps. + * + * @param Stamp1Ptr - First sampled time stamp. + * @param Stamp1Ptr - Sedond sampled time stamp. + * + * @return An unsigned int value with units of milliseconds. + */ + +/*****************************************************************************//** + * + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. + * + * @param delay is the number of microseconds to delay. + * + * @return None + */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ + +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xenv_standalone.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xenv_standalone.h new file mode 100644 index 0000000..9794da0 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xenv_standalone.h @@ -0,0 +1,350 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xenv_standalone.h +* +* Defines common services specified by xenv.h. +* +* @note +* This file is not intended to be included directly by driver code. +* Instead, the generic xenv.h file is intended to be included by driver +* code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a wgr  02/28/07 Added cache handling macros.
+* 1.00a wgr  02/27/07 Simplified code. Deprecated old-style macro names.
+* 1.00a rmm  01/24/06 Implemented XENV_USLEEP. Assume implementation is being
+*                     used under Xilinx standalone BSP.
+* 1.00a xd   11/03/04 Improved support for doxygen.
+* 1.00a rmm  03/21/02 First release
+* 1.00a wgr  03/22/07 Converted to new coding style.
+* 1.00a rpm  06/29/07 Added udelay macro for standalone
+* 1.00a xd   07/19/07 Included xparameters.h as XPAR_ constants are referred
+*                     to in MICROBLAZE section
+* 1.00a ecm  09/19/08 updated for v7.20 of Microblaze, new functionality
+*
+* 
+* +* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XENV_STANDALONE_H +#define XENV_STANDALONE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +/****************************************************************************** + * + * Get the processor dependent includes + * + ******************************************************************************/ + +#include + +#if defined __MICROBLAZE__ +# include "mb_interface.h" +# include "xparameters.h" /* XPAR constants used below in MB section */ + +#elif defined __PPC__ +# include "sleep.h" +# include "xcache_l.h" /* also include xcache_l.h for caching macros */ +#endif + +/****************************************************************************** + * + * MEMCPY / MEMSET related macros. + * + * The following are straight forward implementations of memset and memcpy. + * + * NOTE: memcpy may not work if source and target memory area are overlapping. + * + ******************************************************************************/ +/*****************************************************************************/ +/** + * + * Copies a non-overlapping block of memory. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param SrcPtr + * Source address to copy data from. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_COPY is deprecated. Use memcpy() instead. + * + * @note + * This implementation MAY BREAK work if source and target memory + * area are overlapping. + * + *****************************************************************************/ + +#define XENV_MEM_COPY(DestPtr, SrcPtr, Bytes) \ + memcpy((void *) DestPtr, (const void *) SrcPtr, (size_t) Bytes) + + + +/*****************************************************************************/ +/** + * + * Fills an area of memory with constant data. + * + * @param DestPtr + * Destination address to copy data to. + * + * @param Data + * Value to set. + * + * @param Bytes + * Number of bytes to copy. + * + * @return None. + * + * @note + * The use of XENV_MEM_FILL is deprecated. Use memset() instead. + * + *****************************************************************************/ + +#define XENV_MEM_FILL(DestPtr, Data, Bytes) \ + memset((void *) DestPtr, (s32) Data, (size_t) Bytes) + + + +/****************************************************************************** + * + * TIME related macros + * + ******************************************************************************/ + +/** + * A structure that contains a time stamp used by other time stamp macros + * defined below. This structure is processor dependent. + */ +typedef s32 XENV_TIME_STAMP; + +/*****************************************************************************/ +/** + * + * Time is derived from the 64 bit PPC timebase register + * + * @param StampPtr is the storage for the retrieved time stamp. + * + * @return None. + * + * @note + * + * Signature: void XENV_TIME_STAMP_GET(XTIME_STAMP *StampPtr) + *

+ * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_GET(StampPtr) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_US(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * + * This macro is not yet implemented and always returns 0. + * + * @param Stamp1Ptr is the first sampled time stamp. + * @param Stamp2Ptr is the second sampled time stamp. + * + * @return 0 + * + * @note + * + * This macro must be implemented by the user. + * + *****************************************************************************/ +#define XENV_TIME_STAMP_DELTA_MS(Stamp1Ptr, Stamp2Ptr) (0) + +/*****************************************************************************/ +/** + * XENV_USLEEP(unsigned delay) + * + * Delay the specified number of microseconds. Not implemented without OS + * support. + * + * @param delay + * Number of microseconds to delay. + * + * @return None. + * + *****************************************************************************/ + +#ifdef __PPC__ +#define XENV_USLEEP(delay) usleep(delay) +#define udelay(delay) usleep(delay) +#else +#define XENV_USLEEP(delay) +#define udelay(delay) +#endif + + +/****************************************************************************** + * + * CACHE handling macros / mappings + * + ******************************************************************************/ +/****************************************************************************** + * + * Processor independent macros + * + ******************************************************************************/ + +#define XCACHE_ENABLE_CACHE() \ + { XCACHE_ENABLE_DCACHE(); XCACHE_ENABLE_ICACHE(); } + +#define XCACHE_DISABLE_CACHE() \ + { XCACHE_DISABLE_DCACHE(); XCACHE_DISABLE_ICACHE(); } + + +/****************************************************************************** + * + * MicroBlaze case + * + * NOTE: Currently the following macros will only work on systems that contain + * only ONE MicroBlaze processor. Also, the macros will only be enabled if the + * system is built using a xparameters.h file. + * + ******************************************************************************/ + +#if defined __MICROBLAZE__ + +/* Check if MicroBlaze data cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_DCACHE == 1) +# define XCACHE_ENABLE_DCACHE() microblaze_enable_dcache() +# define XCACHE_DISABLE_DCACHE() microblaze_disable_dcache() +# define XCACHE_INVALIDATE_DCACHE() microblaze_invalidate_dcache() + +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) + +#if (XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK == 1) +# define XCACHE_FLUSH_DCACHE() microblaze_flush_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_flush_dcache_range((s32)(Addr), (s32)(Len)) +#else +# define XCACHE_FLUSH_DCACHE() microblaze_invalidate_dcache() +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + microblaze_invalidate_dcache_range((s32)(Addr), (s32)(Len)) +#endif /*XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK*/ + +#else +# define XCACHE_ENABLE_DCACHE() +# define XCACHE_DISABLE_DCACHE() +# define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) +# define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) +#endif /*XPAR_MICROBLAZE_USE_DCACHE*/ + + +/* Check if MicroBlaze instruction cache was built into the core. + */ +#if (XPAR_MICROBLAZE_USE_ICACHE == 1) +# define XCACHE_ENABLE_ICACHE() microblaze_enable_icache() +# define XCACHE_DISABLE_ICACHE() microblaze_disable_icache() + +# define XCACHE_INVALIDATE_ICACHE() microblaze_invalidate_icache() + +# define XCACHE_INVALIDATE_ICACHE_RANGE(Addr, Len) \ + microblaze_invalidate_icache_range((s32)(Addr), (s32)(Len)) + +#else +# define XCACHE_ENABLE_ICACHE() +# define XCACHE_DISABLE_ICACHE() +#endif /*XPAR_MICROBLAZE_USE_ICACHE*/ + + +/****************************************************************************** + * + * PowerPC case + * + * Note that the XCACHE_ENABLE_xxx functions are hardcoded to enable a + * specific memory region (0x80000001). Each bit (0-30) in the regions + * bitmask stands for 128MB of memory. Bit 31 stands for the upper 2GB + * range. + * + * regions --> cached address range + * ------------|-------------------------------------------------- + * 0x80000000 | [0, 0x7FFFFFF] + * 0x00000001 | [0xF8000000, 0xFFFFFFFF] + * 0x80000001 | [0, 0x7FFFFFF],[0xF8000000, 0xFFFFFFFF] + * + ******************************************************************************/ + +#elif defined __PPC__ + +#define XCACHE_ENABLE_DCACHE() XCache_EnableDCache(0x80000001) +#define XCACHE_DISABLE_DCACHE() XCache_DisableDCache() +#define XCACHE_ENABLE_ICACHE() XCache_EnableICache(0x80000001) +#define XCACHE_DISABLE_ICACHE() XCache_DisableICache() + +#define XCACHE_INVALIDATE_DCACHE_RANGE(Addr, Len) \ + XCache_InvalidateDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_FLUSH_DCACHE_RANGE(Addr, Len) \ + XCache_FlushDCacheRange((u32)(Addr), (u32)(Len)) + +#define XCACHE_INVALIDATE_ICACHE() XCache_InvalidateICache() + + +/****************************************************************************** + * + * Unknown processor / architecture + * + ******************************************************************************/ + +#else +/* #error "Unknown processor / architecture. Must be MicroBlaze or PowerPC." */ +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef XENV_STANDALONE_H */ + + /** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil-crt0.S b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil-crt0.S new file mode 100644 index 0000000..a560286 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil-crt0.S @@ -0,0 +1,136 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xil-crt0.S +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a ecm  10/20/09 Initial version
+* 3.05a sdm  02/02/12 Added code for profiling
+* 3.06a sgd  05/16/12 Added global constructors and cleanup code
+*                     Uart initialization based on compiler flag
+* 3.07a sgd  07/05/12 Updated with reset and start Global Timer
+* 3.07a sgd  10/19/12 SMC NOR and SRAM initialization with build option
+* 4.2	pkp  08/04/14 Removed PEEP board related code which contained
+*		      initialization of uart smc nor and sram
+* 5.3	pkp  10/07/15 Added support for OpenAMP by not initializing global
+*		      timer when USE_AMP flag is defined
+* 6.6   srm  10/18/17 Added timer configuration using XTime_StartTTCTimer API.
+*		      Now the TTC instance as specified by the user will be
+*		      started.
+* 7.7   adk  11/30/21 Added support for xiltimer library.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ +#include "bspconfig.h" +#include "xparameters.h" + + .file "xil-crt0.S" + .section ".got2","aw" + .align 2 + + .text +.Lsbss_start: + .long __sbss_start + +.Lsbss_end: + .long __sbss_end + +.Lbss_start: + .long __bss_start + +.Lbss_end: + .long __bss_end + +.Lstack: + .long __stack + + + .globl _start +_start: + bl __cpu_init /* Initialize the CPU first (BSP provides this) */ + + mov r0, #0 + + /* clear sbss */ + ldr r1,.Lsbss_start /* calculate beginning of the SBSS */ + ldr r2,.Lsbss_end /* calculate end of the SBSS */ + +.Lloop_sbss: + cmp r1,r2 + bge .Lenclsbss /* If no SBSS, no clearing required */ + str r0, [r1], #4 + b .Lloop_sbss + +.Lenclsbss: + /* clear bss */ + ldr r1,.Lbss_start /* calculate beginning of the BSS */ + ldr r2,.Lbss_end /* calculate end of the BSS */ + +.Lloop_bss: + cmp r1,r2 + bge .Lenclbss /* If no BSS, no clearing required */ + str r0, [r1], #4 + b .Lloop_bss + +.Lenclbss: + + /* set stack pointer */ + ldr r13,.Lstack /* stack address */ + + /* Reset and start Global Timer */ + mov r0, #0x0 + mov r1, #0x0 + + /* Reset and start Triple Timer Counter */ + #if defined SLEEP_TIMER_BASEADDR + bl XTime_StartTTCTimer + #endif + +#ifndef XPAR_XILTIMER_ENABLED +#if USE_AMP != 1 + bl XTime_SetTime +#endif +#endif + +#ifdef PROFILING /* defined in Makefile */ + /* Setup profiling stuff */ + bl _profile_init +#endif /* PROFILING */ + + /* run global constructors */ + bl __libc_init_array + + /* make sure argc and argv are valid */ + mov r0, #0 + mov r1, #0 + + /* Let her rip */ + bl main + + /* Cleanup global constructors */ + bl __libc_fini_array + +#ifdef PROFILING + /* Cleanup profiling stuff */ + bl _profile_clean +#endif /* PROFILING */ + + /* All done */ + bl exit + +.Lexit: /* should never get here */ + b .Lexit + +.Lstart: + .size _start,.Lstart-_start diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_assert.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_assert.c new file mode 100644 index 0000000..b3dd7e9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_assert.c @@ -0,0 +1,126 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_assert.c +* @addtogroup common_assert_apis Assert APIs and Macros +* @{ +* +* This file contains basic assert related functions for Xilinx software IP. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 Initial release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/** + * @brief This variable allows testing to be done easier with asserts. An assert + * sets this variable such that a driver can evaluate this variable + * to determine if an assert occurred. + */ +u32 Xil_AssertStatus; + +/** + * @brief This variable allows the assert functionality to be changed for testing + * such that it does not wait infinitely. Use the debugger to disable the + * waiting during testing of asserts. + */ +s32 Xil_AssertWait = 1; + +/* The callback function to be invoked when an assert is taken */ +static Xil_AssertCallback Xil_AssertCallbackRoutine = NULL; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* @brief Implement assert. Currently, it calls a user-defined callback +* function if one has been set. Then, it potentially enters an +* infinite loop depending on the value of the Xil_AssertWait +* variable. +* +* @param File: filename of the source +* @param Line: linenumber within File +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void Xil_Assert(const char8 *File, s32 Line) +{ + /* if the callback has been set then invoke it */ + if (Xil_AssertCallbackRoutine != 0) { + (*Xil_AssertCallbackRoutine)(File, Line); + } + + /* if specified, wait indefinitely such that the assert will show up + * in testing + */ + while (Xil_AssertWait != 0) { + } +} + +/*****************************************************************************/ +/** +* +* @brief Set up a callback function to be invoked when an assert occurs. +* If a callback is already installed, then it will be replaced. +* +* @param Routine: callback to be invoked when an assert is taken +* +* @return None. +* +* @note This function has no effect if NDEBUG is set +* +******************************************************************************/ +void Xil_AssertSetCallback(Xil_AssertCallback Routine) +{ + Xil_AssertCallbackRoutine = Routine; +} + +/*****************************************************************************/ +/** +* +* @brief Null handler function. This follows the XInterruptHandler +* signature for interrupt handlers. It can be used to assign a null +* handler (a stub) to an interrupt controller vector table. +* +* @param NullParameter: arbitrary void pointer and not used. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XNullHandler(void *NullParameter) +{ + (void) NullParameter; +} +/** +* @} End of "addtogroup common_assert_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_assert.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_assert.h new file mode 100644 index 0000000..e8b87b5 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_assert.h @@ -0,0 +1,176 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_assert.h +* +* @addtogroup common_assert_apis Assert APIs and Macros +* +* The xil_assert.h file contains assert related functions and macros. +* Assert APIs/Macros specifies that a application program satisfies certain +* conditions at particular points in its execution. These function can be +* used by application programs to ensure that, application code is satisfying +* certain conditions. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 6.0   kvn  05/31/16 Make Xil_AsserWait a global variable
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_ASSERT_H /* prevent circular inclusions */ +#define XIL_ASSERT_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + + +/************************** Constant Definitions *****************************/ + +#define XIL_ASSERT_NONE 0U +#define XIL_ASSERT_OCCURRED 1U +#define XNULL NULL + +extern u32 Xil_AssertStatus; +extern s32 Xil_AssertWait; +extern void Xil_Assert(const char8 *File, s32 Line); +/** + *@endcond + */ +void XNullHandler(void *NullParameter); + +/** + * This data type defines a callback to be invoked when an + * assert occurs. The callback is invoked only when asserts are enabled + */ +typedef void (*Xil_AssertCallback) (const char8 *File, s32 Line); + +/***************** Macros (Inline Functions) Definitions *********************/ + +#ifndef NDEBUG + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for void functions. This in +* conjunction with the Xil_AssertWait boolean can be used to +* accommodate tests so that asserts which fail allow execution to +* continue. +* +* @param Expression: expression to be evaluated. If it evaluates to +* false, the assert occurs. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief This assert macro is to be used for functions that do return a +* value. This in conjunction with the Xil_AssertWait boolean can be +* used to accommodate tests so that asserts which fail allow execution +* to continue. +* +* @param Expression: expression to be evaluated. If it evaluates to false, +* the assert occurs. +* +* @return Returns 0 unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoid(Expression) \ +{ \ + if (Expression) { \ + Xil_AssertStatus = XIL_ASSERT_NONE; \ + } else { \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ + } \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for void functions. +* Use for instances where an assert should always occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertVoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return; \ +} + +/*****************************************************************************/ +/** +* @brief Always assert. This assert macro is to be used for functions that +* do return a value. Use for instances where an assert should always +* occur. +* +* @return Returns void unless the Xil_AssertWait variable is true, in which +* case no return is made and an infinite loop is entered. +* +******************************************************************************/ +#define Xil_AssertNonvoidAlways() \ +{ \ + Xil_Assert(__FILE__, __LINE__); \ + Xil_AssertStatus = XIL_ASSERT_OCCURRED; \ + return 0; \ +} + + +#else + +#define Xil_AssertVoid(Expression) +#define Xil_AssertVoidAlways() +#define Xil_AssertNonvoid(Expression) +#define Xil_AssertNonvoidAlways() + +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_AssertSetCallback(Xil_AssertCallback Routine); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_assert_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache.c new file mode 100644 index 0000000..f00fb25 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache.c @@ -0,0 +1,1530 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_cache.c +* +* Contains required functions for the ARM cache functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a  ecm 01/29/10 First release
+* 1.00a  ecm 06/24/10 Moved the L1 and L2 specific function prototypes
+*		      		  to xil_cache_mach.h to give access to sophisticated users
+* 3.02a  sdm 04/07/11 Updated Flush/InvalidateRange APIs to flush/invalidate
+*		      		  L1 and L2 caches in a single loop and used dsb, L2 sync
+*		      		  at the end of the loop.
+* 3.04a  sdm 01/02/12 Remove redundant dsb/dmb instructions in cache maintenance
+*		      		  APIs.
+* 3.07a  asa 07/16/12 Corrected the L1 and L2 cache invalidation order.
+* 3.07a  sgd 09/18/12 Corrected the L2 cache enable and disable sequence.
+* 3.10a  srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      		  'xil_errata.h' for errata description
+* 3.10a  asa 05/13/13 Modified cache disable APIs. The L2 cache disable
+*			  		  operation was being done with L1 Data cache disabled. This is
+*			  		  fixed so that L2 cache disable operation happens independent of
+*			  		  L1 cache disable operation. This fixes CR #706464.
+*			  		  Changes are done to do a L2 cache sync (poll reg7_?cache_?sync).
+*			  		  This is done to fix the CR #700542.
+* 3.11a  asa 09/23/13 Modified the Xil_DCacheFlushRange and
+*			 		  Xil_DCacheInvalidateRange to fix potential issues. Fixed other
+*			 		  relevant cache APIs to disable and enable back the interrupts.
+*			 		  This fixes CR #663885.
+* 3.11a  asa 09/28/13 Made changes for L2 cache sync operation. It is found
+*			 		  out that for L2 cache flush/clean/invalidation by cache lines
+*			 		  does not need a cache sync as these are atomic nature. Similarly
+*			 		  figured out that for complete L2 cache flush/invalidation by way
+*			 		  we need to wait for some more time in a loop till the status
+*			 		  shows that the cache operation is completed.
+* 4.00	 pkp 24/01/14 Modified Xil_DCacheInvalidateRange to fix the bug. Few
+*			 		  cache lines were missed to invalidate when unaligned address
+*			 		  invalidation was accommodated. That fixes CR #766768.
+*			 		  Also in Xil_L1DCacheInvalidate, while invalidating all L1D cache
+*			 		  stack memory which contains return address was invalidated. So
+*			 		  stack memory was flushed first and then L1D cache is invalidated.
+*			 		  This is done to fix CR #763829
+* 4.01   asa 05/09/14 Made changes in cortexa9/xil_cache.c to fix CR# 798230.
+* 4.02	 pkp 06/27/14 Added notes to Xil_L1DCacheInvalidateRange function for
+*					  explanation of CR#785243
+* 5.00   kvn 12/15/14 Xil_L2CacheInvalidate was modified to fix CR# 838835. L2 Cache
+*					  has stack memory which has return address. Before invalidating
+*					  cache, stack memory was flushed first and L2 Cache is invalidated.
+* 5.01	 pkp 05/12/15 Xil_DCacheInvalidateRange and Xil_DCacheFlushRange is modified
+*					  to remove unnecessary dsb in the APIs. Instead of using dsb
+*					  for L2 Cache, L2CacheSync has been used for each L2 cache line
+*					  and single dsb has been used for L1 cache. Also L2CacheSync is
+*					  added into Xil_L2CacheInvalidateRange API. Xil_L1DCacheInvalidate
+*					  and Xil_L2CacheInvalidate APIs are modified to flush the complete
+*					  stack instead of just System Stack
+* 5.03	 pkp 10/07/15 L2 Cache functionalities are avoided for the OpenAMP slave
+*					  application(when USE_AMP flag is defined for BSP) as master CPU
+*					  would be utilizing L2 cache for its operation
+* 6.6    mus 12/07/17 Errata 753970 is not applicable for the PL130 cache controller
+*                     version r0p2, which is present in zynq. So,removed the handling
+*                     related to same.It fixes CR#989132.
+* 6.6    asa 16/01/18 Changes made in Xil_L1DCacheInvalidate and Xil_L2CacheInvalidate
+*					  routines to ensure the stack data flushed only when the respective
+*					  caches are enabled. This fixes CR-992023.
+* 7.5    mus 01/19/21 Implement workaround for errata#588369 in Xil_DCacheFlushRange.
+*					  It fixes CR#1086022.
+* 8.0    asa 05/25/22 Fix issues in cache maintenance APIs Xil_DCacheFlushRange
+*                     and Xil_DCacheInvalidateRange to ensure that clean and
+*                     invalidation of outer cache (L2 cache) is separated out and
+*                     is independent from inner cache (L1 cache). This is inline
+*                     with recommendations and implementations available in open
+*                     source. It fixes CR#1130368.
+*                     Minimize use of barriers (dsb) as per guidances.
+*                     Remove the use of XREG_CP15_CACHE_SIZE_SEL register as it is
+*                     not needed for Zynq architecture.
+*                     Replace dsb with Xil_L2CacheSync as applicable as the latter
+*                     is more efficient while handling L2 cache maintenance.
+* 8.1    asa 02/13/23 The existing Xil_DCacheInvalidateRange has a bug where
+*                     the last cache line will not get invalidated under certain
+*                     scenarios. Changes are made to fix the same.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_cache.h" +#include "xil_cache_l.h" +#include "xil_io.h" +#include "xpseudo_asm.h" +#include "xparameters.h" +#include "xreg_cortexa9.h" +#include "xl2cc.h" +#include "xil_errata.h" +#include "xil_exception.h" + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#define IRQ_FIQ_MASK 0xC0U /* Mask IRQ and FIQ interrupts in cpsr */ + +#ifdef __GNUC__ + extern s32 _stack_end; + extern s32 __undef_stack; +#endif + +#ifndef USE_AMP +/**************************************************************************** +* +* Access L2 Debug Control Register. +* +* @param Value, value to be written to Debug Control Register. +* +* @return None. +* +****************************************************************************/ +#ifdef __GNUC__ +static inline void Xil_L2WriteDebugCtrl(u32 Value) +#else +static void Xil_L2WriteDebugCtrl(u32 Value) +#endif +{ +#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_DEBUG_CTRL_OFFSET, Value); +#else + (void)(Value); +#endif +} + +/**************************************************************************** +* +* Perform L2 Cache Sync Operation. +* +* @return None. +* +****************************************************************************/ +#ifdef __GNUC__ +static inline void Xil_L2CacheSync(void) +#else +static void Xil_L2CacheSync(void) +#endif +{ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_SYNC_OFFSET, 0x0U); +} +#endif +/****************************************************************************/ +/** +* @brief Enable the Data cache. +* +* @return None. +* +****************************************************************************/ +void Xil_DCacheEnable(void) +{ + Xil_L1DCacheEnable(); +#ifndef USE_AMP + Xil_L2CacheEnable(); +#endif +} + +/****************************************************************************/ +/** +* @brief Disable the Data cache. +* +* @return None. +* +****************************************************************************/ +void Xil_DCacheDisable(void) +{ +#ifndef USE_AMP + Xil_L2CacheDisable(); +#endif + Xil_L1DCacheDisable(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the entire Data cache. +* +* @return None. +* +****************************************************************************/ +void Xil_DCacheInvalidate(void) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidate(); +#endif + Xil_L1DCacheInvalidate(); + + mtcpsr(currmask); +} + +/*****************************************************************************/ +/** +* @brief Invalidate a Data cache line. If the byte specified by the address +* (adr) is cached by the Data cache, the cacheline containing that +* byte is invalidated. If the cacheline is modified (dirty), the +* modified contents are lost and are NOT written to the system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data to be flushed. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_DCacheInvalidateLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidateLine(adr); +#endif + Xil_L1DCacheInvalidateLine(adr); + + mtcpsr(currmask); +} + + +/*****************************************************************************/ +/** +* Invalidate the Data cache for the given address range. +* If the bytes specified by the address range are cached by the Data +* cache, the cachelines containing those bytes are invalidated. If +* the cachelines are modified (dirty), the modified contents are lost +* and NOT written to the system memory before the lines are +* invalidated. +* +* In this function, if start address or end address is not aligned to +* cache-line, particular cache-line containing unaligned start or end +* address is flush first and then invalidated the others as +* invalidating the same unaligned cache line may result into loss of +* data. This issue raises few possibilities. +* +* If the address to be invalidated is not cache-line aligned, the +* following choices are available: +* 1. Invalidate the cache line when required and do not bother much +* for the side effects. Though it sounds good, it can result in +* hard-to-debug issues. The problem is, if some other variable are +* allocated in the same cache line and had been recently updated +* (in cache), the invalidation would result in loss of data. +* 2. Flush the cache line first. This will ensure that if any other +* variable present in the same cache line and updated recently are +* flushed out to memory. Then it can safely be invalidated. Again it +* sounds good, but this can result in issues. For example, when the +* invalidation happens in a typical ISR (after a DMA transfer has +* updated the memory), then flushing the cache line means, losing +* data that were updated recently before the ISR got invoked. +* +* Linux prefers the second one. To have uniform implementation +* (across standalone and Linux), the second option is implemented. +* This being the case, following needs to be taken care of: +* 1. Whenever possible, the addresses must be cache line aligned. +* Please nore that, not just start address, even the end address must +* be cache line aligned. If that is taken care of, this will always +* work. +* 2. Avoid situations where invalidation has to be done after the +* data is updated by peripheral/DMA directly into the memory. It is +* not tough to achieve (may be a bit risky). The common use case to +* do invalidation is when a DMA happens. Generally for such use +* cases, buffers can be allocated first and then start the DMA. The +* practice that needs to be followed here is, immediately after +* buffer allocation and before starting the DMA, do the invalidation. +* With this approach, invalidation need not to be done after the DMA +* transfer is over. +* +* This is going to always work if done carefully. +* However, the concern is, there is no guarantee that invalidate has +* not needed to be done after DMA is complete. For example, because +* of some reasons if the first cache line or last cache line +* (assuming the buffer in question comprises of multiple cache lines) +* are brought into cache (between the time it is invalidated and DMA +* completes) because of some speculative prefetching or reading data +* for a variable present in the same cache line, then we will have to +* invalidate the cache after DMA is complete. +* +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +****************************************************************************/ +void Xil_DCacheInvalidateRange(INTPTR opstartaddr, u32 len) +{ + const u32 cacheline = 32U; + INTPTR tempadr; + INTPTR opendaddr; + INTPTR endaddr; + u32 currmask; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INVLD_PA_OFFSET); + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + opendaddr = opstartaddr + len; + endaddr = opendaddr; + + if ((opstartaddr & (cacheline-1U)) != 0U) { + opstartaddr &= (~(cacheline - 1U)); + + Xil_L1DCacheFlushLine(opstartaddr); +#ifndef USE_AMP + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + Xil_L2CacheFlushLine(opstartaddr); + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + Xil_L2CacheSync(); +#endif + opstartaddr += cacheline; + } + if ((opendaddr & (cacheline-1U)) != 0U) { + opendaddr &= (~(cacheline - 1U)); + + if (opendaddr != opstartaddr) { + Xil_L1DCacheFlushLine(opendaddr); +#ifndef USE_AMP + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + Xil_L2CacheFlushLine(opendaddr); + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + Xil_L2CacheSync(); +#endif + } + } + + tempadr = opstartaddr; + + while (tempadr < endaddr) { +#ifndef USE_AMP + /* Invalidate L2 cache line */ + *L2CCOffset = tempadr; + Xil_L2CacheSync(); + tempadr += cacheline; +#endif + } + + while (opstartaddr < endaddr) { + /* Invalidate L1 Data cache line */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_dc_line_mva_poc(opstartaddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_DC_LINE_MVA_POC); + Reg = opstartaddr; } +#endif + opstartaddr += cacheline; + } + /* Wait for L1 cache invalidation to complete */ + dsb(); + } + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the entire Data cache. +* +* @return None. +* +****************************************************************************/ +void Xil_DCacheFlush(void) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + Xil_L1DCacheFlush(); +#ifndef USE_AMP + Xil_L2CacheFlush(); +#endif + mtcpsr(currmask); +} + + +/****************************************************************************/ +/** +* @brief Flush a Data cache line. If the byte specified by the address (adr) +* is cached by the Data cache, the cacheline containing that byte is +* invalidated. If the cacheline is modified (dirty), the entire +* contents of the cacheline are written to system memory before the +* line is invalidated. +* +* @param adr: 32bit address of the data to be flushed. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_DCacheFlushLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + Xil_L1DCacheFlushLine(adr); +#ifndef USE_AMP + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + Xil_L2CacheFlushLine(adr); + + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); +#endif + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the Data cache for the given address range. +* If the bytes specified by the address range are cached by the +* data cache, the cachelines containing those bytes are invalidated. +* If the cachelines are modified (dirty), they are written to the +* system memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be flushed. +* @param len: Length of the range to be flushed in bytes. +* +* @return None. +* +****************************************************************************/ +void Xil_DCacheFlushRange(INTPTR opstartadr, u32 len) +{ + const u32 cacheline = 32U; + u32 opendadr; + u32 currmask; + u32 tempadr; + + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INV_CLN_PA_OFFSET); + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + opendadr = opstartadr + len; + opstartadr &= ~(cacheline - 1U); + + tempadr = opstartadr; + + while (tempadr < opendadr) { + /* Flush L1 Data cache line */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_clean_inval_dc_line_mva_poc(tempadr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC); + Reg = tempadr; } +#endif + tempadr += cacheline; + } + /* Wait for L1 cache clean and invalidation to complete */ + dsb(); + +#ifndef USE_AMP + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + while ((u32)opstartadr < opendadr) { + /* Flush L2 cache line */ + *L2CCOffset = opstartadr; + Xil_L2CacheSync(); + opstartadr += cacheline; + } + Xil_L2WriteDebugCtrl(0x0U); +#endif + } + mtcpsr(currmask); +} +/****************************************************************************/ +/** +* @brief Store a Data cache line. If the byte specified by the address (adr) +* is cached by the Data cache and the cacheline is modified (dirty), +* the entire contents of the cacheline are written to system memory. +* After the store completes, the cacheline is marked as unmodified +* (not dirty). +* +* @param adr: 32bit address of the data to be stored. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_DCacheStoreLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + Xil_L1DCacheStoreLine(adr); +#ifndef USE_AMP + Xil_L2CacheStoreLine(adr); +#endif + mtcpsr(currmask); +} + +/***************************************************************************/ +/** +* @brief Enable the instruction cache. +* +* @return None. +* +****************************************************************************/ +void Xil_ICacheEnable(void) +{ + Xil_L1ICacheEnable(); +#ifndef USE_AMP + Xil_L2CacheEnable(); +#endif +} + +/***************************************************************************/ +/** +* @brief Disable the instruction cache. +* +* @return None. +* +****************************************************************************/ +void Xil_ICacheDisable(void) +{ +#ifndef USE_AMP + Xil_L2CacheDisable(); +#endif + Xil_L1ICacheDisable(); +} + + +/****************************************************************************/ +/** +* @brief Invalidate the entire instruction cache. +* +* @return None. +* +****************************************************************************/ +void Xil_ICacheInvalidate(void) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidate(); +#endif + Xil_L1ICacheInvalidate(); + + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Invalidate an instruction cache line. If the instruction specified +* by the address is cached by the instruction cache, the cacheline +* containing that instruction is invalidated. +* +* @param adr: 32bit address of the instruction to be invalidated. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_ICacheInvalidateLine(u32 adr) +{ + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); +#ifndef USE_AMP + Xil_L2CacheInvalidateLine(adr); +#endif + Xil_L1ICacheInvalidateLine(adr); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Invalidate the instruction cache for the given address range. +* If the instructions specified by the address range are cached by +* the instrunction cache, the cachelines containing those +* instructions are invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +****************************************************************************/ +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INVLD_PA_OFFSET); + + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + while (LocalAddr < end) { +#ifndef USE_AMP + /* Invalidate L2 cache line */ + *L2CCOffset = LocalAddr; + Xil_L2CacheSync(); +#endif + + /* Invalidate L1 I-cache line */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_ic_line_mva_pou(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_IC_LINE_MVA_POU); + Reg = LocalAddr; } +#endif + LocalAddr += cacheline; + } + /* Wait for L1 I cache invalidation to complete */ + dsb(); + } + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Enable the level 1 Data cache. +* +* @return None. +* +****************************************************************************/ +void Xil_L1DCacheEnable(void) +{ + register u32 CtrlReg; + + /* enable caches only if they are disabled */ +#ifdef __GNUC__ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + if ((CtrlReg & (XREG_CP15_CONTROL_C_BIT)) != 0U) { + return; + } + + /* clean and invalidate the Data cache */ + Xil_L1DCacheInvalidate(); + + /* enable the Data cache */ + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/***************************************************************************/ +/** +* @brief Disable the level 1 Data cache. +* +* @return None. +* +****************************************************************************/ +void Xil_L1DCacheDisable(void) +{ + register u32 CtrlReg; + + /* clean and invalidate the Data cache */ + Xil_L1DCacheFlush(); + +#ifdef __GNUC__ + /* disable the Data cache */ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 1 Data cache. +* +* @return None. +* +* @note In Cortex A9, there is no cp instruction for invalidating +* the whole D-cache. This function invalidates each line by +* set/way. +* +****************************************************************************/ +void Xil_L1DCacheInvalidate(void) +{ + register u32 CsidReg, C7Reg; + u32 CacheSize, LineSize, NumWays; + u32 Way, WayIndex, Set, SetIndex, NumSet; + u32 currmask; + +#ifdef __GNUC__ + u32 stack_start,stack_end,stack_size; + register u32 CtrlReg; +#endif + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + +#ifdef __GNUC__ + stack_end = (u32)&_stack_end; + stack_start = (u32)&__undef_stack; + stack_size=stack_start-stack_end; + + /* Check for the cache status. If cache is enabled, then only + * flush stack memory to save return address. If cache is disabled, + * don't flush anything as it might result in flushing stale date into + * memory which is undesirable. + * */ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + if ((CtrlReg & (XREG_CP15_CONTROL_C_BIT)) != 0U) { + Xil_DCacheFlushRange(stack_end, stack_size); + } +#endif + +#ifdef __GNUC__ + CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_CACHE_SIZE_ID, CsidReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_CACHE_SIZE_ID); + CsidReg = Reg; } +#endif + /* Determine Cache Size */ + CacheSize = (CsidReg >> 13U) & 0x1FFU; + CacheSize +=1U; + CacheSize *=128U; /* to get number of bytes */ + + /* Number of Ways */ + NumWays = (CsidReg & 0x3ffU) >> 3U; + NumWays += 1U; + + /* Get the cacheline size, way size, index size from csidr */ + LineSize = (CsidReg & 0x07U) + 4U; + + NumSet = CacheSize/NumWays; + NumSet /= (0x00000001U << LineSize); + + Way = 0U; + Set = 0U; + + /* Invalidate all the cachelines */ + for (WayIndex =0U; WayIndex < NumWays; WayIndex++) { + for (SetIndex =0U; SetIndex < NumSet; SetIndex++) { + C7Reg = Way | Set; + + /* Invalidate by Set/Way */ +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_dc_line_sw(C7Reg); +#else + /*mtcp(XREG_CP15_INVAL_DC_LINE_SW, C7Reg), */ + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_DC_LINE_SW); + Reg = C7Reg; } +#endif + Set += (0x00000001U << LineSize); + } + Set=0U; + Way += 0x40000000U; + } + + /* Wait for L1 invalidate to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Invalidate a level 1 Data cache line. If the byte specified by the +* address (Addr) is cached by the Data cache, the cacheline +* containing that byte is invalidated. If the cacheline is modified +* (dirty), the modified contents are lost and are NOT written to +* system memory before the line is invalidated. +* +* @param adr: 32bit address of the data to be invalidated. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1DCacheInvalidateLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1FU))); + + /* Wait for L1 invalidate to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 1 Data cache for the given address range. +* If the bytes specified by the address range are cached by the Data +* cache, the cachelines containing those bytes are invalidated. If the +* cachelines are modified (dirty), the modified contents are lost and +* NOT written to the system memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +****************************************************************************/ +void Xil_L1DCacheInvalidateRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + while (LocalAddr < end) { + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_dc_line_mva_poc(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_DC_LINE_MVA_POC); + Reg = LocalAddr; } +#endif + LocalAddr += cacheline; + } + + /* Wait for L1 cache invalidation to complete */ + dsb(); + } + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the level 1 Data cache. +* +* @return None. +* +* @note In Cortex A9, there is no cp instruction for flushing +* the whole D-cache. Need to flush each line. +* +****************************************************************************/ +void Xil_L1DCacheFlush(void) +{ + register u32 CsidReg, C7Reg; + u32 CacheSize, LineSize, NumWays; + u32 Way; + u32 WayIndex, Set, SetIndex, NumSet; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + +#ifdef __GNUC__ + CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_CACHE_SIZE_ID, CsidReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_CACHE_SIZE_ID); + CsidReg = Reg; } +#endif + + /* Determine Cache Size */ + + CacheSize = (CsidReg >> 13U) & 0x1FFU; + CacheSize +=1U; + CacheSize *=128U; /* to get number of bytes */ + + /* Number of Ways */ + NumWays = (CsidReg & 0x3ffU) >> 3U; + NumWays += 1U; + + /* Get the cacheline size, way size, index size from csidr */ + LineSize = (CsidReg & 0x07U) + 4U; + + NumSet = CacheSize/NumWays; + NumSet /= (0x00000001U << LineSize); + + Way = 0U; + Set = 0U; + + /* Invalidate all the cachelines */ + for (WayIndex =0U; WayIndex < NumWays; WayIndex++) { + for (SetIndex =0U; SetIndex < NumSet; SetIndex++) { + C7Reg = Way | Set; + /* Flush by Set/Way */ + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_clean_inval_dc_line_sw(C7Reg); +#else + { volatile register u32 Reg + __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_SW); + Reg = C7Reg; } +#endif + Set += (0x00000001U << LineSize); + } + Set = 0U; + Way += 0x40000000U; + } + + /* Wait for L1 flush to complete */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush a level 1 Data cache line. If the byte specified by the +* address (adr) is cached by the Data cache, the cacheline containing +* that byte is invalidated. If the cacheline is modified (dirty), the +* entire contents of the cacheline are written to system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data to be flushed. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1DCacheFlushLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1FU))); + + /* Wait for L1 flush to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Flush the level 1 Data cache for the given address range. +* If the bytes specified by the address range are cached by the Data +* cache, the cacheline containing those bytes are invalidated. If the +* cachelines are modified (dirty), they are written to system memory +* before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be flushed. +* @param len: Length of the range to be flushed in bytes. +* +* @return None. +* +****************************************************************************/ +void Xil_L1DCacheFlushRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + while (LocalAddr < end) { + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_clean_inval_dc_line_mva_poc(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC); + Reg = LocalAddr; } +#endif + LocalAddr += cacheline; + } + + /* Wait for L1 cache clean and invalidation to complete */ + dsb(); + } + + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Store a level 1 Data cache line. If the byte specified by the +* address (adr) is cached by the Data cache and the cacheline is +* modified (dirty), the entire contents of the cacheline are written +* to system memory. After the store completes, the cacheline is +* marked as unmodified (not dirty). +* +* @param adr: Address to be stored. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1DCacheStoreLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U); + mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1FU))); + + /* Wait for L1 store to complete */ + dsb(); +} + + +/****************************************************************************/ +/** +* @brief Enable the level 1 instruction cache. +* +* @return None. +* +****************************************************************************/ +void Xil_L1ICacheEnable(void) +{ + register u32 CtrlReg; + + /* enable caches only if they are disabled */ +#ifdef __GNUC__ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + if ((CtrlReg & (XREG_CP15_CONTROL_I_BIT)) != 0U) { + return; + } + + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0U); + + /* enable the instruction cache */ + CtrlReg |= (XREG_CP15_CONTROL_I_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/****************************************************************************/ +/** +* @brief Disable level 1 the instruction cache. +* +* @return None. +* +****************************************************************************/ +void Xil_L1ICacheDisable(void) +{ + register u32 CtrlReg; + + dsb(); + + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0U); + + /* disable the instruction cache */ +#ifdef __GNUC__ + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, CtrlReg); +#else + { volatile register u32 Reg __asm(XREG_CP15_SYS_CONTROL); + CtrlReg = Reg; } +#endif + CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT); + + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); +} + +/****************************************************************************/ +/** +* @brief Invalidate the entire level 1 instruction cache. +* +* @return None. +* +****************************************************************************/ +void Xil_L1ICacheInvalidate(void) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); + /* invalidate the instruction cache */ + mtcp(XREG_CP15_INVAL_IC_POU, 0U); + + /* Wait for L1 invalidate to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate a level 1 instruction cache line. If the instruction +* specified by the address is cached by the instruction cache, the +* cacheline containing that instruction is invalidated. +* +* @param adr: 32bit address of the instruction to be invalidated. +* +* @return None. +* +* @note The bottom 5 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L1ICacheInvalidateLine(u32 adr) +{ + mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U); + mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1FU))); + + /* Wait for L1 invalidate to complete */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 1 instruction cache for the given address +* range. If the instrucions specified by the address range are cached +* by the instruction cache, the cacheline containing those bytes are +* invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +****************************************************************************/ +void Xil_L1ICacheInvalidateRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + while (LocalAddr < end) { + +#if defined (__GNUC__) || defined (__ICCARM__) + asm_cp15_inval_ic_line_mva_pou(LocalAddr); +#else + { volatile register u32 Reg + __asm(XREG_CP15_INVAL_IC_LINE_MVA_POU); + Reg = LocalAddr; } +#endif + LocalAddr += cacheline; + } + + /* Wait for L1 cache invalidation to complete */ + dsb(); + } + + mtcpsr(currmask); +} + +#ifndef USE_AMP +/****************************************************************************/ +/** +* @brief Enable the L2 cache. +* +* @return None. +* +****************************************************************************/ +void Xil_L2CacheEnable(void) +{ + register u32 L2CCReg; + + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + + /* only enable if L2CC is currently disabled */ + if ((L2CCReg & 0x01U) == 0U) { + /* set up the way size and latencies */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + + XPS_L2CC_AUX_CNTRL_OFFSET); + L2CCReg &= XPS_L2CC_AUX_REG_ZERO_MASK; + L2CCReg |= XPS_L2CC_AUX_REG_DEFAULT_MASK; + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_AUX_CNTRL_OFFSET, + L2CCReg); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_TAG_RAM_CNTRL_OFFSET, + XPS_L2CC_TAG_RAM_DEFAULT_MASK); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_DATA_RAM_CNTRL_OFFSET, + XPS_L2CC_DATA_RAM_DEFAULT_MASK); + + /* Clear the pending interrupts */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + + XPS_L2CC_ISR_OFFSET); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_IAR_OFFSET, L2CCReg); + + Xil_L2CacheInvalidate(); + /* Enable the L2CC */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + + XPS_L2CC_CNTRL_OFFSET); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET, + (L2CCReg | (0x01U))); + + Xil_L2CacheSync(); + /* synchronize the processor */ + dsb(); + + } +} + +/****************************************************************************/ +/** +* @brief Disable the L2 cache. +* +* @return None. +* +****************************************************************************/ +void Xil_L2CacheDisable(void) +{ + register u32 L2CCReg; + + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + + if((L2CCReg & 0x1U) != 0U) { + + /* Clean and Invalidate L2 Cache */ + Xil_L2CacheFlush(); + + /* Disable the L2CC */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET, + (L2CCReg & (~0x01U))); + /* Wait for the cache operations to complete */ + + dsb(); + } +} + +/*****************************************************************************/ +/** +* @brief Invalidate the entire level 2 cache. +* +* @return None. +* +****************************************************************************/ +void Xil_L2CacheInvalidate(void) +{ + #ifdef __GNUC__ + u32 stack_start,stack_end,stack_size; + register u32 L2CCReg; + stack_end = (u32)&_stack_end; + stack_start = (u32)&__undef_stack; + stack_size=stack_start-stack_end; + + /* Check for the cache status. If cache is enabled, then only + * flush stack memory to save return address. If cache is disabled, + * don't flush anything as it might result in flushing stale date into + * memory which is undesirable. + */ + L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CNTRL_OFFSET); + if ((L2CCReg & 0x01U) != 0U) { + /*Flush stack memory to save return address*/ + Xil_DCacheFlushRange(stack_end, stack_size); + } + + #endif + u32 ResultDCache; + /* Invalidate the caches */ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET, + 0x0000FFFFU); + ResultDCache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET) + & 0x0000FFFFU; + while(ResultDCache != (u32)0U) { + ResultDCache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_WAY_OFFSET) + & 0x0000FFFFU; + } + + /* Wait for the invalidate to complete */ + Xil_L2CacheSync(); + + /* synchronize the processor */ + dsb(); +} + +/*****************************************************************************/ +/** +* @brief Invalidate a level 2 cache line. If the byte specified by the +* address (adr) is cached by the Data cache, the cacheline containing +* that byte is invalidated. If the cacheline is modified (dirty), +* the modified contents are lost and are NOT written to system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data/instruction to be invalidated. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L2CacheInvalidateLine(u32 adr) +{ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_PA_OFFSET, (u32)adr); + /* synchronize the processor */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Invalidate the level 2 cache for the given address range. +* If the bytes specified by the address range are cached by the L2 +* cache, the cacheline containing those bytes are invalidated. If the +* cachelines are modified (dirty), the modified contents are lost and +* are NOT written to system memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be invalidated. +* @param len: Length of the range to be invalidated in bytes. +* +* @return None. +* +****************************************************************************/ +void Xil_L2CacheInvalidateRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INVLD_PA_OFFSET); + + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + while (LocalAddr < end) { + *L2CCOffset = LocalAddr; + Xil_L2CacheSync(); + LocalAddr += cacheline; + } + + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + } + + /* synchronize the processor */ + dsb(); + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Flush the entire level 2 cache. +* +* @return None. +* +****************************************************************************/ +void Xil_L2CacheFlush(void) +{ + u32 ResultL2Cache; + + /* Flush the caches */ + + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET, + 0x0000FFFFU); + ResultL2Cache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET) + & 0x0000FFFFU; + + while(ResultL2Cache != (u32)0U) { + ResultL2Cache = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET) + & 0x0000FFFFU; + } + + Xil_L2CacheSync(); + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + + /* synchronize the processor */ + dsb(); +} + +/****************************************************************************/ +/** +* @brief Flush a level 2 cache line. If the byte specified by the address +* (adr) is cached by the L2 cache, the cacheline containing that +* byte is invalidated. If the cacheline is modified (dirty), the +* entire contents of the cacheline are written to system memory +* before the line is invalidated. +* +* @param adr: 32bit address of the data/instruction to be flushed. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L2CacheFlushLine(u32 adr) +{ +#ifdef CONFIG_PL310_ERRATA_588369 + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_CLEAN_PA_OFFSET, adr); + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INVLD_PA_OFFSET, adr); +#else + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_INV_CLN_PA_OFFSET, adr); +#endif + Xil_L2CacheSync(); +} + +/****************************************************************************/ +/** +* @brief Flush the level 2 cache for the given address range. +* If the bytes specified by the address range are cached by the L2 +* cache, the cacheline containing those bytes are invalidated. If the +* cachelines are modified (dirty), they are written to the system +* memory before the lines are invalidated. +* +* @param adr: 32bit start address of the range to be flushed. +* @param len: Length of the range to be flushed in bytes. +* +* @return None. +* +****************************************************************************/ +void Xil_L2CacheFlushRange(u32 adr, u32 len) +{ + u32 LocalAddr = adr; + const u32 cacheline = 32U; + u32 end; + volatile u32 *L2CCOffset = (volatile u32 *)(XPS_L2CC_BASEADDR + + XPS_L2CC_CACHE_INV_CLN_PA_OFFSET); + + u32 currmask; + + currmask = mfcpsr(); + mtcpsr(currmask | IRQ_FIQ_MASK); + if (len != 0U) { + /* Back the starting address up to the start of a cache line + * perform cache operations until adr+len + */ + end = LocalAddr + len; + LocalAddr = LocalAddr & ~(cacheline - 1U); + + /* Disable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x3U); + + while (LocalAddr < end) { + *L2CCOffset = LocalAddr; + Xil_L2CacheSync(); + LocalAddr += cacheline; + } + + /* Enable Write-back and line fills */ + Xil_L2WriteDebugCtrl(0x0U); + } + mtcpsr(currmask); +} + +/****************************************************************************/ +/** +* @brief Store a level 2 cache line. If the byte specified by the address +* (adr) is cached by the L2 cache and the cacheline is modified +* (dirty), the entire contents of the cacheline are written to +* system memory. After the store completes, the cacheline is marked +* as unmodified (not dirty). +* +* @param adr: 32bit address of the data/instruction to be stored. +* +* @return None. +* +* @note The bottom 4 bits are set to 0, forced by architecture. +* +****************************************************************************/ +void Xil_L2CacheStoreLine(u32 adr) +{ + Xil_Out32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_CLEAN_PA_OFFSET, adr); + Xil_L2CacheSync(); +} +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache.h new file mode 100644 index 0000000..75cd6f6 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache.h @@ -0,0 +1,105 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_cache.h +* +* @addtogroup a9_cache_apis Cortex A9 Processor Cache Functions +* +* Cache functions provide access to cache related operations such as flush +* and invalidate for instruction and data caches. It gives option to perform +* the cache operations on a single cacheline, a range of memory and an entire +* cache. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/29/10 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb/dmb instructions in cache maintenance
+*		      APIs.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef XIL_CACHE_H +#define XIL_CACHE_H + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNUC__ + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#elif defined (__ICCARM__) + +#define asm_cp15_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_mva_poc(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param)); + +#define asm_cp15_inval_ic_line_mva_pou(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)); + +#define asm_cp15_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_INVAL_DC_LINE_SW :: "r" (param)); + +#define asm_cp15_clean_inval_dc_line_sw(param) __asm volatile ("mcr " \ + XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param)); + +#endif + +/** +*@endcond +*/ + +void Xil_DCacheEnable(void); +void Xil_DCacheDisable(void); +void Xil_DCacheInvalidate(void); +void Xil_DCacheInvalidateRange(INTPTR adr, u32 len); +void Xil_DCacheFlush(void); +void Xil_DCacheFlushRange(INTPTR adr, u32 len); + +void Xil_ICacheEnable(void); +void Xil_ICacheDisable(void); +void Xil_ICacheInvalidate(void); +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache_l.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache_l.h new file mode 100644 index 0000000..21c8ced --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache_l.h @@ -0,0 +1,75 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_cache_l.h +* +* Contains L1 and L2 specific functions for the ARM cache functionality +* used by xcache.c. This functionality is being made available here for +* more sophisticated users. +* +* @addtogroup a9_cache_apis +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  01/24/10 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XIL_CACHE_MACH_H +#define XIL_CACHE_MACH_H + +#include "xil_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes ******************************/ + +void Xil_DCacheInvalidateLine(u32 adr); +void Xil_DCacheFlushLine(u32 adr); +void Xil_DCacheStoreLine(u32 adr); +void Xil_ICacheInvalidateLine(u32 adr); + +void Xil_L1DCacheEnable(void); +void Xil_L1DCacheDisable(void); +void Xil_L1DCacheInvalidate(void); +void Xil_L1DCacheInvalidateLine(u32 adr); +void Xil_L1DCacheInvalidateRange(u32 adr, u32 len); +void Xil_L1DCacheFlush(void); +void Xil_L1DCacheFlushLine(u32 adr); +void Xil_L1DCacheFlushRange(u32 adr, u32 len); +void Xil_L1DCacheStoreLine(u32 adr); + +void Xil_L1ICacheEnable(void); +void Xil_L1ICacheDisable(void); +void Xil_L1ICacheInvalidate(void); +void Xil_L1ICacheInvalidateLine(u32 adr); +void Xil_L1ICacheInvalidateRange(u32 adr, u32 len); + +void Xil_L2CacheEnable(void); +void Xil_L2CacheDisable(void); +void Xil_L2CacheInvalidate(void); +void Xil_L2CacheInvalidateLine(u32 adr); +void Xil_L2CacheInvalidateRange(u32 adr, u32 len); +void Xil_L2CacheFlush(void); +void Xil_L2CacheFlushLine(u32 adr); +void Xil_L2CacheFlushRange(u32 adr, u32 len); +void Xil_L2CacheStoreLine(u32 adr); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_cache_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache_vxworks.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache_vxworks.h new file mode 100644 index 0000000..64079e7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_cache_vxworks.h @@ -0,0 +1,75 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_cache_vxworks.h +* +* Contains the cache related functions for VxWorks that is wrapped by +* xil_cache. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  12/11/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_CACHE_VXWORKS_H +#define XIL_CACHE_VXWORKS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "vxWorks.h" +#include "vxLib.h" +#include "sysLibExtra.h" +#include "cacheLib.h" + +#if (CPU_FAMILY==PPC) + +#define Xil_DCacheEnable() cacheEnable(DATA_CACHE) + +#define Xil_DCacheDisable() cacheDisable(DATA_CACHE) + +#define Xil_DCacheInvalidateRange(Addr, Len) \ + cacheInvalidate(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_DCacheFlushRange(Addr, Len) \ + cacheFlush(DATA_CACHE, (void *)(Addr), (Len)) + +#define Xil_ICacheEnable() cacheEnable(INSTRUCTION_CACHE) + +#define Xil_ICacheDisable() cacheDisable(INSTRUCTION_CACHE) + +#define Xil_ICacheInvalidateRange(Addr, Len) \ + cacheInvalidate(INSTRUCTION_CACHE, (void *)(Addr), (Len)) + + +#else +#error "Unknown processor / architecture. Must be PPC for VxWorks." +#endif + +#ifdef __cplusplus +} +#endif + +#endif +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_errata.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_errata.h new file mode 100644 index 0000000..5923f44 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_errata.h @@ -0,0 +1,101 @@ +/****************************************************************************** +* Copyright (c) 2013 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_errata.h +* +* @addtogroup a9_errata Cortex A9 Processor and pl310 Errata Support +* @{ +* Various ARM errata are handled in the standalone BSP. The implementation for +* errata handling follows ARM guidelines and is based on the open source Linux +* support for these errata. +* +* @note The errata handling is enabled by default. To disable handling of all the +* errata globally, un-define the macro ENABLE_ARM_ERRATA in xil_errata.h. To +* disable errata on a per-erratum basis, un-define relevant macros in +* xil_errata.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a srt  04/18/13 First release
+* 6.6   mus  12/07/17 Removed errata 753970, It fixes CR#989132
+* 7.7   asa  01/06/22 Removed errata 742230 and 743622. These are
+*                     already fixed in Cortex-A9 r3p0, the revision
+*                     that is being used in Zynq platforms.
+* 
+* +******************************************************************************/ +#ifndef XIL_ERRATA_H +#define XIL_ERRATA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + *@cond nocomments + */ +/** + * @name errata_definitions + * + * The errata conditions handled in the standalone BSP are listed below + * @{ + */ + +#define ENABLE_ARM_ERRATA 1 + +/** + *@endcond + */ + +#ifdef ENABLE_ARM_ERRATA + +/** + * Errata No: 775420 + * Description: A data cache maintenance operation which aborts, + * might lead to deadlock + */ +#define CONFIG_ARM_ERRATA_775420 1 + +/** + * Errata No: 794073 + * Description: Speculative instruction fetches with MMU disabled + * might not comply with architectural requirements + */ +#define CONFIG_ARM_ERRATA_794073 1 + + +/** PL310 L2 Cache Errata */ + +/** + * Errata No: 588369 + * Description: Clean & Invalidate maintenance operations do not + * invalidate clean lines + */ +#define CONFIG_PL310_ERRATA_588369 1 + +/** + * Errata No: 727915 + * Description: Background Clean and Invalidate by Way operation + * can cause data corruption + */ +#define CONFIG_PL310_ERRATA_727915 1 + +/*@}*/ +#endif /* ENABLE_ARM_ERRATA */ + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_ERRATA_H */ +/** +* @} End of "addtogroup a9_errata". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_exception.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_exception.c new file mode 100644 index 0000000..4388d52 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_exception.c @@ -0,0 +1,861 @@ +/****************************************************************************** +* Copyright (c) 2015 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xil_exception.c +* +* This file contains low-level driver functions for the Cortex A53,A9,R5 exception +* Handler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.2	pkp  	 28/05/15 First release
+* 6.0   mus      27/07/16 Consolidated exceptions for a53,a9 and r5
+*                         processors and added Xil_UndefinedExceptionHandler
+*                         for a53 32 bit and r5 as well.
+* 6.4   mus      08/06/17 Updated debug prints to replace %x with the %lx, to
+*                         fix the warnings.
+* 6.7   mna      26/04/18 Add an API to obtain a corresponding
+*                         Xil_ExceptionHandler entry from XExc_VectorTable.
+* 6.7  asa       18/05/18 Fix bugs in the API Xil_GetExceptionRegisterHandler.
+* 7.0  mus       07/03/19 Tweak Xil_ExceptionRegisterHandler and
+*                         Xil_GetExceptionRegisterHandler to support legacy
+*                         examples for Cortexa72 EL3 exception level.
+* 7.3  mus       07/27/20 Updated Xil_ExceptionRegisterHandler and
+*                         Xil_GetExceptionRegisterHandler to ignore
+*                         Exception_id, only if its pointing to IRQ.
+*                         It fixes CR#1069524
+* 8.0  mus       02/24/22 Updated Xil_ExceptionRegisterHandler and
+*                         Xil_GetExceptionRegisterHandler to support legacy
+*                         driver examples for CortexR52. This is needed, as
+*                         by default scugic driver configures interrupts as
+*                         group0, and CortexR52 GIC triggers FIQ for group0
+*                         interrupts.
+* 8.0  sk	 03/02/22 Move XExc_VectorTableEntry structure to header
+* 			  file to fix misra_c_2012_rule_5_6 violation.
+* 8.1  asa       02/12/23 Updated data abort and prefetch abort fault
+*                         status reporting for ARMv7.
+*						  Updated Sync and SError fault status reporting
+*						  for ARMv8.
+*
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_exception.h" +#include "xpseudo_asm.h" +#include "xdebug.h" +#include "bspconfig.h" +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ +#ifdef DEBUG +#if defined (__aarch64__) +static u32 NotifyFaultStatusDetails(u32 Fault_Type, u64 FaultStatus); +static void DecodeSyncAbortWithIss(u32 Type, u64 IssVal); +static void DecodeSErrorWithIss(u64 IssVal); +#else +static u32 NotifyFaultStatusDetails(u32 Fault_Type, u32 FaultStatus); +#endif +#endif +/************************** Function Prototypes *****************************/ +static void Xil_ExceptionNullHandler(void *Data); +#if defined (__aarch64__) +static void Xil_SyncErrorHandler(void *CallBackRef); +static void Xil_SErrorHandler(void *CallBackRef); +#else +static void Xil_DataAbortHandler(void *CallBackRef); +static void Xil_PrefetchAbortHandler(void *CallBackRef); +static void Xil_UndefinedExceptionHandler(void *CallBackRef); +#endif +/************************** Variable Definitions *****************************/ +/* + * Exception vector table to store handlers for each exception vector. + */ +#if defined (__aarch64__) +XExc_VectorTableEntry XExc_VectorTable[XIL_EXCEPTION_ID_LAST + 1] = +{ + {Xil_ExceptionNullHandler, NULL}, + {Xil_SyncErrorHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_SErrorHandler, NULL}, + +}; +#else +XExc_VectorTableEntry XExc_VectorTable[XIL_EXCEPTION_ID_LAST + 1] = +{ + {Xil_ExceptionNullHandler, NULL}, + {Xil_UndefinedExceptionHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_PrefetchAbortHandler, NULL}, + {Xil_DataAbortHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, + {Xil_ExceptionNullHandler, NULL}, +}; +#endif /* #if defined (__aarch64__) */ +#if !defined (__aarch64__) +u32 DataAbortAddr; /* Address of instruction causing data abort */ +u32 PrefetchAbortAddr; /* Address of instruction causing prefetch abort */ +u32 UndefinedExceptionAddr; /* Address of instruction causing Undefined + exception */ +#endif + +/*****************************************************************************/ + +/****************************************************************************/ +/** +* +* This function is a stub Handler that is the default Handler that gets called +* if the application has not setup a Handler for a specific exception. The +* function interface has to match the interface specified for a Handler even +* though none of the arguments are used. +* +* @param Data is unused by this function. +* +* @return None. +* +*****************************************************************************/ +static void Xil_ExceptionNullHandler(void *Data) +{ + (void) Data; +DieLoop: goto DieLoop; +} + +/****************************************************************************/ +/** +* @brief The function is a common API used to initialize exception handlers +* across all supported arm processors. For ARM Cortex-A53, Cortex-R5, +* and Cortex-A9, the exception handlers are being initialized +* statically and this function does not do anything. +* However, it is still present to take care of backward compatibility +* issues (in earlier versions of BSPs, this API was being used to +* initialize exception handlers). +* +* @return None. +* +*****************************************************************************/ +void Xil_ExceptionInit(void) +{ + return; +} + +/*****************************************************************************/ +/** +* @brief Register a handler for a specific exception. This handler is being +* called when the processor encounters the specified exception. +* +* @param Exception_id contains the ID of the exception source and should +* be in the range of 0 to XIL_EXCEPTION_ID_LAST. +* See xil_exception.h for further information. +* @param Handler to the Handler for that exception. +* @param Data is a reference to Data that will be passed to the +* Handler when it gets called. +* +* @return None. +* +****************************************************************************/ +void Xil_ExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler Handler, + void *Data) +{ +#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52) + if ( XIL_EXCEPTION_ID_IRQ_INT == Exception_id ) + { + /* + * Cortexa72 processor in versal is coupled with GIC-500, and + * GIC-500 supports only FIQ at EL3. Hence, tweaking this API + * to act on IRQ, if Exception_id is pointing to IRQ + */ + Exception_id = XIL_EXCEPTION_ID_FIQ_INT; + } +#endif + XExc_VectorTable[Exception_id].Handler = Handler; + XExc_VectorTable[Exception_id].Data = Data; +} + +/*****************************************************************************/ +/** +* @brief Get a handler for a specific exception. This handler is being +* called when the processor encounters the specified exception. +* +* @param Exception_id contains the ID of the exception source and should +* be in the range of 0 to XIL_EXCEPTION_ID_LAST. +* See xil_exception.h for further information. +* @param Handler to the Handler for that exception. +* @param Data is a reference to Data that will be passed to the +* Handler when it gets called. +* +* @return None. +* +****************************************************************************/ +void Xil_GetExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler *Handler, + void **Data) +{ +#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52) + if ( XIL_EXCEPTION_ID_IRQ_INT == Exception_id ) + { + /* + * Cortexa72 processor in versal is coupled with GIC-500, and + * GIC-500 supports only FIQ at EL3. Hence, tweaking this API + * to act on IRQ, if Exception_id is pointing to IRQ + */ + + Exception_id = XIL_EXCEPTION_ID_FIQ_INT; + } +#endif + + *Handler = XExc_VectorTable[Exception_id].Handler; + *Data = XExc_VectorTable[Exception_id].Data; +} + +/*****************************************************************************/ +/** +* +* @brief Removes the Handler for a specific exception Id. The stub Handler +* is then registered for this exception Id. +* +* @param Exception_id contains the ID of the exception source and should +* be in the range of 0 to XIL_EXCEPTION_ID_LAST. +* See xil_exception.h for further information. +* +* @return None. +* +****************************************************************************/ +void Xil_ExceptionRemoveHandler(u32 Exception_id) +{ + Xil_ExceptionRegisterHandler(Exception_id, + Xil_ExceptionNullHandler, + NULL); +} + +#if defined (__aarch64__) +/*****************************************************************************/ +/** +* +* Default Synchronous abort handler which prints a debug message on console if +* Debug flag is enabled +* +* @return None. +* +****************************************************************************/ + +static void Xil_SyncErrorHandler(void *CallBackRef){ + (void) CallBackRef; + +#ifdef __GNUC__ +#ifdef DEBUG + volatile u64 EsrVal; + volatile u64 ElrVal; + volatile u64 FarVal; + u32 Far_Status; +#if (EL3 == 1) + EsrVal = mfesrel3(); + ElrVal = mfelrel3(); +#else + EsrVal = mfesrel1(); + ElrVal = mfelrel1(); +#endif + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "-------------------------------------------------------------\n"); + Far_Status = NotifyFaultStatusDetails(ARMV8_SYNC_ERROR, EsrVal); + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "-------------------------------------------------------------\n"); + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Address of Instruction causing Sync error is: 0x%lx\n", ElrVal); + if (Far_Status) { +#if (EL3 == 1) + FarVal = mffarel3(); +#else + FarVal = mffarel1(); +#endif + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Address of Memory whose access caused the Sync Error is: 0x%lx\n", + FarVal); + } + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "-------------------------------------------------------------\n"); +#endif +#else + xdbg_printf(XDBG_DEBUG_ERROR, "Synchronous Error \n"); +#endif + while(1) { + ; + } +} + +/*****************************************************************************/ +/** +* +* Default SError abort handler which prints a debug message on console if +* Debug flag is enabled +* +* @return None. +* +****************************************************************************/ +static void Xil_SErrorHandler(void *CallBackRef){ + (void) CallBackRef; + +#ifdef __GNUC__ +#ifdef DEBUG + volatile u64 EsrVal; +#if (EL3 == 1) + EsrVal = mfesrel3(); +#else + EsrVal = mfesrel1(); +#endif + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "-------------------------------------------------------------\n"); + (void)NotifyFaultStatusDetails(ARMV8_SERROR, EsrVal); + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "-------------------------------------------------------------\n"); +#endif +#else + xdbg_printf(XDBG_DEBUG_ERROR, "Asynchronous SError \n"); +#endif + + while(1) { + ; + } +} + +#if defined (__aarch64__) +#ifdef DEBUG +static u32 NotifyFaultStatusDetails(u32 Fault_Type, u64 EsrVal) +{ + u32 Far_Status = 0x0; + u64 EcVal = ARMV8_EXTRACT_ESR_EC(EsrVal); + u64 IssVal = ARMV8_EXTRACT_ESR_ISS(EsrVal); + + if (Fault_Type == ARMV8_SYNC_ERROR) { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Sync Error with ESR = 0x%lx, EC = 0x%lx, ISS = 0x%lx \n", + EsrVal, EcVal, IssVal); + + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "-------------------------------------------------------------\n"); + + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Exception Type based on Exception Class (EC val) : "); + switch (EcVal) { + case ARMV8_ESR_EC_UNKNOWN_ERR: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Unknown Error\n"); + break; + case ARMV8_ESR_EC_FP_ASIMD: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Access to ASIMD or floating point functionality based " + "on CPACR_EL1 FPEN configuration\n"); + Far_Status = ARMV8_FAR_VALUE_VALID; + break; + case ARMV8_ESR_EC_DATA_ABORT_LOWER: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Data Abort From a Lower " + "Exception Level\n"); + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Exception Details based on Instruction Specific Syndrome " + "(ISS val) : "); + DecodeSyncAbortWithIss(ARMV8_ESR_EC_DATA_ABORT, IssVal); + Far_Status = ARMV8_FAR_VALUE_VALID; + break; + case ARMV8_ESR_EC_DATA_ABORT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Data Abort \n"); + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Exception Details based on Instruction Specific Syndrome " + "(ISS val) : "); + DecodeSyncAbortWithIss(ARMV8_ESR_EC_DATA_ABORT, IssVal); + Far_Status = ARMV8_FAR_VALUE_VALID; + break; + case ARMV8_ESR_EC_INS_ABORT_LOWER: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Instruction Abort Taken From a Lower Exception Level\n"); + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Exception Details based on Instruction Specific Syndrome " + "(ISS val) : "); + DecodeSyncAbortWithIss(ARMV8_ESR_EC_INS_ABORT, IssVal); + Far_Status = ARMV8_FAR_VALUE_VALID; + break; + case ARMV8_ESR_EC_INS_ABORT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Instruction Abort\n"); + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Exception Details based on Instruction Specific Syndrome " + "(ISS val) : "); + DecodeSyncAbortWithIss(ARMV8_ESR_EC_INS_ABORT, IssVal); + Far_Status = ARMV8_FAR_VALUE_VALID; + break; + case ARMV8_ESR_EC_PC_ALIGNMENT_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "PC Alignment Fault\n"); + Far_Status = ARMV8_FAR_VALUE_VALID; + break; + case ARMV8_ESR_EC_SP_ALIGNMENT_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "SP Alignment Fault\n"); + break; + case ARMV8_ESR_ILL_EXECUTION_STATE: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Illegal Execution State\n"); + break; + default: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Other error\n"); + break; + } + } else { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Asynchronous SError with ESR = 0x%lx, EC = 0x%lx, ISS = 0x%lx \n", + EsrVal, EcVal, IssVal); + + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "-------------------------------------------------------------\n"); + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Exception Details (based on Instruction Specific Syndrome " + "(ISS val) : "); + + DecodeSErrorWithIss(IssVal); + } + return Far_Status; +} + +static void DecodeSyncAbortWithIss(u32 Type, u64 IssVal) +{ + u64 FscVal; + + FscVal = IssVal & ARMV8_ESR_ISS_FSC; + switch (FscVal) { + case ARMV8_LEVEL_0_ADDR_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Address Size fault at Level 0 translation \n"); + break; + case ARMV8_LEVEL_1_ADDR_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Address Size fault at Level 1 translation \n"); + break; + case ARMV8_LEVEL_2_ADDR_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Address Size fault at Level 2 translation \n"); + break; + case ARMV8_LEVEL_3_ADDR_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Address Size fault at Level 3 translation \n"); + break; + case ARMV8_LEVEL_0_TRANS_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Translation fault at Level 0 translation \n"); + break; + case ARMV8_LEVEL_1_TRANS_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Translation fault at Level 1 translation \n"); + break; + case ARMV8_LEVEL_2_TRANS_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Translation fault at Level 2 translation \n"); + break; + case ARMV8_LEVEL_3_TRANS_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Translation fault at Level 3 translation \n"); + break; + case ARMV8_LEVEL_0_ACCS_FLAG_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Access Flag Fault at Level 0 translation \n"); + break; + case ARMV8_LEVEL_1_ACCS_FLAG_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Access Flag Fault at Level 1 translation \n"); + break; + case ARMV8_LEVEL_2_ACCS_FLAG_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Access Flag Fault at Level 2 translation \n"); + break; + case ARMV8_LEVEL_3_ACCS_FLAG_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Access Flag Fault at Level 3 translation \n"); + break; + case ARMV8_LEVEL_0_PERMISSION_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Permission Fault at Level 0 translation \n"); + break; + case ARMV8_LEVEL_1_PERMISSION_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Permission Fault at Level 1 translation \n"); + break; + case ARMV8_LEVEL_2_PERMISSION_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Permission Fault at Level 2 translation \n"); + break; + case ARMV8_LEVEL_3_PERMISSION_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Permission Fault at Level 3 translation \n"); + break; + + case ARMV8_SYNC_EXT_ABORT_NOT_ON_TTW: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous External Abort, not on translation table walk or " + "hw update of translation table \n"); + break; + case ARMV8_LEVEL_0_SYNC_EXT_ABORT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous External Abort at Level 0 translation on " + "translation table walk or hw update of translation table \n"); + break; + case ARMV8_LEVEL_1_SYNC_EXT_ABORT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous External Abort at Level 1 translation on " + "translation table walk or hw update of translation table \n"); + break; + case ARMV8_LEVEL_2_SYNC_EXT_ABORT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous External Abort at Level 2 translation on " + "translation table walk or hw update of translation table \n"); + break; + case ARMV8_LEVEL_3_SYNC_EXT_ABORT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous External Abort at Level 3 translation on " + "translation table walk or hw update of translation table \n"); + break; + case ARMV8_SYNC_PAR_OR_ECC_ERROR_NOT_ON_TTW: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous Parity or ECC error for memory access, " + "not on translation table walk \n"); + break; + case ARMV8_LEVEL_0_SYNC_PAR_OR_ECC_ERROR: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous Parity or ECC error for memory access, " + "for level 0 translation \n"); + break; + case ARMV8_LEVEL_1_SYNC_PAR_OR_ECC_ERROR: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous Parity or ECC error for memory access, " + "for level 1 translation \n"); + break; + case ARMV8_LEVEL_2_SYNC_PAR_OR_ECC_ERROR: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous Parity or ECC error for memory access, " + "for level 2 translation \n"); + break; + case ARMV8_LEVEL_3_SYNC_PAR_OR_ECC_ERROR: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous Parity or ECC error for memory access, " + "for level 3 translation \n"); + break; + case ARMV8_ALIGNMENT_FAULT: + if (Type == ARMV8_ESR_EC_DATA_ABORT) { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Alignment Fault \n"); + } else { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Unknown fault \n"); + } + break; + case ARMV8_TLB_CONFLICT_ABORT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "TLB Conflict Abort \n"); + break; + default: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Unknown fault \n"); + } + + if (Type == ARMV8_ESR_EC_DATA_ABORT) { + if (IssVal & ARMV8_ESR_ISS_WNR_MASK) { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Data abort caused by instruction writing to a memory location.\n "); + } else { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Data abort caused by instruction reading from a memory location.\n"); + } + if (IssVal & ARMV8_ESR_ISS_CM_MASK) { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Data abort caused by a cache maintenance instruction \n"); + } + } +} + +static void DecodeSErrorWithIss(u64 IssVal) +{ + u64 FscVal; + u64 MaskVal; + + FscVal = IssVal & ARMV8_ESR_ISS_FSC; + if (FscVal == ARMV8_ASYNC_SEEROR_INTERRUPT) { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "SError caused by Asynchronous Serror Interrupt \n "); + + MaskVal = IssVal & ARMV8_ESR_ISS_AET_MASK; + switch (MaskVal) { + case ARMV8_ESR_ISS_AET_UC: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Uncontainable Error State \n "); + break; + case ARMV8_ESR_ISS_AET_UEU: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Unrecoverable Error State \n "); + break; + case ARMV8_ESR_ISS_AET_UEO: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Restartable Error State \n "); + break; + case ARMV8_ESR_ISS_AET_UER: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Recoverable Error State \n "); + break; + case ARMV8_ESR_ISS_AET_CE: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Corrected Error State \n "); + break; + default: + break; + + } + + } else { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "SError caused by uncategorized error \n "); + } +} + + +#endif /* #ifdef DEBUG */ +#endif /* #if defined (__aarch64__) */ + +#else /* #if defined (__aarch64__) */ +/*****************************************************************************/ +/** +* +* Default Data abort handler which prints data fault status register through +* which information about data fault can be acquired +* +* @return None. +* +****************************************************************************/ + +static void Xil_DataAbortHandler(void *CallBackRef){ + (void) CallBackRef; +#ifdef DEBUG + u32 FaultStatus; +#ifdef __GNUC__ + u32 DataAbortMemAddr; + u32 DfarStatus; +#endif + +#ifdef __GNUC__ + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "-------------------------------------------------------------\n"); + FaultStatus = mfcp(XREG_CP15_DATA_FAULT_STATUS); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_DATA_FAULT_STATUS,FaultStatus); +#else + { volatile register u32 Reg __asm(XREG_CP15_DATA_FAULT_STATUS); + FaultStatus = Reg; } +#endif /* #ifdef __GNUC__ */ + +#ifdef __GNUC__ + DfarStatus = NotifyFaultStatusDetails(DATA_ABORT, FaultStatus); + if (DfarStatus) { + DataAbortMemAddr = mfcp(XREG_CP15_DATA_FAULT_ADDRESS); + } + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Address of Instruction causing data abort is: 0x%lx\n", + DataAbortAddr); + if (DfarStatus) { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Address of Memory whose access caused the data abort is: 0x%lx\n", + DataAbortMemAddr); + } + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "-------------------------------------------------------------\n"); +#else + xdbg_printf(XDBG_DEBUG_GENERAL, "Data abort with Data Fault Status Register %lx\n",FaultStatus); + xdbg_printf(XDBG_DEBUG_GENERAL, "Address of Instruction causing Data abort %lx\n",DataAbortAddr); +#endif +#endif /* #ifdef DEBUG */ + while(1) { + ; + } +} + +/*****************************************************************************/ +/** +* +* Default Prefetch abort handler which prints prefetch fault status register through +* which information about instruction prefetch fault can be acquired +* +* @return None. +* +****************************************************************************/ +static void Xil_PrefetchAbortHandler(void *CallBackRef){ + (void) CallBackRef; +#ifdef DEBUG + u32 FaultStatus; +#ifdef __GNUC__ + u32 IfarStatus; +#endif + +#ifdef __GNUC__ + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "-------------------------------------------------------------\n"); + FaultStatus = mfcp(XREG_CP15_INST_FAULT_STATUS); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_INST_FAULT_STATUS,FaultStatus); +#else + { volatile register u32 Reg __asm(XREG_CP15_INST_FAULT_STATUS); + FaultStatus = Reg; } +#endif /* #ifdef __GNUC__ */ + +#ifdef __GNUC__ + IfarStatus = NotifyFaultStatusDetails(INS_PREFETCH_ABORT, FaultStatus); + if (IfarStatus) { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Address of Instruction Causing Prefetch Abort is: 0x%lx\n", + PrefetchAbortAddr); + } + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "-------------------------------------------------------------\n"); +#else + xdbg_printf(XDBG_DEBUG_GENERAL, "Prefetch abort with Instruction Fault Status Register %lx\n",FaultStatus); + xdbg_printf(XDBG_DEBUG_GENERAL, "Address of Instruction causing Prefetch abort %lx\n",PrefetchAbortAddr); +#endif +#endif /* #ifdef DEBUG */ + while(1) { + ; + } +} + +/*****************************************************************************/ +/** +* +* Default undefined exception handler which prints address of the undefined +* instruction if debug prints are enabled +* +* @return None. +* +****************************************************************************/ +static void Xil_UndefinedExceptionHandler(void *CallBackRef){ + (void) CallBackRef; +#ifdef DEBUG + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Address of the undefined instruction 0x%lx\n", + UndefinedExceptionAddr); +#endif + while(1) { + ; + } +} + +#ifdef DEBUG +static u32 NotifyFaultStatusDetails(u32 Fault_Type, u32 FaultStatus) +{ + u32 Far_Status = 0x0; + + if (Fault_Type == DATA_ABORT) { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Data Abort with Fault Status Register (DFSR) = 0x%lx\n", + FaultStatus); + } else { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Instruction Prefetch Abort with Fault Status Register (IFSR) = 0x%lx\n", + FaultStatus); + } + + /* Extract bit 10 and bits 3:0 to form the 5 bit error identifier */ + + FaultStatus = EXTRACT_BITS_10_AND_3_TO_0(FaultStatus); + + switch (FaultStatus) { +#if defined(ARMR5) + case ARMV7_BACKGROUND_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Background Fault\n"); + Far_Status = ARMV7_DFAR_VALUE_VALID; + break; +#endif + case ARMV7_ALIGNMENT_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Alignment Fault\n"); + Far_Status = ARMV7_DFAR_VALUE_VALID; + break; + case ARMV7_DEBUG_EVENT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Debug Event\n"); + break; +#if !defined(ARMR5) + case ARMV7_ACCESS_FLAG_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Debug Event\n"); + Far_Status = ARMV7_DFAR_VALUE_VALID; + break; + case ARMV7_ICACHE_MAINTENANCE_FAULT: + if (Fault_Type == DATA_ABORT) { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Fault on Instruction Cache Maintenance\n"); + Far_Status = ARMV7_DFAR_VALUE_VALID; + } + break; + case ARMV7_TRANSLATION_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Translation Fault\n"); + break; + case ARMV7_DOMAIN_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Domain Fault\n"); + break; + case ARMV7_SYNC_ABORT_TRANSTAB_WALK: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous External Abort on Translation Table Walk\n"); + Far_Status = ARMV7_DFAR_VALUE_VALID; + break; +#endif + case ARMV7_PERMISSION_FAULT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Permission Fault\n"); + Far_Status = ARMV7_DFAR_VALUE_VALID; + break; +#if !defined(ARMR5) + case ARMV7_TLB_CONFLICT_ABORT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "TLB Conflict Abort\n"); + Far_Status = ARMV7_DFAR_VALUE_VALID; + break; +#endif + case ARMV7_ASYNC_EXT_ABORT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Asynchronous External Abort\n"); + break; + case ARMV7_SYNC_EXT_ABORT: + xdbg_exception_printf(XDBG_DEBUG_ERROR, "Synchronous External Abort\n"); + Far_Status = ARMV7_DFAR_VALUE_VALID; + break; + case ARMV7_MEM_ACS_SYNC_PAR_ERR: + if (Fault_Type == DATA_ABORT) { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous Parity Error on Memory Access\n"); + Far_Status = ARMV7_DFAR_VALUE_VALID; + } + break; + case ARMV7_MEM_ACS_ASYNC_PAR_ERR: + if (Fault_Type == DATA_ABORT) { + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Asynchronous Parity Error on Memory Access\n"); + } + break; +#if !defined(ARMR5) + case ARMV7_SYNCPAR_ERR_TRANSTAB_WALK: + xdbg_exception_printf(XDBG_DEBUG_ERROR, + "Synchronous Parity Error on Translation Table Walk\n"); + Far_Status = ARMV7_DFAR_VALUE_VALID; + break; +#endif + default: + break; + } + + return Far_Status; +} +#endif /* #ifdef DEBUG */ +#endif /* #if defined (__aarch64__) */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_exception.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_exception.h new file mode 100644 index 0000000..3a5bb29 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_exception.h @@ -0,0 +1,530 @@ +/****************************************************************************** +* Copyright (c) 2015 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_exception.h +* +* This header file contains ARM Cortex A53,A9,R5 specific exception related APIs. +* For exception related functions that can be used across all Xilinx supported +* processors, please use xil_exception.h. +* +* @addtogroup arm_exception_apis ARM Processor Exception Handling +* @{ +* ARM processors specific exception related APIs for cortex A53,A9 and R5 can +* utilized for enabling/disabling IRQ, registering/removing handler for +* exceptions or initializing exception vector table with null handler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.2	pkp  	 28/05/15 First release
+* 6.0   mus      27/07/16 Consolidated file for a53,a9 and r5 processors
+* 6.7   mna      26/04/18 Add API Xil_GetExceptionRegisterHandler.
+* 6.7   asa      18/05/18 Update signature of API Xil_GetExceptionRegisterHandler.
+* 7.0   mus      01/03/19 Tweak Xil_ExceptionEnableMask and
+*                         Xil_ExceptionDisableMask macros to support legacy
+*                         examples for Cortexa72 EL3 exception level.
+* 7.3   mus      04/15/20 Added Xil_EnableNestedInterrupts and
+*                         Xil_DisableNestedInterrupts macros for ARMv8.
+*                         For Cortexa72, these macro's would not be supported
+*                         at EL3, as Cortexa72 is using GIC-500(GICv3),  which
+*                         triggeres only FIQ at EL3. Fix for CR#1062506
+* 7.6   mus      09/17/21 Updated flag checking to fix warning reported with
+*                         -Wundef compiler option CR#1110261
+* 7.7   mus      01/31/22 Few of the #defines in xil_exception.h in are treated
+*                         in different way based on "versal" flag. In existing
+*                         flow, this flag is defined only in xparameters.h and
+*                         BSP compiler flags, it is not defined in application
+*                         compiler flags. So, including xil_exception.h in
+*                         application source file, without including
+*                         xparameters.h results  in incorrect behavior.
+*                         Including xparameters.h in xil_exception.h to avoid
+*                         such issues. It fixes CR#1120498.
+* 8.0  mus       02/24/22 Updated few macros to support legacy driver examples
+*                         for CortexR52. This is needed, as by default scugic
+*                         driver configures interrupts as group0 and CortexR52
+*                         GIC triggers FIQ for group0 interrupts.
+* 8.0  sk	 03/02/22 Define XExc_VectorTableEntry structure to fix
+* 			  misra_c_2012_rule_5_6 violation.
+* 8.0  sk	 03/02/22 Add XExc_VectorTable as extern to fix misra_c_2012_
+* 			  rule_8_4 violation.
+* 8.1  asa       02/12/23 Updated data abort and prefetch abort fault
+*                         status reporting for ARMv7.
+*						  Updated Sync and SError fault status reporting
+*						  for ARMv8.
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_EXCEPTION_H /* prevent circular inclusions */ +#define XIL_EXCEPTION_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xpseudo_asm.h" +#include "bspconfig.h" +#include "xparameters.h" +#include "xdebug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions ****************************/ + +#define XIL_EXCEPTION_FIQ XREG_CPSR_FIQ_ENABLE +#define XIL_EXCEPTION_IRQ XREG_CPSR_IRQ_ENABLE +#define XIL_EXCEPTION_ALL (XREG_CPSR_FIQ_ENABLE | XREG_CPSR_IRQ_ENABLE) + +#define XIL_EXCEPTION_ID_FIRST 0U +#if defined (__aarch64__) +#define XIL_EXCEPTION_ID_SYNC_INT 1U +#define XIL_EXCEPTION_ID_IRQ_INT 2U +#define XIL_EXCEPTION_ID_FIQ_INT 3U +#define XIL_EXCEPTION_ID_SERROR_ABORT_INT 4U +#define XIL_EXCEPTION_ID_LAST 5U +#else +#define XIL_EXCEPTION_ID_RESET 0U +#define XIL_EXCEPTION_ID_UNDEFINED_INT 1U +#define XIL_EXCEPTION_ID_SWI_INT 2U +#define XIL_EXCEPTION_ID_PREFETCH_ABORT_INT 3U +#define XIL_EXCEPTION_ID_DATA_ABORT_INT 4U +#define XIL_EXCEPTION_ID_IRQ_INT 5U +#define XIL_EXCEPTION_ID_FIQ_INT 6U +#define XIL_EXCEPTION_ID_LAST 6U +#endif + +#ifdef DEBUG + +#if defined (__aarch64__) +#define ARMV8_SYNC_ERROR 0x01U +#define ARMV8_SERROR 0x02U + +#define ARMV8_FAR_VALUE_VALID 0x01U + +#define ARMV8_ESR_EC_SHIFT 26U +#define ARMV8_ESR_EC_MASK ((0x3FU) << ARMV8_ESR_EC_SHIFT) +#define ARMV8_EXTRACT_ESR_EC(Val) \ + (((Val) & ARMV8_ESR_EC_MASK) >> ARMV8_ESR_EC_SHIFT) + +#define ARMV8_ESR_IL_SHIFT (25U) +#define ARMV8_ESR_IL_MASK ((1U) << ARMV8_ESR_IL_SHIFT) +#define ARMV8_EXTRACT_ESR_IL(Val) \ + (((Val) & ARMV8_ESR_IL_MASK) >> ARMV8_ESR_IL_SHIFT) + +#define ARMV8_ESR_ISS_MASK (ARMV8_ESR_IL_MASK - 1U) +#define ARMV8_EXTRACT_ESR_ISS(Val) ((Val) & ARMV8_ESR_ISS_MASK) + + +#define ARMV8_ESR_EC_UNKNOWN_ERR 0x00U +#define ARMV8_ESR_EC_FP_ASIMD 0x07U +#define ARMV8_ESR_ILL_EXECUTION_STATE 0x0EU +#define ARMV8_ESR_EC_DATA_ABORT_LOWER 0x24U +#define ARMV8_ESR_EC_DATA_ABORT 0x25U +#define ARMV8_ESR_EC_INS_ABORT_LOWER 0x20U +#define ARMV8_ESR_EC_INS_ABORT 0x21U +#define ARMV8_ESR_EC_PC_ALIGNMENT_FAULT 0x22U +#define ARMV8_ESR_EC_SP_ALIGNMENT_FAULT 0x26U +#define ARMV8_ESR_EC_SERROR 0x2FU + + +/* ISS field definitions shared by different classes */ +#define ARMV8_ESR_ISS_WNR_SHIFT (6U) +#define ARMV8_ESR_ISS_WNR_MASK ((1U) << ARMV8_ESR_ISS_WNR_SHIFT) + +/* Asynchronous Error Type */ + +#define ARMV8_ESR_ISS_AET_SHIFT (10U) +#define ARMV8_ESR_ISS_AET_MASK ((0x7U) << ARMV8_ESR_ISS_AET_SHIFT) +#define ARMV8_ESR_ISS_AET_UC ((0U) << ARMV8_ESR_ISS_AET_SHIFT) +#define ARMV8_ESR_ISS_AET_UEU ((1U) << ARMV8_ESR_ISS_AET_SHIFT) +#define ARMV8_ESR_ISS_AET_UEO ((2U) << ARMV8_ESR_ISS_AET_SHIFT) +#define ARMV8_ESR_ISS_AET_UER ((3U) << ARMV8_ESR_ISS_AET_SHIFT) +#define ARMV8_ESR_ISS_AET_CE ((6U) << ARMV8_ESR_ISS_AET_SHIFT) + + +/* Shared ISS fault status code(IFSC/DFSC) for Data/Instruction aborts */ +#define ARMV8_ESR_ISS_FSC (0x3FU) +#define ARMV8_ESR_ISS_CM_SHIFT (8U) +#define ARMV8_ESR_ISS_CM_MASK ((1U) << ARMV8_ESR_ISS_CM_SHIFT) + +#define ARMV8_LEVEL_0_ADDR_FAULT 0x00U +#define ARMV8_LEVEL_1_ADDR_FAULT 0x01U +#define ARMV8_LEVEL_2_ADDR_FAULT 0x02U +#define ARMV8_LEVEL_3_ADDR_FAULT 0x03U +#define ARMV8_LEVEL_0_TRANS_FAULT 0x04U +#define ARMV8_LEVEL_1_TRANS_FAULT 0x05U +#define ARMV8_LEVEL_2_TRANS_FAULT 0x06U +#define ARMV8_LEVEL_3_TRANS_FAULT 0x07U +#define ARMV8_LEVEL_0_ACCS_FLAG_FAULT 0x08U +#define ARMV8_LEVEL_1_ACCS_FLAG_FAULT 0x09U +#define ARMV8_LEVEL_2_ACCS_FLAG_FAULT 0x0AU +#define ARMV8_LEVEL_3_ACCS_FLAG_FAULT 0x0BU +#define ARMV8_LEVEL_0_PERMISSION_FAULT 0x0CU +#define ARMV8_LEVEL_1_PERMISSION_FAULT 0x0DU +#define ARMV8_LEVEL_2_PERMISSION_FAULT 0x0EU +#define ARMV8_LEVEL_3_PERMISSION_FAULT 0x0FU + +#define ARMV8_SYNC_EXT_ABORT_NOT_ON_TTW 0x10U +#define ARMV8_LEVEL_0_SYNC_EXT_ABORT 0x14U +#define ARMV8_LEVEL_1_SYNC_EXT_ABORT 0x15U +#define ARMV8_LEVEL_2_SYNC_EXT_ABORT 0x16U +#define ARMV8_LEVEL_3_SYNC_EXT_ABORT 0x17U + +#define ARMV8_SYNC_PAR_OR_ECC_ERROR_NOT_ON_TTW 0x18U +#define ARMV8_LEVEL_0_SYNC_PAR_OR_ECC_ERROR 0x1CU +#define ARMV8_LEVEL_1_SYNC_PAR_OR_ECC_ERROR 0x1DU +#define ARMV8_LEVEL_2_SYNC_PAR_OR_ECC_ERROR 0x1EU +#define ARMV8_LEVEL_3_SYNC_PAR_OR_ECC_ERROR 0x1FU + +#define ARMV8_ALIGNMENT_FAULT 0x21U +#define ARMV8_TLB_CONFLICT_ABORT 0x30U + +#define ARMV8_ASYNC_SEEROR_INTERRUPT 0x11U + +#else /* #if defined (__aarch64__) */ + +#define DATA_ABORT 0x00U +#define INS_PREFETCH_ABORT 0x01U +#define ARMV7_FAULT_STATUS_MASK_BIT3_0 0x0FU +#define ARMV7_DFAR_VALUE_VALID 0x01U +#define ARMV7_FAULT_STATUS_BIT10_MASK 0x400U + +#define ARMV7_BACKGROUND_FAULT 0x00U +#define ARMV7_ALIGNMENT_FAULT 0x01U +#define ARMV7_DEBUG_EVENT 0x02U +#define ARMV7_ACCESS_FLAG_FAULT 0x03U +#define ARMV7_ICACHE_MAINTENANCE_FAULT 0x04U +#define ARMV7_TRANSLATION_FAULT 0x05U +#define ARMV7_SYNC_EXT_ABORT 0x08U +#define ARMV7_DOMAIN_FAULT 0x09U +#define ARMV7_SYNC_ABORT_TRANSTAB_WALK 0x0CU +#define ARMV7_PERMISSION_FAULT 0x0DU +#define ARMV7_TLB_CONFLICT_ABORT 0x10U +#define ARMV7_ASYNC_EXT_ABORT 0x16U +#define ARMV7_MEM_ACS_ASYNC_PAR_ERR 0x18U +#define ARMV7_MEM_ACS_SYNC_PAR_ERR 0x19U +#define ARMV7_SYNCPAR_ERR_TRANSTAB_WALK 0x1CU + +#define EXTRACT_BITS_10_AND_3_TO_0(Val) \ + ((Val & (ARMV7_FAULT_STATUS_BIT10_MASK)) >> 6) | \ + (Val & ARMV7_FAULT_STATUS_MASK_BIT3_0) + +#endif /* #if defined (__aarch64__) */ +#endif /* #ifdef DEBUG */ + +/* + * XIL_EXCEPTION_ID_INT is defined for all Xilinx processors. + */ +#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52) +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_FIQ_INT +#else +#define XIL_EXCEPTION_ID_INT XIL_EXCEPTION_ID_IRQ_INT +#endif + +/**************************** Type Definitions ******************************/ + +/** + * This typedef is the exception handler function. + */ +typedef void (*Xil_ExceptionHandler)(void *data); +typedef void (*Xil_InterruptHandler)(void *data); + +typedef struct { + Xil_ExceptionHandler Handler; + void *Data; +} XExc_VectorTableEntry; + +extern XExc_VectorTableEntry XExc_VectorTable[]; + +/** +*@endcond +*/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* @brief Enable Exceptions. +* +* @param Mask: Value for enabling the exceptions. +* +* @return None. +* +* @note If bit is 0, exception is enabled. +* C-Style signature: void Xil_ExceptionEnableMask(Mask) +* +******************************************************************************/ +#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52) +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always enable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionEnableMask(Mask) \ + (void)Mask; \ + mtcpsr(mfcpsr() & ~ ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionEnableMask(Mask) \ + mtcpsr(mfcpsr() & ~ ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionEnableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) & (~((Mask) & XIL_EXCEPTION_ALL))); \ + } +#endif +/****************************************************************************/ +/** +* @brief Enable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52) +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_FIQ) +#else +#define Xil_ExceptionEnable() \ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ) +#endif + +/****************************************************************************/ +/** +* @brief Disable Exceptions. +* +* @param Mask: Value for disabling the exceptions. +* +* @return None. +* +* @note If bit is 1, exception is disabled. +* C-Style signature: Xil_ExceptionDisableMask(Mask) +* +******************************************************************************/ +#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52) +/* + * Cortexa72 processor in versal is coupled with GIC-500, and GIC-500 supports + * only FIQ at EL3. Hence, tweaking this macro to always disable FIQ + * ignoring argument passed by user. + */ +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((XIL_EXCEPTION_FIQ) & XIL_EXCEPTION_ALL)) +#elif defined (__GNUC__) || defined (__ICCARM__) +#define Xil_ExceptionDisableMask(Mask) \ + mtcpsr(mfcpsr() | ((Mask) & XIL_EXCEPTION_ALL)) +#else +#define Xil_ExceptionDisableMask(Mask) \ + { \ + register u32 Reg __asm("cpsr"); \ + mtcpsr((Reg) | ((Mask) & XIL_EXCEPTION_ALL)); \ + } +#endif +/****************************************************************************/ +/** +* Disable the IRQ exception. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +#define Xil_ExceptionDisable() \ + Xil_ExceptionDisableMask(XIL_EXCEPTION_IRQ) + +#if ( defined (PLATFORM_ZYNQMP) && defined (EL3) && (EL3==1) ) +/****************************************************************************/ +/** +* @brief Enable nested interrupts by clearing the I bit in DAIF.This +* macro is defined for Cortex-A53 64 bit mode BSP configured to run +* at EL3.. However,it is not defined for Versal Cortex-A72 BSP +* configured to run at EL3. Reason is, Cortex-A72 is coupled +* with GIC-500(GICv3 specifications) and it triggers only FIQ at EL3. +* +* @return None. +* +* @note This macro is supposed to be used from interrupt handlers. In the +* interrupt handler the interrupts are disabled by default (I bit +* is set as 1). To allow nesting of interrupts, this macro should be +* used. It clears the I bit. Once that bit is cleared and provided the +* preemption of interrupt conditions are met in the GIC, nesting of +* interrupts will start happening. +* Caution: This macro must be used with caution. Before calling this +* macro, the user must ensure that the source of the current IRQ +* is appropriately cleared. Otherwise, as soon as we clear the I +* bit, there can be an infinite loop of interrupts with an +* eventual crash (all the stack space getting consumed). +******************************************************************************/ +#define Xil_EnableNestedInterrupts() \ + __asm__ __volatile__ ("mrs X1, ELR_EL3"); \ + __asm__ __volatile__ ("mrs X2, SPSR_EL3"); \ + __asm__ __volatile__ ("stp X1,X2, [sp,#-0x10]!"); \ + __asm__ __volatile__ ("mrs X1, DAIF"); \ + __asm__ __volatile__ ("bic X1,X1,#(0x1<<7)"); \ + __asm__ __volatile__ ("msr DAIF, X1"); \ + +/****************************************************************************/ +/** +* @brief Disable the nested interrupts by setting the I bit in DAIF. This +* macro is defined for Cortex-A53 64 bit mode BSP configured to run +* at EL3. +* +* @return None. +* +* @note This macro is meant to be called in the interrupt service routines. +* This macro cannot be used independently. It can only be used when +* nesting of interrupts have been enabled by using the macro +* Xil_EnableNestedInterrupts(). In a typical flow, the user first +* calls the Xil_EnableNestedInterrupts in the ISR at the appropriate +* point. The user then must call this macro before exiting the interrupt +* service routine. This macro puts the ARM back in IRQ mode and +* hence sets back the I bit. +******************************************************************************/ +#define Xil_DisableNestedInterrupts() \ + __asm__ __volatile__ ("ldp X1,X2, [sp,#0x10]!"); \ + __asm__ __volatile__ ("msr ELR_EL3, X1"); \ + __asm__ __volatile__ ("msr SPSR_EL3, X2"); \ + __asm__ __volatile__ ("mrs X1, DAIF"); \ + __asm__ __volatile__ ("orr X1, X1, #(0x1<<7)"); \ + __asm__ __volatile__ ("msr DAIF, X1"); \ + +#elif (defined (EL1_NONSECURE) && (EL1_NONSECURE==1)) +/****************************************************************************/ +/** +* @brief Enable nested interrupts by clearing the I bit in DAIF.This +* macro is defined for Cortex-A53 64 bit mode and Cortex-A72 64 bit +* BSP configured to run at EL1 NON SECURE +* +* @return None. +* +* @note This macro is supposed to be used from interrupt handlers. In the +* interrupt handler the interrupts are disabled by default (I bit +* is set as 1). To allow nesting of interrupts, this macro should be +* used. It clears the I bit. Once that bit is cleared and provided the +* preemption of interrupt conditions are met in the GIC, nesting of +* interrupts will start happening. +* Caution: This macro must be used with caution. Before calling this +* macro, the user must ensure that the source of the current IRQ +* is appropriately cleared. Otherwise, as soon as we clear the I +* bit, there can be an infinite loop of interrupts with an +* eventual crash (all the stack space getting consumed). +******************************************************************************/ +#define Xil_EnableNestedInterrupts() \ + __asm__ __volatile__ ("mrs X1, ELR_EL1"); \ + __asm__ __volatile__ ("mrs X2, SPSR_EL1"); \ + __asm__ __volatile__ ("stp X1,X2, [sp,#-0x10]!"); \ + __asm__ __volatile__ ("mrs X1, DAIF"); \ + __asm__ __volatile__ ("bic X1,X1,#(0x1<<7)"); \ + __asm__ __volatile__ ("msr DAIF, X1"); \ + +/****************************************************************************/ +/** +* @brief Disable the nested interrupts by setting the I bit in DAIF. This +* macro is defined for Cortex-A53 64 bit mode and Cortex-A72 64 bit +* BSP configured to run at EL1 NON SECURE +* +* @return None. +* +* @note This macro is meant to be called in the interrupt service routines. +* This macro cannot be used independently. It can only be used when +* nesting of interrupts have been enabled by using the macro +* Xil_EnableNestedInterrupts(). In a typical flow, the user first +* calls the Xil_EnableNestedInterrupts in the ISR at the appropriate +* point. The user then must call this macro before exiting the interrupt +* service routine. This macro puts the ARM back in IRQ mode and +* hence sets back the I bit. +******************************************************************************/ +#define Xil_DisableNestedInterrupts() \ + __asm__ __volatile__ ("ldp X1,X2, [sp,#0x10]!"); \ + __asm__ __volatile__ ("msr ELR_EL1, X1"); \ + __asm__ __volatile__ ("msr SPSR_EL1, X2"); \ + __asm__ __volatile__ ("mrs X1, DAIF"); \ + __asm__ __volatile__ ("orr X1, X1, #(0x1<<7)"); \ + __asm__ __volatile__ ("msr DAIF, X1"); \ + +#elif (!defined (__aarch64__) && !defined (ARMA53_32)) +/****************************************************************************/ +/** +* @brief Enable nested interrupts by clearing the I and F bits in CPSR. This +* API is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is supposed to be used from interrupt handlers. In the +* interrupt handler the interrupts are disabled by default (I and F +* are 1). To allow nesting of interrupts, this macro should be +* used. It clears the I and F bits by changing the ARM mode to +* system mode. Once these bits are cleared and provided the +* preemption of interrupt conditions are met in the GIC, nesting of +* interrupts will start happening. +* Caution: This macro must be used with caution. Before calling this +* macro, the user must ensure that the source of the current IRQ +* is appropriately cleared. Otherwise, as soon as we clear the I and +* F bits, there can be an infinite loop of interrupts with an +* eventual crash (all the stack space getting consumed). +******************************************************************************/ +#define Xil_EnableNestedInterrupts() \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("mrs lr, spsr"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x1F"); \ + __asm__ __volatile__ ("stmfd sp!, {lr}"); +/****************************************************************************/ +/** +* @brief Disable the nested interrupts by setting the I and F bits. This API +* is defined for cortex-a9 and cortex-r5. +* +* @return None. +* +* @note This macro is meant to be called in the interrupt service routines. +* This macro cannot be used independently. It can only be used when +* nesting of interrupts have been enabled by using the macro +* Xil_EnableNestedInterrupts(). In a typical flow, the user first +* calls the Xil_EnableNestedInterrupts in the ISR at the appropriate +* point. The user then must call this macro before exiting the interrupt +* service routine. This macro puts the ARM back in IRQ/FIQ mode and +* hence sets back the I and F bits. +******************************************************************************/ +#define Xil_DisableNestedInterrupts() \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr cpsr_c, #0x92"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + __asm__ __volatile__ ("msr spsr_cxsf, lr"); \ + __asm__ __volatile__ ("ldmfd sp!, {lr}"); \ + +#endif +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +extern void Xil_ExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler Handler, + void *Data); + +extern void Xil_ExceptionRemoveHandler(u32 Exception_id); +extern void Xil_GetExceptionRegisterHandler(u32 Exception_id, + Xil_ExceptionHandler *Handler, void **Data); + +extern void Xil_ExceptionInit(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_EXCEPTION_H */ +/** +* @} End of "addtogroup arm_exception_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_hal.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_hal.h new file mode 100644 index 0000000..4b289a7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_hal.h @@ -0,0 +1,43 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_hal.h +* +* Contains all the HAL header files. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+*
+* 
+* +* @note +* +******************************************************************************/ + +#ifndef XIL_HAL_H +#define XIL_HAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_cache.h" +#include "xil_io.h" +#include "xil_assert.h" +#include "xil_exception.h" +#include "xil_types.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_io.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_io.h new file mode 100644 index 0000000..853ef6b --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_io.h @@ -0,0 +1,412 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_io.h +* +* @addtogroup common_io_interfacing_apis Register IO interfacing APIs +* +* The xil_io.h file contains the interface for the general I/O component, which +* encapsulates the Input/Output functions for the processors that do not +* require any special I/O handling. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp  	 05/29/14 First release
+* 6.00  mus      08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
+*                         ARM processors
+* 7.20  har      01/03/20 Added Xil_SecureOut32 for avoiding blindwrite for
+*                         CR-1049218
+* 7.30  kpt      09/21/20 Moved Xil_EndianSwap16 and Xil_EndianSwap32 to
+*                         xil_io.h and made them as static inline
+*       am       10/13/20 Changed the return type of Xil_SecureOut32 function
+*                         from u32 to int
+* 7.50  dp       02/12/21 Fix compilation error in Xil_EndianSwap32() that occur
+*                         when -Werror=conversion compiler flag is enabled
+* 7.5   mus      05/17/21 Update the functions with comments. It fixes CR#1067739.
+*
+* 
+******************************************************************************/ + +#ifndef XIL_IO_H /* prevent circular inclusions */ +#define XIL_IO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_printf.h" +#include "xstatus.h" + +#if defined (__MICROBLAZE__) +#include "mb_interface.h" +#else +#include "xpseudo_asm.h" +#endif + +/************************** Function Prototypes ******************************/ +#ifdef ENABLE_SAFETY +extern u32 XStl_RegUpdate(u32 RegAddr, u32 RegVal); +#endif + +/***************** Macros (Inline Functions) Definitions *********************/ +#if defined __GNUC__ +#if defined (__MICROBLAZE__) +# define INST_SYNC mbar(0) +# define DATA_SYNC mbar(1) +# else +# define SYNCHRONIZE_IO dmb() +# define INST_SYNC isb() +# define DATA_SYNC dsb() +# endif +#else +# define SYNCHRONIZE_IO +# define INST_SYNC +# define DATA_SYNC +# define INST_SYNC +# define DATA_SYNC +#endif + +#if defined (__GNUC__) || defined (__ICCARM__) || defined (__MICROBLAZE__) +#define INLINE inline +#else +#define INLINE __inline +#endif + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading +* from the specified address and returning the 8 bit Value read from +* that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 8 bit Value read from the specified input address. + +* +******************************************************************************/ +static INLINE u8 Xil_In8(UINTPTR Addr) +{ + return *(volatile u8 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading from +* the specified address and returning the 16 bit Value read from that +* address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 16 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u16 Xil_In16(UINTPTR Addr) +{ + return *(volatile u16 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by +* reading from the specified address and returning the 32 bit Value +* read from that address. +* +* @param Addr: contains the address to perform the input operation +* +* @return The 32 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u32 Xil_In32(UINTPTR Addr) +{ + return *(volatile u32 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an input operation for a memory location by reading the +* 64 bit Value read from that address. +* +* +* @param Addr: contains the address to perform the input operation +* +* @return The 64 bit Value read from the specified input address. +* +******************************************************************************/ +static INLINE u64 Xil_In64(UINTPTR Addr) +{ + return *(volatile u64 *) Addr; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for an memory location by +* writing the 8 bit Value to the the specified address. +* +* @param Addr: contains the address to perform the output operation +* @param Value: contains the 8 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out8(UINTPTR Addr, u8 Value) +{ + /* write 8 bit value to specified address */ + volatile u8 *LocalAddr = (volatile u8 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 16 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out16(UINTPTR Addr, u16 Value) +{ + /* write 16 bit value to specified address */ + volatile u16 *LocalAddr = (volatile u16 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 32 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains the 32 bit Value to be written at the specified +* address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out32(UINTPTR Addr, u32 Value) +{ + /* write 32 bit value to specified address */ +#ifndef ENABLE_SAFETY + volatile u32 *LocalAddr = (volatile u32 *)Addr; + *LocalAddr = Value; +#else + XStl_RegUpdate(Addr, Value); +#endif +} + +/*****************************************************************************/ +/** +* +* @brief Performs an output operation for a memory location by writing the +* 64 bit Value to the the specified address. +* +* @param Addr contains the address to perform the output operation +* @param Value contains 64 bit Value to be written at the specified address. +* +* @return None. +* +******************************************************************************/ +static INLINE void Xil_Out64(UINTPTR Addr, u64 Value) +{ + /* write 64 bit value to specified address */ + volatile u64 *LocalAddr = (volatile u64 *)Addr; + *LocalAddr = Value; +} + +/*****************************************************************************/ +/** + * + * @brief Performs an output operation for a memory location by writing the + * 32 bit Value to the the specified address and then reading it + * back to verify the value written in the register. + * + * @param Addr contains the address to perform the output operation + * @param Value contains 32 bit Value to be written at the specified address + * + * @return Returns Status + * - XST_SUCCESS on success + * - XST_FAILURE on failure + * + *****************************************************************************/ +static INLINE int Xil_SecureOut32(UINTPTR Addr, u32 Value) +{ + int Status = XST_FAILURE; + u32 ReadReg; + u32 ReadRegTemp; + + /* writing 32 bit value to specified address */ + Xil_Out32(Addr, Value); + + /* verify value written to specified address with multiple reads */ + ReadReg = Xil_In32(Addr); + ReadRegTemp = Xil_In32(Addr); + + if( (ReadReg == Value) && (ReadRegTemp == Value) ) { + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief Perform a 16-bit endian conversion. +* +* @param Data: 16 bit value to be converted +* +* @return 16 bit Data with converted endianness +* +******************************************************************************/ +static INLINE __attribute__((always_inline)) u16 Xil_EndianSwap16(u16 Data) +{ + return (u16) (((Data & 0xFF00U) >> 8U) | ((Data & 0x00FFU) << 8U)); +} + +/*****************************************************************************/ +/** +* +* @brief Perform a 32-bit endian conversion. +* +* @param Data: 32 bit value to be converted +* +* @return 32 bit data with converted endianness +* +******************************************************************************/ +static INLINE __attribute__((always_inline)) u32 Xil_EndianSwap32(u32 Data) +{ + u16 LoWord; + u16 HiWord; + + /* get each of the half words from the 32 bit word */ + + LoWord = (u16) (Data & 0x0000FFFFU); + HiWord = (u16) ((Data & 0xFFFF0000U) >> 16U); + + /* byte swap each of the 16 bit half words */ + + LoWord = (u16)(((LoWord & 0xFF00U) >> 8U) | ((LoWord & 0x00FFU) << 8U)); + HiWord = (u16)(((HiWord & 0xFF00U) >> 8U) | ((HiWord & 0x00FFU) << 8U)); + + /* swap the half words before returning the value */ + + return ((((u32)LoWord) << (u32)16U) | (u32)HiWord); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +# else +# define Xil_In16BE Xil_In16 +# define Xil_In32BE Xil_In32 +# define Xil_Out16BE Xil_Out16 +# define Xil_Out32BE Xil_Out32 +# define Xil_Htons(Data) (Data) +# define Xil_Htonl(Data) (Data) +# define Xil_Ntohs(Data) (Data) +# define Xil_Ntohl(Data) (Data) +#endif +#else +# define Xil_In16LE Xil_In16 +# define Xil_In32LE Xil_In32 +# define Xil_Out16LE Xil_Out16 +# define Xil_Out32LE Xil_Out32 +# define Xil_Htons Xil_EndianSwap16 +# define Xil_Htonl Xil_EndianSwap32 +# define Xil_Ntohs Xil_EndianSwap16 +# define Xil_Ntohl Xil_EndianSwap32 +#endif + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#else +static INLINE u16 Xil_In16LE(UINTPTR Addr) +#endif +#else +static INLINE u16 Xil_In16BE(UINTPTR Addr) +#endif +{ + u16 value = Xil_In16(Addr); + return Xil_EndianSwap16(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#else +static INLINE u32 Xil_In32LE(UINTPTR Addr) +#endif +#else +static INLINE u32 Xil_In32BE(UINTPTR Addr) +#endif +{ + u32 value = Xil_In32(Addr); + return Xil_EndianSwap32(value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#else +static INLINE void Xil_Out16LE(UINTPTR Addr, u16 Value) +#endif +#else +static INLINE void Xil_Out16BE(UINTPTR Addr, u16 Value) +#endif +{ + Value = Xil_EndianSwap16(Value); + Xil_Out16(Addr, Value); +} + +#if defined (__MICROBLAZE__) +#ifdef __LITTLE_ENDIAN__ +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#else +static INLINE void Xil_Out32LE(UINTPTR Addr, u32 Value) +#endif +#else +static INLINE void Xil_Out32BE(UINTPTR Addr, u32 Value) +#endif +{ + Value = Xil_EndianSwap32(Value); + Xil_Out32(Addr, Value); +} + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_io_interfacing_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_macroback.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_macroback.h new file mode 100644 index 0000000..7a0135a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_macroback.h @@ -0,0 +1,1113 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +/*********************************************************************/ +/** + * @file xil_macroback.h + * + * This header file is meant to bring back the removed _m macros. + * This header file must be included last. + * The following macros are not defined here due to the driver change: + * XGpio_mSetDataDirection + * XGpio_mGetDataReg + * XGpio_mSetDataReg + * XIIC_RESET + * XIIC_CLEAR_STATS + * XSpi_mReset + * XSysAce_mSetCfgAddr + * XSysAce_mIsCfgDone + * XTft_mSetPixel + * XTft_mGetPixel + * XWdtTb_mEnableWdt + * XWdtTb_mDisbleWdt + * XWdtTb_mRestartWdt + * XWdtTb_mGetTimebaseReg + * XWdtTb_mHasReset + * + * Please refer the corresponding driver document for replacement. + * + *********************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_MACROBACK_H +#define XIL_MACROBACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************/ +/** + * Macros for Driver XCan + * + *********************************************************************/ +#ifndef XCan_mReadReg +#define XCan_mReadReg XCan_ReadReg +#endif + +#ifndef XCan_mWriteReg +#define XCan_mWriteReg XCan_WriteReg +#endif + +#ifndef XCan_mIsTxDone +#define XCan_mIsTxDone XCan_IsTxDone +#endif + +#ifndef XCan_mIsTxFifoFull +#define XCan_mIsTxFifoFull XCan_IsTxFifoFull +#endif + +#ifndef XCan_mIsHighPriorityBufFull +#define XCan_mIsHighPriorityBufFull XCan_IsHighPriorityBufFull +#endif + +#ifndef XCan_mIsRxEmpty +#define XCan_mIsRxEmpty XCan_IsRxEmpty +#endif + +#ifndef XCan_mIsAcceptFilterBusy +#define XCan_mIsAcceptFilterBusy XCan_IsAcceptFilterBusy +#endif + +#ifndef XCan_mCreateIdValue +#define XCan_mCreateIdValue XCan_CreateIdValue +#endif + +#ifndef XCan_mCreateDlcValue +#define XCan_mCreateDlcValue XCan_CreateDlcValue +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDmaCentral + * + *********************************************************************/ +#ifndef XDmaCentral_mWriteReg +#define XDmaCentral_mWriteReg XDmaCentral_WriteReg +#endif + +#ifndef XDmaCentral_mReadReg +#define XDmaCentral_mReadReg XDmaCentral_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsAdc + * + *********************************************************************/ +#ifndef XDsAdc_mWriteReg +#define XDsAdc_mWriteReg XDsAdc_WriteReg +#endif + +#ifndef XDsAdc_mReadReg +#define XDsAdc_mReadReg XDsAdc_ReadReg +#endif + +#ifndef XDsAdc_mIsEmpty +#define XDsAdc_mIsEmpty XDsAdc_IsEmpty +#endif + +#ifndef XDsAdc_mSetFstmReg +#define XDsAdc_mSetFstmReg XDsAdc_SetFstmReg +#endif + +#ifndef XDsAdc_mGetFstmReg +#define XDsAdc_mGetFstmReg XDsAdc_GetFstmReg +#endif + +#ifndef XDsAdc_mEnableConversion +#define XDsAdc_mEnableConversion XDsAdc_EnableConversion +#endif + +#ifndef XDsAdc_mDisableConversion +#define XDsAdc_mDisableConversion XDsAdc_DisableConversion +#endif + +#ifndef XDsAdc_mGetFifoOccyReg +#define XDsAdc_mGetFifoOccyReg XDsAdc_GetFifoOccyReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XDsDac + * + *********************************************************************/ +#ifndef XDsDac_mWriteReg +#define XDsDac_mWriteReg XDsDac_WriteReg +#endif + +#ifndef XDsDac_mReadReg +#define XDsDac_mReadReg XDsDac_ReadReg +#endif + +#ifndef XDsDac_mIsEmpty +#define XDsDac_mIsEmpty XDsDac_IsEmpty +#endif + +#ifndef XDsDac_mFifoIsFull +#define XDsDac_mFifoIsFull XDsDac_FifoIsFull +#endif + +#ifndef XDsDac_mGetVacancy +#define XDsDac_mGetVacancy XDsDac_GetVacancy +#endif + +/*********************************************************************/ +/** + * Macros for Driver XEmacLite + * + *********************************************************************/ +#ifndef XEmacLite_mReadReg +#define XEmacLite_mReadReg XEmacLite_ReadReg +#endif + +#ifndef XEmacLite_mWriteReg +#define XEmacLite_mWriteReg XEmacLite_WriteReg +#endif + +#ifndef XEmacLite_mGetTxStatus +#define XEmacLite_mGetTxStatus XEmacLite_GetTxStatus +#endif + +#ifndef XEmacLite_mSetTxStatus +#define XEmacLite_mSetTxStatus XEmacLite_SetTxStatus +#endif + +#ifndef XEmacLite_mGetRxStatus +#define XEmacLite_mGetRxStatus XEmacLite_GetRxStatus +#endif + +#ifndef XEmacLite_mSetRxStatus +#define XEmacLite_mSetRxStatus XEmacLite_SetRxStatus +#endif + +#ifndef XEmacLite_mIsTxDone +#define XEmacLite_mIsTxDone XEmacLite_IsTxDone +#endif + +#ifndef XEmacLite_mIsRxEmpty +#define XEmacLite_mIsRxEmpty XEmacLite_IsRxEmpty +#endif + +#ifndef XEmacLite_mNextTransmitAddr +#define XEmacLite_mNextTransmitAddr XEmacLite_NextTransmitAddr +#endif + +#ifndef XEmacLite_mNextReceiveAddr +#define XEmacLite_mNextReceiveAddr XEmacLite_NextReceiveAddr +#endif + +#ifndef XEmacLite_mIsMdioConfigured +#define XEmacLite_mIsMdioConfigured XEmacLite_IsMdioConfigured +#endif + +#ifndef XEmacLite_mIsLoopbackConfigured +#define XEmacLite_mIsLoopbackConfigured XEmacLite_IsLoopbackConfigured +#endif + +#ifndef XEmacLite_mGetReceiveDataLength +#define XEmacLite_mGetReceiveDataLength XEmacLite_GetReceiveDataLength +#endif + +#ifndef XEmacLite_mGetTxActive +#define XEmacLite_mGetTxActive XEmacLite_GetTxActive +#endif + +#ifndef XEmacLite_mSetTxActive +#define XEmacLite_mSetTxActive XEmacLite_SetTxActive +#endif + +/*********************************************************************/ +/** + * Macros for Driver XGpio + * + *********************************************************************/ +#ifndef XGpio_mWriteReg +#define XGpio_mWriteReg XGpio_WriteReg +#endif + +#ifndef XGpio_mReadReg +#define XGpio_mReadReg XGpio_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XHwIcap + * + *********************************************************************/ +#ifndef XHwIcap_mFifoWrite +#define XHwIcap_mFifoWrite XHwIcap_FifoWrite +#endif + +#ifndef XHwIcap_mFifoRead +#define XHwIcap_mFifoRead XHwIcap_FifoRead +#endif + +#ifndef XHwIcap_mSetSizeReg +#define XHwIcap_mSetSizeReg XHwIcap_SetSizeReg +#endif + +#ifndef XHwIcap_mGetControlReg +#define XHwIcap_mGetControlReg XHwIcap_GetControlReg +#endif + +#ifndef XHwIcap_mStartConfig +#define XHwIcap_mStartConfig XHwIcap_StartConfig +#endif + +#ifndef XHwIcap_mStartReadBack +#define XHwIcap_mStartReadBack XHwIcap_StartReadBack +#endif + +#ifndef XHwIcap_mGetStatusReg +#define XHwIcap_mGetStatusReg XHwIcap_GetStatusReg +#endif + +#ifndef XHwIcap_mIsTransferDone +#define XHwIcap_mIsTransferDone XHwIcap_IsTransferDone +#endif + +#ifndef XHwIcap_mIsDeviceBusy +#define XHwIcap_mIsDeviceBusy XHwIcap_IsDeviceBusy +#endif + +#ifndef XHwIcap_mIntrGlobalEnable +#define XHwIcap_mIntrGlobalEnable XHwIcap_IntrGlobalEnable +#endif + +#ifndef XHwIcap_mIntrGlobalDisable +#define XHwIcap_mIntrGlobalDisable XHwIcap_IntrGlobalDisable +#endif + +#ifndef XHwIcap_mIntrGetStatus +#define XHwIcap_mIntrGetStatus XHwIcap_IntrGetStatus +#endif + +#ifndef XHwIcap_mIntrDisable +#define XHwIcap_mIntrDisable XHwIcap_IntrDisable +#endif + +#ifndef XHwIcap_mIntrEnable +#define XHwIcap_mIntrEnable XHwIcap_IntrEnable +#endif + +#ifndef XHwIcap_mIntrGetEnabled +#define XHwIcap_mIntrGetEnabled XHwIcap_IntrGetEnabled +#endif + +#ifndef XHwIcap_mIntrClear +#define XHwIcap_mIntrClear XHwIcap_IntrClear +#endif + +#ifndef XHwIcap_mGetWrFifoVacancy +#define XHwIcap_mGetWrFifoVacancy XHwIcap_GetWrFifoVacancy +#endif + +#ifndef XHwIcap_mGetRdFifoOccupancy +#define XHwIcap_mGetRdFifoOccupancy XHwIcap_GetRdFifoOccupancy +#endif + +#ifndef XHwIcap_mSliceX2Col +#define XHwIcap_mSliceX2Col XHwIcap_SliceX2Col +#endif + +#ifndef XHwIcap_mSliceY2Row +#define XHwIcap_mSliceY2Row XHwIcap_SliceY2Row +#endif + +#ifndef XHwIcap_mSliceXY2Slice +#define XHwIcap_mSliceXY2Slice XHwIcap_SliceXY2Slice +#endif + +#ifndef XHwIcap_mReadReg +#define XHwIcap_mReadReg XHwIcap_ReadReg +#endif + +#ifndef XHwIcap_mWriteReg +#define XHwIcap_mWriteReg XHwIcap_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIic + * + *********************************************************************/ +#ifndef XIic_mReadReg +#define XIic_mReadReg XIic_ReadReg +#endif + +#ifndef XIic_mWriteReg +#define XIic_mWriteReg XIic_WriteReg +#endif + +#ifndef XIic_mEnterCriticalRegion +#define XIic_mEnterCriticalRegion XIic_IntrGlobalDisable +#endif + +#ifndef XIic_mExitCriticalRegion +#define XIic_mExitCriticalRegion XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_GINTR_DISABLE +#define XIIC_GINTR_DISABLE XIic_IntrGlobalDisable +#endif + +#ifndef XIIC_GINTR_ENABLE +#define XIIC_GINTR_ENABLE XIic_IntrGlobalEnable +#endif + +#ifndef XIIC_IS_GINTR_ENABLED +#define XIIC_IS_GINTR_ENABLED XIic_IsIntrGlobalEnabled +#endif + +#ifndef XIIC_WRITE_IISR +#define XIIC_WRITE_IISR XIic_WriteIisr +#endif + +#ifndef XIIC_READ_IISR +#define XIIC_READ_IISR XIic_ReadIisr +#endif + +#ifndef XIIC_WRITE_IIER +#define XIIC_WRITE_IIER XIic_WriteIier +#endif + +#ifndef XIic_mClearIisr +#define XIic_mClearIisr XIic_ClearIisr +#endif + +#ifndef XIic_mSend7BitAddress +#define XIic_mSend7BitAddress XIic_Send7BitAddress +#endif + +#ifndef XIic_mDynSend7BitAddress +#define XIic_mDynSend7BitAddress XIic_DynSend7BitAddress +#endif + +#ifndef XIic_mDynSendStartStopAddress +#define XIic_mDynSendStartStopAddress XIic_DynSendStartStopAddress +#endif + +#ifndef XIic_mDynSendStop +#define XIic_mDynSendStop XIic_DynSendStop +#endif + +#ifndef XIic_mSend10BitAddrByte1 +#define XIic_mSend10BitAddrByte1 XIic_Send10BitAddrByte1 +#endif + +#ifndef XIic_mSend10BitAddrByte2 +#define XIic_mSend10BitAddrByte2 XIic_Send10BitAddrByte2 +#endif + +#ifndef XIic_mSend7BitAddr +#define XIic_mSend7BitAddr XIic_Send7BitAddr +#endif + +#ifndef XIic_mDisableIntr +#define XIic_mDisableIntr XIic_DisableIntr +#endif + +#ifndef XIic_mEnableIntr +#define XIic_mEnableIntr XIic_EnableIntr +#endif + +#ifndef XIic_mClearIntr +#define XIic_mClearIntr XIic_ClearIntr +#endif + +#ifndef XIic_mClearEnableIntr +#define XIic_mClearEnableIntr XIic_ClearEnableIntr +#endif + +#ifndef XIic_mFlushRxFifo +#define XIic_mFlushRxFifo XIic_FlushRxFifo +#endif + +#ifndef XIic_mFlushTxFifo +#define XIic_mFlushTxFifo XIic_FlushTxFifo +#endif + +#ifndef XIic_mReadRecvByte +#define XIic_mReadRecvByte XIic_ReadRecvByte +#endif + +#ifndef XIic_mWriteSendByte +#define XIic_mWriteSendByte XIic_WriteSendByte +#endif + +#ifndef XIic_mSetControlRegister +#define XIic_mSetControlRegister XIic_SetControlRegister +#endif + +/*********************************************************************/ +/** + * Macros for Driver XIntc + * + *********************************************************************/ +#ifndef XIntc_mMasterEnable +#define XIntc_mMasterEnable XIntc_MasterEnable +#endif + +#ifndef XIntc_mMasterDisable +#define XIntc_mMasterDisable XIntc_MasterDisable +#endif + +#ifndef XIntc_mEnableIntr +#define XIntc_mEnableIntr XIntc_EnableIntr +#endif + +#ifndef XIntc_mDisableIntr +#define XIntc_mDisableIntr XIntc_DisableIntr +#endif + +#ifndef XIntc_mAckIntr +#define XIntc_mAckIntr XIntc_AckIntr +#endif + +#ifndef XIntc_mGetIntrStatus +#define XIntc_mGetIntrStatus XIntc_GetIntrStatus +#endif + +/*********************************************************************/ +/** + * Macros for Driver XLlDma + * + *********************************************************************/ +#ifndef XLlDma_mBdRead +#define XLlDma_mBdRead XLlDma_BdRead +#endif + +#ifndef XLlDma_mBdWrite +#define XLlDma_mBdWrite XLlDma_BdWrite +#endif + +#ifndef XLlDma_mWriteReg +#define XLlDma_mWriteReg XLlDma_WriteReg +#endif + +#ifndef XLlDma_mReadReg +#define XLlDma_mReadReg XLlDma_ReadReg +#endif + +#ifndef XLlDma_mBdClear +#define XLlDma_mBdClear XLlDma_BdClear +#endif + +#ifndef XLlDma_mBdSetStsCtrl +#define XLlDma_mBdSetStsCtrl XLlDma_BdSetStsCtrl +#endif + +#ifndef XLlDma_mBdGetStsCtrl +#define XLlDma_mBdGetStsCtrl XLlDma_BdGetStsCtrl +#endif + +#ifndef XLlDma_mBdSetLength +#define XLlDma_mBdSetLength XLlDma_BdSetLength +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mBdSetId +#define XLlDma_mBdSetId XLlDma_BdSetId +#endif + +#ifndef XLlDma_mBdGetId +#define XLlDma_mBdGetId XLlDma_BdGetId +#endif + +#ifndef XLlDma_mBdSetBufAddr +#define XLlDma_mBdSetBufAddr XLlDma_BdSetBufAddr +#endif + +#ifndef XLlDma_mBdGetBufAddr +#define XLlDma_mBdGetBufAddr XLlDma_BdGetBufAddr +#endif + +#ifndef XLlDma_mBdGetLength +#define XLlDma_mBdGetLength XLlDma_BdGetLength +#endif + +#ifndef XLlDma_mGetTxRing +#define XLlDma_mGetTxRing XLlDma_GetTxRing +#endif + +#ifndef XLlDma_mGetRxRing +#define XLlDma_mGetRxRing XLlDma_GetRxRing +#endif + +#ifndef XLlDma_mGetCr +#define XLlDma_mGetCr XLlDma_GetCr +#endif + +#ifndef XLlDma_mSetCr +#define XLlDma_mSetCr XLlDma_SetCr +#endif + +#ifndef XLlDma_mBdRingCntCalc +#define XLlDma_mBdRingCntCalc XLlDma_BdRingCntCalc +#endif + +#ifndef XLlDma_mBdRingMemCalc +#define XLlDma_mBdRingMemCalc XLlDma_BdRingMemCalc +#endif + +#ifndef XLlDma_mBdRingGetCnt +#define XLlDma_mBdRingGetCnt XLlDma_BdRingGetCnt +#endif + +#ifndef XLlDma_mBdRingGetFreeCnt +#define XLlDma_mBdRingGetFreeCnt XLlDma_BdRingGetFreeCnt +#endif + +#ifndef XLlDma_mBdRingSnapShotCurrBd +#define XLlDma_mBdRingSnapShotCurrBd XLlDma_BdRingSnapShotCurrBd +#endif + +#ifndef XLlDma_mBdRingNext +#define XLlDma_mBdRingNext XLlDma_BdRingNext +#endif + +#ifndef XLlDma_mBdRingPrev +#define XLlDma_mBdRingPrev XLlDma_BdRingPrev +#endif + +#ifndef XLlDma_mBdRingGetSr +#define XLlDma_mBdRingGetSr XLlDma_BdRingGetSr +#endif + +#ifndef XLlDma_mBdRingSetSr +#define XLlDma_mBdRingSetSr XLlDma_BdRingSetSr +#endif + +#ifndef XLlDma_mBdRingGetCr +#define XLlDma_mBdRingGetCr XLlDma_BdRingGetCr +#endif + +#ifndef XLlDma_mBdRingSetCr +#define XLlDma_mBdRingSetCr XLlDma_BdRingSetCr +#endif + +#ifndef XLlDma_mBdRingBusy +#define XLlDma_mBdRingBusy XLlDma_BdRingBusy +#endif + +#ifndef XLlDma_mBdRingIntEnable +#define XLlDma_mBdRingIntEnable XLlDma_BdRingIntEnable +#endif + +#ifndef XLlDma_mBdRingIntDisable +#define XLlDma_mBdRingIntDisable XLlDma_BdRingIntDisable +#endif + +#ifndef XLlDma_mBdRingIntGetEnabled +#define XLlDma_mBdRingIntGetEnabled XLlDma_BdRingIntGetEnabled +#endif + +#ifndef XLlDma_mBdRingGetIrq +#define XLlDma_mBdRingGetIrq XLlDma_BdRingGetIrq +#endif + +#ifndef XLlDma_mBdRingAckIrq +#define XLlDma_mBdRingAckIrq XLlDma_BdRingAckIrq +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMbox + * + *********************************************************************/ +#ifndef XMbox_mWriteReg +#define XMbox_mWriteReg XMbox_WriteReg +#endif + +#ifndef XMbox_mReadReg +#define XMbox_mReadReg XMbox_ReadReg +#endif + +#ifndef XMbox_mWriteMBox +#define XMbox_mWriteMBox XMbox_WriteMBox +#endif + +#ifndef XMbox_mReadMBox +#define XMbox_mReadMBox XMbox_ReadMBox +#endif + +#ifndef XMbox_mFSLReadMBox +#define XMbox_mFSLReadMBox XMbox_FSLReadMBox +#endif + +#ifndef XMbox_mFSLWriteMBox +#define XMbox_mFSLWriteMBox XMbox_FSLWriteMBox +#endif + +#ifndef XMbox_mFSLIsEmpty +#define XMbox_mFSLIsEmpty XMbox_FSLIsEmpty +#endif + +#ifndef XMbox_mFSLIsFull +#define XMbox_mFSLIsFull XMbox_FSLIsFull +#endif + +#ifndef XMbox_mIsEmpty +#define XMbox_mIsEmpty XMbox_IsEmptyHw +#endif + +#ifndef XMbox_mIsFull +#define XMbox_mIsFull XMbox_IsFullHw +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMpmc + * + *********************************************************************/ +#ifndef XMpmc_mReadReg +#define XMpmc_mReadReg XMpmc_ReadReg +#endif + +#ifndef XMpmc_mWriteReg +#define XMpmc_mWriteReg XMpmc_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XMutex + * + *********************************************************************/ +#ifndef XMutex_mWriteReg +#define XMutex_mWriteReg XMutex_WriteReg +#endif + +#ifndef XMutex_mReadReg +#define XMutex_mReadReg XMutex_ReadReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XPcie + * + *********************************************************************/ +#ifndef XPcie_mReadReg +#define XPcie_mReadReg XPcie_ReadReg +#endif + +#ifndef XPcie_mWriteReg +#define XPcie_mWriteReg XPcie_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSpi + * + *********************************************************************/ +#ifndef XSpi_mIntrGlobalEnable +#define XSpi_mIntrGlobalEnable XSpi_IntrGlobalEnable +#endif + +#ifndef XSpi_mIntrGlobalDisable +#define XSpi_mIntrGlobalDisable XSpi_IntrGlobalDisable +#endif + +#ifndef XSpi_mIsIntrGlobalEnabled +#define XSpi_mIsIntrGlobalEnabled XSpi_IsIntrGlobalEnabled +#endif + +#ifndef XSpi_mIntrGetStatus +#define XSpi_mIntrGetStatus XSpi_IntrGetStatus +#endif + +#ifndef XSpi_mIntrClear +#define XSpi_mIntrClear XSpi_IntrClear +#endif + +#ifndef XSpi_mIntrEnable +#define XSpi_mIntrEnable XSpi_IntrEnable +#endif + +#ifndef XSpi_mIntrDisable +#define XSpi_mIntrDisable XSpi_IntrDisable +#endif + +#ifndef XSpi_mIntrGetEnabled +#define XSpi_mIntrGetEnabled XSpi_IntrGetEnabled +#endif + +#ifndef XSpi_mSetControlReg +#define XSpi_mSetControlReg XSpi_SetControlReg +#endif + +#ifndef XSpi_mGetControlReg +#define XSpi_mGetControlReg XSpi_GetControlReg +#endif + +#ifndef XSpi_mGetStatusReg +#define XSpi_mGetStatusReg XSpi_GetStatusReg +#endif + +#ifndef XSpi_mSetSlaveSelectReg +#define XSpi_mSetSlaveSelectReg XSpi_SetSlaveSelectReg +#endif + +#ifndef XSpi_mGetSlaveSelectReg +#define XSpi_mGetSlaveSelectReg XSpi_GetSlaveSelectReg +#endif + +#ifndef XSpi_mEnable +#define XSpi_mEnable XSpi_Enable +#endif + +#ifndef XSpi_mDisable +#define XSpi_mDisable XSpi_Disable +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysAce + * + *********************************************************************/ +#ifndef XSysAce_mGetControlReg +#define XSysAce_mGetControlReg XSysAce_GetControlReg +#endif + +#ifndef XSysAce_mSetControlReg +#define XSysAce_mSetControlReg XSysAce_SetControlReg +#endif + +#ifndef XSysAce_mOrControlReg +#define XSysAce_mOrControlReg XSysAce_OrControlReg +#endif + +#ifndef XSysAce_mAndControlReg +#define XSysAce_mAndControlReg XSysAce_AndControlReg +#endif + +#ifndef XSysAce_mGetErrorReg +#define XSysAce_mGetErrorReg XSysAce_GetErrorReg +#endif + +#ifndef XSysAce_mGetStatusReg +#define XSysAce_mGetStatusReg XSysAce_GetStatusReg +#endif + +#ifndef XSysAce_mWaitForLock +#define XSysAce_mWaitForLock XSysAce_WaitForLock +#endif + +#ifndef XSysAce_mEnableIntr +#define XSysAce_mEnableIntr XSysAce_EnableIntr +#endif + +#ifndef XSysAce_mDisableIntr +#define XSysAce_mDisableIntr XSysAce_DisableIntr +#endif + +#ifndef XSysAce_mIsReadyForCmd +#define XSysAce_mIsReadyForCmd XSysAce_IsReadyForCmd +#endif + +#ifndef XSysAce_mIsMpuLocked +#define XSysAce_mIsMpuLocked XSysAce_IsMpuLocked +#endif + +#ifndef XSysAce_mIsIntrEnabled +#define XSysAce_mIsIntrEnabled XSysAce_IsIntrEnabled +#endif + +/*********************************************************************/ +/** + * Macros for Driver XSysMon + * + *********************************************************************/ +#ifndef XSysMon_mIsEventSamplingModeSet +#define XSysMon_mIsEventSamplingModeSet XSysMon_IsEventSamplingModeSet +#endif + +#ifndef XSysMon_mIsDrpBusy +#define XSysMon_mIsDrpBusy XSysMon_IsDrpBusy +#endif + +#ifndef XSysMon_mIsDrpLocked +#define XSysMon_mIsDrpLocked XSysMon_IsDrpLocked +#endif + +#ifndef XSysMon_mRawToTemperature +#define XSysMon_mRawToTemperature XSysMon_RawToTemperature +#endif + +#ifndef XSysMon_mRawToVoltage +#define XSysMon_mRawToVoltage XSysMon_RawToVoltage +#endif + +#ifndef XSysMon_mTemperatureToRaw +#define XSysMon_mTemperatureToRaw XSysMon_TemperatureToRaw +#endif + +#ifndef XSysMon_mVoltageToRaw +#define XSysMon_mVoltageToRaw XSysMon_VoltageToRaw +#endif + +#ifndef XSysMon_mReadReg +#define XSysMon_mReadReg XSysMon_ReadReg +#endif + +#ifndef XSysMon_mWriteReg +#define XSysMon_mWriteReg XSysMon_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XTmrCtr + * + *********************************************************************/ +#ifndef XTimerCtr_mReadReg +#define XTimerCtr_mReadReg XTimerCtr_ReadReg +#endif + +#ifndef XTmrCtr_mWriteReg +#define XTmrCtr_mWriteReg XTmrCtr_WriteReg +#endif + +#ifndef XTmrCtr_mSetControlStatusReg +#define XTmrCtr_mSetControlStatusReg XTmrCtr_SetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetControlStatusReg +#define XTmrCtr_mGetControlStatusReg XTmrCtr_GetControlStatusReg +#endif + +#ifndef XTmrCtr_mGetTimerCounterReg +#define XTmrCtr_mGetTimerCounterReg XTmrCtr_GetTimerCounterReg +#endif + +#ifndef XTmrCtr_mSetLoadReg +#define XTmrCtr_mSetLoadReg XTmrCtr_SetLoadReg +#endif + +#ifndef XTmrCtr_mGetLoadReg +#define XTmrCtr_mGetLoadReg XTmrCtr_GetLoadReg +#endif + +#ifndef XTmrCtr_mEnable +#define XTmrCtr_mEnable XTmrCtr_Enable +#endif + +#ifndef XTmrCtr_mDisable +#define XTmrCtr_mDisable XTmrCtr_Disable +#endif + +#ifndef XTmrCtr_mEnableIntr +#define XTmrCtr_mEnableIntr XTmrCtr_EnableIntr +#endif + +#ifndef XTmrCtr_mDisableIntr +#define XTmrCtr_mDisableIntr XTmrCtr_DisableIntr +#endif + +#ifndef XTmrCtr_mLoadTimerCounterReg +#define XTmrCtr_mLoadTimerCounterReg XTmrCtr_LoadTimerCounterReg +#endif + +#ifndef XTmrCtr_mHasEventOccurred +#define XTmrCtr_mHasEventOccurred XTmrCtr_HasEventOccurred +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartLite + * + *********************************************************************/ +#ifndef XUartLite_mUpdateStats +#define XUartLite_mUpdateStats XUartLite_UpdateStats +#endif + +#ifndef XUartLite_mWriteReg +#define XUartLite_mWriteReg XUartLite_WriteReg +#endif + +#ifndef XUartLite_mReadReg +#define XUartLite_mReadReg XUartLite_ReadReg +#endif + +#ifndef XUartLite_mClearStats +#define XUartLite_mClearStats XUartLite_ClearStats +#endif + +#ifndef XUartLite_mSetControlReg +#define XUartLite_mSetControlReg XUartLite_SetControlReg +#endif + +#ifndef XUartLite_mGetStatusReg +#define XUartLite_mGetStatusReg XUartLite_GetStatusReg +#endif + +#ifndef XUartLite_mIsReceiveEmpty +#define XUartLite_mIsReceiveEmpty XUartLite_IsReceiveEmpty +#endif + +#ifndef XUartLite_mIsTransmitFull +#define XUartLite_mIsTransmitFull XUartLite_IsTransmitFull +#endif + +#ifndef XUartLite_mIsIntrEnabled +#define XUartLite_mIsIntrEnabled XUartLite_IsIntrEnabled +#endif + +#ifndef XUartLite_mEnableIntr +#define XUartLite_mEnableIntr XUartLite_EnableIntr +#endif + +#ifndef XUartLite_mDisableIntr +#define XUartLite_mDisableIntr XUartLite_DisableIntr +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUartNs550 + * + *********************************************************************/ +#ifndef XUartNs550_mUpdateStats +#define XUartNs550_mUpdateStats XUartNs550_UpdateStats +#endif + +#ifndef XUartNs550_mReadReg +#define XUartNs550_mReadReg XUartNs550_ReadReg +#endif + +#ifndef XUartNs550_mWriteReg +#define XUartNs550_mWriteReg XUartNs550_WriteReg +#endif + +#ifndef XUartNs550_mClearStats +#define XUartNs550_mClearStats XUartNs550_ClearStats +#endif + +#ifndef XUartNs550_mGetLineStatusReg +#define XUartNs550_mGetLineStatusReg XUartNs550_GetLineStatusReg +#endif + +#ifndef XUartNs550_mGetLineControlReg +#define XUartNs550_mGetLineControlReg XUartNs550_GetLineControlReg +#endif + +#ifndef XUartNs550_mSetLineControlReg +#define XUartNs550_mSetLineControlReg XUartNs550_SetLineControlReg +#endif + +#ifndef XUartNs550_mEnableIntr +#define XUartNs550_mEnableIntr XUartNs550_EnableIntr +#endif + +#ifndef XUartNs550_mDisableIntr +#define XUartNs550_mDisableIntr XUartNs550_DisableIntr +#endif + +#ifndef XUartNs550_mIsReceiveData +#define XUartNs550_mIsReceiveData XUartNs550_IsReceiveData +#endif + +#ifndef XUartNs550_mIsTransmitEmpty +#define XUartNs550_mIsTransmitEmpty XUartNs550_IsTransmitEmpty +#endif + +/*********************************************************************/ +/** + * Macros for Driver XUsb + * + *********************************************************************/ +#ifndef XUsb_mReadReg +#define XUsb_mReadReg XUsb_ReadReg +#endif + +#ifndef XUsb_mWriteReg +#define XUsb_mWriteReg XUsb_WriteReg +#endif + +/*********************************************************************/ +/** + * Macros for Driver XPmonPsv + * + *********************************************************************/ +#ifndef XpsvPmon_CfgInitialize +#define XpsvPmon_CfgInitialize XPmonPsv_CfgInitialize +#endif + +#ifndef XpsvPmon_LookupConfig +#define XpsvPmon_LookupConfig XPmonPsv_LookupConfig +#endif + +#ifndef XpsvPmon_WriteReg +#define XpsvPmon_WriteReg XPmonPsv_WriteReg +#endif + +#ifndef XpsvPmon_SetMetrics +#define XpsvPmon_SetMetrics XPmonPsv_SetMetrics +#endif + +#ifndef XpsvPmon_GetMetrics +#define XpsvPmon_GetMetrics XPmonPsv_GetMetrics +#endif + +#ifndef XpsvPmon_ResetCounter +#define XpsvPmon_ResetCounter XPmonPsv_ResetCounter +#endif + +#ifndef XpsvPmon_GetWriteCounter +#define XpsvPmon_GetWriteCounter XPmonPsv_GetWriteCounter +#endif + +#ifndef XpsvPmon_GetReadCounter +#define XpsvPmon_GetReadCounter XPmonPsv_GetReadCounter +#endif + +#ifndef XpsvPmon_EnableCounters +#define XpsvPmon_EnableCounters XPmonPsv_EnableCounters +#endif + +#ifndef XpsvPmon_StopCounter +#define XpsvPmon_StopCounter XPmonPsv_StopCounter +#endif + +#ifndef XpsvPmon_SetPort +#define XpsvPmon_SetPort XPmonPsv_SetPort +#endif + +#ifndef XpsvPmon_SetSrc +#define XpsvPmon_SetSrc XPmonPsv_SetSrc +#endif + +#ifndef XpsvPmon_Unlock +#define XpsvPmon_Unlock XPmonPsv_Unlock +#endif + +#ifndef XpsvPmon_Lock +#define XpsvPmon_Lock XPmonPsv_Lock +#endif + + +#ifndef XpsvPmon_RequestCounter +#define XpsvPmon_RequestCounter XPmonPsv_RequestCounter +#endif + +#ifndef XPmonpsv_Config +#define XPmonpsv_Config XPmonPsv_Config +#endif + +typedef XPmonPsv XpsvPmon; +#ifdef __cplusplus +} +#endif + +#endif +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mem.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mem.c new file mode 100644 index 0000000..44e7d9a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mem.c @@ -0,0 +1,70 @@ +/******************************************************************************/ +/** +* Copyright (c) 2015 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* @file xil_mem.c +* +* This file contains xil mem copy function to use in case of word aligned +* data copies. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+* 7.7	sk	 01/10/22 Update Xil_MemCpy functions variables typecast
+* 			  from int to s32 to fix misra_c_2012_directive_4_6
+* 			  violations.
+* 7.7	sk	 01/10/22 Include xil_mem.h header file to fix Xil_MemCpy
+* 			  prototype misra_c_2012_rule_8_4 violation.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_mem.h" + +/***************** Inline Functions Definitions ********************/ +/*****************************************************************************/ +/** +* @brief This function copies memory from once location to other. +* +* @param dst: pointer pointing to destination memory +* +* @param src: pointer pointing to source memory +* +* @param cnt: 32 bit length of bytes to be copied +* +*****************************************************************************/ +void Xil_MemCpy(void* dst, const void* src, u32 cnt) +{ + char *d = (char*)(void *)dst; + const char *s = src; + + while (cnt >= sizeof (s32)) { + *(s32*)d = *(s32*)s; + d += sizeof (s32); + s += sizeof (s32); + cnt -= sizeof (s32); + } + while (cnt >= sizeof (u16)) { + *(u16*)d = *(u16*)s; + d += sizeof (u16); + s += sizeof (u16); + cnt -= sizeof (u16); + } + while ((cnt) > 0U){ + *d = *s; + d += 1U; + s += 1U; + cnt -= 1U; + } +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mem.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mem.h new file mode 100644 index 0000000..4da150e --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mem.h @@ -0,0 +1,48 @@ +/******************************************************************************/ +/** +* Copyright (c) 2015 - 2020 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* @file xil_mem.h +* +* @addtogroup common_mem_operation_api Customized APIs for Memory Operations +* +* The xil_mem.h file contains prototype for functions related +* to memory operations. These APIs are applicable for all processors supported +* by Xilinx. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.1   nsk      11/07/16 First release.
+* 7.0   mus      01/07/19 Add cpp extern macro
+*
+* 
+* +*****************************************************************************/ +#ifndef XIL_MEM_H /* prevent circular inclusions */ +#define XIL_MEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Function Prototypes *****************************/ + +void Xil_MemCpy(void* dst, const void* src, u32 cnt); + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MEM_H */ +/** +* @} End of "addtogroup common_mem_operation_api". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_misc_psreset_api.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_misc_psreset_api.c new file mode 100644 index 0000000..10366fb --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_misc_psreset_api.c @@ -0,0 +1,436 @@ +/****************************************************************************** +* Copyright (c) 2013 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_misc_psreset_api.c +* +* This file contains the implementation of the reset sequence for various +* zynq ps devices like DDR,OCM,Slcr,Ethernet,Usb.. controllers. The reset +* sequence provided to the interfaces is based on the provision in +* slcr reset functional block. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00b kpc   03/07/13 First release
+* 5.4	pkp	  09/11/15 Change the description for XOcm_Remap function
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_misc_psreset_api.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +/** +* This function contains the implementation for ddr reset. +* +* +* @return N/A. +* +******************************************************************************/ +void XDdr_ResetHw(void) +{ + u32 RegVal; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert and deassert the ddr softreset bit */ + RegVal = Xil_In32(XDDRC_CTRL_BASEADDR); + RegVal &= (u32)(~XDDRPS_CTRL_RESET_MASK); + Xil_Out32(XDDRC_CTRL_BASEADDR,RegVal); + RegVal |= ((u32)XDDRPS_CTRL_RESET_MASK); + Xil_Out32(XDDRC_CTRL_BASEADDR,RegVal); + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for remapping the ocm memory region +* to postbootrom state. +* +* @return N/A. +* +******************************************************************************/ +void XOcm_Remap(void) +{ + u32 RegVal; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Map the ocm region to postbootrom state */ + RegVal = Xil_In32(XSLCR_OCM_CFG_ADDR); + RegVal = (RegVal & (u32)(~XSLCR_OCM_CFG_HIADDR_MASK)) | (u32)XSLCR_OCM_CFG_RESETVAL; + Xil_Out32(XSLCR_OCM_CFG_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for SMC reset sequence +* +* @param BaseAddress of the interface +* +* @return N/A. +* +******************************************************************************/ +void XSmc_ResetHw(u32 BaseAddress) +{ + u32 RegVal; + + /* Clear the interuupts */ + RegVal = Xil_In32(BaseAddress + XSMC_MEMC_CLR_CONFIG_OFFSET); + RegVal = RegVal | (u32)XSMC_MEMC_CLR_CONFIG_MASK; + Xil_Out32(BaseAddress + XSMC_MEMC_CLR_CONFIG_OFFSET, RegVal); + /* Clear the idle counter registers */ + Xil_Out32(BaseAddress + XSMC_REFRESH_PERIOD_0_OFFSET, 0x0U); + Xil_Out32(BaseAddress + XSMC_REFRESH_PERIOD_1_OFFSET, 0x0U); + /* Update the ecc registers with reset values */ + Xil_Out32(BaseAddress + XSMC_ECC_MEMCFG1_OFFSET, + XSMC_ECC_MEMCFG1_RESET_VAL); + Xil_Out32(BaseAddress + XSMC_ECC_MEMCMD1_OFFSET, + XSMC_ECC_MEMCMD1_RESET_VAL); + Xil_Out32(BaseAddress + XSMC_ECC_MEMCMD2_OFFSET, + XSMC_ECC_MEMCMD2_RESET_VAL); + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for updating the slcr mio registers +* with reset values +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_MioWriteResetValues(void) +{ + u32 i; + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Update all the MIO registers with reset values */ + for (i=0U; i<=1U;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_00_RESET_VAL); + } + for (; i<=8U;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_02_RESET_VAL); + } + for (; i<=53U ;i++) + { + Xil_Out32((XSLCR_MIO_PIN_00_ADDR + (i * 4U)), + XSLCR_MIO_PIN_00_RESET_VAL); + } + + +} + +/*****************************************************************************/ +/** +* This function contains the implementation for updating the slcr pll registers +* with reset values +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_PllWriteResetValues(void) +{ + + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + + /* update the pll control registers with reset values */ + Xil_Out32(XSLCR_IO_PLL_CTRL_ADDR, XSLCR_IO_PLL_CTRL_RESET_VAL); + Xil_Out32(XSLCR_ARM_PLL_CTRL_ADDR, XSLCR_ARM_PLL_CTRL_RESET_VAL); + Xil_Out32(XSLCR_DDR_PLL_CTRL_ADDR, XSLCR_DDR_PLL_CTRL_RESET_VAL); + /* update the pll config registers with reset values */ + Xil_Out32(XSLCR_IO_PLL_CFG_ADDR, XSLCR_IO_PLL_CFG_RESET_VAL); + Xil_Out32(XSLCR_ARM_PLL_CFG_ADDR, XSLCR_ARM_PLL_CFG_RESET_VAL); + Xil_Out32(XSLCR_DDR_PLL_CFG_ADDR, XSLCR_DDR_PLL_CFG_RESET_VAL); + /* update the clock control registers with reset values */ + Xil_Out32(XSLCR_ARM_CLK_CTRL_ADDR, XSLCR_ARM_CLK_CTRL_RESET_VAL); + Xil_Out32(XSLCR_DDR_CLK_CTRL_ADDR, XSLCR_DDR_CLK_CTRL_RESET_VAL); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for disabling the level shifters +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_DisableLevelShifters(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Disable the level shifters */ + RegVal = Xil_In32(XSLCR_LVL_SHFTR_EN_ADDR); + RegVal = RegVal & (u32)(~XSLCR_LVL_SHFTR_EN_MASK); + Xil_Out32(XSLCR_LVL_SHFTR_EN_ADDR, RegVal); + +} +/*****************************************************************************/ +/** +* This function contains the implementation for OCM software reset from the +* slcr +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_OcmReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_OCM_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_OCM_RST_CTRL_VAL); + Xil_Out32(XSLCR_OCM_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_OCM_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_OCM_RST_CTRL_VAL); + Xil_Out32(XSLCR_OCM_RST_CTRL_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for Ethernet software reset from +* the slcr +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_EmacPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_GEM_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_GEM_RST_CTRL_VAL); + Xil_Out32(XSLCR_GEM_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_GEM_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_GEM_RST_CTRL_VAL); + Xil_Out32(XSLCR_GEM_RST_CTRL_ADDR, RegVal); +} + +/*****************************************************************************/ +/** +* This function contains the implementation for USB software reset from the +* slcr +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_UsbPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_USB_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_USB_RST_CTRL_VAL); + Xil_Out32(XSLCR_USB_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_USB_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_USB_RST_CTRL_VAL); + Xil_Out32(XSLCR_USB_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for QSPI software reset from the +* slcr +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_QspiPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_LQSPI_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_QSPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_LQSPI_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_LQSPI_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_QSPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_LQSPI_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for SPI software reset from the +* slcr +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_SpiPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_SPI_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_SPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_SPI_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_SPI_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_SPI_RST_CTRL_VAL); + Xil_Out32(XSLCR_SPI_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for i2c software reset from the slcr +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_I2cPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_I2C_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_I2C_RST_CTRL_VAL); + Xil_Out32(XSLCR_I2C_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_I2C_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_I2C_RST_CTRL_VAL); + Xil_Out32(XSLCR_I2C_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for UART software reset from the +* slcr +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_UartPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_UART_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_UART_RST_CTRL_VAL); + Xil_Out32(XSLCR_UART_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_UART_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_UART_RST_CTRL_VAL); + Xil_Out32(XSLCR_UART_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for CAN software reset from slcr +* registers +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_CanPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_CAN_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_CAN_RST_CTRL_VAL); + Xil_Out32(XSLCR_CAN_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_CAN_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_CAN_RST_CTRL_VAL); + Xil_Out32(XSLCR_CAN_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for SMC software reset from the slcr +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_SmcPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_SMC_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_SMC_RST_CTRL_VAL); + Xil_Out32(XSLCR_SMC_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_SMC_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_SMC_RST_CTRL_VAL); + Xil_Out32(XSLCR_SMC_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for DMA controller software reset +* from the slcr +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_DmaPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_DMAC_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_DMAC_RST_CTRL_VAL); + Xil_Out32(XSLCR_DMAC_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_DMAC_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_DMAC_RST_CTRL_VAL); + Xil_Out32(XSLCR_DMAC_RST_CTRL_ADDR, RegVal); +} +/*****************************************************************************/ +/** +* This function contains the implementation for Gpio AMBA software reset from +* the slcr +* +* @return N/A. +* +******************************************************************************/ +void XSlcr_GpioPsReset(void) +{ + u32 RegVal; + /* Unlock the slcr register access lock */ + Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE); + /* Assert the reset */ + RegVal = Xil_In32(XSLCR_GPIO_RST_CTRL_ADDR); + RegVal = RegVal | ((u32)XSLCR_GPIO_RST_CTRL_VAL); + Xil_Out32(XSLCR_GPIO_RST_CTRL_ADDR, RegVal); + /* Release the reset */ + RegVal = Xil_In32(XSLCR_GPIO_RST_CTRL_ADDR); + RegVal = RegVal & (u32)(~XSLCR_GPIO_RST_CTRL_VAL); + Xil_Out32(XSLCR_GPIO_RST_CTRL_ADDR, RegVal); +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_misc_psreset_api.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_misc_psreset_api.h new file mode 100644 index 0000000..878d575 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_misc_psreset_api.h @@ -0,0 +1,261 @@ +/****************************************************************************** +* Copyright (c) 2013 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xil_misc_psreset_api.h +* +* This file contains the various register definitions and function prototypes for +* implementing the reset functionality of zynq ps devices +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00b kpc 03/07/13 First release. +*
+* +******************************************************************************/ + +#ifndef XIL_MISC_RESET_H /* prevent circular inclusions */ +#define XIL_MISC_RESET_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** + *@cond nocomments + */ + +#define XDDRC_CTRL_BASEADDR 0xF8006000U +#define XSLCR_BASEADDR 0xF8000000U +/**< OCM configuration register */ +#define XSLCR_OCM_CFG_ADDR (XSLCR_BASEADDR + 0x00000910U) +/**< SLCR unlock register */ +#define XSLCR_UNLOCK_ADDR (XSLCR_BASEADDR + 0x00000008U) +/**< SLCR GEM0 rx clock control register */ +#define XSLCR_GEM0_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000138U) +/**< SLCR GEM1 rx clock control register */ +#define XSLCR_GEM1_RCLK_CTRL_ADDR (XSLCR_BASEADDR + 0x0000013CU) +/**< SLCR GEM0 clock control register */ +#define XSLCR_GEM0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000140U) +/**< SLCR GEM1 clock control register */ +#define XSLCR_GEM1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000144U) +/**< SLCR SMC clock control register */ +#define XSLCR_SMC_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000148U) +/**< SLCR GEM reset control register */ +#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U) +/**< SLCR USB0 clock control register */ +#define XSLCR_USB0_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000130U) +/**< SLCR USB1 clock control register */ +#define XSLCR_USB1_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000134U) +/**< SLCR USB1 reset control register */ +#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U) +/**< SLCR SMC reset control register */ +#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U) +/**< SLCR Level shifter enable register */ +#define XSLCR_LVL_SHFTR_EN_ADDR (XSLCR_BASEADDR + 0x00000900U) +/**< SLCR ARM pll control register */ +#define XSLCR_ARM_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000100U) +/**< SLCR DDR pll control register */ +#define XSLCR_DDR_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000104U) +/**< SLCR IO pll control register */ +#define XSLCR_IO_PLL_CTRL_ADDR (XSLCR_BASEADDR + 0x00000108U) +/**< SLCR ARM pll configuration register */ +#define XSLCR_ARM_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000110U) +/**< SLCR DDR pll configuration register */ +#define XSLCR_DDR_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000114U) +/**< SLCR IO pll configuration register */ +#define XSLCR_IO_PLL_CFG_ADDR (XSLCR_BASEADDR + 0x00000118U) +/**< SLCR ARM clock control register */ +#define XSLCR_ARM_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000120U) +/**< SLCR DDR clock control register */ +#define XSLCR_DDR_CLK_CTRL_ADDR (XSLCR_BASEADDR + 0x00000124U) +/**< SLCR MIO pin address register */ +#define XSLCR_MIO_PIN_00_ADDR (XSLCR_BASEADDR + 0x00000700U) +/**< SLCR DMAC reset control address register */ +#define XSLCR_DMAC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000020CU) +/**< SLCR USB reset control address register */ +/*#define XSLCR_USB_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000210U)*/ +/**< SLCR GEM reset control address register */ +/*#define XSLCR_GEM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000214U)*/ +/**< SLCR SDIO reset control address register */ +#define XSLCR_SDIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000218U) +/**< SLCR SPI reset control address register */ +#define XSLCR_SPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000021CU) +/**< SLCR CAN reset control address register */ +#define XSLCR_CAN_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000220U) +/**< SLCR I2C reset control address register */ +#define XSLCR_I2C_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000224U) +/**< SLCR UART reset control address register */ +#define XSLCR_UART_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000228U) +/**< SLCR GPIO reset control address register */ +#define XSLCR_GPIO_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x0000022CU) +/**< SLCR LQSPI reset control address register */ +#define XSLCR_LQSPI_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000230U) +/**< SLCR SMC reset control address register */ +/*#define XSLCR_SMC_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000234U)*/ +/**< SLCR OCM reset control address register */ +#define XSLCR_OCM_RST_CTRL_ADDR (XSLCR_BASEADDR + 0x00000238U) + +/**< SMC mem controller clear config register */ +#define XSMC_MEMC_CLR_CONFIG_OFFSET 0x0000000CU +/**< SMC idlecount configuration register */ +#define XSMC_REFRESH_PERIOD_0_OFFSET 0x00000020U +#define XSMC_REFRESH_PERIOD_1_OFFSET 0x00000024U +/**< SMC ECC configuration register */ +#define XSMC_ECC_MEMCFG1_OFFSET 0x00000404U +/**< SMC ECC command 1 register */ +#define XSMC_ECC_MEMCMD1_OFFSET 0x00000404U +/**< SMC ECC command 2 register */ +#define XSMC_ECC_MEMCMD2_OFFSET 0x00000404U + +/**< SLCR unlock code */ +#define XSLCR_UNLOCK_CODE 0x0000DF0DU + +/**< SMC mem clear configuration mask */ +#define XSMC_MEMC_CLR_CONFIG_MASK 0x000005FU +/**< SMC ECC memconfig 1 reset value */ +#define XSMC_ECC_MEMCFG1_RESET_VAL 0x0000043U +/**< SMC ECC memcommand 1 reset value */ +#define XSMC_ECC_MEMCMD1_RESET_VAL 0x01300080U +/**< SMC ECC memcommand 2 reset value */ +#define XSMC_ECC_MEMCMD2_RESET_VAL 0x01E00585U + +/**< DDR controller reset bit mask */ +#define XDDRPS_CTRL_RESET_MASK 0x00000001U +/**< SLCR OCM configuration reset value*/ +#define XSLCR_OCM_CFG_RESETVAL 0x00000008U +/**< SLCR OCM bank selection mask*/ +#define XSLCR_OCM_CFG_HIADDR_MASK 0x0000000FU +/**< SLCR level shifter enable mask*/ +#define XSLCR_LVL_SHFTR_EN_MASK 0x0000000FU + +/**< SLCR PLL register reset values */ +#define XSLCR_ARM_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_DDR_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_IO_PLL_CTRL_RESET_VAL 0x0001A008U +#define XSLCR_ARM_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_DDR_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_IO_PLL_CFG_RESET_VAL 0x00177EA0U +#define XSLCR_ARM_CLK_CTRL_RESET_VAL 0x1F000400U +#define XSLCR_DDR_CLK_CTRL_RESET_VAL 0x18400003U + +/**< SLCR MIO register default values */ +#define XSLCR_MIO_PIN_00_RESET_VAL 0x00001601U +#define XSLCR_MIO_PIN_02_RESET_VAL 0x00000601U + +/**< SLCR Reset control registers default values */ +#define XSLCR_DMAC_RST_CTRL_VAL 0x00000001U +#define XSLCR_GEM_RST_CTRL_VAL 0x000000F3U +#define XSLCR_USB_RST_CTRL_VAL 0x00000003U +#define XSLCR_I2C_RST_CTRL_VAL 0x00000003U +#define XSLCR_SPI_RST_CTRL_VAL 0x0000000FU +#define XSLCR_UART_RST_CTRL_VAL 0x0000000FU +#define XSLCR_QSPI_RST_CTRL_VAL 0x00000003U +#define XSLCR_GPIO_RST_CTRL_VAL 0x00000001U +#define XSLCR_SMC_RST_CTRL_VAL 0x00000003U +#define XSLCR_OCM_RST_CTRL_VAL 0x00000001U +#define XSLCR_SDIO_RST_CTRL_VAL 0x00000033U +#define XSLCR_CAN_RST_CTRL_VAL 0x00000003U + +/** + *@endcond + */ + +/**************************** Type Definitions *******************************/ + +/* the following data type is used to hold a null terminated version string + * consisting of the following format, "X.YYX" + */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ +/* + * Performs reset operation to the ddr interface + */ +void XDdr_ResetHw(void); +/* + * Map the ocm region to post bootrom state + */ +void XOcm_Remap(void); +/* + * Performs the smc interface reset + */ +void XSmc_ResetHw(u32 BaseAddress); +/* + * updates the MIO registers with reset values + */ +void XSlcr_MioWriteResetValues(void); +/* + * updates the PLL and clock registers with reset values + */ +void XSlcr_PllWriteResetValues(void); +/* + * Disables the level shifters + */ +void XSlcr_DisableLevelShifters(void); +/* + * provides softreset to the GPIO interface + */ +void XSlcr_GpioPsReset(void); +/* + * provides softreset to the DMA interface + */ +void XSlcr_DmaPsReset(void); +/* + * provides softreset to the SMC interface + */ +void XSlcr_SmcPsReset(void); +/* + * provides softreset to the CAN interface + */ +void XSlcr_CanPsReset(void); +/* + * provides softreset to the Uart interface + */ +void XSlcr_UartPsReset(void); +/* + * provides softreset to the I2C interface + */ +void XSlcr_I2cPsReset(void); +/* + * provides softreset to the SPI interface + */ +void XSlcr_SpiPsReset(void); +/* + * provides softreset to the QSPI interface + */ +void XSlcr_QspiPsReset(void); +/* + * provides softreset to the USB interface + */ +void XSlcr_UsbPsReset(void); +/* + * provides softreset to the GEM interface + */ +void XSlcr_EmacPsReset(void); +/* + * provides softreset to the OCM interface + */ +void XSlcr_OcmReset(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_MISC_RESET_H */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mmu.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mmu.c new file mode 100644 index 0000000..85a1af4 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mmu.c @@ -0,0 +1,202 @@ +/****************************************************************************** +* Copyright (c) 2012 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xil_mmu.c +* +* This file provides APIs for enabling/disabling MMU and setting the memory +* attributes for sections, in the MMU translation table. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  01/12/12 Initial version
+* 3.05a asa  03/10/12 Modified the Xil_EnableMMU to invalidate the caches
+*		      before enabling back.
+* 3.05a asa  04/15/12 Modified the Xil_SetTlbAttributes routine so that
+*		      translation table and branch predictor arrays are
+*		      invalidated, D-cache flushed before the attribute
+*		      change is applied. This is done so that the user
+*		      need not call Xil_DisableMMU before calling
+*		      Xil_SetTlbAttributes.
+* 3.10a  srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      'xil_errata.h' for errata description
+* 3.11a  asa 09/23/13 Modified Xil_SetTlbAttributes to flush the complete
+*			 D cache after the translation table update. Removed the
+*			 redundant TLB invalidation in the same API at the beginning.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+*                     It fixes CR#1008309.
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_cache.h" +#include "xpseudo_asm.h" +#include "xil_types.h" +#include "xil_mmu.h" +#include "xil_errata.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ +#define ARM_AR_MEM_TTB_SECT_SIZE 1024*1024 +#define ARM_AR_MEM_TTB_SECT_SIZE_MASK (~(ARM_AR_MEM_TTB_SECT_SIZE-1UL)) +/************************** Variable Definitions *****************************/ + +extern u32 MMUTable; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* @brief This function sets the memory attributes for a section covering 1MB +* of memory in the translation table. +* +* @param Addr: 32-bit address for which memory attributes need to be set. +* @param attrib: Attribute for the given memory region. xil_mmu.h contains +* definitions of commonly used memory attributes which can be +* utilized for this function. +* +* +* @return None. +* +* @note The MMU or D-cache does not need to be disabled before changing a +* translation table entry. +* +******************************************************************************/ +void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib) +{ + u32 *ptr; + u32 section; + + section = Addr / 0x100000U; + ptr = &MMUTable; + ptr += section; + if(ptr != NULL) { + *ptr = (Addr & 0xFFF00000U) | attrib; + } + + Xil_DCacheFlush(); + + mtcp(XREG_CP15_INVAL_UTLB_UNLOCKED, 0U); + /* Invalidate all branch predictors */ + mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0U); + + dsb(); /* ensure completion of the BP and TLB invalidation */ + isb(); /* synchronize context on this processor */ +} + +/*****************************************************************************/ +/** +* @brief Enable MMU for cortex A9 processor. This function invalidates the +* instruction and data caches, and then enables MMU. +* +* @return None. +* +******************************************************************************/ +void Xil_EnableMMU(void) +{ + u32 Reg; + Xil_DCacheInvalidate(); + Xil_ICacheInvalidate(); + +#ifdef __GNUC__ + Reg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, Reg); +#else + { volatile register u32 Cp15Reg __asm(XREG_CP15_SYS_CONTROL); + Reg = Cp15Reg; } +#endif + Reg |= (u32)0x05U; + mtcp(XREG_CP15_SYS_CONTROL, Reg); + + dsb(); + isb(); +} + +/*****************************************************************************/ +/** +* @brief Disable MMU for Cortex A9 processors. This function invalidates +* the TLBs, Branch Predictor Array and flushed the D Caches before +* disabling the MMU. +* +* @return None. +* +* @note When the MMU is disabled, all the memory accesses are treated as +* strongly ordered. +******************************************************************************/ +void Xil_DisableMMU(void) +{ + u32 Reg; + + mtcp(XREG_CP15_INVAL_UTLB_UNLOCKED, 0U); + mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0U); + Xil_DCacheFlush(); + +#ifdef __GNUC__ + Reg = mfcp(XREG_CP15_SYS_CONTROL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_SYS_CONTROL, Reg); +#else + { volatile register u32 Cp15Reg __asm(XREG_CP15_SYS_CONTROL); + Reg = Cp15Reg; } +#endif + Reg &= (u32)(~0x05U); +#ifdef CONFIG_ARM_ERRATA_794073 + /* Disable Branch Prediction */ + Reg &= (u32)(~0x800U); +#endif + mtcp(XREG_CP15_SYS_CONTROL, Reg); +} + +/*****************************************************************************/ +/** +* @brief Memory mapping for Cortex A9 processor. +* +* @param PhysAddr is physical address. +* @param size is size of region. +* @param flags is flags used to set translation table. +* +* @return Pointer to virtual address. +* +* @note: Previously this was implemented in libmetal. Move to embeddedsw as this +* functionality is specific to A9 processor. +* +******************************************************************************/ +void* Xil_MemMap(UINTPTR PhysAddr, size_t size, u32 flags) +{ + u32 Sectionoffset; + u32 Ttbaddr; + + if (!flags) + return (void*)PhysAddr; + + /* Ensure alignment on a section boundary */ + PhysAddr &= ARM_AR_MEM_TTB_SECT_SIZE_MASK; + + /* Loop through entire region of memory (one MMU section at a time). + Each section requires a TTB entry. */ + for (Sectionoffset = 0; Sectionoffset < size; + Sectionoffset += ARM_AR_MEM_TTB_SECT_SIZE) { + /* Calculate translation table entry for this memory section */ + Ttbaddr = (PhysAddr + Sectionoffset); + + /* Write translation table entry value to entry address */ + Xil_SetTlbAttributes(Ttbaddr, flags); + } + return (void*)PhysAddr; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mmu.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mmu.h new file mode 100644 index 0000000..d21e13a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_mmu.h @@ -0,0 +1,92 @@ +/****************************************************************************** +* Copyright (c) 2012 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xil_mmu.h +* +* @addtogroup a9_mmu_apis Cortex A9 Processor MMU Functions +* +* MMU functions equip users to enable MMU, disable MMU and modify default +* memory attributes of MMU table as per the need. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  01/12/12 Initial version
+* 4.2	pkp	 07/21/14 Included xil_types.h file which contains definition for
+*					  u32 which resolves issue of CR#805869
+* 5.4	pkp	 23/11/15 Added attribute definitions for Xil_SetTlbAttributes API
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef XIL_MMU_H +#define XIL_MMU_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/* Memory type */ +#define NORM_NONCACHE 0x11DE2 /* Normal Non-cacheable */ +#define STRONG_ORDERED 0xC02 /* Strongly ordered */ +#define DEVICE_MEMORY 0xC06 /* Device memory */ +#define RESERVED 0x0 /* reserved memory */ + +/* Normal write-through cacheable shareable */ +#define NORM_WT_CACHE 0x16DEA + +/* Normal write back cacheable shareable */ +#define NORM_WB_CACHE 0x15DE6 + +/* shareability attribute */ +#define SHAREABLE (0x1 << 16) +#define NON_SHAREABLE (~(0x1 << 16)) + +/* Execution type */ +#define EXECUTE_NEVER ((0x1 << 4) | (0x1 << 0)) + +/** +*@endcond +*/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib); +void Xil_EnableMMU(void); +void Xil_DisableMMU(void); +void* Xil_MemMap(UINTPTR PhysAddr, size_t size, u32 flags); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_MMU_H */ +/** +* @} End of "addtogroup a9_mmu_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_printf.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_printf.c new file mode 100644 index 0000000..bf104fd --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_printf.c @@ -0,0 +1,447 @@ +/****************************************************************************** +* Copyright (c) 1995 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +*******************************************************************************/ +/*---------------------------------------------------*/ +/* Modified from : */ +/* Public Domain version of printf */ +/* Rud Merriam, Compsult, Inc. Houston, Tx. */ +/* For Embedded Systems Programming, 1991 */ +/* */ +/*---------------------------------------------------*/ +#include "xil_printf.h" +#include "xil_types.h" +#include "xil_assert.h" +#include +#include +#include + +static void padding( const s32 l_flag,const struct params_s *par); +static void outs(const charptr lp, struct params_s *par); +static s32 getnum( charptr* linep); + +typedef struct params_s { + s32 len; + s32 num1; + s32 num2; + char8 pad_character; + s32 do_padding; + s32 left_flag; + s32 unsigned_flag; +} params_t; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + + +/*---------------------------------------------------*/ +/* */ +/* This routine puts pad characters into the output */ +/* buffer. */ +/* */ +static void padding( const s32 l_flag, const struct params_s *par) +{ + s32 i; + + if ((par->do_padding != 0) && (l_flag != 0) && (par->len < par->num1)) { + i=(par->len); + for (; i<(par->num1); i++) { +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( par->pad_character); +#endif + } + } +} + +/*---------------------------------------------------*/ +/* */ +/* This routine moves a string to the output buffer */ +/* as directed by the padding and positioning flags. */ +/* */ +static void outs(const charptr lp, struct params_s *par) +{ + charptr LocalPtr; + LocalPtr = lp; + /* pad on left if needed */ + if(LocalPtr != NULL) { + par->len = (s32)strlen( LocalPtr); + padding( !(par->left_flag), par); + /* Move string to the buffer */ + while (((*LocalPtr) != (char8)0) && ((par->num2) != 0)) { + (par->num2)--; +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte(*LocalPtr); +#endif + LocalPtr += 1; + } +} + + /* Pad on right if needed */ + /* CR 439175 - elided next stmt. Seemed bogus. */ + padding( par->left_flag, par); +} + +/*---------------------------------------------------*/ +/* */ +/* This routine moves a number to the output buffer */ +/* as directed by the padding and positioning flags. */ +/* */ + +static void outnum( const s32 n, const s32 base, struct params_s *par) +{ + s32 negative; + s32 i; + char8 outbuf[32]; + const char8 digits[] = "0123456789ABCDEF"; + u32 num; + for(i = 0; i<32; i++) { + outbuf[i] = '0'; + } + + /* Check if number is negative */ + if ((par->unsigned_flag == 0) && (base == 10) && (n < 0L)) { + negative = 1; + num =(-(n)); + } + else{ + num = n; + negative = 0; + } + + /* Build number (backwards) in outbuf */ + i = 0; + do { + outbuf[i] = digits[(num % (u32)base)]; + i++; + num /= base; + } while (num > 0U); + + if (negative != 0) { + outbuf[i] = '-'; + i++; + } + + outbuf[i] = '\0'; + i--; + + /* Move the converted number to the buffer and */ + /* add in the padding where needed. */ + par->len = (s32)strlen(outbuf); + padding( !(par->left_flag), par); + while (&outbuf[i] >= outbuf) { +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( outbuf[i] ); +#endif + i--; +} + padding( par->left_flag, par); +} +/*---------------------------------------------------*/ +/* */ +/* This routine moves a 64-bit number to the output */ +/* buffer as directed by the padding and positioning */ +/* flags. */ +/* */ +#if defined (__aarch64__) || defined (__arch64__) +static void outnum1( const s64 n, const s32 base, params_t *par) +{ + s32 negative; + s32 i; + char8 outbuf[64]; + const char8 digits[] = "0123456789ABCDEF"; + u64 num; + for(i = 0; i<64; i++) { + outbuf[i] = '0'; + } + + /* Check if number is negative */ + if ((par->unsigned_flag == 0) && (base == 10) && (n < 0L)) { + negative = 1; + num =(-(n)); + } + else{ + num = (n); + negative = 0; + } + + /* Build number (backwards) in outbuf */ + i = 0; + do { + outbuf[i] = digits[(num % base)]; + i++; + num /= base; + } while (num > 0); + + if (negative != 0) { + outbuf[i] = '-'; + i++; + } + + outbuf[i] = '\0'; + i--; + + /* Move the converted number to the buffer and */ + /* add in the padding where needed. */ + par->len = (s32)strlen(outbuf); + padding( !(par->left_flag), par); + while (&outbuf[i] >= outbuf) { + outbyte( outbuf[i] ); + i--; +} + padding( par->left_flag, par); +} +#endif +/*---------------------------------------------------*/ +/* */ +/* This routine gets a number from the format */ +/* string. */ +/* */ +static s32 getnum(charptr* linep) +{ + s32 n = 0; + s32 ResultIsDigit = 0; + charptr cptr = *linep; + + while (cptr != NULL) { + ResultIsDigit = isdigit(((u8)*cptr)); + if (ResultIsDigit == 0) { + break; + } + n = ((n*10) + (((s32)*cptr) - (s32)'0')); + cptr += 1; + } + + *linep = ((charptr)(cptr)); + return(n); +} + +/*---------------------------------------------------*/ +/* */ +/* This routine operates just like a printf/sprintf */ +/* routine. It outputs a set of data under the */ +/* control of a formatting string. Not all of the */ +/* standard C format control are supported. The ones */ +/* provided are primarily those needed for embedded */ +/* systems work. Primarily the floating point */ +/* routines are omitted. Other formats could be */ +/* added easily by following the examples shown for */ +/* the supported formats. */ +/* */ + +/* void esp_printf( const func_ptr f_ptr, + const charptr ctrl1, ...) */ +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +void xil_printf( const char8 *ctrl1, ...){ + XPVXenConsole_Printf(ctrl1); +} +#else +void xil_printf( const char8 *ctrl1, ...) +{ + va_list argp; + + va_start(argp, ctrl1); + + xil_vprintf(ctrl1, argp); + + va_end(argp); +} +#endif + +/* This routine is equivalent to vprintf routine */ +void xil_vprintf(const char8 *ctrl1, va_list argp) +{ + s32 Check; +#if defined (__aarch64__) || defined (__arch64__) + s32 long_flag; +#endif + s32 dot_flag; + + params_t par; + + u8 ch; + char8 *ctrl = (char8 *)ctrl1; + + while ((ctrl != NULL) && (*ctrl != (char8)0)) { + + /* move format string chars to buffer until a */ + /* format control is found. */ + if (*ctrl != '%') { +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte(*ctrl); +#endif + ctrl += 1; + continue; + } + + /* initialize all the flags for this format. */ + dot_flag = 0; +#if defined (__aarch64__) || defined (__arch64__) + long_flag = 0; +#endif + par.unsigned_flag = 0; + par.left_flag = 0; + par.do_padding = 0; + par.pad_character = ' '; + par.num2=32767; + par.num1=0; + par.len=0; + + try_next: + if(ctrl != NULL) { + ctrl += 1; + } + if(ctrl != NULL) { + ch = (u8)*ctrl; + } else { + break; + } + + if (isdigit(ch) != 0) { + if (dot_flag != 0) { + par.num2 = getnum(&ctrl); + } + else { + if (ch == (u8)'0') { + par.pad_character = '0'; + } + if(ctrl != NULL) { + par.num1 = getnum(&ctrl); + } + par.do_padding = 1; + } + if(ctrl != NULL) { + ctrl -= 1; + } + goto try_next; + } + + switch (tolower(ch)) { + case '%': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( '%'); +#endif + Check = 1; + break; + + case '-': + par.left_flag = 1; + Check = 0; + break; + + case '.': + dot_flag = 1; + Check = 0; + break; + + case 'l': + #if defined (__aarch64__) || defined (__arch64__) + long_flag = 1; + #endif + Check = 0; + break; + + case 'u': + par.unsigned_flag = 1; + /* fall through */ + case 'i': + case 'd': + #if defined (__aarch64__) || defined (__arch64__) + if (long_flag != 0){ + outnum1((s64)va_arg(argp, s64), 10L, &par); + } + else { + outnum( va_arg(argp, s32), 10L, &par); + } + #else + outnum( va_arg(argp, s32), 10L, &par); + #endif + Check = 1; + break; + case 'p': + #if defined (__aarch64__) || defined (__arch64__) + par.unsigned_flag = 1; + outnum1((s64)va_arg(argp, s64), 16L, &par); + Check = 1; + break; + #endif + case 'X': + case 'x': + par.unsigned_flag = 1; + #if defined (__aarch64__) || defined (__arch64__) + if (long_flag != 0) { + outnum1((s64)va_arg(argp, s64), 16L, &par); + } + else { + outnum((s32)va_arg(argp, s32), 16L, &par); + } + #else + outnum((s32)va_arg(argp, s32), 16L, &par); + #endif + Check = 1; + break; + + case 's': + outs( va_arg( argp, char *), &par); + Check = 1; + break; + + case 'c': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( (char8)va_arg( argp, s32)); +#endif + Check = 1; + break; + + case '\\': + switch (*ctrl) { + case 'a': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( ((char8)0x07)); +#endif + break; + case 'h': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( ((char8)0x08)); +#endif + break; + case 'r': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( ((char8)0x0D)); +#endif + break; + case 'n': +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( ((char8)0x0D)); + outbyte( ((char8)0x0A)); +#endif + break; + default: +#if defined(STDOUT_BASEADDRESS) || defined(VERSAL_PLM) + outbyte( *ctrl); +#endif + break; + } + ctrl += 1; + Check = 0; + break; + + default: + Check = 1; + break; + } + if(Check == 1) { + if(ctrl != NULL) { + ctrl += 1; + } + continue; + } + goto try_next; + } +} +/*---------------------------------------------------*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_printf.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_printf.h new file mode 100644 index 0000000..062ad6b --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_printf.h @@ -0,0 +1,53 @@ +/****************************************************************************** +* Copyright (c) 1995 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +*******************************************************************************/ + #ifndef XIL_PRINTF_H + #define XIL_PRINTF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "xil_types.h" +#include "xparameters.h" +#include "bspconfig.h" +#if defined (__aarch64__) && HYP_GUEST && EL1_NONSECURE && XEN_USE_PV_CONSOLE +#include "xen_console.h" +#endif + +/*----------------------------------------------------*/ +/* Use the following parameter passing structure to */ +/* make xil_printf re-entrant. */ +/*----------------------------------------------------*/ + +struct params_s; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + +typedef char8* charptr; +typedef s32 (*func_ptr)(int c); + +/* */ + +void xil_printf( const char8 *ctrl1, ...); +void xil_vprintf(const char8 *ctrl1, va_list argp); +void print( const char8 *ptr); +extern void outbyte (char c); +extern char inbyte(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleepcommon.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleepcommon.c new file mode 100644 index 0000000..aba3a08 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleepcommon.c @@ -0,0 +1,85 @@ +/****************************************************************************** +* Copyright (c) 2017 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +*@file xil_sleepcommon.c +* +* This file contains the sleep API's +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.6 	srm  	 11/02/17 First release
+* 7.7	sk	 01/10/22 Typecast sleep function argument from unsigned
+* 			  int to u32 to fix misra_c_2012_directive_4_6
+* 			  violation.
+* 8.0	sk	 03/02/22 Update usleep argument type to fix misra_c_2012_
+* 			  directive_4_6 violation.
+* 
+******************************************************************************/ + + +/***************************** Include Files *********************************/ +#include "xil_io.h" +#include "sleep.h" + +/**************************** Constant Definitions *************************/ + + +/*****************************************************************************/ +/** +* +* This API gives delay in sec +* +* @param seconds - delay time in seconds +* +* @return none +* +* @note none +* +*****************************************************************************/ + void sleep(u32 seconds) + { +#if defined (ARMR5) + sleep_R5(seconds); +#elif defined (__aarch64__) || defined (ARMA53_32) + sleep_A53(seconds); +#elif defined (__MICROBLAZE__) + sleep_MB(seconds); +#else + sleep_A9(seconds); +#endif + + } + +/****************************************************************************/ +/** +* +* This API gives delay in usec +* +* @param useconds - delay time in useconds +* +* @return none +* +* @note none +* +*****************************************************************************/ + void usleep(ULONG useconds) + { +#if defined (ARMR5) + usleep_R5(useconds); +#elif defined (__aarch64__) || defined (ARMA53_32) + usleep_A53(useconds); +#elif defined (__MICROBLAZE__) + usleep_MB(useconds); +#else + usleep_A9(useconds); +#endif + + } diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleeptimer.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleeptimer.c new file mode 100644 index 0000000..2d3df6c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleeptimer.c @@ -0,0 +1,152 @@ +/****************************************************************************** +* Copyright (c) 2017 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +/*****************************************************************************/ +/** +* +* @file xil_sleeptimer.c +* +* This file provides the common helper routines for the sleep API's +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6	srm  10/18/17 First Release.
+* 6.6   srm  04/20/18 Fixed compilation warning in Xil_SleepTTCCommon API
+* 7.0   mus  03/27/19 Updated XTime_StartTTCTimer to skip IOU slcr address
+*                     space access, if processor is nonsecure and IOU slcr
+*                     address space is secure. CR#1015725.
+* 7.7	sk   01/10/22 Update values from signed to unsigned to fix
+* 		      misra_c_2012_rule_10_4 violation.
+* 7.7	sk   01/10/22 Add explicit parentheses for EL3==1 to fix
+* 		      misra_c_2012_rule_12_1 violation.
+* 7.7	sk   01/10/22 Add void argument to XTime_StartTTCTimer function to
+* 		      fix misra_c_2012_rule_8_2 violation.
+* 7.7	sk   01/10/22 Add braces for the if statement to make it a compound
+* 		      statement and fix misra_c_2012_rule_15_6 violation.
+*
+* 
+*****************************************************************************/ + +/**************************** Include Files ********************************/ + +#include "xil_io.h" +#include "xil_sleeptimer.h" +#include "xtime_l.h" + +/**************************** Constant Definitions *************************/ + + +/* Function definitions are applicable only when TTC3 is present*/ +#if defined (SLEEP_TIMER_BASEADDR) +/****************************************************************************/ +/** +* +* This is a helper function used by sleep/usleep APIs to +* have delay in sec/usec +* +* @param delay - delay time in seconds/micro seconds +* +* @param frequency - Number of counts per second/micro second +* +* @return none +* +* @note none +* +*****************************************************************************/ +void Xil_SleepTTCCommon(u32 delay, u64 frequency) +{ + u64 tEnd = 0U; + u64 tCur = 0U; + XCntrVal TimeHighVal = 0U; + XCntrVal TimeLowVal1 = 0U; + XCntrVal TimeLowVal2 = 0U; + + TimeLowVal1 = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET); + tEnd = (u64)TimeLowVal1 + ((u64)(delay) * frequency); + do + { + TimeLowVal2 = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET); + if (TimeLowVal2 < TimeLowVal1) { + TimeHighVal++; + } + TimeLowVal1 = TimeLowVal2; + tCur = (((u64) TimeHighVal) << XSLEEP_TIMER_REG_SHIFT) | + (u64)TimeLowVal2; + }while (tCur < tEnd); +} + + +/*****************************************************************************/ +/** +* +* This API starts the Triple Timer Counter +* +* @param none +* +* @return none +* +* @note none +* +*****************************************************************************/ +void XTime_StartTTCTimer(void) +{ + u32 TimerPrescalar; + u32 TimerCntrl; + +#if (defined (__aarch64__) && (EL3==1)) || (defined (ARMR5) && (PROCESSOR_ACCESS_VALUE & IOU_SLCR_TZ_MASK)) || defined (ARMA53_32) + u32 LpdRst; + +#if defined (versal) + u32 RstAddr = CRL_TTC_RST; + u32 RstMask = CRL_TTC_BASE_RST_MASK << XSLEEP_TTC_INSTANCE; +#else + u32 RstAddr = RST_LPD_IOU2; + u32 RstMask = RST_LPD_IOU2_TTC_BASE_RESET_MASK << XSLEEP_TTC_INSTANCE; +#endif + /* check if the timer is reset */ + LpdRst = XSleep_ReadCounterVal(RstAddr); + if ((LpdRst & RstMask) != 0U ) { + LpdRst = LpdRst & (~RstMask); + Xil_Out32(RstAddr, LpdRst); + } else { +#endif + TimerCntrl = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET); + /* check if Timer is disabled */ + if ((TimerCntrl & XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK) == 0U) { + TimerPrescalar = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET); + /* check if Timer is configured with proper functionalty for sleep */ + if ((TimerPrescalar & XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK) == 0U) { + return; + } + } +#if (defined (__aarch64__) && (EL3==1)) || (defined (ARMR5) && (PROCESSOR_ACCESS_VALUE & IOU_SLCR_TZ_MASK)) || defined (ARMA53_32) + } +#endif + /* Disable the timer to configure */ + TimerCntrl = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET); + TimerCntrl = TimerCntrl | XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK; + Xil_Out32(SLEEP_TIMER_BASEADDR + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET, + TimerCntrl); + /* Disable the prescalar */ + TimerPrescalar = XSleep_ReadCounterVal(SLEEP_TIMER_BASEADDR + + XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET); + TimerPrescalar = TimerPrescalar & (~XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK); + Xil_Out32(SLEEP_TIMER_BASEADDR + XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET, + TimerPrescalar); + /* Enable the Timer */ + TimerCntrl = TimerCntrl & (~XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK); + Xil_Out32(SLEEP_TIMER_BASEADDR + XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET, + TimerCntrl); +} +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleeptimer.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleeptimer.h new file mode 100644 index 0000000..b133eaf --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_sleeptimer.h @@ -0,0 +1,115 @@ +/****************************************************************************** +* Copyright (c) 2017 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_sleeptimer.h +* +* This header file contains ARM Cortex A53,A9,R5 specific sleep related APIs. +* For sleep related functions that can be used across all Xilinx supported +* processors, please use xil_sleeptimer.h. +* +* +*
+* MODIFICATION HISTORY :
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 6.6	srm  10/18/17 First Release.
+* 7.0   mus  01/07/19 Add cpp extern macro
+* 7.7	sk   01/10/22 Add explicit parentheses for EL3==1 to fix
+* 		      misra_c_2012_rule_12_1 violation.
+* 7.7	sk   01/10/22 Add void to XTime_StartTTCTimer function declaration
+* 		      to fix misra_c_2012_rule_8_2 violation.
+*
+* 
+*****************************************************************************/ + +/** + *@cond nocomments + */ +#ifndef XIL_SLEEPTIMER_H /* prevent circular inclusions */ +#define XIL_SLEEPTIMER_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files ********************************/ + +#include "xil_io.h" +#include "xparameters.h" +#include "bspconfig.h" + +/************************** Constant Definitions *****************************/ + +#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) +#define XSLEEP_TIMER_REG_SHIFT 32U +#define XSleep_ReadCounterVal Xil_In32 +#define XCntrVal u32 +#else +#define XSLEEP_TIMER_REG_SHIFT 16U +#define XSleep_ReadCounterVal Xil_In16 +#define XCntrVal u16 +#endif + +#if defined(ARMR5) || (defined (__aarch64__) && (EL3==1)) || defined (ARMA53_32) +#if defined (versal) +#define CRL_TTC_RST 0xFF5E0344U +#define CRL_TTC_BASE_RST_MASK 0x1U +#else +#define RST_LPD_IOU2 0xFF5E0238U +#define RST_LPD_IOU2_TTC_BASE_RESET_MASK 0x00000800U +#endif +#endif + +#if defined (SLEEP_TIMER_BASEADDR) +/** @name Register Map +* +* Register offsets from the base address of the TTC device +* +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_OFFSET 0x00000000U + /**< Clock Control Register */ + #define XSLEEP_TIMER_TTC_CNT_CNTRL_OFFSET 0x0000000CU + /**< Counter Control Register*/ + #define XSLEEP_TIMER_TTC_COUNT_VALUE_OFFSET 0x00000018U + /**< Current Counter Value */ +/* @} */ +/** @name Clock Control Register +* Clock Control Register definitions of TTC +* @{ +*/ + #define XSLEEP_TIMER_TTC_CLK_CNTRL_PS_EN_MASK 0x00000001U + /**< Prescale enable */ +/* @} */ +/** @name Counter Control Register +* Counter Control Register definitions of TTC +* @{ +*/ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_DIS_MASK 0x00000001U + /**< Disable the counter */ +#define XSLEEP_TIMER_TTC_CNT_CNTRL_RST_MASK 0x00000010U + /**< Reset counter */ +/* @} */ + +/**************************** Type Definitions *******************************/ +/** + *@endcond + */ +/************************** Function Prototypes ******************************/ + +void Xil_SleepTTCCommon(u32 delay, u64 frequency); +void XTime_StartTTCTimer(void); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_SLEEPTIMER_H */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_spinlock.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_spinlock.c new file mode 100644 index 0000000..e1b5240 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_spinlock.c @@ -0,0 +1,368 @@ +/****************************************************************************** +* Copyright (c) 2021 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_spinlock.c +* +* Implements a spinlocking mechanism using ARM load-exclusive and +* store-exclusive instructions. +* +* spinlocks in baremetal world are useful mainly for AMP kind of use cases +* where different applications run in different CPUs in a CPU cluster and +* they have a common resource to work with. +* A simple yet common example is: +* R5-0 and R5-1 have separate applications and at runtime they try to access a +* shared register space (GIC) or shared memory space. Mutual exclusion is +* really needed for such use cases. +* Similar use case applies for Zynq CortexA9-0 and CortesA9-1. +* +* The spinlock mechanism provided with this file is very simple to cater to +* baremetal world requirements. +* +* A) Unlike OS type of use cases, at any point of time, only a single lock +* can be used. There is no way in BM world we can support multiple locks +* at the same time. +* B) The spinlocking is available for ARM v7 (Cortex-R5 and Cortex-A9). +* C) Users need to provide a lock (essentially a shared address), and a flag +* (also a shared address) for spinlocking to work. These shared addresses +* must be agreed upon by apps running on both CPUs. Needless to say, +* the linker scripts must change accordingly so that apps running on both +* CPUs can have a shared DDR region from which address can be used for +* spinlocking. +* D) The address that is used for spinlocking and the address that is used +* as flag address must be in a memory region that is strongly-ordered +* or device memory. +* E) Like any similar standard use cases, one application running in any +* of the CPUs must create the spinlock address. It is advisable that the +* the same application must destroy or release the spinlock address, +* though nothing stops the other CPU in destroying and releasing the +* spinlock addresses. There has to be understanding between applications +* running on both the CPUs to ensure that correct ordering is followed. +* Once a spinlock is released, it spinlock APIs cannot be used anymore. +* F) Once a spinlock address is created it can be used any number of times +* to protect critical sections as long as a certain set of rules are +* followed and a certain set of sequences are followed. More about the +* sequences later in this description. +* G) To re-iterate, the spinlocking mechanism provided through this file is +* pretty rudimentary. Users can always improvise. The use case that +* the whole mechanism is trying to solve is: common register space +* being accesses in an AMP scenario by independent applications running +* at multiple CPUs. +* +* The usage of APIs provided in this file are summarized below. +* A) Applications running at both the CPUs ensure that they allocate shared +* memory space to be used for locking and flag maintenance. +* B) The memory allocated as shared should be of minimum size 1 MB. This +* limitation is because the way translation tables/memory map is setup +* for R5 or A9. In future, this limitation can be brought down 4 KB. +* C) The spinlock and the flag address must be uncached. Users need to c +* all Xilinx provided API Xil_SetTlbAttributes to mark the shared +* 1 MB memory space as strongly ordered or device memory. +* D) Both the applications must call the API Xil_InitializeSpinLock with +* the spinlock address, flag address and flag value to be used. Currently +* only one flag value is supported (i.e. XIL_SPINLOCK_ENABLE with +* a value of 1). +* Only if the Xil_InitializeSpinLock returns success, should they +* proceed to use Xil_SpinLock and Xil_SpinUnlock. +* F) Afterwards applications can start using the APIs Xil_SpinLock() and +* Xil_SpinUnlock() to protect the critical sections. +* G) It is highly suggested to use Xil_IsSpinLockEnabled() as a check +* before using Xil_SpinLock() or Xil_SpinUnlock(). Refer to the code +* snippet below. +* H) If spinlock is no more needed by an application, they can use the API +* Xil_ReleaseSpinLock(). +* I) Once a spinlock is created it can be used as many numbers of time as +* needed. +* +* A typical code snippet with R5 as an example and lock address falling +* in the 1 MB memory region (0x300000 to 0x400000) is given below. +* +* Code snippet for R5-0 (that runs first): +* int main() +* { +* u32 *sharedlockaddr = (int *)0x300008; +* u32 *sharedlockflagaddr = int *)0x30000C; +* Xil_SetTlbAttributes(0x300000,STRONG_ORDERD_SHARED | PRIV_RW_USER_RW); +* Xil_InitializeSpinLock((UINTPTR)sharedlockaddr,(UINTPTR)sharedlockflagaddr, +* XIL_SPINLOCK_ENABLE); +* .... +* .... +* if (Xil_IsSpinLockEnabled()) +* Xil_SpinLock(); +* // Critical Section +* .... +* .... +* if (Xil_IsSpinLockEnabled()) +* Xil_SpinUnlock(); +* ..... +* ..... +* Xil_ReleaseSpinLock(); +* } // End of main +* +* * Code snippet for R5-1 (that runs second): +* int main() +* { +* u32 *sharedlockaddr = (int *)0x300008; +* u32 *sharedlockflagaddr = int *)0x30000C; +* Xil_SetTlbAttributes(0x300000,STRONG_ORDERD_SHARED | PRIV_RW_USER_RW); +* Xil_InitializeSpinLock((UINTPTR)sharedlockaddr,(UINTPTR)sharedlockflagaddr, +* XIL_SPINLOCK_ENABLE); +* .... +* if (Xil_IsSpinLockEnabled()) +* Xil_SpinLock(); +* // Critical Section +* .... +* .... +* if (Xil_IsSpinLockEnabled()) +* Xil_SpinUnlock(); +* ..... +* ..... +* Xil_ReleaseSpinLock(); +* } // End of main +* +* Xil_SpinLock() and Xil_SpinLock() return XST_FAILURE if the spinlock +* is initialized. Instead of calling Xil_IsSpinLockEnabled before using +* Xil_SpinLock() or Xil_SpinLock(), users can also check the return +* value of Xil_SpinLock and Xil_SpinLock. If a lock is not initialized, +* Xil_SpinLock will just return failure and not perform load-exclusive +* operations. +* +* Guidelines on when to use the spinlocking mechanism in Xilinx baremetal +* environment: +* A) Spinlocking mechanism can only be used for Cortex-R5s (split mode) +* and Cortex-A9s (Zynq). +* B) In Cortex-R5 split mode or Cortex-A9 cluster, applications running on +* both the CPUs, by design should never be sharing the same peripheral. +* It is impossible to support such use cases reliably. +* Hence none of the peripheral drivers (except GIC driver) have +* spinlocking support added into their APIs. +* C) GIC register space is shared by both the CPUs (R5 split mode, A9s). +* The GIC driver APIs have spinlocking mechanism added to the relevant +* APIs. Users need to follow the guidelines stated earlier to enable +* the spinlocks and use them. +* It is really advisable to use spinlock mechanism for use cases where +* applications running on multiple CPUs can simultaneously access +* GIC register space through driver APIs. +* D) The spinlock mechanism can be used to protect any critical region +* implemented through shared memory space. +* +* IMPORTANT NOTE: Circular spinlocks are not allowed (as expected). +* Use case where an application calls Xil_SpinLock back to back without +* calling Xil_SpinUnlock in between will/may result in a deadlock +* condition. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 7.5 	asa      02/23/21 First release
+* 7.5   asa      04/28/21 Fixed bug Xil_IsSpinLockEnabled to avoid
+*                         dereferencing to address zero.
+* 7.7	sk	 01/10/22 Update values from signed to unsigned to fix
+* 			  misra_c_2012_rule_10_4 violation.
+* 
+* +******************************************************************************/ + + +/***************************** Include Files ********************************/ +#if !defined (__aarch64__) && defined(__GNUC__) && !defined(__clang__) +#include "xil_spinlock.h" + + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + + + +/************************** Variable Definitions ****************************/ +static UINTPTR Xil_Spinlock_Addr = 0x0; +static UINTPTR Xil_Spinlock_Flag_Addr = 0x0; + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* @brief Used at the beginning of a critical section. This API takes the +* lock using load-exclusive and store-exclusive operations. In +* case the lock is not available (being held by an application +* running at the other CPU and doing operations inside the +* critical section, the control will never go out from the API +* till the other CPU releases the lock. +* +* @param None. +* +* @return XST_FAILURE: If spinlock is not properly initialized. +* XST_SUCCESS: If the lock was successfully obtained. +* +* @note None. +* +*****************************************************************************/ +u32 Xil_SpinLock(void) +{ + UINTPTR lockaddr = Xil_Spinlock_Addr; + u32 LockTempVar; + + if (Xil_Spinlock_Addr == 0U) { + return XST_FAILURE; + } + + __asm__ __volatile__( + "1: ldrex %0, [%1] \n" + " teq %0, %3 \n" + " strexeq %0, %2, [%1] \n" + " teqeq %0, #0 \n" + " bne 1b \n" + " dmb \n" + : "=&r" (LockTempVar) + : "r" (lockaddr), "r"(XIL_SPINLOCK_LOCKVAL), "r"(XIL_SPINLOCK_RESETVAL) + : "cc"); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* @brief Used to release a lock previously held by calling Xil_SpinLock. +* +* @param None. +* +* @return XST_FAILURE: If spinlock is not properly initialized. +* XST_SUCCESS: If the lock was successfully obtained. +* +* @note None. +* +*****************************************************************************/ +u32 Xil_SpinUnlock(void) +{ + UINTPTR lockaddr = Xil_Spinlock_Addr; + + if (Xil_Spinlock_Addr == 0U) { + return XST_FAILURE; + } + __asm__ __volatile__( + "dmb \n" + "str %1, [%0] \n" + : + : "r" (lockaddr), "r" (XIL_SPINLOCK_RESETVAL) + : "cc"); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* @brief Used to initialize a spinlock. +* +* @param lockaddr: Address of the lock variable. The address must be in +* a shared memory region. +* lockflagaddr: Address of the flag variable. The address must be +* in a shared memory region. +* lockflag: The value of the flag. Currently only one value +* is supported, which is XIL_SPINLOCK_ENABLE. +* +* @return XST_SUCCESS, if the initialization succeeded. +* XST_FAILURE, if the initialization failed +* +* @note None. +* +*****************************************************************************/ +u32 Xil_InitializeSpinLock(UINTPTR lockaddr, UINTPTR lockflagaddr, + u32 lockflag) +{ + if (Xil_Spinlock_Flag_Addr == 0U) { + Xil_Spinlock_Flag_Addr = lockflagaddr; + if (*(u32 *)Xil_Spinlock_Flag_Addr == XIL_SPINLOCK_ENABLED) { + /* + * spinlock is already initialized by one of the CPUs, just update + * the local variable Xil_Spinlock_Addr with the passed address + * and dont write to the lock value as it might be currently + * getting used. + */ + /* + * Ensure to update the global variable Xil_Spinlock_Addr only + * if it is zero. A non-zero value may mean that there is something + * wrong. + */ + if (Xil_Spinlock_Addr == 0U) { + Xil_Spinlock_Addr = lockaddr; + } else { + /* + * May be spinlock is already initialized and the user has not + * called Xil_ReleaseSpinLock before calling Xil_InitializeSpinLock. + */ + return XST_FAILURE; + } + } else { + /* All good, do the necessary initializations */ + Xil_Spinlock_Addr = lockaddr; + *(u32 *)(Xil_Spinlock_Addr) = XIL_SPINLOCK_RESETVAL; + *(u32 *)(Xil_Spinlock_Flag_Addr) = lockflag; + } + return XST_SUCCESS; + } else { + /* + * Most probably spinlock is already initialized and the user has not + * called Xil_ReleaseSpinLock before calling Xil_InitializeSpinLock. + */ + return XST_FAILURE; + } +} + + +/****************************************************************************/ +/** +* @brief Used to release the spinlock. Typically called by the application +* once spinlock feature is no more required. +* +* @param None. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Xil_ReleaseSpinLock(void) +{ + Xil_Spinlock_Addr = 0; + Xil_Spinlock_Flag_Addr = 0; +} + +/****************************************************************************/ +/** +* @brief Used to know if the spinlock feature has been enabled. To ensure +* that spinlock feature does not break use cases where lock is +* not initialized, the application must call this API first to know +* if it can use spinlock. If this API returns non-zero value, an +* application should then use Xil_SpinLock or Xil_SpinUnlock. +* +* @param None +* +* @return Non-zero, if spinlock is already initialized and can be used. +* Zero, if spinlock is not initialized. +* +* @note +* +*****************************************************************************/ +u32 Xil_IsSpinLockEnabled(void) +{ + u32 retVal = FALSE; + + if (Xil_Spinlock_Flag_Addr != 0U) { + if (*(u32 *)(Xil_Spinlock_Flag_Addr) == XIL_SPINLOCK_ENABLED) { + retVal = TRUE; + } + } + return retVal; +} +#endif /* !(__aarch64__) && (__GNUC__) && !(__clang__)*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_spinlock.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_spinlock.h new file mode 100644 index 0000000..0cdf288 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_spinlock.h @@ -0,0 +1,80 @@ +/****************************************************************************** +* Copyright (c) 2021 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_spinlock.h +* +* This header file contains function prototypes to be used while using Xilinx +* spinlocking mechanism. +* Please refer to file header contents of xil_spinlock.c to understand in +* detail the spinlocking mechanism. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 7.5 	asa		 02/16/21 First release
+* 7.6	sk	 08/05/21 Add Boolean check and braces for Xil_IsSpinLockEnabled
+* 			  if condition to fix misrac violations.
+* 7.7	sk	 01/10/22 Update XIL_SPINLOCK_ENABLED from signed to unsigned to
+* 			  fix misra_c_2012_rule_10_4 violation.
+* 
+* +******************************************************************************/ + +#ifndef XIL_SPINLOCK_H /* prevent circular inclusions */ +#define XIL_SPINLOCK_H /* by using protection macros */ + +/***************************** Include Files ********************************/ +#include "xil_types.h" +#include "xstatus.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if !defined (__aarch64__) && defined(__GNUC__) && !defined(__clang__) +/************************** Function Prototypes *****************************/ +u32 Xil_SpinLock(void); +u32 Xil_SpinUnlock(void); +u32 Xil_InitializeSpinLock(UINTPTR lockaddr, UINTPTR lockflagaddr, + u32 lockflag); +void Xil_ReleaseSpinLock(void); +u32 Xil_IsSpinLockEnabled(void); + +/************************** MACRO Definitions ****************************/ +#define XIL_SPINLOCK_LOCKVAL 0x10203040 +#define XIL_SPINLOCK_RESETVAL 0x40302010 +#define XIL_SPINLOCK_ENABLE 0x17273747 +#define XIL_SPINLOCK_ENABLED 0x17273747U +/***************** Macros (Inline Functions) Definitions ********************/ + +#endif /* !(__aarch64__) && (__GNUC__) && !(__clang__)*/ +/***************************************************************************/ +#if !defined (__aarch64__) && defined(__GNUC__) && !defined(__clang__) +#define XIL_SPINLOCK() \ + if(Xil_IsSpinLockEnabled()!=(u32)0) { \ + Xil_SpinLock(); } +#else +#define XIL_SPINLOCK() +#endif /* !(__aarch64__) && (__GNUC__) && !(__clang__)*/ + +#if !defined (__aarch64__) && defined(__GNUC__) && !defined(__clang__) +#define XIL_SPINUNLOCK() \ + if(Xil_IsSpinLockEnabled()!=(u32)0) { \ + Xil_SpinUnlock(); } +#else +#define XIL_SPINUNLOCK() +#endif /* !(__aarch64__) && (__GNUC__) && !(__clang__)*/ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_SPINLOCK_H */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testcache.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testcache.c new file mode 100644 index 0000000..f101c14 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testcache.c @@ -0,0 +1,341 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testcache.c +* @addtogroup common_test_utils +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/28/09 Initial release
+* 4.1   asa  05/09/14 Ensured that the address uses for cache test is aligned
+*				      cache line.
+* 
+* +******************************************************************************/ +#ifdef __ARM__ +#include "xil_cache.h" +#include "xil_testcache.h" +#include "xil_types.h" +#include "xpseudo_asm.h" +#ifdef __aarch64__ +#include "xreg_cortexa53.h" +#else +#include "xreg_cortexr5.h" +#endif + +#include "xil_types.h" + +extern void xil_printf(const char8 *ctrl1, ...); + +#define DATA_LENGTH 128 + +#ifdef __aarch64__ +static INTPTR Data[DATA_LENGTH] __attribute__ ((aligned(64))); +#else +static INTPTR Data[DATA_LENGTH] __attribute__ ((aligned(32))); +#endif + + +/*****************************************************************************/ +/** +* +* @brief Perform DCache range related API test such as Xil_DCacheFlushRange +* and Xil_DCacheInvalidateRange. This test function writes a constant +* value to the Data array, flushes the range, writes a new value, then +* invalidates the corresponding range. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ +s32 Xil_TestDCacheRange(void) +{ + s32 Index; + s32 Status = 0; + u32 CtrlReg; + INTPTR Value; + + xil_printf("-- Cache Range Test --\n\r"); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A00505; + + xil_printf(" initialize Data done:\r\n"); + + Xil_DCacheFlushRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + xil_printf(" flush range done\r\n"); + + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0xA0A00505) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Flush worked\r\n"); + } + else { + xil_printf("Error: flush dcache range not working\r\n"); + } + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A0C505; + + + + Xil_DCacheFlushRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = Index + 3; + + Xil_DCacheInvalidateRange((INTPTR)Data, DATA_LENGTH * sizeof(INTPTR)); + + xil_printf(" invalidate dcache range done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0xA0A0A05; + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0xA0A0A05) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + + if (!Status) { + xil_printf(" Invalidate worked\r\n"); + } + else { + xil_printf("Error: Invalidate dcache range not working\r\n"); + } + xil_printf("-- Cache Range Test Complete --\r\n"); + return Status; + +} + +/*****************************************************************************/ +/** +* @brief Perform DCache all related API test such as Xil_DCacheFlush and +* Xil_DCacheInvalidate. This test function writes a constant value +* to the Data array, flushes the DCache, writes a new value, +* then invalidates the DCache. +* +* @return +* - 0 is returned for a pass +* - -1 is returned for a failure +*****************************************************************************/ +s32 Xil_TestDCacheAll(void) +{ + s32 Index; + s32 Status; + INTPTR Value; + u32 CtrlReg; + + xil_printf("-- Cache All Test --\n\r"); + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x50500A0A; + xil_printf(" initialize Data done:\r\n"); + + Xil_DCacheFlush(); + xil_printf(" flush all done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + + if (Value != 0x50500A0A) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Flush all worked\r\n"); + } + else { + xil_printf("Error: Flush dcache all not working\r\n"); + } + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x505FFA0A; + + Xil_DCacheFlush(); + + + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = Index + 3; + + Xil_DCacheInvalidate(); + + xil_printf(" invalidate all done\r\n"); + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + for (Index = 0; Index < DATA_LENGTH; Index++) + Data[Index] = 0x50CFA0A; + dsb(); + #ifdef __aarch64__ + CtrlReg = mfcp(SCTLR_EL3); + CtrlReg |= (XREG_CONTROL_DCACHE_BIT); + mtcp(SCTLR_EL3,CtrlReg); + #else + CtrlReg = mfcp(XREG_CP15_SYS_CONTROL); + CtrlReg |= (XREG_CP15_CONTROL_C_BIT); + mtcp(XREG_CP15_SYS_CONTROL, CtrlReg); + #endif + dsb(); + Status = 0; + + for (Index = 0; Index < DATA_LENGTH; Index++) { + Value = Data[Index]; + if (Value != 0x50CFA0A) { + Status = -1; + xil_printf("Data[%d] = %x\r\n", Index, Value); + break; + } + } + + if (!Status) { + xil_printf(" Invalidate all worked\r\n"); + } + else { + xil_printf("Error: Invalidate dcache all not working\r\n"); + } + + xil_printf("-- DCache all Test Complete --\n\r"); + + return Status; +} + +/*****************************************************************************/ +/** +* @brief Perform Xil_ICacheInvalidateRange() on a few function pointers. +* +* @return +* - 0 is returned for a pass +* +* @note The function will hang if it fails. +*****************************************************************************/ +s32 Xil_TestICacheRange(void) +{ + + Xil_ICacheInvalidateRange((INTPTR)Xil_TestICacheRange, 1024); + Xil_ICacheInvalidateRange((INTPTR)Xil_TestDCacheRange, 1024); + Xil_ICacheInvalidateRange((INTPTR)Xil_TestDCacheAll, 1024); + + xil_printf("-- Invalidate icache range done --\r\n"); + + return 0; +} + +/*****************************************************************************/ +/** +* @brief Perform Xil_ICacheInvalidate() on a few function pointers. +* +* @return +* - 0 is returned for a pass +* +* @note The function will hang if it fails. +*****************************************************************************/ +s32 Xil_TestICacheAll(void) +{ + Xil_ICacheInvalidate(); + xil_printf("-- Invalidate icache all done --\r\n"); + return 0; +} +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testcache.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testcache.h new file mode 100644 index 0000000..5798c21 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testcache.h @@ -0,0 +1,54 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testcache.h +* +* @addtogroup common_test_utils +*

Cache test

+* The xil_testcache.h file contains utility functions to test cache. +* +* @{ +*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  07/29/09 First release
+* 
+* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef XIL_TESTCACHE_H /* prevent circular inclusions */ +#define XIL_TESTCACHE_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern s32 Xil_TestDCacheRange(void); +extern s32 Xil_TestDCacheAll(void); +extern s32 Xil_TestICacheRange(void); +extern s32 Xil_TestICacheAll(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ + +/** + *@endcond + */ + +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testio.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testio.c new file mode 100644 index 0000000..c05acd9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testio.c @@ -0,0 +1,273 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testio.c +* @addtogroup common_test_utils +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_testio.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ +/************************** Function Prototypes *****************************/ + + + +/** + * + * Endian swap a 16-bit word. + * @param Data is the 16-bit word to be swapped. + * @return The endian swapped value. + * + */ +static u16 Swap16(u16 Data) +{ + return ((Data >> 8U) & 0x00FFU) | ((Data << 8U) & 0xFF00U); +} + +/** + * + * Endian swap a 32-bit word. + * @param Data is the 32-bit word to be swapped. + * @return The endian swapped value. + * + */ +static u32 Swap32(u32 Data) +{ + u16 Lo16; + u16 Hi16; + + u16 Swap16Lo; + u16 Swap16Hi; + + Hi16 = (u16)((Data >> 16U) & 0x0000FFFFU); + Lo16 = (u16)(Data & 0x0000FFFFU); + + Swap16Lo = Swap16(Lo16); + Swap16Hi = Swap16(Hi16); + + return (((u32)(Swap16Lo)) << 16U) | ((u32)Swap16Hi); +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide register IO test where the +* register is accessed using Xil_Out8 and Xil_In8, and comparing +* the written values by reading them back. +* +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writing the memory. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ + +s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value) +{ + u8 ValueIn; + s32 Index; + s32 Status = 0; + + for (Index = 0; Index < Length; Index++) { + Xil_Out8((INTPTR)Addr, Value); + + ValueIn = Xil_In8((INTPTR)Addr); + + if ((Value != ValueIn) && (Status == 0)) { + Status = -1; + break; + } + } + return Status; + +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide register IO test. Each location +* is tested by sequentially writing a 16-bit wide register, reading +* the register, and comparing value. This function tests three kinds +* of register IO functions, normal register IO, little-endian register +* IO, and big-endian register IO. When testing little/big-endian IO, +* the function performs the following sequence, Xil_Out16LE/Xil_Out16BE, +* Xil_In16, Compare In-Out values, Xil_Out16, Xil_In16LE/Xil_In16BE, +* Compare In-Out values. Whether to swap the read-in value before +* comparing is controlled by the 5th argument. +* +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writing the memory. +* @param Kind: Type of test. Acceptable values are: +* XIL_TESTIO_DEFAULT, XIL_TESTIO_LE, XIL_TESTIO_BE. +* @param Swap: indicates whether to byte swap the read-in value. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ + +s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap) +{ + u16 *TempAddr16; + u16 ValueIn = 0U; + s32 Index; + TempAddr16 = Addr; + Xil_AssertNonvoid(TempAddr16 != NULL); + + for (Index = 0; Index < Length; Index++) { + switch (Kind) { + case XIL_TESTIO_LE: + Xil_Out16LE((INTPTR)TempAddr16, Value); + break; + case XIL_TESTIO_BE: + Xil_Out16BE((INTPTR)TempAddr16, Value); + break; + default: + Xil_Out16((INTPTR)TempAddr16, Value); + break; + } + + ValueIn = Xil_In16((INTPTR)TempAddr16); + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap16(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + + /* second round */ + Xil_Out16((INTPTR)TempAddr16, Value); + + switch (Kind) { + case XIL_TESTIO_LE: + ValueIn = Xil_In16LE((INTPTR)TempAddr16); + break; + case XIL_TESTIO_BE: + ValueIn = Xil_In16BE((INTPTR)TempAddr16); + break; + default: + ValueIn = Xil_In16((INTPTR)TempAddr16); + break; + } + + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap16(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + TempAddr16 += sizeof(u16); + } + return 0; +} + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide register IO test. Each location +* is tested by sequentially writing a 32-bit wide register, reading +* the register, and comparing value. This function tests three kinds +* of register IO functions, normal register IO, little-endian register IO, +* and big-endian register IO. When testing little/big-endian IO, +* the function perform the following sequence, Xil_Out32LE/ +* Xil_Out32BE, Xil_In32, Compare, Xil_Out32, Xil_In32LE/Xil_In32BE, Compare. +* Whether to swap the read-in value *before comparing is controlled +* by the 5th argument. +* @param Addr: a pointer to the region of memory to be tested. +* @param Length: Length of the block. +* @param Value: constant used for writing the memory. +* @param Kind: type of test. Acceptable values are: +* XIL_TESTIO_DEFAULT, XIL_TESTIO_LE, XIL_TESTIO_BE. +* @param Swap: indicates whether to byte swap the read-in value. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +*****************************************************************************/ +s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap) +{ + u32 *TempAddr; + u32 ValueIn = 0U; + s32 Index; + TempAddr = Addr; + Xil_AssertNonvoid(TempAddr != NULL); + + for (Index = 0; Index < Length; Index++) { + switch (Kind) { + case XIL_TESTIO_LE: + Xil_Out32LE((INTPTR)TempAddr, Value); + break; + case XIL_TESTIO_BE: + Xil_Out32BE((INTPTR)TempAddr, Value); + break; + default: + Xil_Out32((INTPTR)TempAddr, Value); + break; + } + + ValueIn = Xil_In32((INTPTR)TempAddr); + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap32(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + + /* second round */ + Xil_Out32((INTPTR)TempAddr, Value); + + + switch (Kind) { + case XIL_TESTIO_LE: + ValueIn = Xil_In32LE((INTPTR)TempAddr); + break; + case XIL_TESTIO_BE: + ValueIn = Xil_In32BE((INTPTR)TempAddr); + break; + default: + ValueIn = Xil_In32((INTPTR)TempAddr); + break; + } + + if ((Kind != 0) && (Swap != 0)) { + ValueIn = Swap32(ValueIn); + } + + if (Value != ValueIn) { + return -1; + } + TempAddr += sizeof(u32); + } + return 0; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testio.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testio.h new file mode 100644 index 0000000..5a1bda3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testio.h @@ -0,0 +1,76 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testio.h +* +* @addtogroup common_test_utils Test Utilities for Memory and Caches +*

I/O test

+* The xil_testio.h file contains utility functions to test endian related memory +* IO functions. +* +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests +* are selected. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00 hbm  08/05/09 First release
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_TESTIO_H /* prevent circular inclusions */ +#define XIL_TESTIO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +#define XIL_TESTIO_DEFAULT 0 +#define XIL_TESTIO_LE 1 +#define XIL_TESTIO_BE 2 + +/** + *@endcond + */ + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +extern s32 Xil_TestIO8(u8 *Addr, s32 Length, u8 Value); +extern s32 Xil_TestIO16(u16 *Addr, s32 Length, u16 Value, s32 Kind, s32 Swap); +extern s32 Xil_TestIO32(u32 *Addr, s32 Length, u32 Value, s32 Kind, s32 Swap); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testmem.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testmem.c new file mode 100644 index 0000000..aaa0617 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testmem.c @@ -0,0 +1,1575 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testmem.c +* @addtogroup common_test_utils +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 7.5   mus  03/10/21 Added new set of Xil_TestMem32, Xil_TestMem16 and
+*                     Xil_TestMem8 APIs to support memory test for memory
+*                     regions mapped at extended addresses
+*                     (addresses > 4 GB). These new set of APIs would be
+*                     compiled only for 32 bit Microblaze processor, if
+*                     XPAR_MICROBLAZE_ADDR_SIZE is greater than 32.
+*                     It fixes CR#1089129.
+* 7.6   mus  07/29/21 Updated Xil_TestMem8 to fix issues reported by static
+*                     analysis tool. It fixes CR#1105956.
+* 7.7	sk   01/10/22 Remove commented macro to fix misra_c_2012_directive_4_4
+* 		      violation.
+* 7.7	sk   01/10/22 Modify operands to fix misra_c_2012_rule_10_1 violation.
+* 7.7	sk   01/10/22 Typecast to make the both left and right sides expressions
+* 		      of same type and fix misra_c_2012_rule_10_6 violation.
+* 7.7	sk   01/10/22 Modify varaiable name from I to i to fix misra_c_2012_rule_
+* 		      21_2 violation.
+* 7.7	sk   01/10/22 Remove arithematic operations on pointer varaible to fix
+* 		      misra_c_2012_rule_18_4 violation.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_testmem.h" +#include "xil_io.h" +#include "xil_assert.h" + +/************************** Constant Definitions ****************************/ +/************************** Function Prototypes *****************************/ + +static u32 RotateLeft(u32 Input, u8 Width); + +/* define ROTATE_RIGHT to give access to this functionality */ +#ifdef ROTATE_RIGHT +static u32 RotateRight(u32 Input, u8 Width); +#endif /* ROTATE_RIGHT */ + +#if defined(__MICROBLAZE__) && !defined(__arch64__) && (XPAR_MICROBLAZE_ADDR_SIZE > 32) + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide memory test. +* +* @param Addrlow: lower 32 bit address of memory to be tested. +* @param Addrhigh: upper 32 bit address of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem8(u32 Addrlow, u32 Addrhigh, u32 Words, u8 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u8 Val; + u8 WordMem8; + s32 Status = 0; + u64 Addr = (Addrlow + ((u64)Addrhigh << 32)); + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + + /* + * select the proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from XIL_TESTMEM_INIT_VALUE + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + sbea(Addr+I, Val); + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = XIL_TESTMEM_INIT_VALUE; + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = lbuea(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_BYTE; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + Val = (u8)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + for (I = 0U; I < NUM_OF_BITS_IN_BYTE; I++) { + /* write memory location */ + sbea(Addr+I, Val); + Val = (u8)RotateLeft(Val, 8U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u8)((u32)1 << j); + /* Read the values from each location that was written */ + for (I = 0U; I < NUM_OF_BITS_IN_BYTE; I++) { + /* read memory location */ + WordMem8 = lbuea(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val = (u8)RotateLeft(Val, NUM_OF_BITS_IN_BYTE); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking zeros test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_BYTE; j++) { + /* + * Generate an initial value for walking ones test to test + * for bad data bits + */ + Val = (u8) (~(1U << j)); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + for (I = 0U; I < NUM_OF_BITS_IN_BYTE; I++) { + /* write memory location */ + sbea(Addr+I, Val); + Val = ~((u8)RotateLeft(~Val, NUM_OF_BITS_IN_BYTE)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u8) (~(1U << j)); + /* Read the values from each location that was written */ + for (I = 0U; I < NUM_OF_BITS_IN_BYTE; I++) { + /* read memory location */ + WordMem8 = lbuea(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + + Val = ~((u8)RotateLeft(~Val, NUM_OF_BITS_IN_BYTE)); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + Val = (u8) (~((INTPTR) (Addr + I))); + sbea(Addr+I, Val); + } + + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = lbuea(Addr+I); + Val = (u8) (~((INTPTR) (Addr+I))); + if ((WordMem8 ^ Val) != 0x00U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u8)0) { + Val = 0xA5U; + } + else { + Val = Pattern; + } + /* + * Fill the memory with fixed Pattern + */ + for (I = 0U; I < Words; I++) { + /* write memory location */ + sbea(Addr+I, Val); + } + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (I = 0U; I < Words; I++) { + /* read memory location */ + WordMem8 = lbuea(Addr+I); + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide memory test. +* +* @param Addrlow: lower 32 bit address of memory to be tested. +* @param Addrhigh: upper 32 bit address of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant Pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem16(u32 Addrlow,u32 Addrhigh, u32 Words, u16 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u16 Val; + u16 WordMem16; + s32 Status = 0; + u64 Addr = (Addrlow + ((u64)Addrhigh << 32)); + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + + /* + * selectthe proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'XIL_TESTMEM_INIT_VALUE' + */ + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * Words);) { + /* write memory location */ + shea(Addr+I, Val); + Val++; + I = I + NUM_OF_BYTES_IN_HW; + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = XIL_TESTMEM_INIT_VALUE; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference val + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * Words);) { + /* read memory location */ + WordMem16 = lhuea(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val++; + I = I + NUM_OF_BYTES_IN_HW; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking ones test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_HW; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (u16)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * NUM_OF_BITS_IN_HW); ) { + /* write memory location */ + shea(Addr+I,Val); + Val = (u16)RotateLeft(Val, 16U); + I = I + NUM_OF_BYTES_IN_HW; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u16)((u32)1 << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * NUM_OF_BITS_IN_HW); ) { + /* read memory location */ + WordMem16 = lhuea(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = (u16)RotateLeft(Val, NUM_OF_BITS_IN_HW); + I = I + NUM_OF_BYTES_IN_HW; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking zeros test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_HW; j++) { + /* + * Generate an initial value for walking ones + * test to test for bad + * data bits + */ + + Val = ~(1U << j); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * NUM_OF_BITS_IN_HW);) { + shea(Addr+I, Val); + Val = ~((u16)RotateLeft(~Val, 16U)); + I = I + NUM_OF_BYTES_IN_HW; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = ~(1U << j); + /* Read the values from each location that was written */ + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * NUM_OF_BITS_IN_HW); ) { + WordMem16= lhuea(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u16)RotateLeft(~Val, NUM_OF_BITS_IN_HW)); + I = I + NUM_OF_BYTES_IN_HW; + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * Words);) { + /* write memory location */ + Val = (u16) (~((INTPTR)((Addr+I)))); + shea(Addr+I, Val); + I = I + NUM_OF_BYTES_IN_HW; + } + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_HW*Words); ) { + /* read memory location */ + WordMem16 = lhuea(Addr+I); + Val = (u16) (~((INTPTR) ((Addr+I)))); + if ((WordMem16 ^ Val) != 0x0000U) { + Status = -1; + goto End_Label; + } + I = I + NUM_OF_BYTES_IN_HW; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + if (Pattern == (u16)0) { + Val = 0xDEADU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed pattern + */ + + for (I = 0U; I < (2*Words);) { + /* write memory location */ + shea(Addr+I, Val); + I = I + NUM_OF_BYTES_IN_HW; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed pattern + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_HW * Words);) { + /* read memory location */ + WordMem16=lhuea(Addr+I); + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + I = I + NUM_OF_BYTES_IN_HW; + } + } +End_Label: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide memory test. +* +* @param Addrlow: lower 32 bit address of memory to be tested. +* @param Addrhigh: upper 32 bit address of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: test type selected. See xil_testmem.h for possible +* values. +* +* @return +* - 0 is returned for a pass +* - 1 is returned for a failure +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem32(u32 Addrlow, u32 Addrhigh, u32 Words, u32 Pattern, u8 Subtest) +{ + u32 I; + u32 j; + u32 Val; + u32 WordMem32; + s32 Status = 0; + u64 Addr = (Addrlow + ((u64)Addrhigh << 32)); + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= (u8)XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'XIL_TESTMEM_INIT_VALUE' + */ + for (I = 0U; I <(NUM_OF_BYTES_IN_WORD * Words);) { + swea(Addr+I, Val); + Val++; + I = I + NUM_OF_BYTES_IN_WORD; + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = XIL_TESTMEM_INIT_VALUE; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (I = 0U; I < ( NUM_OF_BYTES_IN_WORD * Words);) { + WordMem32 = lwea(Addr+I); + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val++; + I = I + NUM_OF_BYTES_IN_WORD; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_WORD; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (1U << j); + + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_WORD * NUM_OF_BITS_IN_WORD);) { + /* write memory location */ + swea(Addr+I, Val); + Val = (u32) RotateLeft(Val, NUM_OF_BITS_IN_WORD); + I = I + NUM_OF_BYTES_IN_WORD; + } + + /* + * Restore the reference 'val' to the + * initial value + */ + Val = 1U << j; + + /* Read the values from each location that was + * written */ + for (I = 0U; I < ((u32)32 * NUM_OF_BYTES_IN_WORD);) { + /* read memory location */ + + WordMem32 = lwea(Addr+I); + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val = (u32)RotateLeft(Val, NUM_OF_BITS_IN_WORD); + I = I + NUM_OF_BYTES_IN_WORD; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible + * initial test Patterns for walking zeros test + */ + + for (j = 0U; j < NUM_OF_BITS_IN_WORD; j++) { + + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = ~(1U << j); + + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (I = 0U; I < (NUM_OF_BITS_IN_WORD * NUM_OF_BYTES_IN_WORD);) { + /* write memory location */ + swea(Addr+I, Val); + Val = ~((u32)RotateLeft(~Val, NUM_OF_BITS_IN_WORD)); + I = I + NUM_OF_BYTES_IN_WORD; + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + + Val = ~(1U << j); + + /* Read the values from each location that was + * written */ + for (I = 0U; I < (NUM_OF_BITS_IN_WORD * NUM_OF_BYTES_IN_WORD);) { + /* read memory location */ + WordMem32 = lwea(Addr+I); + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u32)RotateLeft(~Val, NUM_OF_BITS_IN_WORD)); + I = I + NUM_OF_BYTES_IN_WORD; + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (I = 0U; I < (NUM_OF_BYTES_IN_WORD * Words);) { + /* write memory location */ + Val = (u32) (~((INTPTR) (Addr+I))); + swea(Addr+I, Val); + I = I + NUM_OF_BYTES_IN_WORD; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_WORD * Words);) { + /* Read the location */ + WordMem32 = lwea(Addr+I); + Val = (u32) (~((INTPTR) (Addr+I))); + + if ((WordMem32 ^ Val) != 0x00000000U) { + Status = -1; + goto End_Label; + } + I = I + NUM_OF_BYTES_IN_WORD; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u32)0) { + Val = 0xDEADBEEFU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed Pattern + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_WORD * Words);) { + /* write memory location */ + swea(Addr+I, Val); + I = I + NUM_OF_BYTES_IN_WORD; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (I = 0U; I < (NUM_OF_BYTES_IN_WORD * Words);) { + + /* read memory location */ + + WordMem32 = lwea(Addr+I); + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + I = I + NUM_OF_BYTES_IN_WORD; + } + } + +End_Label: + return Status; +} + +#else +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 32-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: test type selected. See xil_testmem.h for possible +* values. +* +* @return +* - 0 is returned for a pass +* - 1 is returned for a failure +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest) +{ + u32 i; + u32 j; + u32 Val; + u32 FirtVal; + u32 WordMem32; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= (u8)XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (i = 0U; i < Words; i++) { + Addr[i] = Val; + Val++; + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (i = 0U; i < Words; i++) { + WordMem32 = Addr[i]; + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < (u32)32; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (1UL << j); + + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (i = 0U; i < (u32)32; i++) { + /* write memory location */ + Addr[i] = Val; + Val = (u32) RotateLeft(Val, 32U); + } + + /* + * Restore the reference 'val' to the + * initial value + */ + Val = 1UL << j; + + /* Read the values from each location that was + * written */ + for (i = 0U; i < (u32)32; i++) { + /* read memory location */ + + WordMem32 = Addr[i]; + + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + + Val = (u32)RotateLeft(Val, 32U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible + * initial test Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)32; j++) { + + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = ~(1UL << j); + + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (i = 0U; i < (u32)32; i++) { + /* write memory location */ + Addr[i] = Val; + Val = ~((u32)RotateLeft(~Val, 32U)); + } + + /* + * Restore the reference 'Val' to the + * initial value + */ + + Val = ~(1UL << j); + + /* Read the values from each location that was + * written */ + for (i = 0U; i < (u32)32; i++) { + /* read memory location */ + WordMem32 = Addr[i]; + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u32)RotateLeft(~Val, 32U)); + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Val = ~(u32) (UINTPTR) &Addr[i]; + Addr[i] = Val; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (i = 0U; i < Words; i++) { + /* Read the location */ + WordMem32 = Addr[i]; + Val = ~(u32) (UINTPTR) &Addr[i]; + + if ((WordMem32 ^ Val) != 0x00000000U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u32)0) { + Val = 0xDEADBEEFU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed Pattern + */ + + for (i = 0U; i < Words; i++) { + /* write memory location */ + Addr[i] = Val; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (i = 0U; i < Words; i++) { + + /* read memory location */ + + WordMem32 = Addr[i]; + if (WordMem32 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 16-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant Pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest) +{ + u32 i; + u32 j; + u16 Val; + u16 FirtVal; + u16 WordMem16; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + /* + * selectthe proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Addr[i] = Val; + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference val + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem16 = Addr[i]; + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking ones test + */ + + for (j = 0U; j < (u32)16; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + + Val = (u16)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + + for (i = 0U; i < (u32)16; i++) { + /* write memory location */ + Addr[i] = Val; + Val = (u16)RotateLeft(Val, 16U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u16)((u32)1 << j); + /* Read the values from each location that was written */ + for (i = 0U; i < (u32)16; i++) { + /* read memory location */ + WordMem16 = Addr[i]; + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = (u16)RotateLeft(Val, 16U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)16; j++) { + /* + * Generate an initial value for walking ones + * test to test for bad + * data bits + */ + + Val = (u16) (~((u16)1U << j)); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + + for (i = 0U; i < (u32)16; i++) { + /* write memory location */ + Addr[i] = Val; + Val = ~((u16)RotateLeft(~((u32)Val), 16U)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u16) (~((u16)1U << j)); + /* Read the values from each location that was written */ + for (i = 0U; i < (u32)16; i++) { + /* read memory location */ + WordMem16 = Addr[i]; + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + Val = ~((u16)RotateLeft(~((u32)Val), 16U)); + } + + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Val = ~(u16) (UINTPTR) &Addr[i]; + Addr[i] = Val; + } + /* + * Check every word within the words + * of tested memory + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem16 = Addr[i]; + Val = ~(u16) (UINTPTR) &Addr[i]; + if ((WordMem16 ^ Val) != 0x0000U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + if (Pattern == (u16)0) { + Val = 0xDEADU; + } + else { + Val = Pattern; + } + + /* + * Fill the memory with fixed pattern + */ + + for (i = 0U; i < Words; i++) { + /* write memory location */ + Addr[i] = Val; + } + + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed pattern + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem16 = Addr[i]; + if (WordMem16 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} + + +/*****************************************************************************/ +/** +* +* @brief Perform a destructive 8-bit wide memory test. +* +* @param Addr: pointer to the region of memory to be tested. +* @param Words: length of the block. +* @param Pattern: constant used for the constant pattern test, if 0, +* 0xDEADBEEF is used. +* @param Subtest: type of test selected. See xil_testmem.h for possible +* values. +* +* @return +* - -1 is returned for a failure +* - 0 is returned for a pass +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** Width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*****************************************************************************/ +s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest) +{ + u32 i; + u32 j; + u8 Val; + u8 FirtVal; + u8 WordMem8; + s32 Status = 0; + + Xil_AssertNonvoid(Words != (u32)0); + Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST); + + /* + * variable initialization + */ + Val = XIL_TESTMEM_INIT_VALUE; + FirtVal = XIL_TESTMEM_INIT_VALUE; + + /* + * select the proper Subtest(s) + */ + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) { + /* + * Fill the memory with incrementing + * values starting from 'FirtVal' + */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Addr[i] = Val; + Val++; + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = FirtVal; + /* + * Check every word within the words + * of tested memory and compare it + * with the incrementing reference + * Val + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem8 = Addr[i]; + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val++; + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) { + /* + * set up to cycle through all possible initial + * test Patterns for walking ones test + */ + + for (j = 0U; j < (u32)8; j++) { + /* + * Generate an initial value for walking ones test + * to test for bad data bits + */ + Val = (u8)((u32)1 << j); + /* + * START walking ones test + * Write a one to each data bit indifferent locations + */ + for (i = 0U; i < (u32)8; i++) { + /* write memory location */ + Addr[i] = Val; + Val = (u8)RotateLeft(Val, 8U); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u8)((u32)1 << j); + /* Read the values from each location that was written */ + for (i = 0U; i < (u32)8; i++) { + /* read memory location */ + WordMem8 = Addr[i]; + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + Val = (u8)RotateLeft(Val, 8U); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) { + /* + * set up to cycle through all possible initial test + * Patterns for walking zeros test + */ + + for (j = 0U; j < (u32)8; j++) { + /* + * Generate an initial value for walking ones test to test + * for bad data bits + */ + Val = (u8) (~(1U << j)); + /* + * START walking zeros test + * Write a one to each data bit indifferent locations + */ + for (i = 0U; i < (u32)8; i++) { + /* write memory location */ + Addr[i] = Val; + Val = ~((u8)RotateLeft(~((u32)Val), 8U)); + } + /* + * Restore the reference 'Val' to the + * initial value + */ + Val = (u8) (~(1U << j)); + /* Read the values from each location that was written */ + for (i = 0U; i < (u32)8; i++) { + /* read memory location */ + WordMem8 = Addr[i]; + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + + Val = ~((u8)RotateLeft(~((u32)Val), 8U)); + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) { + /* Fill the memory with inverse of address */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Val = ~(u8) (UINTPTR) &Addr[i]; + Addr[i] = Val; + } + + /* + * Check every word within the words + * of tested memory + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem8 = Addr[i]; + Val = ~(u8) (UINTPTR) &Addr[i]; + if ((WordMem8 ^ Val) != 0x00U) { + Status = -1; + goto End_Label; + } + } + } + + if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) { + /* + * Generate an initial value for + * memory testing + */ + + if (Pattern == (u8)0) { + Val = 0xA5U; + } + else { + Val = Pattern; + } + /* + * Fill the memory with fixed Pattern + */ + for (i = 0U; i < Words; i++) { + /* write memory location */ + Addr[i] = Val; + } + /* + * Check every word within the words + * of tested memory and compare it + * with the fixed Pattern + */ + + for (i = 0U; i < Words; i++) { + /* read memory location */ + WordMem8 = Addr[i]; + if (WordMem8 != Val) { + Status = -1; + goto End_Label; + } + } + } + +End_Label: + return Status; +} +#endif + +/*****************************************************************************/ +/** +* +* @brief Rotates the provided value to the left one bit position +* +* @param Input is value to be rotated to the left +* @param Width is the number of bits in the input data +* +* @return The resulting unsigned long value of the rotate left +* +* +*****************************************************************************/ +static u32 RotateLeft(u32 Input, u8 Width) +{ + u32 Msb; + u32 ReturnVal; + u32 WidthMask; + u32 MsbMask; + u32 LocalInput = Input; + + /* + * set up the WidthMask and the MsbMask + */ + + MsbMask = 1UL << (Width - 1U); + + WidthMask = (MsbMask << (u32)1) - (u32)1; + + /* + * set the Width of the Input to the correct width + */ + + LocalInput = LocalInput & WidthMask; + + Msb = LocalInput & MsbMask; + + ReturnVal = LocalInput << 1U; + + if (Msb != 0x00000000U) { + ReturnVal = ReturnVal | (u32)0x00000001; + } + + ReturnVal = ReturnVal & WidthMask; + + return ReturnVal; + +} + +#ifdef ROTATE_RIGHT +/*****************************************************************************/ +/** +* +* @brief Rotates the provided value to the right one bit position +* +* @param Input: value to be rotated to the right +* @param Width: number of bits in the input data +* +* @return +* The resulting u32 value of the rotate right +* +*****************************************************************************/ +static u32 RotateRight(u32 Input, u8 Width) +{ + u32 Lsb; + u32 ReturnVal; + u32 WidthMask; + u32 MsbMask; + u32 LocalInput = Input; + /* + * set up the WidthMask and the MsbMask + */ + + MsbMask = 1U << (Width - 1U); + + WidthMask = (MsbMask << 1U) - 1U; + + /* + * set the width of the input to the correct width + */ + + LocalInput = LocalInput & WidthMask; + + ReturnVal = LocalInput >> 1U; + + Lsb = LocalInput & 0x00000001U; + + if (Lsb != 0x00000000U) { + ReturnVal = ReturnVal | MsbMask; + } + + ReturnVal = ReturnVal & WidthMask; + + return ReturnVal; + +} +#endif /* ROTATE_RIGHT */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testmem.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testmem.h new file mode 100644 index 0000000..7e29233 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_testmem.h @@ -0,0 +1,165 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_testmem.h +* @addtogroup common_test_utils Test Utilities for Memory and Caches +* +* - Cache test: xil_testcache.h contains utility functions to test cache. +* +* - I/O test: The Xil_testio.h file contains endian related memory IO functions. A +* subset of the memory tests can be selected or all of the tests can be run in order. +* If there is an error detected by a subtest, the test stops and the failure code is +* returned. Further tests are not run even if all of the tests are selected. +* +* - Memory test: The xil_testmem.h file contains utility functions to test memory. +* A subset of the memory tests can be selected or all of the tests can be run +* in order. If there is an error detected by a subtest, the test stops and the +* failure code is returned. Further tests are not run even if all of the tests are selected. +* +* +* Following list describes the supported memory tests: +* +* - XIL_TESTMEM_ALLMEMTESTS: This test runs all of the subtests. +* +* - XIL_TESTMEM_INCREMENT: This test +* starts at 'XIL_TESTMEM_INIT_VALUE' and uses the incrementing value as the +* test value for memory. +* +* - XIL_TESTMEM_WALKONES: Also known as the Walking ones test. This test +* uses a walking '1' as the test value for memory. +* @code +* location 1 = 0x00000001 +* location 2 = 0x00000002 +* ... +* @endcode +* +* - XIL_TESTMEM_WALKZEROS: Also known as the Walking zero's test. +* This test uses the inverse value of the walking ones test +* as the test value for memory. +* @code +* location 1 = 0xFFFFFFFE +* location 2 = 0xFFFFFFFD +* ... +*@endcode +* +* - XIL_TESTMEM_INVERSEADDR: Also known as the inverse address test. +* This test uses the inverse of the address of the location under test +* as the test value for memory. +* +* - XIL_TESTMEM_FIXEDPATTERN: Also known as the fixed pattern test. +* This test uses the provided patters as the test value for memory. +* If zero is provided as the pattern the test uses '0xDEADBEEF". +* +* @warning +* The tests are DESTRUCTIVE. Run before any initialized memory spaces +* have been set up. +* The address provided to the memory tests is not checked for +* validity except for the NULL case. It is possible to provide a code-space +* pointer for this test to start with and ultimately destroy executable code +* causing random failures. +* +* @note +* Used for spaces where the address range of the region is smaller than +* the data width. If the memory range is greater than 2 ** width, +* the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will +* repeat on a boundary of a power of two making it more difficult to detect +* addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR +* tests suffer the same problem. Ideally, if large blocks of memory are to be +* tested, break them up into smaller regions of memory to allow the test +* patterns used not to repeat over the region tested. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver    Who    Date    Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a hbm  08/25/09 First release
+* 7.5   mus  03/10/21 Added new set of Xil_TestMem32, Xil_TestMem16 and
+*                     Xil_TestMem8 APIs to support memory test for memory
+*                     regions mapped at extended addresses
+*                     (addresses > 4 GB). These new set of APIs would be
+*                     compiled only for 32 bit Microblaze processor, if
+*                     XPAR_MICROBLAZE_ADDR_SIZE is greater than 32.
+*                     It fixes CR#1089129.
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XIL_TESTMEM_H /* prevent circular inclusions */ +#define XIL_TESTMEM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/* xutil_memtest defines */ + +#define XIL_TESTMEM_INIT_VALUE 1U + +/** @name Memory subtests + * @{ + */ +/** + * See the detailed description of the subtests in the file description. + */ +#define XIL_TESTMEM_ALLMEMTESTS 0x00U +#define XIL_TESTMEM_INCREMENT 0x01U +#define XIL_TESTMEM_WALKONES 0x02U +#define XIL_TESTMEM_WALKZEROS 0x03U +#define XIL_TESTMEM_INVERSEADDR 0x04U +#define XIL_TESTMEM_FIXEDPATTERN 0x05U +#define XIL_TESTMEM_MAXTEST XIL_TESTMEM_FIXEDPATTERN +/* @} */ + +#if !defined(__aarch64__) && !defined(__arch64__) +#define NUM_OF_BITS_IN_BYTE 8U +#define NUM_OF_BYTES_IN_HW 2U +#define NUM_OF_BITS_IN_HW 16U +#define NUM_OF_BYTES_IN_WORD 4U +#define NUM_OF_BITS_IN_WORD 32U +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/** + *@endcond + */ + +/************************** Function Prototypes ******************************/ + +/* xutil_testmem prototypes */ +#if defined(__MICROBLAZE__) && !defined(__arch64__) && (XPAR_MICROBLAZE_ADDR_SIZE > 32) +extern s32 Xil_TestMem32(u32 AddrLow, u32 AddrHigh, u32 Words, u32 Pattern, u8 Subtest); +extern s32 Xil_TestMem16(u32 AddrLow, u32 AddrHigh, u32 Words, u16 Pattern, u8 Subtest); +extern s32 Xil_TestMem8(u32 AddrLow, u32 AddrHigh, u32 Words, u8 Pattern, u8 Subtest); +#else +extern s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest); +extern s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest); +extern s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_test_utils". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_types.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_types.h new file mode 100644 index 0000000..100bddd --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_types.h @@ -0,0 +1,222 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xil_types.h +* +* @addtogroup common_types Basic Data types for Xilinx® Software IP +* +* The xil_types.h file contains basic types for Xilinx software IP. These data types +* are applicable for all processors supported by Xilinx. +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a hbm  07/14/09 First release
+* 3.03a sdm  05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros
+* 5.00 	pkp  05/29/14 Made changes for 64 bit architecture
+*	srt  07/14/14 Use standard definitions from stdint.h and stddef.h
+*		      Define LONG and ULONG datatypes and mask values
+* 7.00  mus  01/07/19 Add cpp extern macro
+* 7.1   aru  08/19/19 Shift the value in UPPER_32_BITS only if it
+*                     is 64-bit processor
+* 8.1    dp  12/23/22 Updated UINTPTR and INTPTR to point to 64bit data types
+*                     incase of microblaze 32-bit with extended address enabled
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ +#ifndef XIL_TYPES_H /* prevent circular inclusions */ +#define XIL_TYPES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#define XIL_COMPONENT_IS_READY 0x11111111U /**< In device drivers, This macro will be + assigend to "IsReady" member of driver + instance to indicate that driver + instance is initialized and ready to use. */ +#define XIL_COMPONENT_IS_STARTED 0x22222222U /**< In device drivers, This macro will be assigend to + "IsStarted" member of driver instance + to indicate that driver instance is + started and it can be enabled. */ + +/* @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XBASIC_TYPES_H +/* + * guarded against xbasic_types.h. + */ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +/** @}*/ +#define __XUINT64__ +typedef struct +{ + u32 Upper; + u32 Lower; +} Xuint64; + + +/*****************************************************************************/ +/** +* @brief Return the most significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The upper 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_MSW(x) ((x).Upper) + +/*****************************************************************************/ +/** +* @brief Return the least significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The lower 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_LSW(x) ((x).Lower) + +#endif /* XBASIC_TYPES_H */ + +/* + * xbasic_types.h does not typedef s* or u64 + */ +/** @{ */ +typedef char char8; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint64_t u64; +typedef int sint32; + +#if defined(__MICROBLAZE__) && !defined(__arch64__) && \ + (XPAR_MICROBLAZE_ADDR_SIZE > 32) +typedef uint64_t UINTPTR; +typedef int64_t INTPTR; +#else +typedef uintptr_t UINTPTR; +typedef intptr_t INTPTR; +#endif + +typedef ptrdiff_t PTRDIFF; +/** @}*/ +#if !defined(LONG) || !defined(ULONG) +typedef long LONG; +typedef unsigned long ULONG; +#endif + +#define ULONG64_HI_MASK 0xFFFFFFFF00000000U +#define ULONG64_LO_MASK ~ULONG64_HI_MASK + +#else +#include +#endif + +/** @{ */ +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/** + * This data type defines an exception handler for a processor. + * The argument points to the instance of the component + */ +typedef void (*XExceptionHandler) (void *InstancePtr); + +/** + * @brief Returns 32-63 bits of a number. + * @param n : Number being accessed. + * @return Bits 32-63 of number. + * + * @note A basic shift-right of a 64- or 32-bit quantity. + * Use this to suppress the "right shift count >= width of type" + * warning when that quantity is 32-bits. + */ +#if defined (__aarch64__) || defined (__arch64__) +#define UPPER_32_BITS(n) ((u32)(((n) >> 16) >> 16)) +#else +#define UPPER_32_BITS(n) 0U +#endif +/** + * @brief Returns 0-31 bits of a number + * @param n : Number being accessed. + * @return Bits 0-31 of number + */ +#define LOWER_32_BITS(n) ((u32)(n)) + +/** + * @brief Returns 0-31 bits of a number . + * @param n : Number being accessed. + * @return Bits 0-31 of number. + */ +#if defined (__aarch64__) || defined (__arch64__) +#define LEFT_SHIFT_BY_32_BITS(n) (u64)(((u64)n) << 32) +#else +#define LEFT_SHIFT_BY_32_BITS(n) 0U +#endif + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** + *@endcond + */ +/** +* @} End of "addtogroup common_types". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_util.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_util.c new file mode 100644 index 0000000..b056c3c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_util.c @@ -0,0 +1,1377 @@ +/******************************************************************************/ +/** +* Copyright (c) 2019 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* @file xil_util.c +* +* xil_util.c file contains xil utility functions +* Except few functions, most of these functions are wrappers to standard functions. +* The standard string functions do not validate the input and that results into +* buffer overflows. To avoid it, the wrapper function validates the input and +* then passed to standard function. There are few constant time functions +* ( xxx_CT() ) which are used to compare the data in constant time. +* The constant time functions should be used while comparing secure data +* like password, keys which prevent disclosing of the data using +* timing analysis. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+* 7.2   nava     08/01/20 Updated Xil_WaitForEvent() and Xil_WaitForEvents(()
+*                         API to use microsecond timeout instead of a free
+*                         counter.
+* 7.3   kal      06/30/20 Converted Xil_Ceil macro to API.
+*       rpo      08/19/20 Added function for read,modify,write
+*       kal      09/22/20 Changed the param type from const char to const char*
+*                         to avoid copying key onto stack
+*       td       10/16/20 Added Xil_Strcpy, Xil_Strcat, Xil_SecureMemCpy and
+*                         Xil_MemCmp functions
+* 7.4   am       11/26/20 Added Xil_StrCpyRange function
+* 7.6   kpt      07/15/21 Added Xil_SecureZeroize function
+* 7.7   kpt      11/09/21 Added Xil_SMemCmp, Xil_SMemCmp_CT, Xil_SMemCpy,
+*                         Xil_SMemSet, Xil_SStrCat, Xil_SStrCmp, Xil_SStrCmp_CT
+*                         Xil_SStrCpy functions
+*       kpt      11/25/21 Added strnlen function to fix ARMCC compilation
+*                         failure
+* 7.7	sk	 01/10/22 Update functions return type and update RetVal variable
+* 			  data type to fix misra_c_2012_directive_4_6 misrac
+* 			  violations.
+* 7.7	sk	 01/10/22 Update values from signed to unsigned to fix
+* 			  misra_c_2012_rule_10_4 violation.
+* 7.7	sk	 01/10/22 Add explicit parentheses to fix misra_c_2012_rule_12_1
+* 			  violation.
+* 7.7	sk	 01/10/22 Typecast character strings to u8 to fix misra_c_2012_rule_
+* 			  10_3 violation.
+* 7.7	sk	 01/10/22 Modify the code to reduce multiple break statements
+* 			  and fix misra_c_2012_rule_15_4 violation.
+* 7.7	sk	 01/10/22 Modify Xil_SMemCmp_CT and Xil_SMemCmp function argument
+* 			  type to fix misra_c_2012_rule_8_3 violation.
+* 7.7	sk	 01/10/22 Update conditional expression to fix misra_c_2012_rule_14_4
+* 			  violation.
+*       bm       01/20/22 Fix compilation warnings in Xil_SMemCpy
+*       mmd      02/28/22 Added Xil_SMemMove function
+* 8.0	sk	 03/02/22 Add explicit parentheses to fix misra_c_2012_rule_12_1
+* 			  violation.
+* 8.0	sk	 03/02/22 Add const qualifier to varaibles to fix misra_c_2012_rule_
+* 			  11_8 violation.
+* 8.0	sk	 03/02/22 Typecast expression with unsigned int to fix
+* 			  misra_c_2012_rule_10_7 violation.
+* 8.0	sk	 03/02/22 Typecast variables with unsigned or signed to fix misra_c
+* 			  _2012_rule_10_3 violation.
+* 8.0	sk	 03/02/22 Add const to unmodified variable to fix misra_c_2012
+* 			  _rule_8_13 violation.
+* 8.0	sk	 03/02/22 Typecast the function with void as return type is
+* 			  not used and fix misra_c_2012_rule_17_7 violation.
+* 8.0	sk	 03/02/22 Remove increment operations during comparision to
+* 			  fix misra_c_2012_rule_13_3 violation.
+* 8.0	sk	 03/02/22 Update values from signed to unsigned to fix
+* 			  misra_c_2012_rule_10_4 violation.
+* 8.0	sk	 03/17/22 Add const to unmodified pointer variable to fix misra_c
+*			  _2012_rule_8_13 violation.
+* 8.0   adk      04/18/22 Added Xil_WaitForEventSet function.
+*       adk	 07/15/22 Updated the Xil_WaitForEventSet() API to
+*			  support variable number of events.
+*	ssc	 08/25/22 Added Xil_SecureRMW32 API
+* 8.1	sa       09/29/22 Change the type of first argument passed to Xil_WaitForEvent
+*			  API from u32 to UINTPTR for supporting 64 bit addressing.
+* 8.1   sa       10/20/22 Change the type of first argument passed to Xil_WaitForEvents
+*                         API from u32 to UINTPTR for supporting 64 bit addressing.
+* 8.1   akm      01/02/23 Added Xil_RegisterPlmHandler() & Xil_PlmStubHandler() APIs.
+* 
+* +*****************************************************************************/ + +/****************************** Include Files *********************************/ +#include "xil_util.h" +#include "sleep.h" + +/************************** Constant Definitions ****************************/ +#define MAX_NIBBLES 8U + +/************************** Function Prototypes *****************************/ +void (*fptr)(void) = NULL; + +#ifdef __ARMCC_VERSION +/******************************************************************************/ +/** + * + * This API returns the length of the input string + * + * @param StartPtr is the pointer to the input string + * @param StrSize is the maximum length of the input string + * + * @return Returns the length of the input string + * + ******************************************************************************/ +static size_t strnlen (const char *StartPtr, size_t StrSize) +{ + const char *EndPtr = StartPtr; + size_t StrLen = 0U; + + EndPtr = memchr(StartPtr, '\0', StrSize); + if (EndPtr == NULL) { + StrLen = StrSize; + } + else { + StrLen = (size_t) (EndPtr - StartPtr); + } + + return StrLen; +} +#endif + +/******************************************************************************/ +/** +* This API ceils the provided float value. +* +* @param Value is a float variable which has to ceiled to nearest +* integer. +* +* @return Returns ceiled value. +* +*******************************************************************************/ +s32 Xil_Ceil(float Value) +{ + s32 Result = Value; + + if (Value > Result) { + Result = Result + 1; + } + + return Result; +} + +/****************************************************************************/ +/** + * Converts the char into the equivalent nibble. + * Ex: 'a' -> 0xa, 'A' -> 0xa, '9'->0x9 + * + * @param InChar - Input character to be converted to nibble. + * Valid characters are between 0-9, a-f, A-F + * @param Num - Memory location where nibble is to be stored + * + * @return + * XST_SUCCESS - Character converted to nibble + * XST_FAILURE - Invalid input character + * + * @note None. + * + *****************************************************************************/ + +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num) +{ + u32 Status; + + /* Convert the char to nibble */ + if ((InChar >= (u8)'0') && (InChar <= (u8)'9')) { + *Num = InChar - (u8)'0'; + Status = XST_SUCCESS; + } + else if ((InChar >= (u8)'a') && (InChar <= (u8)'f')) { + *Num = InChar - (u8)'a' + 10U; + Status = XST_SUCCESS; + } + else if ((InChar >= (u8)'A') && (InChar <= (u8)'F')) { + *Num = InChar - (u8)'A' + 10U; + Status = XST_SUCCESS; + } + else { + Status = XST_FAILURE; + } + + return Status; +} + +/****************************************************************************/ +/* + * Converts the string into the equivalent Hex buffer. + * Ex: "abc123" -> {0xab, 0xc1, 0x23} + * + * @param Str - Pointer to string to be converted to Hex. + * Accepted characters in string are between 0-9, a-f and A-F + * @param Buf - Pointer to memory location where converted hex values are to + * be stored. + * @param Len - Length of input string + * + * @return + * XST_SUCCESS - Input string is converted to hex + * XST_FAILURE - Invalid character in inpit string + * + * @note None. + * + *****************************************************************************/ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len) +{ + u32 Status = XST_FAILURE; + u8 ConvertedLen = 0U, index = 0U; + u8 Nibble[MAX_NIBBLES] = {0U}; + u8 i; + + while (ConvertedLen < Len) { + for (i = 0U; i < MAX_NIBBLES; i++) { + Status = Xil_ConvertCharToNibble((u8)Str[ConvertedLen], + &Nibble[i]); + ConvertedLen = ConvertedLen +1U; + if (Status != XST_SUCCESS) { + /* Error converting char to nibble */ + goto END; + } + } + + buf[index] = (((u32)Nibble[0] << (u8)28U) | ((u32)Nibble[1] << (u8)24U) | + ((u32)Nibble[2] << (u8)20U) | ((u32)Nibble[3] << (u8)16U) | + ((u32)Nibble[4] << (u8)12U) | ((u32)Nibble[5] << (u8)8U) | + ((u32)Nibble[6] << (u8)4U) | (u32)Nibble[7]); + index++; + } +END: + return Status; +} + +#ifdef VERSAL_PLM +/****************************************************************************/ +/* + * Register PLM Alive Handler. + * + * @param PlmAlive - Pointer to PlmAlive API. + * + * @return None. + * + *****************************************************************************/ +void Xil_RegisterPlmHandler(void (*PlmAlive) (void)) { + fptr = PlmAlive; +} + +/****************************************************************************/ +/* + * PLM Stub Handler called while waiting for event. + * + * @param None. + * + * @return None. + * + *****************************************************************************/ +void Xil_PlmStubHandler(void) { + if (fptr != NULL) { + fptr(); + } +} +#endif + +/****************************************************************************/ +/* + * Waits for the event + * + * @param RegAddr - Address of register to be checked for event(s) occurrence + * @param EventMask - Mask indicating event(s) to be checked + * @param Event - Specific event(s) value to be checked + * @param Timeout - Max number of microseconds to wait for an event(s). + * + * @return + * XST_SUCCESS - On occurrence of the event(s). + * XST_FAILURE - Event did not occur before counter reaches 0 + * + * @note None. + * + *****************************************************************************/ +u32 Xil_WaitForEvent(UINTPTR RegAddr, u32 EventMask, u32 Event, u32 Timeout) +{ + u32 EventStatus; + u32 PollCount = Timeout; + u32 Status = XST_FAILURE; + + while(PollCount > 0U) { + EventStatus = Xil_In32(RegAddr) & EventMask; + if (EventStatus == Event) { + Status = XST_SUCCESS; + break; + } + PollCount--; +#ifdef VERSAL_PLM + Xil_PlmStubHandler(); +#endif + usleep(1U); + } + + return Status; +} + + +/******************************************************************************/ +/** + * Waits for the events. Returns on occurrence of first event / timeout. + * + * @param EventsRegAddr - Address of register to be checked for event(s) + * occurrence + * @param EventsMask - Mask indicating event(s) to be checked + * @param WaitEvents - Specific event(s) to be checked + * @param Timeout - Max number of microseconds to wait for an event(s). + * @param Events - Mask of Events occurred returned in memory pointed by + * this variable + * + * @return + * XST_SUCCESS - On occurrence of the event(s). + * XST_FAILURE - Event did not occur before counter reaches 0 + * + ******************************************************************************/ +u32 Xil_WaitForEvents(UINTPTR EventsRegAddr, u32 EventsMask, u32 WaitEvents, + u32 Timeout, u32* Events) +{ + u32 EventStatus; + u32 PollCount = Timeout; + u32 Status = XST_TIMEOUT; + + *Events = 0x00; + do { + EventStatus = Xil_In32(EventsRegAddr); + EventStatus &= EventsMask; + if((EventStatus & WaitEvents) != 0U) { + Status = XST_SUCCESS; + *Events = EventStatus; + break; + } + PollCount--; +#ifdef VERSAL_PLM + Xil_PlmStubHandler(); +#endif + usleep(1U); + } + while(PollCount > 0U); + + return Status; +} + +/******************************************************************************/ +/** + * Checks whether the passed character is a valid hex digit + * + * @param Ch - Pointer to the input character + * + * @return + * XST_SUCCESS - on valid hex digit + * XST_FAILURE - on invalid hex digit + * + * @note None. + * + ******************************************************************************/ +u32 Xil_IsValidHexChar(const char *Ch) +{ + u32 Status = XST_FAILURE; + + if(NULL == Ch) { + goto END; + } + if (((*Ch >= '0') && (*Ch <='9'))|| + ((*Ch >= 'a') && (*Ch <='f'))|| + ((*Ch >= 'A') && (*Ch <='F'))) { + + Status = XST_SUCCESS; + } +END: + return Status; +} + +/******************************************************************************/ +/** + * Validate the input string contains only hexadecimal characters + * + * @param HexStr - Pointer to string to be validated + * + * @return + * XST_SUCCESS - On valid input hex string + * XST_INVALID_PARAM - On invalid length of the input string + * XST_FAILURE - On non hexadecimal character in string + * + * @note None + * + ******************************************************************************/ +u32 Xil_ValidateHexStr(const char *HexStr) +{ + u32 Idx; + u32 Len; + u32 Status = XST_INVALID_PARAM; + + if(NULL == HexStr) { + goto END; + } + + Len = Xil_Strnlen(HexStr, XIL_MAX_HEX_STR_LEN + 1U); + if (Len > XIL_MAX_HEX_STR_LEN) { + goto END; + } + + for (Idx = 0U; Idx < Len; Idx++) { + Status = Xil_IsValidHexChar(&HexStr[Idx]); + if (Status != XST_SUCCESS) { + break; + } + } + +END: + return Status; +} + +/****************************************************************************/ +/** + * Converts the string into the equivalent Hex buffer. + * Ex: "abc123" -> {0xab, 0xc1, 0x23} + * + * @param Str is a Input String. Will support the lower and upper case values. + * Value should be between 0-9, a-f and A-F + * @param Buf is Output buffer. + * @param Len of the input string. Should have even values + * + * @return + * - XST_SUCCESS no errors occurred. + * - XST_FAILURE an error when input parameters are not valid + * - an error when input buffer has invalid values + * + * TDD Test Cases: + * ---Initialization--- + * Len is odd + * Len is zero + * Str is NULL + * Buf is NULL + * ---Functionality--- + * Str input with only numbers + * Str input with All values in A-F + * Str input with All values in a-f + * Str input with values in a-f, 0-9, A-F + * Str input with values in a-z, 0-9, A-Z + * Boundary Cases + * Memory Bounds of buffer checking + * ****************************************************************************/ +u32 Xil_ConvertStringToHexBE(const char *Str, u8 *Buf, u32 Len) +{ + u32 ConvertedLen; + u8 LowerNibble = 0U; + u8 UpperNibble = 0U; + u32 Status = (u32)XST_FAILURE; + + if ((Str == NULL) || (Buf == NULL)) { + Status = (u32)XST_INVALID_PARAM; + goto END; + } + + if ((Len == 0U) || ((Len % XIL_SIZE_OF_BYTE_IN_BITS) != 0U)) { + Status = (u32)XST_INVALID_PARAM; + goto END; + } + + if(Len != (strlen(Str) * XIL_SIZE_OF_NIBBLE_IN_BITS)) { + Status = (u32)XST_INVALID_PARAM; + goto END; + } + + ConvertedLen = 0U; + while (ConvertedLen < (Len / XIL_SIZE_OF_NIBBLE_IN_BITS)) { + if ((Xil_ConvertCharToNibble(((u8)Str[ConvertedLen]),&UpperNibble) + == (u32)XST_SUCCESS) && (Xil_ConvertCharToNibble(((u8)Str[ConvertedLen+1U]), + &LowerNibble) == (u32)XST_SUCCESS)) { + Buf[ConvertedLen/2U] = + (UpperNibble << XIL_SIZE_OF_NIBBLE_IN_BITS) | + LowerNibble; + } + else { + Status = (u32)XST_INVALID_PARAM; + goto END; + } + ConvertedLen += 2U; + } + Status = (u32)XST_SUCCESS; +END: + return Status; +} + +/******************************************************************************/ +/** + * Converts the string into the equivalent Hex buffer. + * Ex: "abc123" -> {0x23, 0xc1, 0xab} + * + * @param Str - Input String to be converted to hex number in little + * endian format. Valid characters of input strin are between + * 0-9, a-f and A-F + * @param Buf - Pointer to memory location where converted hex numbers are to + * be stored. + * @param Len - Expected number of output bits + * + * @return + * XST_SUCCESS - Input string is converted to hex number(s) + * XST_FAILURE - Invalid input character detected in input string + * + * @note + * + ******************************************************************************/ +u32 Xil_ConvertStringToHexLE(const char *Str, u8 *Buf, u32 Len) +{ + u32 ConvertedLen; + u8 LowerNibble = 0U; + u8 UpperNibble = 0U; + u32 StrIndex; + u32 Status = XST_FAILURE; + + if ((NULL == Str) || (NULL == Buf)) { + Status = XST_INVALID_PARAM; + goto END; + } + + if ((Len == 0U) || ((Len % XIL_SIZE_OF_BYTE_IN_BITS) != 0U)) { + Status = XST_INVALID_PARAM; + goto END; + } + + if(Len != (strlen(Str) * XIL_SIZE_OF_NIBBLE_IN_BITS)) { + Status = XST_INVALID_PARAM; + goto END; + } + + StrIndex = (Len / XIL_SIZE_OF_BYTE_IN_BITS) - 1U; + ConvertedLen = 0U; + while (ConvertedLen < (Len / XIL_SIZE_OF_NIBBLE_IN_BITS)) { + if ((Xil_ConvertCharToNibble(((u8)Str[ConvertedLen]), + &UpperNibble) == XST_SUCCESS) && + (Xil_ConvertCharToNibble(((u8)Str[ConvertedLen + 1U]), + &LowerNibble) == XST_SUCCESS)) { + Buf[StrIndex] = + (UpperNibble << XIL_SIZE_OF_NIBBLE_IN_BITS) | + LowerNibble; + StrIndex = StrIndex - 1U; + } + else { + Status = XST_INVALID_PARAM; + goto END; + } + ConvertedLen += 2U; + } + + Status = XST_SUCCESS; +END: + return Status; +} + +/******************************************************************************/ +/** + * Returns the length of input string. + * + * @param Str - Input string + * @param MaxLen - Maximum expected length of the input string + * + * @return + * Returns length of the input string if length is less than MaxLen. + * Returns MaxLen if the length of the input string is >= MaxLen. + * + * @note + * + ******************************************************************************/ +u32 Xil_Strnlen(const char *Str, u32 MaxLen) +{ + const char *InStr = Str; + u32 StrLen = 0U; + + if (NULL == Str) { + goto END; + } + + while(StrLen < MaxLen) { + if ('\0' == *InStr) { + break; + } + StrLen++; + InStr++; + } + +END: + return StrLen; +} + +/*****************************************************************************/ +/** + * @brief This function will Read, Modify and Write to an address. + * + * @param Addr denotes Address + * @param Mask denotes the bits to be modified + * @param Value is the value to be written to the address + * + * @return None + * + *****************************************************************************/ +void Xil_UtilRMW32(u32 Addr, u32 Mask, u32 Value) +{ + u32 Val; + + Val = Xil_In32(Addr); + Val = (Val & (~Mask)) | (Mask & Value); + Xil_Out32(Addr, Val); +} + +/*****************************************************************************/ +/** + * @brief This functions copies source string to destination string. This + * function is a safe version of strcpy + * + * @param DestPtr is pointer to destination string + * @param SrcPtr is pointer to source string + * @param Size is the maximum number of bytes of the source string + * to be copied + * + * @return XST_SUCCESS on success and error code on failure + * + ******************************************************************************/ +int Xil_Strcpy(char *DestPtr, const char *SrcPtr, const u32 Size) +{ + int Status = XST_FAILURE; + u32 Count; + + if ((SrcPtr == NULL) || (DestPtr == NULL) || (Size == 0U)) { + goto END; + } + + for (Count = 0U; (SrcPtr[Count] != '\0') && (Count < Size); ++Count) { + DestPtr[Count] = SrcPtr[Count]; + } + if (Count == Size) { + DestPtr[0U] = '\0'; + goto END; + } + DestPtr[Count] = '\0'; + Status = XST_SUCCESS; + +END: + return Status; +} + +/****************************************************************************/ +/** + * @brief Copies specified range from source string to destination string + * + * @param Src is a pointer to source string + * @param Dest is a pointer to destination string + * @param From is 0 based index from where string copy starts + * @param To is 0 based index till which string is copied + * @param MaxSrcLen is the maximum length of source string + * @param MaxDstLen is the maximum length of destination string + * + * @return XST_SUCCESS on success + * XST_FAILURE on failure + * + * @note None + * + ****************************************************************************/ +int Xil_StrCpyRange(const u8 *Src, u8 *Dest, u32 From, u32 To, u32 MaxSrcLen, + u32 MaxDstLen) +{ + int Status = XST_FAILURE; + u32 SrcLength; + u32 Index; + + if ((Src == NULL) || (Dest == NULL)) { + Status = XST_INVALID_PARAM; + goto END; + } + + if ((To >= MaxSrcLen) || (To < From)) { + Status = XST_INVALID_PARAM; + goto END; + } + + if ((To - From + 1U) >= MaxDstLen) { + Status = XST_INVALID_PARAM; + goto END; + } + + SrcLength = Xil_Strnlen((const char *)Src, MaxSrcLen); + if (To >= SrcLength) { + Status = XST_INVALID_PARAM; + goto END; + } + + for (Index = From; (Index <= To) && (Src[Index]!= (u8)'\0'); Index++) { + Dest[Index - From] = Src[Index]; + } + + Dest[Index - From] = (u8)'\0'; + Status = XST_SUCCESS; + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function appends string2 to string1. This function is a safe + * version of strcat + * + * @param Str1Ptr is pointer to string1 + * @param Str2Ptr is pointer to string2 + * @param Size is the maximum number of bytes Str1 can hold + * + * @return XST_SUCCESS on success and error code on failure + * + ******************************************************************************/ +int Xil_Strcat(char* Str1Ptr, const char* Str2Ptr, const u32 Size) +{ + int Status = XST_FAILURE; + u32 Count = 0U; + u32 CountTmp = 0U; + + if ((Str1Ptr == NULL) || (Str2Ptr == NULL) || (Size == 0U)) { + goto END; + } + + while ((Count < Size) && (Str1Ptr[Count] != '\0')) { + Count++; + } + + while ((Str2Ptr[CountTmp] != '\0') && (Count < Size)) { + Str1Ptr[Count] = Str2Ptr[CountTmp]; + Count++; + CountTmp++; + } + if (Count == Size) { + Str1Ptr[0U] = '\0'; + goto END; + } + Str1Ptr[Count] = '\0'; + Status = XST_SUCCESS; + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function copies Len bytes from source memory to destination + * memory. If Len is greater than DestPtrLen, then DestPtr is also + * filled with 0s till DestPtrLen bytes and is considered as a failure. + * This function is a secure implementation of memcpy + * + * @param DestPtr is pointer to destination address + * @param DestPtrLen is the memory alloted to the destination buffer + * @param SrcPtr is pointer to source address + * @param Len is number of bytes to be copied + * + * @return XST_SUCCESS on success and error code on failure + * + ******************************************************************************/ +int Xil_SecureMemCpy(void * DestPtr, u32 DestPtrLen, const void * SrcPtr, u32 Len) +{ + int Status = XST_FAILURE; + u8 *Dest = (u8 *)DestPtr; + const u8 *Src = (const u8 *)SrcPtr; + + if ((DestPtr == NULL) || (SrcPtr == NULL)) { + goto END; + } + + if (Len > DestPtrLen) { + while (DestPtrLen != 0U) { + *Dest = 0U; + Dest++; + DestPtrLen--; + } + goto END; + } + + /* Loop and copy. */ + while (Len != 0U) { + *Dest = *Src; + Dest++; + Src++; + Len--; + } + Status = XST_SUCCESS; + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function compares Len bytes from memory1 and memory2. This + * function is a secure implementation of memcmp + * + * @param Buf1Ptr is pointer to memory1 + * @param Buf2Ptr is pointer to memory2 + * @param Len is number of byets to be compared + * + * @return 0 if contents of both the memory regions are same, + * -1 if first non-matching character has lower value in Buf1Ptr + * 1 if first non-matching character is greater value in Buf1Ptr + * + ******************************************************************************/ +int Xil_MemCmp(const void * Buf1Ptr, const void * Buf2Ptr, u32 Len) +{ + volatile int RetVal = 1; + const u8 *Buf1 = Buf1Ptr; + const u8 *Buf2 = Buf2Ptr; + u32 Size = Len; + + /* Assert validates the input arguments */ + if ((Buf1 == NULL) || (Buf2 == NULL) || (Len == 0x0U)) { + goto END; + } + + /* Loop and compare */ + while (Size != 0U) { + if (*Buf1 > *Buf2) { + RetVal = 1; + goto END; + } else if (*Buf1 < *Buf2) { + RetVal = -1; + goto END; + } else { + Buf1++; + Buf2++; + Size--; + } + } + + /* Make sure size is zero to know the whole of data is compared */ + if (Size == 0U) { + RetVal = 0; + } + +END: + return RetVal; +} + +/*****************************************************************************/ +/** + * @brief This function is used to zeroize the memory + * + * @param DataPtr Pointer to the memory which need to be zeroized. + * @param Length Length of the data in bytes. + * + * @return + * - XST_SUCCESS: If Zeroization is successful. + * - XST_FAILURE: If Zeroization is not successful. + ********************************************************************************/ +int Xil_SecureZeroize(u8 *DataPtr, const u32 Length) +{ + u32 Index; + int Status = XST_FAILURE; + + /* Clear the data */ + (void)memset(DataPtr, 0, Length); + + /* Read it back to verify */ + for (Index = 0U; Index < Length; Index++) { + if (DataPtr[Index] != 0x00U) { + goto END; + } + } + if (Index == Length) { + Status = XST_SUCCESS; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function compares two memory regions for specified number + * of bytes. This function takes size of two memory regions to + * make sure not to read from or write to out of bound memory + * region. + * + * @param Src1 - Pointer to first memory range + * @param Src1Size - Maximum size of first memory range + * @param Src2 - Pointer to second memory range + * @param Src2Size - Maximum size of second memory range + * @param CmpLen - Number of bytes to be compared + * + * @return + * XST_SUCCESS - If specified number of bytes matches + * XST_FAILURE - If there is a mistmatch found during comparison + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SMemCmp(const void *Src1, const u32 Src1Size, + const void *Src2, const u32 Src2Size, const u32 CmpLen) +{ + int Status = XST_FAILURE; + + if ((Src1 == NULL) || (Src2 == NULL)) { + Status = XST_INVALID_PARAM; + } + else if ((CmpLen == 0U) || (Src1Size < CmpLen) || (Src2Size < CmpLen)) { + Status = XST_INVALID_PARAM; + } + else { + Status = memcmp (Src1, Src2, CmpLen); + if (Status != 0) { + Status = XST_FAILURE; + } + } + + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function compares two memory regions for specified number + * of bytes. This function takes size of two memory regions to + * make sure not to read from or write to out of bound memory + * region. + * Note that this function compares till end to make it execute + * in constant time irrespective of the content of input memory. + * + * @param Src1 - Pointer to first memory range + * @param Src1Size - Maximum size of first memory range + * @param Src2 - Pointer to second memory range + * @param Src2Size - Maximum size of second memory range + * @param CmpLen - Number of bytes to be compared + * + * @return + * XST_SUCCESS - If specified number of bytes matches + * XST_FAILURE - If mistmatch + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SMemCmp_CT(const void *Src1, const u32 Src1Size, + const void *Src2, const u32 Src2Size, const u32 CmpLen) +{ + volatile int Status = XST_FAILURE; + volatile int StatusRedundant = XST_FAILURE; + volatile u32 Data = 0U; + volatile u32 DataRedundant = 0xFFFFFFFFU; + u32 Cnt = CmpLen; + const u8 *Src_1 = (const u8 *)Src1; + const u8 *Src_2 = (const u8 *)Src2; + + + if ((Src1 == NULL) || (Src2 == NULL)) { + Status = XST_INVALID_PARAM; + } + else if ((CmpLen == 0U) || (Src1Size < CmpLen) || (Src2Size < CmpLen)) { + Status = XST_INVALID_PARAM; + } + else { + while (Cnt >= sizeof(u32)) { + Data |= (*(const u32 *)Src_1 ^ *(const u32 *)Src_2); + DataRedundant &= ~Data; + Src_1 += sizeof(u32); + Src_2 += sizeof(u32); + Cnt -= sizeof(u32); + } + + while (Cnt > 0U) { + Data |= (u32)(*Src_1 ^ *Src_2); + DataRedundant &= ~Data; + Src_1++; + Src_2++; + Cnt--; + } + + if ((Data == 0U) && (DataRedundant == 0xFFFFFFFFU)) { + Status = XST_SUCCESS; + StatusRedundant = XST_SUCCESS; + } + } + + return (Status | StatusRedundant); +} + +/*****************************************************************************/ +/** + * @brief This is wrapper function to memcpy function. This function + * takes size of two memory regions to make sure not read from + * or write to out of bound memory region. + * + * @param Dest - Pointer to destination memory + * @param DestSize - Memory available at destination + * @param Src - Pointer to source memory + * @param SrcSize - Maximum data that can be copied from source + * @param CopyLen - Number of bytes to be copied + * + * @return + * XST_SUCCESS - Copy is successful + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SMemCpy(void *Dest, const u32 DestSize, + const void *Src, const u32 SrcSize, const u32 CopyLen) +{ + int Status = XST_FAILURE; + const u8 *Src8 = (const u8 *) Src; + const u8 *Dst8 = (u8 *) Dest; + void * volatile DestTemp = Dest; + const void * volatile SrcTemp = Src; + + if ((Dest == NULL) || (Src == NULL)) { + Status = XST_INVALID_PARAM; + } + else if ((CopyLen == 0U) || (DestSize < CopyLen) || (SrcSize < CopyLen)) { + Status = XST_INVALID_PARAM; + } + /* Return error for overlap string */ + else if ((Src8 < Dst8) && (&Src8[CopyLen - 1U] >= Dst8)) { + Status = XST_INVALID_PARAM; + } + else if ((Dst8 < Src8) && (&Dst8[CopyLen - 1U] >= Src8)) { + Status = XST_INVALID_PARAM; + } + else { + (void)memcpy(DestTemp, SrcTemp, CopyLen); + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** + * @brief This is wrapper function to memset function. This function + * writes specified byte to destination specified number of times. + * This function also takes maximum string size that destination + * holds to make sure not to write out of bound area. + * + * @param Dest - Pointer to destination memory + * @param DestSize - Memory available at destination + * @param Data - Any value from 0 to 255 + * @param Len - Number of bytes to be copied + * + * @return + * XST_SUCCESS - Copy is successful + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SMemSet(void *Dest, const u32 DestSize, + const u8 Data, const u32 Len) +{ + int Status = XST_FAILURE; + + if ((Dest == NULL) || (DestSize < Len) || (Len == 0U)) { + Status = XST_INVALID_PARAM; + } + else { + (void)memset(Dest, (s32)Data, Len); + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function concatenates two strings. This function + * takes size of both strings to make sure not to read from / + * write to out of bound area. + * + * @param DestStr - Pointer to destination string + * @param DestSize - Maximum string size that detination can hold + * @param SrcStr - Pointer to source string + * @param SrcSize - Maximum string size that source can hold + * + * @return + * XST_SUCCESS - Copy is successful + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SStrCat (u8 *DestStr, const u32 DestSize, + const u8 *SrcStr, const u32 SrcSize) +{ + int Status = XST_FAILURE; + u32 SrcLen; + u32 DstLen; + + if ((DestStr == NULL) || (SrcStr == NULL)) { + Status = XST_INVALID_PARAM; + goto END; + } + + SrcLen = strnlen((const char*)SrcStr, SrcSize); + DstLen = strnlen((const char*)DestStr, DestSize); + + if ((DestSize <= DstLen) || (SrcSize <= SrcLen)) { + Status = XST_INVALID_PARAM; + } + else if (DestSize <= (SrcLen + DstLen)) { + Status = XST_INVALID_PARAM; + } + else { + (void)strcat((char*)DestStr, (const char*)SrcStr); + Status = XST_SUCCESS; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function compares two strings. It also takes maximum string + * size that Src1 and Src2 can hold to make sure not to read out of + * bound data for comparison. + * + * @param Str1 - Pointer to first string + * @param Str1Size - Maximum string size that Str1 can hold + * @param Str2 - Pointer to second string + * @param Str2Size - Maximum string size that Str2 can hold + * + * @return + * XST_SUCCESS - If both strings are same + * XST_FAILURE - If there is difference between two strings + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SStrCmp(const u8 *Str1, const u32 Str1Size, + const u8 *Str2, const u32 Str2Size) +{ + int Status = XST_FAILURE; + u32 Str1Len = 0U; + u32 Str2Len = 0U; + + if ((Str1 == NULL) || (Str2 == NULL)) { + Status = XST_INVALID_PARAM; + goto END; + } + + Str1Len = strnlen((const char*)Str1, Str1Size); + Str2Len = strnlen((const char*)Str2, Str2Size); + + if ((Str1Size <= Str1Len) || (Str2Size <= Str2Len)) { + Status = XST_INVALID_PARAM; + } + else if ((Str1Len < Str2Len) || (Str1Len > Str2Len)) { + Status = XST_FAILURE; + } + else { + Status = memcmp(Str1, Str2, Str1Len); + if (Status != 0) { + Status = XST_FAILURE; + } + } + +END: + return Status; +} + + +/*****************************************************************************/ +/** + * @brief This function compares two strings. It also takes maximum string + * size that Src1 and Src2 can hold to make sure not to read out of + * bound data for comparison. This function compares each character + * of the strings so that execution time of the function is not + * dependent on the content of two input strings. The execution + * time is constant when string size are same. + * + * @param Str1 - Pointer to first string + * @param Str1Size - Maximum string size that Str1 can hold + * @param Str2 - Pointer to second string + * @param Str2Size - Maximum string size that Str2 can hold + * + * @return + * XST_SUCCESS - If both strings are same + * XST_FAILURE - If there is difference between two strings + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SStrCmp_CT (const u8 *Str1, const u32 Str1Size, + const u8 *Str2, const u32 Str2Size) +{ + int Status = XST_FAILURE; + u32 Str1Len = 0U; + u32 Str2Len = 0U; + + if ((Str1 == NULL) || (Str2 == NULL)) { + Status = XST_INVALID_PARAM; + goto END; + } + + Str1Len = strnlen((const char*)Str1, Str1Size); + Str2Len = strnlen((const char*)Str2, Str2Size); + + if ((Str1Size <= Str1Len) || (Str2Size <= Str2Len)) { + Status = XST_INVALID_PARAM; + } + else if (Str1Len != Str2Len) { + Status = XST_FAILURE; + } + else { + Status = Xil_SMemCmp_CT (Str1, Str1Size, Str2, Str2Size, Str1Len); + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function copies one string to other. This function + * takes size of both strings to make sure not to read from / + * write to out of bound area. + * + * @param DestStr - Pointer to destination string + * @param DestSize - Maximum string size that detination can hold + * @param SrcStr - Pointer to source string + * @param SrcSize - Maximum string size that source can hold + * + * @return + * XST_SUCCESS - Copy is successful + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SStrCpy(u8 *DestStr, const u32 DestSize, + const u8 *SrcStr, const u32 SrcSize) +{ + int Status = XST_FAILURE; + u32 SrcLen = 0U; + + if ((DestStr == NULL) || (SrcStr == NULL)) { + Status = XST_INVALID_PARAM; + goto END; + } + + SrcLen = strnlen((const char*)SrcStr, SrcSize); + + if ((DestSize <= SrcLen) || (SrcSize <= SrcLen)) { + Status = XST_INVALID_PARAM; + } + else { + (void)memcpy(DestStr, SrcStr, SrcLen + 1U); + Status = XST_SUCCESS; + } + +END: + return Status; +} + +/*****************************************************************************/ +/** + * @brief This is wrapper function to memmove function. This function + * takes size of two memory regions to avoid out of bound memory region. + * + * @param Dest - Pointer to destination memory + * @param DestSize - Memory available at destination + * @param Src - Pointer to source memory + * @param SrcSize - Maximum data that can be copied from source + * @param CopyLen - Number of bytes to be copied + * + * @return + * XST_SUCCESS - Copy is successful + * XST_INVALID_PARAM - Invalid inputs + * + *****************************************************************************/ +int Xil_SMemMove(void *Dest, const u32 DestSize, + const void *Src, const u32 SrcSize, const u32 CopyLen) +{ + volatile int Status = XST_FAILURE; + const void *Output = NULL; + + if ((Dest == NULL) || (Src == NULL)) { + Status = XST_INVALID_PARAM; + } + else if ((CopyLen == 0U) || (DestSize < CopyLen) || (SrcSize < CopyLen)) { + Status = XST_INVALID_PARAM; + } + else { + Output = memmove(Dest, Src, CopyLen); + if (Output != NULL) { + Status = XST_SUCCESS; + } + } + + return Status; +} + +/****************************************************************************/ +/* + * Waits for the event to be set with in timeout and returns error incase + * event was not set in specified time out. + * + * @param Timeout - Max number of microseconds to wait for an event, + * It should be maximum timeout needed among the + * events specified. + * @param NumOfEvents - Number of event(s) to be checked. + * @param EventAddr - Pointer to address of event(s) to be set. + * + * @return + * XST_SUCCESS - On occurrence of the event(s). + * XST_FAILURE - Event(s) did not occur before counter reaches 0 + * + * @note None. + * + *****************************************************************************/ +u32 Xil_WaitForEventSet(u32 Timeout, u32 NumOfEvents, volatile u32 *EventAddr, ...) +{ + u32 PollCount = Timeout; + u32 Status = XST_FAILURE; + u32 LoopCnt = 0, i; + va_list Event; + + va_start(Event, EventAddr); + /* wait for all events to complete */ + for (i = 0; i < NumOfEvents; i++) { + while(PollCount > 0U) { + if (Xil_In32((UINTPTR)EventAddr)) { + LoopCnt++; + break; + } + PollCount--; +#ifdef VERSAL_PLM + Xil_PlmStubHandler(); +#endif + usleep(1U); + } + if (PollCount == 0U) { + goto END; + } + EventAddr = va_arg(Event, volatile u32 *); + PollCount = Timeout; + } + va_end(Event); + +END: + if (LoopCnt == NumOfEvents) { + Status = XST_SUCCESS; + } + + return Status; +} + +/****************************************************************************/ +/** + * @brief + * Performs a Read Modify Write operation for a memory location by writing the + * 32 bit value to the the specified address and then reading it back to + * verify the value written in the register. + * + * @param Addr contains the address to perform the output operation + * @param Mask indicates the bits to be modified + * @param Value contains 32 bit Value to be written at the specified address + * + * @return + * XST_SUCCESS on success + * XST_FAILURE on failure + * + *****************************************************************************/ +s32 Xil_SecureRMW32(UINTPTR Addr, u32 Mask, u32 Value) +{ + s32 Status = XST_FAILURE; + u32 ReadReg; + u32 Val; + + Val = Xil_In32(Addr); + Val = (Val & (~Mask)) | (Mask & Value); + Xil_Out32(Addr, Val); + + /* verify value written to specified address */ + ReadReg = Xil_In32(Addr) & Mask; + + if(ReadReg == (Mask & Value)) { + Status = XST_SUCCESS; + } + + return Status; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_util.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_util.h new file mode 100644 index 0000000..d65854c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xil_util.h @@ -0,0 +1,318 @@ +/******************************************************************************/ +/** +* Copyright (c) 2019 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* @file xil_util.h +* @addtogroup common_utilities Common Utility APIs +* @{ +* @details +* +* xil_util.h file contains xil utility functions declarations +* Except few functions, most of these functions are wrappers to standard functions. +* The standard string functions do not validate the input and that results into +* buffer overflows. To avoid it, the wrapper function validates the input and +* then passed to standard function. There are few constant time functions +* ( xxx_CT() ) which are used to compare the data in constant time. +* The constant time functions should be used while comparing secure data +* like password, keys which prevent disclosing of the data using +* timing analysis. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 6.4   mmd      04/21/19 First release.
+* 6.5   kal      02/29/20 Added Xil_ConvertStringToHexBE API
+* 7.3   kal      06/30/20 Converted Xil_Ceil macro to API
+*       rpo      08/19/20 Added function for read, modify and write
+*       bsv      08/21/20 Added XSECURE_TEMPORAL_CHECK macro to add
+*                         redundancy in security critical functions, to avoid
+*                         glitches from altering the return values of security
+*                         critical functions. The macro requires a label to be
+*                         passed to "go to" in case of error.
+*      kpt       09/03/20 Added XSECURE_TEMPORAL_IMPL macro for redundancy
+*      kal       09/22/20 Changed the param type from const char to const char*
+*                         to avoid copying key onto stack
+*      td        10/16/20 Added Xil_Strcpy, Xil_Strcat, Xil_SecureMemCpy and
+*                         Xil_MemCmp functions
+*      am        10/13/20 Resolved Coverity warning
+*      td        11/19/20 Updated XSECURE_TEMPORAL_CHECK and
+*                         XSECURE_TEMPORAL_IMPL to fix MISRA C Rule 15.3
+* 7.4  am        11/26/20 Added Xil_StrCpyRange function
+* 7.6  kpt       07/15/21 Added Xil_SecureZeroize function
+* 7.7  kpt       11/09/21 Added Xil_SMemCmp, Xil_SMemCmp_CT, Xil_SMemCpy,
+*                         Xil_SMemSet, Xil_SStrCat, Xil_SStrCmp, Xil_SStrCmp_CT
+*                         Xil_SStrCpy functions
+* 7.7	sk	 01/10/22 Update functions return type to fix misra_c_2012_
+* 			  directive_4_6 violations.
+*      mmd       02/28/22 Added Xil_SMemMove function prototype
+* 8.0  adk       04/18/22 Added Xil_WaitForEventSet function prototype.
+*      ssc       08/25/22 Added Xil_SecureRMW32 prototype
+* 8.1  sa        09/29/22 Change the type of first argument passed to Xil_WaitForEvent
+*			  API from u32 to UINTPTR for supporting 64 bit addressing.
+* 8.1  sa        10/20/22 Change the type of first argument passed to Xil_WaitForEvents
+*                         API from u32 to UINTPTR for supporting 64 bit addressing.
+* 8.1  akm       01/02/23 Added Xil_RegisterPlmHandler() & Xil_PlmStubHandler() APIs.
+*      bm        03/14/23 Added XSECURE_REDUNDANT_CALL and XSECURE_REDUNDANT_IMPL macros
+*      sk        03/14/23 Added Status Check Glitch detect Macro
+* 
+* +*****************************************************************************/ + +#ifndef XIL_UTIL_H_ +#define XIL_UTIL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_types.h" +#include "xil_io.h" +#include "xstatus.h" + +/*************************** Constant Definitions *****************************/ +#define XIL_SIZE_OF_NIBBLE_IN_BITS 4U +#define XIL_SIZE_OF_BYTE_IN_BITS 8U + +/* Maximum string length handled by Xil_ValidateHexStr function */ +#define XIL_MAX_HEX_STR_LEN 512U + + +/****************** Macros (Inline Functions) Definitions *********************/ +#ifdef __GNUC__ +/******************************************************************************/ +/** + * + * Updates the return value of the called function into Var and VarTmp variables + * for redundancy. This is to avoid glitches from altering the return values of + * security critical functions. + * + * @param Var is the variable which holds the return value of function + * executed + * @param VarTmp is the variable which holds the value stored in Var + * @param Function is the function to be executed + * @param Other params are arguments to the called function + * + * @return None + * + ******************************************************************************/ +#define XSECURE_TEMPORAL_IMPL(Var, VarTmp, Function, ...) \ + { \ + Var = XST_FAILURE; \ + VarTmp = XST_FAILURE; \ + Var = Function(__VA_ARGS__); \ + VarTmp = Var; \ + } + +/******************************************************************************/ +/** + * + * Adds redundancy while checking the status of the called function. + * This is to avoid glitches from altering the return values of security + * critical functions. The macro requires a label to be passed to "go to" + * in case of error. + * + * @param Label is the label defined in function and the control + * will jump to the label in case of XST_FAILURE + * @param Status is the variable which holds the return value of + * function executed + * @param Function is the function to be executed + * @param Other params are arguments to the called function + * + * @return None + * + ******************************************************************************/ +#define XSECURE_TEMPORAL_CHECK(Label, Status, Function, ...) \ + { \ + volatile int StatusTmp; \ + XSECURE_TEMPORAL_IMPL(Status, StatusTmp, Function, __VA_ARGS__); \ + if ((Status != XST_SUCCESS) || \ + (StatusTmp != XST_SUCCESS)) { \ + if (((Status) != (StatusTmp)) || \ + (Status == XST_SUCCESS)) { \ + Status = XST_GLITCH_ERROR; \ + }\ + goto Label; \ + } \ + } + +/******************************************************************************/ +/** + * + * Adds redundancy to the function call. This is to avoid glitches which can skip + * a function call and cause altering of the code flow in security critical + * functions. + * + * @param Status is the variable which holds the return value of + * function executed + * @param StatusTmp is the variable which holds the return value of + * redundant function call executed + * @param Function is the function to be executed + * @param Other params are arguments to the called function + * + * @return None + * + ******************************************************************************/ +#define XSECURE_REDUNDANT_CALL(Status, StatusTmp, Function, ...) \ + { \ + Status = Function(__VA_ARGS__); \ + StatusTmp = Function(__VA_ARGS__); \ + } + +/******************************************************************************/ +/** + * + * Adds redundancy to the function call. This is to avoid glitches which can skip + * a function call and cause altering of the code flow in security critical + * functions. + * + * @param Function is the function to be executed + * @param Other params are arguments to the called function + * + * @return None + * + ******************************************************************************/ +#define XSECURE_REDUNDANT_IMPL(Function, ...) \ + { \ + Function(__VA_ARGS__); \ + Function(__VA_ARGS__); \ + } + +/******************************************************************************/ +/** + * + * This Macro helps to detect glitches skipping the Status check + * in case of error. + * + * @param None + * + * @return None + * + ******************************************************************************/ +#define XSECURE_STATUS_CHK_GLITCH_DETECT(Status) \ + { \ + if (Status == XST_SUCCESS) { \ + Status = (int)XST_GLITCH_ERROR; \ + } \ + } + +#endif +/*************************** Function Prototypes ******************************/ +/* Ceils the provided float value */ +s32 Xil_Ceil(float Value); + +/* Converts input character to nibble */ +u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num); + +/* Convert input hex string to array of 32-bits integers */ +u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len); + +#ifdef VERSAL_PLM +/* Register PLM handler */ +void Xil_RegisterPlmHandler(void (*PlmAlive) (void)); + +/* Call PLM handler */ +void Xil_PlmStubHandler(void); +#endif + +/* Waits for specified event */ +u32 Xil_WaitForEvent(UINTPTR RegAddr, u32 EventMask, u32 Event, u32 Timeout); + +/* Waits for specified events */ +u32 Xil_WaitForEvents(UINTPTR EventsRegAddr, u32 EventsMask, u32 WaitEvents, + u32 Timeout, u32* Events); + +/* Validate input hex character */ +u32 Xil_IsValidHexChar(const char *Ch); + +/* Validate the input string contains only hexadecimal characters */ +u32 Xil_ValidateHexStr(const char *HexStr); + +/* Convert string to hex numbers in little enidian format */ +u32 Xil_ConvertStringToHexLE(const char *Str, u8 *Buf, u32 Len); + +/* Returns length of the input string */ +u32 Xil_Strnlen(const char *Str, u32 MaxLen); + +/* Convert string to hex numbers in big endian format */ +u32 Xil_ConvertStringToHexBE(const char * Str, u8 * Buf, u32 Len); + +/*Read, Modify and Write to an address*/ +void Xil_UtilRMW32(u32 Addr, u32 Mask, u32 Value); + +/* Copies source string to destination string */ +int Xil_Strcpy(char *DestPtr, const char *SrcPtr, const u32 Size); + +/* Copies specified range from source string to destination string */ +int Xil_StrCpyRange(const u8 *Src, u8 *Dest, u32 From, u32 To, u32 MaxSrcLen, + u32 MaxDstLen); + +/* Appends string2 to string1 */ +int Xil_Strcat(char* Str1Ptr, const char* Str2Ptr, const u32 Size); + +/* Copies Len bytes from source memory to destination memory */ +int Xil_SecureMemCpy(void * DestPtr, u32 DestPtrLen, const void * SrcPtr, u32 Len); + +/* Compares Len bytes from memory1 and memory2 */ +int Xil_MemCmp(const void * Buf1Ptr, const void * Buf2Ptr, u32 Len); + +/* Zeroizes the memory of given length */ +int Xil_SecureZeroize(u8 *DataPtr, const u32 Length); + +/* Copies Len bytes from source memory to destination memory */ +int Xil_SMemCpy (void *Dest, const u32 DestSize, + const void *Src, const u32 SrcSize, const u32 CopyLen); + +/* Copies Len bytes from source memory to destination memory, allows + overlapped memory between source and destination */ +int Xil_SMemMove(void *Dest, const u32 DestSize, + const void *Src, const u32 SrcSize, const u32 CopyLen); + +/* Compares Len bytes between source and destination memory */ +int Xil_SMemCmp (const void *Src1, const u32 Src1Size, + const void *Src2, const u32 Src2Size, const u32 CmpLen); + +/* Compares Len bytes between source and destination memory with constant time */ +int Xil_SMemCmp_CT (const void *Src1, const u32 Src1Size, + const void *Src2, const u32 Src2Size, const u32 CmpLen); + +/* Sets the destination memory of given length with given data */ +int Xil_SMemSet (void *Dest, const u32 DestSize, + const u8 Data, const u32 Len); + +/* Copies source string to destination string */ +int Xil_SStrCpy (u8 *DestStr, const u32 DestSize, + const u8 *SrcStr, const u32 SrcSize); + +/* Compares source string with destination string */ +int Xil_SStrCmp (const u8 *Str1, const u32 Str1Size, + const u8 *Str2, const u32 Str2Size); + +/* Compares source string with destination string with constant time */ +int Xil_SStrCmp_CT (const u8 *Str1, const u32 Str1Size, + const u8 *Str2, const u32 Str2Size); + +/* Concatenates source string to destination string */ +int Xil_SStrCat (u8 *DestStr, const u32 DestSize, + const u8 *SrcStr, const u32 SrcSize); + +/* Waits for event timeout */ +u32 Xil_WaitForEventSet(u32 Timeout, u32 NumOfEvents, volatile u32 *EventAddr, ...); + +/* Implements Read Modify Writes securely */ +s32 Xil_SecureRMW32(UINTPTR Addr, u32 Mask, u32 Value); + +#ifdef __cplusplus +} +#endif + +#endif /* XIL_UTIL_H_ */ +/** +* @} End of "addtogroup common_utilities". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc.h new file mode 100644 index 0000000..4df6d87 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc.h @@ -0,0 +1,155 @@ +/****************************************************************************** +* Copyright (c) 2011 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xl2cc.h +* +* This file contains the address definitions for the PL310 Level-2 Cache +* Controller. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 1.00a sdm  02/01/10 Initial version
+* 3.10a srt 04/18/13 Implemented ARM Erratas. Please refer to file
+*		      'xil_errata.h' for errata description
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef _XL2CC_H_ +#define _XL2CC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions *****************************/ +/* L2CC Register Offsets */ +#define XPS_L2CC_ID_OFFSET 0x0000U +#define XPS_L2CC_TYPE_OFFSET 0x0004U +#define XPS_L2CC_CNTRL_OFFSET 0x0100U +#define XPS_L2CC_AUX_CNTRL_OFFSET 0x0104U +#define XPS_L2CC_TAG_RAM_CNTRL_OFFSET 0x0108U +#define XPS_L2CC_DATA_RAM_CNTRL_OFFSET 0x010CU + +#define XPS_L2CC_EVNT_CNTRL_OFFSET 0x0200U +#define XPS_L2CC_EVNT_CNT1_CTRL_OFFSET 0x0204U +#define XPS_L2CC_EVNT_CNT0_CTRL_OFFSET 0x0208U +#define XPS_L2CC_EVNT_CNT1_VAL_OFFSET 0x020CU +#define XPS_L2CC_EVNT_CNT0_VAL_OFFSET 0x0210U + +#define XPS_L2CC_IER_OFFSET 0x0214U /* Interrupt Mask */ +#define XPS_L2CC_IPR_OFFSET 0x0218U /* Masked interrupt status */ +#define XPS_L2CC_ISR_OFFSET 0x021CU /* Raw Interrupt Status */ +#define XPS_L2CC_IAR_OFFSET 0x0220U /* Interrupt Clear */ + +#define XPS_L2CC_CACHE_SYNC_OFFSET 0x0730U /* Cache Sync */ +#define XPS_L2CC_DUMMY_CACHE_SYNC_OFFSET 0x0740U /* Dummy Register for Cache Sync */ +#define XPS_L2CC_CACHE_INVLD_PA_OFFSET 0x0770U /* Cache Invalid by PA */ +#define XPS_L2CC_CACHE_INVLD_WAY_OFFSET 0x077CU /* Cache Invalid by Way */ +#define XPS_L2CC_CACHE_CLEAN_PA_OFFSET 0x07B0U /* Cache Clean by PA */ +#define XPS_L2CC_CACHE_CLEAN_INDX_OFFSET 0x07B8U /* Cache Clean by Index */ +#define XPS_L2CC_CACHE_CLEAN_WAY_OFFSET 0x07BCU /* Cache Clean by Way */ +#define XPS_L2CC_CACHE_INV_CLN_PA_OFFSET 0x07F0U /* Cache Invalidate and Clean by PA */ +#define XPS_L2CC_CACHE_INV_CLN_INDX_OFFSET 0x07F8U /* Cache Invalidate and Clean by Index */ +#define XPS_L2CC_CACHE_INV_CLN_WAY_OFFSET 0x07FCU /* Cache Invalidate and Clean by Way */ + +#define XPS_L2CC_CACHE_DLCKDWN_0_WAY_OFFSET 0x0900U /* Cache Data Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_0_WAY_OFFSET 0x0904U /* Cache Instruction Lockdown 0 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_1_WAY_OFFSET 0x0908U /* Cache Data Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_1_WAY_OFFSET 0x090CU /* Cache Instruction Lockdown 1 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_2_WAY_OFFSET 0x0910U /* Cache Data Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_2_WAY_OFFSET 0x0914U /* Cache Instruction Lockdown 2 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_3_WAY_OFFSET 0x0918U /* Cache Data Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_3_WAY_OFFSET 0x091CU /* Cache Instruction Lockdown 3 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_4_WAY_OFFSET 0x0920U /* Cache Data Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_4_WAY_OFFSET 0x0924U /* Cache Instruction Lockdown 4 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_5_WAY_OFFSET 0x0928U /* Cache Data Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_5_WAY_OFFSET 0x092CU /* Cache Instruction Lockdown 5 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_6_WAY_OFFSET 0x0930U /* Cache Data Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_6_WAY_OFFSET 0x0934U /* Cache Instruction Lockdown 6 by Way */ +#define XPS_L2CC_CACHE_DLCKDWN_7_WAY_OFFSET 0x0938U /* Cache Data Lockdown 7 by Way */ +#define XPS_L2CC_CACHE_ILCKDWN_7_WAY_OFFSET 0x093CU /* Cache Instruction Lockdown 7 by Way */ + +#define XPS_L2CC_CACHE_LCKDWN_LINE_ENABLE_OFFSET 0x0950U /* Cache Lockdown Line Enable */ +#define XPS_L2CC_CACHE_UUNLOCK_ALL_WAY_OFFSET 0x0954U /* Cache Unlock All Lines by Way */ + +#define XPS_L2CC_ADDR_FILTER_START_OFFSET 0x0C00U /* Start of address filtering */ +#define XPS_L2CC_ADDR_FILTER_END_OFFSET 0x0C04U /* Start of address filtering */ + +#define XPS_L2CC_DEBUG_CTRL_OFFSET 0x0F40U /* Debug Control Register */ + +/* XPS_L2CC_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_ENABLE_MASK 0x00000001U /* enables the L2CC */ + +/* XPS_L2CC_AUX_CNTRL_OFFSET bit masks */ +#define XPS_L2CC_AUX_EBRESPE_MASK 0x40000000U /* Early BRESP Enable */ +#define XPS_L2CC_AUX_IPFE_MASK 0x20000000U /* Instruction Prefetch Enable */ +#define XPS_L2CC_AUX_DPFE_MASK 0x10000000U /* Data Prefetch Enable */ +#define XPS_L2CC_AUX_NSIC_MASK 0x08000000U /* Non-secure interrupt access control */ +#define XPS_L2CC_AUX_NSLE_MASK 0x04000000U /* Non-secure lockdown enable */ +#define XPS_L2CC_AUX_CRP_MASK 0x02000000U /* Cache replacement policy */ +#define XPS_L2CC_AUX_FWE_MASK 0x01800000U /* Force write allocate */ +#define XPS_L2CC_AUX_SAOE_MASK 0x00400000U /* Shared attribute override enable */ +#define XPS_L2CC_AUX_PE_MASK 0x00200000U /* Parity enable */ +#define XPS_L2CC_AUX_EMBE_MASK 0x00100000U /* Event monitor bus enable */ +#define XPS_L2CC_AUX_WAY_SIZE_MASK 0x000E0000U /* Way-size */ +#define XPS_L2CC_AUX_ASSOC_MASK 0x00010000U /* Associativity */ +#define XPS_L2CC_AUX_SAIE_MASK 0x00002000U /* Shared attribute invalidate enable */ +#define XPS_L2CC_AUX_EXCL_CACHE_MASK 0x00001000U /* Exclusive cache configuration */ +#define XPS_L2CC_AUX_SBDLE_MASK 0x00000800U /* Store buffer device limitation Enable */ +#define XPS_L2CC_AUX_HPSODRE_MASK 0x00000400U /* High Priority for SO and Dev Reads Enable */ +#define XPS_L2CC_AUX_FLZE_MASK 0x00000001U /* Full line of zero enable */ + +#define XPS_L2CC_AUX_REG_DEFAULT_MASK 0x72360000U /* Enable all prefetching, */ + /* Cache replacement policy, Parity enable, */ + /* Event monitor bus enable and Way Size (64 KB) */ +#define XPS_L2CC_AUX_REG_ZERO_MASK 0xFFF1FFFFU /* */ + +#define XPS_L2CC_TAG_RAM_DEFAULT_MASK 0x00000111U /* latency for TAG RAM */ +#define XPS_L2CC_DATA_RAM_DEFAULT_MASK 0x00000121U /* latency for DATA RAM */ + +/* Interrupt bit masks */ +#define XPS_L2CC_IXR_DECERR_MASK 0x00000100U /* DECERR from L3 */ +#define XPS_L2CC_IXR_SLVERR_MASK 0x00000080U /* SLVERR from L3 */ +#define XPS_L2CC_IXR_ERRRD_MASK 0x00000040U /* Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_ERRRT_MASK 0x00000020U /* Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ERRWD_MASK 0x00000010U /* Error on L2 data RAM (Write) */ +#define XPS_L2CC_IXR_ERRWT_MASK 0x00000008U /* Error on L2 tag RAM (Write) */ +#define XPS_L2CC_IXR_PARRD_MASK 0x00000004U /* Parity Error on L2 data RAM (Read) */ +#define XPS_L2CC_IXR_PARRT_MASK 0x00000002U /* Parity Error on L2 tag RAM (Read) */ +#define XPS_L2CC_IXR_ECNTR_MASK 0x00000001U /* Event Counter1/0 Overflow Increment */ + +/* Address filtering mask and enable bit */ +#define XPS_L2CC_ADDR_FILTER_VALID_MASK 0xFFF00000U /* Address filtering valid bits*/ +#define XPS_L2CC_ADDR_FILTER_ENABLE_MASK 0x00000001U /* Address filtering enable bit*/ + +/* Debug control bits */ +#define XPS_L2CC_DEBUG_SPIDEN_MASK 0x00000004U /* Debug SPIDEN bit */ +#define XPS_L2CC_DEBUG_DWB_MASK 0x00000002U /* Debug DWB bit, forces write through */ +#define XPS_L2CC_DEBUG_DCL_MASK 0x00000002U /* Debug DCL bit, disables cache line fill */ + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ + +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc_counter.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc_counter.c new file mode 100644 index 0000000..ea3a08c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc_counter.c @@ -0,0 +1,133 @@ +/****************************************************************************** +* Copyright (c) 2011 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xl2cc_counter.c +* +* This file contains APIs for configuring and controlling the event counters +* in PL310 L2 cache controller. For more information about the event counters, +* see xl2cc_counter.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 3.07a asa  08/30/12 Updated for CR 675636 to provide the L2 Base Address
+*		      inside the APIs
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include +#include "xparameters_ps.h" +#include "xl2cc_counter.h" +#include "xl2cc.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void XL2cc_EventCtrReset(void); + +/******************************************************************************/ + +/****************************************************************************/ +/** +* +* @brief This function initializes the event counters in L2 Cache controller +* with a set of event codes specified by the user. +* +* @param Event0: Event code for counter 0. +* @param Event1: Event code for counter 1. +* +* @return None. +* +* @note The definitions for event codes XL2CC_* can be found in +* xl2cc_counter.h. +* +*****************************************************************************/ +void XL2cc_EventCtrInit(s32 Event0, s32 Event1) +{ + + /* Write event code into cnt1 cfg reg */ + *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT1_CTRL_OFFSET)) = (((u32)Event1) << 2); + + /* Write event code into cnt0 cfg reg */ + *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT0_CTRL_OFFSET)) = (((u32)Event0) << 2); + + /* Reset counters */ + XL2cc_EventCtrReset(); +} + + +/****************************************************************************/ +/** +* +* @brief This function starts the event counters in L2 Cache controller. +* +* @return None. +* +*****************************************************************************/ +void XL2cc_EventCtrStart(void) +{ + u32 *LocalPtr; + LocalPtr = (u32 *)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET); + XL2cc_EventCtrReset(); + + /* Enable counter */ + /* *((volatile u32*)((void *)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET))) = 1 */ + *LocalPtr = (u32)1; +} + +/****************************************************************************/ +/** +* +* @brief This function disables the event counters in L2 Cache controller, +* saves the counter values and resets the counters. +* +* @param EveCtr0: Output parameter which is used to return the value +* in event counter 0. +* @param EveCtr1: Output parameter which is used to return the value +* in event counter 1. +* +* @return None. +* +*****************************************************************************/ +void XL2cc_EventCtrStop(u32 *EveCtr0, u32 *EveCtr1) +{ + /* Disable counter */ + *((volatile u32*) (XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET)) = 0U; + + /* Save counter values */ + *EveCtr1 = *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT1_VAL_OFFSET)); + *EveCtr0 = *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNT0_VAL_OFFSET)); + + XL2cc_EventCtrReset(); +} + +/****************************************************************************/ +/** +* +* @brief This function resets the event counters in L2 Cache controller. +* +* @return None. +* +*****************************************************************************/ +void XL2cc_EventCtrReset(void) +{ + *((volatile u32*)(XPS_L2CC_BASEADDR + XPS_L2CC_EVNT_CNTRL_OFFSET)) = 0x6U; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc_counter.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc_counter.h new file mode 100644 index 0000000..31156ee --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xl2cc_counter.h @@ -0,0 +1,96 @@ +/****************************************************************************** +* Copyright (c) 2011 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xl2cc_counter.h +* +* @addtogroup l2_event_counter_apis PL310 L2 Event Counters Functions +* +* xl2cc_counter.h contains APIs for configuring and controlling the event +* counters in PL310 L2 cache controller. +* PL310 has two event counters which can be used to count variety of events +* like DRHIT, DRREQ, DWHIT, DWREQ, etc. xl2cc_counter.h contains definitions +* for different configurations which can be used for the event counters to +* count a set of events. +* +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 3.07a asa  08/30/12 Updated for CR 675636 to provide the L2 Base Address
+*		      inside the APIs
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef L2CCCOUNTER_H /* prevent circular inclusions */ +#define L2CCCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* + * The following constants define the event codes for the event counters. + */ +#define XL2CC_CO 0x1 +#define XL2CC_DRHIT 0x2 +#define XL2CC_DRREQ 0x3 +#define XL2CC_DWHIT 0x4 +#define XL2CC_DWREQ 0x5 +#define XL2CC_DWTREQ 0x6 +#define XL2CC_IRHIT 0x7 +#define XL2CC_IRREQ 0x8 +#define XL2CC_WA 0x9 +#define XL2CC_IPFALLOC 0xa +#define XL2CC_EPFHIT 0xb +#define XL2CC_EPFALLOC 0xc +#define XL2CC_SRRCVD 0xd +#define XL2CC_SRCONF 0xe +#define XL2CC_EPFRCVD 0xf + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/** +*@endcond +*/ + +/************************** Function Prototypes *****************************/ + +void XL2cc_EventCtrInit(s32 Event0, s32 Event1); +void XL2cc_EventCtrStart(void); +void XL2cc_EventCtrStop(u32 *EveCtr0, u32 *EveCtr1); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* L2CCCOUNTER_H */ +/** +* @} End of "addtogroup l2_event_counter_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xparameters_ps.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xparameters_ps.h new file mode 100644 index 0000000..f8b4e00 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xparameters_ps.h @@ -0,0 +1,334 @@ +/****************************************************************************** +* Copyright (c) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xparameters_ps.h +* +* This file contains the address definitions for the hard peripherals +* attached to the ARM Cortex A9 core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 02/01/10 Initial version
+* 3.04a sdm     02/02/12 Removed some of the defines as they are being generated through
+*                        driver tcl
+* 5.0	pkp		01/16/15 Added interrupt ID definition of ttc for TEST APP
+* 6.6   srm     10/18/17 Added ARMA9 macro to identify CortexA9
+*
+* 
+* +* @note +* +* None. +* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef _XPARAMETERS_PS_H_ +#define _XPARAMETERS_PS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************** Include Files *******************************/ + + +/************************** Constant Definitions *****************************/ + +/* + * This block contains constant declarations for the peripherals + * within the hardblock + */ + +/* Canonical definitions for DDR MEMORY */ +#define XPAR_DDR_MEM_BASEADDR 0x00000000U +#define XPAR_DDR_MEM_HIGHADDR 0x3FFFFFFFU + +/* Canonical definitions for Interrupts */ +#define XPAR_XUARTPS_0_INTR XPS_UART0_INT_ID +#define XPAR_XUARTPS_1_INTR XPS_UART1_INT_ID +#define XPAR_XUSBPS_0_INTR XPS_USB0_INT_ID +#define XPAR_XUSBPS_1_INTR XPS_USB1_INT_ID +#define XPAR_XIICPS_0_INTR XPS_I2C0_INT_ID +#define XPAR_XIICPS_1_INTR XPS_I2C1_INT_ID +#define XPAR_XSPIPS_0_INTR XPS_SPI0_INT_ID +#define XPAR_XSPIPS_1_INTR XPS_SPI1_INT_ID +#define XPAR_XCANPS_0_INTR XPS_CAN0_INT_ID +#define XPAR_XCANPS_1_INTR XPS_CAN1_INT_ID +#define XPAR_XGPIOPS_0_INTR XPS_GPIO_INT_ID +#define XPAR_XEMACPS_0_INTR XPS_GEM0_INT_ID +#define XPAR_XEMACPS_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_XEMACPS_1_INTR XPS_GEM1_INT_ID +#define XPAR_XEMACPS_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_XSDIOPS_0_INTR XPS_SDIO0_INT_ID +#define XPAR_XQSPIPS_0_INTR XPS_QSPI_INT_ID +#define XPAR_XSDIOPS_1_INTR XPS_SDIO1_INT_ID +#define XPAR_XWDTPS_0_INTR XPS_WDT_INT_ID +#define XPAR_XDCFG_0_INTR XPS_DVC_INT_ID +#define XPAR_SCUTIMER_INTR XPS_SCU_TMR_INT_ID +#define XPAR_SCUWDT_INTR XPS_SCU_WDT_INT_ID +#define XPAR_XTTCPS_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_XTTCPS_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_XTTCPS_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_XTTCPS_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_XTTCPS_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_XTTCPS_5_INTR XPS_TTC1_2_INT_ID +#define XPAR_XDMAPS_0_FAULT_INTR XPS_DMA0_ABORT_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_0 XPS_DMA0_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_1 XPS_DMA1_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_2 XPS_DMA2_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_3 XPS_DMA3_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_4 XPS_DMA4_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_5 XPS_DMA5_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_6 XPS_DMA6_INT_ID +#define XPAR_XDMAPS_0_DONE_INTR_7 XPS_DMA7_INT_ID + + +#define XPAR_XQSPIPS_0_LINEAR_BASEADDR XPS_QSPI_LINEAR_BASEADDR +#define XPAR_XPARPORTPS_CTRL_BASEADDR XPS_PARPORT_CRTL_BASEADDR + + + +/* Canonical definitions for DMAC */ + + +/* Canonical definitions for WDT */ + +/* Canonical definitions for SLCR */ +#define XPAR_XSLCR_NUM_INSTANCES 1U +#define XPAR_XSLCR_0_DEVICE_ID 0U +#define XPAR_XSLCR_0_BASEADDR XPS_SYS_CTRL_BASEADDR + +/* Canonical definitions for SCU GIC */ +#define XPAR_SCUGIC_NUM_INSTANCES 1U +#define XPAR_SCUGIC_SINGLE_DEVICE_ID 0U +#define XPAR_SCUGIC_CPU_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000100U) +#define XPAR_SCUGIC_DIST_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00001000U) +#define XPAR_SCUGIC_ACK_BEFORE 0U + +/* Canonical definitions for Global Timer */ +#define XPAR_GLOBAL_TMR_NUM_INSTANCES 1U +#define XPAR_GLOBAL_TMR_DEVICE_ID 0U +#define XPAR_GLOBAL_TMR_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000200U) +#define XPAR_GLOBAL_TMR_INTR XPS_GLOBAL_TMR_INT_ID + + +/* Xilinx Parallel Flash Library (XilFlash) User Settings */ +#define XPAR_AXI_EMC + + +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ + + +/* + * This block contains constant declarations for the peripherals + * within the hardblock. These have been put for bacwards compatibility + */ + +#define XPS_PERIPHERAL_BASEADDR 0xE0000000U +#define XPS_UART0_BASEADDR 0xE0000000U +#define XPS_UART1_BASEADDR 0xE0001000U +#define XPS_USB0_BASEADDR 0xE0002000U +#define XPS_USB1_BASEADDR 0xE0003000U +#define XPS_I2C0_BASEADDR 0xE0004000U +#define XPS_I2C1_BASEADDR 0xE0005000U +#define XPS_SPI0_BASEADDR 0xE0006000U +#define XPS_SPI1_BASEADDR 0xE0007000U +#define XPS_CAN0_BASEADDR 0xE0008000U +#define XPS_CAN1_BASEADDR 0xE0009000U +#define XPS_GPIO_BASEADDR 0xE000A000U +#define XPS_GEM0_BASEADDR 0xE000B000U +#define XPS_GEM1_BASEADDR 0xE000C000U +#define XPS_QSPI_BASEADDR 0xE000D000U +#define XPS_PARPORT_CRTL_BASEADDR 0xE000E000U +#define XPS_SDIO0_BASEADDR 0xE0100000U +#define XPS_SDIO1_BASEADDR 0xE0101000U +#define XPS_IOU_BUS_CFG_BASEADDR 0xE0200000U +#define XPS_NAND_BASEADDR 0xE1000000U +#define XPS_PARPORT0_BASEADDR 0xE2000000U +#define XPS_PARPORT1_BASEADDR 0xE4000000U +#define XPS_QSPI_LINEAR_BASEADDR 0xFC000000U +#define XPS_SYS_CTRL_BASEADDR 0xF8000000U /* AKA SLCR */ +#define XPS_TTC0_BASEADDR 0xF8001000U +#define XPS_TTC1_BASEADDR 0xF8002000U +#define XPS_DMAC0_SEC_BASEADDR 0xF8003000U +#define XPS_DMAC0_NON_SEC_BASEADDR 0xF8004000U +#define XPS_WDT_BASEADDR 0xF8005000U +#define XPS_DDR_CTRL_BASEADDR 0xF8006000U +#define XPS_DEV_CFG_APB_BASEADDR 0xF8007000U +#define XPS_AFI0_BASEADDR 0xF8008000U +#define XPS_AFI1_BASEADDR 0xF8009000U +#define XPS_AFI2_BASEADDR 0xF800A000U +#define XPS_AFI3_BASEADDR 0xF800B000U +#define XPS_OCM_BASEADDR 0xF800C000U +#define XPS_EFUSE_BASEADDR 0xF800D000U +#define XPS_CORESIGHT_BASEADDR 0xF8800000U +#define XPS_TOP_BUS_CFG_BASEADDR 0xF8900000U +#define XPS_SCU_PERIPH_BASE 0xF8F00000U +#define XPS_L2CC_BASEADDR 0xF8F02000U +#define XPS_SAM_RAM_BASEADDR 0xFFFC0000U +#define XPS_FPGA_AXI_S0_BASEADDR 0x40000000U +#define XPS_FPGA_AXI_S1_BASEADDR 0x80000000U +#define XPS_IOU_S_SWITCH_BASEADDR 0xE0000000U +#define XPS_PERIPH_APB_BASEADDR 0xF8000000U + +/* Shared Peripheral Interrupts (SPI) */ +#define XPS_CORE_PARITY0_INT_ID 32U +#define XPS_CORE_PARITY1_INT_ID 33U +#define XPS_L2CC_INT_ID 34U +#define XPS_OCMINTR_INT_ID 35U +#define XPS_ECC_INT_ID 36U +#define XPS_PMU0_INT_ID 37U +#define XPS_PMU1_INT_ID 38U +#define XPS_SYSMON_INT_ID 39U +#define XPS_DVC_INT_ID 40U +#define XPS_WDT_INT_ID 41U +#define XPS_TTC0_0_INT_ID 42U +#define XPS_TTC0_1_INT_ID 43U +#define XPS_TTC0_2_INT_ID 44U +#define XPS_DMA0_ABORT_INT_ID 45U +#define XPS_DMA0_INT_ID 46U +#define XPS_DMA1_INT_ID 47U +#define XPS_DMA2_INT_ID 48U +#define XPS_DMA3_INT_ID 49U +#define XPS_SMC_INT_ID 50U +#define XPS_QSPI_INT_ID 51U +#define XPS_GPIO_INT_ID 52U +#define XPS_USB0_INT_ID 53U +#define XPS_GEM0_INT_ID 54U +#define XPS_GEM0_WAKE_INT_ID 55U +#define XPS_SDIO0_INT_ID 56U +#define XPS_I2C0_INT_ID 57U +#define XPS_SPI0_INT_ID 58U +#define XPS_UART0_INT_ID 59U +#define XPS_CAN0_INT_ID 60U +#define XPS_FPGA0_INT_ID 61U +#define XPS_FPGA1_INT_ID 62U +#define XPS_FPGA2_INT_ID 63U +#define XPS_FPGA3_INT_ID 64U +#define XPS_FPGA4_INT_ID 65U +#define XPS_FPGA5_INT_ID 66U +#define XPS_FPGA6_INT_ID 67U +#define XPS_FPGA7_INT_ID 68U +#define XPS_TTC1_0_INT_ID 69U +#define XPS_TTC1_1_INT_ID 70U +#define XPS_TTC1_2_INT_ID 71U +#define XPS_DMA4_INT_ID 72U +#define XPS_DMA5_INT_ID 73U +#define XPS_DMA6_INT_ID 74U +#define XPS_DMA7_INT_ID 75U +#define XPS_USB1_INT_ID 76U +#define XPS_GEM1_INT_ID 77U +#define XPS_GEM1_WAKE_INT_ID 78U +#define XPS_SDIO1_INT_ID 79U +#define XPS_I2C1_INT_ID 80U +#define XPS_SPI1_INT_ID 81U +#define XPS_UART1_INT_ID 82U +#define XPS_CAN1_INT_ID 83U +#define XPS_FPGA8_INT_ID 84U +#define XPS_FPGA9_INT_ID 85U +#define XPS_FPGA10_INT_ID 86U +#define XPS_FPGA11_INT_ID 87U +#define XPS_FPGA12_INT_ID 88U +#define XPS_FPGA13_INT_ID 89U +#define XPS_FPGA14_INT_ID 90U +#define XPS_FPGA15_INT_ID 91U + +/* Private Peripheral Interrupts (PPI) */ +#define XPS_GLOBAL_TMR_INT_ID 27U /* SCU Global Timer interrupt */ +#define XPS_FIQ_INT_ID 28U /* FIQ from FPGA fabric */ +#define XPS_SCU_TMR_INT_ID 29U /* SCU Private Timer interrupt */ +#define XPS_SCU_WDT_INT_ID 30U /* SCU Private WDT interrupt */ +#define XPS_IRQ_INT_ID 31U /* IRQ from FPGA fabric */ + + +/* REDEFINES for TEST APP */ +/* Definitions for UART */ +#define XPAR_PS7_UART_0_INTR XPS_UART0_INT_ID +#define XPAR_PS7_UART_1_INTR XPS_UART1_INT_ID +#define XPAR_PS7_USB_0_INTR XPS_USB0_INT_ID +#define XPAR_PS7_USB_1_INTR XPS_USB1_INT_ID +#define XPAR_PS7_I2C_0_INTR XPS_I2C0_INT_ID +#define XPAR_PS7_I2C_1_INTR XPS_I2C1_INT_ID +#define XPAR_PS7_SPI_0_INTR XPS_SPI0_INT_ID +#define XPAR_PS7_SPI_1_INTR XPS_SPI1_INT_ID +#define XPAR_PS7_CAN_0_INTR XPS_CAN0_INT_ID +#define XPAR_PS7_CAN_1_INTR XPS_CAN1_INT_ID +#define XPAR_PS7_GPIO_0_INTR XPS_GPIO_INT_ID +#define XPAR_PS7_ETHERNET_0_INTR XPS_GEM0_INT_ID +#define XPAR_PS7_ETHERNET_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID +#define XPAR_PS7_ETHERNET_1_INTR XPS_GEM1_INT_ID +#define XPAR_PS7_ETHERNET_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID +#define XPAR_PS7_QSPI_0_INTR XPS_QSPI_INT_ID +#define XPAR_PS7_WDT_0_INTR XPS_WDT_INT_ID +#define XPAR_PS7_SCUWDT_0_INTR XPS_SCU_WDT_INT_ID +#define XPAR_PS7_SCUTIMER_0_INTR XPS_SCU_TMR_INT_ID +#define XPAR_PS7_XADC_0_INTR XPS_SYSMON_INT_ID +#define XPAR_PS7_TTC_0_INTR XPS_TTC0_0_INT_ID +#define XPAR_PS7_TTC_1_INTR XPS_TTC0_1_INT_ID +#define XPAR_PS7_TTC_2_INTR XPS_TTC0_2_INT_ID +#define XPAR_PS7_TTC_3_INTR XPS_TTC1_0_INT_ID +#define XPAR_PS7_TTC_4_INTR XPS_TTC1_1_INT_ID +#define XPAR_PS7_TTC_5_INTR XPS_TTC1_2_INT_ID + +#define XPAR_XADCPS_INT_ID XPS_SYSMON_INT_ID + +/* For backwards compatibility */ +#define XPAR_XUARTPS_0_CLOCK_HZ XPAR_XUARTPS_0_UART_CLK_FREQ_HZ +#define XPAR_XUARTPS_1_CLOCK_HZ XPAR_XUARTPS_1_UART_CLK_FREQ_HZ +#define XPAR_XTTCPS_0_CLOCK_HZ XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_1_CLOCK_HZ XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_2_CLOCK_HZ XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_3_CLOCK_HZ XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_4_CLOCK_HZ XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ +#define XPAR_XTTCPS_5_CLOCK_HZ XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ +#define XPAR_XIICPS_0_CLOCK_HZ XPAR_XIICPS_0_I2C_CLK_FREQ_HZ +#define XPAR_XIICPS_1_CLOCK_HZ XPAR_XIICPS_1_I2C_CLK_FREQ_HZ + +#define XPAR_XQSPIPS_0_CLOCK_HZ XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ + +#ifdef XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#endif + +#ifdef XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#define XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXA9_1_CPU_CLK_FREQ_HZ +#endif + +#define XPAR_SCUTIMER_DEVICE_ID 0U +#define XPAR_SCUWDT_DEVICE_ID 0U + +/* + * Defines for interrupt wrapper API + * For more details about usage please refer xinterrupt_wrap.h + * Here Bits[11:0] represents interrupt id + * Bits[15:12] represents interrupt trigger type and level flags + */ +#define XPAR_PS7_SCUTIMER_0_INTERRUPT_ID 0x10000D +#define XPAR_PS7_TTC_0_INTERRUPT_ID 0x400A +#define XPAR_PS7_TTC_1_INTERRUPT_ID 0x400B +#define XPAR_PS7_TTC_2_INTERRUPT_ID 0x400C +#define XPAR_PS7_TTC_3_INTERRUPT_ID 0x4025 +#define XPAR_PS7_TTC_4_INTERRUPT_ID 0x4026 +#define XPAR_PS7_TTC_5_INTERRUPT_ID 0x4027 + + +#ifdef __cplusplus +} +#endif + +#endif /* protection macro */ + +/** + *@endcond + */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xplatform_info.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xplatform_info.c new file mode 100644 index 0000000..83692d8 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xplatform_info.c @@ -0,0 +1,206 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xplatform_info.c +* @addtogroup common_platform_info Hardware Platform Information +* @{ +* This file contains information about hardware for which the code is built +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 5.00  pkp  12/15/14 Initial release
+* 5.04  pkp  01/12/16 Added platform information support for Cortex-A53 32bit
+*					  mode
+* 6.00  mus  17/08/16 Removed unused variable from XGetPlatform_Info
+* 6.4   ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                     function for PMUFW.
+*       ms   06/13/17 Added PSU_PMU macro to provide support of
+*                     XGetPlatform_Info function for PMUFW.
+*       mus  08/17/17 Add EL1 NS mode support for
+*                     XGet_Zynq_UltraMp_Platform_info and XGetPSVersion_Info
+*                     APIs.
+* 7.0	aru 03/15/19  Check for versal before aarch64 and armr5
+*		      in XGetPlatform_Info()
+* 7.2   adk 08/01/20  Added versal support for the XGetPSVersion_Info function.
+* 7.6   mus 08/23/21  Updated prototypes for functions which are not taking any
+*                     arguments with void keyword. This has been done to fix
+*                     compilation warnings with "-Wstrict-prototypes" flag.
+*                     It fixes CR#1108601.
+* 7.6    mus 08/30/21 Updated flag checking to fix compilation warnings
+*                     reported with "-Wundef" flag. It fixes CR#1108601.
+
+* 7.7    mus 11/02/21 Updated XGet_Zynq_UltraMp_Platform_info and
+*                     XGetPSVersion_Info to fix compilation warning
+*                     reported with "-Wundef" flag CR#1111453
+* 8.1    mus 02/13/23 Added new API's XGetCoreId and XGetClusterId. As of now
+*                     they are supported only for VERSAL_NET APU and RPU.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_io.h" +#include "xplatform_info.h" +#if defined (__aarch64__) +#include "bspconfig.h" +#include "xil_smc.h" +#endif +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about platform +* +* @return The information about platform defined in xplatform_info.h +* +******************************************************************************/ +u32 XGetPlatform_Info(void) +{ +#if defined (versal) + return XPLAT_VERSAL; +#elif defined (ARMR5) || defined (__aarch64__) || defined (ARMA53_32) || defined (PSU_PMU) + return XPLAT_ZYNQ_ULTRA_MP; +#elif defined (__microblaze__) + return XPLAT_MICROBLAZE; +#else + return XPLAT_ZYNQ; +#endif +} + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about zynq ultrascale MP platform +* +* @return The information about zynq ultrascale MP platform defined in +* xplatform_info.h +* +******************************************************************************/ +#if defined (ARMR5) || defined (__aarch64__) || defined (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info(void) +{ +#if defined (__aarch64__) && (EL1_NONSECURE == 1) + XSmc_OutVar reg; + /* + * This SMC call will return, + * idcode - upper 32 bits of reg.Arg0 + * version - lower 32 bits of reg.Arg1 + */ + reg = Xil_Smc(GET_CHIPID_SMC_FID,0,0, 0, 0, 0, 0, 0); + return (u32)((reg.Arg1 >> XPLAT_INFO_SHIFT) & XPLAT_INFO_MASK); +#else + u32 reg; + reg = ((Xil_In32(XPLAT_PS_VERSION_ADDRESS) >> XPLAT_INFO_SHIFT ) + & XPLAT_INFO_MASK); + return reg; +#endif +} +#endif + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide information about PS Silicon version +* +* @return The information about PS Silicon version. +* +******************************************************************************/ +#if defined (ARMR5) || defined (__aarch64__) || defined (ARMA53_32) || defined (PSU_PMU) || defined (versal) +u32 XGetPSVersion_Info(void) +{ +#if defined (__aarch64__) && (EL1_NONSECURE == 1) + /* + * This SMC call will return, + * idcode - upper 32 bits of reg.Arg0 + * version - lower 32 bits of reg.Arg1 + */ + XSmc_OutVar reg; + reg = Xil_Smc(GET_CHIPID_SMC_FID,0,0, 0, 0, 0, 0, 0); + return (u32)((reg.Arg1 & XPS_VERSION_INFO_MASK) >> + XPS_VERSION_INFO_SHIFT); +#else + u32 reg; + reg = (Xil_In32(XPLAT_PS_VERSION_ADDRESS) + & XPS_VERSION_INFO_MASK); + return (reg >> XPS_VERSION_INFO_SHIFT); +#endif +} +#endif + +#if (defined (__aarch64__) && defined (VERSAL_NET)) || defined (ARMR52) +/*****************************************************************************/ +/** +* +* @brief This API is used to provide infomation about cluster id of the +* CPU core from which it is executed. +* +* @return Cluster id of the core on which API is executed. +* +******************************************************************************/ +u8 XGetClusterId(void) +{ + u64 ClusterId = 0; + +#if defined (ARMR52) + ClusterId = (mfcp(XREG_CP15_MULTI_PROC_AFFINITY) & XREG_MPIDR_MASK); + ClusterId = ((ClusterId & XREG_MPIDR_AFFINITY1_MASK) >> \ + XREG_MPIDR_AFFINITY1_SHIFT); +#else + ClusterId = (mfcp(MPIDR_EL1) & XREG_MPIDR_MASK); + ClusterId = ((ClusterId & XREG_MPIDR_AFFINITY2_MASK) >> \ + XREG_MPIDR_AFFINITY2_SHIFT); +#endif + + return (u8)ClusterId; +} + +/*****************************************************************************/ +/** +* +* @brief This API is used to provide infomation about core id of the +* CPU core from which it is executed. +* +* @return Core id of the core on which API is executed. +* +******************************************************************************/ +u8 XGetCoreId(void) +{ + u64 CoreId; + +#if defined (ARMR52) + CoreId = (mfcp(XREG_CP15_MULTI_PROC_AFFINITY) & XREG_MPIDR_MASK); + CoreId = ((CoreId & XREG_MPIDR_AFFINITY0_MASK) >> \ + XREG_MPIDR_AFFINITY0_SHIFT); +#else + CoreId = (mfcp(MPIDR_EL1) & XREG_MPIDR_MASK); + CoreId = ((CoreId & XREG_MPIDR_AFFINITY1_MASK) >> \ + XREG_MPIDR_AFFINITY1_SHIFT); +#endif + + return (u8)CoreId; +} + +#endif + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xplatform_info.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xplatform_info.h new file mode 100644 index 0000000..3e5df15 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xplatform_info.h @@ -0,0 +1,124 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xplatform_info.h +* +* +* @addtogroup common_platform_info APIs to Get Platform Information +* +* +* The xplatform_info.h file contains definitions for various available Xilinx® +* platforms. Also, it contains prototype of APIs, which can be used to get the +* platform information. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date    Changes
+* ----- ---- --------- -------------------------------------------------------
+* 6.4    ms   05/23/17 Added PSU_PMU macro to support XGetPSVersion_Info
+*                      function for PMUFW.
+* 7.2    adk  08/01/20 Added versal support for the XGetPSVersion_Info function.
+* 7.6    mus  08/23/21 Updated prototypes for functions which are not taking any
+*                      arguments with void keyword. This has been done to fix
+*                      compilation warnings with "-Wstrict-prototypes" flag.
+*                      It fixes CR#1108601.
+* 7.6    mus  08/30/21 Updated flag checking to fix compilation warnings
+*                      reported with "-Wundef" flag.
+* 7.7	 sk   01/10/22 Update XPLAT_INFO_MASK from signed to unsigned to fix
+*		       misra_c_2012_rule_10_4 violation.
+* 8.1    mus  02/13/23 Added new API's XGetCoreId and XGetClusterId. As of now
+*                      they are supported only for VERSAL_NET APU and RPU.
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XPLATFORM_INFO_H /* prevent circular inclusions */ +#define XPLATFORM_INFO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +#if defined (versal) +#define XPAR_PMC_TAP_BASEADDR 0xF11A0000U +#define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \ + XPAR_PMC_TAP_VERSION_OFFSET) +#else +#define XPAR_CSU_BASEADDR 0xFFCA0000U +#define XPAR_CSU_VER_OFFSET 0x00000044U +#define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \ + XPAR_CSU_VER_OFFSET) +#endif +#define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0 +#define XPLAT_ZYNQ_ULTRA_MP 0x1 +#define XPLAT_ZYNQ_ULTRA_MPVEL 0x2 +#define XPLAT_ZYNQ_ULTRA_MPQEMU 0x3 +#define XPLAT_ZYNQ 0x4 +#define XPLAT_MICROBLAZE 0x5 +#define XPLAT_VERSAL 0x6U + +#define XPS_VERSION_1 0x0 +#define XPS_VERSION_2 0x1 +#define XPLAT_INFO_MASK (0xFU) + +#if defined (versal) +#define XPS_VERSION_INFO_MASK 0xFF00U +#define XPS_VERSION_INFO_SHIFT 0x8U +#define XPLAT_INFO_SHIFT 0x18U +#else +#define XPS_VERSION_INFO_MASK (0xF) +#define XPS_VERSION_INFO_SHIFT 0x0U +#define XPLAT_INFO_SHIFT 0xCU +#endif + +/**************************** Type Definitions *******************************/ +/** + *@endcond + */ +/***************** Macros (Inline Functions) Definitions *********************/ + + +u32 XGetPlatform_Info(void); + +#if defined (ARMR5) || defined (__aarch64__) || defined (ARMA53_32) || defined (PSU_PMU) || defined (versal) +u32 XGetPSVersion_Info(void); +#endif + +#if defined (ARMR5) || defined (__aarch64__) || defined (ARMA53_32) +u32 XGet_Zynq_UltraMp_Platform_info(void); +#endif + +#if (defined (__aarch64__) && defined (VERSAL_NET)) || defined (ARMR52) +u8 XGetClusterId(void); +u8 XGetCoreId(void); +#endif + +/************************** Function Prototypes ******************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_platform_info". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpm_counter.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpm_counter.c new file mode 100644 index 0000000..73a69d9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpm_counter.c @@ -0,0 +1,610 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xpm_counter.c +* +* This file contains APIs for configuring and controlling the Performance +* Monitor Events for ARM based processors supported by standalone BSP. +* For more information about the event counters, see xpm_counter.h. +* The file contains APIs to setup an event, return the event counter value, +* disable event(s), enable events, reset event counters. +* It also provides a helper function: Xpm_SleepPerfCounter that is used to +* implement sleep routines in non-OS environment. +* It also contains two APIs which are being deprecated. Users are advised +* not to use them. +* On usage of these APIs, please refer to xpm_conter_example.c file which can +* be found at standalone example folder. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 8.00  mus  07/07/22 Initial version
+* 8.00  mus  07/14/22 Existing PMU APIs dont have support for CortexA53 32
+*                     bit processor, added check to skip PMU APIs
+*                     compilation in case of CortexA53 32 bit BSP.
+* 8.1   adk  03/13/23 Include xstatus.h when xiltimer is enabled.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#if !defined(ARMA53_32) +#include "xpm_counter.h" +#ifndef XPAR_XILTIMER_ENABLED +#include "xil_sleeptimer.h" +#include "xtime_l.h" +#else +#include "xstatus.h" +#endif + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ +typedef const u32 PmcrEventCfg32[XPM_CTRCOUNT]; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions *****************************/ + + +/******************************************************************************/ + +/****************************************************************************/ +/** +* +* @brief This function disables the event counters. +* +* @return None. +* +*****************************************************************************/ +void Xpm_DisableEventCounters(void) +{ + u32 RegVal; + +#if defined(__aarch64__) + RegVal = mfcp(PMCNTENCLR_EL0); +#else + /* Disable the event counters */ +#ifdef __GNUC__ + RegVal = mfcp(XREG_CP15_COUNT_ENABLE_CLR); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_COUNT_ENABLE_CLR, RegVal); +#else + { register u32 C15Reg __asm(XREG_CP15_COUNT_ENABLE_CLR); + RegVal = C15Reg; } +#endif +#endif + + RegVal &= 0x7FFFFFFF; + RegVal |= (XPM_EVENT_CNTRS_MASK & 0x7FFFFFFF); +#if defined(__aarch64__) + mtcp(PMCNTENCLR_EL0, RegVal); +#else + mtcp(XREG_CP15_COUNT_ENABLE_CLR, RegVal); +#endif +} + +/****************************************************************************/ +/** +* +* @brief This function enables the event counters. +* +* @return None. +* +*****************************************************************************/ +void Xpm_EnableEventCounters(void) +{ + u32 RegVal; + +#if defined(__aarch64__) + RegVal = mfcp(PMCNTENSET_EL0); +#else + /* Enable the event counters */ +#ifdef __GNUC__ + RegVal = mfcp(XREG_CP15_COUNT_ENABLE_SET); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_COUNT_ENABLE_SET, RegVal); +#else + { register u32 C15Reg __asm(XREG_CP15_COUNT_ENABLE_SET); + RegVal = C15Reg; } +#endif +#endif + RegVal |= XPM_EVENT_CNTRS_MASK; +#if defined(__aarch64__) + mtcp(PMCNTENSET_EL0, RegVal); +#if defined(VERSAL_NET) + RegVal = mfcp(MDCR_EL3); + mtcp(MDCR_EL3, RegVal | XPM_MDCR_EL3_SPME_MASK); +#endif +#else + mtcp(XREG_CP15_COUNT_ENABLE_SET, RegVal); +#endif +} + +/****************************************************************************/ +/** +* +* @brief This function resets the event counters. +* +* @return None. +* +*****************************************************************************/ +void Xpm_ResetEventCounters(void) +{ + u32 Reg; + +#if defined(__aarch64__) + Reg = mfcp(PMCR_EL0); +#else +#ifdef __GNUC__ + Reg = mfcp(XREG_CP15_PERF_MONITOR_CTRL); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_PERF_MONITOR_CTRL, Reg); +#else + { register u32 C15Reg __asm(XREG_CP15_PERF_MONITOR_CTRL); + Reg = C15Reg; } +#endif +#endif + + Reg |= (1U << 1U); /* reset event counters */ + +#if defined(__aarch64__) + mtcp(PMCR_EL0, Reg); +#else + mtcp(XREG_CP15_PERF_MONITOR_CTRL, Reg); +#endif +} + +/*****************************************************************************/ +/** + * + * Disables the requested event counter. + * + * + * @param EventCntrId: Event Counter ID. The counter ID is the same that + * was earlier returned through a call to Xpm_SetUpAnEvent. + * + * @return + * - XST_SUCCESS if successful. + * - XST_FAILURE if the passed Counter ID is invalid + * + ******************************************************************************/ +u32 Xpm_DisableEvent(u32 EventCntrId) +{ + u32 Counters; + u32 CntrMask = 0x1U; + + if (EventCntrId > XPM_MAX_EVENTHANDLER_ID) { + xil_printf("Invalid EventHandlerID\r\n"); + return XST_FAILURE; + } else { + CntrMask = CntrMask << EventCntrId; +#if defined(__aarch64__) + Counters = mfcp(PMCNTENCLR_EL0); +#else +#ifdef __GNUC__ + Counters = mfcp(XREG_CP15_COUNT_ENABLE_CLR); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_COUNT_ENABLE_CLR, Counters); +#else + { register u32 C15Reg __asm(XREG_CP15_COUNT_ENABLE_CLR); + Counters = C15Reg; } +#endif +#endif + Counters &= ~CntrMask; +#if defined(__aarch64__) + mtcp(PMCNTENCLR_EL0, Counters); +#else + mtcp(XREG_CP15_COUNT_ENABLE_CLR, Counters); +#endif + return XST_SUCCESS; + } +} + +/*****************************************************************************/ +/** + * + * Sets up one of the event counters to count events based on the Event ID + * passed. For supported Event IDs please refer xpm_counter.h. + * Upon invoked, the API searches for an available counter. After finding + * one, it sets up the counter to count events for the requested event. + * + * + * @param EventID: For valid values, please refer xpm_counter.h. + * + * @return + * - Counter Number if successful. For Cortex-R5, valid return values are + * 0, 1, or 2, and for others valid values are 0 to 5 + * - XPM_NO_COUNTERS_AVAILABLE (0xFF) if all counters are being used + * + ******************************************************************************/ +u32 Xpm_SetUpAnEvent(u32 EventID) +{ + u32 Counters; + u32 OriginalCounters; + u32 Index; + +#if defined(__aarch64__) + OriginalCounters = mfcp(PMCNTENSET_EL0); +#else +#ifdef __GNUC__ + OriginalCounters = mfcp(XREG_CP15_COUNT_ENABLE_SET); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_COUNT_ENABLE_SET, OriginalCounters); +#else + { register u32 C15Reg __asm(XREG_CP15_COUNT_ENABLE_SET); + OriginalCounters = C15Reg; } +#endif +#endif + + OriginalCounters &= XPM_EVENT_CNTRS_BIT_MASK; + Counters = OriginalCounters; + if (Counters == XPM_ALL_EVENT_CNTRS_IN_USE) { + xil_printf("No counters available\r\n"); + return XPM_NO_COUNTERS_AVAILABLE; + } else { + for(Index = 0U; Index < XPM_CTRCOUNT; Index++) { + if ((Counters & 0x1U) == 0x0U) { + break; + } else { + Counters = Counters >> 0x1U; + } + } + } + +#if defined(__aarch64__) + /* Select event counter */ + mtcp(PMSELR_EL0, Index); + /* Set the event */ + mtcp( PMXEVTYPER_EL0, EventID); + /* Enable event counter */ + mtcp(PMCNTENSET_EL0, OriginalCounters | (1U << Index)); +#else + /* Select event counter */ + mtcp(XREG_CP15_EVENT_CNTR_SEL, Index); + /* Set the event */ + mtcp(XREG_CP15_EVENT_TYPE_SEL, EventID); + /* Enable event counter */ + mtcp(XREG_CP15_COUNT_ENABLE_SET, OriginalCounters | ((u32)1U << Index)); +#endif + return Index; +} + +/*****************************************************************************/ +/** + * + * Reads the counter value for the requested counter ID. This is used to read + * the number of events that has been counted for the requsted event ID. + * This can only be called after a call to Xpm_SetUpAnEvent. + * + * + * @param EventCntrId: The counter ID is the same that was earlier + * returned through a call to Xpm_SetUpAnEvent. + * Cortex-R5 supports only 3 counters. The valid values are 0, 1, + * or 2 for other processors valid values are 0 to 5. + * @param CntVal: Pointer to a 32 bit unsigned int type. This is used to return + * the event counter value. + * + * @return + * - XST_SUCCESS if successful. + * - XST_FAILURE if the passed Counter ID is invalid + * + ******************************************************************************/ +u32 Xpm_GetEventCounter(u32 EventCntrId, u32 *CntVal) +{ + if (EventCntrId > XPM_MAX_EVENTHANDLER_ID) { + xil_printf("Invalid Event Handler ID\r\n"); + return XST_FAILURE; + } else { +#if defined(__aarch64__) + mtcp(PMSELR_EL0, EventCntrId); + *CntVal = mfcp(PMXEVCNTR_EL0); +#else + mtcp(XREG_CP15_EVENT_CNTR_SEL, EventCntrId); +#ifdef __GNUC__ + *CntVal = mfcp(XREG_CP15_PERF_MONITOR_COUNT); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_PERF_MONITOR_COUNT, (*CntVal)); +#else + { register u32 C15Reg __asm(XREG_CP15_PERF_MONITOR_COUNT); + *CntVal = C15Reg; } +#endif +#endif + return XST_SUCCESS; + } +} + +/****************************************************************************/ +/** +* +* @brief This is helper function used by sleep/usleep APIs to generate +* delay in sec/usec +* +* @param delay - delay time in sec/usec +* @param frequency - Number of countes in second/micro second +* +* @return None. +* +*****************************************************************************/ +#ifndef XPAR_XILTIMER_ENABLED +void Xpm_SleepPerfCounter(u32 delay, u64 frequency) +{ + u64 tEnd = 0U; + u64 tCur = 0U; + XCntrVal TimeHighVal = 0U; + XCntrVal TimeLowVal1 = 0U; + XCntrVal TimeLowVal2 = 0U; + +#if defined (__GNUC__) + TimeLowVal1 = Xpm_ReadCycleCounterVal(); +#elif defined (__ICCARM__) + Xpm_ReadCycleCounterVal(TimeLowVal1); +#endif + tEnd = (u64)TimeLowVal1 + ((u64)(delay) * frequency); + do { +#if defined (__GNUC__) + TimeLowVal2 = Xpm_ReadCycleCounterVal(); +#elif defined (__ICCARM__) + Xpm_ReadCycleCounterVal(TimeLowVal2); +#endif + if (TimeLowVal2 < TimeLowVal1) { + TimeHighVal++; + } + TimeLowVal1 = TimeLowVal2; + tCur = (((u64) TimeHighVal) << XSLEEP_TIMER_REG_SHIFT) | + (u64)TimeLowVal2; + }while (tCur < tEnd); +} +#endif +#if !defined(__aarch64__) +/****************************************************************************/ +/** +* +* @brief This function configures the event counters controller, +* with the event codes, in a configuration selected by the user and +* enables the counters. +* +* @param PmcrCfg: Configuration value based on which the event counters +* are configured.XPM_CNTRCFG* values defined in xpm_counter.h can +* be utilized for setting configuration +* +* @return None. +* +*****************************************************************************/ +void Xpm_SetEvents(s32 PmcrCfg) +{ + u32 Counter; + static PmcrEventCfg32 PmcrEvents[] = { + +#if defined(ARMR5) + { + XPM_EVENT_SOFTINCR, + XPM_EVENT_INSTRCACHEMISS, + XPM_EVENT_DATACACHEMISS + }, + { + XPM_EVENT_DATACACHEACCESS, + XPM_EVENT_DATAREAD, + XPM_EVENT_DATAWRITE + }, + { + XPM_EVENT_INSTR, + XPM_EVENT_DUALINSTR, + XPM_EVENT_EXCEPTION + }, + { + XPM_EVENT_EXCEPTIONRET, + XPM_EVENT_CHANGETOCONTEXID, + XPM_EVENT_SWCHANGE + }, + { + XPM_EVENT_IMMEDIATEINSTR, + XPM_EVENT_PROCEDURERET, + XPM_EVENT_UNALIGNACCESS + }, + { + XPM_EVENT_BRANCHMISPREDICT, + XPM_EVENT_CLOCKCYCLES, + XPM_EVENT_BRANCHPREDICT + }, + { + XPM_EVENT_INSTRSTALL, + XPM_EVENT_DATASTALL, + XPM_EVENT_DATACACHEWRITE + }, + { + XPM_EVENT_EXTERNALMEMREQ, + XPM_EVENT_LSUSTALL, + XPM_EVENT_FORCEDRAINSTORE + }, + { + XPM_EVENT_INSTRTAGPARITY, + XPM_EVENT_INSTRDATAPARITY, + XPM_EVENT_DATATAGPARITY + }, + { + XPM_EVENT_DATADATAPARITY, + XPM_EVENT_TCMERRORPREFETCH, + XPM_EVENT_TCMERRORSTORE + }, + { + XPM_EVENT_INSTRCACHEACCESS, + XPM_EVENT_DUALISSUEA, + XPM_EVENT_DUALISSUEB + }, + { + XPM_EVENT_DUALISSUEOTHER, + XPM_EVENT_FPA, + XPM_EVENT_DATACACHEDATAERROR + }, + { + XPM_EVENT_DATACACHETAGERROR, + XPM_EVENT_PROCESSORLIVELOCK, + XPM_EVENT_ATCMMULTIBITERROR + }, + { + XPM_EVENT_B0TCMMULTIBITERROR, + XPM_EVENT_B1TCMMULTIBITERROR, + XPM_EVENT_ATCMSINGLEBITERROR + }, + { + XPM_EVENT_B0TCMSINGLEBITERROR, + XPM_EVENT_B1TCMSINGLEBITERROR, + XPM_EVENT_TCMERRORLSU + }, + { + XPM_EVENT_TCMERRORPFU, + XPM_EVENT_TCMFATALERRORAXI, + XPM_EVENT_TCMERRORAXI + }, +#else + { + XPM_EVENT_SOFTINCR, + XPM_EVENT_INSRFETCH_CACHEREFILL, + XPM_EVENT_INSTRFECT_TLBREFILL, + XPM_EVENT_DATA_CACHEREFILL, + XPM_EVENT_DATA_CACHEACCESS, + XPM_EVENT_DATA_TLBREFILL + }, + { + XPM_EVENT_DATA_READS, + XPM_EVENT_DATA_WRITE, + XPM_EVENT_EXCEPTION, + XPM_EVENT_EXCEPRETURN, + XPM_EVENT_CHANGECONTEXT, + XPM_EVENT_SW_CHANGEPC + }, + { + XPM_EVENT_IMMEDBRANCH, + XPM_EVENT_UNALIGNEDACCESS, + XPM_EVENT_BRANCHMISS, + XPM_EVENT_CLOCKCYCLES, + XPM_EVENT_BRANCHPREDICT, + XPM_EVENT_JAVABYTECODE + }, + { + XPM_EVENT_SWJAVABYTECODE, + XPM_EVENT_JAVABACKBRANCH, + XPM_EVENT_COHERLINEMISS, + XPM_EVENT_COHERLINEHIT, + XPM_EVENT_INSTRSTALL, + XPM_EVENT_DATASTALL + }, + { + XPM_EVENT_MAINTLBSTALL, + XPM_EVENT_STREXPASS, + XPM_EVENT_STREXFAIL, + XPM_EVENT_DATAEVICT, + XPM_EVENT_NODISPATCH, + XPM_EVENT_ISSUEEMPTY + }, + { + XPM_EVENT_INSTRRENAME, + XPM_EVENT_PREDICTFUNCRET, + XPM_EVENT_MAINEXEC, + XPM_EVENT_SECEXEC, + XPM_EVENT_LDRSTR, + XPM_EVENT_FLOATRENAME + }, + { + XPM_EVENT_NEONRENAME, + XPM_EVENT_PLDSTALL, + XPM_EVENT_WRITESTALL, + XPM_EVENT_INSTRTLBSTALL, + XPM_EVENT_DATATLBSTALL, + XPM_EVENT_INSTR_uTLBSTALL + }, + { + XPM_EVENT_DATA_uTLBSTALL, + XPM_EVENT_DMB_STALL, + XPM_EVENT_INT_CLKEN, + XPM_EVENT_DE_CLKEN, + XPM_EVENT_INSTRISB, + XPM_EVENT_INSTRDSB + }, + { + XPM_EVENT_INSTRDMB, + XPM_EVENT_EXTINT, + XPM_EVENT_PLE_LRC, + XPM_EVENT_PLE_LRS, + XPM_EVENT_PLE_FLUSH, + XPM_EVENT_PLE_CMPL + }, + { + XPM_EVENT_PLE_OVFL, + XPM_EVENT_PLE_PROG, + XPM_EVENT_PLE_LRC, + XPM_EVENT_PLE_LRS, + XPM_EVENT_PLE_FLUSH, + XPM_EVENT_PLE_CMPL + }, + { + XPM_EVENT_DATASTALL, + XPM_EVENT_INSRFETCH_CACHEREFILL, + XPM_EVENT_INSTRFECT_TLBREFILL, + XPM_EVENT_DATA_CACHEREFILL, + XPM_EVENT_DATA_CACHEACCESS, + XPM_EVENT_DATA_TLBREFILL + }, +#endif + }; + const u32 *ptr = PmcrEvents[PmcrCfg]; + + Xpm_DisableEventCounters(); + + for(Counter = 0U; Counter < XPM_CTRCOUNT; Counter++) { + + /* Select event counter */ + mtcp(XREG_CP15_EVENT_CNTR_SEL, Counter); + + /* Set the event */ + mtcp(XREG_CP15_EVENT_TYPE_SEL, ptr[Counter]); + } + + Xpm_ResetEventCounters(); + Xpm_EnableEventCounters(); +} + +/****************************************************************************/ +/** +* +* @brief This function disables the event counters and returns the counter +* values. +* +* @param PmCtrValue: Pointer to an array of type u32 PmCtrValue[6]. +* It is an output parameter which is used to return the PM +* counter values. +* +* @return None. +* +*****************************************************************************/ +void Xpm_GetEventCounters(u32 *PmCtrValue) +{ + u32 Counter; + + Xpm_DisableEventCounters(); + + for(Counter = 0U; Counter < XPM_CTRCOUNT; Counter++) { + + mtcp(XREG_CP15_EVENT_CNTR_SEL, Counter); + +#ifdef __GNUC__ + PmCtrValue[Counter] = mfcp(XREG_CP15_PERF_MONITOR_COUNT); +#elif defined (__ICCARM__) + mfcp(XREG_CP15_PERF_MONITOR_COUNT, PmCtrValue[Counter]); +#else + { register u32 Cp15Reg __asm(XREG_CP15_PERF_MONITOR_COUNT); + PmCtrValue[Counter] = Cp15Reg; } +#endif + } +} +#endif +#endif diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpm_counter.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpm_counter.h new file mode 100644 index 0000000..8b09ef5 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpm_counter.h @@ -0,0 +1,575 @@ +/****************************************************************************** +* Copyright (c) 2011 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xpm_counter.h +* +* @addtogroup a9_event_counter_apis Cortex A9 Event Counters Functions +* +* Cortex A9 event counter functions can be utilized to configure and control +* the Cortex-A9 performance monitor events. +* +* Cortex-A9 performance monitor has six event counters which can be used to +* count a variety of events described in Coretx-A9 TRM. xpm_counter.h defines +* configurations XPM_CNTRCFGx which can be used to program the event counters +* to count a set of events. +* +* @note +* It doesn't handle the Cortex-A9 cycle counter, as the cycle counter is +* being used for time keeping. +* +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  07/11/11 First release
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 8.0   mus  07/07/22 Added prototype for new APIs as per consolidated
+*                     xpm_counter.c.
+* 
+* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef XPMCOUNTER_H /* prevent circular inclusions */ +#define XPMCOUNTER_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include +#include "xpseudo_asm.h" +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/* Number of performance counters */ +#define XPM_CTRCOUNT 6U + +/* The following constants define the Cortex-A9 Performance Monitor Events */ + +/* + * Software increment. The register is incremented only on writes to the + * Software Increment Register + */ +#define XPM_EVENT_SOFTINCR 0x00U + +/* + * Instruction fetch that causes a refill at (at least) the lowest level(s) of + * instruction or unified cache. Includes the speculative linefills in the + * count + */ +#define XPM_EVENT_INSRFETCH_CACHEREFILL 0x01U + +/* + * Instruction fetch that causes a TLB refill at (at least) the lowest level of + * TLB. Includes the speculative requests in the count + */ +#define XPM_EVENT_INSTRFECT_TLBREFILL 0x02U + +/* + * Data read or write operation that causes a refill at (at least) the lowest + * level(s)of data or unified cache. Counts the number of allocations performed + * in the Data Cache due to a read or a write + */ +#define XPM_EVENT_DATA_CACHEREFILL 0x03U + +/* + * Data read or write operation that causes a cache access at (at least) the + * lowest level(s) of data or unified cache. This includes speculative reads + */ +#define XPM_EVENT_DATA_CACHEACCESS 0x04U + +/* + * Data read or write operation that causes a TLB refill at (at least) the + * lowest level of TLB. This does not include micro TLB misses due to PLD, PLI, + * CP15 Cache operation by MVA and CP15 VA to PA operations + */ +#define XPM_EVENT_DATA_TLBREFILL 0x05U + +/* + * Data read architecturally executed. Counts the number of data read + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted LDR/LDM, as well as the reads due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_READS 0x06U + +/* + * Data write architecturally executed. Counts the number of data write + * instructions accepted by the Load Store Unit. This includes counting the + * speculative and aborted STR/STM, as well as the writes due to the SWP + * instructions + */ +#define XPM_EVENT_DATA_WRITE 0x07U + +/* Exception taken. Counts the number of exceptions architecturally taken.*/ +#define XPM_EVENT_EXCEPTION 0x09U + +/* Exception return architecturally executed.*/ +#define XPM_EVENT_EXCEPRETURN 0x0AU + +/* + * Change to ContextID retired. Counts the number of instructions + * architecturally executed writing into the ContextID Register + */ +#define XPM_EVENT_CHANGECONTEXT 0x0BU + +/* + * Software change of PC, except by an exception, architecturally executed. + * Count the number of PC changes architecturally executed, excluding the PC + * changes due to taken exceptions + */ +#define XPM_EVENT_SW_CHANGEPC 0x0CU + +/* + * Immediate branch architecturally executed (taken or not taken). This includes + * the branches which are flushed due to a previous load/store which aborts + * late + */ +#define XPM_EVENT_IMMEDBRANCH 0x0DU + +/* + * Unaligned access architecturally executed. Counts the number of aborted + * unaligned accessed architecturally executed, and the number of not-aborted + * unaligned accesses, including the speculative ones + */ +#define XPM_EVENT_UNALIGNEDACCESS 0x0FU + +/* + * Branch mispredicted/not predicted. Counts the number of mispredicted or + * not-predicted branches executed. This includes the branches which are flushed + * due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHMISS 0x10U + +/* + * Counts clock cycles when the Cortex-A9 processor is not in WFE/WFI. This + * event is not exported on the PMUEVENT bus + */ +#define XPM_EVENT_CLOCKCYCLES 0x11U + +/* + * Branches or other change in program flow that could have been predicted by + * the branch prediction resources of the processor. This includes the branches + * which are flushed due to a previous load/store which aborts late + */ +#define XPM_EVENT_BRANCHPREDICT 0x12U + +/* + * Java bytecode execute. Counts the number of Java bytecodes being decoded, + * including speculative ones + */ +#define XPM_EVENT_JAVABYTECODE 0x40U + +/* + * Software Java bytecode executed. Counts the number of software java bytecodes + * being decoded, including speculative ones + */ +#define XPM_EVENT_SWJAVABYTECODE 0x41U + +/* + * Jazelle backward branches executed. Counts the number of Jazelle taken + * branches being executed. This includes the branches which are flushed due + * to a previous load/store which aborts late + */ +#define XPM_EVENT_JAVABACKBRANCH 0x42U + +/* + * Coherent linefill miss Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which also miss in all the other + * Cortex-A9 processors, meaning that the request is sent to the external + * memory + */ +#define XPM_EVENT_COHERLINEMISS 0x50U + +/* + * Coherent linefill hit. Counts the number of coherent linefill requests + * performed by the Cortex-A9 processor which hit in another Cortex-A9 + * processor, meaning that the linefill data is fetched directly from the + * relevant Cortex-A9 cache + */ +#define XPM_EVENT_COHERLINEHIT 0x51U + +/* + * Instruction cache dependent stall cycles. Counts the number of cycles where + * the processor is ready to accept new instructions, but does not receive any + * due to the instruction side not being able to provide any and the + * instruction cache is currently performing at least one linefill + */ +#define XPM_EVENT_INSTRSTALL 0x60U + +/* + * Data cache dependent stall cycles. Counts the number of cycles where the core + * has some instructions that it cannot issue to any pipeline, and the Load + * Store unit has at least one pending linefill request, and no pending + */ +#define XPM_EVENT_DATASTALL 0x61U + +/* + * Main TLB miss stall cycles. Counts the number of cycles where the processor + * is stalled waiting for the completion of translation table walks from the + * main TLB. The processor stalls can be due to the instruction side not being + * able to provide the instructions, or to the data side not being able to + * provide the necessary data, due to them waiting for the main TLB translation + * table walk to complete + */ +#define XPM_EVENT_MAINTLBSTALL 0x62U + +/* + * Counts the number of STREX instructions architecturally executed and + * passed + */ +#define XPM_EVENT_STREXPASS 0x63U + +/* + * Counts the number of STREX instructions architecturally executed and + * failed + */ +#define XPM_EVENT_STREXFAIL 0x64U + +/* + * Data eviction. Counts the number of eviction requests due to a linefill in + * the data cache + */ +#define XPM_EVENT_DATAEVICT 0x65U + +/* + * Counts the number of cycles where the issue stage does not dispatch any + * instruction because it is empty or cannot dispatch any instructions + */ +#define XPM_EVENT_NODISPATCH 0x66U + +/* + * Counts the number of cycles where the issue stage is empty + */ +#define XPM_EVENT_ISSUEEMPTY 0x67U + +/* + * Counts the number of instructions going through the Register Renaming stage. + * This number is an approximate number of the total number of instructions + * speculatively executed, and even more approximate of the total number of + * instructions architecturally executed. The approximation depends mainly on + * the branch misprediction rate. + * The renaming stage can handle two instructions in the same cycle so the event + * is two bits long: + * - b00 no instructions renamed + * - b01 one instruction renamed + * - b10 two instructions renamed + */ +#define XPM_EVENT_INSTRRENAME 0x68U + +/* + * Counts the number of procedure returns whose condition codes do not fail, + * excluding all returns from exception. This count includes procedure returns + * which are flushed due to a previous load/store which aborts late. + * Only the following instructions are reported: + * - BX R14 + * - MOV PC LR + * - POP {..,pc} + * - LDR pc,[sp],#offset + * The following instructions are not reported: + * - LDMIA R9!,{..,PC} (ThumbEE state only) + * - LDR PC,[R9],#offset (ThumbEE state only) + * - BX R0 (Rm != R14) + * - MOV PC,R0 (Rm != R14) + * - LDM SP,{...,PC} (writeback not specified) + * - LDR PC,[SP,#offset] (wrong addressing mode) + */ +#define XPM_EVENT_PREDICTFUNCRET 0x6EU + +/* + * Counts the number of instructions being executed in the main execution + * pipeline of the processor, the multiply pipeline and arithmetic logic unit + * pipeline. The counted instructions are still speculative + */ +#define XPM_EVENT_MAINEXEC 0x70U + +/* + * Counts the number of instructions being executed in the processor second + * execution pipeline (ALU). The counted instructions are still speculative + */ +#define XPM_EVENT_SECEXEC 0x71U + +/* + * Counts the number of instructions being executed in the Load/Store unit. The + * counted instructions are still speculative + */ +#define XPM_EVENT_LDRSTR 0x72U + +/* + * Counts the number of Floating-point instructions going through the Register + * Rename stage. Instructions are still speculative in this stage. + *Two floating-point instructions can be renamed in the same cycle so the event + * is two bitslong: + *0b00 no floating-point instruction renamed + *0b01 one floating-point instruction renamed + *0b10 two floating-point instructions renamed + */ +#define XPM_EVENT_FLOATRENAME 0x73U + +/* + * Counts the number of Neon instructions going through the Register Rename + * stage.Instructions are still speculative in this stage. + * Two NEON instructions can be renamed in the same cycle so the event is two + * bits long: + *0b00 no NEON instruction renamed + *0b01 one NEON instruction renamed + *0b10 two NEON instructions renamed + */ +#define XPM_EVENT_NEONRENAME 0x74U + +/* + * Counts the number of cycles where the processor is stalled because PLD slots + * are all full + */ +#define XPM_EVENT_PLDSTALL 0x80U + +/* + * Counts the number of cycles when the processor is stalled and the data side + * is stalled too because it is full and executing writes to the external + * memory + */ +#define XPM_EVENT_WRITESTALL 0x81U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the instruction side + */ +#define XPM_EVENT_INSTRTLBSTALL 0x82U + +/* + * Counts the number of stall cycles due to main TLB misses on requests issued + * by the data side + */ +#define XPM_EVENT_DATATLBSTALL 0x83U + +/* + * Counts the number of stall cycles due to micro TLB misses on the instruction + * side. This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_INSTR_uTLBSTALL 0x84U + +/* + * Counts the number of stall cycles due to micro TLB misses on the data side. + * This event does not include main TLB miss stall cycles that are already + * counted in the corresponding main TLB event + */ +#define XPM_EVENT_DATA_uTLBSTALL 0x85U + +/* + * Counts the number of stall cycles because of the execution of a DMB memory + * barrier. This includes all DMB instructions being executed, even + * speculatively + */ +#define XPM_EVENT_DMB_STALL 0x86U + +/* + * Counts the number of cycles during which the integer core clock is enabled + */ +#define XPM_EVENT_INT_CLKEN 0x8AU + +/* + * Counts the number of cycles during which the Data Engine clock is enabled + */ +#define XPM_EVENT_DE_CLKEN 0x8BU + +/* + * Counts the number of ISB instructions architecturally executed + */ +#define XPM_EVENT_INSTRISB 0x90U + +/* + * Counts the number of DSB instructions architecturally executed + */ +#define XPM_EVENT_INSTRDSB 0x91U + +/* + * Counts the number of DMB instructions speculatively executed + */ +#define XPM_EVENT_INSTRDMB 0x92U + +/* + * Counts the number of external interrupts executed by the processor + */ +#define XPM_EVENT_EXTINT 0x93U + +/* + * PLE cache line request completed + */ +#define XPM_EVENT_PLE_LRC 0xA0U + +/* + * PLE cache line request skipped + */ +#define XPM_EVENT_PLE_LRS 0xA1U + +/* + * PLE FIFO flush + */ +#define XPM_EVENT_PLE_FLUSH 0xA2U + +/* + * PLE request complete + */ +#define XPM_EVENT_PLE_CMPL 0xA3U + +/* + * PLE FIFO overflow + */ +#define XPM_EVENT_PLE_OVFL 0xA4U + +/* + * PLE request programmed + */ +#define XPM_EVENT_PLE_PROG 0xA5U + +/* + * The following constants define the configurations for Cortex-A9 Performance + * Monitor Events. Each configuration configures the event counters for a set + * of events. + * ----------------------------------------------- + * Config PmCtr0... PmCtr5 + * ----------------------------------------------- + * XPM_CNTRCFG1 { XPM_EVENT_SOFTINCR, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + * + * XPM_CNTRCFG2 { XPM_EVENT_DATA_READS, + * XPM_EVENT_DATA_WRITE, + * XPM_EVENT_EXCEPTION, + * XPM_EVENT_EXCEPRETURN, + * XPM_EVENT_CHANGECONTEXT, + * XPM_EVENT_SW_CHANGEPC } + * + * XPM_CNTRCFG3 { XPM_EVENT_IMMEDBRANCH, + * XPM_EVENT_UNALIGNEDACCESS, + * XPM_EVENT_BRANCHMISS, + * XPM_EVENT_CLOCKCYCLES, + * XPM_EVENT_BRANCHPREDICT, + * XPM_EVENT_JAVABYTECODE } + * + * XPM_CNTRCFG4 { XPM_EVENT_SWJAVABYTECODE, + * XPM_EVENT_JAVABACKBRANCH, + * XPM_EVENT_COHERLINEMISS, + * XPM_EVENT_COHERLINEHIT, + * XPM_EVENT_INSTRSTALL, + * XPM_EVENT_DATASTALL } + * + * XPM_CNTRCFG5 { XPM_EVENT_MAINTLBSTALL, + * XPM_EVENT_STREXPASS, + * XPM_EVENT_STREXFAIL, + * XPM_EVENT_DATAEVICT, + * XPM_EVENT_NODISPATCH, + * XPM_EVENT_ISSUEEMPTY } + * + * XPM_CNTRCFG6 { XPM_EVENT_INSTRRENAME, + * XPM_EVENT_PREDICTFUNCRET, + * XPM_EVENT_MAINEXEC, + * XPM_EVENT_SECEXEC, + * XPM_EVENT_LDRSTR, + * XPM_EVENT_FLOATRENAME } + * + * XPM_CNTRCFG7 { XPM_EVENT_NEONRENAME, + * XPM_EVENT_PLDSTALL, + * XPM_EVENT_WRITESTALL, + * XPM_EVENT_INSTRTLBSTALL, + * XPM_EVENT_DATATLBSTALL, + * XPM_EVENT_INSTR_uTLBSTALL } + * + * XPM_CNTRCFG8 { XPM_EVENT_DATA_uTLBSTALL, + * XPM_EVENT_DMB_STALL, + * XPM_EVENT_INT_CLKEN, + * XPM_EVENT_DE_CLKEN, + * XPM_EVENT_INSTRISB, + * XPM_EVENT_INSTRDSB } + * + * XPM_CNTRCFG9 { XPM_EVENT_INSTRDMB, + * XPM_EVENT_EXTINT, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG10 { XPM_EVENT_PLE_OVFL, + * XPM_EVENT_PLE_PROG, + * XPM_EVENT_PLE_LRC, + * XPM_EVENT_PLE_LRS, + * XPM_EVENT_PLE_FLUSH, + * XPM_EVENT_PLE_CMPL } + * + * XPM_CNTRCFG11 { XPM_EVENT_DATASTALL, + * XPM_EVENT_INSRFETCH_CACHEREFILL, + * XPM_EVENT_INSTRFECT_TLBREFILL, + * XPM_EVENT_DATA_CACHEREFILL, + * XPM_EVENT_DATA_CACHEACCESS, + * XPM_EVENT_DATA_TLBREFILL } + */ +#define XPM_CNTRCFG1 0 +#define XPM_CNTRCFG2 1 +#define XPM_CNTRCFG3 2 +#define XPM_CNTRCFG4 3 +#define XPM_CNTRCFG5 4 +#define XPM_CNTRCFG6 5 +#define XPM_CNTRCFG7 6 +#define XPM_CNTRCFG8 7 +#define XPM_CNTRCFG9 8 +#define XPM_CNTRCFG10 9 +#define XPM_CNTRCFG11 10 + +#define XPM_NO_COUNTERS_AVAILABLE 0xFFU +#define XPM_MAX_EVENTHANDLER_ID 0x6U +#define XPM_EVENT_CNTRS_BIT_MASK 0x3FU +#define XPM_ALL_EVENT_CNTRS_IN_USE 0x3FU +#define XPM_EVENT_CNTRS_MASK 0x3FU +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ +#if defined(__GNUC__) +#define Xpm_ReadCycleCounterVal() mfcp(XREG_CP15_PERF_CYCLE_COUNTER) +#elif defined (__ICCARM__) +#define Xpm_ReadCycleCounterVal(val) mfcp(XREG_CP15_PERF_CYCLE_COUNTER,val) +#endif +/************************** Variable Definitions ****************************/ + +/** +*@endcond +*/ + +/************************** Function Prototypes *****************************/ + +/* Interface functions to access performance counters from abstraction layer */ +void Xpm_SetEvents(s32 PmcrCfg); +void Xpm_GetEventCounters(u32 *PmCtrValue); +u32 Xpm_DisableEvent(u32 EventCntrId); +void Xpm_DisableEventCounters(void); +void Xpm_EnableEventCounters (void); +void Xpm_ResetEventCounters (void); +u32 Xpm_SetUpAnEvent(u32 EventID); +u32 Xpm_GetEventCounter(u32 EventCntrId, u32 *CntVal); + +#ifdef __cplusplus +} +#endif + +#endif +/** +* @} End of "addtogroup a9_event_counter_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpseudo_asm.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpseudo_asm.h new file mode 100644 index 0000000..6d07851 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpseudo_asm.h @@ -0,0 +1,60 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xpseudo_asm.h +* +* @addtogroup a9_specific Cortex A9 Processor Specific Include Files +* +* The xpseudo_asm.h includes xreg_cortexa9.h and xpseudo_asm_gcc.h. +* +* The xreg_cortexa9.h file contains definitions for inline assembler code. +* It provides inline definitions for Cortex A9 GPRs, SPRs, MPE registers, +* co-processor registers and Debug registers. +* +* The xpseudo_asm_gcc.h contains the definitions for the most often used inline +* assembler instructions, available as macros. These can be very useful for +* tasks such as setting or getting special purpose registers, synchronization, +* or cache manipulation etc. These inline assembler instructions can be used +* from drivers and user applications written in C. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm  10/18/09 First release
+* 3.04a sdm  01/02/12 Remove redundant dsb in mcr instruction.
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 
+* +******************************************************************************/ +#ifndef XPSEUDO_ASM_H +#define XPSEUDO_ASM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xreg_cortexa9.h" +#ifdef __GNUC__ + #include "xpseudo_asm_gcc.h" +#elif defined (__ICCARM__) + #include "xpseudo_asm_iccarm.h" +#else + #include "xpseudo_asm_rvct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XPSEUDO_ASM_H */ +/** +* @} End of "addtogroup a9_specific". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpseudo_asm_gcc.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpseudo_asm_gcc.h new file mode 100644 index 0000000..b8517d3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xpseudo_asm_gcc.h @@ -0,0 +1,285 @@ +/****************************************************************************** +* Copyright (c) 2014 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 - 2023 Advanced Micro Devices, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xpseudo_asm_gcc.h +* +* This header file contains macros for using inline assembler code. It is +* written specifically for the GNU compiler. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 5.00 	pkp		 05/21/14 First release
+* 6.0   mus      07/27/16 Consolidated file for a53,a9 and r5 processors
+* 7.2   asa      04/03/20 Renamed the str macro to strw.
+* 7.2   dp       04/30/20 Added clobber "cc" to mtcpsr for aarch32 processors
+* 8.0   mus      02/24/22 Added macro mfcpnotoken and mtcpnotoken.
+* 8.1   asa      02/13/23 Create macros to read ESR, FAR and ELR registers.
+* 
+* +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XPSEUDO_ASM_GCC_H /* prevent circular inclusions */ +#define XPSEUDO_ASM_GCC_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "bspconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/* necessary for pre-processor */ +#define stringify(s) tostring(s) +#define tostring(s) #s + +#if defined (__aarch64__) +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + asm volatile("mrs %0, DAIF" : "=r" (rval));\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__ ("msr DAIF, %0" : : "r" (v)) + +#define cpsiei() //__asm__ __volatile__("cpsie i\n") +#define cpsidi() //__asm__ __volatile__("cpsid i\n") + +#define cpsief() //__asm__ __volatile__("cpsie f\n") +#define cpsidf() //__asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) /*__asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + )*/ + +#define mfgpr(rn) /*({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + })*/ + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb sy") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__("dsb sy") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__("dmb sy") + + +/* Memory Operations */ +#define ldr(adr) ({u64 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#if (EL3 == 1) +#define mfelrel3() ({u64 rval = 0U; \ + asm volatile("mrs %0, ELR_EL3" : "=r" (rval));\ + rval;\ + }) +#define mfesrel3() ({u64 rval = 0U; \ + asm volatile("mrs %0, ESR_EL3" : "=r" (rval));\ + rval;\ + }) + +#define mffarel3() ({u64 rval = 0U; \ + asm volatile("mrs %0, FAR_EL3" : "=r" (rval));\ + rval;\ + }) + +#else +#define mfelrel1() ({u64 rval = 0U; \ + asm volatile("mrs %0, ELR_EL1" : "=r" (rval));\ + rval;\ + }) + +#define mfesrel1() ({u64 rval = 0U; \ + asm volatile("mrs %0, ESR_EL1" : "=r" (rval));\ + rval;\ + }) + +#define mffarel1() ({u64 rval = 0U; \ + asm volatile("mrs %0, FAR_EL1" : "=r" (rval));\ + rval;\ + }) + + +#endif + +#define mtelrel3(v) __asm__ __volatile__ ("msr ELR_EL3, %0" : : "r" (v)) + +#else + +/* pseudo assembler instructions */ +#define mfcpsr() ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrs %0, cpsr\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +#define mtcpsr(v) __asm__ __volatile__(\ + "msr cpsr,%0\n"\ + : : "r" (v) : "cc" \ + ) + +#define cpsiei() __asm__ __volatile__("cpsie i\n") +#define cpsidi() __asm__ __volatile__("cpsid i\n") + +#define cpsief() __asm__ __volatile__("cpsie f\n") +#define cpsidf() __asm__ __volatile__("cpsid f\n") + + + +#define mtgpr(rn, v) __asm__ __volatile__(\ + "mov r" stringify(rn) ", %0 \n"\ + : : "r" (v)\ + ) + +#define mfgpr(rn) ({u32 rval; \ + __asm__ __volatile__(\ + "mov %0,r" stringify(rn) "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +/* memory synchronization operations */ + +/* Instruction Synchronization Barrier */ +#define isb() __asm__ __volatile__ ("isb" : : : "memory") + +/* Data Synchronization Barrier */ +#define dsb() __asm__ __volatile__ ("dsb" : : : "memory") + +/* Data Memory Barrier */ +#define dmb() __asm__ __volatile__ ("dmb" : : : "memory") + + +/* Memory Operations */ +#define ldr(adr) ({u32 rval; \ + __asm__ __volatile__(\ + "ldr %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#endif + +#define ldrb(adr) ({u8 rval; \ + __asm__ __volatile__(\ + "ldrb %0,[%1]"\ + : "=r" (rval) : "r" (adr)\ + );\ + rval;\ + }) + +#define strw(adr, val) __asm__ __volatile__(\ + "str %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +#define strb(adr, val) __asm__ __volatile__(\ + "strb %0,[%1]\n"\ + : : "r" (val), "r" (adr)\ + ) + +/* Count leading zeroes (clz) */ +#define clz(arg) ({u8 rval; \ + __asm__ __volatile__(\ + "clz %0,%1"\ + : "=r" (rval) : "r" (arg)\ + );\ + rval;\ + }) + +#if defined (__aarch64__) +#define mtcpdc(reg,val) __asm__ __volatile__("dc " #reg ",%0" : : "r" (val)) +#define mtcpic(reg,val) __asm__ __volatile__("ic " #reg ",%0" : : "r" (val)) + +#define mtcpicall(reg) __asm__ __volatile__("ic " #reg) +#define mtcptlbi(reg) __asm__ __volatile__("tlbi " #reg) +#define mtcpat(reg,val) __asm__ __volatile__("at " #reg ",%0" : : "r" (val)) +/* CP15 operations */ +#define mfcp(reg) ({u64 rval = 0U;\ + __asm__ __volatile__("mrs %0, " #reg : "=r" (rval));\ + rval;\ + }) + +#define mfcpnotoken(reg) ({u64 rval = 0U;\ + __asm__ __volatile__("mrs %0, " reg : "=r" (rval));\ + rval;\ + }) + +#define mtcp(reg,val) __asm__ __volatile__("msr " #reg ",%0" : : "r" (val)) +#define mtcpnotoken(reg,val) __asm__ __volatile__("msr " reg ",%0" : : "r" (val)) + +#else +/* CP15 operations */ +#define mtcp(rn, v) __asm__ __volatile__(\ + "mcr " rn "\n"\ + : : "r" (v)\ + ); + +#define mfcp(rn) ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrc " rn "\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +#define mtcp2(rn, v) __asm__ __volatile__(\ + "mcrr " rn "\n"\ + : : "r" (v), "r" (0)\ + ); + +#endif + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/** + *@endcond + */ + +#endif /* XPSEUDO_ASM_GCC_H */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xreg_cortexa9.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xreg_cortexa9.h new file mode 100644 index 0000000..2a4fff2 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xreg_cortexa9.h @@ -0,0 +1,573 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xreg_cortexa9.h +* +* This header file contains definitions for using inline assembler code. It is +* written specifically for the GNU, ARMCC compiler. +* +* All of the ARM Cortex A9 GPRs, SPRs, and Debug Registers are defined along +* with the positions of the bits within the registers. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------- -------- -----------------------------------------------
+* 1.00a ecm/sdm  10/20/09 First release
+* 
+* +******************************************************************************/ +#ifndef XREG_CORTEXA9_H +#define XREG_CORTEXA9_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + *@cond nocomments + */ + +/* GPRs */ +#define XREG_GPR0 r0 +#define XREG_GPR1 r1 +#define XREG_GPR2 r2 +#define XREG_GPR3 r3 +#define XREG_GPR4 r4 +#define XREG_GPR5 r5 +#define XREG_GPR6 r6 +#define XREG_GPR7 r7 +#define XREG_GPR8 r8 +#define XREG_GPR9 r9 +#define XREG_GPR10 r10 +#define XREG_GPR11 r11 +#define XREG_GPR12 r12 +#define XREG_GPR13 r13 +#define XREG_GPR14 r14 +#define XREG_GPR15 r15 +#define XREG_CPSR cpsr + +/* Coprocessor number defines */ +#define XREG_CP0 0 +#define XREG_CP1 1 +#define XREG_CP2 2 +#define XREG_CP3 3 +#define XREG_CP4 4 +#define XREG_CP5 5 +#define XREG_CP6 6 +#define XREG_CP7 7 +#define XREG_CP8 8 +#define XREG_CP9 9 +#define XREG_CP10 10 +#define XREG_CP11 11 +#define XREG_CP12 12 +#define XREG_CP13 13 +#define XREG_CP14 14 +#define XREG_CP15 15 + +/* Coprocessor control register defines */ +#define XREG_CR0 cr0 +#define XREG_CR1 cr1 +#define XREG_CR2 cr2 +#define XREG_CR3 cr3 +#define XREG_CR4 cr4 +#define XREG_CR5 cr5 +#define XREG_CR6 cr6 +#define XREG_CR7 cr7 +#define XREG_CR8 cr8 +#define XREG_CR9 cr9 +#define XREG_CR10 cr10 +#define XREG_CR11 cr11 +#define XREG_CR12 cr12 +#define XREG_CR13 cr13 +#define XREG_CR14 cr14 +#define XREG_CR15 cr15 + +/* Current Processor Status Register (CPSR) Bits */ +#define XREG_CPSR_THUMB_MODE 0x20 +#define XREG_CPSR_MODE_BITS 0x1F +#define XREG_CPSR_SYSTEM_MODE 0x1F +#define XREG_CPSR_UNDEFINED_MODE 0x1B +#define XREG_CPSR_DATA_ABORT_MODE 0x17 +#define XREG_CPSR_SVC_MODE 0x13 +#define XREG_CPSR_IRQ_MODE 0x12 +#define XREG_CPSR_FIQ_MODE 0x11 +#define XREG_CPSR_USER_MODE 0x10 + +#define XREG_CPSR_IRQ_ENABLE 0x80 +#define XREG_CPSR_FIQ_ENABLE 0x40 + +#define XREG_CPSR_N_BIT 0x80000000 +#define XREG_CPSR_Z_BIT 0x40000000 +#define XREG_CPSR_C_BIT 0x20000000 +#define XREG_CPSR_V_BIT 0x10000000 + + +/* CP15 defines */ +#if defined (__GNUC__) || defined (__ICCARM__) +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "p15, 0, %0, c0, c0, 0" +#define XREG_CP15_CACHE_TYPE "p15, 0, %0, c0, c0, 1" +#define XREG_CP15_TCM_TYPE "p15, 0, %0, c0, c0, 2" +#define XREG_CP15_TLB_TYPE "p15, 0, %0, c0, c0, 3" +#define XREG_CP15_MULTI_PROC_AFFINITY "p15, 0, %0, c0, c0, 5" + +#define XREG_CP15_PROC_FEATURE_0 "p15, 0, %0, c0, c1, 0" +#define XREG_CP15_PROC_FEATURE_1 "p15, 0, %0, c0, c1, 1" +#define XREG_CP15_DEBUG_FEATURE_0 "p15, 0, %0, c0, c1, 2" +#define XREG_CP15_MEMORY_FEATURE_0 "p15, 0, %0, c0, c1, 4" +#define XREG_CP15_MEMORY_FEATURE_1 "p15, 0, %0, c0, c1, 5" +#define XREG_CP15_MEMORY_FEATURE_2 "p15, 0, %0, c0, c1, 6" +#define XREG_CP15_MEMORY_FEATURE_3 "p15, 0, %0, c0, c1, 7" + +#define XREG_CP15_INST_FEATURE_0 "p15, 0, %0, c0, c2, 0" +#define XREG_CP15_INST_FEATURE_1 "p15, 0, %0, c0, c2, 1" +#define XREG_CP15_INST_FEATURE_2 "p15, 0, %0, c0, c2, 2" +#define XREG_CP15_INST_FEATURE_3 "p15, 0, %0, c0, c2, 3" +#define XREG_CP15_INST_FEATURE_4 "p15, 0, %0, c0, c2, 4" + +#define XREG_CP15_CACHE_SIZE_ID "p15, 1, %0, c0, c0, 0" +#define XREG_CP15_CACHE_LEVEL_ID "p15, 1, %0, c0, c0, 1" +#define XREG_CP15_AUXILARY_ID "p15, 1, %0, c0, c0, 7" + +#define XREG_CP15_CACHE_SIZE_SEL "p15, 2, %0, c0, c0, 0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "p15, 0, %0, c1, c0, 0" +#define XREG_CP15_AUX_CONTROL "p15, 0, %0, c1, c0, 1" +#define XREG_CP15_CP_ACCESS_CONTROL "p15, 0, %0, c1, c0, 2" + +#define XREG_CP15_SECURE_CONFIG "p15, 0, %0, c1, c1, 0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "p15, 0, %0, c1, c1, 1" +#define XREG_CP15_NS_ACCESS_CONTROL "p15, 0, %0, c1, c1, 2" +#define XREG_CP15_VIRTUAL_CONTROL "p15, 0, %0, c1, c1, 3" + +#else /* RVCT */ +/* C0 Register defines */ +#define XREG_CP15_MAIN_ID "cp15:0:c0:c0:0" +#define XREG_CP15_CACHE_TYPE "cp15:0:c0:c0:1" +#define XREG_CP15_TCM_TYPE "cp15:0:c0:c0:2" +#define XREG_CP15_TLB_TYPE "cp15:0:c0:c0:3" +#define XREG_CP15_MULTI_PROC_AFFINITY "cp15:0:c0:c0:5" + +#define XREG_CP15_PROC_FEATURE_0 "cp15:0:c0:c1:0" +#define XREG_CP15_PROC_FEATURE_1 "cp15:0:c0:c1:1" +#define XREG_CP15_DEBUG_FEATURE_0 "cp15:0:c0:c1:2" +#define XREG_CP15_MEMORY_FEATURE_0 "cp15:0:c0:c1:4" +#define XREG_CP15_MEMORY_FEATURE_1 "cp15:0:c0:c1:5" +#define XREG_CP15_MEMORY_FEATURE_2 "cp15:0:c0:c1:6" +#define XREG_CP15_MEMORY_FEATURE_3 "cp15:0:c0:c1:7" + +#define XREG_CP15_INST_FEATURE_0 "cp15:0:c0:c2:0" +#define XREG_CP15_INST_FEATURE_1 "cp15:0:c0:c2:1" +#define XREG_CP15_INST_FEATURE_2 "cp15:0:c0:c2:2" +#define XREG_CP15_INST_FEATURE_3 "cp15:0:c0:c2:3" +#define XREG_CP15_INST_FEATURE_4 "cp15:0:c0:c2:4" + +#define XREG_CP15_CACHE_SIZE_ID "cp15:1:c0:c0:0" +#define XREG_CP15_CACHE_LEVEL_ID "cp15:1:c0:c0:1" +#define XREG_CP15_AUXILARY_ID "cp15:1:c0:c0:7" + +#define XREG_CP15_CACHE_SIZE_SEL "cp15:2:c0:c0:0" + +/* C1 Register Defines */ +#define XREG_CP15_SYS_CONTROL "cp15:0:c1:c0:0" +#define XREG_CP15_AUX_CONTROL "cp15:0:c1:c0:1" +#define XREG_CP15_CP_ACCESS_CONTROL "cp15:0:c1:c0:2" + +#define XREG_CP15_SECURE_CONFIG "cp15:0:c1:c1:0" +#define XREG_CP15_SECURE_DEBUG_ENABLE "cp15:0:c1:c1:1" +#define XREG_CP15_NS_ACCESS_CONTROL "cp15:0:c1:c1:2" +#define XREG_CP15_VIRTUAL_CONTROL "cp15:0:c1:c1:3" +#endif + +/* XREG_CP15_CONTROL bit defines */ +#define XREG_CP15_CONTROL_TE_BIT 0x40000000U +#define XREG_CP15_CONTROL_AFE_BIT 0x20000000U +#define XREG_CP15_CONTROL_TRE_BIT 0x10000000U +#define XREG_CP15_CONTROL_NMFI_BIT 0x08000000U +#define XREG_CP15_CONTROL_EE_BIT 0x02000000U +#define XREG_CP15_CONTROL_HA_BIT 0x00020000U +#define XREG_CP15_CONTROL_RR_BIT 0x00004000U +#define XREG_CP15_CONTROL_V_BIT 0x00002000U +#define XREG_CP15_CONTROL_I_BIT 0x00001000U +#define XREG_CP15_CONTROL_Z_BIT 0x00000800U +#define XREG_CP15_CONTROL_SW_BIT 0x00000400U +#define XREG_CP15_CONTROL_B_BIT 0x00000080U +#define XREG_CP15_CONTROL_C_BIT 0x00000004U +#define XREG_CP15_CONTROL_A_BIT 0x00000002U +#define XREG_CP15_CONTROL_M_BIT 0x00000001U + +#if defined (__GNUC__) || defined (__ICCARM__) +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "p15, 0, %0, c2, c0, 0" +#define XREG_CP15_TTBR1 "p15, 0, %0, c2, c0, 1" +#define XREG_CP15_TTB_CONTROL "p15, 0, %0, c2, c0, 2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "p15, 0, %0, c3, c0, 0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "p15, 0, %0, c5, c0, 0" +#define XREG_CP15_INST_FAULT_STATUS "p15, 0, %0, c5, c0, 1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "p15, 0, %0, c5, c1, 0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "p15, 0, %0, c5, c1, 1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "p15, 0, %0, c6, c0, 0" +#define XREG_CP15_INST_FAULT_ADDRESS "p15, 0, %0, c6, c0, 2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "p15, 0, %0, c7, c0, 4" + +#define XREG_CP15_INVAL_IC_POU_IS "p15, 0, %0, c7, c1, 0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "p15, 0, %0, c7, c1, 6" + +#define XREG_CP15_PHYS_ADDR "p15, 0, %0, c7, c4, 0" + +#define XREG_CP15_INVAL_IC_POU "p15, 0, %0, c7, c5, 0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "p15, 0, %0, c7, c5, 1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "p15, 0, %0, c7, c5, 4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "p15, 0, %0, c7, c5, 6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c6, 1" +#define XREG_CP15_INVAL_DC_LINE_SW "p15, 0, %0, c7, c6, 2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "p15, 0, %0, c7, c8, 0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "p15, 0, %0, c7, c8, 1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "p15, 0, %0, c7, c8, 2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "p15, 0, %0, c7, c8, 3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "p15, 0, %0, c7, c8, 4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "p15, 0, %0, c7, c8, 5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "p15, 0, %0, c7, c8, 6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "p15, 0, %0, c7, c8, 7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "p15, 0, %0, c7, c10, 1" +#define XREG_CP15_CLEAN_DC_LINE_SW "p15, 0, %0, c7, c10, 2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "p15, 0, %0, c7, c10, 4" +#define XREG_CP15_DATA_MEMORY_BARRIER "p15, 0, %0, c7, c10, 5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "p15, 0, %0, c7, c11, 1" + +#define XREG_CP15_NOP2 "p15, 0, %0, c7, c13, 1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c14, 1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "p15, 0, %0, c7, c14, 2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "p15, 0, %0, c8, c3, 0" +#define XREG_CP15_INVAL_TLB_MVA_IS "p15, 0, %0, c8, c3, 1" +#define XREG_CP15_INVAL_TLB_ASID_IS "p15, 0, %0, c8, c3, 2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "p15, 0, %0, c8, c3, 3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "p15, 0, %0, c8, c5, 0" +#define XREG_CP15_INVAL_ITLB_MVA "p15, 0, %0, c8, c5, 1" +#define XREG_CP15_INVAL_ITLB_ASID "p15, 0, %0, c8, c5, 2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "p15, 0, %0, c8, c6, 0" +#define XREG_CP15_INVAL_DTLB_MVA "p15, 0, %0, c8, c6, 1" +#define XREG_CP15_INVAL_DTLB_ASID "p15, 0, %0, c8, c6, 2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "p15, 0, %0, c8, c7, 0" +#define XREG_CP15_INVAL_UTLB_MVA "p15, 0, %0, c8, c7, 1" +#define XREG_CP15_INVAL_UTLB_ASID "p15, 0, %0, c8, c7, 2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "p15, 0, %0, c8, c7, 3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "p15, 0, %0, c9, c12, 0" +#define XREG_CP15_COUNT_ENABLE_SET "p15, 0, %0, c9, c12, 1" +#define XREG_CP15_COUNT_ENABLE_CLR "p15, 0, %0, c9, c12, 2" +#define XREG_CP15_V_FLAG_STATUS "p15, 0, %0, c9, c12, 3" +#define XREG_CP15_SW_INC "p15, 0, %0, c9, c12, 4" +#define XREG_CP15_EVENT_CNTR_SEL "p15, 0, %0, c9, c12, 5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "p15, 0, %0, c9, c13, 0" +#define XREG_CP15_EVENT_TYPE_SEL "p15, 0, %0, c9, c13, 1" +#define XREG_CP15_PERF_MONITOR_COUNT "p15, 0, %0, c9, c13, 2" + +#define XREG_CP15_USER_ENABLE "p15, 0, %0, c9, c14, 0" +#define XREG_CP15_INTR_ENABLE_SET "p15, 0, %0, c9, c14, 1" +#define XREG_CP15_INTR_ENABLE_CLR "p15, 0, %0, c9, c14, 2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "p15, 0, %0, c10, c0, 0" + +#define XREG_CP15_PRI_MEM_REMAP "p15, 0, %0, c10, c2, 0" +#define XREG_CP15_NORM_MEM_REMAP "p15, 0, %0, c10, c2, 1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "p15, 0, %0, c12, c0, 1" + +#define XREG_CP15_INTERRUPT_STATUS "p15, 0, %0, c12, c1, 0" +#define XREG_CP15_VIRTUALIZATION_INTR "p15, 0, %0, c12, c1, 1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "p15, 0, %0, c13, c0, 1" +#define USER_RW_THREAD_PID "p15, 0, %0, c13, c0, 2" +#define USER_RO_THREAD_PID "p15, 0, %0, c13, c0, 3" +#define USER_PRIV_THREAD_PID "p15, 0, %0, c13, c0, 4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "p15, 0, %0, c15, c0, 0" +#define XREG_CP15_CONFIG_BASE_ADDR "p15, 4, %0, c15, c0, 0" + +#define XREG_CP15_READ_TLB_ENTRY "p15, 5, %0, c15, c4, 2" +#define XREG_CP15_WRITE_TLB_ENTRY "p15, 5, %0, c15, c4, 4" + +#define XREG_CP15_MAIN_TLB_VA "p15, 5, %0, c15, c5, 2" + +#define XREG_CP15_MAIN_TLB_PA "p15, 5, %0, c15, c6, 2" + +#define XREG_CP15_MAIN_TLB_ATTR "p15, 5, %0, c15, c7, 2" + +#else +/* C2 Register Defines */ +#define XREG_CP15_TTBR0 "cp15:0:c2:c0:0" +#define XREG_CP15_TTBR1 "cp15:0:c2:c0:1" +#define XREG_CP15_TTB_CONTROL "cp15:0:c2:c0:2" + +/* C3 Register Defines */ +#define XREG_CP15_DOMAIN_ACCESS_CTRL "cp15:0:c3:c0:0" + +/* C4 Register Defines */ +/* Not Used */ + +/* C5 Register Defines */ +#define XREG_CP15_DATA_FAULT_STATUS "cp15:0:c5:c0:0" +#define XREG_CP15_INST_FAULT_STATUS "cp15:0:c5:c0:1" + +#define XREG_CP15_AUX_DATA_FAULT_STATUS "cp15:0:c5:c1:0" +#define XREG_CP15_AUX_INST_FAULT_STATUS "cp15:0:c5:c1:1" + +/* C6 Register Defines */ +#define XREG_CP15_DATA_FAULT_ADDRESS "cp15:0:c6:c0:0" +#define XREG_CP15_INST_FAULT_ADDRESS "cp15:0:c6:c0:2" + +/* C7 Register Defines */ +#define XREG_CP15_NOP "cp15:0:c7:c0:4" + +#define XREG_CP15_INVAL_IC_POU_IS "cp15:0:c7:c1:0" +#define XREG_CP15_INVAL_BRANCH_ARRAY_IS "cp15:0:c7:c1:6" + +#define XREG_CP15_PHYS_ADDR "cp15:0:c7:c4:0" + +#define XREG_CP15_INVAL_IC_POU "cp15:0:c7:c5:0" +#define XREG_CP15_INVAL_IC_LINE_MVA_POU "cp15:0:c7:c5:1" + +/* The CP15 register access below has been deprecated in favor of the new + * isb instruction in Cortex A9. + */ +#define XREG_CP15_INST_SYNC_BARRIER "cp15:0:c7:c5:4" +#define XREG_CP15_INVAL_BRANCH_ARRAY "cp15:0:c7:c5:6" + +#define XREG_CP15_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c6:1" +#define XREG_CP15_INVAL_DC_LINE_SW "cp15:0:c7:c6:2" + +#define XREG_CP15_VA_TO_PA_CURRENT_0 "cp15:0:c7:c8:0" +#define XREG_CP15_VA_TO_PA_CURRENT_1 "cp15:0:c7:c8:1" +#define XREG_CP15_VA_TO_PA_CURRENT_2 "cp15:0:c7:c8:2" +#define XREG_CP15_VA_TO_PA_CURRENT_3 "cp15:0:c7:c8:3" + +#define XREG_CP15_VA_TO_PA_OTHER_0 "cp15:0:c7:c8:4" +#define XREG_CP15_VA_TO_PA_OTHER_1 "cp15:0:c7:c8:5" +#define XREG_CP15_VA_TO_PA_OTHER_2 "cp15:0:c7:c8:6" +#define XREG_CP15_VA_TO_PA_OTHER_3 "cp15:0:c7:c8:7" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "cp15:0:c7:c10:1" +#define XREG_CP15_CLEAN_DC_LINE_SW "cp15:0:c7:c10:2" + +/* The next two CP15 register accesses below have been deprecated in favor + * of the new dsb and dmb instructions in Cortex A9. + */ +#define XREG_CP15_DATA_SYNC_BARRIER "cp15:0:c7:c10:4" +#define XREG_CP15_DATA_MEMORY_BARRIER "cp15:0:c7:c10:5" + +#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "cp15:0:c7:c11:1" + +#define XREG_CP15_NOP2 "cp15:0:c7:c13:1" + +#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "cp15:0:c7:c14:1" +#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "cp15:0:c7:c14:2" + +/* C8 Register Defines */ +#define XREG_CP15_INVAL_TLB_IS "cp15:0:c8:c3:0" +#define XREG_CP15_INVAL_TLB_MVA_IS "cp15:0:c8:c3:1" +#define XREG_CP15_INVAL_TLB_ASID_IS "cp15:0:c8:c3:2" +#define XREG_CP15_INVAL_TLB_MVA_ASID_IS "cp15:0:c8:c3:3" + +#define XREG_CP15_INVAL_ITLB_UNLOCKED "cp15:0:c8:c5:0" +#define XREG_CP15_INVAL_ITLB_MVA "cp15:0:c8:c5:1" +#define XREG_CP15_INVAL_ITLB_ASID "cp15:0:c8:c5:2" + +#define XREG_CP15_INVAL_DTLB_UNLOCKED "cp15:0:c8:c6:0" +#define XREG_CP15_INVAL_DTLB_MVA "cp15:0:c8:c6:1" +#define XREG_CP15_INVAL_DTLB_ASID "cp15:0:c8:c6:2" + +#define XREG_CP15_INVAL_UTLB_UNLOCKED "cp15:0:c8:c7:0" +#define XREG_CP15_INVAL_UTLB_MVA "cp15:0:c8:c7:1" +#define XREG_CP15_INVAL_UTLB_ASID "cp15:0:c8:c7:2" +#define XREG_CP15_INVAL_UTLB_MVA_ASID "cp15:0:c8:c7:3" + +/* C9 Register Defines */ +#define XREG_CP15_PERF_MONITOR_CTRL "cp15:0:c9:c12:0" +#define XREG_CP15_COUNT_ENABLE_SET "cp15:0:c9:c12:1" +#define XREG_CP15_COUNT_ENABLE_CLR "cp15:0:c9:c12:2" +#define XREG_CP15_V_FLAG_STATUS "cp15:0:c9:c12:3" +#define XREG_CP15_SW_INC "cp15:0:c9:c12:4" +#define XREG_CP15_EVENT_CNTR_SEL "cp15:0:c9:c12:5" + +#define XREG_CP15_PERF_CYCLE_COUNTER "cp15:0:c9:c13:0" +#define XREG_CP15_EVENT_TYPE_SEL "cp15:0:c9:c13:1" +#define XREG_CP15_PERF_MONITOR_COUNT "cp15:0:c9:c13:2" + +#define XREG_CP15_USER_ENABLE "cp15:0:c9:c14:0" +#define XREG_CP15_INTR_ENABLE_SET "cp15:0:c9:c14:1" +#define XREG_CP15_INTR_ENABLE_CLR "cp15:0:c9:c14:2" + +/* C10 Register Defines */ +#define XREG_CP15_TLB_LOCKDWN "cp15:0:c10:c0:0" + +#define XREG_CP15_PRI_MEM_REMAP "cp15:0:c10:c2:0" +#define XREG_CP15_NORM_MEM_REMAP "cp15:0:c10:c2:1" + +/* C11 Register Defines */ +/* Not used */ + +/* C12 Register Defines */ +#define XREG_CP15_VEC_BASE_ADDR "cp15:0:c12:c0:0" +#define XREG_CP15_MONITOR_VEC_BASE_ADDR "cp15:0:c12:c0:1" + +#define XREG_CP15_INTERRUPT_STATUS "cp15:0:c12:c1:0" +#define XREG_CP15_VIRTUALIZATION_INTR "cp15:0:c12:c1:1" + +/* C13 Register Defines */ +#define XREG_CP15_CONTEXT_ID "cp15:0:c13:c0:1" +#define USER_RW_THREAD_PID "cp15:0:c13:c0:2" +#define USER_RO_THREAD_PID "cp15:0:c13:c0:3" +#define USER_PRIV_THREAD_PID "cp15:0:c13:c0:4" + +/* C14 Register Defines */ +/* not used */ + +/* C15 Register Defines */ +#define XREG_CP15_POWER_CTRL "cp15:0:c15:c0:0" +#define XREG_CP15_CONFIG_BASE_ADDR "cp15:4:c15:c0:0" + +#define XREG_CP15_READ_TLB_ENTRY "cp15:5:c15:c4:2" +#define XREG_CP15_WRITE_TLB_ENTRY "cp15:5:c15:c4:4" + +#define XREG_CP15_MAIN_TLB_VA "cp15:5:c15:c5:2" + +#define XREG_CP15_MAIN_TLB_PA "cp15:5:c15:c6:2" + +#define XREG_CP15_MAIN_TLB_ATTR "cp15:5:c15:c7:2" +#endif + + +/* MPE register definitions */ +#define XREG_FPSID c0 +#define XREG_FPSCR c1 +#define XREG_MVFR1 c6 +#define XREG_MVFR0 c7 +#define XREG_FPEXC c8 +#define XREG_FPINST c9 +#define XREG_FPINST2 c10 + +/* FPSID bits */ +#define XREG_FPSID_IMPLEMENTER_BIT (24) +#define XREG_FPSID_IMPLEMENTER_MASK (0xFF << FPSID_IMPLEMENTER_BIT) +#define XREG_FPSID_SOFTWARE (1<<23) +#define XREG_FPSID_ARCH_BIT (16) +#define XREG_FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) +#define XREG_FPSID_PART_BIT (8) +#define XREG_FPSID_PART_MASK (0xFF << FPSID_PART_BIT) +#define XREG_FPSID_VARIANT_BIT (4) +#define XREG_FPSID_VARIANT_MASK (0xF << FPSID_VARIANT_BIT) +#define XREG_FPSID_REV_BIT (0) +#define XREG_FPSID_REV_MASK (0xF << FPSID_REV_BIT) + +/* FPSCR bits */ +#define XREG_FPSCR_N_BIT (1 << 31) +#define XREG_FPSCR_Z_BIT (1 << 30) +#define XREG_FPSCR_C_BIT (1 << 29) +#define XREG_FPSCR_V_BIT (1 << 28) +#define XREG_FPSCR_QC (1 << 27) +#define XREG_FPSCR_AHP (1 << 26) +#define XREG_FPSCR_DEFAULT_NAN (1 << 25) +#define XREG_FPSCR_FLUSHTOZERO (1 << 24) +#define XREG_FPSCR_ROUND_NEAREST (0 << 22) +#define XREG_FPSCR_ROUND_PLUSINF (1 << 22) +#define XREG_FPSCR_ROUND_MINUSINF (2 << 22) +#define XREG_FPSCR_ROUND_TOZERO (3 << 22) +#define XREG_FPSCR_RMODE_BIT (22) +#define XREG_FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT) +#define XREG_FPSCR_STRIDE_BIT (20) +#define XREG_FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT) +#define XREG_FPSCR_LENGTH_BIT (16) +#define XREG_FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT) +#define XREG_FPSCR_IDC (1 << 7) +#define XREG_FPSCR_IXC (1 << 4) +#define XREG_FPSCR_UFC (1 << 3) +#define XREG_FPSCR_OFC (1 << 2) +#define XREG_FPSCR_DZC (1 << 1) +#define XREG_FPSCR_IOC (1 << 0) + +/* MVFR0 bits */ +#define XREG_MVFR0_RMODE_BIT (28) +#define XREG_MVFR0_RMODE_MASK (0xF << XREG_MVFR0_RMODE_BIT) +#define XREG_MVFR0_SHORT_VEC_BIT (24) +#define XREG_MVFR0_SHORT_VEC_MASK (0xF << XREG_MVFR0_SHORT_VEC_BIT) +#define XREG_MVFR0_SQRT_BIT (20) +#define XREG_MVFR0_SQRT_MASK (0xF << XREG_MVFR0_SQRT_BIT) +#define XREG_MVFR0_DIVIDE_BIT (16) +#define XREG_MVFR0_DIVIDE_MASK (0xF << XREG_MVFR0_DIVIDE_BIT) +#define XREG_MVFR0_EXEC_TRAP_BIT (12) +#define XREG_MVFR0_EXEC_TRAP_MASK (0xF << XREG_MVFR0_EXEC_TRAP_BIT) +#define XREG_MVFR0_DP_BIT (8) +#define XREG_MVFR0_DP_MASK (0xF << XREG_MVFR0_DP_BIT) +#define XREG_MVFR0_SP_BIT (4) +#define XREG_MVFR0_SP_MASK (0xF << XREG_MVFR0_SP_BIT) +#define XREG_MVFR0_A_SIMD_BIT (0) +#define XREG_MVFR0_A_SIMD_MASK (0xF << MVFR0_A_SIMD_BIT) + +/* FPEXC bits */ +#define XREG_FPEXC_EX (1 << 31) +#define XREG_FPEXC_EN (1 << 30) +#define XREG_FPEXC_DEX (1 << 29) + + +/** + *@endcond + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XREG_CORTEXA9_H */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xstatus.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xstatus.h new file mode 100644 index 0000000..85d1e73 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xstatus.h @@ -0,0 +1,524 @@ +/****************************************************************************** +* Copyright (c) 2002 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All Rights Reserved. * +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xstatus.h +* +* @addtogroup common_status_codes Xilinx software status codes +* +* The xstatus.h file contains the Xilinx software status codes.These codes are +* used throughout the Xilinx device drivers. +* +* @{ +******************************************************************************/ + +/** + *@cond nocomments + */ + +#ifndef XSTATUS_H /* prevent circular inclusions */ +#define XSTATUS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/*********************** Common statuses 0 - 500 *****************************/ +/** +@name Common Status Codes for All Device Drivers +@{ +*/ +#define XST_SUCCESS 0L +#define XST_FAILURE 1L +#define XST_DEVICE_NOT_FOUND 2L +#define XST_DEVICE_BLOCK_NOT_FOUND 3L +#define XST_INVALID_VERSION 4L +#define XST_DEVICE_IS_STARTED 5L +#define XST_DEVICE_IS_STOPPED 6L +#define XST_FIFO_ERROR 7L /*!< An error occurred during an + operation with a FIFO such as + an underrun or overrun, this + error requires the device to + be reset */ +#define XST_RESET_ERROR 8L /*!< An error occurred which requires + the device to be reset */ +#define XST_DMA_ERROR 9L /*!< A DMA error occurred, this error + typically requires the device + using the DMA to be reset */ +#define XST_NOT_POLLED 10L /*!< The device is not configured for + polled mode operation */ +#define XST_FIFO_NO_ROOM 11L /*!< A FIFO did not have room to put + the specified data into */ +#define XST_BUFFER_TOO_SMALL 12L /*!< The buffer is not large enough + to hold the expected data */ +#define XST_NO_DATA 13L /*!< There was no data available */ +#define XST_REGISTER_ERROR 14L /*!< A register did not contain the + expected value */ +#define XST_INVALID_PARAM 15L /*!< An invalid parameter was passed + into the function */ +#define XST_NOT_SGDMA 16L /*!< The device is not configured for + scatter-gather DMA operation */ +#define XST_LOOPBACK_ERROR 17L /*!< A loopback test failed */ +#define XST_NO_CALLBACK 18L /*!< A callback has not yet been + registered */ +#define XST_NO_FEATURE 19L /*!< Device is not configured with + the requested feature */ +#define XST_NOT_INTERRUPT 20L /*!< Device is not configured for + interrupt mode operation */ +#define XST_DEVICE_BUSY 21L /*!< Device is busy */ +#define XST_ERROR_COUNT_MAX 22L /*!< The error counters of a device + have maxed out */ +#define XST_IS_STARTED 23L /*!< Used when part of device is + already started i.e. + sub channel */ +#define XST_IS_STOPPED 24L /*!< Used when part of device is + already stopped i.e. + sub channel */ +#define XST_DATA_LOST 26L /*!< Driver defined error */ +#define XST_RECV_ERROR 27L /*!< Generic receive error */ +#define XST_SEND_ERROR 28L /*!< Generic transmit error */ +#define XST_NOT_ENABLED 29L /*!< A requested service is not + available because it has not + been enabled */ +#define XST_NO_ACCESS 30L /* Generic access error */ +#define XST_TIMEOUT 31L /*!< Event timeout occurred */ +#define XST_GLITCH_ERROR 32L /*!< Used when a glitch occurs*/ + +/** @} */ +/***************** Utility Component statuses 401 - 500 *********************/ +/** +@name Utility Component Status Codes 401 - 500 +@{ +*/ +#define XST_MEMTEST_FAILED 401L /*!< Memory test failed */ + +/** @} */ +/***************** Common Components statuses 501 - 1000 *********************/ +/** +@name Packet Fifo Status Codes 501 - 510 +@{ +*/ +/********************* Packet Fifo statuses 501 - 510 ************************/ + +#define XST_PFIFO_LACK_OF_DATA 501L /*!< Not enough data in FIFO */ +#define XST_PFIFO_NO_ROOM 502L /*!< Not enough room in FIFO */ +#define XST_PFIFO_BAD_REG_VALUE 503L /*!< Self test, a register value + was invalid after reset */ +#define XST_PFIFO_ERROR 504L /*!< Generic packet FIFO error */ +#define XST_PFIFO_DEADLOCK 505L /*!< Packet FIFO is reporting + * empty and full simultaneously + */ +/** @} */ +/** +@name DMA Status Codes 511 - 530 +@{ +*/ +/************************** DMA statuses 511 - 530 ***************************/ + +#define XST_DMA_TRANSFER_ERROR 511L /*!< Self test, DMA transfer + failed */ +#define XST_DMA_RESET_REGISTER_ERROR 512L /*!< Self test, a register value + was invalid after reset */ +#define XST_DMA_SG_LIST_EMPTY 513L /*!< Scatter gather list contains + no buffer descriptors ready + to be processed */ +#define XST_DMA_SG_IS_STARTED 514L /*!< Scatter gather not stopped */ +#define XST_DMA_SG_IS_STOPPED 515L /*!< Scatter gather not running */ +#define XST_DMA_SG_LIST_FULL 517L /*!< All the buffer descriptors of + the scatter gather list are + being used */ +#define XST_DMA_SG_BD_LOCKED 518L /*!< The scatter gather buffer + descriptor which is to be + copied over in the scatter + list is locked */ +#define XST_DMA_SG_NOTHING_TO_COMMIT 519L /*!< No buffer descriptors have been + put into the scatter gather + list to be committed */ +#define XST_DMA_SG_COUNT_EXCEEDED 521L /*!< The packet count threshold + specified was larger than the + total # of buffer descriptors + in the scatter gather list */ +#define XST_DMA_SG_LIST_EXISTS 522L /*!< The scatter gather list has + already been created */ +#define XST_DMA_SG_NO_LIST 523L /*!< No scatter gather list has + been created */ +#define XST_DMA_SG_BD_NOT_COMMITTED 524L /*!< The buffer descriptor which was + being started was not committed + to the list */ +#define XST_DMA_SG_NO_DATA 525L /*!< The buffer descriptor to start + has already been used by the + hardware so it can't be reused + */ +#define XST_DMA_SG_LIST_ERROR 526L /*!< General purpose list access + error */ +#define XST_DMA_BD_ERROR 527L /*!< General buffer descriptor + error */ +/** @} */ +/** +@name IPIF Status Codes Codes 531 - 550 +@{ +*/ +/************************** IPIF statuses 531 - 550 ***************************/ + +#define XST_IPIF_REG_WIDTH_ERROR 531L /*!< An invalid register width + was passed into the function */ +#define XST_IPIF_RESET_REGISTER_ERROR 532L /*!< The value of a register at + reset was not valid */ +#define XST_IPIF_DEVICE_STATUS_ERROR 533L /*!< A write to the device interrupt + status register did not read + back correctly */ +#define XST_IPIF_DEVICE_ACK_ERROR 534L /*!< The device interrupt status + register did not reset when + acked */ +#define XST_IPIF_DEVICE_ENABLE_ERROR 535L /*!< The device interrupt enable + register was not updated when + other registers changed */ +#define XST_IPIF_IP_STATUS_ERROR 536L /*!< A write to the IP interrupt + status register did not read + back correctly */ +#define XST_IPIF_IP_ACK_ERROR 537L /*!< The IP interrupt status register + did not reset when acked */ +#define XST_IPIF_IP_ENABLE_ERROR 538L /*!< IP interrupt enable register was + not updated correctly when other + registers changed */ +#define XST_IPIF_DEVICE_PENDING_ERROR 539L /*!< The device interrupt pending + register did not indicate the + expected value */ +#define XST_IPIF_DEVICE_ID_ERROR 540L /*!< The device interrupt ID register + did not indicate the expected + value */ +#define XST_IPIF_ERROR 541L /*!< Generic ipif error */ +/** @} */ + +/****************** Device specific statuses 1001 - 4095 *********************/ +/** +@name Ethernet Status Codes 1001 - 1050 +@{ +*/ +/********************* Ethernet statuses 1001 - 1050 *************************/ + +#define XST_EMAC_MEMORY_SIZE_ERROR 1001L /*!< Memory space is not big enough + * to hold the minimum number of + * buffers or descriptors */ +#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L /*!< Memory allocation failed */ +#define XST_EMAC_MII_READ_ERROR 1003L /*!< MII read error */ +#define XST_EMAC_MII_BUSY 1004L /*!< An MII operation is in progress */ +#define XST_EMAC_OUT_OF_BUFFERS 1005L /*!< Driver is out of buffers */ +#define XST_EMAC_PARSE_ERROR 1006L /*!< Invalid driver init string */ +#define XST_EMAC_COLLISION_ERROR 1007L /*!< Excess deferral or late + * collision on polled send */ +/** @} */ +/** +@name UART Status Codes 1051 - 1075 +@{ +*/ +/*********************** UART statuses 1051 - 1075 ***************************/ +#define XST_UART + +#define XST_UART_INIT_ERROR 1051L +#define XST_UART_START_ERROR 1052L +#define XST_UART_CONFIG_ERROR 1053L +#define XST_UART_TEST_FAIL 1054L +#define XST_UART_BAUD_ERROR 1055L +#define XST_UART_BAUD_RANGE 1056L + +/** @} */ +/** +@name IIC Status Codes 1076 - 1100 +@{ +*/ +/************************ IIC statuses 1076 - 1100 ***************************/ + +#define XST_IIC_SELFTEST_FAILED 1076 /*!< self test failed */ +#define XST_IIC_BUS_BUSY 1077 /*!< bus found busy */ +#define XST_IIC_GENERAL_CALL_ADDRESS 1078 /*!< mastersend attempted with */ + /* general call address */ +#define XST_IIC_STAND_REG_RESET_ERROR 1079 /*!< A non parameterizable reg */ + /* value after reset not valid */ +#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080 /*!< Tx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081 /*!< Rx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_TBA_REG_RESET_ERROR 1082 /*!< 10 bit addr incl in design */ + /* value after reset not valid */ +#define XST_IIC_CR_READBACK_ERROR 1083 /*!< Read of the control register */ + /* didn't return value written */ +#define XST_IIC_DTR_READBACK_ERROR 1084 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_DRR_READBACK_ERROR 1085 /*!< Read of the data Receive reg */ + /* didn't return value written */ +#define XST_IIC_ADR_READBACK_ERROR 1086 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_TBA_READBACK_ERROR 1087 /*!< Read of the 10 bit addr reg */ + /* didn't return written value */ +#define XST_IIC_NOT_SLAVE 1088 /*!< The device isn't a slave */ +#define XST_IIC_ARB_LOST 1089 /*!< Arbitration lost for master */ +/** @} */ +/** +@name ATMC Status Codes 1101 - 1125 +@{ +*/ +/*********************** ATMC statuses 1101 - 1125 ***************************/ + +#define XST_ATMC_ERROR_COUNT_MAX 1101L /*!< the error counters in the ATM + controller hit the max value + which requires the statistics + to be cleared */ +/** @} */ +/** +@name Flash Status Codes 1126 - 1150 +@{ +*/ +/*********************** Flash statuses 1126 - 1150 **************************/ + +#define XST_FLASH_BUSY 1126L /*!< Flash is erasing or programming + */ +#define XST_FLASH_READY 1127L /*!< Flash is ready for commands */ +#define XST_FLASH_ERROR 1128L /*!< Flash had detected an internal + error. Use XFlash_DeviceControl + to retrieve device specific codes + */ +#define XST_FLASH_ERASE_SUSPENDED 1129L /*!< Flash is in suspended erase state + */ +#define XST_FLASH_WRITE_SUSPENDED 1130L /*!< Flash is in suspended write state + */ +#define XST_FLASH_PART_NOT_SUPPORTED 1131L /*!< Flash type not supported by + driver */ +#define XST_FLASH_NOT_SUPPORTED 1132L /*!< Operation not supported */ +#define XST_FLASH_TOO_MANY_REGIONS 1133L /*!< Too many erase regions */ +#define XST_FLASH_TIMEOUT_ERROR 1134L /*!< Programming or erase operation + aborted due to a timeout */ +#define XST_FLASH_ADDRESS_ERROR 1135L /*!< Accessed flash outside its + addressible range */ +#define XST_FLASH_ALIGNMENT_ERROR 1136L /*!< Write alignment error */ +#define XST_FLASH_BLOCKING_CALL_ERROR 1137L /*!< Couldn't return immediately from + write/erase function with + XFL_NON_BLOCKING_WRITE/ERASE + option cleared */ +#define XST_FLASH_CFI_QUERY_ERROR 1138L /*!< Failed to query the device */ +/** @} */ +/** +@name SPI Status Codes 1151 - 1175 +@{ +*/ +/*********************** SPI statuses 1151 - 1175 ****************************/ + +#define XST_SPI_MODE_FAULT 1151 /*!< master was selected as slave */ +#define XST_SPI_TRANSFER_DONE 1152 /*!< data transfer is complete */ +#define XST_SPI_TRANSMIT_UNDERRUN 1153 /*!< slave underruns transmit register */ +#define XST_SPI_RECEIVE_OVERRUN 1154 /*!< device overruns receive register */ +#define XST_SPI_NO_SLAVE 1155 /*!< no slave has been selected yet */ +#define XST_SPI_TOO_MANY_SLAVES 1156 /*!< more than one slave is being + * selected */ +#define XST_SPI_NOT_MASTER 1157 /*!< operation is valid only as master */ +#define XST_SPI_SLAVE_ONLY 1158 /*!< device is configured as slave-only + */ +#define XST_SPI_SLAVE_MODE_FAULT 1159 /*!< slave was selected while disabled */ +#define XST_SPI_SLAVE_MODE 1160 /*!< device has been addressed as slave */ +#define XST_SPI_RECEIVE_NOT_EMPTY 1161 /*!< device received data in slave mode */ + +#define XST_SPI_COMMAND_ERROR 1162 /*!< unrecognised command - qspi only */ +#define XST_SPI_POLL_DONE 1163 /*!< controller completed polling the + device for status */ +/** @} */ +/** +@name OPB Arbiter Status Codes 1176 - 1200 +@{ +*/ +/********************** OPB Arbiter statuses 1176 - 1200 *********************/ + +#define XST_OPBARB_INVALID_PRIORITY 1176 /*!< the priority registers have either + * one master assigned to two or more + * priorities, or one master not + * assigned to any priority + */ +#define XST_OPBARB_NOT_SUSPENDED 1177 /*!< an attempt was made to modify the + * priority levels without first + * suspending the use of priority + * levels + */ +#define XST_OPBARB_PARK_NOT_ENABLED 1178 /*!< bus parking by id was enabled but + * bus parking was not enabled + */ +#define XST_OPBARB_NOT_FIXED_PRIORITY 1179 /*!< the arbiter must be in fixed + * priority mode to allow the + * priorities to be changed + */ +/** @} */ +/** +@name INTC Status Codes 1201 - 1225 +@{ +*/ +/************************ Intc statuses 1201 - 1225 **************************/ + +#define XST_INTC_FAIL_SELFTEST 1201 /*!< self test failed */ +#define XST_INTC_CONNECT_ERROR 1202 /*!< interrupt already in use */ +/** @} */ +/** +@name TmrCtr Status Codes 1226 - 1250 +@{ +*/ +/********************** TmrCtr statuses 1226 - 1250 **************************/ + +#define XST_TMRCTR_TIMER_FAILED 1226 /*!< self test failed */ +/** @} */ +/** +@name WdtTb Status Codes 1251 - 1275 +@{ +*/ +/********************** WdtTb statuses 1251 - 1275 ***************************/ + +#define XST_WDTTB_TIMER_FAILED 1251L +/** @} */ +/** +@name PlbArb status Codes 1276 - 1300 +@{ +*/ +/********************** PlbArb statuses 1276 - 1300 **************************/ + +#define XST_PLBARB_FAIL_SELFTEST 1276L +/** @} */ +/** +@name Plb2Opb Status Codes 1301 - 1325 +@{ +*/ +/********************** Plb2Opb statuses 1301 - 1325 *************************/ + +#define XST_PLB2OPB_FAIL_SELFTEST 1301L +/** @} */ +/** +@name Opb2Plb Status 1326 - 1350 +@{ +*/ +/********************** Opb2Plb statuses 1326 - 1350 *************************/ + +#define XST_OPB2PLB_FAIL_SELFTEST 1326L +/** @} */ +/** +@name SysAce Status Codes 1351 - 1360 +@{ +*/ +/********************** SysAce statuses 1351 - 1360 **************************/ + +#define XST_SYSACE_NO_LOCK 1351L /*!< No MPU lock has been granted */ +/** @} */ +/** +@name PCI Bridge Status Codes 1361 - 1375 +@{ +*/ +/********************** PCI Bridge statuses 1361 - 1375 **********************/ + +#define XST_PCI_INVALID_ADDRESS 1361L +/** @} */ +/** +@name FlexRay Constants 1400 - 1409 +@{ +*/ +/********************** FlexRay constants 1400 - 1409 *************************/ + +#define XST_FR_TX_ERROR 1400 +#define XST_FR_TX_BUSY 1401 +#define XST_FR_BUF_LOCKED 1402 +#define XST_FR_NO_BUF 1403 +/** @} */ +/** +@name USB constants 1410 - 1420 +@{ +*/ +/****************** USB constants 1410 - 1420 *******************************/ + +#define XST_USB_ALREADY_CONFIGURED 1410 +#define XST_USB_BUF_ALIGN_ERROR 1411 +#define XST_USB_NO_DESC_AVAILABLE 1412 +#define XST_USB_BUF_TOO_BIG 1413 +#define XST_USB_NO_BUF 1414 +/** @} */ +/** +@name HWICAP constants 1421 - 1429 +@{ +*/ +/****************** HWICAP constants 1421 - 1429 *****************************/ + +#define XST_HWICAP_WRITE_DONE 1421 + +/** @} */ +/** +@name AXI VDMA constants 1430 - 1440 +@{ +*/ +/****************** AXI VDMA constants 1430 - 1440 *****************************/ + +#define XST_VDMA_MISMATCH_ERROR 1430 +/** @} */ +/** +@name NAND Flash Status Codes 1441 - 1459 +@{ +*/ +/*********************** NAND Flash statuses 1441 - 1459 *********************/ + +#define XST_NAND_BUSY 1441L /*!< Flash is erasing or + * programming + */ +#define XST_NAND_READY 1442L /*!< Flash is ready for commands + */ +#define XST_NAND_ERROR 1443L /*!< Flash had detected an + * internal error. + */ +#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by + * driver + */ +#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported + */ +#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase + * operation aborted due to a + * timeout + */ +#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its + * addressible range + */ +#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error + */ +#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter + * page of the device + */ +#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error + */ + +#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected + */ +/** @} */ + +/**************************** Type Definitions *******************************/ + +typedef s32 XStatus; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ + +/** + *@endcond + */ + +/** +* @} End of "addtogroup common_status_codes". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xtime_l.c b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xtime_l.c new file mode 100644 index 0000000..a2443fe --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xtime_l.c @@ -0,0 +1,100 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xtime_l.c +* +* This file contains low level functions to get/set time from the Global Timer +* register in the ARM Cortex A9 MP core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------------
+* 1.00a rp/sdm 11/03/09 Initial release.
+* 3.07a sgd    07/05/12 Updated get/set time functions to make use Global Timer
+* 7.5   mus    04/30/21  Moved pragma message from xtime_l.h to xtime_l.c, to avoid
+*                        displaying same warnings multiple times. It fixes CR#1090562.
+* 
+* +* @note None. +* +******************************************************************************/ +/***************************** Include Files *********************************/ + +#include "xtime_l.h" +#include "xpseudo_asm.h" +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +#if defined (XSLEEP_TIMER_IS_DEFAULT_TIMER) +#pragma message ("For the sleep routines, Global timer is being used") +#endif +/****************************************************************************/ +/** +* @brief Set the time in the Global Timer Counter Register. +* +* @param Xtime_Global: 64-bit Value to be written to the Global Timer +* Counter Register. +* +* @return None. +* +* @note When this function is called by any one processor in a multi- +* processor environment, reference time will reset/lost for all +* processors. +* +****************************************************************************/ +void XTime_SetTime(XTime Xtime_Global) +{ + /* Disable Global Timer */ + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_CONTROL_OFFSET, (u32)0x0); + + /* Updating Global Timer Counter Register */ + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_COUNTER_LOWER_OFFSET, (u32)Xtime_Global); + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_COUNTER_UPPER_OFFSET, + (u32)((u32)(Xtime_Global>>32U))); + + /* Enable Global Timer */ + Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_CONTROL_OFFSET, (u32)0x1); +} + +/****************************************************************************/ +/** +* @brief Get the time from the Global Timer Counter Register. +* +* @param Xtime_Global: Pointer to the 64-bit location which will be +* updated with the current timer value. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XTime_GetTime(XTime *Xtime_Global) +{ + u32 low; + u32 high; + + /* Reading Global Timer Counter Register */ + do + { + high = Xil_In32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_UPPER_OFFSET); + low = Xil_In32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_LOWER_OFFSET); + } while(Xil_In32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_UPPER_OFFSET) != high); + + *Xtime_Global = (((XTime) high) << 32U) | (XTime) low; +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xtime_l.h b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xtime_l.h new file mode 100644 index 0000000..9d17f5c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/src/xtime_l.h @@ -0,0 +1,86 @@ +/****************************************************************************** +* Copyright (c) 2009 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xtime_l.h +* @addtogroup a9_time_apis Cortex A9 Time Functions +* +* xtime_l.h provides access to the 64-bit Global Counter in the PMU. This +* counter increases by one at every two processor cycles. These functions can +* be used to get/set time in the global timer. +* +* @{ +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------------
+* 1.00a rp/sdm 11/03/09 Initial release.
+* 3.06a sgd    05/15/12 Updated get/set time functions to make use Global Timer
+* 3.06a asa    06/17/12 Reverted back the changes to make use Global Timer.
+* 3.07a sgd    07/05/12 Updated get/set time functions to make use Global Timer
+* 6.6   srm    10/23/17 Updated the macros to support user configurable sleep
+*						implementation
+* 6.8   aru  09/06/18 Removed compilation warnings for ARMCC toolchain.
+* 7.5   mus    04/30/21  Moved pragma message from xtime_l.h to xtime_l.c, to avoid
+*                        displaying same warnings multiple times. It fixes CR#1090562.
+* 
+* +******************************************************************************/ + +/** +*@cond nocomments +*/ + +#ifndef XTIME_H /* prevent circular inclusions */ +#define XTIME_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xparameters.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +typedef u64 XTime; + +/************************** Constant Definitions *****************************/ +#define GLOBAL_TMR_BASEADDR XPAR_GLOBAL_TMR_BASEADDR +#define GTIMER_COUNTER_LOWER_OFFSET 0x00U +#define GTIMER_COUNTER_UPPER_OFFSET 0x04U +#define GTIMER_CONTROL_OFFSET 0x08U + +#if defined (SLEEP_TIMER_BASEADDR) +#define COUNTS_PER_SECOND (SLEEP_TIMER_FREQUENCY) +#else +/* Global Timer is always clocked at half of the CPU frequency */ +#define COUNTS_PER_SECOND (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ /2) +#endif +/************************** Variable Definitions *****************************/ + +/** +*@endcond +*/ + +/************************** Function Prototypes ******************************/ + +void XTime_SetTime(XTime Xtime_Global); +void XTime_GetTime(XTime *Xtime_Global); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XTIME_H */ +/** +* @} End of "addtogroup a9_time_apis". +*/ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/Makefile new file mode 100644 index 0000000..eb496ea --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/Makefile @@ -0,0 +1,39 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf ${DEPFILES} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps.c b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps.c new file mode 100644 index 0000000..56727eb --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps.c @@ -0,0 +1,540 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xttcps.c +* @addtogroup ttcps Overview +* @{ +* +* This file contains the implementation of the XTtcPs driver. This driver +* controls the operation of one timer counter in the Triple Timer Counter (TTC) +* module in the Ps block. Refer to xttcps.h for more detailed description +* of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -------------------------------------------------
+* 1.00a drg/jz 01/21/10 First release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.01	pkp	   01/30/16 Modified XTtcPs_CfgInitialize to add XTtcps_Stop
+*						to stop the timer before configuring
+* 3.2   mus    10/28/16 Modified XTtcPs_CalcIntervalFromFreq to calculate
+*                       32 bit interval count for zynq ultrascale+mpsoc
+* 3.5   srm    10/06/17 Updated XTtcPs_GetMatchValue and XTtcPs_SetMatchValue
+*                       APIs to use correct match register width for zynq
+*                       (i.e. 16 bit) and zynq ultrascale+mpsoc (i.e. 32 bit).
+*                       It fixes CR# 986617
+* 3.6   srm    04/25/18 Corrected the Match register initialization in
+						XTtcPs_CfgInitialize API.
+* 3.7   mus    09/20/18 Modified XTtcPs_CalcIntervalFromFreq API to use
+*						XTTCPS_MAX_INTERVAL_COUNT instead of hardcoding
+*						MAX interval count to 16 bit value(i.e.65532),
+*						which is incorrect for  zynq ultrascale+mpsoc
+*						(i.e. max interval count is 32 bit).
+* 3.10  aru    05/06/19 Added assert check for driver instance and freq
+*			parameter in  XTtcPs_CalcIntervalFromFreq().
+* 3.10  aru    05/30/19 Added interrupt handler to clear ISR
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xttcps.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +static void StubStatusHandler(const void *CallBackRef, u32 StatusEvent); +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Initializes a specific XTtcPs instance such that the driver is ready to use. +* This function initializes a single timer counter in the triple timer counter +* function block. +* +* The state of the device after initialization is: +* - Overflow Mode +* - Internal (pclk) selected +* - Counter disabled +* - All Interrupts disabled +* - Output waveforms disabled +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param ConfigPtr is a reference to a structure containing information +* about a specific TTC device. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, then use +* ConfigPtr->BaseAddress for this parameter, passing the physical +* address instead. +* +* @return +* +* - XST_SUCCESS if the initialization is successful. +* - XST_DEVICE_IS_STARTED if the device is started. It must be +* stopped to re-initialize. +* +* @note Device has to be stopped first to call this function to +* initialize it. +* +******************************************************************************/ +s32 XTtcPs_CfgInitialize(XTtcPs *InstancePtr, XTtcPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + s32 Status; + u32 IsStartResult; + /* + * Assert to validate input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * Set some default values + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz; + InstancePtr->StatusHandler = StubStatusHandler; +#ifdef XIL_INTERRUPT + InstancePtr->Config.IntrId = ConfigPtr->IntrId; + InstancePtr->Config.IntrParent = ConfigPtr->IntrParent; +#endif + + IsStartResult = XTtcPs_IsStarted(InstancePtr); + /* + * If the timer counter has already started, return an error + * Device should be stopped first. + */ + if(IsStartResult == (u32)TRUE) { + Status = XST_DEVICE_IS_STARTED; + } else { + + /* + * stop the timer before configuring + */ + XTtcPs_Stop(InstancePtr); + /* + * Reset the count control register to it's default value. + */ + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTTCPS_CNT_CNTRL_OFFSET, + XTTCPS_CNT_CNTRL_RESET_VALUE); + + /* + * Reset the rest of the registers to the default values. + */ + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTTCPS_CLK_CNTRL_OFFSET, 0x00U); + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTTCPS_INTERVAL_VAL_OFFSET, 0x00U); + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTTCPS_MATCH_0_OFFSET, 0x00U); + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTTCPS_MATCH_1_OFFSET, 0x00U); + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTTCPS_MATCH_2_OFFSET, 0x00U); + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTTCPS_IER_OFFSET, 0x00U); + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTTCPS_ISR_OFFSET, XTTCPS_IXR_ALL_MASK); + + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* + * Reset the counter value + */ + XTtcPs_ResetCounterValue(InstancePtr); + Status = XST_SUCCESS; + } + return Status; +} + +/*****************************************************************************/ +/** +* +* This function is used to set the match registers. There are three match +* registers. +* +* The match 0 register is special. If the waveform output mode is enabled, the +* waveform will change polarity when the count matches the value in the match 0 +* register. The polarity of the waveform output can also be set using the +* XTtcPs_SetOptions() function. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param MatchIndex is the index to the match register to be set. +* Valid values are: 0 - 2. +* @param Value is the 16-bit value to be set in the match register. +* Valid Values are: (For Zynq): +* 0 - ((2^16)-1) +* (For Zynq UltraScale + MpSoc) and Versal: +* 0 - ((2^32) - 1) +* +* @return None +* +* @note None +* +****************************************************************************/ +void XTtcPs_SetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex, XMatchRegValue Value) +{ + /* + * Assert to validate input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(MatchIndex < (u8)XTTCPS_NUM_MATCH_REG); + + /* + * Write the value to the correct match register with MatchIndex + */ + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTtcPs_Match_N_Offset(MatchIndex), Value); +} + +/*****************************************************************************/ +/** +* +* This function is used to get the value of the match registers. There are +* three match registers. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param MatchIndex is the index to the match register to be set. +* There are three match registers are there. +* Valid values are: 0 - 2. +* +* @return The match register value +* +* @note None +* +****************************************************************************/ +XMatchRegValue XTtcPs_GetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex) +{ + u32 MatchReg; + + /* + * Assert to validate input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(MatchIndex < XTTCPS_NUM_MATCH_REG); + + MatchReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress, + XTtcPs_Match_N_Offset(MatchIndex)); + + return (XMatchRegValue) MatchReg; +} + +/*****************************************************************************/ +/** +* +* This function sets the prescaler enable bit and if needed sets the prescaler +* bits in the control register. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param PrescalerValue is a number from 0-16 that sets the prescaler +* to use. +* If the parameter is 0 - 15, use a prescaler on the clock of +* 2^(PrescalerValue+1), or 2-65536. +* If the parameter is XTTCPS_CLK_CNTRL_PS_DISABLE, do not use a +* prescaler. +* +* Valid values are: 0 - 15 +* +* @return None +* +* @note None +* +****************************************************************************/ +void XTtcPs_SetPrescaler(XTtcPs *InstancePtr, u8 PrescalerValue) +{ + u32 ClockReg; + + /* + * Assert to validate input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(PrescalerValue <= XTTCPS_CLK_CNTRL_PS_DISABLE); + + /* + * Read the clock control register + */ + ClockReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress, + XTTCPS_CLK_CNTRL_OFFSET); + + /* + * Clear all of the prescaler control bits in the register + */ + ClockReg &= + ~(XTTCPS_CLK_CNTRL_PS_VAL_MASK | XTTCPS_CLK_CNTRL_PS_EN_MASK); + + if (PrescalerValue < XTTCPS_CLK_CNTRL_PS_DISABLE) { + /* + * Set the prescaler value and enable prescaler + */ + ClockReg |= (u32)(((u32)PrescalerValue << (u32)XTTCPS_CLK_CNTRL_PS_VAL_SHIFT) & + (u32)XTTCPS_CLK_CNTRL_PS_VAL_MASK); + ClockReg |= (u32)XTTCPS_CLK_CNTRL_PS_EN_MASK; + } + + /* + * Write the register with the new values. + */ + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTTCPS_CLK_CNTRL_OFFSET, ClockReg); +} + +/*****************************************************************************/ +/** +* +* This function gets the input clock prescaler +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +*
+* @return	The value(n) from which the prescalar value is calculated
+*		    as 2^(n+1). Some example values are given below :
+*
+* 	Value		Prescaler
+* 	0		2
+* 	1		4
+* 	N		2^(n+1)
+* 	15		65536
+* 	16		1
+*
+*           Valid values are: 0 - 16
+* 
+* +* @note None. +* +****************************************************************************/ +u8 XTtcPs_GetPrescaler(XTtcPs *InstancePtr) +{ + u8 Status; + u32 ClockReg; + + /* + * Assert to validate input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the clock control register + */ + ClockReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress, + XTTCPS_CLK_CNTRL_OFFSET); + + if (0 == (ClockReg & XTTCPS_CLK_CNTRL_PS_EN_MASK)) { + /* + * Prescaler is disabled. Return the correct flag value + */ + Status = (u8)XTTCPS_CLK_CNTRL_PS_DISABLE; + } + else { + + Status = (u8)((ClockReg & (u32)XTTCPS_CLK_CNTRL_PS_VAL_MASK) >> + (u32)XTTCPS_CLK_CNTRL_PS_VAL_SHIFT); + } + return Status; +} + +/*****************************************************************************/ +/** +* +* This function calculates the interval value as well as the prescaler value +* for a given frequency. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param Freq is the requested output frequency for the device. +* valid values are: 1 - (2^32)-1 +* @param Interval is the interval value for the given frequency, +* it is the output value for this function. +* @param Prescaler is the prescaler value for the given frequency, +* it is the output value for this function. +* +* @return None. +* +* @note +* Upon successful calculation for the given frequency, Interval and Prescaler +* carry the settings for the timer counter; Upon unsuccessful calculation, +* Interval and Prescaler are set to 0xFF(FF) for their maximum values to +* signal the caller of failure. Therefore, caller needs to check the return +* interval or prescaler values for whether the function has succeeded. +* +****************************************************************************/ +void XTtcPs_CalcIntervalFromFreq(XTtcPs *InstancePtr, u32 Freq, + XInterval *Interval, u8 *Prescaler) +{ + u8 TmpPrescaler; + UINTPTR TempValue; + u32 InputClock; + + /* + * Assert to validate input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Freq > 0U); + + InputClock = InstancePtr->Config.InputClockHz; + /* + * Find the smallest prescaler that will work for a given frequency. The + * smaller the prescaler, the larger the count and the more accurate the + * PWM setting. + */ + TempValue = InputClock/ Freq; + + if (TempValue < 4U) { + /* + * The frequency is too high, it is too close to the input + * clock value. Use maximum values to signal caller. + */ + *Interval = XTTCPS_MAX_INTERVAL_COUNT; + *Prescaler = 0xFFU; + return; + } + + /* + * First, do we need a prescaler or not? + */ + if (((UINTPTR)XTTCPS_MAX_INTERVAL_COUNT) > TempValue) { + /* + * We do not need a prescaler, so set the values appropriately + */ + *Interval = (XInterval)TempValue; + *Prescaler = XTTCPS_CLK_CNTRL_PS_DISABLE; + return; + } + + + for (TmpPrescaler = 0U; TmpPrescaler < XTTCPS_CLK_CNTRL_PS_DISABLE; + TmpPrescaler++) { + TempValue = InputClock/ (Freq * (1U << (TmpPrescaler + 1U))); + + /* + * The first value less than 2^16 is the best bet + */ + if (((UINTPTR)XTTCPS_MAX_INTERVAL_COUNT) > TempValue) { + /* + * Set the values appropriately + */ + *Interval = (XInterval)TempValue; + *Prescaler = TmpPrescaler; + return; + } + } + + /* Can not find interval values that work for the given frequency. + * Return maximum values to signal caller. + */ + *Interval = XTTCPS_MAX_INTERVAL_COUNT; + *Prescaler = 0XFFU; + return; +} + +/*****************************************************************************/ +/** + * + * Handles interrupts by resetting the counter value + * and clearing the status register + * + * @param InstancePtr is a pointer to the XTtcPs instance. + * + * @return + * - XST_SUCCESS if successful. + * + * @note None. + * + ******************************************************************************/ + +u32 XTtcPs_InterruptHandler(XTtcPs *InstancePtr) +{ + u32 XTtcPsStatusReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + + XTtcPsStatusReg = XTtcPs_GetInterruptStatus(InstancePtr); + XTtcPs_ClearInterruptStatus(InstancePtr, XTtcPsStatusReg); + InstancePtr->StatusHandler(InstancePtr->StatusRef, + XTtcPsStatusReg); + return XST_SUCCESS; + + + +} + +/*****************************************************************************/ +/** + * + * Sets the status callback function, the status handler, which the driver + * calls when it encounters conditions that should be reported to upper + * layer software. The handler executes in an interrupt context, so it must + * minimize the amount of processing performed. One of the following status + * events is passed to the status handler. + * + *
+ * @param InstancePtr is a pointer to the XTtcPs instance. + * @param CallBackRef is the upper layer callback reference passed back + * when the callback function is invoked. + * @param FuncPointer is the pointer to the callback function. + * + * @return None. + * + * @note + * + * The handler is called within interrupt context, so it should do its work + * quickly and queue potentially time-consuming work to a task-level thread. + * + ******************************************************************************/ +void XTtcPs_SetStatusHandler(XTtcPs *InstancePtr, void *CallBackRef, + XTtcPs_StatusHandler FuncPointer) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPointer != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->StatusHandler = FuncPointer; + InstancePtr->StatusRef = CallBackRef; +} + + +/*****************************************************************************/ +/** + * + * This is a stub for the status callback. The stub is here in case the upper + * layers forget to set the handler. + * + * @param CallBackRef is a pointer to the upper layer callback reference + * @param StatusEvent is the event that just occurred. + * + * @return None. + * + * @note None. + * + ******************************************************************************/ +static void StubStatusHandler(const void *CallBackRef, u32 StatusEvent) +{ + (void) CallBackRef; + (void) StatusEvent; + + Xil_AssertVoidAlways(); +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps.h b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps.h new file mode 100644 index 0000000..643e73e --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps.h @@ -0,0 +1,526 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2022 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xttcps.h +* @addtogroup ttcps Overview +* @{ +* @details +* +* This is the driver for one 16-bit timer counter in the Triple Timer Counter +* (TTC) module in the Ps block. +* +* The TTC module provides three independent timer/counter modules that can each +* be clocked using either the system clock (pclk) or an externally driven +* clock (ext_clk). In addition, each counter can independently prescale its +* selected clock input (divided by 2 to 65536). Counters can be set to +* decrement or increment. +* +* Each of the counters can be programmed to generate interrupt pulses: +* . At a regular, predefined period, that is on a timed interval +* . When the counter registers overflow +* . When the count matches any one of the three 'match' registers +* +* Therefore, up to six different events can trigger a timer interrupt: three +* match interrupts, an overflow interrupt, an interval interrupt and an event +* timer interrupt. Note that the overflow interrupt and the interval interrupt +* are mutually exclusive. +* +* Initialization & Configuration +* +* An XTtcPs_Config structure is used to configure a driver instance. +* Information in the XTtcPs_Config structure is the hardware properties +* about the device. +* +* A driver instance is initialized through +* XTtcPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr). Where CfgPtr +* is a pointer to the XTtcPs_Config structure, it can be looked up statically +* through XTtcPs_LookupConfig(DeviceID), or passed in by the caller. The +* EffectiveAddr can be the static base address of the device or virtual +* mapped address if address translation is supported. +* +* Interrupts +* +* Interrupt handler is not provided by the driver, as handling of interrupt +* is application specific. +* +* stack usage(in bytes) +* +* XTtcPs_LookupConfig : 32 +* XTtcPs_CfgInitialize : 80 +* XTtcPs_SetMatchValue : 32 +* XTtcPs_GetMatchValue : 48 +* XTtcPs_SetPrescaler : 48 +* XTtcPs_GetPrescaler : 48 +* XTtcPs_CalcIntervalFromFreq : 48 +* XTtcPs_SetOptions : 48 +* XTtcPs_GetOptions : 48 +* XTtcPs_SelfTest : 48 +* XTtcPs_InterruptHandler : 48 +* XTtcPs_SetStatusHandler : 48 +* +* Memory foot-print(in bytes) +* +* XTtcPs_LookupConfig : 72 +* XTtcPs_CfgInitialize : 304 +* XTtcPs_SetMatchValue : 168 +* XTtcPs_GetMatchValue : 176 +* XTtcPs_SetPrescaler : 172 +* XTtcPs_GetPrescaler : 152 +* XTtcPs_CalcIntervalFromFreq : 228 +* XTtcPs_SetOptions : 424 +* XTtcPs_GetOptions : 200 +* XTtcPs_SelfTest : 148 +* XTtcPs_InterruptHandler : 88 +* XTtcPs_SetStatusHandler : 140 +* +* Execution Time(in usec) +* +* XTtcPs_LookupConfig : 8.31 +* TtcPs_CfgInitialize : 1.30 +* XTtcPs_SetMatchValue : 1.10 +* XTtcPs_GetMatchValue : 1.00 +* XTtcPs_SetPrescaler : 1.09 +* XTtcPs_GetPrescaler : 1.00 +* XTtcPs_CalcIntervalFromFreq : 1.29 +* XTtcPs_SetOptions: 1.91 +* XTtcPs_GetOptions: 2.55 +* XTtcPs_SelfTest: .85 +* +* Assumptions of Use + +* 1.The default setting for a timer/counter is: +* - Overflow Mode +* - Internal clock (pclk) selected +* - Counter disabled +* - All Interrupts disabled +* - Output waveforms disabled +* +* Compiler Name +* +* gcc +* +* Compiler version +* +* 8.2.0 +* +* Compiler options +* +* -DARMR5 -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-r5 -mfloat-abi=hard -mfpu=vfpv3-d16 -I +* -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -mcpu=cortex-a72 -I +* -Wall -O0 -g3 -c -fmessage-length=0 -MT"$@" -I +* +* User Defined data types +* +* u8 1 byte +* u16 2 bytes +* u32 4 bytes / 1 word +* u64 8 bytes / double word +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------------
+* 1.00a drg/jz 01/20/10 First release..
+* 2.0   adk    12/10/13 Updated as per the New Tcl API's
+* 3.0	pkp    12/09/14 Added support for Zynq Ultrascale Mp.Also code
+*			modified for MISRA-C:2012 compliance.
+* 3.2   mus    10/28/16 Modified XTtcPs_GetCounterValue and XTtcPs_SetInterval
+*                       macros to return 32 bit values for zynq ultrascale+mpsoc
+*       ms   01/23/17 Modified xil_printf statement in main function for all
+*                     examples to ensure that "Successfully ran" and "Failed"
+*                     strings are available in all examples. This is a fix
+*                     for CR-965028.
+*       ms   03/17/17 Added readme.txt file in examples folder for doxygen
+*                     generation.
+* 3.4   ms   04/18/17 Modified tcl file to add suffix U for all macros
+*                     definitions of ttcps in xparameters.h
+* 3.5   srm  10/06/17 Added new typedef XMatchRegValue for match register width
+* 3.8   aru  12/19/18 Modified in XTtcPs_ClearInterruptStatus function to clear
+*                     Interrupt status register by reading instead of writing it.
+* 3.14   mus 02/22/21 Updated XTtcPs_ClearInterruptStatus to fix compiler warning.
+*                     It fixes CR#1084697.
+* 3.16  adk  04/19/22 Fix infinite loop in the examples by adding polled
+* 		      timeout loop.
+* 
+* +******************************************************************************/ + +#ifndef XTTCPS_H /* prevent circular inclusions */ +#define XTTCPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xttcps_hw.h" +#include "xstatus.h" + +/*****************************************************************************/ +typedef void (*XTtcPs_StatusHandler) (const void *CallBackRef, u32 StatusEvent); + + +/************************** Constant Definitions *****************************/ + + +/* + * Maximum Value for interval counter + */ + #if defined(ARMA9) + #define XTTCPS_MAX_INTERVAL_COUNT 0xFFFFU + #else + #define XTTCPS_MAX_INTERVAL_COUNT 0xFFFFFFFFU + #endif + +/** @name Configuration options + * + * Options for the device. Each of the options is bit field, so more than one + * options can be specified. + * + * @{ + */ +#define XTTCPS_OPTION_EXTERNAL_CLK 0x00000001U /**< External clock source */ +#define XTTCPS_OPTION_CLK_EDGE_NEG 0x00000002U /**< Clock on trailing edge for + external clock*/ +#define XTTCPS_OPTION_INTERVAL_MODE 0x00000004U /**< Interval mode */ +#define XTTCPS_OPTION_DECREMENT 0x00000008U /**< Decrement the counter */ +#define XTTCPS_OPTION_MATCH_MODE 0x00000010U /**< Match mode */ +#define XTTCPS_OPTION_WAVE_DISABLE 0x00000020U /**< No waveform output */ +#define XTTCPS_OPTION_WAVE_POLARITY 0x00000040U /**< Waveform polarity */ +/*@}*/ +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID for device */ + u32 BaseAddress; /**< Base address for device */ + u32 InputClockHz; /**< Input clock frequency */ +#ifdef XIL_INTERRUPT + u16 IntrId; + UINTPTR IntrParent; /** Bit[0] Interrupt parent type Bit[64/32:1] Parent base address */ +#endif +} XTtcPs_Config; + +/** + * The XTtcPs driver instance data. The user is required to allocate a + * variable of this type for each PS timer/counter device in the system. A + * pointer to a variable of this type is then passed to various driver API + * functions. + */ +typedef struct { + XTtcPs_Config Config; /**< Configuration structure */ + u32 IsReady; /**< Device is initialized and ready */ + XTtcPs_StatusHandler StatusHandler; + void *StatusRef; /**< Callback reference for status handler */ +} XTtcPs; + +/** + * This typedef contains interval count and Match register value + */ +#if defined(ARMA9) +typedef u16 XInterval; +typedef u16 XMatchRegValue; +#else +typedef u32 XInterval; +typedef u32 XMatchRegValue; +#endif +/***************** Macros (Inline Functions) Definitions *********************/ + +/* + * Internal helper macros + */ +#define InstReadReg(InstancePtr, RegOffset) \ + (Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)(RegOffset))) + +#define InstWriteReg(InstancePtr, RegOffset, Data) \ + (Xil_Out32(((InstancePtr)->Config.BaseAddress) + (u32)(RegOffset), (u32)(Data))) + +/*****************************************************************************/ +/** +* +* This function starts the counter/timer without resetting the counter value. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return None +* +* @note C-style signature: +* void XTtcPs_Start(XTtcPs *InstancePtr) +* +****************************************************************************/ +#define XTtcPs_Start(InstancePtr) \ + InstWriteReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET, \ + (InstReadReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET) & \ + ~XTTCPS_CNT_CNTRL_DIS_MASK)) + +/*****************************************************************************/ +/** +* +* This function stops the counter/timer. This macro may be called at any time +* to stop the counter. The counter holds the last value until it is reset, +* restarted or enabled. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return None +* +* @note C-style signature: +* void XTtcPs_Stop(XTtcPs *InstancePtr) +* +****************************************************************************/ +#define XTtcPs_Stop(InstancePtr) \ + InstWriteReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET, \ + (InstReadReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET) | \ + XTTCPS_CNT_CNTRL_DIS_MASK)) + +/*****************************************************************************/ +/** +* +* This function checks whether the timer counter has already started. +* +* @param InstancePtr is a pointer to the XTtcPs instance +* +* @return Non-zero if the device has started, '0' otherwise. +* +* @note C-style signature: +* int XTtcPs_IsStarted(XTtcPs *InstancePtr) +* +****************************************************************************/ +#define XTtcPs_IsStarted(InstancePtr) \ + ((InstReadReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET) & \ + XTTCPS_CNT_CNTRL_DIS_MASK) == 0U) + +/*****************************************************************************/ +/** +* +* This function returns the current 16-bit counter value. It may be called at +* any time. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return zynq:16 bit counter value. +* zynq ultrascale+mpsoc:32 bit counter value. +* +* @note C-style signature: +* zynq: u16 XTtcPs_GetCounterValue(XTtcPs *InstancePtr) +* zynq ultrascale+mpsoc: u32 XTtcPs_GetCounterValue(XTtcPs *InstancePtr) +* +****************************************************************************/ +#if defined(ARMA9) +/* + * ttc supports 16 bit counter for zynq + */ +#define XTtcPs_GetCounterValue(InstancePtr) \ + (u16)InstReadReg((InstancePtr), XTTCPS_COUNT_VALUE_OFFSET) +#else +/* + * ttc supports 32 bit counter for zynq ultrascale+mpsoc + */ +#define XTtcPs_GetCounterValue(InstancePtr) \ + InstReadReg((InstancePtr), XTTCPS_COUNT_VALUE_OFFSET) +#endif + +/*****************************************************************************/ +/** +* +* This function sets the interval value to be used in interval mode. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param Value is the 16-bit value to be set in the interval register. +* +* @return None +* +* @note C-style signature: +* void XTtcPs_SetInterval(XTtcPs *InstancePtr, XInterval Value) +* +****************************************************************************/ +#define XTtcPs_SetInterval(InstancePtr, Value) \ + InstWriteReg((InstancePtr), XTTCPS_INTERVAL_VAL_OFFSET, (Value)) + +/*****************************************************************************/ +/** +* +* This function gets the interval value from the interval register. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return zynq:16 bit interval value. +* zynq ultrascale+mpsoc:32 bit interval value. +* +* @note C-style signature: +* zynq: u16 XTtcPs_GetInterval(XTtcPs *InstancePtr) +* zynq ultrascale+mpsoc: u32 XTtcPs_GetInterval(XTtcPs *InstancePtr) +* +****************************************************************************/ +#if defined(ARMA9) +/* + * ttc supports 16 bit interval counter for zynq + */ +#define XTtcPs_GetInterval(InstancePtr) \ + (u16)InstReadReg((InstancePtr), XTTCPS_INTERVAL_VAL_OFFSET) +#else +/* + * ttc supports 32 bit interval counter for zynq ultrascale+mpsoc + */ +#define XTtcPs_GetInterval(InstancePtr) \ + InstReadReg((InstancePtr), XTTCPS_INTERVAL_VAL_OFFSET) +#endif +/*****************************************************************************/ +/** +* +* This macro resets the count register. It may be called at any time. The +* counter is reset to either 0 or 0xFFFF, or the interval value, depending on +* the increment/decrement mode. The state of the counter, as started or +* stopped, is not affected by calling reset. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return None +* +* @note C-style signature: +* void XTtcPs_ResetCounterValue(XTtcPs *InstancePtr) +* +****************************************************************************/ +#define XTtcPs_ResetCounterValue(InstancePtr) \ + InstWriteReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET, \ + (InstReadReg((InstancePtr), XTTCPS_CNT_CNTRL_OFFSET) | \ + (u32)XTTCPS_CNT_CNTRL_RST_MASK)) + +/*****************************************************************************/ +/** +* +* This function enables the interrupts. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param InterruptMask defines which interrupt should be enabled. +* Constants are defined in xttcps_hw.h as XTTCPS_IXR_*. +* This is a bit mask, all set bits will be enabled, cleared bits +* will not be disabled. +* +* @return None. +* +* @note +* C-style signature: +* void XTtcPs_EnableInterrupts(XTtcPs *InstancePtr, u32 InterruptMask) +* +******************************************************************************/ +#define XTtcPs_EnableInterrupts(InstancePtr, InterruptMask) \ + InstWriteReg((InstancePtr), XTTCPS_IER_OFFSET, \ + (InstReadReg((InstancePtr), XTTCPS_IER_OFFSET) | \ + (InterruptMask))) + +/*****************************************************************************/ +/** +* +* This function disables the interrupts. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param InterruptMask defines which interrupt should be disabled. +* Constants are defined in xttcps_hw.h as XTTCPS_IXR_*. +* This is a bit mask, all set bits will be disabled, cleared bits +* will not be disabled. +* +* @return None. +* +* @note +* C-style signature: +* void XTtcPs_DisableInterrupts(XTtcPs *InstancePtr, u32 InterruptMask) +* +******************************************************************************/ +#define XTtcPs_DisableInterrupts(InstancePtr, InterruptMask) \ + InstWriteReg((InstancePtr), XTTCPS_IER_OFFSET, \ + (InstReadReg((InstancePtr), XTTCPS_IER_OFFSET) & \ + ~(InterruptMask))) + +/*****************************************************************************/ +/** +* +* This function reads the interrupt status. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return None. +* +* @note C-style signature: +* u32 XTtcPs_GetInterruptStatus(XTtcPs *InstancePtr) +* +******************************************************************************/ +#define XTtcPs_GetInterruptStatus(InstancePtr) \ + InstReadReg((InstancePtr), XTTCPS_ISR_OFFSET) + +/*****************************************************************************/ +/** +* +* This function clears the interrupt status. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param InterruptMask defines which interrupt should be cleared. +* Constants are defined in xttcps_hw.h as XTTCPS_IXR_*. +* This is a bit mask, all set bits will be cleared, cleared bits +* will not be cleared. +* +* @return None. +* +* @note +* C-style signature: +* void XTtcPs_ClearInterruptStatus(XTtcPs *InstancePtr, u32 InterruptMask) +* +******************************************************************************/ +#define XTtcPs_ClearInterruptStatus(InstancePtr, InterruptMask) \ + (void) InterruptMask; \ + InstReadReg((InstancePtr), XTTCPS_ISR_OFFSET) + + +/************************** Function Prototypes ******************************/ + +/* + * Initialization functions in xttcps_sinit.c + */ +XTtcPs_Config *XTtcPs_LookupConfig(u16 DeviceId); + +/* + * Required functions, in xttcps.c + */ +s32 XTtcPs_CfgInitialize(XTtcPs *InstancePtr, + XTtcPs_Config * ConfigPtr, u32 EffectiveAddr); + +void XTtcPs_SetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex, XMatchRegValue Value); +XMatchRegValue XTtcPs_GetMatchValue(XTtcPs *InstancePtr, u8 MatchIndex); + +void XTtcPs_SetPrescaler(XTtcPs *InstancePtr, u8 PrescalerValue); +u8 XTtcPs_GetPrescaler(XTtcPs *InstancePtr); + +void XTtcPs_CalcIntervalFromFreq(XTtcPs *InstancePtr, u32 Freq, + XInterval *Interval, u8 *Prescaler); + +/* + * Functions for options, in file xttcps_options.c + */ +s32 XTtcPs_SetOptions(XTtcPs *InstancePtr, u32 Options); +u32 XTtcPs_GetOptions(XTtcPs *InstancePtr); + +/* + * Function for self-test, in file xttcps_selftest.c + */ +s32 XTtcPs_SelfTest(XTtcPs *InstancePtr); +u32 XTtcPs_InterruptHandler(XTtcPs *InstancePtr); +void XTtcPs_SetStatusHandler(XTtcPs *InstancePtr, void *CallBackRef, + XTtcPs_StatusHandler FuncPointer); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_g.c new file mode 100644 index 0000000..ee027ca --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_g.c @@ -0,0 +1,98 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xttcps_g.c +* @addtogroup ttcps Overview +* @{ +* +* This file contains a configuration table where each entry is the +* configuration information for one timer counter device in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00a drg/jz 01/21/10 First release
+* 2.00  hk     22/01/14 Added check for picking instances other than
+*                       default.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xttcps.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Prototypes ******************************/ + +/** + * This table contains configuration information for each TTC device + * in the system. + */ +XTtcPs_Config XTtcPs_ConfigTable[XPAR_XTTCPS_NUM_INSTANCES] = { + { + (u16)XPAR_XTTCPS_0_DEVICE_ID, /* Device ID for instance */ + (u32)XPAR_XTTCPS_0_BASEADDR, /* Device base address */ + (u32)XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ /* Device input clock frequency */ + }, +#ifdef XPAR_XTTCPS_1_DEVICE_ID + { + (u16)XPAR_XTTCPS_1_DEVICE_ID, /* Device ID for instance */ + (u32)XPAR_XTTCPS_1_BASEADDR, /* Device base address */ + (u32)XPAR_XTTCPS_1_CLOCK_HZ /* Device input clock frequency */ + }, +#endif + +#ifdef XPAR_XTTCPS_2_DEVICE_ID + { + (u16)XPAR_XTTCPS_2_DEVICE_ID, /* Device ID for instance */ + (u32)XPAR_XTTCPS_2_BASEADDR, /* Device base address */ + (u32)XPAR_XTTCPS_2_CLOCK_HZ /* Device input clock frequency */ + }, +#endif + +#ifdef XPAR_XTTCPS_3_DEVICE_ID + { + (u16)XPAR_XTTCPS_3_DEVICE_ID, /* Device ID for instance */ + (u32)XPAR_XTTCPS_3_BASEADDR, /* Device base address */ + (u32)XPAR_XTTCPS_3_CLOCK_HZ /* Device input clock frequency */ + }, +#endif + +#ifdef XPAR_XTTCPS_4_DEVICE_ID + { + (u16)XPAR_XTTCPS_4_DEVICE_ID, /* Device ID for instance */ + (u32)XPAR_XTTCPS_4_BASEADDR, /* Device base address */ + (u32)XPAR_XTTCPS_4_CLOCK_HZ /* Device input clock frequency */ + }, +#endif + +#ifdef XPAR_XTTCPS_5_DEVICE_ID + { + (u16)XPAR_XTTCPS_5_DEVICE_ID, /* Device ID for instance */ + (u32)XPAR_XTTCPS_5_BASEADDR, /* Device base address */ + (u32)XPAR_XTTCPS_5_CLOCK_HZ /* Device input clock frequency */ + }, +#endif +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_hw.h new file mode 100644 index 0000000..64354a3 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_hw.h @@ -0,0 +1,208 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xttcps_hw.h +* @addtogroup ttcps Overview +* @{ +* +* This file defines the hardware interface to one of the three timer counters +* in the Ps block. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -------------------------------------------------
+* 1.00a drg/jz 01/21/10 First release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.5   srm    10/06/17 Updated XTTCPS_COUNT_VALUE_MASK,
+*                       XTTCPS_INTERVAL_VAL_MASK, XTTCPS_MATCH_MASK macros to
+*                       mask 16 bit values for zynq and 32 bit values for
+*                       zynq ultrascale+mpsoc "
+* 
+* +******************************************************************************/ + +#ifndef XTTCPS_HW_H /* prevent circular inclusions */ +#define XTTCPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ +/* + * Flag for a9 processor + */ + #if !defined (ARMR5) && !defined (__aarch64__) && !defined (ARMA53_32) + #define ARMA9 + #endif + +/** @name Register Map + * + * Register offsets from the base address of the device. + * + * @{ + */ +#define XTTCPS_CLK_CNTRL_OFFSET 0x00000000U /**< Clock Control Register */ +#define XTTCPS_CNT_CNTRL_OFFSET 0x0000000CU /**< Counter Control Register*/ +#define XTTCPS_COUNT_VALUE_OFFSET 0x00000018U /**< Current Counter Value */ +#define XTTCPS_INTERVAL_VAL_OFFSET 0x00000024U /**< Interval Count Value */ +#define XTTCPS_MATCH_0_OFFSET 0x00000030U /**< Match 1 value */ +#define XTTCPS_MATCH_1_OFFSET 0x0000003CU /**< Match 2 value */ +#define XTTCPS_MATCH_2_OFFSET 0x00000048U /**< Match 3 value */ +#define XTTCPS_ISR_OFFSET 0x00000054U /**< Interrupt Status Register */ +#define XTTCPS_IER_OFFSET 0x00000060U /**< Interrupt Enable Register */ +/* @} */ + +/** @name Clock Control Register + * Clock Control Register definitions + * @{ + */ +#define XTTCPS_CLK_CNTRL_PS_EN_MASK 0x00000001U /**< Prescale enable */ +#define XTTCPS_CLK_CNTRL_PS_VAL_MASK 0x0000001EU /**< Prescale value */ +#define XTTCPS_CLK_CNTRL_PS_VAL_SHIFT 1U /**< Prescale shift */ +#define XTTCPS_CLK_CNTRL_PS_DISABLE 16U /**< Prescale disable */ +#define XTTCPS_CLK_CNTRL_SRC_MASK 0x00000020U /**< Clock source */ +#define XTTCPS_CLK_CNTRL_EXT_EDGE_MASK 0x00000040U /**< External Clock edge */ +/* @} */ + +/** @name Counter Control Register + * Counter Control Register definitions + * @{ + */ +#define XTTCPS_CNT_CNTRL_DIS_MASK 0x00000001U /**< Disable the counter */ +#define XTTCPS_CNT_CNTRL_INT_MASK 0x00000002U /**< Interval mode */ +#define XTTCPS_CNT_CNTRL_DECR_MASK 0x00000004U /**< Decrement mode */ +#define XTTCPS_CNT_CNTRL_MATCH_MASK 0x00000008U /**< Match mode */ +#define XTTCPS_CNT_CNTRL_RST_MASK 0x00000010U /**< Reset counter */ +#define XTTCPS_CNT_CNTRL_EN_WAVE_MASK 0x00000020U /**< Enable waveform */ +#define XTTCPS_CNT_CNTRL_POL_WAVE_MASK 0x00000040U /**< Waveform polarity */ +#define XTTCPS_CNT_CNTRL_RESET_VALUE 0x00000021U /**< Reset value */ +/* @} */ + +/** @name Current Counter Value Register + * Current Counter Value Register definitions + * @{ + */ +#if defined(ARMA9) +#define XTTCPS_COUNT_VALUE_MASK 0x0000FFFFU /**< 16-bit counter value */ +#else +#define XTTCPS_COUNT_VALUE_MASK 0xFFFFFFFFU /**< 32-bit counter value */ +#endif +/* @} */ + +/** @name Interval Value Register + * Interval Value Register is the maximum value the counter will count up or + * down to. + * @{ + */ +#if defined(ARMA9) +#define XTTCPS_INTERVAL_VAL_MASK 0x0000FFFFU /**< 16-bit Interval value*/ +#else +#define XTTCPS_INTERVAL_VAL_MASK 0xFFFFFFFFU /**< 32-bit Interval value*/ +#endif +/* @} */ + +/** @name Match Registers + * Definitions for Match registers, each timer counter has three match + * registers. + * @{ + */ +#if defined(ARMA9) +#define XTTCPS_MATCH_MASK 0x0000FFFFU /**< 16-bit Match value */ +#else +#define XTTCPS_MATCH_MASK 0xFFFFFFFFU /**< 32-bit Match value */ +#endif +#define XTTCPS_NUM_MATCH_REG 3U /**< Num of Match reg */ +/* @} */ + +/** @name Interrupt Registers + * Following register bit mask is for all interrupt registers. + * + * @{ + */ +#define XTTCPS_IXR_INTERVAL_MASK 0x00000001U /**< Interval Interrupt */ +#define XTTCPS_IXR_MATCH_0_MASK 0x00000002U /**< Match 1 Interrupt */ +#define XTTCPS_IXR_MATCH_1_MASK 0x00000004U /**< Match 2 Interrupt */ +#define XTTCPS_IXR_MATCH_2_MASK 0x00000008U /**< Match 3 Interrupt */ +#define XTTCPS_IXR_CNT_OVR_MASK 0x00000010U /**< Counter Overflow */ +#define XTTCPS_IXR_ALL_MASK 0x0000001FU /**< All valid Interrupts */ +/* @} */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* Read the given Timer Counter register. +* +* @param BaseAddress is the base address of the timer counter device. +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note C-style signature: +* u32 XTtcPs_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XTtcPs_ReadReg(BaseAddress, RegOffset) \ + (Xil_In32((BaseAddress) + (u32)(RegOffset))) + +/****************************************************************************/ +/** +* +* Write the given Timer Counter register. +* +* @param BaseAddress is the base address of the timer counter device. +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note C-style signature: +* void XTtcPs_WriteReg(XTtcPs BaseAddress, u32 RegOffset, +* u32 Data) +* +*****************************************************************************/ +#define XTtcPs_WriteReg(BaseAddress, RegOffset, Data) \ + (Xil_Out32((BaseAddress) + (u32)(RegOffset), (u32)(Data))) + +/****************************************************************************/ +/** +* +* Calculate a match register offset using the Match Register index. +* +* @param MatchIndex is the 0-2 value of the match register +* +* @return MATCH_N_OFFSET. +* +* @note C-style signature: +* u32 XTtcPs_Match_N_Offset(u8 MatchIndex) +* +*****************************************************************************/ +#define XTtcPs_Match_N_Offset(MatchIndex) \ + ((u32)XTTCPS_MATCH_0_OFFSET + ((u32)(12U) * (u32)(MatchIndex))) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +#ifdef __cplusplus +} +#endif +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_options.c b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_options.c new file mode 100644 index 0000000..6da2260 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_options.c @@ -0,0 +1,193 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xttcps_options.c +* @addtogroup ttcps Overview +* @{ +* +* This file contains functions to get or set option features for the device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------
+* 1.00a drg/jz 01/21/10 First release
+* 1.01a nm     03/05/2012 Removed break statement after return to remove
+*                         compilation warnings.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.10  aru    05/16/19 Removed the redudant code from XTtcPs_SetOptions().
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xttcps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +/* + * Create the table of options which are processed to get/set the device + * options. These options are table driven to allow easy maintenance and + * expansion of the options. + */ +typedef struct { + u32 Option; + u32 Mask; + u32 Register; +} OptionsMap; + +static OptionsMap TmrCtrOptionsTable[] = { + {XTTCPS_OPTION_EXTERNAL_CLK, XTTCPS_CLK_CNTRL_SRC_MASK, + XTTCPS_CLK_CNTRL_OFFSET}, + {XTTCPS_OPTION_CLK_EDGE_NEG, XTTCPS_CLK_CNTRL_EXT_EDGE_MASK, + XTTCPS_CLK_CNTRL_OFFSET}, + {XTTCPS_OPTION_INTERVAL_MODE, XTTCPS_CNT_CNTRL_INT_MASK, + XTTCPS_CNT_CNTRL_OFFSET}, + {XTTCPS_OPTION_DECREMENT, XTTCPS_CNT_CNTRL_DECR_MASK, + XTTCPS_CNT_CNTRL_OFFSET}, + {XTTCPS_OPTION_MATCH_MODE, XTTCPS_CNT_CNTRL_MATCH_MASK, + XTTCPS_CNT_CNTRL_OFFSET}, + {XTTCPS_OPTION_WAVE_DISABLE, XTTCPS_CNT_CNTRL_EN_WAVE_MASK, + XTTCPS_CNT_CNTRL_OFFSET}, + {XTTCPS_OPTION_WAVE_POLARITY, XTTCPS_CNT_CNTRL_POL_WAVE_MASK, + XTTCPS_CNT_CNTRL_OFFSET}, +}; + +#define XTTCPS_NUM_TMRCTR_OPTIONS (sizeof(TmrCtrOptionsTable) / \ + sizeof(OptionsMap)) + +/*****************************************************************************/ +/** +* +* This function sets the options for the TTC device. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* @param Options contains the specified options to be set. This is a bit +* mask where a 1 means to turn the option on, and a 0 means to +* turn the option off. One or more bit values may be contained +* in the mask. See the bit definitions named XTTCPS_*_OPTION in +* the file xttcps.h. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_FAILURE if any of the options are unknown. +* +* @note None +* +******************************************************************************/ +s32 XTtcPs_SetOptions(XTtcPs *InstancePtr, u32 Options) +{ + u32 CountReg; + u32 ClockReg; + u32 Index; + s32 Status = XST_SUCCESS; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + ClockReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress, + XTTCPS_CLK_CNTRL_OFFSET); + CountReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress, + XTTCPS_CNT_CNTRL_OFFSET); + + /* + * Loop through the options table, turning the option on or off + * depending on whether the bit is set in the incoming options flag. + */ + for (Index = 0U; Index < XTTCPS_NUM_TMRCTR_OPTIONS; Index++) { + if ((Options & TmrCtrOptionsTable[Index].Option) != (u32)0) { + if(TmrCtrOptionsTable[Index].Register == XTTCPS_CLK_CNTRL_OFFSET) { + ClockReg |= TmrCtrOptionsTable[Index].Mask; + } else { + CountReg |= TmrCtrOptionsTable[Index].Mask; + } + } else { + if(TmrCtrOptionsTable[Index].Register == XTTCPS_CLK_CNTRL_OFFSET) { + ClockReg &= ~TmrCtrOptionsTable[Index].Mask; + } else { + CountReg &= ~TmrCtrOptionsTable[Index].Mask; + } + } + } + + /* + * Now write the registers. Leave it to the upper layers to restart the + * device. + */ + if (Status != (s32)XST_FAILURE ) { + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTTCPS_CLK_CNTRL_OFFSET, ClockReg); + XTtcPs_WriteReg(InstancePtr->Config.BaseAddress, + XTTCPS_CNT_CNTRL_OFFSET, CountReg); + } + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function gets the settings for the options for the TTC device. +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return +* +* The return u32 contains the specified options that are set. This is a bit +* mask where a '1' means the option is on, and a'0' means the option is off. +* One or more bit values may be contained in the mask. See the bit definitions +* named XTTCPS_*_OPTION in the file xttcps.h. +* +* @note None. +* +******************************************************************************/ +u32 XTtcPs_GetOptions(XTtcPs *InstancePtr) +{ + u32 OptionsFlag = 0U; + u32 Register; + u32 Index; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + /* + * Loop through the options table to determine which options are set + */ + for (Index = 0U; Index < XTTCPS_NUM_TMRCTR_OPTIONS; Index++) { + /* + * Get the control register to determine which options are + * currently set. + */ + Register = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress, + TmrCtrOptionsTable[Index]. + Register); + + if ((Register & TmrCtrOptionsTable[Index].Mask) != (u32)0) { + OptionsFlag |= TmrCtrOptionsTable[Index].Option; + } + } + + return OptionsFlag; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_selftest.c b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_selftest.c new file mode 100644 index 0000000..a0be259 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_selftest.c @@ -0,0 +1,84 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xttcps_selftest.c +* @addtogroup ttcps Overview +* @{ +* +* This file contains the implementation of self test function for the +* XTtcPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------
+* 1.00a drg/jz 01/21/10 First release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xttcps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Runs a self-test on the driver/device. +* +* +* @param InstancePtr is a pointer to the XTtcPs instance. +* +* @return +* +* - XST_SUCCESS if successful +* - XST_FAILURE indicates a register did not read or write correctly +* +* @note This test fails if it is not called right after initialization. +* +******************************************************************************/ +s32 XTtcPs_SelfTest(XTtcPs *InstancePtr) +{ + s32 Status; + u32 TempReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * All the TTC registers should be in their default state right now. + */ + TempReg = XTtcPs_ReadReg(InstancePtr->Config.BaseAddress, + XTTCPS_CNT_CNTRL_OFFSET); + if (XTTCPS_CNT_CNTRL_RESET_VALUE != (u32)TempReg) { + Status = XST_FAILURE; + } + else { + Status = XST_SUCCESS; + } + return Status; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_sinit.c new file mode 100644 index 0000000..5d50de9 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/ttcps/src/xttcps_sinit.c @@ -0,0 +1,73 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xttcps_sinit.c +* @addtogroup ttcps Overview +* @{ +* +* The implementation of the XTtcPs driver's static initialization functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------
+* 1.00a drg/jz 01/21/10 First release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xttcps.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XTtcPs_Config XTtcPs_ConfigTable[XPAR_XTTCPS_NUM_INSTANCES]; + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the unique ID of the device +* +* @return +* +* A pointer to the configuration found or NULL if the specified device ID was +* not found. See xttcps.h for the definition of XTtcPs_Config. +* +* @note None. +* +******************************************************************************/ +XTtcPs_Config *XTtcPs_LookupConfig(u16 DeviceId) +{ + XTtcPs_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_XTTCPS_NUM_INSTANCES; Index++) { + if (XTtcPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XTtcPs_ConfigTable[Index]; + break; + } + } + + return (XTtcPs_Config *)CfgPtr; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/Makefile new file mode 100644 index 0000000..5feeb49 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/Makefile @@ -0,0 +1,39 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf $(DEPFILES) diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps.c b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps.c new file mode 100644 index 0000000..86af54d --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps.c @@ -0,0 +1,631 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xuartps.c +* @addtogroup uartps Overview +* @{ +* +* This file contains the implementation of the interface functions for XUartPs +* driver. Refer to the header file xuartps.h for more detailed information. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	 Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/13/10 First Release
+* 2.2   hk     06/23/14 SW reset of RX and TX should be done when changing
+*                       baud rate. CR# 804281.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.5	NK     09/26/17 Fix the RX Buffer Overflow issue.
+* 3.7   aru    08/17/18 Resolved MISRA-C mandatory violations.(CR#1007755)
+* 3.9   sd     02/06/20 Added clock support
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xuartps.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ + +/* The following constant defines the amount of error that is allowed for + * a specified baud rate. This error is the difference between the actual + * baud rate that will be generated using the specified clock and the + * desired baud rate. + */ +#define XUARTPS_MAX_BAUD_ERROR_RATE 3U /* max % error allowed */ + +/**************************** Type Definitions ******************************/ + + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +static void XUartPs_StubHandler(void *CallBackRef, u32 Event, + u32 ByteCount); + +u32 XUartPs_SendBuffer(XUartPs *InstancePtr); + +u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr); + +/************************** Variable Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Initializes a specific XUartPs instance such that it is ready to be used. +* The data format of the device is setup for 8 data bits, 1 stop bit, and no +* parity by default. The baud rate is set to a default value specified by +* Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The +* receive FIFO threshold is set for 8 bytes. The default operating mode of the +* driver is polled mode. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param Config is a reference to a structure containing information +* about a specific XUartPs driver. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, pass in the physical +* address instead. +* +* @return +* +* - XST_SUCCESS if initialization was successful +* - XST_UART_BAUD_ERROR if the baud rate is not possible because +* the inputclock frequency is not divisible with an acceptable +* amount of error +* +* @note +* +* The default configuration for the UART after initialization is: +* +* - 19,200 bps or XPAR_DFT_BAUDRATE if defined +* - 8 data bits +* - 1 stop bit +* - no parity +* - FIFO's are enabled with a receive threshold of 8 bytes +* - The RX timeout is enabled with a timeout of 1 (4 char times) +* +* All interrupts are disabled. +* +*****************************************************************************/ +s32 XUartPs_CfgInitialize(XUartPs *InstancePtr, + XUartPs_Config * Config, u32 EffectiveAddr) +{ + s32 Status; + u32 ModeRegister; + u32 BaudRate; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Config != NULL); + + /* Setup the driver instance using passed in parameters */ + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->Config.InputClockHz = Config->InputClockHz; +#if defined (XCLOCKING) + InstancePtr->Config.RefClk = Config->RefClk; +#endif + InstancePtr->Config.ModemPinsConnected = Config->ModemPinsConnected; + + /* Initialize other instance data to default values */ + InstancePtr->Handler = (XUartPs_Handler)XUartPs_StubHandler; + + InstancePtr->SendBuffer.NextBytePtr = NULL; + InstancePtr->SendBuffer.RemainingBytes = 0U; + InstancePtr->SendBuffer.RequestedBytes = 0U; + + InstancePtr->ReceiveBuffer.NextBytePtr = NULL; + InstancePtr->ReceiveBuffer.RemainingBytes = 0U; + InstancePtr->ReceiveBuffer.RequestedBytes = 0U; + + /* Initialize the platform data */ + InstancePtr->Platform = XGetPlatform_Info(); + + InstancePtr->is_rxbs_error = 0U; + + /* Flag that the driver instance is ready to use */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* + * Set the default baud rate here, can be changed prior to + * starting the device + */ + BaudRate = (u32)XUARTPS_DFT_BAUDRATE; + Status = XUartPs_SetBaudRate(InstancePtr, BaudRate); + if (Status != (s32)XST_SUCCESS) { + InstancePtr->IsReady = 0U; + } else { + + /* + * Set up the default data format: 8 bit data, 1 stop bit, no + * parity + */ + ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* Mask off what's already there */ + ModeRegister &= (~((u32)XUARTPS_MR_CHARLEN_MASK | + (u32)XUARTPS_MR_STOPMODE_MASK | + (u32)XUARTPS_MR_PARITY_MASK)); + + /* Set the register value to the desired data format */ + ModeRegister |= ((u32)XUARTPS_MR_CHARLEN_8_BIT | + (u32)XUARTPS_MR_STOPMODE_1_BIT | + (u32)XUARTPS_MR_PARITY_NONE); + + /* Write the mode register out */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + + /* Set the RX FIFO trigger at 8 data bytes. */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXWM_OFFSET, 0x08U); + + /* Set the RX timeout to 1, which will be 4 character time */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXTOUT_OFFSET, 0x01U); + + /* Disable all interrupts, polled mode is the default */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + XUARTPS_IXR_MASK); + + Status = XST_SUCCESS; + } + return Status; +} + +/****************************************************************************/ +/** +* +* This functions sends the specified buffer using the device in either +* polled or interrupt driven mode. This function is non-blocking, if the device +* is busy sending data, it will return and indicate zero bytes were sent. +* Otherwise, it fills the TX FIFO as much as it can, and return the number of +* bytes sent. +* +* In a polled mode, this function will only send as much data as TX FIFO can +* buffer. The application may need to call it repeatedly to send the entire +* buffer. +* +* In interrupt mode, this function will start sending the specified buffer, +* then the interrupt handler will continue sending data until the entire +* buffer has been sent. A callback function, as specified by the application, +* will be called to indicate the completion of sending. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param BufferPtr is pointer to a buffer of data to be sent. +* @param NumBytes contains the number of bytes to be sent. A value of +* zero will stop a previous send operation that is in progress +* in interrupt mode. Any data that was already put into the +* transmit FIFO will be sent. +* +* @return The number of bytes actually sent. +* +* @note +* +* The number of bytes is not asserted so that this function may be called with +* a value of zero to stop an operation that is already in progress. +*

+* +*****************************************************************************/ +u32 XUartPs_Send(XUartPs *InstancePtr, u8 *BufferPtr, + u32 NumBytes) +{ + u32 BytesSent; + + /* Asserts validate the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#if defined (XCLOCKING) + Xil_ClockEnable(InstancePtr->Config.RefClk); +#endif + /* + * Disable the UART transmit interrupts to allow this call to stop a + * previous operation that may be interrupt driven. + */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL)); + + /* Setup the buffer parameters */ + InstancePtr->SendBuffer.RequestedBytes = NumBytes; + InstancePtr->SendBuffer.RemainingBytes = NumBytes; + InstancePtr->SendBuffer.NextBytePtr = BufferPtr; + + /* + * Transmit interrupts will be enabled in XUartPs_SendBuffer(), after + * filling the TX FIFO. + */ + BytesSent = XUartPs_SendBuffer(InstancePtr); + + return BytesSent; +} + +/****************************************************************************/ +/** +* +* This function attempts to receive a specified number of bytes of data +* from the device and store it into the specified buffer. This function works +* for both polled or interrupt driven modes. It is non-blocking. +* +* In a polled mode, this function will only receive the data already in the +* RX FIFO. The application may need to call it repeatedly to receive the +* entire buffer. Polled mode is the default mode of operation for the device. +* +* In interrupt mode, this function will start the receiving, if not the entire +* buffer has been received, the interrupt handler will continue receiving data +* until the entire buffer has been received. A callback function, as specified +* by the application, will be called to indicate the completion of the +* receiving or error conditions. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param BufferPtr is pointer to buffer for data to be received into +* @param NumBytes is the number of bytes to be received. A value of zero +* will stop a previous receive operation that is in progress in +* interrupt mode. +* +* @return The number of bytes received. +* +* @note +* +* The number of bytes is not asserted so that this function may be called +* with a value of zero to stop an operation that is already in progress. +* +*****************************************************************************/ +u32 XUartPs_Recv(XUartPs *InstancePtr, + u8 *BufferPtr, u32 NumBytes) +{ + u32 ReceivedCount; + u32 ImrRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + +#if defined (XCLOCKING) + Xil_ClockEnable(InstancePtr->Config.RefClk); +#endif + /* + * Disable all the interrupts. + * This stops a previous operation that may be interrupt driven + */ + ImrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + XUARTPS_IXR_MASK); + + /* Setup the buffer parameters */ + InstancePtr->ReceiveBuffer.RequestedBytes = NumBytes; + InstancePtr->ReceiveBuffer.RemainingBytes = NumBytes; + InstancePtr->ReceiveBuffer.NextBytePtr = BufferPtr; + + /* Receive the data from the device */ + ReceivedCount = XUartPs_ReceiveBuffer(InstancePtr); + + /* Restore the interrupt state */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, + ImrRegister); + + return ReceivedCount; +} + +/****************************************************************************/ +/* +* +* This function sends a buffer that has been previously specified by setting +* up the instance variables of the instance. This function is an internal +* function for the XUartPs driver such that it may be called from a shell +* function that sets up the buffer or from an interrupt handler. +* +* This function sends the specified buffer in either polled or interrupt +* driven modes. This function is non-blocking. +* +* In a polled mode, this function only sends as much data as the TX FIFO +* can buffer. The application may need to call it repeatedly to send the +* entire buffer. +* +* In interrupt mode, this function starts the sending of the buffer, if not +* the entire buffer has been sent, then the interrupt handler continues the +* sending until the entire buffer has been sent. A callback function, as +* specified by the application, will be called to indicate the completion of +* sending. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return The number of bytes actually sent +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_SendBuffer(XUartPs *InstancePtr) +{ + u32 SentCount = 0U; + u32 ImrRegister; + + /* + * If the TX FIFO is full, send nothing. + * Otherwise put bytes into the TX FIFO unil it is full, or all of the + * data has been put into the FIFO. + */ + while ((!XUartPs_IsTransmitFull(InstancePtr->Config.BaseAddress)) && + (InstancePtr->SendBuffer.RemainingBytes > SentCount)) { + + /* Fill the FIFO from the buffer */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_FIFO_OFFSET, + ((u32)InstancePtr->SendBuffer. + NextBytePtr[SentCount])); + + /* Increment the send count. */ + SentCount++; + } + + /* Update the buffer to reflect the bytes that were sent from it */ + InstancePtr->SendBuffer.NextBytePtr += SentCount; + InstancePtr->SendBuffer.RemainingBytes -= SentCount; + + /* + * If interrupts are enabled as indicated by the receive interrupt, then + * enable the TX FIFO empty interrupt, so further action can be taken + * for this sending. + */ + ImrRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + if (((ImrRegister & XUARTPS_IXR_RXFULL) != (u32)0) || + ((ImrRegister & XUARTPS_IXR_RXEMPTY) != (u32)0)|| + ((ImrRegister & XUARTPS_IXR_RXOVR) != (u32)0)) { + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IER_OFFSET, + ImrRegister | (u32)XUARTPS_IXR_TXEMPTY); + } + + return SentCount; +} + +/****************************************************************************/ +/* +* +* This function receives a buffer that has been previously specified by setting +* up the instance variables of the instance. This function is an internal +* function, and it may be called from a shell function that sets up the buffer +* or from an interrupt handler. +* +* This function attempts to receive a specified number of bytes from the +* device and store it into the specified buffer. This function works for +* either polled or interrupt driven modes. It is non-blocking. +* +* In polled mode, this function only receives as much data as in the RX FIFO. +* The application may need to call it repeatedly to receive the entire buffer. +* Polled mode is the default mode for the driver. +* +* In interrupt mode, this function starts the receiving, if not the entire +* buffer has been received, the interrupt handler will continue until the +* entire buffer has been received. A callback function, as specified by the +* application, will be called to indicate the completion of the receiving or +* error conditions. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return The number of bytes received. +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr) +{ + u32 CsrRegister; + u32 ReceivedCount = 0U; + u32 ByteStatusValue, EventData; + u32 Event; + + /* + * Read the Channel Status Register to determine if there is any data in + * the RX FIFO + */ + CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_SR_OFFSET); + + /* + * Loop until there is no more data in RX FIFO or the specified + * number of bytes has been received + */ + while((ReceivedCount < InstancePtr->ReceiveBuffer.RemainingBytes)&& + (((CsrRegister & XUARTPS_SR_RXEMPTY) == (u32)0))){ + + if (InstancePtr->is_rxbs_error) { + ByteStatusValue = XUartPs_ReadReg( + InstancePtr->Config.BaseAddress, + XUARTPS_RXBS_OFFSET); + if((ByteStatusValue & XUARTPS_RXBS_MASK)!= (u32)0) { + EventData = ByteStatusValue; + Event = XUARTPS_EVENT_PARE_FRAME_BRKE; + /* + * Call the application handler to indicate that there is a receive + * error or a break interrupt, if the application cares about the + * error it call a function to get the last errors. + */ + InstancePtr->Handler(InstancePtr->CallBackRef, + Event, EventData); + } + } + + InstancePtr->ReceiveBuffer.NextBytePtr[ReceivedCount] = + XUartPs_ReadReg(InstancePtr->Config. + BaseAddress, + XUARTPS_FIFO_OFFSET); + + ReceivedCount++; + + CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_SR_OFFSET); + } + InstancePtr->is_rxbs_error = 0; + /* + * Update the receive buffer to reflect the number of bytes just + * received + */ + if(InstancePtr->ReceiveBuffer.NextBytePtr != NULL){ + InstancePtr->ReceiveBuffer.NextBytePtr += ReceivedCount; + } + InstancePtr->ReceiveBuffer.RemainingBytes -= ReceivedCount; + + return ReceivedCount; +} + +/*****************************************************************************/ +/** +* +* Sets the baud rate for the device. Checks the input value for +* validity and also verifies that the requested rate can be configured to +* within the maximum error range specified by XUARTPS_MAX_BAUD_ERROR_RATE. +* If the provided rate is not possible, the current setting is unchanged. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param BaudRate to be set +* +* @return +* - XST_SUCCESS if everything configured as expected +* - XST_UART_BAUD_ERROR if the requested rate is not available +* because there was too much error +* +* @note None. +* +*****************************************************************************/ +s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate) +{ + u32 IterBAUDDIV; /* Iterator for available baud divisor values */ + u32 BRGR_Value; /* Calculated value for baud rate generator */ + u32 CalcBaudRate; /* Calculated baud rate */ + u32 BaudError; /* Diff between calculated and requested baud rate */ + u32 Best_BRGR = 0U; /* Best value for baud rate generator */ + u8 Best_BAUDDIV = 0U; /* Best value for baud divisor */ + u32 Best_Error = 0xFFFFFFFFU; + u32 PercentError; + u32 ModeReg; + u32 InputClk; + + /* Asserts validate the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(BaudRate <= (u32)XUARTPS_MAX_RATE); + Xil_AssertNonvoid(BaudRate >= (u32)XUARTPS_MIN_RATE); + + /* + * Make sure the baud rate is not impossilby large. + * Fastest possible baud rate is Input Clock / 2. + */ + if ((BaudRate * 2) > InstancePtr->Config.InputClockHz) { + return XST_UART_BAUD_ERROR; + } + /* Check whether the input clock is divided by 8 */ + ModeReg = XUartPs_ReadReg( InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + InputClk = InstancePtr->Config.InputClockHz; + if(ModeReg & XUARTPS_MR_CLKSEL) { + InputClk = InstancePtr->Config.InputClockHz / 8; + } + + /* + * Determine the Baud divider. It can be 4to 254. + * Loop through all possible combinations + */ + for (IterBAUDDIV = 4; IterBAUDDIV < 255; IterBAUDDIV++) { + + /* Calculate the value for BRGR register */ + BRGR_Value = InputClk / (BaudRate * (IterBAUDDIV + 1)); + + /* Calculate the baud rate from the BRGR value */ + CalcBaudRate = InputClk/ (BRGR_Value * (IterBAUDDIV + 1)); + + /* Avoid unsigned integer underflow */ + if (BaudRate > CalcBaudRate) { + BaudError = BaudRate - CalcBaudRate; + } + else { + BaudError = CalcBaudRate - BaudRate; + } + + /* Find the calculated baud rate closest to requested baud rate. */ + if (Best_Error > BaudError) { + + Best_BRGR = BRGR_Value; + Best_BAUDDIV = IterBAUDDIV; + Best_Error = BaudError; + } + } + + /* Make sure the best error is not too large. */ + PercentError = (Best_Error * 100) / BaudRate; + if (XUARTPS_MAX_BAUD_ERROR_RATE < PercentError) { + return XST_UART_BAUD_ERROR; + } + + /* Disable TX and RX to avoid glitches when setting the baud rate. */ + XUartPs_DisableUart(InstancePtr); + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_BAUDGEN_OFFSET, Best_BRGR); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_BAUDDIV_OFFSET, Best_BAUDDIV); + + /* RX and TX SW reset */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_CR_OFFSET, + XUARTPS_CR_TXRST | XUARTPS_CR_RXRST); + + /* Enable device */ + XUartPs_EnableUart(InstancePtr); + + InstancePtr->BaudRate = BaudRate; + + return XST_SUCCESS; + +} + +/****************************************************************************/ +/** +* +* This function is a stub handler that is the default handler such that if the +* application has not set the handler when interrupts are enabled, this +* function will be called. +* +* @param CallBackRef is unused by this function. +* @param Event is unused by this function. +* @param ByteCount is unused by this function. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void XUartPs_StubHandler(void *CallBackRef, u32 Event, + u32 ByteCount) +{ + (void) CallBackRef; + (void) Event; + (void) ByteCount; + /* Assert occurs always since this is a stub and should never be called */ + Xil_AssertVoidAlways(); +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps.h b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps.h new file mode 100644 index 0000000..20dd99f --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps.h @@ -0,0 +1,508 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xuartps.h +* @addtogroup uartps Overview +* @{ +* @details +* +* This driver supports the following features: +* +* - Dynamic data format (baud rate, data bits, stop bits, parity) +* - Polled mode +* - Interrupt driven mode +* - Transmit and receive FIFOs (32 byte FIFO depth) +* - Access to the external modem control lines +* +* Initialization & Configuration +* +* The XUartPs_Config structure is used by the driver to configure itself. +* Fields inside this structure are properties of XUartPs based on its hardware +* build. +* +* To support multiple runtime loading and initialization strategies employed +* by various operating systems, the driver instance can be initialized in the +* following way: +* +* - XUartPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a +* configuration structure provided by the caller. If running in a system +* with address translation, the parameter EffectiveAddr should be the +* virtual address. +* +* Baud Rate +* +* The UART has an internal baud rate generator, which furnishes the baud rate +* clock for both the receiver and the transmitter. The input clock frequency +* can be either the master clock or the master clock divided by 8, configured +* through the mode register. +* +* Accompanied with the baud rate divider register, the baud rate is determined +* by: +*
+*	baud_rate = input_clock / (bgen * (bdiv + 1)
+* 
+* where bgen is the value of the baud rate generator, and bdiv is the value of +* baud rate divider. +* +* Interrupts +* +* The FIFOs are not flushed when the driver is initialized, but a function is +* provided to allow the user to reset the FIFOs if desired. +* +* The driver defaults to no interrupts at initialization such that interrupts +* must be enabled if desired. An interrupt is generated for one of the +* following conditions. +* +* - A change in the modem signals +* - Data in the receive FIFO for a configuable time without receiver activity +* - A parity error +* - A framing error +* - An overrun error +* - Transmit FIFO is full +* - Transmit FIFO is empty +* - Receive FIFO is full +* - Receive FIFO is empty +* - Data in the receive FIFO equal to the receive threshold +* +* The application can control which interrupts are enabled using the +* XUartPs_SetInterruptMask() function. +* +* In order to use interrupts, it is necessary for the user to connect the +* driver interrupt handler, XUartPs_InterruptHandler(), to the interrupt +* system of the application. A separate handler should be provided by the +* application to communicate with the interrupt system, and conduct +* application specific interrupt handling. An application registers its own +* handler through the XUartPs_SetHandler() function. +* +* Data Transfer +* +* The functions, XUartPs_Send() and XUartPs_Recv(), are provided in the +* driver to allow data to be sent and received. They can be used in either +* polled or interrupt mode. +* +* @note +* +* The default configuration for the UART after initialization is: +* +* - 9,600 bps or XPAR_DFT_BAUDRATE if defined +* - 8 data bits +* - 1 stop bit +* - no parity +* - FIFO's are enabled with a receive threshold of 8 bytes +* - The RX timeout is enabled with a timeout of 1 (4 char times) +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00a	drg/jz 01/12/10 First Release
+* 1.00a sdm    09/27/11 Fixed compiler warnings and also a bug
+*		        in XUartPs_SetFlowDelay where the value was not
+*			being written to the register.
+* 1.01a sdm    12/20/11 Removed the InputClockHz parameter from the XUartPs
+*			instance structure and the driver is updated to use
+*			InputClockHz parameter from the XUartPs_Config config
+*			structure.
+*			Added a parameter to XUartPs_Config structure which
+*			specifies whether the user has selected Modem pins
+*			to be connected to MIO or FMIO.
+*			Added the tcl file to generate the xparameters.h
+* 1.02a sg     05/16/12	Changed XUARTPS_RXWM_MASK to 0x3F for CR 652540 fix.
+* 1.03a sg     07/16/12 Updated XUARTPS_FORMAT_7_BITS and XUARTPS_FORMAT_6_BITS
+*			with the correct values for CR 666724
+* 			Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the name of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added API for uart reset and related
+*			constant definitions.
+* 2.0   hk      03/07/14 Version number revised.
+* 2.1   hk     04/16/14 Change XUARTPS_MAX_RATE to 921600. CR# 780625.
+* 2.2   hk     06/23/14 SW reset of RX and TX should be done when changing
+*                       baud rate. CR# 804281.
+* 3.0   vm     12/09/14 Modified source code according to misrac guideline.
+*			Support for Zynq Ultrascale Mp added.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes. Also added
+*						platform variable in driver instance structure.
+* 3.1   adk   14/03/16  Include interrupt examples in the peripheral test when
+*			uart is connected to a valid interrupt controller CR#946803.
+* 3.2   rk     07/20/16 Modified the logic for transmission break bit set
+* 3.4   ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+* 3.6   ms     02/16/18 Updates the flow control mode offset value in modem
+*                       control register.
+* 3.7   aru    08/17/18 Resolved MISRA-C:2012 compliance mandatory violations.
+* 3.9   rna    12/03/19 Modified the XUARTPS_MAX_RATE macro.
+* 3.9   sd     02/06/20 Added clock support
+* 3.12	gm     11/04/22 Added timeout support using Xil_WaitForEvent
+*
+* 
+* +*****************************************************************************/ + +#ifndef XUARTPS_H /* prevent circular inclusions */ +#define XUARTPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xuartps_hw.h" +#include "xplatform_info.h" +#if defined (XCLOCKING) +#include "xil_clocking.h" +#endif +#include "xil_util.h" + +/************************** Constant Definitions ****************************/ + +/* + * The following constants indicate the max and min baud rates and these + * numbers are based only on the testing that has been done. The hardware + * is capable of other baud rates. + */ +#define XUARTPS_MAX_RATE 6240000U +#define XUARTPS_MIN_RATE 110U + +#define XUARTPS_DFT_BAUDRATE 115200U /* Default baud rate */ + +/** @name Configuration options + * @{ + */ +/** + * These constants specify the options that may be set or retrieved + * with the driver, each is a unique bit mask such that multiple options + * may be specified. These constants indicate the available options + * in active state. + * + */ + +#define XUARTPS_OPTION_SET_BREAK 0x0080U /**< Starts break transmission */ +#define XUARTPS_OPTION_STOP_BREAK 0x0040U /**< Stops break transmission */ +#define XUARTPS_OPTION_RESET_TMOUT 0x0020U /**< Reset the receive timeout */ +#define XUARTPS_OPTION_RESET_TX 0x0010U /**< Reset the transmitter */ +#define XUARTPS_OPTION_RESET_RX 0x0008U /**< Reset the receiver */ +#define XUARTPS_OPTION_ASSERT_RTS 0x0004U /**< Assert the RTS bit */ +#define XUARTPS_OPTION_ASSERT_DTR 0x0002U /**< Assert the DTR bit */ +#define XUARTPS_OPTION_SET_FCM 0x0001U /**< Turn on flow control mode */ +/*@}*/ + + +/** @name Channel Operational Mode + * + * The UART can operate in one of four modes: Normal, Local Loopback, Remote + * Loopback, or automatic echo. + * + * @{ + */ + +#define XUARTPS_OPER_MODE_NORMAL (u8)0x00U /**< Normal Mode */ +#define XUARTPS_OPER_MODE_AUTO_ECHO (u8)0x01U /**< Auto Echo Mode */ +#define XUARTPS_OPER_MODE_LOCAL_LOOP (u8)0x02U /**< Local Loopback Mode */ +#define XUARTPS_OPER_MODE_REMOTE_LOOP (u8)0x03U /**< Remote Loopback Mode */ + +/* @} */ + +/** @name Data format values + * + * These constants specify the data format that the driver supports. + * The data format includes the number of data bits, the number of stop + * bits and parity. + * + * @{ + */ +#define XUARTPS_FORMAT_8_BITS 0U /**< 8 data bits */ +#define XUARTPS_FORMAT_7_BITS 2U /**< 7 data bits */ +#define XUARTPS_FORMAT_6_BITS 3U /**< 6 data bits */ + +#define XUARTPS_FORMAT_NO_PARITY 4U /**< No parity */ +#define XUARTPS_FORMAT_MARK_PARITY 3U /**< Mark parity */ +#define XUARTPS_FORMAT_SPACE_PARITY 2U /**< parity */ +#define XUARTPS_FORMAT_ODD_PARITY 1U /**< Odd parity */ +#define XUARTPS_FORMAT_EVEN_PARITY 0U /**< Even parity */ + +#define XUARTPS_FORMAT_2_STOP_BIT 2U /**< 2 stop bits */ +#define XUARTPS_FORMAT_1_5_STOP_BIT 1U /**< 1.5 stop bits */ +#define XUARTPS_FORMAT_1_STOP_BIT 0U /**< 1 stop bit */ +/*@}*/ + +/** @name Callback events + * + * These constants specify the handler events that an application can handle + * using its specific handler function. Note that these constants are not bit + * mask, so only one event can be passed to an application at a time. + * + * @{ + */ +#define XUARTPS_EVENT_RECV_DATA 1U /**< Data receiving done */ +#define XUARTPS_EVENT_RECV_TOUT 2U /**< A receive timeout occurred */ +#define XUARTPS_EVENT_SENT_DATA 3U /**< Data transmission done */ +#define XUARTPS_EVENT_RECV_ERROR 4U /**< A receive error detected */ +#define XUARTPS_EVENT_MODEM 5U /**< Modem status changed */ +#define XUARTPS_EVENT_PARE_FRAME_BRKE 6U /**< A receive parity, frame, break + * error detected */ +#define XUARTPS_EVENT_RECV_ORERR 7U /**< A receive overrun error detected */ + +/*@}*/ + +#define TIMEOUT_VAL 1000000U /**< Wait for 1 sec in worst case */ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Base address of device (IPIF) */ + u32 InputClockHz;/**< Input clock frequency */ + s32 ModemPinsConnected; /** Specifies whether modem pins are connected + * to MIO or FMIO */ +#if defined (XCLOCKING) + u32 RefClk; /**< Input clock frequency */ +#endif +} XUartPs_Config; + +/* Keep track of state information about a data buffer in the interrupt mode. */ +typedef struct { + u8 *NextBytePtr; + u32 RequestedBytes; + u32 RemainingBytes; +} XUartPsBuffer; + +/** + * Keep track of data format setting of a device. + */ +typedef struct { + u32 BaudRate; /**< In bps, ie 1200 */ + u32 DataBits; /**< Number of data bits */ + u32 Parity; /**< Parity */ + u8 StopBits; /**< Number of stop bits */ +} XUartPsFormat; + +/******************************************************************************/ +/** + * This data type defines a handler that an application defines to communicate + * with interrupt system to retrieve state information about an application. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the handler, and is passed back to the upper layer + * when the handler is called. It is used to find the device driver + * instance. + * @param Event contains one of the event constants indicating events that + * have occurred. + * @param EventData contains the number of bytes sent or received at the + * time of the call for send and receive events and contains the + * modem status for modem events. + * + ******************************************************************************/ +typedef void (*XUartPs_Handler) (void *CallBackRef, u32 Event, + u32 EventData); + +/** + * The XUartPs driver instance data structure. A pointer to an instance data + * structure is passed around by functions to refer to a specific driver + * instance. + */ +typedef struct { + XUartPs_Config Config; /* Configuration data structure */ + u32 InputClockHz; /* Input clock frequency */ + u32 IsReady; /* Device is initialized and ready */ + u32 BaudRate; /* Current baud rate */ + + XUartPsBuffer SendBuffer; + XUartPsBuffer ReceiveBuffer; + + XUartPs_Handler Handler; + void *CallBackRef; /* Callback reference for event handler */ + u32 Platform; + u8 is_rxbs_error; +} XUartPs; + + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* Get the UART Channel Status Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u16 XUartPs_GetChannelStatus(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetChannelStatus(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) + +/****************************************************************************/ +/** +* Get the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_GetControl(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_GetModeControl(InstancePtr) \ + Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET) + +/****************************************************************************/ +/** +* Set the UART Mode Control Register. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_SetModeControl(XUartPs *InstancePtr, u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_SetModeControl(InstancePtr, RegisterValue) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_CR_OFFSET, \ + (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Enable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_EnableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_EnableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + ((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_EN | (u32)XUARTPS_CR_TX_EN))) + +/****************************************************************************/ +/** +* Disable the transmitter and receiver of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_DisableUart(XUartPs *InstancePtr) +* +******************************************************************************/ +#define XUartPs_DisableUart(InstancePtr) \ + Xil_Out32(((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET), \ + (((Xil_In32((InstancePtr)->Config.BaseAddress + (u32)XUARTPS_CR_OFFSET)) & \ + (u32)(~XUARTPS_CR_EN_DIS_MASK)) | ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS))) + +/****************************************************************************/ +/** +* Determine if the transmitter FIFO is empty. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* - TRUE if a byte can be sent +* - FALSE if the Transmitter Fifo is not empty +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitEmpty(XUartPs InstancePtr) +* +******************************************************************************/ +#define XUartPs_IsTransmitEmpty(InstancePtr) \ + ((Xil_In32(((InstancePtr)->Config.BaseAddress) + (u32)XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXEMPTY) == (u32)XUARTPS_SR_TXEMPTY) + + +/************************** Function Prototypes *****************************/ + +/* Static lookup function implemented in xuartps_sinit.c */ +XUartPs_Config *XUartPs_LookupConfig(u16 DeviceId); + +/* Interface functions implemented in xuartps.c */ +s32 XUartPs_CfgInitialize(XUartPs *InstancePtr, + XUartPs_Config * Config, u32 EffectiveAddr); + +u32 XUartPs_Send(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +u32 XUartPs_Recv(XUartPs *InstancePtr,u8 *BufferPtr, + u32 NumBytes); + +s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate); + +/* Options functions in xuartps_options.c */ +void XUartPs_SetOptions(XUartPs *InstancePtr, u16 Options); + +u16 XUartPs_GetOptions(XUartPs *InstancePtr); + +void XUartPs_SetFifoThreshold(XUartPs *InstancePtr, u8 TriggerLevel); + +u8 XUartPs_GetFifoThreshold(XUartPs *InstancePtr); + +u16 XUartPs_GetModemStatus(XUartPs *InstancePtr); + +u32 XUartPs_IsSending(XUartPs *InstancePtr); + +u8 XUartPs_GetOperMode(XUartPs *InstancePtr); + +void XUartPs_SetOperMode(XUartPs *InstancePtr, u8 OperationMode); + +u8 XUartPs_GetFlowDelay(XUartPs *InstancePtr); + +void XUartPs_SetFlowDelay(XUartPs *InstancePtr, u8 FlowDelayValue); + +u8 XUartPs_GetRecvTimeout(XUartPs *InstancePtr); + +void XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout); + +s32 XUartPs_SetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +void XUartPs_GetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr); + +/* interrupt functions in xuartps_intr.c */ +u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr); + +void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask); + +void XUartPs_InterruptHandler(XUartPs *InstancePtr); + +void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr, + void *CallBackRef); + +/* self-test functions in xuartps_selftest.c */ +s32 XUartPs_SelfTest(XUartPs *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_g.c new file mode 100644 index 0000000..d70a76a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_g.c @@ -0,0 +1,67 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xuartps_g.c +* @addtogroup uartps Overview +* @{ +* +* This file contains a configuration table where each entry is a configuration +* structure for an XUartPs device in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 05/13/08 First Release
+* 2.00  hk     22/01/14 Added check for selecting uart0 instance.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xuartps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Prototypes ******************************/ + +/** + * Each XUartPs device in the system has an entry in this table. + */ +XUartPs_Config XUartPs_ConfigTable[XPAR_XUARTPS_NUM_INSTANCES] = { + { + (u16)XPAR_XUARTPS_0_DEVICE_ID, + (u32)XPAR_XUARTPS_0_BASEADDR, + (u32)XPAR_XUARTPS_0_UART_CLK_FREQ_HZ, + (s32)0 + }, +#ifdef XPAR_XUARTPS_1_DEVICE_ID + { + (u16)XPAR_XUARTPS_1_DEVICE_ID, + (u32)XPAR_XUARTPS_1_BASEADDR, + (u32)XPAR_XUARTPS_1_UART_CLK_FREQ_HZ, + (s32)0 + } +#endif +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_hw.c b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_hw.c new file mode 100644 index 0000000..ec5c088 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_hw.c @@ -0,0 +1,155 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xuartps_hw.c +* @addtogroup uartps Overview +* @{ +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/12/10 First Release
+* 1.05a hk     08/22/13 Added reset function
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xuartps_hw.h" + +/************************** Constant Definitions ****************************/ + + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* +* This function sends one byte using the device. This function operates in +* polled mode and blocks until the data has been put into the TX FIFO register. +* +* @param BaseAddress contains the base address of the device. +* @param Data contains the byte to be sent. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SendByte(u32 BaseAddress, u8 Data) +{ + /* Wait until there is space in TX FIFO */ + while (XUartPs_IsTransmitFull(BaseAddress)) { + ; + } + + /* Write the byte into the TX FIFO */ + XUartPs_WriteReg(BaseAddress, XUARTPS_FIFO_OFFSET, (u32)Data); +} + +/****************************************************************************/ +/** +* +* This function receives a byte from the device. It operates in polled mode +* and blocks until a byte has received. +* +* @param BaseAddress contains the base address of the device. +* +* @return The data byte received. +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_RecvByte(u32 BaseAddress) +{ + u32 RecievedByte; + /* Wait until there is data */ + while (!XUartPs_IsReceiveData(BaseAddress)) { + ; + } + RecievedByte = XUartPs_ReadReg(BaseAddress, XUARTPS_FIFO_OFFSET); + /* Return the byte received */ + return (u8)RecievedByte; +} + +/****************************************************************************/ +/** +* +* This function resets UART +* +* @param BaseAddress contains the base address of the device. +* +* @return None +* +* @note None. +* +*****************************************************************************/ +void XUartPs_ResetHw(u32 BaseAddress) +{ + + /* Disable interrupts */ + XUartPs_WriteReg(BaseAddress, XUARTPS_IDR_OFFSET, XUARTPS_IXR_MASK); + + /* Disable receive and transmit */ + XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, + ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS)); + + /* + * Software reset of receive and transmit + * This clears the FIFO. + */ + XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, + ((u32)XUARTPS_CR_TXRST | (u32)XUARTPS_CR_RXRST)); + + /* Clear status flags - SW reset wont clear sticky flags. */ + XUartPs_WriteReg(BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_MASK); + + /* + * Mode register reset value : All zeroes + * Normal mode, even parity, 1 stop bit + */ + XUartPs_WriteReg(BaseAddress, XUARTPS_MR_OFFSET, + XUARTPS_MR_CHMODE_NORM); + + /* Rx and TX trigger register reset values */ + XUartPs_WriteReg(BaseAddress, XUARTPS_RXWM_OFFSET, + XUARTPS_RXWM_RESET_VAL); + XUartPs_WriteReg(BaseAddress, XUARTPS_TXWM_OFFSET, + XUARTPS_TXWM_RESET_VAL); + + /* Rx timeout disabled by default */ + XUartPs_WriteReg(BaseAddress, XUARTPS_RXTOUT_OFFSET, + XUARTPS_RXTOUT_DISABLE); + + /* Baud rate generator and dividor reset values */ + XUartPs_WriteReg(BaseAddress, XUARTPS_BAUDGEN_OFFSET, + XUARTPS_BAUDGEN_RESET_VAL); + XUartPs_WriteReg(BaseAddress, XUARTPS_BAUDDIV_OFFSET, + XUARTPS_BAUDDIV_RESET_VAL); + + /* + * Control register reset value - + * RX and TX are disable by default + */ + XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, + ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_DIS | + (u32)XUARTPS_CR_STOPBRK)); + +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_hw.h new file mode 100644 index 0000000..59d4ccf --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_hw.h @@ -0,0 +1,426 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xuartps_hw.h +* @addtogroup uartps Overview +* @{ +* +* This header file contains the hardware interface of an XUartPs device. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	drg/jz 01/12/10 First Release
+* 1.03a sg     09/04/12 Added defines for XUARTPS_IXR_TOVR,  XUARTPS_IXR_TNFUL
+*			and XUARTPS_IXR_TTRIG.
+*			Modified the names of these defines
+*			XUARTPS_MEDEMSR_DCDX to XUARTPS_MODEMSR_DDCD
+*			XUARTPS_MEDEMSR_RIX to XUARTPS_MODEMSR_TERI
+*			XUARTPS_MEDEMSR_DSRX to XUARTPS_MODEMSR_DDSR
+*			XUARTPS_MEDEMSR_CTSX to XUARTPS_MODEMSR_DCTS
+* 1.05a hk     08/22/13 Added prototype for uart reset and related
+*			constant definitions.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.6   ms     02/16/18 Updates flow control mode offset value in
+*			modem control register.
+*
+* 
+* +******************************************************************************/ +#ifndef XUARTPS_HW_H /* prevent circular inclusions */ +#define XUARTPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the UART. + * @{ + */ +#define XUARTPS_CR_OFFSET 0x0000U /**< Control Register [8:0] */ +#define XUARTPS_MR_OFFSET 0x0004U /**< Mode Register [9:0] */ +#define XUARTPS_IER_OFFSET 0x0008U /**< Interrupt Enable [12:0] */ +#define XUARTPS_IDR_OFFSET 0x000CU /**< Interrupt Disable [12:0] */ +#define XUARTPS_IMR_OFFSET 0x0010U /**< Interrupt Mask [12:0] */ +#define XUARTPS_ISR_OFFSET 0x0014U /**< Interrupt Status [12:0]*/ +#define XUARTPS_BAUDGEN_OFFSET 0x0018U /**< Baud Rate Generator [15:0] */ +#define XUARTPS_RXTOUT_OFFSET 0x001CU /**< RX Timeout [7:0] */ +#define XUARTPS_RXWM_OFFSET 0x0020U /**< RX FIFO Trigger Level [5:0] */ +#define XUARTPS_MODEMCR_OFFSET 0x0024U /**< Modem Control [5:0] */ +#define XUARTPS_MODEMSR_OFFSET 0x0028U /**< Modem Status [8:0] */ +#define XUARTPS_SR_OFFSET 0x002CU /**< Channel Status [14:0] */ +#define XUARTPS_FIFO_OFFSET 0x0030U /**< FIFO [7:0] */ +#define XUARTPS_BAUDDIV_OFFSET 0x0034U /**< Baud Rate Divider [7:0] */ +#define XUARTPS_FLOWDEL_OFFSET 0x0038U /**< Flow Delay [5:0] */ +#define XUARTPS_TXWM_OFFSET 0x0044U /**< TX FIFO Trigger Level [5:0] */ +#define XUARTPS_RXBS_OFFSET 0x0048U /**< RX FIFO Byte Status [11:0] */ +/* @} */ + +/** @name Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + */ + +#define XUARTPS_CR_STOPBRK 0x00000100U /**< Stop transmission of break */ +#define XUARTPS_CR_STARTBRK 0x00000080U /**< Set break */ +#define XUARTPS_CR_TORST 0x00000040U /**< RX timeout counter restart */ +#define XUARTPS_CR_TX_DIS 0x00000020U /**< TX disabled. */ +#define XUARTPS_CR_TX_EN 0x00000010U /**< TX enabled */ +#define XUARTPS_CR_RX_DIS 0x00000008U /**< RX disabled. */ +#define XUARTPS_CR_RX_EN 0x00000004U /**< RX enabled */ +#define XUARTPS_CR_EN_DIS_MASK 0x0000003CU /**< Enable/disable Mask */ +#define XUARTPS_CR_TXRST 0x00000002U /**< TX logic reset */ +#define XUARTPS_CR_RXRST 0x00000001U /**< RX logic reset */ +/* @}*/ + + +/** @name Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * @{ + */ +#define XUARTPS_MR_CCLK 0x00000400U /**< Input clock selection */ +#define XUARTPS_MR_CHMODE_R_LOOP 0x00000300U /**< Remote loopback mode */ +#define XUARTPS_MR_CHMODE_L_LOOP 0x00000200U /**< Local loopback mode */ +#define XUARTPS_MR_CHMODE_ECHO 0x00000100U /**< Auto echo mode */ +#define XUARTPS_MR_CHMODE_NORM 0x00000000U /**< Normal mode */ +#define XUARTPS_MR_CHMODE_SHIFT 8U /**< Mode shift */ +#define XUARTPS_MR_CHMODE_MASK 0x00000300U /**< Mode mask */ +#define XUARTPS_MR_STOPMODE_2_BIT 0x00000080U /**< 2 stop bits */ +#define XUARTPS_MR_STOPMODE_1_5_BIT 0x00000040U /**< 1.5 stop bits */ +#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000U /**< 1 stop bit */ +#define XUARTPS_MR_STOPMODE_SHIFT 6U /**< Stop bits shift */ +#define XUARTPS_MR_STOPMODE_MASK 0x000000A0U /**< Stop bits mask */ +#define XUARTPS_MR_PARITY_NONE 0x00000020U /**< No parity mode */ +#define XUARTPS_MR_PARITY_MARK 0x00000018U /**< Mark parity mode */ +#define XUARTPS_MR_PARITY_SPACE 0x00000010U /**< Space parity mode */ +#define XUARTPS_MR_PARITY_ODD 0x00000008U /**< Odd parity mode */ +#define XUARTPS_MR_PARITY_EVEN 0x00000000U /**< Even parity mode */ +#define XUARTPS_MR_PARITY_SHIFT 3U /**< Parity setting shift */ +#define XUARTPS_MR_PARITY_MASK 0x00000038U /**< Parity mask */ +#define XUARTPS_MR_CHARLEN_6_BIT 0x00000006U /**< 6 bits data */ +#define XUARTPS_MR_CHARLEN_7_BIT 0x00000004U /**< 7 bits data */ +#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000U /**< 8 bits data */ +#define XUARTPS_MR_CHARLEN_SHIFT 1U /**< Data Length shift */ +#define XUARTPS_MR_CHARLEN_MASK 0x00000006U /**< Data length mask */ +#define XUARTPS_MR_CLKSEL 0x00000001U /**< Input clock selection */ +/* @} */ + + +/** @name Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + * @{ + */ +#define XUARTPS_IXR_RBRK 0x00002000U /**< Rx FIFO break detect interrupt */ +#define XUARTPS_IXR_TOVR 0x00001000U /**< Tx FIFO Overflow interrupt */ +#define XUARTPS_IXR_TNFUL 0x00000800U /**< Tx FIFO Nearly Full interrupt */ +#define XUARTPS_IXR_TTRIG 0x00000400U /**< Tx Trig interrupt */ +#define XUARTPS_IXR_DMS 0x00000200U /**< Modem status change interrupt */ +#define XUARTPS_IXR_TOUT 0x00000100U /**< Timeout error interrupt */ +#define XUARTPS_IXR_PARITY 0x00000080U /**< Parity error interrupt */ +#define XUARTPS_IXR_FRAMING 0x00000040U /**< Framing error interrupt */ +#define XUARTPS_IXR_OVER 0x00000020U /**< Overrun error interrupt */ +#define XUARTPS_IXR_TXFULL 0x00000010U /**< TX FIFO full interrupt. */ +#define XUARTPS_IXR_TXEMPTY 0x00000008U /**< TX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXFULL 0x00000004U /**< RX FIFO full interrupt. */ +#define XUARTPS_IXR_RXEMPTY 0x00000002U /**< RX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXOVR 0x00000001U /**< RX FIFO trigger interrupt. */ +#define XUARTPS_IXR_MASK 0x00003FFFU /**< Valid bit mask */ +/* @} */ + + +/** @name Baud Rate Generator Register + * + * The baud rate generator control register (BRGR) is a 16 bit register that + * controls the receiver bit sample clock and baud rate. + * Valid values are 1 - 65535. + * + * Bit Sample Rate = CCLK / BRGR, where the CCLK is selected by the MR_CCLK bit + * in the MR register. + * @{ + */ +#define XUARTPS_BAUDGEN_DISABLE 0x00000000U /**< Disable clock */ +#define XUARTPS_BAUDGEN_MASK 0x0000FFFFU /**< Valid bits mask */ +#define XUARTPS_BAUDGEN_RESET_VAL 0x0000028BU /**< Reset value */ + +/** @name Baud Divisor Rate register + * + * The baud rate divider register (BDIV) controls how much the bit sample + * rate is divided by. It sets the baud rate. + * Valid values are 0x04 to 0xFF. Writing a value less than 4 will be ignored. + * + * Baud rate = CCLK / ((BAUDDIV + 1) x BRGR), where the CCLK is selected by + * the MR_CCLK bit in the MR register. + * @{ + */ +#define XUARTPS_BAUDDIV_MASK 0x000000FFU /**< 8 bit baud divider mask */ +#define XUARTPS_BAUDDIV_RESET_VAL 0x0000000FU /**< Reset value */ +/* @} */ + + +/** @name Receiver Timeout Register + * + * Use the receiver timeout register (RTR) to detect an idle condition on + * the receiver data line. + * + * @{ + */ +#define XUARTPS_RXTOUT_DISABLE 0x00000000U /**< Disable time out */ +#define XUARTPS_RXTOUT_MASK 0x000000FFU /**< Valid bits mask */ + +/** @name Receiver FIFO Trigger Level Register + * + * Use the Receiver FIFO Trigger Level Register (RTRIG) to set the value at + * which the RX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_RXWM_DISABLE 0x00000000U /**< Disable RX trigger interrupt */ +#define XUARTPS_RXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_RXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Transmit FIFO Trigger Level Register + * + * Use the Transmit FIFO Trigger Level Register (TTRIG) to set the value at + * which the TX FIFO triggers an interrupt event. + * @{ + */ + +#define XUARTPS_TXWM_MASK 0x0000003FU /**< Valid bits mask */ +#define XUARTPS_TXWM_RESET_VAL 0x00000020U /**< Reset value */ +/* @} */ + +/** @name Modem Control Register + * + * This register (MODEMCR) controls the interface with the modem or data set, + * or a peripheral device emulating a modem. + * + * @{ + */ +#define XUARTPS_MODEMCR_FCM 0x00000020U /**< Flow control mode */ +#define XUARTPS_MODEMCR_RTS 0x00000002U /**< Request to send */ +#define XUARTPS_MODEMCR_DTR 0x00000001U /**< Data terminal ready */ +/* @} */ + +/** @name Modem Status Register + * + * This register (MODEMSR) indicates the current state of the control lines + * from a modem, or another peripheral device, to the CPU. In addition, four + * bits of the modem status register provide change information. These bits + * are set to a logic 1 whenever a control input from the modem changes state. + * + * Note: Whenever the DCTS, DDSR, TERI, or DDCD bit is set to logic 1, a modem + * status interrupt is generated and this is reflected in the modem status + * register. + * + * @{ + */ +#define XUARTPS_MODEMSR_FCMS 0x00000100U /**< Flow control mode (FCMS) */ +#define XUARTPS_MODEMSR_DCD 0x00000080U /**< Complement of DCD input */ +#define XUARTPS_MODEMSR_RI 0x00000040U /**< Complement of RI input */ +#define XUARTPS_MODEMSR_DSR 0x00000020U /**< Complement of DSR input */ +#define XUARTPS_MODEMSR_CTS 0x00000010U /**< Complement of CTS input */ +#define XUARTPS_MODEMSR_DDCD 0x00000008U /**< Delta DCD indicator */ +#define XUARTPS_MODEMSR_TERI 0x00000004U /**< Trailing Edge Ring Indicator */ +#define XUARTPS_MODEMSR_DDSR 0x00000002U /**< Change of DSR */ +#define XUARTPS_MODEMSR_DCTS 0x00000001U /**< Change of CTS */ +/* @} */ + +/** @name Channel Status Register + * + * The channel status register (CSR) is provided to enable the control logic + * to monitor the status of bits in the channel interrupt status register, + * even if these are masked out by the interrupt mask register. + * + * @{ + */ +#define XUARTPS_SR_TNFUL 0x00004000U /**< TX FIFO Nearly Full Status */ +#define XUARTPS_SR_TTRIG 0x00002000U /**< TX FIFO Trigger Status */ +#define XUARTPS_SR_FLOWDEL 0x00001000U /**< RX FIFO fill over flow delay */ +#define XUARTPS_SR_TACTIVE 0x00000800U /**< TX active */ +#define XUARTPS_SR_RACTIVE 0x00000400U /**< RX active */ +#define XUARTPS_SR_TXFULL 0x00000010U /**< TX FIFO full */ +#define XUARTPS_SR_TXEMPTY 0x00000008U /**< TX FIFO empty */ +#define XUARTPS_SR_RXFULL 0x00000004U /**< RX FIFO full */ +#define XUARTPS_SR_RXEMPTY 0x00000002U /**< RX FIFO empty */ +#define XUARTPS_SR_RXOVR 0x00000001U /**< RX FIFO fill over trigger */ +/* @} */ + +/** @name Flow Delay Register + * + * Operation of the flow delay register (FLOWDEL) is very similar to the + * receive FIFO trigger register. An internal trigger signal activates when the + * FIFO is filled to the level set by this register. This trigger will not + * cause an interrupt, although it can be read through the channel status + * register. In hardware flow control mode, RTS is deactivated when the trigger + * becomes active. RTS only resets when the FIFO level is four less than the + * level of the flow delay trigger and the flow delay trigger is not activated. + * A value less than 4 disables the flow delay. + * @{ + */ +#define XUARTPS_FLOWDEL_MASK XUARTPS_RXWM_MASK /**< Valid bit mask */ +/* @} */ + +/** @name Receiver FIFO Byte Status Register + * + * The Receiver FIFO Status register is used to have a continuous + * monitoring of the raw unmasked byte status information. The register + * contains frame, parity and break status information for the top + * four bytes in the RX FIFO. + * + * Receiver FIFO Byte Status Register Bit Definition + * @{ + */ +#define XUARTPS_RXBS_BYTE3_BRKE 0x00000800U /**< Byte3 Break Error */ +#define XUARTPS_RXBS_BYTE3_FRME 0x00000400U /**< Byte3 Frame Error */ +#define XUARTPS_RXBS_BYTE3_PARE 0x00000200U /**< Byte3 Parity Error */ +#define XUARTPS_RXBS_BYTE2_BRKE 0x00000100U /**< Byte2 Break Error */ +#define XUARTPS_RXBS_BYTE2_FRME 0x00000080U /**< Byte2 Frame Error */ +#define XUARTPS_RXBS_BYTE2_PARE 0x00000040U /**< Byte2 Parity Error */ +#define XUARTPS_RXBS_BYTE1_BRKE 0x00000020U /**< Byte1 Break Error */ +#define XUARTPS_RXBS_BYTE1_FRME 0x00000010U /**< Byte1 Frame Error */ +#define XUARTPS_RXBS_BYTE1_PARE 0x00000008U /**< Byte1 Parity Error */ +#define XUARTPS_RXBS_BYTE0_BRKE 0x00000004U /**< Byte0 Break Error */ +#define XUARTPS_RXBS_BYTE0_FRME 0x00000002U /**< Byte0 Frame Error */ +#define XUARTPS_RXBS_BYTE0_PARE 0x00000001U /**< Byte0 Parity Error */ +#define XUARTPS_RXBS_MASK 0x00000007U /**< 3 bit RX byte status mask */ +/* @} */ + + +/* + * Defines for backwards compatibility, will be removed + * in the next version of the driver + */ +#define XUARTPS_MEDEMSR_DCDX XUARTPS_MODEMSR_DDCD +#define XUARTPS_MEDEMSR_RIX XUARTPS_MODEMSR_TERI +#define XUARTPS_MEDEMSR_DSRX XUARTPS_MODEMSR_DDSR +#define XUARTPS_MEDEMSR_CTSX XUARTPS_MODEMSR_DCTS + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* Read a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XUartPs_ReadReg(u32 BaseAddress, int RegOffset) +* +******************************************************************************/ +#define XUartPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (u32)(RegOffset)) + +/***************************************************************************/ +/** +* Write a UART register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the base address of the +* device. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XUartPs_WriteReg(u32 BaseAddress, int RegOffset, +* u16 RegisterValue) +* +******************************************************************************/ +#define XUartPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + Xil_Out32((BaseAddress) + (u32)(RegOffset), (u32)(RegisterValue)) + +/****************************************************************************/ +/** +* Determine if there is receive data in the receiver and/or FIFO. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if there is receive data, FALSE otherwise. +* +* @note C-Style signature: +* u32 XUartPs_IsReceiveData(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsReceiveData(BaseAddress) \ + !((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_RXEMPTY) == (u32)XUARTPS_SR_RXEMPTY) + +/****************************************************************************/ +/** +* Determine if a byte of data can be sent with the transmitter. +* +* @param BaseAddress contains the base address of the device. +* +* @return TRUE if the TX FIFO is full, FALSE if a byte can be put in the +* FIFO. +* +* @note C-Style signature: +* u32 XUartPs_IsTransmitFull(u32 BaseAddress) +* +******************************************************************************/ +#define XUartPs_IsTransmitFull(BaseAddress) \ + ((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \ + (u32)XUARTPS_SR_TXFULL) == (u32)XUARTPS_SR_TXFULL) + +/************************** Function Prototypes ******************************/ + +void XUartPs_SendByte(u32 BaseAddress, u8 Data); + +u8 XUartPs_RecvByte(u32 BaseAddress); + +void XUartPs_ResetHw(u32 BaseAddress); + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_intr.c b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_intr.c new file mode 100644 index 0000000..1f37143 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_intr.c @@ -0,0 +1,426 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xuartps_intr.c +* @addtogroup uartps Overview +* @{ +* +* This file contains the functions for interrupt handling +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/13/10 First Release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1	kvn    04/10/15 Modified code for latest RTL changes.
+* 3.7   aru    08/17/18 Resolved MISRA-C mandatory violations.(CR#1007755)
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xuartps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Function Prototypes *****************************/ + +static void ReceiveDataHandler(XUartPs *InstancePtr); +static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus); +static void ReceiveErrorHandler(XUartPs *InstancePtr, u32 IsrStatus); +static void ReceiveTimeoutHandler(XUartPs *InstancePtr); +static void ModemHandler(XUartPs *InstancePtr); + + +/* Internal function prototypes implemented in xuartps.c */ +extern u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr); +extern u32 XUartPs_SendBuffer(XUartPs *InstancePtr); + +/************************** Variable Definitions ****************************/ + +typedef void (*Handler)(XUartPs *InstancePtr); + +/****************************************************************************/ +/** +* +* This function gets the interrupt mask +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* The current interrupt mask. The mask indicates which interrupts +* are enabled. +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr) +{ + /* Assert validates the input argument */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Read the Interrupt Mask register */ + return (XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET)); +} + +/****************************************************************************/ +/** +* +* This function sets the interrupt mask. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param Mask contains the interrupts to be enabled or disabled. +* A '1' enables an interrupt, and a '0' disables. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask) +{ + u32 TempMask = Mask; + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + + TempMask &= (u32)XUARTPS_IXR_MASK; + + /* Write the mask to the IER Register */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IER_OFFSET, TempMask); + + /* Write the inverse of the Mask to the IDR register */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IDR_OFFSET, (~TempMask)); + +} + +/****************************************************************************/ +/** +* +* This function sets the handler that will be called when an event (interrupt) +* occurs that needs application's attention. +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param FuncPtr is the pointer to the callback function. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* +* @return None. +* +* @note +* +* There is no assert on the CallBackRef since the driver doesn't know what it +* is (nor should it) +* +*****************************************************************************/ +void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr, + void *CallBackRef) +{ + /* + * Asserts validate the input arguments + * CallBackRef not checked, no way to know what is valid + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->Handler = (XUartPs_Handler)FuncPtr; + InstancePtr->CallBackRef = CallBackRef; +} + +/****************************************************************************/ +/** +* +* This function is the interrupt handler for the driver. +* It must be connected to an interrupt system by the application such that it +* can be called when an interrupt occurs. +* +* @param InstancePtr contains a pointer to the driver instance +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XUartPs_InterruptHandler(XUartPs *InstancePtr) +{ + u32 IsrStatus; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the interrupt ID register to determine which + * interrupt is active + */ + IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + + IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_ISR_OFFSET); + + /* Dispatch an appropriate handler. */ + if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY | + (u32)XUARTPS_IXR_RXFULL)) != (u32)0) { + /* Received data interrupt */ + ReceiveDataHandler(InstancePtr); + } + + if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL)) + != (u32)0) { + /* Transmit data interrupt */ + SendDataHandler(InstancePtr, IsrStatus); + } + + /* XUARTPS_IXR_RBRK is applicable only for Zynq Ultrascale+ MP */ + if ((IsrStatus & ((u32)XUARTPS_IXR_OVER | (u32)XUARTPS_IXR_FRAMING | + (u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK)) != (u32)0) { + /* Received Error Status interrupt */ + ReceiveErrorHandler(InstancePtr, IsrStatus); + } + + if((IsrStatus & ((u32)XUARTPS_IXR_TOUT)) != (u32)0) { + /* Received Timeout interrupt */ + ReceiveTimeoutHandler(InstancePtr); + } + + if((IsrStatus & ((u32)XUARTPS_IXR_DMS)) != (u32)0) { + /* Modem status interrupt */ + ModemHandler(InstancePtr); + } + + /* Clear the interrupt status. */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET, + IsrStatus); + +} + +/****************************************************************************/ +/* +* +* This function handles interrupts for receive errors which include +* overrun errors, framing errors, parity errors, and the break interrupt. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ReceiveErrorHandler(XUartPs *InstancePtr, u32 IsrStatus) +{ + u32 EventData; + u32 Event; + + InstancePtr->is_rxbs_error = 0; + + if ((InstancePtr->Platform == XPLAT_ZYNQ_ULTRA_MP) && + (IsrStatus & ((u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK + | (u32)XUARTPS_IXR_FRAMING))) { + InstancePtr->is_rxbs_error = 1; + } + /* + * If there are bytes still to be received in the specified buffer + * go ahead and receive them. Removing bytes from the RX FIFO will + * clear the interrupt. + */ + + (void)XUartPs_ReceiveBuffer(InstancePtr); + + if (!(InstancePtr->is_rxbs_error)) { + Event = XUARTPS_EVENT_RECV_ERROR; + EventData = InstancePtr->ReceiveBuffer.RequestedBytes - + InstancePtr->ReceiveBuffer.RemainingBytes; + + /* + * Call the application handler to indicate that there is a receive + * error or a break interrupt, if the application cares about the + * error it call a function to get the last errors. + */ + InstancePtr->Handler(InstancePtr->CallBackRef, + Event, + EventData); + } +} + +/****************************************************************************/ +/** +* +* This function handles the receive timeout interrupt. This interrupt occurs +* whenever a number of bytes have been present in the RX FIFO and the receive +* data line has been idle for at lease 4 or more character times, (the timeout +* is set using XUartPs_SetrecvTimeout() function). +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ReceiveTimeoutHandler(XUartPs *InstancePtr) +{ + u32 Event; + + /* + * If there are bytes still to be received in the specified buffer + * go ahead and receive them. Removing bytes from the RX FIFO will + * clear the interrupt. + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) { + (void)XUartPs_ReceiveBuffer(InstancePtr); + } + + /* + * If there are no more bytes to receive then indicate that this is + * not a receive timeout but the end of the buffer reached, a timeout + * normally occurs if # of bytes is not divisible by FIFO threshold, + * don't rely on previous test of remaining bytes since receive + * function updates it + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) { + Event = XUARTPS_EVENT_RECV_TOUT; + } else { + Event = XUARTPS_EVENT_RECV_DATA; + } + + /* + * Call the application handler to indicate that there is a receive + * timeout or data event + */ + InstancePtr->Handler(InstancePtr->CallBackRef, Event, + InstancePtr->ReceiveBuffer.RequestedBytes - + InstancePtr->ReceiveBuffer.RemainingBytes); + +} +/****************************************************************************/ +/** +* +* This function handles the interrupt when data is in RX FIFO. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ReceiveDataHandler(XUartPs *InstancePtr) +{ + /* + * If there are bytes still to be received in the specified buffer + * go ahead and receive them. Removing bytes from the RX FIFO will + * clear the interrupt. + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) { + (void)XUartPs_ReceiveBuffer(InstancePtr); + } + + /* If the last byte of a message was received then call the application + * handler, this code should not use an else from the previous check of + * the number of bytes to receive because the call to receive the buffer + * updates the bytes ramained + */ + if (InstancePtr->ReceiveBuffer.RemainingBytes == (u32)0) { + InstancePtr->Handler(InstancePtr->CallBackRef, + XUARTPS_EVENT_RECV_DATA, + (InstancePtr->ReceiveBuffer.RequestedBytes - + InstancePtr->ReceiveBuffer.RemainingBytes)); + } + +} + +/****************************************************************************/ +/** +* +* This function handles the interrupt when data has been sent, the transmit +* FIFO is empty (transmitter holding register). +* +* @param InstancePtr is a pointer to the XUartPs instance +* @param IsrStatus is the register value for channel status register +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus) +{ + + /* + * If there are not bytes to be sent from the specified buffer then disable + * the transmit interrupt so it will stop interrupting as it interrupts + * any time the FIFO is empty + */ + if (InstancePtr->SendBuffer.RemainingBytes == (u32)0) { + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_IDR_OFFSET, + ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL)); + + /* Call the application handler to indicate the sending is done */ + InstancePtr->Handler(InstancePtr->CallBackRef, + XUARTPS_EVENT_SENT_DATA, + InstancePtr->SendBuffer.RequestedBytes - + InstancePtr->SendBuffer.RemainingBytes); + } + + /* If TX FIFO is empty, send more. */ + else if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY)) != (u32)0) { + (void)XUartPs_SendBuffer(InstancePtr); + } + else { + /* Else with dummy entry for MISRA-C Compliance.*/ + ; + } +} + +/****************************************************************************/ +/** +* +* This function handles modem interrupts. It does not do any processing +* except to call the application handler to indicate a modem event. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +static void ModemHandler(XUartPs *InstancePtr) +{ + u32 MsrRegister; + + /* + * Read the modem status register so that the interrupt is acknowledged + * and it can be passed to the callback handler with the event + */ + MsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MODEMSR_OFFSET); + + /* + * Call the application handler to indicate the modem status changed, + * passing the modem status and the event data in the call + */ + InstancePtr->Handler(InstancePtr->CallBackRef, + XUARTPS_EVENT_MODEM, + MsrRegister); + +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_options.c b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_options.c new file mode 100644 index 0000000..9cf2da6 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_options.c @@ -0,0 +1,742 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xuartps_options.c +* @addtogroup uartps Overview +* @{ +* +* The implementation of the options functions for the XUartPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/13/10 First Release
+* 1.00  sdm    09/27/11 Fixed a bug in XUartPs_SetFlowDelay where the input
+*			value was not being written to the register.
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.2   rk     07/20/16 Modified the logic for transmission break bit set
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xuartps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +/* + * The following data type is a map from an option to the offset in the + * register to which it belongs as well as its bit mask in that register. + */ +typedef struct { + u16 Option; + u16 RegisterOffset; + u32 Mask; +} Mapping; + +/* + * Create the table which contains options which are to be processed to get/set + * the options. These options are table driven to allow easy maintenance and + * expansion of the options. + */ + +static Mapping OptionsTable[] = { + {XUARTPS_OPTION_SET_BREAK, XUARTPS_CR_OFFSET, XUARTPS_CR_STARTBRK}, + {XUARTPS_OPTION_STOP_BREAK, XUARTPS_CR_OFFSET, XUARTPS_CR_STOPBRK}, + {XUARTPS_OPTION_RESET_TMOUT, XUARTPS_CR_OFFSET, XUARTPS_CR_TORST}, + {XUARTPS_OPTION_RESET_TX, XUARTPS_CR_OFFSET, XUARTPS_CR_TXRST}, + {XUARTPS_OPTION_RESET_RX, XUARTPS_CR_OFFSET, XUARTPS_CR_RXRST}, + {XUARTPS_OPTION_ASSERT_RTS, XUARTPS_MODEMCR_OFFSET, + XUARTPS_MODEMCR_RTS}, + {XUARTPS_OPTION_ASSERT_DTR, XUARTPS_MODEMCR_OFFSET, + XUARTPS_MODEMCR_DTR}, + {XUARTPS_OPTION_SET_FCM, XUARTPS_MODEMCR_OFFSET, XUARTPS_MODEMCR_FCM} +}; + +/* Create a constant for the number of entries in the table */ + +#define XUARTPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(Mapping)) + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Gets the options for the specified driver instance. The options are +* implemented as bit masks such that multiple options may be enabled or +* disabled simultaneously. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The current options for the UART. The options are bit masks that are +* contained in the file xuartps.h and named XUARTPS_OPTION_*. +* +* @note None. +* +*****************************************************************************/ +u16 XUartPs_GetOptions(XUartPs *InstancePtr) +{ + u16 Options = 0U; + u32 Register; + u32 Index; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Loop through the options table to map the physical options in the + * registers of the UART to the logical options to be returned + */ + for (Index = 0U; Index < XUARTPS_NUM_OPTIONS; Index++) { + Register = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + OptionsTable[Index]. + RegisterOffset); + + /* + * If the bit in the register which correlates to the option + * is set, then set the corresponding bit in the options, + * ignoring any bits which are zero since the options variable + * is initialized to zero + */ + if ((Register & OptionsTable[Index].Mask) != (u32)0) { + Options |= OptionsTable[Index].Option; + } + } + + return Options; +} + +/****************************************************************************/ +/** +* +* Sets the options for the specified driver instance. The options are +* implemented as bit masks such that multiple options may be enabled or +* disabled simultaneously. +* +* The GetOptions function may be called to retrieve the currently enabled +* options. The result is ORed in the desired new settings to be enabled and +* ANDed with the inverse to clear the settings to be disabled. The resulting +* value is then used as the options for the SetOption function call. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param Options contains the options to be set which are bit masks +* contained in the file xuartps.h and named XUARTPS_OPTION_*. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetOptions(XUartPs *InstancePtr, u16 Options) +{ + u32 Index; + u32 Register; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Loop through the options table to map the logical options to the + * physical options in the registers of the UART. + */ + for (Index = 0U; Index < XUARTPS_NUM_OPTIONS; Index++) { + + /* + * Read the register which contains option so that the register + * can be changed without destoying any other bits of the + * register. + */ + Register = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + OptionsTable[Index]. + RegisterOffset); + + /* + * If the option is set in the input, then set the corresponding + * bit in the specified register, otherwise clear the bit in + * the register. + */ + if ((Options & OptionsTable[Index].Option) != (u16)0) { + if(OptionsTable[Index].Option == XUARTPS_OPTION_SET_BREAK) + Register &= ~XUARTPS_CR_STOPBRK; + Register |= OptionsTable[Index].Mask; + } + else { + Register &= ~OptionsTable[Index].Mask; + } + + /* Write the new value to the register to set the option */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + OptionsTable[Index].RegisterOffset, + Register); + } + +} + +/****************************************************************************/ +/** +* +* This function gets the receive FIFO trigger level. The receive trigger +* level indicates the number of bytes in the receive FIFO that cause a receive +* data event (interrupt) to be generated. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The current receive FIFO trigger level. This is a value +* from 0-31. +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetFifoThreshold(XUartPs *InstancePtr) +{ + u8 RtrigRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the value of the FIFO control register so that the threshold + * can be retrieved, this read takes special register processing + */ + RtrigRegister = (u8) XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXWM_OFFSET); + + /* Return only the trigger level from the register value */ + + RtrigRegister &= (u8)XUARTPS_RXWM_MASK; + return RtrigRegister; +} + +/****************************************************************************/ +/** +* +* This functions sets the receive FIFO trigger level. The receive trigger +* level specifies the number of bytes in the receive FIFO that cause a receive +* data event (interrupt) to be generated. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param TriggerLevel contains the trigger level to set. +* +* @return None +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetFifoThreshold(XUartPs *InstancePtr, u8 TriggerLevel) +{ + u32 RtrigRegister; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(TriggerLevel <= (u8)XUARTPS_RXWM_MASK); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + RtrigRegister = ((u32)TriggerLevel) & (u32)XUARTPS_RXWM_MASK; + + /* + * Write the new value for the FIFO control register to it such that the + * threshold is changed + */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXWM_OFFSET, RtrigRegister); + +} + +/****************************************************************************/ +/** +* +* This function gets the modem status from the specified UART. The modem +* status indicates any changes of the modem signals. This function allows +* the modem status to be read in a polled mode. The modem status is updated +* whenever it is read such that reading it twice may not yield the same +* results. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The modem status which are bit masks that are contained in the file +* xuartps.h and named XUARTPS_MODEM_*. +* +* @note +* +* The bit masks used for the modem status are the exact bits of the modem +* status register with no abstraction. +* +*****************************************************************************/ +u16 XUartPs_GetModemStatus(XUartPs *InstancePtr) +{ + u32 ModemStatusRegister; + u16 TmpRegister; + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the modem status register to return + */ + ModemStatusRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MODEMSR_OFFSET); + TmpRegister = (u16)ModemStatusRegister; + return TmpRegister; +} + +/****************************************************************************/ +/** +* +* This function determines if the specified UART is sending data. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* - TRUE if the UART is sending data +* - FALSE if UART is not sending data +* +* @note None. +* +*****************************************************************************/ +u32 XUartPs_IsSending(XUartPs *InstancePtr) +{ + u32 ChanStatRegister; + u32 ChanTmpSRegister; + u32 ActiveResult; + u32 EmptyResult; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the channel status register to determine if the transmitter is + * active + */ + ChanStatRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_SR_OFFSET); + + /* + * If the transmitter is active, or the TX FIFO is not empty, then indicate + * that the UART is still sending some data + */ + ActiveResult = ChanStatRegister & ((u32)XUARTPS_SR_TACTIVE); + EmptyResult = ChanStatRegister & ((u32)XUARTPS_SR_TXEMPTY); + ChanTmpSRegister = (((u32)XUARTPS_SR_TACTIVE) == ActiveResult) || + (((u32)XUARTPS_SR_TXEMPTY) != EmptyResult); +#if defined (XCLOCKING) + if (!ChanTmpSRegister) + Xil_ClockDisable(InstancePtr->Config.RefClk); +#endif + return ChanTmpSRegister; +} + +/****************************************************************************/ +/** +* +* This function gets the operational mode of the UART. The UART can operate +* in one of four modes: Normal, Local Loopback, Remote Loopback, or automatic +* echo. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The operational mode is specified by constants defined in xuartps.h. The +* constants are named XUARTPS_OPER_MODE_* +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetOperMode(XUartPs *InstancePtr) +{ + u32 ModeRegister; + u8 OperMode; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the Mode register. */ + ModeRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + ModeRegister &= (u32)XUARTPS_MR_CHMODE_MASK; + /* Return the constant */ + switch (ModeRegister) { + case XUARTPS_MR_CHMODE_NORM: + OperMode = XUARTPS_OPER_MODE_NORMAL; + break; + case XUARTPS_MR_CHMODE_ECHO: + OperMode = XUARTPS_OPER_MODE_AUTO_ECHO; + break; + case XUARTPS_MR_CHMODE_L_LOOP: + OperMode = XUARTPS_OPER_MODE_LOCAL_LOOP; + break; + case XUARTPS_MR_CHMODE_R_LOOP: + OperMode = XUARTPS_OPER_MODE_REMOTE_LOOP; + break; + default: + OperMode = (u8) ((ModeRegister & (u32)XUARTPS_MR_CHMODE_MASK) >> + XUARTPS_MR_CHMODE_SHIFT); + break; + } + + return OperMode; +} + +/****************************************************************************/ +/** +* +* This function sets the operational mode of the UART. The UART can operate +* in one of four modes: Normal, Local Loopback, Remote Loopback, or automatic +* echo. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param OperationMode is the mode of the UART. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetOperMode(XUartPs *InstancePtr, u8 OperationMode) +{ + u32 ModeRegister; + + /* Assert validates the input arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(OperationMode <= XUARTPS_OPER_MODE_REMOTE_LOOP); + + /* Read the Mode register. */ + ModeRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* Set the correct value by masking the bits, then ORing the const. */ + ModeRegister &= (u32)(~XUARTPS_MR_CHMODE_MASK); + + switch (OperationMode) { + case XUARTPS_OPER_MODE_NORMAL: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_NORM; + break; + case XUARTPS_OPER_MODE_AUTO_ECHO: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_ECHO; + break; + case XUARTPS_OPER_MODE_LOCAL_LOOP: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_L_LOOP; + break; + case XUARTPS_OPER_MODE_REMOTE_LOOP: + ModeRegister |= (u32)XUARTPS_MR_CHMODE_R_LOOP; + break; + default: + /* Default case made for MISRA-C Compliance. */ + break; + } + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + +} + +/****************************************************************************/ +/** +* +* This function sets the Flow Delay. +* 0 - 3: Flow delay inactive +* 4 - 32: If Flow Control mode is enabled, UART_rtsN is deactivated when the +* receive FIFO fills to this level. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return +* +* The Flow Delay is specified by constants defined in xuartps_hw.h. The +* constants are named XUARTPS_FLOWDEL* +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetFlowDelay(XUartPs *InstancePtr) +{ + u32 FdelTmpRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the Mode register. */ + FdelTmpRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_FLOWDEL_OFFSET); + + /* Return the contents of the flow delay register */ + FdelTmpRegister = (u8)(FdelTmpRegister & (u32)XUARTPS_FLOWDEL_MASK); + return FdelTmpRegister; +} + +/****************************************************************************/ +/** +* +* This function sets the Flow Delay. +* 0 - 3: Flow delay inactive +* 4 - 63: If Flow Control mode is enabled, UART_rtsN is deactivated when the +* receive FIFO fills to this level. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param FlowDelayValue is the Setting for the flow delay. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetFlowDelay(XUartPs *InstancePtr, u8 FlowDelayValue) +{ + u32 FdelRegister; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FlowDelayValue > (u8)XUARTPS_FLOWDEL_MASK); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Set the correct value by shifting the input constant, then masking + * the bits + */ + FdelRegister = ((u32)FlowDelayValue) & (u32)XUARTPS_FLOWDEL_MASK; + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_FLOWDEL_OFFSET, FdelRegister); + +} + +/****************************************************************************/ +/** +* +* This function gets the Receive Timeout of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* +* @return The current setting for receive time out. +* +* @note None. +* +*****************************************************************************/ +u8 XUartPs_GetRecvTimeout(XUartPs *InstancePtr) +{ + u32 RtoRegister; + u8 RtoRTmpRegister; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Read the Receive Timeout register. */ + RtoRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXTOUT_OFFSET); + + /* Return the contents of the mode register shifted appropriately */ + RtoRTmpRegister = (u8)(RtoRegister & (u32)XUARTPS_RXTOUT_MASK); + return RtoRTmpRegister; +} + +/****************************************************************************/ +/** +* +* This function sets the Receive Timeout of the UART. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param RecvTimeout setting allows the UART to detect an idle connection +* on the receiver data line. +* Timeout duration = RecvTimeout x 4 x Bit Period. 0 disables the +* timeout function. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout) +{ + u32 RtoRegister; + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Set the correct value by masking the bits */ + RtoRegister = ((u32)RecvTimeout & (u32)XUARTPS_RXTOUT_MASK); + + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, + XUARTPS_RXTOUT_OFFSET, RtoRegister); + + /* Configure CR to restart the receiver timeout counter */ + RtoRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_CR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_CR_OFFSET, + (RtoRegister | XUARTPS_CR_TORST)); + +} +/****************************************************************************/ +/** +* +* Sets the data format for the device. The data format includes the +* baud rate, number of data bits, number of stop bits, and parity. It is the +* caller's responsibility to ensure that the UART is not sending or receiving +* data when this function is called. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param FormatPtr is a pointer to a format structure containing the data +* format to be set. +* +* @return +* - XST_SUCCESS if the data format was successfully set. +* - XST_UART_BAUD_ERROR indicates the baud rate could not be +* set because of the amount of error with the baud rate and +* the input clock frequency. +* - XST_INVALID_PARAM if one of the parameters was not valid. +* +* @note +* +* The data types in the format type, data bits and parity, are 32 bit fields +* to prevent a compiler warning. +* The asserts in this function will cause a warning if these fields are +* bytes. +*

+* +*****************************************************************************/ +s32 XUartPs_SetDataFormat(XUartPs *InstancePtr, + XUartPsFormat * FormatPtr) +{ + s32 Status; + u32 ModeRegister; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(FormatPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Verify the inputs specified are valid */ + if ((FormatPtr->DataBits > ((u32)XUARTPS_FORMAT_6_BITS)) || + (FormatPtr->StopBits > ((u8)XUARTPS_FORMAT_2_STOP_BIT)) || + (FormatPtr->Parity > ((u32)XUARTPS_FORMAT_NO_PARITY))) { + Status = XST_INVALID_PARAM; + } else { + + /* + * Try to set the baud rate and if it's not successful then don't + * continue altering the data format, this is done first to avoid the + * format from being altered when an error occurs + */ + Status = XUartPs_SetBaudRate(InstancePtr, FormatPtr->BaudRate); + if (Status != (s32)XST_SUCCESS) { + ; + } else { + + ModeRegister = + XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* + * Set the length of data (8,7,6) by first clearing out the bits + * that control it in the register, then set the length in the register + */ + ModeRegister &= (u32)(~XUARTPS_MR_CHARLEN_MASK); + ModeRegister |= (FormatPtr->DataBits << XUARTPS_MR_CHARLEN_SHIFT); + + /* + * Set the number of stop bits in the mode register by first clearing + * out the bits that control it in the register, then set the number + * of stop bits in the register. + */ + ModeRegister &= (u32)(~XUARTPS_MR_STOPMODE_MASK); + ModeRegister |= (((u32)FormatPtr->StopBits) << XUARTPS_MR_STOPMODE_SHIFT); + + /* + * Set the parity by first clearing out the bits that control it in the + * register, then set the bits in the register, the default is no parity + * after clearing the register bits + */ + ModeRegister &= (u32)(~XUARTPS_MR_PARITY_MASK); + ModeRegister |= (FormatPtr->Parity << XUARTPS_MR_PARITY_SHIFT); + + /* Update the mode register */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + + Status = XST_SUCCESS; + } + } + return Status; +} + +/****************************************************************************/ +/** +* +* Gets the data format for the specified UART. The data format includes the +* baud rate, number of data bits, number of stop bits, and parity. +* +* @param InstancePtr is a pointer to the XUartPs instance. +* @param FormatPtr is a pointer to a format structure that will contain +* the data format after this call completes. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XUartPs_GetDataFormat(XUartPs *InstancePtr, XUartPsFormat * FormatPtr) +{ + u32 ModeRegister; + + + /* Assert validates the input arguments */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FormatPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the baud rate from the instance, this is not retrieved from the + * hardware because it is only kept as a divisor such that it is more + * difficult to get back to the baud rate + */ + FormatPtr->BaudRate = InstancePtr->BaudRate; + + ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + + /* Get the length of data (8,7,6,5) */ + FormatPtr->DataBits = + ((ModeRegister & (u32)XUARTPS_MR_CHARLEN_MASK) >> + XUARTPS_MR_CHARLEN_SHIFT); + + /* Get the number of stop bits */ + FormatPtr->StopBits = + (u8)((ModeRegister & (u32)XUARTPS_MR_STOPMODE_MASK) >> + XUARTPS_MR_STOPMODE_SHIFT); + + /* Determine what parity is */ + FormatPtr->Parity = + (u32)((ModeRegister & (u32)XUARTPS_MR_PARITY_MASK) >> + XUARTPS_MR_PARITY_SHIFT); +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_selftest.c b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_selftest.c new file mode 100644 index 0000000..b1913d1 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_selftest.c @@ -0,0 +1,147 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xuartps_selftest.c +* @addtogroup uartps Overview +* @{ +* +* This file contains the self-test functions for the XUartPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00	drg/jz 01/13/10 First Release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.9   sd     02/06/20 Added clock support
+* 3.12	gm     11/04/22 Added timeout support using Xil_WaitForEvent
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xuartps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XUARTPS_TOTAL_BYTES (u8)32 + +/************************** Variable Definitions *****************************/ + +static u8 TestString[XUARTPS_TOTAL_BYTES]="abcdefghABCDEFGH012345677654321"; +static u8 ReturnString[XUARTPS_TOTAL_BYTES]; + +/************************** Function Prototypes ******************************/ + + +/****************************************************************************/ +/** +* +* This function runs a self-test on the driver and hardware device. This self +* test performs a local loopback and verifies data can be sent and received. +* +* The time for this test is proportional to the baud rate that has been set +* prior to calling this function. +* +* The mode and control registers are restored before return. +* +* @param InstancePtr is a pointer to the XUartPs instance +* +* @return +* - XST_SUCCESS if the test was successful +* - XST_UART_TEST_FAIL if the test failed looping back the data +* +* @note +* +* This function can hang if the hardware is not functioning properly. +* +******************************************************************************/ +s32 XUartPs_SelfTest(XUartPs *InstancePtr) +{ + s32 Status = XST_SUCCESS; + u32 IntrRegister; + u32 ModeRegister; + u8 Index; + + /* Assert validates the input arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); +#if defined (XCLOCKING) + Xil_ClockEnable(InstancePtr->Config.RefClk); +#endif + + /* Disable all interrupts in the interrupt disable register */ + IntrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_IMR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, + XUARTPS_IXR_MASK); + + /* Setup for local loopback */ + ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, + XUARTPS_MR_OFFSET); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ((ModeRegister & (u32)(~XUARTPS_MR_CHMODE_MASK)) | + (u32)XUARTPS_MR_CHMODE_L_LOOP)); + + /* Send a number of bytes and receive them, one at a time. */ + for (Index = 0U; Index < XUARTPS_TOTAL_BYTES; Index++) { + /* + * Send out the byte and if it was not sent then the failure + * will be caught in the comparison at the end + */ + (void)XUartPs_Send(InstancePtr, &TestString[Index], 1U); + + /* + * Wait until the byte is received with timeout. + */ + Status = (int)Xil_WaitForEvent(((InstancePtr->Config.BaseAddress) + + XUARTPS_SR_OFFSET), XUARTPS_SR_RXEMPTY, + 0, TIMEOUT_VAL); + if (Status != XST_SUCCESS) { + return XST_UART_TEST_FAIL; + } + + /* Receive the byte */ + (void)XUartPs_Recv(InstancePtr, &ReturnString[Index], 1U); + } + + /* + * Compare the bytes received to the bytes sent to verify the exact data + * was received + */ + for (Index = 0U; Index < XUARTPS_TOTAL_BYTES; Index++) { + if (TestString[Index] != ReturnString[Index]) { + Status = XST_UART_TEST_FAIL; + } + } + + /* + * Restore the registers which were altered to put into polling and + * loopback modes so that this test is not destructive + */ + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, + IntrRegister); + XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, + ModeRegister); + +#if defined (XCLOCKING) + Xil_ClockDisable(InstancePtr->Config.RefClk); +#endif + return Status; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_sinit.c new file mode 100644 index 0000000..de64a8c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/uartps/src/xuartps_sinit.c @@ -0,0 +1,74 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xuartps_sinit.c +* @addtogroup uartps Overview +* @{ +* +* The implementation of the XUartPs driver's static initialization +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/13/10 First Release
+* 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xuartps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +extern XUartPs_Config XUartPs_ConfigTable[XPAR_XUARTPS_NUM_INSTANCES]; + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. The table +* contains the configuration info for each device in the system. +* +* @param DeviceId contains the ID of the device +* +* @return A pointer to the configuration structure or NULL if the +* specified device is not in the system. +* +* @note None. +* +******************************************************************************/ +XUartPs_Config *XUartPs_LookupConfig(u16 DeviceId) +{ + XUartPs_Config *CfgPtr = NULL; + + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_XUARTPS_NUM_INSTANCES; Index++) { + if (XUartPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XUartPs_ConfigTable[Index]; + break; + } + } + + return (XUartPs_Config *)CfgPtr; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/Makefile new file mode 100644 index 0000000..5feeb49 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/Makefile @@ -0,0 +1,39 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf $(DEPFILES) diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps.c b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps.c new file mode 100644 index 0000000..c3dabfc --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps.c @@ -0,0 +1,351 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/******************************************************************************/ +/** + * @file xusbps.c +* @addtogroup usbps_v2_7 +* @{ + * + * The XUsbPs driver. Functions in this file are the minimum required + * functions for this driver. See xusbps.h for a detailed description of the + * driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- --------------------------------------------------------
+ * 1.00a jz  10/10/10 First release
+ * 2.1   kpc 04/28/14 Removed unused functions
+ * 2.5   pm  02/20/20 Added usb state interface.
+ * 
+ ******************************************************************************/ + +/***************************** Include Files **********************************/ +#include +#include "xusbps.h" + +/************************** Constant Definitions ******************************/ + +/**************************** Type Definitions ********************************/ + +/***************** Macros (Inline Functions) Definitions **********************/ + +/************************** Variable Definitions ******************************/ + +/************************** Function Prototypes *******************************/ + +/*****************************************************************************/ +/** +* +* This function initializes a XUsbPs instance/driver. +* +* The initialization entails: +* - Initialize all members of the XUsbPs structure. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param ConfigPtr is a pointer to a XUsbPs_Config configuration +* structure. This structure will contain the requested +* configuration for the device. Typically, this is a local +* structure and the content of which will be copied into the +* configuration structure within XUsbPs. +* @param VirtBaseAddress is the base address of the device. For systems +* with virtual memory, this address must be the virtual address +* of the device. +* For systems that do not support virtual memory this address +* should be the physical address of the device. For backwards +* compatibility NULL may be passed in systems that do not support +* virtual memory (deprecated). +* +* @return +* - XST_SUCCESS no errors occurred. +* - XST_FAILURE an error occurred during initialization. +* +* @note +* After calling XUsbPs_CfgInitialize() the controller +* IS NOT READY for use. Before the controller can be used its +* DEVICE parameters must be configured. See xusbps.h +* for details. +* +******************************************************************************/ +int XUsbPs_CfgInitialize(XUsbPs *InstancePtr, + const XUsbPs_Config *ConfigPtr, u32 VirtBaseAddress) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* Copy the config structure. */ + InstancePtr->Config = *ConfigPtr; + + /* Check if the user provided a non-NULL base address. If so, we have + * to overwrite the base address in the configuration structure. + */ + if (0 != VirtBaseAddress) { + InstancePtr->Config.BaseAddress = VirtBaseAddress; + } + + /* Initialize the XUsbPs structure to default values. */ + InstancePtr->CurrentAltSetting = XUSBPS_DEFAULT_ALT_SETTING; + + InstancePtr->HandlerFunc = NULL; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function performs device reset, device is stopped at the end. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XUsbPs_DeviceReset(XUsbPs *InstancePtr) +{ + int Timeout; + + /* Clear all setup token semaphores by reading the + * XUSBPS_EPSTAT_OFFSET register and writing its value back to + * itself. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPSTAT_OFFSET)); + + /* Clear all the endpoint complete status bits by reading the + * XUSBPS_EPCOMPL_OFFSET register and writings its value back + * to itself. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCOMPL_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPCOMPL_OFFSET)); + + /* Cancel all endpoint prime status by waiting until all bits + * in XUSBPS_EPPRIME_OFFSET are 0 and then writing 0xFFFFFFFF + * to XUSBPS_EPFLUSH_OFFSET. + * + * Avoid hanging here by using a Timeout counter... + */ + Timeout = XUSBPS_TIMEOUT_COUNTER; + while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPPRIME_OFFSET) & + XUSBPS_EP_ALL_MASK) && --Timeout) { + /* NOP */ + } + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPFLUSH_OFFSET, 0xFFFFFFFF); + + XUsbPs_Stop(InstancePtr); + + /* Write to CR register for controller reset */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_CMD_OFFSET) | XUSBPS_CMD_RST_MASK); + + /* Wait for reset to finish, hardware clears the reset bit once done */ + Timeout = 1000000; + while((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_CMD_OFFSET) & + XUSBPS_CMD_RST_MASK) && --Timeout) { + /* NOP */ + } +} +/*****************************************************************************/ +/** +* +* This function resets the USB device. All the configuration registers are +* reset to their default values. The function waits until the reset operation +* is complete or for a certain duration within which the reset operation is +* expected to be completed. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @return +* - XST_SUCCESS Reset operation completed successfully. +* - XST_FAILURE Reset operation timed out. +* +* @note None. +* +******************************************************************************/ +int XUsbPs_Reset(XUsbPs *InstancePtr) +{ + int Timeout; + + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Write a 1 to the RESET bit. The RESET bit is cleared by HW once the + * RESET is complete. + * + * We are going to wait for the RESET bit to clear before we return + * from this function. Unfortunately we do not have timers available at + * this point to determine when we should report a Timeout. + * + * However, by using a large number for the poll loop we can assume + * that the polling operation will take longer than the expected time + * the HW needs to RESET. If the poll loop expires we can assume a + * Timeout. The drawback is that on a slow system (and even on a fast + * system) this can lead to _very_ long Timeout periods. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_CMD_OFFSET, XUSBPS_CMD_RST_MASK); + + + /* Wait for the RESET bit to be cleared by HW. */ + Timeout = XUSBPS_TIMEOUT_COUNTER; + while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_CMD_OFFSET) & + XUSBPS_CMD_RST_MASK) && --Timeout) { + /* NOP */ + } + + if (0 == Timeout) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * USB Suspend + * + * In order to conserve power, USB devices automatically enter the suspended + * state when the device has observed no bus traffic for a specified period. + * When suspended, the USB device maintains any internal status, including its + * address and configuration. Attached devices must be prepared to suspend at + * any time they are powered, regardless of if they have been assigned a + * non-default address, are configured, or neither. Bus activity may cease due + * to the host entering a suspend mode of its own. In addition, a USB device + * shall also enter the suspended state when the hub port it is attached to is + * disabled. + * + * A USB device exits suspend mode when there is bus activity. A USB device may + * also request the host to exit suspend mode or selective suspend by using + * electrical signaling to indicate remote wakeup. The ability of a device to + * signal remote wakeup is optional. If the USB device is capable of remote + * wakeup signaling, the device must support the ability of the host to enable + * and disable this capability. When the device is reset, remote wakeup + * signaling must be disabled. + * + * @param InstancePtr is a pointer to XUsbPs instance of the controller. + * + * @return + * - XST_SUCCESS if the USB device has entered Suspend mode + * successfully + * - XST_FAILURE on any error + * + * @note None. + * + ******************************************************************************/ +int XUsbPs_Suspend(const XUsbPs *InstancePtr) +{ + (void) InstancePtr; + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* USB Resume +* + If the USB controller is suspended, its operation is resumed when any +* non-idle signaling is received on its upstream facing port. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @return +* - XST_SUCCESS if the USB device has Resumed successfully +* - XST_FAILURE on any error +* +* @note None. +* +******************************************************************************/ +int XUsbPs_Resume(const XUsbPs *InstancePtr) +{ + (void) InstancePtr; + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* USB Assert Resume +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @return +* - XST_SUCCESS if the USB device has Resumed successfully +* - XST_FAILURE on any error +* +* @note None. +* +******************************************************************************/ + +int XUsbPs_RequestHostResume(const XUsbPs *InstancePtr) +{ + (void) InstancePtr; + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* This functions sets the controller's DEVICE address. It also sets the +* advance bit so the controller will wait for the next IN-ACK before the new +* address takes effect. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param Address is the Address of the device. +* +* @return +* - XST_SUCCESS: Address set successfully. +* - XST_FAILURE: An error occurred. +* - XST_INVALID_PARAM: Invalid parameter passed, e.g. address +* value too big. +* +* @note None. +* +*****************************************************************************/ +int XUsbPs_SetDeviceAddress(XUsbPs *InstancePtr, u8 Address) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + + if ((InstancePtr->AppData != NULL) && + (InstancePtr->AppData->State == + XUSBPS_STATE_CONFIGURED)) { + return XST_FAILURE; + } + + /* Check address range validity. */ + if (Address > XUSBPS_DEVICEADDR_MAX) { + return XST_INVALID_PARAM; + } + + /* Set the address register with the Address value provided. Also set + * the Address Advance Bit. This will cause the address to be set only + * after an IN occurred and has been ACKed on the endpoint. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_DEVICEADDR_OFFSET, + (Address << XUSBPS_DEVICEADDR_ADDR_SHIFT) | + XUSBPS_DEVICEADDR_DEVICEAADV_MASK); + + if (InstancePtr->AppData != NULL) { + if (Address) + InstancePtr->AppData->State = XUSBPS_STATE_ADDRESS; + else + InstancePtr->AppData->State = XUSBPS_STATE_DEFAULT; + } + return XST_SUCCESS; +} + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps.h b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps.h new file mode 100644 index 0000000..5c01051 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps.h @@ -0,0 +1,1132 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xusbps.h +* @addtogroup usbps_v2_7 +* @{ +* @details + * + * This file contains the implementation of the XUsbPs driver. It is the + * driver for an USB controller in DEVICE or HOST mode. + * + *

Introduction

+ * + * The Spartan-3AF Embedded Peripheral Block contains a USB controller for + * communication with serial peripherals or hosts. The USB controller supports + * Host, Device and On the Go (OTG) applications. + * + *

USB Controller Features

+ * + * - Supports Low Speed USB 1.1 (1.5Mbps), Full Speed USB 1.1 (12Mbps), and + * High Speed USB 2.0 (480Mbps) data speeds + * - Supports Device, Host and OTG operational modes + * - ULPI transceiver interface for USB 2.0 operation + * - Integrated USB Full and Low speed serial transceiver interfaces for lowest + * cost connections + * + *

Initialization & Configuration

+ * + * The configuration of the USB driver happens in multiple stages: + * + * - (a) Configuration of the basic parameters: + * In this stage the basic parameters for the driver are configured, + * including the base address and the controller ID. + * + * - (b) Configuration of the DEVICE endpoints (if applicable): + * If DEVICE mode is desired, the endpoints of the controller need to be + * configured using the XUsbPs_DeviceConfig data structure. Once the + * endpoint configuration is set up in the data structure, The user then + * needs to allocate the required amount of DMAable memory and + * finalize the configuration of the XUsbPs_DeviceConfig data structure, + * e.g. setting the DMAMemVirt and DMAMemPhys members. + * + * - (c) Configuration of the DEVICE modes: + * In the second stage the parameters for DEVICE are configured. + * The caller only needs to configure the modes that are + * actually used. Configuration is done with the: + * XUsbPs_ConfigureDevice() + * Configuration parameters are defined and passed + * into these functions using the: + * XUsbPs_DeviceConfig data structures. + * + * + *

USB Device Endpoints

+ * + * The USB core supports up to 4 endpoints. Each endpoint has two directions, + * an OUT (RX) and an IN (TX) direction. Note that the direction is viewed from + * the host's perspective. Endpoint 0 defaults to be the control endpoint and + * does not need to be set up. Other endpoints need to be configured and set up + * depending on the application. Only endpoints that are actuelly used by the + * application need to be initialized. + * See the example code (xusbps_intr_example.c) for more information. + * + * + *

Interrupt Handling

+ * + * The USB core uses one interrupt line to report interrupts to the CPU. + * Interrupts are handled by the driver's interrupt handler function + * XUsbPs_IntrHandler(). + * It has to be registered with the OS's interrupt subsystem. The driver's + * interrupt handler divides incoming interrupts into two categories: + * + * - General device interrupts + * - Endopint related interrupts + * + * The user (typically the adapter layer) can register general interrupt + * handler functions and endpoint specific interrupt handler functions with the + * driver to receive those interrupts by calling the + * XUsbPs_IntrSetHandler() + * and + * XUsbPs_EpSetHandler() + * functions respectively. Calling these functions with a NULL pointer as the + * argument for the function pointer will "clear" the handler function. + * + * The user can register one handler function for the generic interrupts and + * two handler functions for each endpoint, one for the RX (OUT) and one for + * the TX (IN) direction. For some applications it may be useful to register a + * single endpoint handler function for muliple endpoints/directions. + * + * When a callback function is called by the driver, parameters identifying the + * type of the interrupt will be passed into the handler functions. For general + * interrupts the interrupt mask will be passed into the handler function. For + * endpoint interrupts the parameters include the number of the endpoint, the + * direction (OUT/IN) and the type of the interrupt. + * + * + *

Data buffer handling

+ * + * Data buffers are sent to and received from endpoint using the + * XUsbPs_EpBufferSend(), XUsbPs_EpBufferSendWithZLT() + * and + * XUsbPs_EpBufferReceive() + * functions. + * + * User data buffer size is limited to 16 Kbytes. If the user wants to send a + * data buffer that is bigger than this limit it needs to break down the data + * buffer into multiple fragments and send the fragments individually. + * + * From the controller perspective Data buffers can be aligned at any boundary. + * if the buffers are from cache region then the buffer and buffer size should + * be aligned to cache line aligned + * + * + *

Zero copy

+ * + * The driver uses a zero copy mechanism which imposes certain restrictions to + * the way the user can handle the data buffers. + * + * One restriction is that the user needs to release a buffer after it is done + * processing the data in the buffer. + * + * Similarly, when the user sends a data buffer it MUST not re-use the buffer + * until it is notified by the driver that the buffer has been transmitted. The + * driver will notify the user via the registered endpoint interrupt handling + * function by sending a XUSBPS_EP_EVENT_DATA_TX event. + * + * + *

DMA

+ * + * The driver uses DMA internally to move data from/to memory. This behaviour + * is transparent to the user. Keeping the DMA handling hidden from the user + * has the advantage that the same API can be used with USB cores that do not + * support DMA. + * + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- ----------------------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 1.02a wgr  05/16/12 Removed comments as they are showing up in SDK
+ *		       Tabs for CR 657898
+ * 1.03a nm   09/21/12 Fixed CR#678977. Added proper sequence for setup packet
+ *                    handling.
+ * 1.04a nm   10/23/12 Fixed CR# 679106.
+ *	      11/02/12 Fixed CR# 683931. Mult bits are set properly in dQH.
+ * 2.00a kpc 04/03/14 Fixed CR#777763. Corrected the setup tripwire macro val.
+ * 2.1   kpc 04/28/14 Removed unused function prototypes
+ * 2.2   kpc 08/23/14 Exported XUsbPs_DeviceReset API as global for calling in
+ *                    code coverage tests.
+ * 2.3   kpc 02/19/14 Fixed CR#873972, CR#873974. Corrected the logic for proper
+ *                    moving of dTD Head/Tail Pointers. Invalidate the cache
+ *                    after buffer receive in Endpoint Buffer Handler.
+ * 2.4   sg  04/26/16 Fixed CR#949693, Corrected the logic for EP flush
+ *       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+ *                    generation.
+ *       ms  04/10/17 Modified filename tag to include the file in doxygen
+ *                    examples.
+ * 2.5   pm  02/20/20 Added ISO support for usb 2.0 and ch9 common framework
+ * 			calls.
+ * 
+ * + ******************************************************************************/ + +#ifndef XUSBPS_H +#define XUSBPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xusbps_hw.h" +#include "xil_types.h" +#include "xstatus.h" + +/************************** Constant Definitions *****************************/ + +/** + * @name System hang prevention Timeout counter value. + * + * This value is used throughout the code to initialize a Timeout counter that + * is used when hard polling a register. The ides is to initialize the Timeout + * counter to a value that is longer than any expected Timeout but short enough + * so the system will continue to work and report an error while the user is + * still paying attention. A reasonable Timeout time would be about 10 seconds. + * The XUSBPS_TIMEOUT_COUNTER value should be chosen so a polling loop would + * run about 10 seconds before a Timeout is detected. For example: + * + * int Timeout = XUSBPS_TIMEOUT_COUNTER; + * while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + * XUSBPS_CMD_OFFSET) & + * XUSBPS_CMD_RST_MASK) && --Timeout) { + * ; + * } + * if (0 == Timeout) { + * return XST_FAILURE; + * } + * + */ +#define XUSBPS_TIMEOUT_COUNTER 1000000 + + +/** + * @name Endpoint Direction (bitmask) + * Definitions to be used with Endpoint related function that require a + * 'Direction' parameter. + * + * NOTE: + * The direction is always defined from the perspective of the HOST! This + * means that an IN endpoint on the controller is used for sending data while + * the OUT endpoint on the controller is used for receiving data. + * @{ + */ +#define XUSBPS_EP_DIRECTION_IN 0x01 /**< Endpoint direction IN. */ +#define XUSBPS_EP_DIRECTION_OUT 0x02 /**< Endpoint direction OUT. */ +/* @} */ + + +/** + * @name Endpoint Type + * Definitions to be used with Endpoint related functions that require a 'Type' + * parameter. + * @{ + */ +#define XUSBPS_EP_TYPE_NONE 0 /**< Endpoint is not used. */ +#define XUSBPS_EP_TYPE_CONTROL 1 /**< Endpoint for Control Transfers */ +#define XUSBPS_EP_TYPE_ISOCHRONOUS 2 /**< Endpoint for isochronous data */ +#define XUSBPS_EP_TYPE_BULK 3 /**< Endpoint for BULK Transfers. */ +#define XUSBPS_EP_TYPE_INTERRUPT 4 /**< Endpoint for interrupt Transfers */ +/* @} */ + +/** + * Endpoint Max Packet Length in DeviceConfig is a coded value, ch9.6.6. + * + * @{ + */ +#define ENDPOINT_MAXP_LENGTH 0x400 +#define ENDPOINT_MAXP_MULT_MASK 0xC00 +#define ENDPOINT_MAXP_MULT_SHIFT 10 +/* @} */ + +/** + * @name Field names for status retrieval + * Definitions for the XUsbPs_GetStatus() function call 'StatusType' + * parameter. + * @{ + */ +#define XUSBPS_EP_STS_ADDRESS 1 /**< Address of controller. */ +#define XUSBPS_EP_STS_CONTROLLER_STATE 2 /**< Current controller state. */ +/* @} */ + + /* + * Device Speeds + */ + #define XUSBPS_SPEED_UNKNOWN 0U + #define XUSBPS_SPEED_LOW 1U + #define XUSBPS_SPEED_FULL 2U + #define XUSBPS_SPEED_HIGH 3U + +/** + * @name USB Default alternate setting + * + * @{ + */ +#define XUSBPS_DEFAULT_ALT_SETTING 0 /**< The default alternate setting is 0 */ +/* @} */ + + /* + * Device States + */ + #define XUSBPS_STATE_ATTACHED 0U + #define XUSBPS_STATE_POWERED 1U + #define XUSBPS_STATE_DEFAULT 2U + #define XUSBPS_STATE_ADDRESS 3U + #define XUSBPS_STATE_CONFIGURED 4U + #define XUSBPS_STATE_SUSPENDED 5U + +/** + * @name Endpoint event types + * Definitions that are used to identify events that occur on endpoints. Passed + * to the endpoint event handler functions registered with + * XUsbPs_EpSetHandler(). + * @{ + */ +#define XUSBPS_EP_EVENT_SETUP_DATA_RECEIVED 0x01 + /**< Setup data has been received on the endpoint. */ +#define XUSBPS_EP_EVENT_DATA_RX 0x02 + /**< Data frame has been received on the endpoint. */ +#define XUSBPS_EP_EVENT_DATA_TX 0x03 + /**< Data frame has been sent on the endpoint. */ +/* @} */ + + +/* + * Maximum packet size for endpoint, 1024 + * @{ + */ +#define XUSBPS_MAX_PACKET_SIZE 1024 + /**< Maximum value can be put into the queue head */ +/* @} */ +/**************************** Type Definitions *******************************/ + +/****************************************************************************** + * This data type defines the callback function to be used for Endpoint + * handlers. + * + * @param CallBackRef is the Callback reference passed in by the upper + * layer when setting the handler, and is passed back to the upper + * layer when the handler is called. + * @param EpNum is the Number of the endpoint that caused the event. + * @param EventType is the type of the event that occurred on the endpoint. + * @param Data is a pointer to user data pointer specified when callback + * was registered. + */ +typedef void (*XUsbPs_EpHandlerFunc)(void *CallBackRef, + u8 EpNum, u8 EventType, void *Data); + +/****************************************************************************** + * This data type defines the callback function to be used for Endpoint + * handlers. + * + * @param CallBackRef is the Callback reference passed in by the upper + * layer when setting the handler, and is passed back to the upper + * layer when the handler is called. + * @param RequestedBytes is the number of bytes requested to transfer. + * @param BytesTxed is the actual number of bytes to be transfer. + */ +typedef void (*XUsbPs_EpIsoHandlerFunc)(void *CallBackRef, + u32 RequestedBytes, u32 BytesTxed); + +/****************************************************************************** + * This data type defines the callback function to be used for the general + * interrupt handler. + * + * @param CallBackRef is the Callback reference passed in by the upper + * layer when setting the handler, and is passed back to the upper + * layer when the handler is called. + * @param IrqMask is the Content of the interrupt status register. This + * value can be used by the callback function to distinguish the + * individual interrupt types. + */ +typedef void (*XUsbPs_IntrHandlerFunc)(void *CallBackRef, u32 IrqMask); + + +/******************************************************************************/ + +/* The following type definitions are used for referencing Queue Heads and + * Transfer Descriptors. The structures themselves are not used, however, the + * types are used in the API to avoid using (void *) pointers. + */ +typedef u8 XUsbPs_dQH[XUSBPS_dQH_ALIGN]; +typedef u8 XUsbPs_dTD[XUSBPS_dTD_ALIGN]; + + +/** + * The following data structures are used internally by the L0/L1 driver. + * Their contents MUST NOT be changed by the upper layers. + */ + +/** + * The following data structure represents OUT endpoint. + */ +typedef struct { + XUsbPs_dQH *dQH; + /**< Pointer to the Queue Head structure of the endpoint. */ + + XUsbPs_dTD *dTDs; + /**< Pointer to the first dTD of the dTD list for this + * endpoint. */ + + XUsbPs_dTD *dTDCurr; + /**< Buffer to the currently processed descriptor. */ + + u8 *dTDBufs; + /**< Pointer to the first buffer of the buffer list for this + * endpoint. */ + + XUsbPs_EpHandlerFunc HandlerFunc; + XUsbPs_EpIsoHandlerFunc HandlerIsoFunc; + /**< Handler function for this endpoint. */ + void *HandlerRef; + /**< User data reference for the handler. */ + u32 RequestedBytes; /**< RequestedBytes for transfer */ + u32 BytesTxed; /**< Actual Bytes transferred */ + u8 *BufferPtr; /**< Buffer location */ + u8 MemAlloted; /**< Mem alloted and data is not received */ + u32 Interval; /**< Data transfer service interval */ +} XUsbPs_EpOut; + + +/** + * The following data structure represents IN endpoint. + */ +typedef struct { + XUsbPs_dQH *dQH; + /**< Pointer to the Queue Head structure of the endpoint. */ + + XUsbPs_dTD *dTDs; + /**< List of pointers to the Transfer Descriptors of the + * endpoint. */ + + XUsbPs_dTD *dTDHead; + /**< Buffer to the next available descriptor in the list. */ + + XUsbPs_dTD *dTDTail; + /**< Buffer to the last unsent descriptor in the list*/ + + XUsbPs_EpHandlerFunc HandlerFunc; + XUsbPs_EpIsoHandlerFunc HandlerIsoFunc; + /**< Handler function for this endpoint. */ + void *HandlerRef; + /**< User data reference for the handler. */ + u32 RequestedBytes; /**< RequestedBytes for transfer */ + u32 BytesTxed; /**< Actual Bytes transferred */ + u8 *BufferPtr; /**< Buffer location */ + u32 Interval; /**< Data transfer service interval */ +} XUsbPs_EpIn; + + +/** + * The following data structure represents an endpoint used internally + * by the L0/L1 driver. + */ +typedef struct { + /* Each endpoint has an OUT and an IN component. + */ + XUsbPs_EpOut Out; /**< OUT endpoint structure */ + XUsbPs_EpIn In; /**< IN endpoint structure */ +} XUsbPs_Endpoint; + + + +/** + * The following structure is used by the user to receive Setup Data from an + * endpoint. Using this structure simplifies the process of interpreting the + * setup data in the core's data fields. + * + * The naming scheme for the members of this structure is different from the + * naming scheme found elsewhere in the code. The members of this structure are + * defined in the Chapter 9 USB reference guide. Using this naming scheme makes + * it easier for people familiar with the standard to read the code. + */ +typedef struct { + u8 bmRequestType; /**< bmRequestType in setup data */ + u8 bRequest; /**< bRequest in setup data */ + u16 wValue; /**< wValue in setup data */ + u16 wIndex; /**< wIndex in setup data */ + u16 wLength; /**< wLength in setup data */ +} +XUsbPs_SetupData; + + +/** + * Data structures used to configure endpoints. + */ +typedef struct { + u32 Type; + /**< Endpoint type: + - XUSBPS_EP_TYPE_CONTROL + - XUSBPS_EP_TYPE_ISOCHRONOUS + - XUSBPS_EP_TYPE_BULK + - XUSBPS_EP_TYPE_INTERRUPT */ + + u32 NumBufs; + /**< Number of buffers to be handled by this endpoint. */ + u32 BufSize; + /**< Buffer size. Only relevant for OUT (receive) Endpoints. */ + + u16 MaxPacketSize; + /**< Maximum packet size for this endpoint. This number will + * define the maximum number of bytes sent on the wire per + * transaction. Range: 0..1024 */ +} XUsbPs_EpSetup; + + +/** + * Endpoint configuration structure. + */ +typedef struct { + XUsbPs_EpSetup Out; /**< OUT component of endpoint. */ + XUsbPs_EpSetup In; /**< IN component of endpoint. */ +} XUsbPs_EpConfig; + + +/** + * The XUsbPs_DeviceConfig structure contains the configuration information to + * configure the USB controller for DEVICE mode. This data structure is used + * with the XUsbPs_ConfigureDevice() function call. + */ +typedef struct { + u8 NumEndpoints; /**< Number of Endpoints for the controller. + This number depends on the runtime + configuration of driver. The driver may + configure fewer endpoints than are available + in the core. */ + + XUsbPs_EpConfig EpCfg[XUSBPS_MAX_ENDPOINTS]; + /**< List of endpoint configurations. */ + + + u32 DMAMemPhys; /**< Physical base address of DMAable memory + allocated for the driver. */ + + /* The following members are used internally by the L0/L1 driver. They + * MUST NOT be accesses and/or modified in any way by the upper layers. + * + * The reason for having these members is that we generally try to + * avoid allocating memory in the L0/L1 driver as we want to be OS + * independent. In order to avoid allocating memory for this data + * structure wihin L0/L1 we put it into the XUsbPs_DeviceConfig + * structure which is allocated by the caller. + */ + XUsbPs_Endpoint Ep[XUSBPS_MAX_ENDPOINTS]; + /**< List of endpoint metadata structures. */ + + u32 PhysAligned; /**< 64 byte aligned base address of the DMA + memory block. Will be computed and set by + the L0/L1 driver. */ +} XUsbPs_DeviceConfig; + + +/** + * The XUsbPs_Config structure contains configuration information for the USB + * controller. + * + * This structure only contains the basic configuration for the controller. The + * caller also needs to initialize the controller for the DEVICE mode + * using the XUsbPs_DeviceConfig data structures with the + * XUsbPs_ConfigureDevice() function call + */ +typedef struct { + u16 DeviceID; /**< Unique ID of controller. */ + u32 BaseAddress; /**< Core register base address. */ +} XUsbPs_Config; + +typedef XUsbPs_Config Usb_Config; + +struct Usb_DevData { + u8 Speed; + u8 State; + + void *PrivateData; +}; + +/** + * The XUsbPs driver instance data. The user is required to allocate a + * variable of this type for every USB controller in the system. A pointer to a + * variable of this type is then passed to the driver API functions. + */ +typedef struct { + XUsbPs_SetupData SetupData; + /**< Setup Packet buffer */ + XUsbPs_Config Config; /**< Configuration structure */ + + int CurrentAltSetting; /**< Current alternative setting of interface */ + + void *UserDataPtr; /**< Data pointer to be used by upper layers to + store application dependent data structures. + The upper layers are responsible to allocated + and free the memory. The driver will not + mofidy this data pointer. */ + + /** + * The following structures hold the configuration for DEVICE mode + * of the controller. They are initialized using the + * XUsbPs_ConfigureDevice() function call. + */ + XUsbPs_DeviceConfig DeviceConfig; + /**< Configuration for the DEVICE mode. */ + + XUsbPs_IntrHandlerFunc HandlerFunc; + /**< Handler function for the controller. */ + void *HandlerRef; + /**< User data reference for the handler. */ + u32 HandlerMask; + /**< User interrupt mask. Defines which interrupts will cause + * the callback to be called. */ + struct Usb_DevData *AppData; + u8 IsConfigDone; + void *data_ptr; /* pointer for storing applications data */ +} XUsbPs; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************** + * + * USB CONTROLLER RELATED MACROS + * + ******************************************************************************/ +/*****************************************************************************/ +/** + * This macro returns the current frame number. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @return The current frame number. + * + * @note C-style signature: + * u32 XUsbPs_GetFrameNum(const XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_GetFrameNum(InstancePtr) \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, XUSBPS_FRAME_OFFSET) + + +/*****************************************************************************/ +/** + * This macro starts the USB engine. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @note C-style signature: + * void XUsbPs_Start(XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_Start(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_CMD_OFFSET, XUSBPS_CMD_RS_MASK) + + +/*****************************************************************************/ +/** + * This macro stops the USB engine. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @note C-style signature: + * void XUsbPs_Stop(XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_Stop(InstancePtr) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_CMD_OFFSET, XUSBPS_CMD_RS_MASK) + + +/*****************************************************************************/ +/** + * This macro forces the USB engine to be in Full Speed (FS) mode. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @note C-style signature: + * void XUsbPs_ForceFS(XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_ForceFS(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_PORTSCR1_OFFSET, \ + XUSBPS_PORTSCR_PFSC_MASK) + + +/*****************************************************************************/ +/** + * This macro starts the USB Timer 0, with repeat option for period of + * one second. + * + * @param InstancePtr is a pointer to XUsbPs instance of the controller. + * @param Interval is the interval for Timer0 to generate an interrupt + * + * @note C-style signature: + * void XUsbPs_StartTimer0(XUsbPs *InstancePtr, u32 Interval) + * + ******************************************************************************/ +#define XUsbPs_StartTimer0(InstancePtr, Interval) \ +{ \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_TIMER0_LD_OFFSET, (Interval)); \ + XUsbPs_SetBits(InstancePtr, XUSBPS_TIMER0_CTL_OFFSET, \ + XUSBPS_TIMER_RUN_MASK | \ + XUSBPS_TIMER_RESET_MASK | \ + XUSBPS_TIMER_REPEAT_MASK); \ +} \ + + +/*****************************************************************************/ +/** +* This macro stops Timer 0. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_StopTimer0(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_StopTimer0(InstancePtr) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_TIMER0_CTL_OFFSET, \ + XUSBPS_TIMER_RUN_MASK) + + +/*****************************************************************************/ +/** +* This macro reads Timer 0. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_ReadTimer0(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_ReadTimer0(InstancePtr) \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_TIMER0_CTL_OFFSET) & \ + XUSBPS_TIMER_COUNTER_MASK + + +/*****************************************************************************/ +/** +* This macro force remote wakeup on host +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_RemoteWakeup(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_RemoteWakeup(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_PORTSCR1_OFFSET, \ + XUSBPS_PORTSCR_FPR_MASK) + + +/****************************************************************************** + * + * ENDPOINT RELATED MACROS + * + ******************************************************************************/ +/*****************************************************************************/ +/** +* This macro enables the given endpoint for the given direction. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is number of the endpoint to enable. +* @param Dir is direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpEnable(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpEnable(InstancePtr, EpNum, Dir) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXE_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXE_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro disables the given endpoint for the given direction. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is the number of the endpoint to disable. +* @param Dir is the direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpDisable(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpDisable(InstancePtr, EpNum, Dir) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXE_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXE_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro stalls the given endpoint for the given direction, and flush +* the buffers. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is number of the endpoint to stall. +* @param Dir is the direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpStall(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpStall(InstancePtr, EpNum, Dir) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXS_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXS_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro unstalls the given endpoint for the given direction. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is the Number of the endpoint to unstall. +* @param Dir is the Direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpUnStall(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpUnStall(InstancePtr, EpNum, Dir) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXS_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXS_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro flush an endpoint upon interface disable +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is the number of the endpoint to flush. +* @param Dir is the direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpFlush(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpFlush(InstancePtr, EpNum, Dir) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPFLUSH_OFFSET, \ + 1 << (EpNum + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? \ + XUSBPS_EPFLUSH_RX_SHIFT:XUSBPS_EPFLUSH_TX_SHIFT))) \ + +/*****************************************************************************/ +/** +* This macro enables the interrupts defined by the bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param IntrMask is the Bit mask of interrupts to be enabled. +* +* @note C-style signature: +* void XUsbPs_IntrEnable(XUsbPs *InstancePtr, u32 IntrMask) +* +******************************************************************************/ +#define XUsbPs_IntrEnable(InstancePtr, IntrMask) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_IER_OFFSET, IntrMask) + + +/*****************************************************************************/ +/** +* This function disables the interrupts defined by the bit mask. +* +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param IntrMask is a Bit mask of interrupts to be disabled. +* +* @note C-style signature: +* void XUsbPs_IntrDisable(XUsbPs *InstancePtr, u32 IntrMask) +* +******************************************************************************/ +#define XUsbPs_IntrDisable(InstancePtr, IntrMask) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_IER_OFFSET, IntrMask) + + +/*****************************************************************************/ +/** +* This macro enables the endpoint NAK interrupts defined by the bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param NakIntrMask is the Bit mask of endpoint NAK interrupts to be +* enabled. +* @note C-style signature: +* void XUsbPs_NakIntrEnable(XUsbPs *InstancePtr, u32 NakIntrMask) +* +******************************************************************************/ +#define XUsbPs_NakIntrEnable(InstancePtr, NakIntrMask) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPNAKIER_OFFSET, NakIntrMask) + + +/*****************************************************************************/ +/** +* This macro disables the endpoint NAK interrupts defined by the bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param NakIntrMask is a Bit mask of endpoint NAK interrupts to be +* disabled. +* +* @note +* C-style signature: +* void XUsbPs_NakIntrDisable(XUsbPs *InstancePtr, u32 NakIntrMask) +* +******************************************************************************/ +#define XUsbPs_NakIntrDisable(InstancePtr, NakIntrMask) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_EPNAKIER_OFFSET, NakIntrMask) + + +/*****************************************************************************/ +/** +* This function clears the endpoint NAK interrupts status defined by the +* bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param NakIntrMask is the Bit mask of endpoint NAK interrupts to be cleared. +* +* @note C-style signature: +* void XUsbPs_NakIntrClear(XUsbPs *InstancePtr, u32 NakIntrMask) +* +******************************************************************************/ +#define XUsbPs_NakIntrClear(InstancePtr, NakIntrMask) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_EPNAKISR_OFFSET, NakIntrMask) + + + +/*****************************************************************************/ +/** +* This macro sets the Interrupt Threshold value in the control register +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param Threshold is the Interrupt threshold to be set. +* Allowed values: +* - XUSBPS_CMD_ITHRESHOLD_0 - Immediate interrupt +* - XUSBPS_CMD_ITHRESHOLD_1 - 1 Frame +* - XUSBPS_CMD_ITHRESHOLD_2 - 2 Frames +* - XUSBPS_CMD_ITHRESHOLD_4 - 4 Frames +* - XUSBPS_CMD_ITHRESHOLD_8 - 8 Frames +* - XUSBPS_CMD_ITHRESHOLD_16 - 16 Frames +* - XUSBPS_CMD_ITHRESHOLD_32 - 32 Frames +* - XUSBPS_CMD_ITHRESHOLD_64 - 64 Frames +* +* @note +* C-style signature: +* void XUsbPs_SetIntrThreshold(XUsbPs *InstancePtr, u8 Threshold) +* +******************************************************************************/ +#define XUsbPs_SetIntrThreshold(InstancePtr, Threshold) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_CMD_OFFSET, (Threshold))\ + + +/*****************************************************************************/ +/** +* This macro sets the Tripwire bit in the USB command register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_SetTripwire(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_SetSetupTripwire(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_CMD_OFFSET, \ + XUSBPS_CMD_SUTW_MASK) + + +/*****************************************************************************/ +/** +* This macro clears the Tripwire bit in the USB command register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_ClrTripwire(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_ClrSetupTripwire(InstancePtr) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_CMD_OFFSET, \ + XUSBPS_CMD_SUTW_MASK) + + +/*****************************************************************************/ +/** +* This macro checks if the Tripwire bit in the USB command register is set. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @return +* - TRUE: The tripwire bit is still set. +* - FALSE: The tripwire bit has been cleared. +* +* @note C-style signature: +* int XUsbPs_TripwireIsSet(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_SetupTripwireIsSet(InstancePtr) \ + (XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_CMD_OFFSET) & \ + XUSBPS_CMD_SUTW_MASK ? TRUE : FALSE) + + +/****************************************************************************** +* +* GENERAL REGISTER / BIT MANIPULATION MACROS +* +******************************************************************************/ +/****************************************************************************/ +/** +* This macro sets the given bit mask in the register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param RegOffset is the register offset to be written. +* @param Bits is the Bits to be set in the register +* +* @return None. +* +* @note C-style signature: +* void XUsbPs_SetBits(u32 BaseAddress, u32 RegOffset, u32 Bits) +* +*****************************************************************************/ +#define XUsbPs_SetBits(InstancePtr, RegOffset, Bits) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, RegOffset, \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + RegOffset) | (Bits)); + + +/****************************************************************************/ +/** +* +* This macro clears the given bits in the register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param RegOffset is the register offset to be written. +* @param Bits are the bits to be cleared in the register +* +* @return None. +* +* @note +* C-style signature: +* void XUsbPs_ClrBits(u32 BaseAddress, u32 RegOffset, u32 Bits) +* +*****************************************************************************/ +#define XUsbPs_ClrBits(InstancePtr, RegOffset, Bits) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, RegOffset, \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + RegOffset) & ~(Bits)); + + +/************************** Function Prototypes ******************************/ + +/** + * Setup / Initialize functions. + * + * Implemented in file xusbps.c + */ +int XUsbPs_CfgInitialize(XUsbPs *InstancePtr, + const XUsbPs_Config *ConfigPtr, u32 BaseAddress); + +int XUsbPs_ConfigureDevice(XUsbPs *InstancePtr, + const XUsbPs_DeviceConfig *CfgPtr); + +/** + * Common functions used for DEVICE/HOST mode. + */ +int XUsbPs_Reset(XUsbPs *InstancePtr); + +void XUsbPs_DeviceReset(XUsbPs *InstancePtr); + +/** + * DEVICE mode specific functions. + */ +int XUsbPs_BusReset(XUsbPs *InstancePtr); +int XUsbPs_SetDeviceAddress(XUsbPs *InstancePtr, u8 Address); + + +/** + * Handling Suspend and Resume. + * + * Implemented in xusbps.c + */ +int XUsbPs_Suspend(const XUsbPs *InstancePtr); +int XUsbPs_Resume(const XUsbPs *InstancePtr); +int XUsbPs_RequestHostResume(const XUsbPs *InstancePtr); + + +/* + * Functions for managing Endpoints / Transfers + * + * Implemented in file xusbps_endpoint.c + */ +int XUsbPs_EpBufferSend(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen); +int XUsbPs_EpBufferSendWithZLT(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen); +int XUsbPs_EpBufferReceive(XUsbPs *InstancePtr, u8 EpNum, + u8 **BufferPtr, u32 *BufferLenPtr, u32 *Handle); +void XUsbPs_EpBufferRelease(u32 Handle); + +int XUsbPs_EpSetHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction, + XUsbPs_EpHandlerFunc CallBackFunc, + void *CallBackRef); +s32 XUsbPs_EpSetIsoHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction, + XUsbPs_EpIsoHandlerFunc CallBackFunc); +int XUsbPs_EpGetSetupData(XUsbPs *InstancePtr, int EpNum, + XUsbPs_SetupData *SetupDataPtr); + +int XUsbPs_EpPrime(XUsbPs *InstancePtr, u8 EpNum, u8 Direction); + +int XUsbPs_ReconfigureEp(XUsbPs *InstancePtr, XUsbPs_DeviceConfig *CfgPtr, + int EpNum, unsigned short NewDirection, int DirectionChanged); + +/* + * Interrupt handling functions + * + * Implemented in file xusbps_intr.c + */ +void XUsbPs_IntrHandler(void *InstancePtr); + +int XUsbPs_IntrSetHandler(XUsbPs *InstancePtr, + XUsbPs_IntrHandlerFunc CallBackFunc, + void *CallBackRef, u32 Mask); +void XUsbPs_EpGetData(XUsbPs *InstancePtr, u8 EpNum, u32 BufferLen); + +s32 XUsbPs_EpDataBufferReceive(XUsbPs *InstancePtr, u8 EpNum, + u8 *BufferPtr, u32 BufferLen); +/* + * Helper functions for static configuration. + * Implemented in xusbps_sinit.c + */ +XUsbPs_Config *XUsbPs_LookupConfig(u16 DeviceId); + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_H */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_endpoint.c b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_endpoint.c new file mode 100644 index 0000000..a22510e --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_endpoint.c @@ -0,0 +1,1649 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/******************************************************************************/ +/** + * @file xusbps_endpoint.c +* @addtogroup usbps_v2_7 +* @{ + * + * Endpoint specific function implementations. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- --------------------------------------------------------
+ * 1.00a jz  10/10/10 First release
+ * 1.03a nm  09/21/12 Fixed CR#678977. Added proper sequence for setup packet
+ *                    handling.
+ * 1.04a nm  11/02/12 Fixed CR#683931. Mult bits are set properly in dQH.
+ * 2.00a kpc 04/03/14 Fixed CR#777763. Updated the macro names 
+ * 2.1   kpc 04/28/14 Added XUsbPs_EpBufferSendWithZLT api and merged common
+ *		      code to XUsbPs_EpQueueRequest.
+ * 2.3   bss 01/19/16 Modified XUsbPs_EpQueueRequest function to fix CR#873972
+ *            (moving of dTD Head/Tail Pointers)and CR#873974(invalidate
+ *            Caches After Buffer Receive in Endpoint Buffer Handler...)
+ * 2.5   pm  02/20/20 Added ISO endpoint support.
+ * 
+ ******************************************************************************/ + +/***************************** Include Files **********************************/ + +#include /* for bzero() */ +#include + +#include "xusbps.h" +#include "xusbps_endpoint.h" + +/************************** Constant Definitions ******************************/ + +/**************************** Type Definitions ********************************/ + +/************************** Variable Definitions ******************************/ + +/************************** Function Prototypes ******************************/ + +static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr); +static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr); +static int XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr); +static int XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr, + const u8 *BufferPtr, u32 BufferLen); + +static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len); + +/* Functions to reconfigure endpoint upon host's set alternate interface + * request. + */ +static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr, + int EpNum, unsigned short NewDirection); +static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr, + int EpNum, unsigned short NewDirection); +static int XUsbPs_EpQueueRequest(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen, u8 ReqZero); + +/******************************* Functions ************************************/ + +/*****************************************************************************/ +/** + * + * This function configures the DEVICE side of the controller. The caller needs + * to pass in the desired configuration (e.g. number of endpoints) and a + * DMAable buffer that will hold the Queue Head List and the Transfer + * Descriptors. The required size for this buffer can be obtained by the caller + * using the: XUsbPs_DeviceMemRequired() macro. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * @param CfgPtr is a pointer to the configuration structure that contains + * the desired DEVICE side configuration. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occurred. + * + * @note + * The caller may configure the controller for both, DEVICE and + * HOST side. + * + ******************************************************************************/ +int XUsbPs_ConfigureDevice(XUsbPs *InstancePtr, + const XUsbPs_DeviceConfig *CfgPtr) +{ + int Status; + u32 ModeValue = 0x0; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + + /* Copy the configuration data over into the local instance structure */ + InstancePtr->DeviceConfig = *CfgPtr; + + + /* Align the buffer to a 2048 byte (XUSBPS_dQH_BASE_ALIGN) boundary.*/ + InstancePtr->DeviceConfig.PhysAligned = + (InstancePtr->DeviceConfig.DMAMemPhys + + XUSBPS_dQH_BASE_ALIGN) & + ~(XUSBPS_dQH_BASE_ALIGN -1); + + /* Initialize the endpoint pointer list data structure. */ + XUsbPs_EpListInit(&InstancePtr->DeviceConfig); + + + /* Initialize the Queue Head structures in DMA memory. */ + XUsbPs_dQHInit(&InstancePtr->DeviceConfig); + + + /* Initialize the Transfer Descriptors in DMA memory.*/ + Status = XUsbPs_dTDInit(&InstancePtr->DeviceConfig); + if (XST_SUCCESS != Status) { + return XST_FAILURE; + } + + /* Changing the DEVICE mode requires a controller RESET. */ + if (XST_SUCCESS != XUsbPs_Reset(InstancePtr)) { + return XST_FAILURE; + } + + /* Set the Queue Head List address. */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPLISTADDR_OFFSET, + InstancePtr->DeviceConfig.PhysAligned); + + /* Set the USB mode register to configure DEVICE mode. + * + * XUSBPS_MODE_SLOM_MASK note: + * Disable Setup Lockout. Setup Lockout is not required as we + * will be using the tripwire mechanism when handling setup + * packets. + */ + ModeValue = XUSBPS_MODE_CM_DEVICE_MASK | XUSBPS_MODE_SLOM_MASK; + + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_MODE_OFFSET, ModeValue); + + XUsbPs_SetBits(InstancePtr, XUSBPS_OTGCSR_OFFSET, + XUSBPS_OTGSC_OT_MASK); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function sends a given data buffer. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param EpNum is the number of the endpoint to receive data from. +* @param BufferPtr is a pointer to the buffer to send. +* @param BufferLen is the Buffer length. +* +* @return +* - XST_SUCCESS: The operation completed successfully. +* - XST_FAILURE: An error occurred. +* - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB). +* - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available. +* +******************************************************************************/ +int XUsbPs_EpBufferSend(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr, + BufferLen, FALSE); +} + +/*****************************************************************************/ +/** +* This function sends a given data buffer and also zero length packet if the +* Bufferlen is in multiples of endpoint max packet size. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param EpNum is the number of the endpoint to receive data from. +* @param BufferPtr is a pointer to the buffer to send. +* @param BufferLen is the Buffer length. +* +* @return +* - XST_SUCCESS: The operation completed successfully. +* - XST_FAILURE: An error occurred. +* - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB). +* - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available. +* +******************************************************************************/ +int XUsbPs_EpBufferSendWithZLT(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen) +{ + u8 ReqZero = FALSE; + XUsbPs_EpSetup *Ep; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + Ep = &InstancePtr->DeviceConfig.EpCfg[EpNum].In; + + if ((BufferLen >= Ep->MaxPacketSize) && + (BufferLen % Ep->MaxPacketSize == 0)) { + ReqZero = TRUE; + } + + return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr, + BufferLen, ReqZero); +} + +/*****************************************************************************/ +/** +* This function sends a given data buffer and also sends ZLT packet if it is +* requested. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param EpNum is the number of the endpoint to receive data from. +* @param BufferPtr is a pointer to the buffer to send. +* @param BufferLen is the Buffer length. +* @param ReqZero is the +* +* @return +* - XST_SUCCESS: The operation completed successfully. +* - XST_FAILURE: An error occurred. +* - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB). +* - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available. +* +******************************************************************************/ +static int XUsbPs_EpQueueRequest(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen, u8 ReqZero) +{ + int Status; + u32 Token; + XUsbPs_EpIn *Ep; + XUsbPs_dTD *DescPtr; + u32 Length; + u32 EpType; + u32 Multo = 0; + u32 PipeEmpty = 1; + u32 Mask = 0x00010000; + u32 BitMask = Mask << EpNum; + u32 RegValue; + u32 Temp; + u32 exit = 1; + + + /* Locate the next available buffer in the ring. A buffer is available + * if its descriptor is not active. + */ + Ep = &InstancePtr->DeviceConfig.Ep[EpNum].In; + EpType = InstancePtr->DeviceConfig.EpCfg[EpNum].In.Type; + + Xil_DCacheFlushRange((unsigned int)BufferPtr, BufferLen); + + if(Ep->dTDTail != Ep->dTDHead) { + PipeEmpty = 0; + } + XUsbPs_dTDInvalidateCache(Ep->dTDHead); + + /* Tell the caller if we do not have any descriptors available. */ + if (XUsbPs_dTDIsActive(Ep->dTDHead)) { + return XST_USB_NO_DESC_AVAILABLE; + } + + /* Remember the current head. */ + DescPtr = Ep->dTDHead; + + Ep->RequestedBytes = BufferLen; + Ep->BytesTxed = 0; + Ep->BufferPtr = (u8 *)BufferPtr; + + do { + + /* Tell the caller if we do not have any descriptors available. */ + if (XUsbPs_dTDIsActive(Ep->dTDHead)) { + return XST_USB_NO_DESC_AVAILABLE; + } + + Length = (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) ? XUSBPS_dTD_BUF_MAX_SIZE : BufferLen; + /* Attach the provided buffer to the current descriptor.*/ + Status = XUsbPs_dTDAttachBuffer(Ep->dTDHead, BufferPtr, Length); + if (XST_SUCCESS != Status) { + return XST_FAILURE; + } + BufferLen -= Length; + BufferPtr += Length; + Ep->BytesTxed += Length; + + if (EpType == XUSBPS_EP_TYPE_ISOCHRONOUS) { + Multo = BufferLen / + InstancePtr-> + DeviceConfig.EpCfg[EpNum].Out.MaxPacketSize; + if (BufferLen == 0 || + (BufferLen % + InstancePtr-> + DeviceConfig.EpCfg[EpNum]. + Out.MaxPacketSize)) + Multo++; + + XUsbPs_dTDSetMultO(Ep->dTDHead, (Multo << 10)); + } + + XUsbPs_dTDSetActive(Ep->dTDHead); + if (BufferLen == 0 && (ReqZero == FALSE)) { + XUsbPs_dTDSetIOC(Ep->dTDHead); + exit = 0; + } + XUsbPs_dTDClrTerminate(Ep->dTDHead); + XUsbPs_dTDFlushCache(Ep->dTDHead); + + /* Advance the head descriptor pointer to the next descriptor. */ + Ep->dTDHead = XUsbPs_dTDGetNLP(Ep->dTDHead); + /* Terminate the next descriptor and flush the cache.*/ + XUsbPs_dTDInvalidateCache(Ep->dTDHead); + + if (ReqZero && BufferLen == 0) { + ReqZero = FALSE; + } + + } while(BufferLen || exit); + + XUsbPs_dTDSetTerminate(Ep->dTDHead); + XUsbPs_dTDFlushCache(Ep->dTDHead); + + if(!PipeEmpty) { + /* Read the endpoint prime register. */ + RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPPRIME_OFFSET); + if(RegValue & BitMask) { + return XST_SUCCESS; + } + + do { + RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET); + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET, + RegValue | XUSBPS_CMD_ATDTW_MASK); + Temp = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPRDY_OFFSET) + & BitMask; + } while(!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) & + XUSBPS_CMD_ATDTW_MASK)); + + RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET); + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET, + RegValue & ~XUSBPS_CMD_ATDTW_MASK); + + if(Temp) { + return XST_SUCCESS; + } + } + + /* Check, if the DMA engine is still running. If it is running, we do + * not clear Queue Head fields. + * + * Same cache rule as for the Transfer Descriptor applies for the Queue + * Head. + */ + XUsbPs_dQHInvalidateCache(Ep->dQH); + /* Add the dTD to the dQH */ + XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDNLP, DescPtr); + Token = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHdTDTOKEN); + Token &= ~(XUSBPS_dTDTOKEN_ACTIVE_MASK | XUSBPS_dTDTOKEN_HALT_MASK); + XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDTOKEN, Token); + + XUsbPs_dQHFlushCache(Ep->dQH); + + Status = XUsbPs_EpPrime(InstancePtr, EpNum, XUSBPS_EP_DIRECTION_IN); + + return Status; +} + +/*****************************************************************************/ +/** + * This function receives a data buffer from the endpoint of the given endpoint + * number and pass it to the application. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * @param EpNum is the number of the endpoint to receive data from. + * @param BufferLen is holding the buffer length. + * + * @return None. + * + * @note None. + * + ******************************************************************************/ +void XUsbPs_EpGetData(XUsbPs *InstancePtr, u8 EpNum, u32 BufferLen) +{ + XUsbPs_EpOut *Ep; + XUsbPs_EpSetup *EpSetup; + u8 *DataBuff; + u32 Handle; + u32 length = 0; + u32 InavalidateLen = 0; + + /* The buffer is not active which means that it has been processed by + * the DMA engine and contains valid data. + */ + Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out; + EpSetup = &InstancePtr->DeviceConfig.EpCfg[EpNum].Out; + + /* Use the buffer pointer stored in the "user data" field of the + * Transfer Descriptor. + */ + + do { + XUsbPs_dTDInvalidateCache(Ep->dTDCurr); + + DataBuff = (u8 *) XUsbPs_ReaddTD(Ep->dTDCurr, + XUSBPS_dTDUSERDATA); + + length = EpSetup->BufSize - + XUsbPs_dTDGetTransferLen(Ep->dTDCurr); + + if (length > 0) { + BufferLen = length; + } else { + BufferLen = 0; + } + + /* Invalidate the Buffer Pointer */ + InavalidateLen = BufferLen; + if (BufferLen % 32) { + InavalidateLen = (BufferLen/32) * 32 + 32; + } + + Xil_DCacheInvalidateRange((unsigned int)DataBuff, + InavalidateLen); + + memcpy(Ep->BufferPtr, DataBuff, BufferLen); + + Ep->BytesTxed += BufferLen; + Ep->BufferPtr += BufferLen; + + Handle = (u32) Ep->dTDCurr; + + /* Reset the descriptor's BufferPointer0 and Transfer Length + * fields to their original value. Note that we can not yet + * re-activate the descriptor as the caller will be using the + * attached buffer. Once the caller releases the buffer by + * calling XUsbPs_EpBufferRelease(), + * we can re-activate the descriptor. + */ + XUsbPs_WritedTD(Ep->dTDCurr, XUSBPS_dTDBPTR0, DataBuff); + XUsbPs_dTDSetTransferLen(Ep->dTDCurr, EpSetup->BufSize); + + XUsbPs_dTDFlushCache(Ep->dTDCurr); + + XUsbPs_EpBufferRelease(Handle); + + Ep->dTDCurr = XUsbPs_dTDGetNLP(Ep->dTDCurr); + XUsbPs_dTDInvalidateCache(Ep->dTDCurr); + + /* Either Host sent exact requested length or more than that + * or lesser data. + */ + if ((Ep->RequestedBytes <= Ep->BytesTxed) || + (Ep->BytesTxed % EpSetup->MaxPacketSize)) { + Ep->MemAlloted = 0; + if (Ep->HandlerIsoFunc) { + Ep->HandlerIsoFunc(Ep->HandlerRef, + Ep->RequestedBytes, + Ep->BytesTxed); + } + + break; + } + } while (!XUsbPs_dTDIsActive(Ep->dTDCurr)); + +} + +/*****************************************************************************/ +/** + * This function receives a data buffer from the endpoint of the given endpoint + * number. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * @param EpNum is the number of the endpoint to receive data from. + * @param BufferPtr (OUT param) is a pointer to the buffer pointer to hold + * the reference of the data buffer. + * @param BufferLenPtr (OUT param) is a pointer to the integer that will + * hold the buffer length. + * @param Handle is the opaque handle to be used when the buffer is + * released. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occurred. + * - XST_USB_NO_BUF: No buffer available. + * + * @note + * After handling the data in the buffer, the user MUST release + * the buffer using the Handle by calling the + * XUsbPs_EpBufferRelease() function. + * + ******************************************************************************/ +int XUsbPs_EpBufferReceive(XUsbPs *InstancePtr, u8 EpNum, + u8 **BufferPtr, u32 *BufferLenPtr, u32 *Handle) +{ + XUsbPs_EpOut *Ep; + XUsbPs_EpSetup *EpSetup; + u32 length = 0; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferPtr != NULL); + Xil_AssertNonvoid(BufferLenPtr != NULL); + Xil_AssertNonvoid(Handle != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + /* Locate the next available buffer in the ring. A buffer is available + * if its descriptor is not active. + */ + Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out; + + XUsbPs_dTDInvalidateCache(Ep->dTDCurr); + + if (XUsbPs_dTDIsActive(Ep->dTDCurr)) { + return XST_USB_NO_BUF; + } + + /* The buffer is not active which means that it has been processed by + * the DMA engine and contains valid data. + */ + EpSetup = &InstancePtr->DeviceConfig.EpCfg[EpNum].Out; + + + /* Use the buffer pointer stored in the "user data" field of the + * Transfer Descriptor. + */ + *BufferPtr = (u8 *) XUsbPs_ReaddTD(Ep->dTDCurr, + XUSBPS_dTDUSERDATA); + + length = EpSetup->BufSize - + XUsbPs_dTDGetTransferLen(Ep->dTDCurr); + + if(length > 0) { + *BufferLenPtr = length; + }else { + *BufferLenPtr = 0; + } + + *Handle = (u32) Ep->dTDCurr; + + + /* Reset the descriptor's BufferPointer0 and Transfer Length fields to + * their original value. Note that we can not yet re-activate the + * descriptor as the caller will be using the attached buffer. Once the + * caller releases the buffer by calling XUsbPs_EpBufferRelease(), we + * can re-activate the descriptor. + */ + XUsbPs_WritedTD(Ep->dTDCurr, XUSBPS_dTDBPTR0, *BufferPtr); + XUsbPs_dTDSetTransferLen(Ep->dTDCurr, EpSetup->BufSize); + + XUsbPs_dTDFlushCache(Ep->dTDCurr); + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* This function returns a previously received data buffer to the driver. +* +* @param Handle is a pointer to the buffer that is returned. +* +* @return None. +* +******************************************************************************/ +void XUsbPs_EpBufferRelease(u32 Handle) +{ + XUsbPs_dTD *dTDPtr; + + /* Perform sanity check on Handle.*/ + Xil_AssertVoid((0 != Handle) && (0 == (Handle % XUSBPS_dTD_ALIGN))); + + /* Activate the descriptor and clear the Terminate bit. Make sure to do + * the proper cache handling. + */ + dTDPtr = (XUsbPs_dTD *) Handle; + + XUsbPs_dTDInvalidateCache(dTDPtr); + + XUsbPs_dTDClrTerminate(dTDPtr); + XUsbPs_dTDSetActive(dTDPtr); + XUsbPs_dTDSetIOC(dTDPtr); + + XUsbPs_dTDFlushCache(dTDPtr); + +} + +/*****************************************************************************/ +/** + * This function receives a data buffer from the endpoint of the given endpoint + * number. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * @param EpNum is the number of the endpoint to receive data from. + * @param BufferPtr (OUT param) is a pointer to the buffer pointer to hold + * the reference of the data buffer. + * @param BufferLen (OUT param) is a pointer to the integer that will + * hold the buffer length. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occurred. + * - XST_USB_NO_BUF: No buffer available. + * + * @note + * + ******************************************************************************/ +s32 XUsbPs_EpDataBufferReceive(XUsbPs *InstancePtr, u8 EpNum, + u8 *BufferPtr, u32 BufferLen) +{ + XUsbPs_EpOut *Ep; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferPtr != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out; + + Ep->RequestedBytes = BufferLen; + Ep->BytesTxed = 0; + Ep->BufferPtr = BufferPtr; + Ep->MemAlloted = 1; + + XUsbPs_dTDInvalidateCache(Ep->dTDCurr); + + /* Locate the next available buffer in the ring. A buffer is available + * if its descriptor is not active. + */ + if (XUsbPs_dTDIsActive(Ep->dTDCurr)) { + return XST_USB_NO_BUF; + } + XUsbPs_EpGetData(InstancePtr, EpNum, BufferLen); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * This function sets the handler for endpoint events. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * @param EpNum is the number of the endpoint to receive data from. + * @param Direction is the direction of the endpoint (bitfield): + * - XUSBPS_EP_DIRECTION_OUT + * - XUSBPS_EP_DIRECTION_IN + * @param CallBackFunc is the Handler callback function. + * Can be NULL if the user wants to disable the handler entry. + * @param CallBackRef is the user definable data pointer that will be + * passed back if the handler is called. May be NULL. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occurred. + * - XST_INVALID_PARAM: Invalid parameter passed. + * + * @note + * The user can disable a handler by setting the callback function + * pointer to NULL. + * + ******************************************************************************/ +int XUsbPs_EpSetHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction, + XUsbPs_EpHandlerFunc CallBackFunc, + void *CallBackRef) +{ + XUsbPs_Endpoint *Ep; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CallBackFunc != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + Ep = &InstancePtr->DeviceConfig.Ep[EpNum]; + + if(Direction & XUSBPS_EP_DIRECTION_OUT) { + Ep->Out.HandlerFunc = CallBackFunc; + Ep->Out.HandlerRef = CallBackRef; + } + + if(Direction & XUSBPS_EP_DIRECTION_IN) { + Ep->In.HandlerFunc = CallBackFunc; + Ep->In.HandlerRef = CallBackRef; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * This function sets the handler for ISO endpoint events. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * @param EpNum is the number of the endpoint to receive data from. + * @param Direction is the direction of the endpoint (bitfield): + * - XUSBPS_EP_DIRECTION_OUT + * - XUSBPS_EP_DIRECTION_IN + * @param CallBackFunc is the Handler callback function. + * Can be NULL if the user wants to disable the handler entry. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occurred. + * - XST_INVALID_PARAM: Invalid parameter passed. + * + * @note + * The user can disable a handler by setting the callback function + * pointer to NULL. + * + ******************************************************************************/ +s32 XUsbPs_EpSetIsoHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction, + XUsbPs_EpIsoHandlerFunc CallBackFunc) +{ + XUsbPs_Endpoint *Ep; + void *CallBackRef = (void *) InstancePtr->AppData; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CallBackFunc != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + Ep = &InstancePtr->DeviceConfig.Ep[EpNum]; + + if (Direction & XUSBPS_EP_DIRECTION_OUT) { + Ep->Out.HandlerIsoFunc = CallBackFunc; + Ep->Out.HandlerRef = CallBackRef; + } + + if (Direction & XUSBPS_EP_DIRECTION_IN) { + Ep->In.HandlerIsoFunc = CallBackFunc; + Ep->In.HandlerRef = CallBackRef; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function primes an endpoint. +* +* @param InstancePtr is pointer to the XUsbPs instance. +* @param EpNum is the number of the endpoint to receive data from. +* @param Direction is the direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @return +* - XST_SUCCESS: The operation completed successfully. +* - XST_FAILURE: An error occurred. +* - XST_INVALID_PARAM: Invalid parameter passed. +* +* @note None. +* +******************************************************************************/ +int XUsbPs_EpPrime(XUsbPs *InstancePtr, u8 EpNum, u8 Direction) +{ + u32 Mask; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + /* Get the right bit mask for the endpoint direction. */ + switch (Direction) { + + case XUSBPS_EP_DIRECTION_OUT: + Mask = 0x00000001; + break; + + case XUSBPS_EP_DIRECTION_IN: + Mask = 0x00010000; + break; + + default: + return XST_INVALID_PARAM; + } + + /* Write the endpoint prime register. */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPPRIME_OFFSET, Mask << EpNum); + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* This function extracts the Setup Data from a given endpoint. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is the number of the endpoint to receive data from. +* @param SetupDataPtr is a pointer to the setup data structure to be +* filled. +* +* @return +* - XST_SUCCESS: The operation completed successfully. +* - XST_FAILURE: An error occurred. +* +* @note None. +******************************************************************************/ +int XUsbPs_EpGetSetupData(XUsbPs *InstancePtr, int EpNum, + XUsbPs_SetupData *SetupDataPtr) +{ + XUsbPs_EpOut *Ep; + + u32 Data[2]; + u8 *p; + + int Timeout; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SetupDataPtr != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out; + + + /* Get the data from the Queue Heads Setup buffer into local variables + * so we can extract the setup data values. + */ + do { + /* Arm the tripwire. The tripwire will tell us if a new setup + * packet arrived (in which case the tripwire bit will be + * cleared) while we were reading the buffer. If a new setup + * packet arrived the buffer is corrupted and we continue + * reading. + */ + XUsbPs_SetSetupTripwire(InstancePtr); + + XUsbPs_dQHInvalidateCache(Ep->dQH); + + Data[0] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB0); + Data[1] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB1); + } while (FALSE == XUsbPs_SetupTripwireIsSet(InstancePtr)); + + /* Clear the pending endpoint setup stat bit. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPSTAT_OFFSET, 1 << EpNum); + + /* Clear the Tripwire bit and continue. + */ + XUsbPs_ClrSetupTripwire(InstancePtr); + + + /* Data in the setup buffer is being converted by the core to big + * endian format. We have to take care of proper byte swapping when + * reading the setup data values. + * + * Need to check if there is a smarter way to do this and take the + * processor/memory-controller endianness into account? + */ + p = (u8 *) Data; + + SetupDataPtr->bmRequestType = p[0]; + SetupDataPtr->bRequest = p[1]; + SetupDataPtr->wValue = (p[3] << 8) | p[2]; + SetupDataPtr->wIndex = (p[5] << 8) | p[4]; + SetupDataPtr->wLength = (p[7] << 8) | p[6]; + + /* Before we leave we need to make sure that the endpoint setup bit has + * cleared. It needs to be 0 before the endpoint can be re-primed. + * + * Note: According to the documentation this endpoint setup bit should + * clear within 1-2us after it has been written above. This means that + * we should never catch it being 1 here. However, we still need to + * poll it to make sure. Just in case, we use a counter 'Timeout' so we + * won't hang here if the bit is stuck for some reason. + */ + Timeout = XUSBPS_TIMEOUT_COUNTER; + while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPSTAT_OFFSET) & + (1 << EpNum)) && --Timeout) { + /* NOP */ + } + if (0 == Timeout) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* +* This function initializes the endpoint pointer data structure. +* +* The function sets up the local data structure with the aligned addresses for +* the Queue Head and Transfer Descriptors. +* +* @param DevCfgPtr is pointer to the XUsbPs DEVICE configuration +* structure. +* +* @return none +* +* @note +* Endpoints of type XUSBPS_EP_TYPE_NONE are not used in the +* system. Therefore no memory is reserved for them. +* +******************************************************************************/ +static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr) +{ + int EpNum; + u8 *p; + + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + + /* Set up the XUsbPs_Endpoint array. This array is used to define the + * location of the Queue Head list and the Transfer Descriptors in the + * block of DMA memory that has been passed into the driver. + * + * 'p' is used to set the pointers in the local data structure. + * Initially 'p' is pointed to the beginning of the DMAable memory + * block. As pointers are assigned, 'p' is incremented by the size of + * the respective object. + */ + Ep = DevCfgPtr->Ep; + EpCfg = DevCfgPtr->EpCfg; + + /* Start off with 'p' pointing to the (aligned) beginning of the DMA + * buffer. + */ + p = (u8 *) DevCfgPtr->PhysAligned; + + + /* Initialize the Queue Head pointer list. + * + * Each endpoint has two Queue Heads. One for the OUT direction and one + * for the IN direction. An OUT Queue Head is always followed by an IN + * Queue Head. + * + * Queue Head alignment is XUSBPS_dQH_ALIGN. + * + * Note that we have to reserve space here for unused endpoints. + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + /* OUT Queue Head */ + Ep[EpNum].Out.dQH = (XUsbPs_dQH *) p; + p += XUSBPS_dQH_ALIGN; + + /* IN Queue Head */ + Ep[EpNum].In.dQH = (XUsbPs_dQH *) p; + p += XUSBPS_dQH_ALIGN; + } + + + /* 'p' now points to the first address after the Queue Head list. The + * Transfer Descriptors start here. + * + * Each endpoint has a variable number of Transfer Descriptors + * depending on user configuration. + * + * Transfer Descriptor alignment is XUSBPS_dTD_ALIGN. + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + /* OUT Descriptors. + */ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) { + Ep[EpNum].Out.dTDs = (XUsbPs_dTD *) p; + Ep[EpNum].Out.dTDCurr = (XUsbPs_dTD *) p; + p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs; + } + + /* IN Descriptors. + */ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) { + Ep[EpNum].In.dTDs = (XUsbPs_dTD *) p; + Ep[EpNum].In.dTDHead = (XUsbPs_dTD *) p; + Ep[EpNum].In.dTDTail = (XUsbPs_dTD *) p; + p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].In.NumBufs; + } + } + + + /* 'p' now points to the first address after the Transfer Descriptors. + * The data buffers for the OUT Transfer Descriptors start here. + * + * Note that IN (TX) Transfer Descriptors are not assigned buffers at + * this point. Buffers will be assigned when the user calls the send() + * function. + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) { + /* If BufSize for this endpoint is set to 0 it means + * that we do not need to attach a buffer to this + * descriptor. We also initialize it's buffer pointer + * to NULL. + */ + if (0 == EpCfg[EpNum].Out.BufSize) { + Ep[EpNum].Out.dTDBufs = NULL; + continue; + } + + Ep[EpNum].Out.dTDBufs = p; + p += EpCfg[EpNum].Out.BufSize * EpCfg[EpNum].Out.NumBufs; + } + } + + + /* Initialize the endpoint event handlers to NULL. + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + Ep[EpNum].Out.HandlerFunc = NULL; + Ep[EpNum].In.HandlerFunc = NULL; + Ep[EpNum].Out.HandlerIsoFunc = NULL; + Ep[EpNum].In.HandlerIsoFunc = NULL; + } +} + + +/*****************************************************************************/ +/** +* +* This function initializes the Queue Head List in memory. +* +* @param DevCfgPtr is a pointer to the XUsbPs DEVICE configuration +* structure. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr) +{ + int EpNum; + + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + + /* Setup pointers for simpler access. */ + Ep = DevCfgPtr->Ep; + EpCfg = DevCfgPtr->EpCfg; + + + /* Go through the list of Queue Head entries and: + * + * - Set Transfer Descriptor addresses + * - Set Maximum Packet Size + * - Disable Zero Length Termination (ZLT) for non-isochronous transfers + * - Enable Interrupt On Setup (IOS) + * + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + + /* OUT Queue Heads.*/ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) { + XUsbPs_WritedQH(Ep[EpNum].Out.dQH, + XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs); + + /* For isochronous, ep max packet size translates to different + * values in queue head than other types. + * Also enable ZLT for isochronous. + */ + if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].Out.Type) { + XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].Out.dQH, + EpCfg[EpNum].Out.MaxPacketSize); + XUsbPs_dQHEnableZLT(Ep[EpNum].Out.dQH); + }else { + XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH, + EpCfg[EpNum].Out.MaxPacketSize); + XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH); + } + + /* Only control OUT needs this */ + if(XUSBPS_EP_TYPE_CONTROL == EpCfg[EpNum].Out.Type) { + XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH); + } + + /* Set up the overlay next dTD pointer. */ + XUsbPs_WritedQH(Ep[EpNum].Out.dQH, + XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs); + + XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH); + } + + + /* IN Queue Heads. */ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) { + XUsbPs_WritedQH(Ep[EpNum].In.dQH, + XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs); + + + /* Isochronous ep packet size can be larger than 1024.*/ + if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].In.Type) { + XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].In.dQH, + EpCfg[EpNum].In.MaxPacketSize); + XUsbPs_dQHEnableZLT(Ep[EpNum].In.dQH); + }else { + XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH, + EpCfg[EpNum].In.MaxPacketSize); + XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH); + } + + XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH); + } + } +} + + +/*****************************************************************************/ +/** + * + * This function initializes the Transfer Descriptors lists in memory. + * + * @param DevCfgPtr is a pointer to the XUsbPs DEVICE configuration + * structure. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occurred. + * + ******************************************************************************/ +static int XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr) +{ + int EpNum; + + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + + /* Setup pointers for simpler access. */ + Ep = DevCfgPtr->Ep; + EpCfg = DevCfgPtr->EpCfg; + + + /* Walk through the list of endpoints and initialize their Transfer + * Descriptors. + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + int Td; + int NumdTD; + + XUsbPs_EpOut *Out = &Ep[EpNum].Out; + XUsbPs_EpIn *In = &Ep[EpNum].In; + + + /* OUT Descriptors + * =============== + * + * + Set the next link pointer + * + Set the interrupt complete and the active bit + * + Attach the buffer to the dTD + */ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) { + NumdTD = EpCfg[EpNum].Out.NumBufs; + } + else { + NumdTD = 0; + } + + for (Td = 0; Td < NumdTD; ++Td) { + int Status; + + int NextTd = (Td + 1) % NumdTD; + + XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]); + + /* Set NEXT link pointer. */ + XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP, + &Out->dTDs[NextTd]); + + /* Set the OUT descriptor ACTIVE and enable the + * interrupt on complete. + */ + XUsbPs_dTDSetActive(&Out->dTDs[Td]); + XUsbPs_dTDSetIOC(&Out->dTDs[Td]); + + + /* Set up the data buffer with the descriptor. If the + * buffer pointer is NULL it means that we do not need + * to attach a buffer to this descriptor. + */ + if (NULL == Out->dTDBufs) { + XUsbPs_dTDFlushCache(&Out->dTDs[Td]); + continue; + } + + Status = XUsbPs_dTDAttachBuffer( + &Out->dTDs[Td], + Out->dTDBufs + + (Td * EpCfg[EpNum].Out.BufSize), + EpCfg[EpNum].Out.BufSize); + if (XST_SUCCESS != Status) { + return XST_FAILURE; + } + + XUsbPs_dTDFlushCache(&Out->dTDs[Td]); + } + + + /* IN Descriptors + * ============== + * + * + Set the next link pointer + * + Set the Terminate bit to mark it available + */ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) { + NumdTD = EpCfg[EpNum].In.NumBufs; + } + else { + NumdTD = 0; + } + + for (Td = 0; Td < NumdTD; ++Td) { + int NextTd = (Td + 1) % NumdTD; + + XUsbPs_dTDInvalidateCache(&In->dTDs[Td]); + + /* Set NEXT link pointer. */ + XUsbPs_WritedTD(In->dTDs[Td], XUSBPS_dTDNLP, + In->dTDs[NextTd]); + + /* Set the IN descriptor's TERMINATE bits. */ + XUsbPs_dTDSetTerminate(In->dTDs[Td]); + + XUsbPs_dTDFlushCache(&In->dTDs[Td]); + } + } + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** + * + * This function associates a buffer with a Transfer Descriptor. The function + * will take care of splitting the buffer into multiple 4kB aligned segments if + * the buffer happens to span one or more 4kB pages. + * + * @param dTDIndex is a pointer to the Transfer Descriptor + * @param BufferPtr is pointer to the buffer to link to the descriptor. + * @param BufferLen is the length of the buffer. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occurred. + * - XST_USB_BUF_TOO_BIG: The provided buffer is bigger than tha + * maximum allowed buffer size (16k). + * + * @note + * Cache invalidation and flushing needs to be handler by the + * caller of this function. + * + ******************************************************************************/ +static int XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr, + const u8 *BufferPtr, u32 BufferLen) +{ + u32 BufAddr; + u32 BufEnd; + u32 PtrNum; + + Xil_AssertNonvoid(dTDPtr != NULL); + + /* Check if the buffer is smaller than 16kB. */ + if (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) { + return XST_USB_BUF_TOO_BIG; + } + + /* Get a u32 of the buffer pointer to avoid casting in the following + * logic operations. + */ + BufAddr = (u32) BufferPtr; + + + /* Set the buffer pointer 0. Buffer pointer 0 can point to any location + * in memory. It does not need to be 4kB aligned. However, if the + * provided buffer spans one or more 4kB boundaries, we need to set up + * the subsequent buffer pointers which must be 4kB aligned. + */ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(0), BufAddr); + + /* Check if the buffer spans a 4kB boundary. + * + * Only do this check, if we are not sending a 0-length buffer. + */ + if (BufferLen > 0) { + BufEnd = BufAddr + BufferLen -1; + PtrNum = 1; + + while ((BufAddr & 0xFFFFF000) != (BufEnd & 0xFFFFF000)) { + /* The buffer spans at least one boundary, let's set + * the next buffer pointer and repeat the procedure + * until the end of the buffer and the pointer written + * are in the same 4kB page. + */ + BufAddr = (BufAddr + 0x1000) & 0xFFFFF000; + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(PtrNum), + BufAddr); + PtrNum++; + } + } + + /* Set the length of the buffer. */ + XUsbPs_dTDSetTransferLen(dTDPtr, BufferLen); + + + /* We remember the buffer pointer in the user data field (reserved + * field in the dTD). This makes it easier to reset the buffer pointer + * after a buffer has been received on the endpoint. The buffer pointer + * needs to be reset because the DMA engine modifies the buffer pointer + * while receiving. + */ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDUSERDATA, BufferPtr); + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** + * This function set the Max PacketLen for the queue head for isochronous EP. + * + * If the max packet length is greater than XUSBPS_MAX_PACKET_SIZE, then + * Mult bits are set to reflect that. + * + * @param dQHPtr is a pointer to the dQH element. + * @param Len is the Length to be set. + * + ******************************************************************************/ +static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len) +{ + u32 Mult = (Len & ENDPOINT_MAXP_MULT_MASK) >> ENDPOINT_MAXP_MULT_SHIFT; + u32 MaxPktSize = (Mult > 1) ? ENDPOINT_MAXP_LENGTH : Len; + + if (MaxPktSize > XUSBPS_MAX_PACKET_SIZE) { + return; + } + + if (Mult > 3) { + return; + } + + /* Set Max packet size */ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, + (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & + ~XUSBPS_dQHCFG_MPL_MASK) | + (MaxPktSize << XUSBPS_dQHCFG_MPL_SHIFT)); + + /* Set Mult to tell hardware how many transactions in each microframe */ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, + (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & + ~XUSBPS_dQHCFG_MULT_MASK) | + (Mult << XUSBPS_dQHCFG_MULT_SHIFT)); + +} + +/*****************************************************************************/ +/** +* This function reconfigures one Ep corresponding to host's request of setting +* alternate interface. The endpoint has been disabled before this call. +* +* Both QH and dTDs are updated for the new configuration. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param CfgPtr +* Pointer to the updated XUsbPs DEVICE configuration structure. +* +* @param EpNum +* The endpoint to be reconfigured. +* +* @param NewDirection +* The new transfer direction the endpoint. +* +* @param DirectionChanged +* A boolean value indicate whether the transfer direction has changed. +* +* @return +* XST_SUCCESS upon success, XST_FAILURE otherwise. +* +******************************************************************************/ +int XUsbPs_ReconfigureEp(XUsbPs *InstancePtr, XUsbPs_DeviceConfig *CfgPtr, + int EpNum, unsigned short NewDirection, + int DirectionChanged) { + + int Status = XST_SUCCESS; + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + + Ep = CfgPtr->Ep; + EpCfg = CfgPtr->EpCfg; + + /* If transfer direction changes, dTDs has to be reset + * Number of buffers are preset and should not to be changed. + */ + if(DirectionChanged) { + if(NewDirection == XUSBPS_EP_DIRECTION_OUT) { + u8 *p; + + /* Swap the pointer to the dTDs. + */ + Ep[EpNum].Out.dTDs = Ep[EpNum].In.dTDs; + p = (u8 *)(Ep[EpNum].Out.dTDs + XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs); + + /* Set the OUT buffer if buffer size is not zero + */ + if(EpCfg[EpNum].Out.BufSize > 0) { + Ep[EpNum].Out.dTDBufs = p; + } + } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) { + Ep[EpNum].In.dTDs = Ep[EpNum].Out.dTDs; + } + } + + /* Reset dTD progress tracking pointers + */ + if(NewDirection == XUSBPS_EP_DIRECTION_IN) { + Ep[EpNum].In.dTDHead = Ep[EpNum].In.dTDTail = Ep[EpNum].In.dTDs; + } else if(NewDirection == XUSBPS_EP_DIRECTION_OUT) { + Ep[EpNum].Out.dTDCurr = Ep[EpNum].Out.dTDs; + } + + /* Reinitialize information in QH + */ + XUsbPs_dQHReinitEp(CfgPtr, EpNum, NewDirection); + + /* Reinitialize the dTD linked list, and flush the cache + */ + Status = XUsbPs_dTDReinitEp(CfgPtr, EpNum, NewDirection); + if(Status != XST_SUCCESS) { + return Status; + } + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** + * This function re-initializes the Queue Head List in memory. + * The endpoint 1 has been disabled before this call. + * + * @param DevCfgPtr + * Pointer to the updated XUsbPs DEVICE configuration structure. + * + * @param EpNum + * The endpoint to be reconfigured. + * + * @param NewDirection + * The new transfer direction of endpoint 1 + * + * @return none + * + ******************************************************************************/ +static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr, +int EpNum, unsigned short NewDirection) +{ + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + + /* Setup pointers for simpler access. + */ + Ep = DevCfgPtr->Ep; + EpCfg = DevCfgPtr->EpCfg; + + + /* Go through the list of Queue Head entries and: + * + * - Set Transfer Descriptor addresses + * - Set Maximum Packet Size + * - Disable Zero Length Termination (ZLT) for non-isochronous transfers + * - Enable Interrupt On Setup (IOS) + * + */ + if(NewDirection == XUSBPS_EP_DIRECTION_OUT) { + /* OUT Queue Heads. + */ + XUsbPs_WritedQH(Ep[EpNum].Out.dQH, + XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs); + + /* For isochronous, ep max packet size translates to different + * values in queue head than other types. + * Also enable ZLT for isochronous. + */ + if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].Out.Type) { + XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].Out.dQH, + EpCfg[EpNum].Out.MaxPacketSize); + XUsbPs_dQHEnableZLT(Ep[EpNum].Out.dQH); + }else { + XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH, + EpCfg[EpNum].Out.MaxPacketSize); + XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH); + } + + XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH); + + /* Set up the overlay next dTD pointer. + */ + XUsbPs_WritedQH(Ep[EpNum].Out.dQH, + XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs); + + XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH); + + } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) { + + /* IN Queue Heads. + */ + XUsbPs_WritedQH(Ep[EpNum].In.dQH, + XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs); + + /* Isochronous ep packet size can be larger than 1024. */ + if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].In.Type) { + XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].In.dQH, + EpCfg[EpNum].In.MaxPacketSize); + XUsbPs_dQHEnableZLT(Ep[EpNum].In.dQH); + }else { + XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH, + EpCfg[EpNum].In.MaxPacketSize); + XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH); + } + + XUsbPs_dQHSetIOS(Ep[EpNum].In.dQH); + + XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH); + } + +} + +/*****************************************************************************/ +/** + * + * This function re-initializes the Transfer Descriptors lists in memory. + * The endpoint has been disabled before the call. The transfer descriptors + * list pointer has been initialized too. + * + * @param DevCfgPtr + * Pointer to the XUsbPs DEVICE configuration structure. + * + * @param EpNum + * The endpoint to be reconfigured. + * + * @param NewDirection + * The new transfer direction of endpoint 1 + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occurred. + * + ******************************************************************************/ +static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr, +int EpNum, unsigned short NewDirection) +{ + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + int Td; + int NumdTD; + + + /* Setup pointers for simpler access. + */ + Ep = DevCfgPtr->Ep; + EpCfg = DevCfgPtr->EpCfg; + + + if(NewDirection == XUSBPS_EP_DIRECTION_OUT) { + XUsbPs_EpOut *Out = &Ep[EpNum].Out; + + /* OUT Descriptors + * =============== + * + * + Set the next link pointer + * + Set the interrupt complete and the active bit + * + Attach the buffer to the dTD + */ + NumdTD = EpCfg[EpNum].Out.NumBufs; + + for (Td = 0; Td < NumdTD; ++Td) { + int Status; + + int NextTd = (Td + 1) % NumdTD; + + XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]); + + /* Set NEXT link pointer. + */ + XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP, + &Out->dTDs[NextTd]); + + /* Set the OUT descriptor ACTIVE and enable the + * interrupt on complete. + */ + XUsbPs_dTDSetActive(&Out->dTDs[Td]); + XUsbPs_dTDSetIOC(&Out->dTDs[Td]); + + /* Set up the data buffer with the descriptor. If the + * buffer pointer is NULL it means that we do not need + * to attach a buffer to this descriptor. + */ + if (Out->dTDBufs != NULL) { + + Status = XUsbPs_dTDAttachBuffer( + &Out->dTDs[Td], + Out->dTDBufs + + (Td * EpCfg[EpNum].Out.BufSize), + EpCfg[EpNum].Out.BufSize); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + } + XUsbPs_dTDFlushCache(&Out->dTDs[Td]); + } + } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) { + XUsbPs_EpIn *In = &Ep[EpNum].In; + + /* IN Descriptors + * ============== + * + * + Set the next link pointer + * + Set the Terminate bit to mark it available + */ + NumdTD = EpCfg[EpNum].In.NumBufs; + + for (Td = 0; Td < NumdTD; ++Td) { + int NextTd = (Td + 1) % NumdTD; + + XUsbPs_dTDInvalidateCache(&In->dTDs[Td]); + + /* Set NEXT link pointer. + */ + XUsbPs_WritedTD(&In->dTDs[Td], XUSBPS_dTDNLP, + &In->dTDs[NextTd]); + + /* Set the IN descriptor's TERMINATE bits. + */ + XUsbPs_dTDSetTerminate(&In->dTDs[Td]); + + XUsbPs_dTDFlushCache(&In->dTDs[Td]); + } + } + + return XST_SUCCESS; +} + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_endpoint.h b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_endpoint.h new file mode 100644 index 0000000..b924726 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_endpoint.h @@ -0,0 +1,507 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xusbps_endpoint.h +* @addtogroup usbps_v2_7 +* @{ + * + * This is an internal file containung the definitions for endpoints. It is + * included by the xusbps_endpoint.c which is implementing the endpoint + * functions and by xusbps_intr.c. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- --------------------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 2.5   pm   02/20/20 Added multiplier bit for ISO frame handling.
+ * 
+ * + ******************************************************************************/ +#ifndef XUSBPS_ENDPOINT_H +#define XUSBPS_ENDPOINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_cache.h" +#include "xusbps.h" +#include "xil_types.h" + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + + +/** + * Endpoint Device Transfer Descriptor + * + * The dTD describes to the device controller the location and quantity of data + * to be sent/received for given transfer. The driver does not attempt to + * modify any field in an active dTD except the Next Link Pointer. + */ +#define XUSBPS_dTDNLP 0x00 /**< Pointer to the next descriptor */ +#define XUSBPS_dTDTOKEN 0x04 /**< Descriptor Token */ +#define XUSBPS_dTDBPTR0 0x08 /**< Buffer Pointer 0 */ +#define XUSBPS_dTDBPTR1 0x0C /**< Buffer Pointer 1 */ +#define XUSBPS_dTDBPTR2 0x10 /**< Buffer Pointer 2 */ +#define XUSBPS_dTDBPTR3 0x14 /**< Buffer Pointer 3 */ +#define XUSBPS_dTDBPTR4 0x18 /**< Buffer Pointer 4 */ +#define XUSBPS_dTDBPTR(n) (XUSBPS_dTDBPTR0 + (n) * 0x04) +#define XUSBPS_dTDRSRVD 0x1C /**< Reserved field */ + +/* We use the reserved field in the dTD to store user data. */ +#define XUSBPS_dTDUSERDATA XUSBPS_dTDRSRVD /**< Reserved field */ + + +/** @name dTD Next Link Pointer (dTDNLP) bit positions. + * @{ + */ +#define XUSBPS_dTDNLP_T_MASK 0x00000001 + /**< USB dTD Next Link Pointer Terminate Bit */ +#define XUSBPS_dTDNLP_ADDR_MASK 0xFFFFFFE0 + /**< USB dTD Next Link Pointer Address [31:5] */ +/* @} */ + + +/** @name dTD Token (dTDTOKEN) bit positions. + * @{ + */ +#define XUSBPS_dTDTOKEN_XERR_MASK 0x00000008 /**< dTD Transaction Error */ +#define XUSBPS_dTDTOKEN_BUFERR_MASK 0x00000020 /**< dTD Data Buffer Error */ +#define XUSBPS_dTDTOKEN_HALT_MASK 0x00000040 /**< dTD Halted Flag */ +#define XUSBPS_dTDTOKEN_ACTIVE_MASK 0x00000080 /**< dTD Active Bit */ +#define XUSBPS_dTDTOKEN_MULTO_MASK 0x00000C00 /**< Multiplier Override Field [1:0] */ +#define XUSBPS_dTDTOKEN_IOC_MASK 0x00008000 /**< Interrupt on Complete Bit */ +#define XUSBPS_dTDTOKEN_LEN_MASK 0x7FFF0000 /**< Transfer Length Field */ +/* @} */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * + * IMPORTANT NOTE: + * =============== + * + * Many of the following macros modify Device Queue Head (dQH) data structures + * and Device Transfer Descriptor (dTD) data structures. Those structures can + * potentially reside in CACHED memory. Therefore, it's the callers + * responsibility to ensure cache coherency by using provided + * + * XUsbPs_dQHInvalidateCache() + * XUsbPs_dQHFlushCache() + * XUsbPs_dTDInvalidateCache() + * XUsbPs_dTDFlushCache() + * + * function calls. + * + ******************************************************************************/ +#define XUsbPs_dTDInvalidateCache(dTDPtr) \ + Xil_DCacheInvalidateRange((unsigned int)dTDPtr, sizeof(XUsbPs_dTD)) + +#define XUsbPs_dTDFlushCache(dTDPtr) \ + Xil_DCacheFlushRange((unsigned int)dTDPtr, sizeof(XUsbPs_dTD)) + +#define XUsbPs_dQHInvalidateCache(dQHPtr) \ + Xil_DCacheInvalidateRange((unsigned int)dQHPtr, sizeof(XUsbPs_dQH)) + +#define XUsbPs_dQHFlushCache(dQHPtr) \ + Xil_DCacheFlushRange((unsigned int)dQHPtr, sizeof(XUsbPs_dQH)) + +/*****************************************************************************/ +/** + * + * This macro sets the Transfer Length for the given Transfer Descriptor. + * + * @param dTDPtr is pointer to the dTD element. + * @param Len is the length to be set. Range: 0..16384 + * + * @note C-style signature: + * void XUsbPs_dTDSetTransferLen(u32 dTDPtr, u32 Len) + * + ******************************************************************************/ +#define XUsbPs_dTDSetTransferLen(dTDPtr, Len) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDTOKEN, \ + (XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) & \ + ~XUSBPS_dTDTOKEN_LEN_MASK) | ((Len) << 16)) + + +/*****************************************************************************/ +/** + * + * This macro gets the Next Link pointer of the given Transfer Descriptor. + * + * @param dTDPtr is pointer to the dTD element. + * + * @return TransferLength field of the descriptor. + * + * @note C-style signature: + * u32 XUsbPs_dTDGetTransferLen(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDGetNLP(dTDPtr) \ + (XUsbPs_dTD *) ((XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP)\ + & XUSBPS_dTDNLP_ADDR_MASK)) + + +/*****************************************************************************/ +/** + * + * This macro sets the Next Link pointer of the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * @param NLP is the Next Link Pointer + * + * @note C-style signature: + * void XUsbPs_dTDSetTransferLen(u32 dTDPtr, u32 Len) + * + ******************************************************************************/ +#define XUsbPs_dTDSetNLP(dTDPtr, NLP) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDNLP, \ + (XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP) & \ + ~XUSBPS_dTDNLP_ADDR_MASK) | \ + ((NLP) & XUSBPS_dTDNLP_ADDR_MASK)) + + +/*****************************************************************************/ +/** + * + * This macro gets the Transfer Length for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @return TransferLength field of the descriptor. + * + * @note C-style signature: + * u32 XUsbPs_dTDGetTransferLen(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDGetTransferLen(dTDPtr) \ + (u32) ((XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) \ + & XUSBPS_dTDTOKEN_LEN_MASK) >> 16) + + +/*****************************************************************************/ +/** + * + * This macro sets the Interrupt On Complete (IOC) bit for the given Transfer + * Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDSetIOC(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDSetIOC(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDTOKEN, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) | \ + XUSBPS_dTDTOKEN_IOC_MASK) + + +/*****************************************************************************/ +/** + * + * This macro sets the Terminate bit for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDSetTerminate(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDSetTerminate(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDNLP, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP) | \ + XUSBPS_dTDNLP_T_MASK) + + +/*****************************************************************************/ +/** + * + * This macro clears the Terminate bit for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDClrTerminate(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDClrTerminate(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDNLP, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP) & \ + ~XUSBPS_dTDNLP_T_MASK) + + +/*****************************************************************************/ +/** + * + * This macro checks if the given descriptor is active. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @return + * - TRUE: The buffer is active. + * - FALSE: The buffer is not active. + * + * @note C-style signature: + * int XUsbPs_dTDIsActive(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDIsActive(dTDPtr) \ + ((XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) & \ + XUSBPS_dTDTOKEN_ACTIVE_MASK) ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * + * This macro sets the Active bit for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDSetActive(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDSetActive(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDTOKEN, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) | \ + XUSBPS_dTDTOKEN_ACTIVE_MASK) + +/*****************************************************************************/ +/** + * + * This macro sets the multiplier bit for the Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * @param val is the multiplier value. + * + * @note C-style signature: + * void XUsbPs_dTDSetMultO(u32 dTDPtr, u32 val) + * + ******************************************************************************/ +#define XUsbPs_dTDSetMultO(dTDPtr, val) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDTOKEN, \ + (XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) & \ + (~XUSBPS_dTDTOKEN_MULTO_MASK)) | val) + + +/*****************************************************************************/ +/** + * + * This macro reads the content of a field in a Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * @param Id is the field ID inside the dTD element to read. + * + * @note C-style signature: + * u32 XUsbPs_ReaddTD(u32 dTDPtr, u32 Id) + * + ******************************************************************************/ +#define XUsbPs_ReaddTD(dTDPtr, Id) (*(u32 *)((u32)(dTDPtr) + (u32)(Id))) + +/*****************************************************************************/ +/** + * + * This macro writes a value to a field in a Transfer Descriptor. + * + * @param dTDPtr is pointer to the dTD element. + * @param Id is the field ID inside the dTD element to read. + * @param Val is the value to write to the field. + * + * @note C-style signature: + * u32 XUsbPs_WritedTD(u32 dTDPtr, u32 Id, u32 Val) + * + ******************************************************************************/ +#define XUsbPs_WritedTD(dTDPtr, Id, Val) \ + (*(u32 *) ((u32)(dTDPtr) + (u32)(Id)) = (u32)(Val)) + + +/******************************************************************************/ +/** + * Endpoint Device Queue Head + * + * Device queue heads are arranged in an array in a continuous area of memory + * pointed to by the ENDPOINTLISTADDR pointer. The device controller will index + * into this array based upon the endpoint number received from the USB bus. + * All information necessary to respond to transactions for all primed + * transfers is contained in this list so the Device Controller can readily + * respond to incoming requests without having to traverse a linked list. + * + * The device Endpoint Queue Head (dQH) is where all transfers are managed. The + * dQH is a 48-byte data structure, but must be aligned on a 64-byte boundary. + * During priming of an endpoint, the dTD (device transfer descriptor) is + * copied into the overlay area of the dQH, which starts at the nextTD pointer + * DWord and continues through the end of the buffer pointers DWords. After a + * transfer is complete, the dTD status DWord is updated in the dTD pointed to + * by the currentTD pointer. While a packet is in progress, the overlay area of + * the dQH is used as a staging area for the dTD so that the Device Controller + * can access needed information with little minimal latency. + * + * @note + * Software must ensure that no interface data structure reachable by the + * Device Controller spans a 4K-page boundary. The first element of the + * Endpoint Queue Head List must be aligned on a 4K boundary. + */ +#define XUSBPS_dQHCFG 0x00 /**< dQH Configuration */ +#define XUSBPS_dQHCPTR 0x04 /**< dQH Current dTD Pointer */ +#define XUSBPS_dQHdTDNLP 0x08 /**< dTD Next Link Ptr in dQH + overlay */ +#define XUSBPS_dQHdTDTOKEN 0x0C /**< dTD Token in dQH overlay */ +#define XUSBPS_dQHSUB0 0x28 /**< USB dQH Setup Buffer 0 */ +#define XUSBPS_dQHSUB1 0x2C /**< USB dQH Setup Buffer 1 */ + + +/** @name dQH Configuration (dQHCFG) bit positions. + * @{ + */ +#define XUSBPS_dQHCFG_IOS_MASK 0x00008000 + /**< USB dQH Interrupt on Setup Bit */ +#define XUSBPS_dQHCFG_MPL_MASK 0x07FF0000 + /**< USB dQH Maximum Packet Length + * Field [10:0] */ +#define XUSBPS_dQHCFG_MPL_SHIFT 16 +#define XUSBPS_dQHCFG_ZLT_MASK 0x20000000 + /**< USB dQH Zero Length Termination + * Select Bit */ +#define XUSBPS_dQHCFG_MULT_MASK 0xC0000000 + /* USB dQH Number of Transactions Field + * [1:0] */ +#define XUSBPS_dQHCFG_MULT_SHIFT 30 +/* @} */ + + +/*****************************************************************************/ +/** + * + * This macro sets the Maximum Packet Length field of the give Queue Head. + * + * @param dQHPtr is a pointer to the dQH element. + * @param Len is the length to be set. + * + * @note C-style signature: + * void XUsbPs_dQHSetMaxPacketLen(u32 dQHPtr, u32 Len) + * + ******************************************************************************/ +#define XUsbPs_dQHSetMaxPacketLen(dQHPtr, Len) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & \ + ~XUSBPS_dQHCFG_MPL_MASK) | ((Len) << 16)) + +/*****************************************************************************/ +/** + * + * This macro sets the Interrupt On Setup (IOS) bit for an endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHSetIOS(u32 dQHPtr) + * + ******************************************************************************/ +#define XUsbPs_dQHSetIOS(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) | \ + XUSBPS_dQHCFG_IOS_MASK) + +/*****************************************************************************/ +/** + * + * This macro clears the Interrupt On Setup (IOS) bit for an endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHClrIOS(u32 dQHPtr) + * + ******************************************************************************/ +#define XUsbPs_dQHClrIOS(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & \ + ~XUSBPS_dQHCFG_IOS_MASK) + +/*****************************************************************************/ +/** + * + * This macro enables Zero Length Termination for the endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHEnableZLT(u32 dQHPtr) + * + * + ******************************************************************************/ +#define XUsbPs_dQHEnableZLT(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & \ + ~XUSBPS_dQHCFG_ZLT_MASK) + + +/*****************************************************************************/ +/** + * + * This macro disables Zero Length Termination for the endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHDisableZLT(u32 dQHPtr) + * + * + ******************************************************************************/ +#define XUsbPs_dQHDisableZLT(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) | \ + XUSBPS_dQHCFG_ZLT_MASK) + +/*****************************************************************************/ +/** + * + * This macro reads the content of a field in a Queue Head. + * + * @param dQHPtr is a pointer to the dQH element. + * @param Id is the Field ID inside the dQH element to read. + * + * @note C-style signature: + * u32 XUsbPs_ReaddQH(u32 dQHPtr, u32 Id) + * + ******************************************************************************/ +#define XUsbPs_ReaddQH(dQHPtr, Id) (*(u32 *)((u32)(dQHPtr) + (u32) (Id))) + +/*****************************************************************************/ +/** + * + * This macro writes a value to a field in a Queue Head. + * + * @param dQHPtr is a pointer to the dQH element. + * @param Id is the Field ID inside the dQH element to read. + * @param Val is the Value to write to the field. + * + * @note C-style signature: + * u32 XUsbPs_WritedQH(u32 dQHPtr, u32 Id, u32 Val) + * + ******************************************************************************/ +#define XUsbPs_WritedQH(dQHPtr, Id, Val) \ + (*(u32 *) ((u32)(dQHPtr) + (u32)(Id)) = (u32)(Val)) + + + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_ENDPOINT_H */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_g.c new file mode 100644 index 0000000..6f90f51 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_g.c @@ -0,0 +1,54 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** + * + * @file xusbps_g.c +* @addtogroup usbps_v2_7 +* @{ + * This file contains a configuration table where each entry is a configuration + * structure for an XUsbPs device in the system. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 2.00  hk   22/01/14 Added check to select second instance.
+ * 
+ * + *****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xusbps.h" +#include "xparameters.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +/** + * Each XUsbPs device in the system has an entry in this table. + */ + +XUsbPs_Config XUsbPs_ConfigTable[] = { + { + 0, + XPAR_XUSBPS_0_BASEADDR + }, +#ifdef XPAR_XUSBPS_1_BASEADDR + { + 1, + XPAR_XUSBPS_1_BASEADDR + } +#endif +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_hw.c b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_hw.c new file mode 100644 index 0000000..f06656a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_hw.c @@ -0,0 +1,96 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** + * + * @file xusbps_hw.c +* @addtogroup usbps_v2_7 +* @{ + * + * The implementation of the XUsbPs interface reset functionality + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.05a kpc  10/10/10 first version
+ * 
+ * + *****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xusbps.h" +#include "xparameters.h" + + +/************************** Constant Definitions ****************************/ +#define XUSBPS_RESET_TIMEOUT 0xFFFFF +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + + +/************************** Function Prototypes *****************************/ + + +/*****************************************************************************/ +/** +* This function perform the reset sequence to the given usbps interface by +* configuring the appropriate control bits in the usbps specific registers. +* the usbps reset sequence involves the below steps +* Disable the interrupts +* Clear the status registers +* Apply the reset command and wait for reset complete status +* Update the relevant control registers with reset values +* @param BaseAddress of the interface +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XUsbPs_ResetHw(u32 BaseAddress) +{ + u32 RegVal; + u32 Timeout = 0; + + /* Host and device mode */ + /* Disable the interrupts */ + XUsbPs_WriteReg(BaseAddress,XUSBPS_IER_OFFSET,0x0); + /* Clear the interuupt status */ + RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_ISR_OFFSET); + XUsbPs_WriteReg(BaseAddress,XUSBPS_ISR_OFFSET,RegVal); + + /* Perform the reset operation using USB CMD register */ + RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET); + RegVal = RegVal | XUSBPS_CMD_RST_MASK; + XUsbPs_WriteReg(BaseAddress,XUSBPS_CMD_OFFSET,RegVal); + RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET); + /* Wait till the reset operation returns success */ + /* + * FIX ME: right now no indication to the caller or user about + * timeout overflow + */ + while ((RegVal & XUSBPS_CMD_RST_MASK) && (Timeout < XUSBPS_RESET_TIMEOUT)) + { + RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET); + Timeout++; + } + /* Update periodic list base address register with reset value */ + XUsbPs_WriteReg(BaseAddress,XUSBPS_LISTBASE_OFFSET,0x0); + /* Update async/endpoint list base address register with reset value */ + XUsbPs_WriteReg(BaseAddress,XUSBPS_ASYNCLISTADDR_OFFSET,0x0); + +} + + + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_hw.h new file mode 100644 index 0000000..4f985dc --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_hw.h @@ -0,0 +1,505 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** + * + * @file xusbps_hw.h +* @addtogroup usbps_v2_7 +* @{ + * + * This header file contains identifiers and low-level driver functions (or + * macros) that can be used to access the device. High-level driver functions + * are defined in xusbps.h. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 1.04a nm   10/23/12 Fixed CR# 679106.
+ * 1.05a kpc  07/03/13 Added XUsbPs_ResetHw function prototype
+ * 2.00a kpc  04/03/14 Fixed CR#777764. Corrected max endpoint vale and masks 
+ * 2.5   pm   02/20/20 Added Endpoint Control Register bit positions for Rx & Tx
+ * 
+ * + ******************************************************************************/ +#ifndef XUSBPS_HW_H +#define XUSBPS_HW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + + +#define XUSBPS_REG_SPACING 4 + +/** @name Timer 0 Register offsets + * + * @{ + */ +#define XUSBPS_TIMER0_LD_OFFSET 0x00000080 +#define XUSBPS_TIMER0_CTL_OFFSET 0x00000084 +/* @} */ + +/** @name Timer Control Register bit mask + * + * @{ + */ +#define XUSBPS_TIMER_RUN_MASK 0x80000000 +#define XUSBPS_TIMER_STOP_MASK 0x80000000 +#define XUSBPS_TIMER_RESET_MASK 0x40000000 +#define XUSBPS_TIMER_REPEAT_MASK 0x01000000 +/* @} */ + +/** @name Timer Control Register bit mask + * + * @{ + */ +#define XUSBPS_TIMER_COUNTER_MASK 0x00FFFFFF +/* @} */ + +/** @name Device Hardware Parameters + * + * @{ + */ +#define XUSBPS_HWDEVICE_OFFSET 0x0000000C + +#define XUSBPS_EP_NUM_MASK 0x3E +#define XUSBPS_EP_NUM_SHIFT 1 +/* @} */ + +/** @name Capability Register offsets + */ +#define XUSBPS_HCSPARAMS_OFFSET 0x00000104 + +/** @name Operational Register offsets. + * Register comments are tagged with "H:" and "D:" for Host and Device modes, + * respectively. + * Tags are only present for registers that have a different meaning DEVICE and + * HOST modes. Most registers are only valid for either DEVICE or HOST mode. + * Those registers don't have tags. + * @{ + */ +#define XUSBPS_CMD_OFFSET 0x00000140 /**< Configuration */ +#define XUSBPS_ISR_OFFSET 0x00000144 /**< Interrupt Status */ +#define XUSBPS_IER_OFFSET 0x00000148 /**< Interrupt Enable */ +#define XUSBPS_FRAME_OFFSET 0x0000014C /**< USB Frame Index */ +#define XUSBPS_LISTBASE_OFFSET 0x00000154 /**< H: Periodic List Base Address */ +#define XUSBPS_DEVICEADDR_OFFSET 0x00000154 /**< D: Device Address */ +#define XUSBPS_ASYNCLISTADDR_OFFSET 0x00000158 /**< H: Async List Address */ +#define XUSBPS_EPLISTADDR_OFFSET 0x00000158 /**< D: Endpoint List Addr */ +#define XUSBPS_TTCTRL_OFFSET 0x0000015C /**< TT Control */ +#define XUSBPS_BURSTSIZE_OFFSET 0x00000160 /**< Burst Size */ +#define XUSBPS_TXFILL_OFFSET 0x00000164 /**< Tx Fill Tuning */ +#define XUSBPS_ULPIVIEW_OFFSET 0x00000170 /**< ULPI Viewport */ +#define XUSBPS_EPNAKISR_OFFSET 0x00000178 /**< Endpoint NAK IRQ Status */ +#define XUSBPS_EPNAKIER_OFFSET 0x0000017C /**< Endpoint NAK IRQ Enable */ +#define XUSBPS_PORTSCR1_OFFSET 0x00000184 /**< Port Control/Status 1 */ + +/* NOTE: The Port Control / Status Register index is 1-based. */ +#define XUSBPS_PORTSCRn_OFFSET(n) \ + (XUSBPS_PORTSCR1_OFFSET + (((n)-1) * XUSBPS_REG_SPACING)) + + +#define XUSBPS_OTGCSR_OFFSET 0x000001A4 /**< OTG Status and Control */ +#define XUSBPS_MODE_OFFSET 0x000001A8 /**< USB Mode */ +#define XUSBPS_EPSTAT_OFFSET 0x000001AC /**< Endpoint Setup Status */ +#define XUSBPS_EPPRIME_OFFSET 0x000001B0 /**< Endpoint Prime */ +#define XUSBPS_EPFLUSH_OFFSET 0x000001B4 /**< Endpoint Flush */ +#define XUSBPS_EPRDY_OFFSET 0x000001B8 /**< Endpoint Ready */ +#define XUSBPS_EPCOMPL_OFFSET 0x000001BC /**< Endpoint Complete */ +#define XUSBPS_EPCR0_OFFSET 0x000001C0 /**< Endpoint Control 0 */ +#define XUSBPS_EPCR1_OFFSET 0x000001C4 /**< Endpoint Control 1 */ +#define XUSBPS_EPCR2_OFFSET 0x000001C8 /**< Endpoint Control 2 */ +#define XUSBPS_EPCR3_OFFSET 0x000001CC /**< Endpoint Control 3 */ +#define XUSBPS_EPCR4_OFFSET 0x000001D0 /**< Endpoint Control 4 */ + +#define XUSBPS_MAX_ENDPOINTS 12 /**< Number of supported Endpoints in + * this core. */ +#define XUSBPS_EP_OUT_MASK 0x00000FFF /**< OUR (RX) endpoint mask */ +#define XUSBPS_EP_IN_MASK 0x0FFF0000 /**< IN (TX) endpoint mask */ +#define XUSBPS_EP_ALL_MASK 0x0FFF0FFF /**< Mask used for endpoint control + * registers */ +#define XUSBPS_EPCRn_OFFSET(n) \ + (XUSBPS_EPCR0_OFFSET + ((n) * XUSBPS_REG_SPACING)) + +#define XUSBPS_EPFLUSH_RX_SHIFT 0 +#define XUSBPS_EPFLUSH_TX_SHIFT 16 + +/* @} */ + + + +/** @name Endpoint Control Register (EPCR) bit positions. + * @{ + */ + +/* Definitions for TX Endpoint bits */ +#define XUSBPS_EPCR_TXT_TYPE_SHIFT 18 /* < Endpoint Type - TX bit shift*/ +#define XUSBPS_EPCR_TXT_TYPE_MASK 0x000C0000 /* < Endpoint Type - TX read only*/ +#define XUSBPS_EPCR_TXT_CONTROL_MASK 0x00000000 /**< Control Endpoint - TX */ +#define XUSBPS_EPCR_TXT_ISO_MASK 0x00040000 /**< Isochronous. Endpoint */ +#define XUSBPS_EPCR_TXT_BULK_MASK 0x00080000 /**< Bulk Endpoint - TX */ +#define XUSBPS_EPCR_TXT_INTR_MASK 0x000C0000 /**< Interrupt Endpoint */ +#define XUSBPS_EPCR_TXS_MASK 0x00010000 /**< Stall TX endpoint */ +#define XUSBPS_EPCR_TXE_MASK 0x00800000 /**< Transmit enable - TX */ +#define XUSBPS_EPCR_TXR_MASK 0x00400000 /**< Data Toggle Reset Bit */ + + +/* Definitions for RX Endpoint bits */ +#define XUSBPS_EPCR_RXT_TYPE_SHIFT 2 /* < Endpoint Type - RX bit shift*/ +#define XUSBPS_EPCR_RXT_TYPE_MASK 0x0000000C /**< Endpoint Type - RX read only*/ +#define XUSBPS_EPCR_RXT_CONTROL_MASK 0x00000000 /**< Control Endpoint - RX */ +#define XUSBPS_EPCR_RXT_ISO_MASK 0x00000004 /**< Isochronous Endpoint */ +#define XUSBPS_EPCR_RXT_BULK_MASK 0x00000008 /**< Bulk Endpoint - RX */ +#define XUSBPS_EPCR_RXT_INTR_MASK 0x0000000C /**< Interrupt Endpoint */ +#define XUSBPS_EPCR_RXS_MASK 0x00000001 /**< Stall RX endpoint. */ +#define XUSBPS_EPCR_RXE_MASK 0x00000080 /**< Transmit enable. - RX */ +#define XUSBPS_EPCR_RXR_MASK 0x00000040 /**< Data Toggle Reset Bit */ +/* @} */ + + +/** @name USB Command Register (CR) bit positions. + * @{ + */ +#define XUSBPS_CMD_RS_MASK 0x00000001 /**< Run/Stop */ +#define XUSBPS_CMD_RST_MASK 0x00000002 /**< Controller RESET */ +#define XUSBPS_CMD_FS01_MASK 0x0000000C /**< Frame List Size bit 0,1 */ +#define XUSBPS_CMD_PSE_MASK 0x00000010 /**< Periodic Sched Enable */ +#define XUSBPS_CMD_ASE_MASK 0x00000020 /**< Async Sched Enable */ +#define XUSBPS_CMD_IAA_MASK 0x00000040 /**< IRQ Async Advance Doorbell */ +#define XUSBPS_CMD_ASP_MASK 0x00000300 /**< Async Sched Park Mode Cnt */ +#define XUSBPS_CMD_ASPE_MASK 0x00000800 /**< Async Sched Park Mode Enbl */ +#define XUSBPS_CMD_SUTW_MASK 0x00002000 /**< Setup TripWire */ +#define XUSBPS_CMD_ATDTW_MASK 0x00004000 /**< Add dTD TripWire */ +#define XUSBPS_CMD_FS2_MASK 0x00008000 /**< Frame List Size bit 2 */ +#define XUSBPS_CMD_ITC_MASK 0x00FF0000 /**< IRQ Threshold Control */ +/* @} */ + + +/** + * @name Interrupt Threshold + * These definitions are used by software to set the maximum rate at which the + * USB controller will generate interrupt requests. The interrupt interval is + * given in number of micro-frames. + * + * USB defines a full-speed 1 ms frame time indicated by a Start Of Frame (SOF) + * packet each and every 1ms. USB also defines a high-speed micro-frame with a + * 125us frame time. For each micro-frame a SOF (Start Of Frame) packet is + * generated. Data is sent in between the SOF packets. The interrupt threshold + * defines how many micro-frames the controller waits before issuing an + * interrupt after data has been received. + * + * For a threshold of 0 the controller will issue an interrupt immediately + * after the last byte of the data has been received. For a threshold n>0 the + * controller will wait for n micro-frames before issuing an interrupt. + * + * Therefore, a setting of 8 micro-frames (default) means that the controller + * will issue at most 1 interrupt per millisecond. + * + * @{ + */ +#define XUSBPS_CMD_ITHRESHOLD_0 0x00 /**< Immediate interrupt. */ +#define XUSBPS_CMD_ITHRESHOLD_1 0x01 /**< 1 micro-frame */ +#define XUSBPS_CMD_ITHRESHOLD_2 0x02 /**< 2 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_4 0x04 /**< 4 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_8 0x08 /**< 8 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_16 0x10 /**< 16 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_32 0x20 /**< 32 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_64 0x40 /**< 64 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_MAX XUSBPS_CMD_ITHRESHOLD_64 +#define XUSBPS_CMD_ITHRESHOLD_DEFAULT XUSBPS_CMD_ITHRESHOLD_8 +/* @} */ + + + +/** @name USB Interrupt Status Register (ISR) / Interrupt Enable Register (IER) + * bit positions. + * @{ + */ +#define XUSBPS_IXR_UI_MASK 0x00000001 /**< USB Transaction Complete */ +#define XUSBPS_IXR_UE_MASK 0x00000002 /**< Transaction Error */ +#define XUSBPS_IXR_PC_MASK 0x00000004 /**< Port Change Detect */ +#define XUSBPS_IXR_FRE_MASK 0x00000008 /**< Frame List Rollover */ +#define XUSBPS_IXR_AA_MASK 0x00000020 /**< Async Advance */ +#define XUSBPS_IXR_UR_MASK 0x00000040 /**< RESET Received */ +#define XUSBPS_IXR_SR_MASK 0x00000080 /**< Start of Frame */ +#define XUSBPS_IXR_SLE_MASK 0x00000100 /**< Device Controller Suspend */ +#define XUSBPS_IXR_ULPI_MASK 0x00000400 /**< ULPI IRQ */ +#define XUSBPS_IXR_HCH_MASK 0x00001000 /**< Host Controller Halted + * Read Only */ +#define XUSBPS_IXR_RCL_MASK 0x00002000 /**< USB Reclamation Read Only */ +#define XUSBPS_IXR_PS_MASK 0x00004000 /**< Periodic Sched Status + * Read Only */ +#define XUSBPS_IXR_AS_MASK 0x00008000 /**< Async Sched Status Read only */ +#define XUSBPS_IXR_NAK_MASK 0x00010000 /**< NAK IRQ */ +#define XUSBPS_IXR_UA_MASK 0x00040000 /**< USB Host Async IRQ */ +#define XUSBPS_IXR_UP_MASK 0x00080000 /**< USB Host Periodic IRQ */ +#define XUSBPS_IXR_TI0_MASK 0x01000000 /**< Timer 0 Interrupt */ +#define XUSBPS_IXR_TI1_MASK 0x02000000 /**< Timer 1 Interrupt */ + +#define XUSBPS_IXR_ALL (XUSBPS_IXR_UI_MASK | \ + XUSBPS_IXR_UE_MASK | \ + XUSBPS_IXR_PC_MASK | \ + XUSBPS_IXR_FRE_MASK | \ + XUSBPS_IXR_AA_MASK | \ + XUSBPS_IXR_UR_MASK | \ + XUSBPS_IXR_SR_MASK | \ + XUSBPS_IXR_SLE_MASK | \ + XUSBPS_IXR_ULPI_MASK | \ + XUSBPS_IXR_HCH_MASK | \ + XUSBPS_IXR_RCL_MASK | \ + XUSBPS_IXR_PS_MASK | \ + XUSBPS_IXR_AS_MASK | \ + XUSBPS_IXR_NAK_MASK | \ + XUSBPS_IXR_UA_MASK | \ + XUSBPS_IXR_UP_MASK | \ + XUSBPS_IXR_TI0_MASK | \ + XUSBPS_IXR_TI1_MASK) + /**< Mask for ALL IRQ types */ +/* @} */ + + +/** @name USB Mode Register (MODE) bit positions. + * @{ + */ +#define XUSBPS_MODE_CM_MASK 0x00000003 /**< Controller Mode Select */ +#define XUSBPS_MODE_CM_IDLE_MASK 0x00000000 +#define XUSBPS_MODE_CM_DEVICE_MASK 0x00000002 +#define XUSBPS_MODE_CM_HOST_MASK 0x00000003 +#define XUSBPS_MODE_ES_MASK 0x00000004 /**< USB Endian Select */ +#define XUSBPS_MODE_SLOM_MASK 0x00000008 /**< USB Setup Lockout Mode Disable */ +#define XUSBPS_MODE_SDIS_MASK 0x00000010 +#define XUSBPS_MODE_VALID_MASK 0x0000001F + +/* @} */ + + +/** @name USB Device Address Register (DEVICEADDR) bit positions. + * @{ + */ +#define XUSBPS_DEVICEADDR_DEVICEAADV_MASK 0x01000000 + /**< Device Addr Auto Advance */ +#define XUSBPS_DEVICEADDR_ADDR_MASK 0xFE000000 + /**< Device Address */ +#define XUSBPS_DEVICEADDR_ADDR_SHIFT 25 + /**< Address shift */ +#define XUSBPS_DEVICEADDR_MAX 127 + /**< Biggest allowed address */ +/* @} */ + +/** @name USB TT Control Register (TTCTRL) bit positions. + * @{ + */ +#define XUSBPS_TTCTRL_HUBADDR_MASK 0x7F000000 /**< TT Hub Address */ +/* @} */ + + +/** @name USB Burst Size Register (BURSTSIZE) bit posisions. + * @{ + */ +#define XUSBPS_BURSTSIZE_RX_MASK 0x000000FF /**< RX Burst Length */ +#define XUSBPS_BURSTSIZE_TX_MASK 0x0000FF00 /**< TX Burst Length */ +/* @} */ + + +/** @name USB Tx Fill Tuning Register (TXFILL) bit positions. + * @{ + */ +#define XUSBPS_TXFILL_OVERHEAD_MASK 0x000000FF + /**< Scheduler Overhead */ +#define XUSBPS_TXFILL_HEALTH_MASK 0x00001F00 + /**< Scheduler Health Cntr */ +#define XUSBPS_TXFILL_BURST_MASK 0x003F0000 + /**< FIFO Burst Threshold */ +/* @} */ + + +/** @name USB ULPI Viewport Register (ULPIVIEW) bit positions. + * @{ + */ +#define XUSBPS_ULPIVIEW_DATWR_MASK 0x000000FF /**< ULPI Data Write */ +#define XUSBPS_ULPIVIEW_DATRD_MASK 0x0000FF00 /**< ULPI Data Read */ +#define XUSBPS_ULPIVIEW_ADDR_MASK 0x00FF0000 /**< ULPI Data Address */ +#define XUSBPS_ULPIVIEW_PORT_MASK 0x07000000 /**< ULPI Port Number */ +#define XUSBPS_ULPIVIEW_SS_MASK 0x08000000 /**< ULPI Synchronous State */ +#define XUSBPS_ULPIVIEW_RW_MASK 0x20000000 /**< ULPI Read/Write Control */ +#define XUSBPS_ULPIVIEW_RUN_MASK 0x40000000 /**< ULPI Run */ +#define XUSBPS_ULPIVIEW_WU_MASK 0x80000000 /**< ULPI Wakeup */ +/* @} */ + + +/** @name Port Status Control Register bit positions. + * @{ + */ +#define XUSBPS_PORTSCR_CCS_MASK 0x00000001 /**< Current Connect Status */ +#define XUSBPS_PORTSCR_CSC_MASK 0x00000002 /**< Connect Status Change */ +#define XUSBPS_PORTSCR_PE_MASK 0x00000004 /**< Port Enable/Disable */ +#define XUSBPS_PORTSCR_PEC_MASK 0x00000008 /**< Port Enable/Disable Change */ +#define XUSBPS_PORTSCR_OCA_MASK 0x00000010 /**< Over-current Active */ +#define XUSBPS_PORTSCR_OCC_MASK 0x00000020 /**< Over-current Change */ +#define XUSBPS_PORTSCR_FPR_MASK 0x00000040 /**< Force Port Resume */ +#define XUSBPS_PORTSCR_SUSP_MASK 0x00000080 /**< Suspend */ +#define XUSBPS_PORTSCR_PR_MASK 0x00000100 /**< Port Reset */ +#define XUSBPS_PORTSCR_HSP_MASK 0x00000200 /**< High Speed Port */ +#define XUSBPS_PORTSCR_LS_MASK 0x00000C00 /**< Line Status */ +#define XUSBPS_PORTSCR_PP_MASK 0x00001000 /**< Port Power */ +#define XUSBPS_PORTSCR_PO_MASK 0x00002000 /**< Port Owner */ +#define XUSBPS_PORTSCR_PIC_MASK 0x0000C000 /**< Port Indicator Control */ +#define XUSBPS_PORTSCR_PTC_MASK 0x000F0000 /**< Port Test Control */ +#define XUSBPS_PORTSCR_WKCN_MASK 0x00100000 /**< Wake on Connect Enable */ +#define XUSBPS_PORTSCR_WKDS_MASK 0x00200000 /**< Wake on Disconnect Enable */ +#define XUSBPS_PORTSCR_WKOC_MASK 0x00400000 /**< Wake on Over-current Enable */ +#define XUSBPS_PORTSCR_PHCD_MASK 0x00800000 /**< PHY Low Power Suspend - + * Clock Disable */ +#define XUSBPS_PORTSCR_PFSC_MASK 0x01000000 /**< Port Force Full Speed + * Connect */ +#define XUSBPS_PORTSCR_PSPD_MASK 0x0C000000 /**< Port Speed */ +/* @} */ + + +/** @name On-The-Go Status Control Register (OTGCSR) bit positions. + * @{ + */ +#define XUSBPS_OTGSC_VD_MASK 0x00000001 /**< VBus Discharge Bit */ +#define XUSBPS_OTGSC_VC_MASK 0x00000002 /**< VBus Charge Bit */ +#define XUSBPS_OTGSC_HAAR_MASK 0x00000004 /**< HW Assist Auto Reset + * Enable Bit */ +#define XUSBPS_OTGSC_OT_MASK 0x00000008 /**< OTG Termination Bit */ +#define XUSBPS_OTGSC_DP_MASK 0x00000010 /**< Data Pulsing Pull-up + * Enable Bit */ +#define XUSBPS_OTGSC_IDPU_MASK 0x00000020 /**< ID Pull-up Enable Bit */ +#define XUSBPS_OTGSC_HADP_MASK 0x00000040 /**< HW Assist Data Pulse + * Enable Bit */ +#define XUSBPS_OTGSC_HABA_MASK 0x00000080 /**< USB Hardware Assist + * B Disconnect to A + * Connect Enable Bit */ +#define XUSBPS_OTGSC_ID_MASK 0x00000100 /**< ID Status Flag */ +#define XUSBPS_OTGSC_AVV_MASK 0x00000200 /**< USB A VBus Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_ASV_MASK 0x00000400 /**< USB A Session Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_BSV_MASK 0x00000800 /**< USB B Session Valid Status Flag */ +#define XUSBPS_OTGSC_BSE_MASK 0x00001000 /**< USB B Session End Status Flag */ +#define XUSBPS_OTGSC_1MST_MASK 0x00002000 /**< USB 1 Millisecond Timer Status Flag */ +#define XUSBPS_OTGSC_DPS_MASK 0x00004000 /**< Data Pulse Status Flag */ +#define XUSBPS_OTGSC_IDIS_MASK 0x00010000 /**< USB ID Interrupt Status Flag */ +#define XUSBPS_OTGSC_AVVIS_MASK 0x00020000 /**< USB A VBus Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_ASVIS_MASK 0x00040000 /**< USB A Session Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_BSVIS_MASK 0x00080000 /**< USB B Session Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_BSEIS_MASK 0x00100000 /**< USB B Session End Interrupt Status Flag */ +#define XUSBPS_OTGSC_1MSS_MASK 0x00200000 /**< 1 Millisecond Timer Interrupt Status Flag */ +#define XUSBPS_OTGSC_DPIS_MASK 0x00400000 /**< Data Pulse Interrupt Status Flag */ +#define XUSBPS_OTGSC_IDIE_MASK 0x01000000 /**< ID Interrupt Enable Bit */ +#define XUSBPS_OTGSC_AVVIE_MASK 0x02000000 /**< USB A VBus Valid Interrupt Enable Bit */ +#define XUSBPS_OTGSC_ASVIE_MASK 0x04000000 /**< USB A Session Valid Interrupt Enable Bit */ +#define XUSBPS_OTGSC_BSVIE_MASK 0x08000000 /**< USB B Session Valid Interrupt Enable Bit */ +#define XUSBPS_OTGSC_BSEE_MASK 0x10000000 /**< USB B Session End Interrupt Enable Bit */ +#define XUSBPS_OTGSC_1MSE_MASK 0x20000000 /**< 1 Millisecond Timer + * Interrupt Enable Bit */ +#define XUSBPS_OTGSC_DPIE_MASK 0x40000000 /**< Data Pulse Interrupt + * Enable Bit */ + +#define XUSBPS_OTG_ISB_ALL (XUSBPS_OTGSC_IDIS_MASK |\ + XUSBPS_OTGSC_AVVIS_MASK | \ + XUSBPS_OTGSC_ASVIS_MASK | \ + XUSBPS_OTGSC_BSVIS_MASK | \ + XUSBPS_OTGSC_BSEIS_MASK | \ + XUSBPS_OTGSC_1MSS_MASK | \ + XUSBPS_OTGSC_DPIS_MASK) + /** Mask for All IRQ status masks */ + +#define XUSBPS_OTG_IEB_ALL (XUSBPS_OTGSC_IDIE_MASK |\ + XUSBPS_OTGSC_AVVIE_MASK | \ + XUSBPS_OTGSC_ASVIE_MASK | \ + XUSBPS_OTGSC_BSVIE_MASK | \ + XUSBPS_OTGSC_BSEE_IEB_MASK | \ + XUSBPS_OTGSC_1MSE_MASK | \ + XUSBPS_OTGSC_DPIE_MASK) + /** Mask for All IRQ Enable masks */ +/* @} */ + + +/**< Alignment of the Device Queue Head List BASE. */ +#define XUSBPS_dQH_BASE_ALIGN 2048 + +/**< Alignment of a Device Queue Head structure. */ +#define XUSBPS_dQH_ALIGN 64 + +/**< Alignment of a Device Transfer Descriptor structure. */ +#define XUSBPS_dTD_ALIGN 32 + +/**< Size of one RX buffer for a OUT Transfer Descriptor. */ +#define XUSBPS_dTD_BUF_SIZE 4096 + +/**< Maximum size of one RX/TX buffer. */ +#define XUSBPS_dTD_BUF_MAX_SIZE 16*1024 + +/**< Alignment requirement for Transfer Descriptor buffers. */ +#define XUSBPS_dTD_BUF_ALIGN 4096 + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* This macro reads the given register. +* +* @param BaseAddress is the base address for the USB registers. +* @param RegOffset is the register offset to be read. +* +* @return The 32-bit value of the register. +* +* @note C-style signature: +* u32 XUsbPs_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XUsbPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32(BaseAddress + (RegOffset)) + + +/****************************************************************************/ +/** +* +* This macro writes the given register. +* +* @param BaseAddress is the the base address for the USB registers. +* @param RegOffset is the register offset to be written. +* @param Data is the the 32-bit value to write to the register. +* +* @return None. +* +* @note C-style signature: +* void XUsbPs_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* + *****************************************************************************/ +#define XUsbPs_WriteReg(BaseAddress, RegOffset, Data) \ + Xil_Out32(BaseAddress + (RegOffset), (Data)) + + +/************************** Function Prototypes ******************************/ +/* + * Perform reset operation to the USB PS interface + */ +void XUsbPs_ResetHw(u32 BaseAddress); +/************************** Variable Definitions ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_L_H */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_intr.c b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_intr.c new file mode 100644 index 0000000..061825a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_intr.c @@ -0,0 +1,495 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/******************************************************************************/ +/** + * @file xusbps_intr.c +* @addtogroup usbps_v2_7 +* @{ + * + * This file contains the functions that are related to interrupt processing + * for the EPB USB driver. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- ----------------------------------------------------------
+ * 1.00a jz  10/10/10 First release
+ * 1.03a nm  09/21/12 Fixed CR#678977. Added proper sequence for setup packet
+ *                    handling.
+ * 2.3   bss 01/19/16 Modified XUsbPs_EpQueueRequest function to fix CR#873972
+ *            (moving of dTD Head/Tail Pointers properly).
+ * 2.5   pm  02/20/20 Added ISO endpoint support.
+ * 
+ ******************************************************************************/ + +/***************************** Include Files **********************************/ + +#include "xusbps.h" +#include "xusbps_endpoint.h" + +/************************** Constant Definitions ******************************/ + +/**************************** Type Definitions ********************************/ + +/***************** Macros (Inline Functions) Definitions **********************/ + +/************************** Variable Definitions ******************************/ + +/************************** Function Prototypes *******************************/ + +static void XUsbPs_IntrHandleTX(XUsbPs *InstancePtr, u32 EpCompl); +static void XUsbPs_IntrHandleRX(XUsbPs *InstancePtr, u32 EpCompl); +static void XUsbPs_IntrHandleReset(XUsbPs *InstancePtr, u32 IrqSts); +static void XUsbPs_IntrHandleEp0Setup(XUsbPs *InstancePtr); + +/*****************************************************************************/ +/** +* This function is the first-level interrupt handler for the USB core. All USB +* interrupts will be handled here. Depending on the type of the interrupt, +* second level interrupt handler may be called. Second level interrupt +* handlers will be registered by the user using the: +* XUsbPs_IntrSetHandler() +* and/or +* XUsbPs_EpSetHandler() +* functions. +* +* +* @param HandlerRef is a Reference passed to the interrupt register +* function. In our case this will be a pointer to the XUsbPs +* instance. +* +* @return None +* +* @note None +* +******************************************************************************/ +void XUsbPs_IntrHandler(void *HandlerRef) +{ + XUsbPs *InstancePtr; + + u32 IrqSts; + + Xil_AssertVoid(HandlerRef != NULL); + + InstancePtr = (XUsbPs *) HandlerRef; + + /* Handle controller (non-endpoint) related interrupts. */ + IrqSts = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_ISR_OFFSET); + + /* Clear the interrupt status register. */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_ISR_OFFSET, IrqSts); + + /* Nak interrupt, used to respond to host's IN request */ + if(IrqSts & XUSBPS_IXR_NAK_MASK) { + /* Ack the hardware */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPNAKISR_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPNAKISR_OFFSET)); + } + + + /*************************************************************** + * + * Handle general interrupts. Endpoint interrupts will be handler + * later. + * + */ + + /* RESET interrupt.*/ + if (IrqSts & XUSBPS_IXR_UR_MASK) { + XUsbPs_IntrHandleReset(InstancePtr, IrqSts); + return; + } + + /* Check if we have a user handler that needs to be called. Note that + * this is the handler for general interrupts. Endpoint interrupts will + * be handled below. + */ + if ((IrqSts & InstancePtr->HandlerMask) && InstancePtr->HandlerFunc) { + (InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, IrqSts); + } + + + /*************************************************************** + * + * Handle Endpoint interrupts. + * + */ + if (IrqSts & XUSBPS_IXR_UI_MASK) { + u32 EpStat; + u32 EpCompl; + + /* ENDPOINT 0 SETUP PACKET HANDLING + * + * Check if we got a setup packet on endpoint 0. Currently we + * only check for setup packets on endpoint 0 as we would not + * expect setup packets on any other endpoint (even though it + * is possible to send setup packets on other endpoints). + */ + EpStat = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPSTAT_OFFSET); + if (EpStat & 0x0001) { + /* Handle the setup packet */ + XUsbPs_IntrHandleEp0Setup(InstancePtr); + + /* Re-Prime the endpoint. + * Endpoint is de-primed if a setup packet comes in. + */ + XUsbPs_EpPrime(InstancePtr, 0, XUSBPS_EP_DIRECTION_OUT); + } + + /* Check for RX and TX complete interrupts. */ + EpCompl = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPCOMPL_OFFSET); + + + /* ACK the complete interrupts. */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPCOMPL_OFFSET, EpCompl); + + /* Check OUT (RX) endpoints. */ + if (EpCompl & XUSBPS_EP_OUT_MASK) { + XUsbPs_IntrHandleRX(InstancePtr, EpCompl); + } + + /* Check IN (TX) endpoints. */ + if (EpCompl & XUSBPS_EP_IN_MASK) { + XUsbPs_IntrHandleTX(InstancePtr, EpCompl); + } + } +} + + +/*****************************************************************************/ +/** +* This function registers the user callback handler for controller +* (non-endpoint) interrupts. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param CallBackFunc is the Callback function to register. +* CallBackFunc may be NULL to clear the entry. +* @param CallBackRef is the user data reference passed to the +* callback function. CallBackRef may be NULL. +* @param Mask is the User interrupt mask. Defines which interrupts +* will cause the callback to be called. +* +* @return +* - XST_SUCCESS: Callback registered successfully. +* - XST_FAILURE: Callback could not be registered. +* +* @note None. +* +******************************************************************************/ +int XUsbPs_IntrSetHandler(XUsbPs *InstancePtr, + XUsbPs_IntrHandlerFunc CallBackFunc, + void *CallBackRef, u32 Mask) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + + InstancePtr->HandlerFunc = CallBackFunc; + InstancePtr->HandlerRef = CallBackRef; + InstancePtr->HandlerMask = Mask; + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* This function handles TX buffer interrupts. It is called by the interrupt +* when a transmit complete interrupt occurs. It returns buffers of completed +* descriptors to the caller. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpCompl is the Bit mask of endpoints that caused a transmit +* complete interrupt. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void XUsbPs_IntrHandleTX(XUsbPs *InstancePtr, u32 EpCompl) +{ + int Index; + u32 Mask; + int NumEp; + + /* Check all endpoints for TX complete bits. + */ + Mask = 0x00010000; + NumEp = InstancePtr->DeviceConfig.NumEndpoints; + + /* Check for every endpoint if its TX complete bit is + * set. + */ + for (Index = 0; Index < NumEp; Index++, Mask <<= 1) { + XUsbPs_EpIn *Ep; + + if (!(EpCompl & Mask)) { + continue; + } + /* The TX complete bit for this endpoint is + * set. Walk the list of descriptors to see + * which ones are completed. + */ + Ep = &InstancePtr->DeviceConfig.Ep[Index].In; + do { + + XUsbPs_dTDInvalidateCache(Ep->dTDTail); + + /* If the descriptor is not active then the buffer has + * not been sent yet. + */ + if (XUsbPs_dTDIsActive(Ep->dTDTail)) { + break; + } + + + if (InstancePtr->DeviceConfig.EpCfg[Index].In.Type == + XUSBPS_EP_TYPE_ISOCHRONOUS) { + if (Ep->HandlerIsoFunc) { + Ep->HandlerIsoFunc(Ep->HandlerRef, + Ep->RequestedBytes, + Ep->BytesTxed); + } + } else { + if (Ep->HandlerFunc) { + void *BufPtr; + + BufPtr = (void *) XUsbPs_ReaddTD(Ep->dTDTail, + XUSBPS_dTDUSERDATA); + + Ep->HandlerFunc(Ep->HandlerRef, Index, + XUSBPS_EP_EVENT_DATA_TX, + BufPtr); + } + } + + Ep->dTDTail = XUsbPs_dTDGetNLP(Ep->dTDTail); + } while(Ep->dTDTail != Ep->dTDHead); + } +} + + +/*****************************************************************************/ +/** + * This function handles RX buffer interrupts. It is called by the interrupt + * when a receive complete interrupt occurs. It notifies the callback functions + * that have been registered with the individual endpoints that data has been + * received. + * + * @param InstancePtr + * Pointer to the XUsbPs instance of the controller. + * + * @param EpCompl + * Bit mask of endpoints that caused a receive complete interrupt. + * @return + * none + * + ******************************************************************************/ +static void XUsbPs_IntrHandleRX(XUsbPs *InstancePtr, u32 EpCompl) +{ + XUsbPs_EpOut *Ep; + int Index; + u32 Mask; + int NumEp; + + /* Check all endpoints for RX complete bits. */ + Mask = 0x00000001; + NumEp = InstancePtr->DeviceConfig.NumEndpoints; + + + /* Check for every endpoint if its RX complete bit is set.*/ + for (Index = 0; Index < NumEp; Index++, Mask <<= 1) { + int numP = 0; + + if (!(EpCompl & Mask)) { + continue; + } + Ep = &InstancePtr->DeviceConfig.Ep[Index].Out; + + XUsbPs_dTDInvalidateCache(Ep->dTDCurr); + + /* Handle all finished dTDs */ + while (!XUsbPs_dTDIsActive(Ep->dTDCurr)) { + numP += 1; + /* We get data RX events for 0 length packets on + * endpoint 0. We receive and immediately release + * them again here, but there's no action to be + * taken. + */ + if (InstancePtr->DeviceConfig.EpCfg[Index].Out.Type == + XUSBPS_EP_TYPE_ISOCHRONOUS){ + if (Index == 0) { + u8 BufferPtr[64] = {0}; + + /* Get the data buffer. */ + XUsbPs_EpDataBufferReceive(InstancePtr, + 0, &BufferPtr[0], 64); + Ep->MemAlloted = 0; + } + + if (Ep->MemAlloted == 1) { + XUsbPs_EpGetData(InstancePtr, Index, + Ep->RequestedBytes); + } else + break; + } else { + if (Ep->HandlerFunc) { + Ep->HandlerFunc(Ep->HandlerRef, Index, + XUSBPS_EP_EVENT_DATA_RX, NULL); + } + + Ep->dTDCurr = XUsbPs_dTDGetNLP(Ep->dTDCurr); + XUsbPs_dTDInvalidateCache(Ep->dTDCurr); + } + } + /* Re-Prime the endpoint.*/ + XUsbPs_EpPrime(InstancePtr, Index, XUSBPS_EP_DIRECTION_OUT); + } +} + + +/*****************************************************************************/ +/** +* This function handles a RESET interrupt. It will notify the interrupt +* handler callback of the RESET condition. +* +* @param InstancePtr is pointer to the XUsbPs instance of the controller +* @param IrqSts is the Interrupt status register content. +* To be passed on to the user. +* +* @return None +* +* @Note None. +* +******************************************************************************/ +static void XUsbPs_IntrHandleReset(XUsbPs *InstancePtr, u32 IrqSts) +{ + u32 Timeout; + u8 Index; + + if (InstancePtr->AppData != NULL) + InstancePtr->AppData->State = XUSBPS_STATE_DEFAULT; + + for (Index = 0; Index < InstancePtr->DeviceConfig.NumEndpoints; + Index++) { + InstancePtr->DeviceConfig.Ep[Index].Out.MemAlloted = 0; + InstancePtr->DeviceConfig.Ep[Index].Out.BufferPtr = NULL; + InstancePtr->DeviceConfig.Ep[Index].Out.BytesTxed = 0; + InstancePtr->DeviceConfig.Ep[Index].Out.RequestedBytes = 0; + InstancePtr->DeviceConfig.Ep[Index].In.BufferPtr = NULL; + InstancePtr->DeviceConfig.Ep[Index].In.BytesTxed = 0; + InstancePtr->DeviceConfig.Ep[Index].In.RequestedBytes = 0; + } + + /* Clear all setup token semaphores by reading the + * XUSBPS_EPSTAT_OFFSET register and writing its value back to + * itself. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPSTAT_OFFSET)); + + /* Clear all the endpoint complete status bits by reading the + * XUSBPS_EPCOMPL_OFFSET register and writings its value back + * to itself. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPCOMPL_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPCOMPL_OFFSET)); + + /* Cancel all endpoint prime status by waiting until all bits + * in XUSBPS_EPPRIME_OFFSET are 0 and then writing 0xFFFFFFFF + * to XUSBPS_EPFLUSH_OFFSET. + * + * Avoid hanging here by using a Timeout counter... + */ + Timeout = XUSBPS_TIMEOUT_COUNTER; + while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPPRIME_OFFSET) & + XUSBPS_EP_ALL_MASK) && --Timeout) { + /* NOP */ + } + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPFLUSH_OFFSET, 0xFFFFFFFF); + + /* Make sure that the reset bit in XUSBPS_PORTSCR1_OFFSET is + * still set at this point. If the code gets to this point and + * the reset bit has already been cleared we are in trouble and + * hardware reset is necessary. + */ + if (!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_PORTSCR1_OFFSET) & + XUSBPS_PORTSCR_PR_MASK)) { + /* Send a notification to the user that a hardware + * RESET is required. At this point we can only hope + * that the user registered an interrupt handler and + * will issue a hardware RESET. + */ + if (InstancePtr->HandlerFunc) { + (InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, + IrqSts); + } + else { + for (;;); + } + + /* If we get here there is nothing more to do. The user + * should have reset the core. + */ + return; + } + + /* Check if we have a user handler that needs to be called. + */ + if (InstancePtr->HandlerFunc) { + (InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, IrqSts); + } + + /* We are done. After RESET we don't proceed in the interrupt + * handler. + */ +} + + +/*****************************************************************************/ +/** +* This function handles a Setup Packet interrupt. It will notify the interrupt +* handler callback of the RESET condition. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* +* @return None +* +* @Note None +* +******************************************************************************/ +static void XUsbPs_IntrHandleEp0Setup(XUsbPs *InstancePtr) +{ + + XUsbPs_EpOut *Ep; + + /* Notify the user. */ + Ep = &InstancePtr->DeviceConfig.Ep[0].Out; + + if (Ep->HandlerFunc) { + Ep->HandlerFunc(Ep->HandlerRef, 0, + XUSBPS_EP_EVENT_SETUP_DATA_RECEIVED, NULL); + } +} + + +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_sinit.c new file mode 100644 index 0000000..bc53739 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/usbps/src/xusbps_sinit.c @@ -0,0 +1,73 @@ +/****************************************************************************** +* Copyright (C) 2010 - 2021 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** + * + * @file xusbps_sinit.c +* @addtogroup usbps_v2_7 +* @{ + * + * The implementation of the XUsbPs driver's static initialization + * functionality. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 
+ * + *****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xusbps.h" +#include "xparameters.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +extern XUsbPs_Config XUsbPs_ConfigTable[]; + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Looks up the controller configuration based on the unique controller ID. A +* table contains the configuration info for each controller in the system. +* +* @param DeviceID is the ID of the controller to look up the +* configuration for. +* +* @return +* A pointer to the configuration found or NULL if the specified +* controller ID was not found. +* +******************************************************************************/ +XUsbPs_Config *XUsbPs_LookupConfig(u16 DeviceID) +{ + XUsbPs_Config *CfgPtr = NULL; + + int Index; + + for (Index = 0; Index < XPAR_XUSBPS_NUM_INSTANCES; Index++) { + if (XUsbPs_ConfigTable[Index].DeviceID == DeviceID) { + CfgPtr = &XUsbPs_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/Makefile b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/Makefile new file mode 100644 index 0000000..5feeb49 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/Makefile @@ -0,0 +1,39 @@ +DRIVER_LIB_VERSION = 1.0 +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib/ +INCLUDEDIR=../../../include/ +INCLUDES=-I./. -I$(INCLUDEDIR) + +SRCFILES:=$(wildcard *.c) + +OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c)))) + +libs: $(OBJECTS) + +DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d) + +include $(wildcard $(DEPFILES)) + +include $(wildcard ../../../../dep.mk) + +$(RELEASEDIR)%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@ + +.PHONY: include +include: $(addprefix $(INCLUDEDIR),$(wildcard *.h)) + +$(INCLUDEDIR)%.h: %.h + $(CP) $< $@ + +clean: + rm -rf ${OBJECTS} + rm -rf $(DEPFILES) diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps.c b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps.c new file mode 100644 index 0000000..e8eb9ee --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps.c @@ -0,0 +1,1813 @@ +/****************************************************************************** +* Copyright (C) 2011 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xadcps.c +* @addtogroup xadcps_v2_6 +* @{ +* +* This file contains the driver API functions that can be used to access +* the XADC device. +* +* Refer to the xadcps.h header file for more information about this driver. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.01a bss    02/18/13	Modified XAdcPs_SetSeqChEnables,XAdcPs_SetSeqAvgEnables
+*			XAdcPs_SetSeqInputMode and XAdcPs_SetSeqAcqTime APIs
+*			to fix CR #693371
+* 2.1   bss    08/05/14	Modified Assert for XAdcPs_SetSingleChParams to fix
+*			CR #807563.
+* 2.2	bss	   04/27/14 Modified to use correct Device Config base address
+*						(CR#854437).
+* 2.3   mn     07/09/18 Fix Doxygen warning
+* 2.6   aad    11/02/20 Fix MISRAC Mandatory and Advisory errors.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xadcps.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Function Prototypes *****************************/ + +void XAdcPs_WriteInternalReg(XAdcPs *InstancePtr, u32 RegOffset, u32 Data); +u32 XAdcPs_ReadInternalReg(XAdcPs *InstancePtr, u32 RegOffset); + + +/************************** Variable Definitions ****************************/ + + +/*****************************************************************************/ +/** +* +* This function initializes a specific XAdcPs device/instance. This function +* must be called prior to using the XADC device. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param ConfigPtr points to the XAdcPs device configuration structure. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. If the address translation is not used then the +* physical address is passed. +* Unexpected errors may occur if the address mapping is changed +* after this function is invoked. +* +* @return +* - XST_SUCCESS if successful. +* +* @note The user needs to first call the XAdcPs_LookupConfig() API +* which returns the Configuration structure pointer which is +* passed as a parameter to the XAdcPs_CfgInitialize() API. +* +******************************************************************************/ +int XAdcPs_CfgInitialize(XAdcPs *InstancePtr, XAdcPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + + u32 RegValue; + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + + /* + * Set the values read from the device config and the base address. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Config.BaseAddress = EffectiveAddr; + + /* Write Unlock value to Device Config Unlock register */ + XAdcPs_WriteReg(XPAR_XDCFG_0_BASEADDR, + XADCPS_UNLK_OFFSET, XADCPS_UNLK_VALUE); + + /* Enable the PS access of xadc and set FIFO thresholds */ + + RegValue = XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET); + + RegValue = RegValue | XADCPS_CFG_ENABLE_MASK | + XADCPS_CFG_CFIFOTH_MASK | XADCPS_CFG_DFIFOTH_MASK; + + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET, RegValue); + + /* Release xadc from reset */ + + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, 0x00); + + /* + * Indicate the instance is now ready to use and + * initialized without error. + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** +* +* The functions sets the contents of the Config Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetConfigRegister(XAdcPs *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET, Data); + +} + + +/****************************************************************************/ +/** +* +* The functions reads the contents of the Config Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the Config Register. +* Use the XADCPS_SR_*_MASK constants defined in xadcps_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetConfigRegister(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Config Register and return the value. + */ + return XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_CFG_OFFSET); +} + + +/****************************************************************************/ +/** +* +* The functions reads the contents of the Miscellaneous Status Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the Miscellaneous +* Status Register. Use the XADCPS_MSTS_*_MASK constants defined +* in xadcps_hw.h to interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetMiscStatus(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Miscellaneous Status Register and return the value. + */ + return XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_MSTS_OFFSET); +} + + +/****************************************************************************/ +/** +* +* The functions sets the contents of the Miscellaneous Control register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the 32 bit data to be written to the Register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetMiscCtrlRegister(XAdcPs *InstancePtr, u32 Data) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Write to the Miscellaneous control register Register. + */ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, Data); +} + + +/****************************************************************************/ +/** +* +* The functions reads the contents of the Miscellaneous control register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the Config Register. +* Use the XADCPS_SR_*_MASK constants defined in xadcps_hw.h to +* interpret the returned value. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetMiscCtrlRegister(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Miscellaneous control register and return the value. + */ + return XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET); +} + + +/*****************************************************************************/ +/** +* +* This function resets the XADC Hard Macro in the device. +* +* @param InstancePtr is a pointer to the Xxadc instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XAdcPs_Reset(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Generate the reset by Control + * register and release from reset + */ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, 0x10); + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, + XADCPS_MCTL_OFFSET, 0x00); +} + + +/****************************************************************************/ +/** +* +* Get the ADC converted data for the specified channel. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Channel is the channel number. Use the XADCPS_CH_* defined in +* the file xadcps.h. +* The valid channels are +* - 0 to 6 +* - 13 to 31 +* +* @return A 16-bit value representing the ADC converted data for the +* specified channel. The XADC Monitor/ADC device guarantees +* a 10 bit resolution for the ADC converted data and data is the +* 10 MSB bits of the 16 data read from the device. +* +* @note The channels 7,8,9 are used for calibration of the device and +* hence there is no associated data with this channel. +* +*****************************************************************************/ +u16 XAdcPs_GetAdcData(XAdcPs *InstancePtr, u8 Channel) +{ + + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel <= XADCPS_CH_VBRAM) || + ((Channel >= XADCPS_CH_VCCPINT) && + (Channel <= XADCPS_CH_AUX_MAX))); + + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_TEMP_OFFSET + (u32)Channel)); + return (u16) RegData; +} + +/****************************************************************************/ +/** +* +* This function gets the calibration coefficient data for the specified +* parameter. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param CoeffType specifies the calibration coefficient +* to be read. Use XADCPS_CALIB_* constants defined in xadcps.h to +* specify the calibration coefficient to be read. +* +* @return A 16-bit value representing the calibration coefficient. +* The XADC device guarantees a 10 bit resolution for +* the ADC converted data and data is the 10 MSB bits of the 16 +* data read from the device. +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetCalibCoefficient(XAdcPs *InstancePtr, u8 CoeffType) +{ + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(CoeffType <= XADCPS_CALIB_GAIN_ERROR_COEFF); + + /* + * Read the selected calibration coefficient. + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_ADC_A_SUPPLY_CALIB_OFFSET + + (u32)CoeffType)); + return (u16) RegData; +} + +/****************************************************************************/ +/** +* +* This function reads the Minimum/Maximum measurement for one of the +* specified parameters. Use XADCPS_MAX_* and XADCPS_MIN_* constants defined in +* xadcps.h to specify the parameters (Temperature, VccInt, VccAux, VBram, +* VccPInt, VccPAux and VccPDro). +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param MeasurementType specifies the parameter for which the +* Minimum/Maximum measurement has to be read. +* Use XADCPS_MAX_* and XADCPS_MIN_* constants defined in xadcps.h to +* specify the data to be read. +* +* @return A 16-bit value representing the maximum/minimum measurement for +* specified parameter. +* The XADC device guarantees a 10 bit resolution for +* the ADC converted data and data is the 10 MSB bits of the 16 +* data read from the device. +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetMinMaxMeasurement(XAdcPs *InstancePtr, u8 MeasurementType) +{ + u32 RegData; + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((MeasurementType <= XADCPS_MAX_VCCPDRO) || + ((MeasurementType >= XADCPS_MIN_VCCPINT) && + (MeasurementType <= XADCPS_MIN_VCCPDRO))) + + /* + * Read and return the specified Minimum/Maximum measurement. + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_MAX_TEMP_OFFSET + + (u32)MeasurementType)); + return (u16) RegData; +} + +/****************************************************************************/ +/** +* +* This function sets the number of samples of averaging that is to be done for +* all the channels in both the single channel mode and sequence mode of +* operations. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Average is the number of samples of averaging programmed to the +* Configuration Register 0. Use the XADCPS_AVG_* definitions defined +* in xadcps.h file : +* - XADCPS_AVG_0_SAMPLES for no averaging +* - XADCPS_AVG_16_SAMPLES for 16 samples of averaging +* - XADCPS_AVG_64_SAMPLES for 64 samples of averaging +* - XADCPS_AVG_256_SAMPLES for 256 samples of averaging +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetAvg(XAdcPs *InstancePtr, u8 Average) +{ + u32 RegData; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Average <= XADCPS_AVG_256_SAMPLES); + + /* + * Write the averaging value into the Configuration Register 0. + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + (~XADCPS_CFR0_AVG_VALID_MASK); + + RegData |= (((u32) Average << XADCPS_CFR0_AVG_SHIFT)); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegData); + +} + +/****************************************************************************/ +/** +* +* This function returns the number of samples of averaging configured for all +* the channels in the Configuration Register 0. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The averaging read from the Configuration Register 0 is +* returned. Use the XADCPS_AVG_* bit definitions defined in +* xadcps.h file to interpret the returned value : +* - XADCPS_AVG_0_SAMPLES means no averaging +* - XADCPS_AVG_16_SAMPLES means 16 samples of averaging +* - XADCPS_AVG_64_SAMPLES means 64 samples of averaging +* - XADCPS_AVG_256_SAMPLES means 256 samples of averaging +* +* @note None. +* +*****************************************************************************/ +u8 XAdcPs_GetAvg(XAdcPs *InstancePtr) +{ + u32 Average; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the averaging value from the Configuration Register 0. + */ + Average = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_AVG_VALID_MASK; + + + return ((u8) (Average >> XADCPS_CFR0_AVG_SHIFT)); +} + +/****************************************************************************/ +/** +* +* The function sets the given parameters in the Configuration Register 0 in +* the single channel mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Channel is the channel number for the singel channel mode. +* The valid channels are 0 to 6, 8, and 13 to 31. +* If the external Mux is used then this specifies the channel +* oonnected to the external Mux. Please read the Device Spec +* to know which channels are valid. +* @param IncreaseAcqCycles is a boolean parameter which specifies whether +* the Acquisition time for the external channels has to be +* increased to 10 ADCCLK cycles (specify TRUE) or remain at the +* default 4 ADCCLK cycles (specify FALSE). This parameter is +* only valid for the external channels. +* @param IsEventMode specifies whether the operation of the ADC is Event +* driven or Continuous mode. +* @param IsDifferentialMode is a boolean parameter which specifies +* unipolar(specify FALSE) or differential mode (specify TRUE) for +* the analog inputs. The input mode is only valid for the +* external channels. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the Configuration Register 0. +* - XST_FAILURE if the channel sequencer is enabled or the input +* parameters are not valid for the selected channel. +* +* @note +* - The number of samples for the averaging for all the channels +* is set by using the function XAdcPs_SetAvg. +* - The calibration of the device is done by doing a ADC +* conversion on the calibration channel(channel 8). The input +* parameters IncreaseAcqCycles, IsDifferentialMode and +* IsEventMode are not valid for this channel +* +* +*****************************************************************************/ +int XAdcPs_SetSingleChParams(XAdcPs *InstancePtr, + u8 Channel, + int IncreaseAcqCycles, + int IsEventMode, + int IsDifferentialMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Channel <= XADCPS_CH_VBRAM) || + (Channel == XADCPS_CH_ADC_CALIB) || + ((Channel >= XADCPS_CH_VCCPINT) && + (Channel <= XADCPS_CH_AUX_MAX))); + Xil_AssertNonvoid((IncreaseAcqCycles == 0x1) || + (IncreaseAcqCycles == 0x0)); + Xil_AssertNonvoid((IsEventMode == 0x1) || (IsEventMode == 0x0)); + Xil_AssertNonvoid((IsDifferentialMode == 0x1) || + (IsDifferentialMode == 0x0)); + + /* + * Check if the device is in single channel mode else return failure + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != + XADCPS_SEQ_MODE_SINGCHAN)) { + return XST_FAILURE; + } + + /* + * Read the Configuration Register 0. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + XADCPS_CFR0_AVG_VALID_MASK; + + /* + * Select the number of acquisition cycles. The acquisition cycles is + * only valid for the external channels. + */ + if (IncreaseAcqCycles == 0x1) { + if (((Channel >= XADCPS_CH_AUX_MIN) && + (Channel <= XADCPS_CH_AUX_MAX)) || + (Channel == XADCPS_CH_VPVN)){ + RegValue |= XADCPS_CFR0_ACQ_MASK; + } else { + return XST_FAILURE; + } + + } + + /* + * Select the input mode. The input mode is only valid for the + * external channels. + */ + if (IsDifferentialMode == 0x1) { + + if ((Channel >= XADCPS_CH_AUX_MIN) || + (Channel == XADCPS_CH_VPVN)){ + RegValue |= XADCPS_CFR0_DU_MASK; + } else { + return XST_FAILURE; + } + } + + /* + * Select the ADC mode. + */ + if (IsEventMode == 0x1) { + RegValue |= XADCPS_CFR0_EC_MASK; + } + + /* + * Write the given values into the Configuration Register 0. + */ + RegValue |= ((u32)Channel & XADCPS_CFR0_CHANNEL_MASK); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegValue); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function enables the alarm outputs for the specified alarms in the +* Configuration Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AlmEnableMask is the bit-mask of the alarm outputs to be enabled +* in the Configuration Register 1. +* Bit positions of 1 will be enabled. Bit positions of 0 will be +* disabled. This mask is formed by OR'ing XADCPS_CFR1_ALM_*_MASK and +* XADCPS_CFR1_OT_MASK masks defined in xadcps_hw.h. +* +* @return None. +* +* @note The implementation of the alarm enables in the Configuration +* register 1 is such that the alarms for bit positions of 1 will +* be disabled and alarms for bit positions of 0 will be enabled. +* The alarm outputs specified by the AlmEnableMask are negated +* before writing to the Configuration Register 1. +* +* +*****************************************************************************/ +void XAdcPs_SetAlarmEnables(XAdcPs *InstancePtr, u16 AlmEnableMask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + RegValue = XAdcPs_ReadInternalReg(InstancePtr, XADCPS_CFR1_OFFSET); + + RegValue &= ~XADCPS_CFR1_ALM_ALL_MASK; + RegValue |= (~(u32)AlmEnableMask & XADCPS_CFR1_ALM_ALL_MASK); + + /* + * Enable/disables the alarm enables for the specified alarm bits in the + * Configuration Register 1. + */ + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR1_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* This function gets the status of the alarm output enables in the +* Configuration Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return This is the bit-mask of the enabled alarm outputs in the +* Configuration Register 1. Use the masks XADCPS_CFR1_ALM*_* and +* XADCPS_CFR1_OT_MASK defined in xadcps_hw.h to interpret the +* returned value. +* Bit positions of 1 indicate that the alarm output is enabled. +* Bit positions of 0 indicate that the alarm output is disabled. +* +* +* @note The implementation of the alarm enables in the Configuration +* register 1 is such that alarms for the bit positions of 1 will +* be disabled and alarms for bit positions of 0 will be enabled. +* The enabled alarm outputs returned by this function is the +* negated value of the the data read from the Configuration +* Register 1. +* +*****************************************************************************/ +u16 XAdcPs_GetAlarmEnables(XAdcPs *InstancePtr) +{ + u32 RegValue; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the status of alarm output enables from the Configuration + * Register 1. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET) & XADCPS_CFR1_ALM_ALL_MASK; + return (u16) (~RegValue & XADCPS_CFR1_ALM_ALL_MASK); +} + +/****************************************************************************/ +/** +* +* This function enables the specified calibration in the Configuration +* Register 1 : +* +* - XADCPS_CFR1_CAL_ADC_OFFSET_MASK : Calibration 0 -ADC offset correction +* - XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK : Calibration 1 -ADC gain and offset +* correction +* - XADCPS_CFR1_CAL_PS_OFFSET_MASK : Calibration 2 -Power Supply sensor +* offset correction +* - XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK : Calibration 3 -Power Supply sensor +* gain and offset correction +* - XADCPS_CFR1_CAL_DISABLE_MASK : No Calibration +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Calibration is the Calibration to be applied. +* Use XADCPS_CFR1_CAL*_* bits defined in xadcps_hw.h. +* Multiple calibrations can be enabled at a time by oring the +* XADCPS_CFR1_CAL_ADC_* and XADCPS_CFR1_CAL_PS_* bits. +* Calibration can be disabled by specifying + XADCPS_CFR1_CAL_DISABLE_MASK; +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetCalibEnables(XAdcPs *InstancePtr, u16 Calibration) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(((Calibration >= XADCPS_CFR1_CAL_ADC_OFFSET_MASK) && + (Calibration <= XADCPS_CFR1_CAL_VALID_MASK)) || + (Calibration == XADCPS_CFR1_CAL_DISABLE_MASK)); + + /* + * Set the specified calibration in the Configuration Register 1. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET); + + RegValue &= ~XADCPS_CFR1_CAL_VALID_MASK; + RegValue |= ((u32)Calibration & XADCPS_CFR1_CAL_VALID_MASK); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR1_OFFSET, + RegValue); + +} + +/****************************************************************************/ +/** +* +* This function reads the value of the calibration enables from the +* Configuration Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The value of the calibration enables in the Configuration +* Register 1 : +* - XADCPS_CFR1_CAL_ADC_OFFSET_MASK : ADC offset correction +* - XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK : ADC gain and offset +* correction +* - XADCPS_CFR1_CAL_PS_OFFSET_MASK : Power Supply sensor offset +* correction +* - XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK : Power Supply sensor +* gain and offset correction +* - XADCPS_CFR1_CAL_DISABLE_MASK : No Calibration +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetCalibEnables(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the calibration enables from the Configuration Register 1. + */ + return (u16) XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET) & XADCPS_CFR1_CAL_VALID_MASK; + +} + +/****************************************************************************/ +/** +* +* This function sets the specified Channel Sequencer Mode in the Configuration +* Register 1 : +* - Default safe mode (XADCPS_SEQ_MODE_SAFE) +* - One pass through sequence (XADCPS_SEQ_MODE_ONEPASS) +* - Continuous channel sequencing (XADCPS_SEQ_MODE_CONTINPASS) +* - Single Channel/Sequencer off (XADCPS_SEQ_MODE_SINGCHAN) +* - Simulataneous sampling mode (XADCPS_SEQ_MODE_SIMUL_SAMPLING) +* - Independent mode (XADCPS_SEQ_MODE_INDEPENDENT) +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param SequencerMode is the sequencer mode to be set. +* Use XADCPS_SEQ_MODE_* bits defined in xadcps.h. +* @return None. +* +* @note Only one of the modes can be enabled at a time. Please +* read the Spec of the XADC for further information about the +* sequencer modes. +* +* +*****************************************************************************/ +void XAdcPs_SetSequencerMode(XAdcPs *InstancePtr, u8 SequencerMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((SequencerMode <= XADCPS_SEQ_MODE_SIMUL_SAMPLING) || + (SequencerMode == XADCPS_SEQ_MODE_INDEPENDENT)); + + /* + * Set the specified sequencer mode in the Configuration Register 1. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET); + RegValue &= (~ XADCPS_CFR1_SEQ_VALID_MASK); + RegValue |= (((u32)SequencerMode << XADCPS_CFR1_SEQ_SHIFT) & + XADCPS_CFR1_SEQ_VALID_MASK); + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR1_OFFSET, + RegValue); + +} + +/****************************************************************************/ +/** +* +* This function gets the channel sequencer mode from the Configuration +* Register 1. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The channel sequencer mode : +* - XADCPS_SEQ_MODE_SAFE : Default safe mode +* - XADCPS_SEQ_MODE_ONEPASS : One pass through sequence +* - XADCPS_SEQ_MODE_CONTINPASS : Continuous channel sequencing +* - XADCPS_SEQ_MODE_SINGCHAN : Single channel/Sequencer off +* - XADCPS_SEQ_MODE_SIMUL_SAMPLING : Simulataneous sampling mode +* - XADCPS_SEQ_MODE_INDEPENDENT : Independent mode +* +* +* @note None. +* +*****************************************************************************/ +u8 XAdcPs_GetSequencerMode(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the channel sequencer mode from the Configuration Register 1. + */ + return ((u8) ((XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR1_OFFSET) & XADCPS_CFR1_SEQ_VALID_MASK) >> + XADCPS_CFR1_SEQ_SHIFT)); + +} + +/****************************************************************************/ +/** +* +* The function sets the frequency of the ADCCLK by configuring the DCLK to +* ADCCLK ratio in the Configuration Register #2 +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Divisor is clock divisor used to derive ADCCLK from DCLK. +* Valid values of the divisor are +* - 0 to 255. Values 0, 1, 2 are all mapped to 2. +* Refer to the device specification for more details +* +* @return None. +* +* @note - The ADCCLK is an internal clock used by the ADC and is +* synchronized to the DCLK clock. The ADCCLK is equal to DCLK +* divided by the user selection in the Configuration Register 2. +* - There is no Assert on the minimum value of the Divisor. +* +*****************************************************************************/ +void XAdcPs_SetAdcClkDivisor(XAdcPs *InstancePtr, u8 Divisor) +{ + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Write the divisor value into the Configuration Register #2. + */ + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR2_OFFSET, + ((u32)Divisor << XADCPS_CFR2_CD_SHIFT)); + +} + +/****************************************************************************/ +/** +* +* The function gets the ADCCLK divisor from the Configuration Register 2. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The divisor read from the Configuration Register 2. +* +* @note The ADCCLK is an internal clock used by the ADC and is +* synchronized to the DCLK clock. The ADCCLK is equal to DCLK +* divided by the user selection in the Configuration Register 2. +* +*****************************************************************************/ +u8 XAdcPs_GetAdcClkDivisor(XAdcPs *InstancePtr) +{ + u16 Divisor; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the divisor value from the Configuration Register 2. + */ + Divisor = (u16) XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR2_OFFSET); + + return (u8) (Divisor >> XADCPS_CFR2_CD_SHIFT); +} + +/****************************************************************************/ +/** +* +* This function enables the specified channels in the ADC Channel Selection +* Sequencer Registers. The sequencer must be disabled before writing to these +* regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param ChEnableMask is the bit mask of all the channels to be enabled. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to specify the Channel +* numbers. Bit masks of 1 will be enabled and bit mask of 0 will +* be disabled. +* The ChEnableMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Selection Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Selection Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None +* +*****************************************************************************/ +int XAdcPs_SetSeqChEnables(XAdcPs *InstancePtr, u32 ChEnableMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Enable the specified channels in the ADC Channel Selection Sequencer + * Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ00_OFFSET, + (ChEnableMask & XADCPS_SEQ00_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ01_OFFSET, + (ChEnableMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ01_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the channel enable bits status from the ADC Channel +* Selection Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Gets the channel enable bits. Use XADCPS_SEQ_CH__* defined in +* xadcps_hw.h to interpret the Channel numbers. Bit masks of 1 +* are the channels that are enabled and bit mask of 0 are +* the channels that are disabled. +* +* @return None +* +* @note None +* +*****************************************************************************/ +u32 XAdcPs_GetSeqChEnables(XAdcPs *InstancePtr) +{ + u32 RegValEnable; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the channel enable bits for all the channels from the ADC + * Channel Selection Register. + */ + RegValEnable = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ00_OFFSET) & + XADCPS_SEQ00_CH_VALID_MASK; + RegValEnable |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ01_OFFSET) & + XADCPS_SEQ01_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + + return RegValEnable; +} + +/****************************************************************************/ +/** +* +* This function enables the averaging for the specified channels in the ADC +* Channel Averaging Enable Sequencer Registers. The sequencer must be disabled +* before writing to these regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AvgEnableChMask is the bit mask of all the channels for which +* averaging is to be enabled. Use XADCPS_SEQ_CH__* defined in +* xadcps_hw.h to specify the Channel numbers. Averaging will be +* enabled for bit masks of 1 and disabled for bit mask of 0. +* The AvgEnableChMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Averaging Enable Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Averaging Enables Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None +* +*****************************************************************************/ +int XAdcPs_SetSeqAvgEnables(XAdcPs *InstancePtr, u32 AvgEnableChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Enable/disable the averaging for the specified channels in the + * ADC Channel Averaging Enables Sequencer Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ02_OFFSET, + (AvgEnableChMask & XADCPS_SEQ02_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ03_OFFSET, + (AvgEnableChMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ03_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function returns the channels for which the averaging has been enabled +* in the ADC Channel Averaging Enables Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @returns The status of averaging (enabled/disabled) for all the channels. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* averaging is enabled and bit mask of 0 are the channels for +* averaging is disabled +* +* @note None +* +*****************************************************************************/ +u32 XAdcPs_GetSeqAvgEnables(XAdcPs *InstancePtr) +{ + u32 RegValAvg; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the averaging enable status for all the channels from the + * ADC Channel Averaging Enables Sequencer Registers. + */ + RegValAvg = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ02_OFFSET) & XADCPS_SEQ02_CH_VALID_MASK; + RegValAvg |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ03_OFFSET) & XADCPS_SEQ03_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + return RegValAvg; +} + +/****************************************************************************/ +/** +* +* This function sets the Analog input mode for the specified channels in the ADC +* Channel Analog-Input Mode Sequencer Registers. The sequencer must be disabled +* before writing to these regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param InputModeChMask is the bit mask of all the channels for which +* the input mode is differential mode. Use XADCPS_SEQ_CH__* defined +* in xadcps_hw.h to specify the channel numbers. Differential +* input mode will be set for bit masks of 1 and unipolar input +* mode for bit masks of 0. +* The InputModeChMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Analog-Input Mode Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the ADC Channel Analog-Input Mode Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None +* +*****************************************************************************/ +int XAdcPs_SetSeqInputMode(XAdcPs *InstancePtr, u32 InputModeChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Set the input mode for the specified channels in the ADC Channel + * Analog-Input Mode Sequencer Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ04_OFFSET, + (InputModeChMask & XADCPS_SEQ04_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ05_OFFSET, + (InputModeChMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ05_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the Analog input mode for all the channels from +* the ADC Channel Analog-Input Mode Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @returns The input mode for all the channels. +* Use XADCPS_SEQ_CH_* defined in xadcps_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* input mode is differential and bit mask of 0 are the channels +* for which input mode is unipolar. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetSeqInputMode(XAdcPs *InstancePtr) +{ + u32 InputMode; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the input mode for all the channels from the ADC Channel + * Analog-Input Mode Sequencer Registers. + */ + InputMode = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ04_OFFSET) & + XADCPS_SEQ04_CH_VALID_MASK; + InputMode |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ05_OFFSET) & + XADCPS_SEQ05_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + return InputMode; +} + +/****************************************************************************/ +/** +* +* This function sets the number of Acquisition cycles in the ADC Channel +* Acquisition Time Sequencer Registers. The sequencer must be disabled +* before writing to these regsiters. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AcqCyclesChMask is the bit mask of all the channels for which +* the number of acquisition cycles is to be extended. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to specify the Channel +* numbers. Acquisition cycles will be extended to 10 ADCCLK cycles +* for bit masks of 1 and will be the default 4 ADCCLK cycles for +* bit masks of 0. +* The AcqCyclesChMask is a 32 bit mask that is written to the two +* 16 bit ADC Channel Acquisition Time Sequencer Registers. +* +* @return +* - XST_SUCCESS if the given values were written successfully to +* the Channel Sequencer Registers. +* - XST_FAILURE if the channel sequencer is enabled. +* +* @note None. +* +*****************************************************************************/ +int XAdcPs_SetSeqAcqTime(XAdcPs *InstancePtr, u32 AcqCyclesChMask) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * The sequencer must be disabled for writing any of these registers + * Return XST_FAILURE if the channel sequencer is enabled. + */ + if ((XAdcPs_GetSequencerMode(InstancePtr) != + XADCPS_SEQ_MODE_SAFE)) { + return XST_FAILURE; + } + + /* + * Set the Acquisition time for the specified channels in the + * ADC Channel Acquisition Time Sequencer Registers. + */ + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ06_OFFSET, + (AcqCyclesChMask & XADCPS_SEQ06_CH_VALID_MASK)); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_SEQ07_OFFSET, + (AcqCyclesChMask >> XADCPS_SEQ_CH_AUX_SHIFT) & + XADCPS_SEQ07_CH_VALID_MASK); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function gets the status of acquisition from the ADC Channel Acquisition +* Time Sequencer Registers. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @returns The acquisition time for all the channels. +* Use XADCPS_SEQ_CH__* defined in xadcps_hw.h to interpret the +* Channel numbers. Bit masks of 1 are the channels for which +* acquisition cycles are extended and bit mask of 0 are the +* channels for which acquisition cycles are not extended. +* +* @note None +* +*****************************************************************************/ +u32 XAdcPs_GetSeqAcqTime(XAdcPs *InstancePtr) +{ + u32 RegValAcq; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get the Acquisition cycles for the specified channels from the ADC + * Channel Acquisition Time Sequencer Registers. + */ + RegValAcq = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ06_OFFSET) & + XADCPS_SEQ06_CH_VALID_MASK; + RegValAcq |= (XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_SEQ07_OFFSET) & + XADCPS_SEQ07_CH_VALID_MASK) << + XADCPS_SEQ_CH_AUX_SHIFT; + + return RegValAcq; +} + +/****************************************************************************/ +/** +* +* This functions sets the contents of the given Alarm Threshold Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AlarmThrReg is the index of an Alarm Threshold Register to +* be set. Use XADCPS_ATR_* constants defined in xadcps.h to +* specify the index. +* @param Value is the 16-bit threshold value to write into the register. +* +* @return None. +* +* @note Use XAdcPs_SetOverTemp() to set the Over Temperature upper +* threshold value. +* +*****************************************************************************/ +void XAdcPs_SetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg, u16 Value) +{ + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(AlarmThrReg <= XADCPS_ATR_VCCPDRO_LOWER); + + /* + * Write the value into the specified Alarm Threshold Register. + */ + XAdcPs_WriteInternalReg(InstancePtr, (XADCPS_ATR_TEMP_UPPER_OFFSET + + (u32)AlarmThrReg), Value); + +} + +/****************************************************************************/ +/** +* +* This function returns the contents of the specified Alarm Threshold Register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param AlarmThrReg is the index of an Alarm Threshold Register +* to be read. Use XADCPS_ATR_* constants defined in xadcps_hw.h +* to specify the index. +* +* @return A 16-bit value representing the contents of the selected Alarm +* Threshold Register. +* +* @note None. +* +*****************************************************************************/ +u16 XAdcPs_GetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg) +{ + u32 RegData; + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(AlarmThrReg <= XADCPS_ATR_VCCPDRO_LOWER); + + /* + * Read the specified Alarm Threshold Register and return + * the value + */ + RegData = XAdcPs_ReadInternalReg(InstancePtr, + (XADCPS_ATR_TEMP_UPPER_OFFSET + + (u32)AlarmThrReg)); + + return (u16) RegData; +} + + +/****************************************************************************/ +/** +* +* This function enables programming of the powerdown temperature for the +* OverTemp signal in the OT Powerdown register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_EnableUserOverTemp(XAdcPs *InstancePtr) +{ + u16 OtUpper; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the OT upper Alarm Threshold Register. + */ + OtUpper = (u16)(XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET)); + OtUpper &= ~((u16)XADCPS_ATR_OT_UPPER_ENB_MASK); + + /* + * Preserve the powerdown value and write OT enable value the into the + * OT Upper Alarm Threshold Register. + */ + OtUpper |= XADCPS_ATR_OT_UPPER_ENB_VAL; + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET, (u32)OtUpper); +} + +/****************************************************************************/ +/** +* +* This function disables programming of the powerdown temperature for the +* OverTemp signal in the OT Powerdown register. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XAdcPs_DisableUserOverTemp(XAdcPs *InstancePtr) +{ + u16 OtUpper; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the OT Upper Alarm Threshold Register. + */ + OtUpper = (u16)(XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET)); + OtUpper &= ~((u16)XADCPS_ATR_OT_UPPER_ENB_MASK); + + XAdcPs_WriteInternalReg(InstancePtr, + XADCPS_ATR_OT_UPPER_OFFSET, (u32)OtUpper); +} + + +/****************************************************************************/ +/** +* +* The function enables the Event mode or Continuous mode in the sequencer mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param IsEventMode is a boolean parameter that specifies continuous +* sampling (specify FALSE) or event driven sampling mode (specify +* TRUE) for the given channel. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetSequencerEvent(XAdcPs *InstancePtr, int IsEventMode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((IsEventMode == 0x1) || (IsEventMode == 0x0)); + + /* + * Read the Configuration Register 0. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + (~XADCPS_CFR0_EC_MASK); + + /* + * Set the ADC mode. + */ + if (IsEventMode == 0x1) { + RegValue |= XADCPS_CFR0_EC_MASK; + } else { + RegValue &= ~XADCPS_CFR0_EC_MASK; + } + + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function returns the sampling mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return The sampling mode +* - 0 specifies continuous sampling +* - 1 specifies event driven sampling mode +* +* @note None. +* +*****************************************************************************/ +int XAdcPs_GetSamplingMode(XAdcPs *InstancePtr) +{ + u32 Mode; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the sampling mode from the Configuration Register 0. + */ + Mode = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + XADCPS_CFR0_EC_MASK; + if (Mode > 0U) { + + return 1; + } + + return (0); +} + + +/****************************************************************************/ +/** +* +* This function sets the External Mux mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param MuxMode specifies whether External Mux is used +* - FALSE specifies NO external MUX +* - TRUE specifies External Mux is used +* @param Channel specifies the channel to be used for the +* external Mux. Please read the Device Spec for which +* channels are valid for which mode. +* +* @return None. +* +* @note There is no Assert in this function for checking the channel +* number if the external Mux is used. The user should provide a +* valid channel number. +* +*****************************************************************************/ +void XAdcPs_SetMuxMode(XAdcPs *InstancePtr, int MuxMode, u8 Channel) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((MuxMode == 0x1) || (MuxMode == 0x0)); + + /* + * Read the Configuration Register 0. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR0_OFFSET) & + (~XADCPS_CFR0_MUX_MASK); + /* + * Select the Mux mode and the channel to be used. + */ + if (MuxMode == 0x1) { + RegValue |= XADCPS_CFR0_MUX_MASK; + RegValue |= ((u32)Channel & XADCPS_CFR0_CHANNEL_MASK); + + } + + /* + * Write the mux mode into the Configuration Register 0. + */ + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR0_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function sets the Power Down mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mode specifies the Power Down Mode +* - XADCPS_PD_MODE_NONE specifies NO Power Down (Both ADC A and +* ADC B are enabled) +* - XADCPS_PD_MODE_ADCB specfies the Power Down of ADC B +* - XADCPS_PD_MODE_XADC specifies the Power Down of +* both ADC A and ADC B. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_SetPowerdownMode(XAdcPs *InstancePtr, u32 Mode) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(Mode < XADCPS_PD_MODE_XADC); + + + /* + * Read the Configuration Register 2. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR2_OFFSET) & + (~XADCPS_CFR2_PD_MASK); + /* + * Select the Power Down mode. + */ + RegValue |= (Mode << XADCPS_CFR2_PD_SHIFT); + + XAdcPs_WriteInternalReg(InstancePtr, XADCPS_CFR2_OFFSET, + RegValue); +} + +/****************************************************************************/ +/** +* +* This function gets the Power Down mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Mode specifies the Power Down Mode +* - XADCPS_PD_MODE_NONE specifies NO Power Down (Both ADC A and +* ADC B are enabled) +* - XADCPS_PD_MODE_ADCB specfies the Power Down of ADC B +* - XADCPS_PD_MODE_XADC specifies the Power Down of +* both ADC A and ADC B. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_GetPowerdownMode(XAdcPs *InstancePtr) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read the Power Down Mode. + */ + RegValue = XAdcPs_ReadInternalReg(InstancePtr, + XADCPS_CFR2_OFFSET) & + (~XADCPS_CFR2_PD_MASK); + /* + * Return the Power Down mode. + */ + return (RegValue >> XADCPS_CFR2_PD_SHIFT); + +} + +/****************************************************************************/ +/** +* +* This function is used for writing to XADC Registers using the command FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param RegOffset is the offset of the XADC register to be written. +* @param Data is the data to be written. +* +* @return None. +* +* @note None. +* +* +*****************************************************************************/ +void XAdcPs_WriteInternalReg(XAdcPs *InstancePtr, u32 RegOffset, u32 Data) +{ + u32 RegData; + + /** + * Write the Data into the FIFO Register. + */ + RegData = (XADCPS_JTAG_CMD_WRITE_MASK) | + ((RegOffset << XADCPS_JTAG_ADDR_SHIFT) & XADCPS_JTAG_ADDR_MASK) | + (Data & XADCPS_JTAG_DATA_MASK); + + XAdcPs_WriteFifo(InstancePtr, RegData); + + /** + * Read the Read FIFO after any write since for each write + * one location of Read FIFO gets updated + */ + XAdcPs_ReadFifo(InstancePtr); + +} + + +/****************************************************************************/ +/** +* +* This function is used for reading from the XADC Registers using the Data FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param RegOffset is the offset of the XADC register to be read. +* +* @return Data read from the FIFO +* +* @note None. +* +* +*****************************************************************************/ +u32 XAdcPs_ReadInternalReg(XAdcPs *InstancePtr, u32 RegOffset) +{ + + u32 RegData; + + RegData = (XADCPS_JTAG_CMD_READ_MASK) | + ((RegOffset << XADCPS_JTAG_ADDR_SHIFT) & XADCPS_JTAG_ADDR_MASK); + + /* Read cmd to FIFO*/ + XAdcPs_WriteFifo(InstancePtr, RegData); + + /* Do a Dummy read */ + RegData = XAdcPs_ReadFifo(InstancePtr); + + /* Do a Dummy write to get the actual read */ + XAdcPs_WriteFifo(InstancePtr, RegData); + + /* Do the Actual read */ + RegData = XAdcPs_ReadFifo(InstancePtr); + + return RegData; + +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps.h b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps.h new file mode 100644 index 0000000..980f394 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps.h @@ -0,0 +1,571 @@ +/****************************************************************************** +* Copyright (C) 2011 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xadcps.h +* @addtogroup xadcps_v2_6 +* @{ +* @details +* +* The XAdcPs driver supports the Xilinx XADC/ADC device. +* +* The XADC/ADC device has the following features: +* - 10-bit, 200-KSPS (kilo samples per second) +* Analog-to-Digital Converter (ADC) +* - Monitoring of on-chip supply voltages and temperature +* - 1 dedicated differential analog-input pair and +* 16 auxiliary differential analog-input pairs +* - Automatic alarms based on user defined limits for the on-chip +* supply voltages and temperature +* - Automatic Channel Sequencer, programmable averaging, programmable +* acquisition time for the external inputs, unipolar or differential +* input selection for the external inputs +* - Inbuilt Calibration +* - Optional interrupt request generation +* +* +* The user should refer to the hardware device specification for detailed +* information about the device. +* +* This header file contains the prototypes of driver functions that can +* be used to access the XADC/ADC device. +* +* +* XADC Channel Sequencer Modes +* +* The XADC Channel Sequencer supports the following operating modes: +* +* - Default : This is the default mode after power up. +* In this mode of operation the XADC operates in +* a sequence mode, monitoring the on chip sensors: +* Temperature, VCCINT, and VCCAUX. +* - One pass through sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers for a single pass and then stops. +* - Continuous cycling of sequence : In this mode the XADC +* converts the channels enabled in the Sequencer Channel Enable +* registers continuously. +* - Single channel mode: In this mode the XADC Channel +* Sequencer is disabled and the XADC operates in a +* Single Channel Mode. +* The XADC can operate either in a Continuous or Event +* driven sampling mode in the single channel mode. +* - Simultaneous Sampling Mode: In this mode the XADC Channel +* Sequencer will automatically sequence through eight fixed pairs +* of auxiliary analog input channels for simulataneous conversion. +* - Independent ADC mode: In this mode the first ADC (A) is used to +* is used to implement a fixed monitoring mode similar to the +* default mode but the alarm fucntions ar eenabled. +* The second ADC (B) is available to be used with external analog +* input channels only. +* +* Read the XADC spec for more information about the sequencer modes. +* +* Initialization and Configuration +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the XADC/ADC device. +* +* XAdcPs_CfgInitialize() API is used to initialize the XADC/ADC +* device. The user needs to first call the XAdcPs_LookupConfig() API which +* returns the Configuration structure pointer which is passed as a parameter to +* the XAdcPs_CfgInitialize() API. +* +* +* Interrupts +* +* The XADC/ADC device supports interrupt driven mode and the default +* operation mode is polling mode. +* +* The interrupt mode is available only if hardware is configured to support +* interrupts. +* +* This driver does not provide a Interrupt Service Routine (ISR) for the device. +* It is the responsibility of the application to provide one if needed. Refer to +* the interrupt example provided with this driver for details on using the +* device in interrupt mode. +* +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* +* +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* +* Building the driver +* +* The XAdcPs driver is composed of several source files. This allows the user +* to build and link only those parts of the driver that are necessary. +* +* Limitations of the driver +* +* XADC/ADC device can be accessed through the JTAG port and the PLB +* interface. The driver implementation does not support the simultaneous access +* of the device by both these interfaces. The user has to care of this situation +* in the user application code. +* +*

+* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.01a bss    02/18/13	Modified XAdcPs_SetSeqChEnables,XAdcPs_SetSeqAvgEnables
+*			XAdcPs_SetSeqInputMode and XAdcPs_SetSeqAcqTime APIs
+*			in xadcps.c to fix CR #693371
+* 1.03a bss    11/01/13 Modified xadcps_hw.h to use correct Register offsets
+*			CR#749687
+* 2.1   bss    08/05/14 Added declarations for XAdcPs_SetSequencerEvent,
+*			XAdcPs_GetSamplingMode, XAdcPs_SetMuxMode,
+*			XAdcPs_SetPowerdownMode and XAdcPs_GetPowerdownMode
+*			functions.
+*			Modified Assert for XAdcPs_SetSingleChParams in
+*			xadcps.c to fix CR #807563.
+* 2.2   bss    04/27/14 Modified to use correct Device Config base address in
+*						xadcps.c (CR#854437).
+*       ms     01/23/17 Added xil_printf statement in main function for all
+*                       examples to ensure that "Successfully ran" and "Failed"
+*                       strings are available in all examples. This is a fix
+*                       for CR-965028.
+*       ms     03/17/17 Added readme.txt file in examples folder for doxygen
+*                       generation.
+*       ms     04/05/17 Modified Comment lines in functions of xadcps
+*                       examples to recognize it as documentation block
+*                       for doxygen generation.
+* 2.3   mn     07/09/18 Fix Doxygen warning
+* 2.6   aad    11/02/20 Fix MISRAC Mandatory and Advisory errors.
+*       aad    12/17/20 Added missing function declarations and removed
+*			functions with no definitions.
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_H /* Prevent circular inclusions */ +#define XADCPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xadcps_hw.h" + +/************************** Constant Definitions ****************************/ + + +/** + * @name Indexes for the different channels. + * @{ + */ +#define XADCPS_CH_TEMP 0x0U /**< On Chip Temperature */ +#define XADCPS_CH_VCCINT 0x1U /**< VCCINT */ +#define XADCPS_CH_VCCAUX 0x2U /**< VCCAUX */ +#define XADCPS_CH_VPVN 0x3U /**< VP/VN Dedicated analog inputs */ +#define XADCPS_CH_VREFP 0x4U /**< VREFP */ +#define XADCPS_CH_VREFN 0x5U /**< VREFN */ +#define XADCPS_CH_VBRAM 0x6U /**< On-chip VBRAM Data Reg, 7 series */ +#define XADCPS_CH_SUPPLY_CALIB 0x07U /**< Supply Calib Data Reg */ +#define XADCPS_CH_ADC_CALIB 0x08U /**< ADC Offset Channel Reg */ +#define XADCPS_CH_GAINERR_CALIB 0x09U /**< Gain Error Channel Reg */ +#define XADCPS_CH_VCCPINT 0x0DU /**< On-chip PS VCCPINT Channel , Zynq */ +#define XADCPS_CH_VCCPAUX 0x0EU /**< On-chip PS VCCPAUX Channel , Zynq */ +#define XADCPS_CH_VCCPDRO 0x0FU /**< On-chip PS VCCPDRO Channel , Zynq */ +#define XADCPS_CH_AUX_MIN 16U /**< Channel number for 1st Aux Channel */ +#define XADCPS_CH_AUX_MAX 31U /**< Channel number for Last Aux channel */ + +/*@}*/ + + +/** + * @name Indexes for reading the Calibration Coefficient Data. + * @{ + */ +#define XADCPS_CALIB_SUPPLY_COEFF 0U /**< Supply Offset Calib Coefficient */ +#define XADCPS_CALIB_ADC_COEFF 1U /**< ADC Offset Calib Coefficient */ +#define XADCPS_CALIB_GAIN_ERROR_COEFF 2U /**< Gain Error Calib Coefficient*/ +/*@}*/ + + +/** + * @name Indexes for reading the Minimum/Maximum Measurement Data. + * @{ + */ +#define XADCPS_MAX_TEMP 0U /**< Maximum Temperature Data */ +#define XADCPS_MAX_VCCINT 1U /**< Maximum VCCINT Data */ +#define XADCPS_MAX_VCCAUX 2U /**< Maximum VCCAUX Data */ +#define XADCPS_MAX_VBRAM 3U /**< Maximum VBRAM Data */ +#define XADCPS_MIN_TEMP 4U /**< Minimum Temperature Data */ +#define XADCPS_MIN_VCCINT 5U /**< Minimum VCCINT Data */ +#define XADCPS_MIN_VCCAUX 6U /**< Minimum VCCAUX Data */ +#define XADCPS_MIN_VBRAM 7U /**< Minimum VBRAM Data */ +#define XADCPS_MAX_VCCPINT 8U /**< Maximum VCCPINT Register , Zynq */ +#define XADCPS_MAX_VCCPAUX 9U /**< Maximum VCCPAUX Register , Zynq */ +#define XADCPS_MAX_VCCPDRO 0xAU /**< Maximum VCCPDRO Register , Zynq */ +#define XADCPS_MIN_VCCPINT 0xCU /**< Minimum VCCPINT Register , Zynq */ +#define XADCPS_MIN_VCCPAUX 0xDU /**< Minimum VCCPAUX Register , Zynq */ +#define XADCPS_MIN_VCCPDRO 0xEU /**< Minimum VCCPDRO Register , Zynq */ + +/*@}*/ + + +/** + * @name Alarm Threshold(Limit) Register (ATR) indexes. + * @{ + */ +#define XADCPS_ATR_TEMP_UPPER 0U /**< High user Temperature */ +#define XADCPS_ATR_VCCINT_UPPER 1U /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_UPPER 2U /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_OT_UPPER 3U /**< VCCAUX high voltage limit register */ +#define XADCPS_ATR_TEMP_LOWER 4U /**< Upper Over Temperature limit Reg */ +#define XADCPS_ATR_VCCINT_LOWER 5U /**< VCCINT high voltage limit register */ +#define XADCPS_ATR_VCCAUX_LOWER 6U /**< VCCAUX low voltage limit register */ +#define XADCPS_ATR_OT_LOWER 7U /**< Lower Over Temperature limit */ +#define XADCPS_ATR_VBRAM_UPPER_ 8U /**< VRBAM Upper Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_UPPER 9U /**< VCCPINT Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER 0xAU /**< VCCPAUX Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER 0xBU /**< VCCPDRO Upper Alarm Reg, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER 0xCU /**< VRBAM Lower Alarm Reg, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER 0xDU /**< VCCPINT Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER 0xEU /**< VCCPAUX Lower Alarm Reg , Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER 0xFU /**< VCCPDRO Lower Alarm Reg , Zynq */ + +/*@}*/ + + +/** + * @name Averaging to be done for the channels. + * @{ + */ +#define XADCPS_AVG_0_SAMPLES 0U /**< No Averaging */ +#define XADCPS_AVG_16_SAMPLES 1U /**< Average 16 samples */ +#define XADCPS_AVG_64_SAMPLES 2U /**< Average 64 samples */ +#define XADCPS_AVG_256_SAMPLES 3U /**< Average 256 samples */ + +/*@}*/ + + +/** + * @name Channel Sequencer Modes of operation + * @{ + */ +#define XADCPS_SEQ_MODE_SAFE 0U /**< Default Safe Mode */ +#define XADCPS_SEQ_MODE_ONEPASS 1U /**< Onepass through Sequencer */ +#define XADCPS_SEQ_MODE_CONTINPASS 2U /**< Continuous Cycling Sequencer */ +#define XADCPS_SEQ_MODE_SINGCHAN 3U /**< Single channel -No Sequencing */ +#define XADCPS_SEQ_MODE_SIMUL_SAMPLING 4U /**< Simultaneous sampling */ +#define XADCPS_SEQ_MODE_INDEPENDENT 8U /**< Independent mode */ + +/*@}*/ + + + +/** + * @name Power Down Modes + * @{ + */ +#define XADCPS_PD_MODE_NONE 0U /**< No Power Down */ +#define XADCPS_PD_MODE_ADCB 1U /**< Power Down ADC B */ +#define XADCPS_PD_MODE_XADC 2U /**< Power Down ADC A and ADC B */ +/*@}*/ + +/**************************** Type Definitions ******************************/ + +/** + * This typedef contains configuration information for the XADC/ADC + * device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Device base address */ +} XAdcPs_Config; + + +/** + * The driver's instance data. The user is required to allocate a variable + * of this type for every XADC/ADC device in the system. A pointer to + * a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XAdcPs_Config Config; /**< XAdcPs_Config of current device */ + u32 IsReady; /**< Device is initialized and ready */ + +} XAdcPs; + +/***************** Macros (Inline Functions) Definitions ********************/ + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in Event Sampling mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in Event Sampling Mode. +* - FALSE if the device is in Continuous Sampling Mode. +* +* @note C-Style signature: +* int XAdcPs_IsEventSamplingMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsEventSamplingModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_EC_MASK) ? \ + TRUE : FALSE)) + + +/****************************************************************************/ +/** +* +* This macro checks if the XADC device is in External Mux mode. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - TRUE if the device is in External Mux Mode. +* - FALSE if the device is NOT in External Mux Mode. +* +* @note C-Style signature: +* int XAdcPs_IsExternalMuxMode(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_IsExternalMuxModeSet(InstancePtr) \ + (((XAdcPs_ReadInternalReg(InstancePtr, \ + XADCPS_CFR0_OFFSET) & XADCPS_CFR0_MUX_MASK) ? \ + TRUE : FALSE)) + +/****************************************************************************/ +/** +* +* This macro converts XADC Raw Data to Temperature(centigrades). +* +* @param AdcData is the Raw ADC Data from XADC. +* +* @return The Temperature in centigrades. +* +* @note C-Style signature: +* float XAdcPs_RawToTemperature(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToTemperature(AdcData) \ + ((((float)(AdcData)/65536.0f)/0.00198421639f ) - 273.15f) + +/****************************************************************************/ +/** +* +* This macro converts XADC/ADC Raw Data to Voltage(volts). +* +* @param AdcData is the XADC/ADC Raw Data. +* +* @return The Voltage in volts. +* +* @note C-Style signature: +* float XAdcPs_RawToVoltage(u32 AdcData); +* +*****************************************************************************/ +#define XAdcPs_RawToVoltage(AdcData) \ + ((((float)(AdcData))* (3.0f))/65536.0f) + +/****************************************************************************/ +/** +* +* This macro converts Temperature in centigrades to XADC/ADC Raw Data. +* +* @param Temperature is the Temperature in centigrades to be +* converted to XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_TemperatureToRaw(float Temperature); +* +*****************************************************************************/ +#define XAdcPs_TemperatureToRaw(Temperature) \ + ((int)(((Temperature) + 273.15f)*65536.0f*0.00198421639f)) + +/****************************************************************************/ +/** +* +* This macro converts Voltage in Volts to XADC/ADC Raw Data. +* +* @param Voltage is the Voltage in volts to be converted to +* XADC/ADC Raw Data. +* +* @return The XADC/ADC Raw Data. +* +* @note C-Style signature: +* int XAdcPs_VoltageToRaw(float Voltage); +* +*****************************************************************************/ +#define XAdcPs_VoltageToRaw(Voltage) \ + ((int)((Voltage)*65536.0f/3.0f)) + + +/****************************************************************************/ +/** +* +* This macro is used for writing to the XADC Registers using the +* command FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Data is the value to be written to XADC register. +* +* @return None. +* +* @note C-Style signature: +* void XAdcPs_WriteFifo(XAdcPs *InstancePtr, u32 Data); +* +*****************************************************************************/ +#define XAdcPs_WriteFifo(InstancePtr, Data) \ + XAdcPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_CMDFIFO_OFFSET, Data); + + +/****************************************************************************/ +/** +* +* This macro is used for reading from the XADC Registers using the +* data FIFO. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return Data read from the FIFO +* +* @note C-Style signature: +* u32 XAdcPs_ReadFifo(XAdcPs *InstancePtr); +* +*****************************************************************************/ +#define XAdcPs_ReadFifo(InstancePtr) \ + XAdcPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XADCPS_RDFIFO_OFFSET); + + +/************************** Function Prototypes *****************************/ + + + +/** + * Functions in xadcps_sinit.c + */ +XAdcPs_Config *XAdcPs_LookupConfig(u16 DeviceId); + +/** + * Functions in xadcps.c + */ +int XAdcPs_CfgInitialize(XAdcPs *InstancePtr, + XAdcPs_Config *ConfigPtr, + u32 EffectiveAddr); + +void XAdcPs_SetConfigRegister(XAdcPs *InstancePtr, u32 Data); +u32 XAdcPs_GetConfigRegister(XAdcPs *InstancePtr); + +u32 XAdcPs_GetMiscStatus(XAdcPs *InstancePtr); + +void XAdcPs_SetMiscCtrlRegister(XAdcPs *InstancePtr, u32 Data); +u32 XAdcPs_GetMiscCtrlRegister(XAdcPs *InstancePtr); + +void XAdcPs_Reset(XAdcPs *InstancePtr); + +u16 XAdcPs_GetAdcData(XAdcPs *InstancePtr, u8 Channel); + +u16 XAdcPs_GetCalibCoefficient(XAdcPs *InstancePtr, u8 CoeffType); + +u16 XAdcPs_GetMinMaxMeasurement(XAdcPs *InstancePtr, u8 MeasurementType); + +void XAdcPs_SetAvg(XAdcPs *InstancePtr, u8 Average); +u8 XAdcPs_GetAvg(XAdcPs *InstancePtr); + +int XAdcPs_SetSingleChParams(XAdcPs *InstancePtr, + u8 Channel, + int IncreaseAcqCycles, + int IsEventMode, + int IsDifferentialMode); + + +void XAdcPs_SetAlarmEnables(XAdcPs *InstancePtr, u16 AlmEnableMask); +u16 XAdcPs_GetAlarmEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetCalibEnables(XAdcPs *InstancePtr, u16 Calibration); +u16 XAdcPs_GetCalibEnables(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerMode(XAdcPs *InstancePtr, u8 SequencerMode); +u8 XAdcPs_GetSequencerMode(XAdcPs *InstancePtr); + +void XAdcPs_SetAdcClkDivisor(XAdcPs *InstancePtr, u8 Divisor); +u8 XAdcPs_GetAdcClkDivisor(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqChEnables(XAdcPs *InstancePtr, u32 ChEnableMask); +u32 XAdcPs_GetSeqChEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAvgEnables(XAdcPs *InstancePtr, u32 AvgEnableChMask); +u32 XAdcPs_GetSeqAvgEnables(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqInputMode(XAdcPs *InstancePtr, u32 InputModeChMask); +u32 XAdcPs_GetSeqInputMode(XAdcPs *InstancePtr); + +int XAdcPs_SetSeqAcqTime(XAdcPs *InstancePtr, u32 AcqCyclesChMask); +u32 XAdcPs_GetSeqAcqTime(XAdcPs *InstancePtr); + +void XAdcPs_SetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg, u16 Value); +u16 XAdcPs_GetAlarmThreshold(XAdcPs *InstancePtr, u8 AlarmThrReg); + +void XAdcPs_EnableUserOverTemp(XAdcPs *InstancePtr); +void XAdcPs_DisableUserOverTemp(XAdcPs *InstancePtr); + +void XAdcPs_SetSequencerEvent(XAdcPs *InstancePtr, int IsEventMode); + +int XAdcPs_GetSamplingMode(XAdcPs *InstancePtr); + +void XAdcPs_SetMuxMode(XAdcPs *InstancePtr, int MuxMode, u8 Channel); + +void XAdcPs_SetPowerdownMode(XAdcPs *InstancePtr, u32 Mode); + +u32 XAdcPs_GetPowerdownMode(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_selftest.c + */ +int XAdcPs_SelfTest(XAdcPs *InstancePtr); + +/** + * Functions in xadcps_intr.c + */ +void XAdcPs_IntrEnable(XAdcPs *InstancePtr, u32 Mask); +void XAdcPs_IntrDisable(XAdcPs *InstancePtr, u32 Mask); +u32 XAdcPs_IntrGetEnabled(XAdcPs *InstancePtr); + +u32 XAdcPs_IntrGetStatus(XAdcPs *InstancePtr); +void XAdcPs_IntrClear(XAdcPs *InstancePtr, u32 Mask); + + +#ifdef __cplusplus +} +#endif + +#endif /* End of protection macro. */ +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_g.c b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_g.c new file mode 100644 index 0000000..338bb94 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_g.c @@ -0,0 +1,59 @@ +/****************************************************************************** +* Copyright (C) 2011 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xadcps_g.c +* @addtogroup xadcps_v2_6 +* @{ +* +* This file contains a configuration table that specifies the configuration +* of XADC devices in the system when accessing through the Device Config +* interface in Zynq. +* +* See xadcps.h for more information about this driver. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xadcps.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Prototypes ******************************/ + +/** + * This table contains configuration information for each XADC Monitor/ADC + * device in the system. + */ +XAdcPs_Config XAdcPs_ConfigTable[XPAR_XADCPS_NUM_INSTANCES] = +{ + { + XPAR_XADCPS_0_DEVICE_ID, /**< Unique ID of device */ + XPAR_XADCPS_0_BASEADDR /**< Base address of device */ + } +}; +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_hw.h b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_hw.h new file mode 100644 index 0000000..51cc7c5 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_hw.h @@ -0,0 +1,477 @@ +/****************************************************************************** +* Copyright (C) 2011 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/****************************************************************************/ +/** +* +* @file xadcps_hw.h +* @addtogroup xadcps_v2_6 +* @{ +* +* This header file contains identifiers and basic driver functions (or +* macros) that can be used to access the XADC device through the Device +* Config Interface of the Zynq. +* +* +* Refer to the device specification for more information about this driver. +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a bss    12/22/11 First release based on the XPS/AXI xadc driver
+* 1.03a bss    11/01/13 Modified macros to use correct Register offsets
+*			CR#749687
+* 2.6   aad    11/02/20 Fix MISRAC Mandatory and Advisory errors.
+*
+* 
+* +*****************************************************************************/ +#ifndef XADCPS_HW_H /* Prevent circular inclusions */ +#define XADCPS_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files ********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions ****************************/ + + +/**@name Register offsets of XADC in the Device Config + * + * The following constants provide access to each of the registers of the + * XADC device. + * @{ + */ + +#define XADCPS_CFG_OFFSET 0x00U /**< Configuration Register */ +#define XADCPS_INT_STS_OFFSET 0x04U /**< Interrupt Status Register */ +#define XADCPS_INT_MASK_OFFSET 0x08U /**< Interrupt Mask Register */ +#define XADCPS_MSTS_OFFSET 0x0CU /**< Misc status register */ +#define XADCPS_CMDFIFO_OFFSET 0x10U /**< Command FIFO Register */ +#define XADCPS_RDFIFO_OFFSET 0x14U /**< Read FIFO Register */ +#define XADCPS_MCTL_OFFSET 0x18U /**< Misc control register */ + +/* @} */ + + + + + +/** @name XADC Config Register Bit definitions + * @{ + */ +#define XADCPS_CFG_ENABLE_MASK 0x80000000U /**< Enable access from PS mask */ +#define XADCPS_CFG_CFIFOTH_MASK 0x00F00000U /**< Command FIFO Threshold mask */ +#define XADCPS_CFG_DFIFOTH_MASK 0x000F0000U /**< Data FIFO Threshold mask */ +#define XADCPS_CFG_WEDGE_MASK 0x00002000U /**< Write Edge Mask */ +#define XADCPS_CFG_REDGE_MASK 0x00001000U /**< Read Edge Mask */ +#define XADCPS_CFG_TCKRATE_MASK 0x00000300U /**< Clock freq control */ +#define XADCPS_CFG_IGAP_MASK 0x0000001FU /**< Idle Gap between + * successive commands */ +/* @} */ + + +/** @name XADC Interrupt Status/Mask Register Bit definitions + * + * The definitions are same for the Interrupt Status Register and + * Interrupt Mask Register. They are defined only once. + * @{ + */ +#define XADCPS_INTX_ALL_MASK 0x000003FFU /**< Alarm Signals Mask */ +#define XADCPS_INTX_CFIFO_LTH_MASK 0x00000200U /**< CMD FIFO less than threshold */ +#define XADCPS_INTX_DFIFO_GTH_MASK 0x00000100U /**< Data FIFO greater than threshold */ +#define XADCPS_INTX_OT_MASK 0x00000080U /**< Over temperature Alarm Status */ +#define XADCPS_INTX_ALM_ALL_MASK 0x0000007FU /**< Alarm Signals Mask */ +#define XADCPS_INTX_ALM6_MASK 0x00000040U /**< Alarm 6 Mask */ +#define XADCPS_INTX_ALM5_MASK 0x00000020U /**< Alarm 5 Mask */ +#define XADCPS_INTX_ALM4_MASK 0x00000010U /**< Alarm 4 Mask */ +#define XADCPS_INTX_ALM3_MASK 0x00000008U /**< Alarm 3 Mask */ +#define XADCPS_INTX_ALM2_MASK 0x00000004U /**< Alarm 2 Mask */ +#define XADCPS_INTX_ALM1_MASK 0x00000002U /**< Alarm 1 Mask */ +#define XADCPS_INTX_ALM0_MASK 0x00000001U /**< Alarm 0 Mask */ + +/* @} */ + + +/** @name XADC Miscellaneous Register Bit definitions + * @{ + */ +#define XADCPS_MSTS_CFIFO_LVL_MASK 0x000F0000U /**< Command FIFO Level mask */ +#define XADCPS_MSTS_DFIFO_LVL_MASK 0x0000F000U /**< Data FIFO Level Mask */ +#define XADCPS_MSTS_CFIFOF_MASK 0x00000800U /**< Command FIFO Full Mask */ +#define XADCPS_MSTS_CFIFOE_MASK 0x00000400U /**< Command FIFO Empty Mask */ +#define XADCPS_MSTS_DFIFOF_MASK 0x00000200U /**< Data FIFO Full Mask */ +#define XADCPS_MSTS_DFIFOE_MASK 0x00000100U /**< Data FIFO Empty Mask */ +#define XADCPS_MSTS_OT_MASK 0x00000080U /**< Over Temperature Mask */ +#define XADCPS_MSTS_ALM_MASK 0x0000007FU /**< Alarms Mask */ +/* @} */ + + +/** @name XADC Miscellaneous Control Register Bit definitions + * @{ + */ +#define XADCPS_MCTL_RESET_MASK 0x00000010U /**< Reset XADC */ +#define XADCPS_MCTL_FLUSH_MASK 0x00000001U /**< Flush the FIFOs */ +/* @} */ + + +/**@name Internal Register offsets of the XADC + * + * The following constants provide access to each of the internal registers of + * the XADC device. + * @{ + */ + +/* + * XADC Internal Channel Registers + */ +#define XADCPS_TEMP_OFFSET 0x00U /**< On-chip Temperature Reg */ +#define XADCPS_VCCINT_OFFSET 0x01U /**< On-chip VCCINT Data Reg */ +#define XADCPS_VCCAUX_OFFSET 0x02U /**< On-chip VCCAUX Data Reg */ +#define XADCPS_VPVN_OFFSET 0x03U /**< ADC out of VP/VN */ +#define XADCPS_VREFP_OFFSET 0x04U /**< On-chip VREFP Data Reg */ +#define XADCPS_VREFN_OFFSET 0x05U /**< On-chip VREFN Data Reg */ +#define XADCPS_VBRAM_OFFSET 0x06U /**< On-chip VBRAM , 7 Series */ +#define XADCPS_ADC_A_SUPPLY_CALIB_OFFSET 0x08U /**< ADC A Supply Offset Reg */ +#define XADCPS_ADC_A_OFFSET_CALIB_OFFSET 0x09U /**< ADC A Offset Data Reg */ +#define XADCPS_ADC_A_GAINERR_CALIB_OFFSET 0x0AU /**< ADC A Gain Error Reg */ +#define XADCPS_VCCPINT_OFFSET 0x0DU /**< On-chip VCCPINT Reg, Zynq */ +#define XADCPS_VCCPAUX_OFFSET 0x0EU /**< On-chip VCCPAUX Reg, Zynq */ +#define XADCPS_VCCPDRO_OFFSET 0x0FU /**< On-chip VCCPDRO Reg, Zynq */ + +/* + * XADC External Channel Registers + */ +#define XADCPS_AUX00_OFFSET 0x10U /**< ADC out of VAUXP0/VAUXN0 */ +#define XADCPS_AUX01_OFFSET 0x11U /**< ADC out of VAUXP1/VAUXN1 */ +#define XADCPS_AUX02_OFFSET 0x12U /**< ADC out of VAUXP2/VAUXN2 */ +#define XADCPS_AUX03_OFFSET 0x13U /**< ADC out of VAUXP3/VAUXN3 */ +#define XADCPS_AUX04_OFFSET 0x14U /**< ADC out of VAUXP4/VAUXN4 */ +#define XADCPS_AUX05_OFFSET 0x15U /**< ADC out of VAUXP5/VAUXN5 */ +#define XADCPS_AUX06_OFFSET 0x16U /**< ADC out of VAUXP6/VAUXN6 */ +#define XADCPS_AUX07_OFFSET 0x17U /**< ADC out of VAUXP7/VAUXN7 */ +#define XADCPS_AUX08_OFFSET 0x18U /**< ADC out of VAUXP8/VAUXN8 */ +#define XADCPS_AUX09_OFFSET 0x19U /**< ADC out of VAUXP9/VAUXN9 */ +#define XADCPS_AUX10_OFFSET 0x1AU /**< ADC out of VAUXP10/VAUXN10 */ +#define XADCPS_AUX11_OFFSET 0x1BU /**< ADC out of VAUXP11/VAUXN11 */ +#define XADCPS_AUX12_OFFSET 0x1CU /**< ADC out of VAUXP12/VAUXN12 */ +#define XADCPS_AUX13_OFFSET 0x1DU /**< ADC out of VAUXP13/VAUXN13 */ +#define XADCPS_AUX14_OFFSET 0x1EU /**< ADC out of VAUXP14/VAUXN14 */ +#define XADCPS_AUX15_OFFSET 0x1FU /**< ADC out of VAUXP15/VAUXN15 */ + +/* + * XADC Registers for Maximum/Minimum data captured for the + * on chip Temperature/VCCINT/VCCAUX data. + */ +#define XADCPS_MAX_TEMP_OFFSET 0x20U /**< Max Temperature Reg */ +#define XADCPS_MAX_VCCINT_OFFSET 0x21U /**< Max VCCINT Register */ +#define XADCPS_MAX_VCCAUX_OFFSET 0x22U /**< Max VCCAUX Register */ +#define XADCPS_MAX_VCCBRAM_OFFSET 0x23U /**< Max BRAM Register, 7 series */ +#define XADCPS_MIN_TEMP_OFFSET 0x24U /**< Min Temperature Reg */ +#define XADCPS_MIN_VCCINT_OFFSET 0x25U /**< Min VCCINT Register */ +#define XADCPS_MIN_VCCAUX_OFFSET 0x26U /**< Min VCCAUX Register */ +#define XADCPS_MIN_VCCBRAM_OFFSET 0x27U /**< Min BRAM Register, 7 series */ +#define XADCPS_MAX_VCCPINT_OFFSET 0x28U /**< Max VCCPINT Register, Zynq */ +#define XADCPS_MAX_VCCPAUX_OFFSET 0x29U /**< Max VCCPAUX Register, Zynq */ +#define XADCPS_MAX_VCCPDRO_OFFSET 0x2AU /**< Max VCCPDRO Register, Zynq */ +#define XADCPS_MIN_VCCPINT_OFFSET 0x2CU /**< Min VCCPINT Register, Zynq */ +#define XADCPS_MIN_VCCPAUX_OFFSET 0x2DU /**< Min VCCPAUX Register, Zynq */ +#define XADCPS_MIN_VCCPDRO_OFFSET 0x2EU /**< Min VCCPDRO Register,Zynq */ + /* Undefined 0x2F to 0x3E */ +#define XADCPS_FLAG_OFFSET 0x3FU /**< Flag Register */ + +/* + * XADC Configuration Registers + */ +#define XADCPS_CFR0_OFFSET 0x40U /**< Configuration Register 0 */ +#define XADCPS_CFR1_OFFSET 0x41U /**< Configuration Register 1 */ +#define XADCPS_CFR2_OFFSET 0x42U /**< Configuration Register 2 */ + +/* Test Registers 0x43 to 0x47 */ + +/* + * XADC Sequence Registers + */ +#define XADCPS_SEQ00_OFFSET 0x48U /**< Seq Reg 00 Adc Channel Selection */ +#define XADCPS_SEQ01_OFFSET 0x49U /**< Seq Reg 01 Adc Channel Selection */ +#define XADCPS_SEQ02_OFFSET 0x4AU /**< Seq Reg 02 Adc Average Enable */ +#define XADCPS_SEQ03_OFFSET 0x4BU /**< Seq Reg 03 Adc Average Enable */ +#define XADCPS_SEQ04_OFFSET 0x4CU /**< Seq Reg 04 Adc Input Mode Select */ +#define XADCPS_SEQ05_OFFSET 0x4DU /**< Seq Reg 05 Adc Input Mode Select */ +#define XADCPS_SEQ06_OFFSET 0x4EU /**< Seq Reg 06 Adc Acquisition Select */ +#define XADCPS_SEQ07_OFFSET 0x4FU /**< Seq Reg 07 Adc Acquisition Select */ + +/* + * XADC Alarm Threshold/Limit Registers (ATR) + */ +#define XADCPS_ATR_TEMP_UPPER_OFFSET 0x50U /**< Temp Upper Alarm Register */ +#define XADCPS_ATR_VCCINT_UPPER_OFFSET 0x51U /**< VCCINT Upper Alarm Reg */ +#define XADCPS_ATR_VCCAUX_UPPER_OFFSET 0x52U /**< VCCAUX Upper Alarm Reg */ +#define XADCPS_ATR_OT_UPPER_OFFSET 0x53U /**< Over Temp Upper Alarm Reg */ +#define XADCPS_ATR_TEMP_LOWER_OFFSET 0x54U /**< Temp Lower Alarm Register */ +#define XADCPS_ATR_VCCINT_LOWER_OFFSET 0x55U /**< VCCINT Lower Alarm Reg */ +#define XADCPS_ATR_VCCAUX_LOWER_OFFSET 0x56U /**< VCCAUX Lower Alarm Reg */ +#define XADCPS_ATR_OT_LOWER_OFFSET 0x57U /**< Over Temp Lower Alarm Reg */ +#define XADCPS_ATR_VBRAM_UPPER_OFFSET 0x58U /**< VBRAM Upper Alarm, 7 series */ +#define XADCPS_ATR_VCCPINT_UPPER_OFFSET 0x59U /**< VCCPINT Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_UPPER_OFFSET 0x5AU /**< VCCPAUX Upper Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_UPPER_OFFSET 0x5BU /**< VCCPDRO Upper Alarm, Zynq */ +#define XADCPS_ATR_VBRAM_LOWER_OFFSET 0x5CU /**< VRBAM Lower Alarm, 7 Series */ +#define XADCPS_ATR_VCCPINT_LOWER_OFFSET 0x5DU /**< VCCPINT Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPAUX_LOWER_OFFSET 0x5EU /**< VCCPAUX Lower Alarm, Zynq */ +#define XADCPS_ATR_VCCPDRO_LOWER_OFFSET 0x5FU /**< VCCPDRO Lower Alarm, Zynq */ + +/* Undefined 0x60 to 0x7F */ + +/*@}*/ + + + +/** + * @name Configuration Register 0 (CFR0) mask(s) + * @{ + */ +#define XADCPS_CFR0_CAL_AVG_MASK 0x00008000U /**< Averaging enable Mask */ +#define XADCPS_CFR0_AVG_VALID_MASK 0x00003000U /**< Averaging bit Mask */ +#define XADCPS_CFR0_AVG1_MASK 0x00000000U /**< No Averaging */ +#define XADCPS_CFR0_AVG16_MASK 0x00001000U /**< Average 16 samples */ +#define XADCPS_CFR0_AVG64_MASK 0x00002000U /**< Average 64 samples */ +#define XADCPS_CFR0_AVG256_MASK 0x00003000U /**< Average 256 samples */ +#define XADCPS_CFR0_AVG_SHIFT 12U /**< Averaging bits shift */ +#define XADCPS_CFR0_MUX_MASK 0x00000800U /**< External Mask Enable */ +#define XADCPS_CFR0_DU_MASK 0x00000400U /**< Bipolar/Unipolar mode */ +#define XADCPS_CFR0_EC_MASK 0x00000200U /**< Event driven/ + * Continuous mode selection + */ +#define XADCPS_CFR0_ACQ_MASK 0x00000100U /**< Add acquisition by 6 ADCCLK */ +#define XADCPS_CFR0_CHANNEL_MASK 0x0000001FU /**< Channel number bit Mask */ + +/*@}*/ + +/** + * @name Configuration Register 1 (CFR1) mask(s) + * @{ + */ +#define XADCPS_CFR1_SEQ_VALID_MASK 0x0000F000U /**< Sequence bit Mask */ +#define XADCPS_CFR1_SEQ_SAFEMODE_MASK 0x00000000U /**< Default Safe Mode */ +#define XADCPS_CFR1_SEQ_ONEPASS_MASK 0x00001000U /**< Onepass through Seq */ +#define XADCPS_CFR1_SEQ_CONTINPASS_MASK 0x00002000U /**< Continuous Cycling Seq */ +#define XADCPS_CFR1_SEQ_SINGCHAN_MASK 0x00003000U /**< Single channel - No Seq */ +#define XADCPS_CFR1_SEQ_SIMUL_SAMPLING_MASK 0x00004000U /**< Simulataneous Sampling Mask */ +#define XADCPS_CFR1_SEQ_INDEPENDENT_MASK 0x00008000U /**< Independent Mode */ +#define XADCPS_CFR1_SEQ_SHIFT 12U /**< Sequence bit shift */ +#define XADCPS_CFR1_ALM_VCCPDRO_MASK 0x00000800U /**< Alm 6 - VCCPDRO, Zynq */ +#define XADCPS_CFR1_ALM_VCCPAUX_MASK 0x00000400U /**< Alm 5 - VCCPAUX, Zynq */ +#define XADCPS_CFR1_ALM_VCCPINT_MASK 0x00000200U /**< Alm 4 - VCCPINT, Zynq */ +#define XADCPS_CFR1_ALM_VBRAM_MASK 0x00000100U /**< Alm 3 - VBRAM, 7 series */ +#define XADCPS_CFR1_CAL_VALID_MASK 0x000000F0U /**< Valid Calibration Mask */ +#define XADCPS_CFR1_CAL_PS_GAIN_OFFSET_MASK 0x00000080U /**< Calibration 3 -Power + Supply Gain/Offset + Enable */ +#define XADCPS_CFR1_CAL_PS_OFFSET_MASK 0x00000040U /**< Calibration 2 -Power + Supply Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_GAIN_OFFSET_MASK 0x00000020U /**< Calibration 1 -ADC Gain + Offset Enable */ +#define XADCPS_CFR1_CAL_ADC_OFFSET_MASK 0x00000010U /**< Calibration 0 -ADC Offset + Enable */ +#define XADCPS_CFR1_CAL_DISABLE_MASK 0x00000000U /**< No Calibration */ +#define XADCPS_CFR1_ALM_ALL_MASK 0x00000F0FU /**< Mask for all alarms */ +#define XADCPS_CFR1_ALM_VCCAUX_MASK 0x00000008U /**< Alarm 2 - VCCAUX Enable */ +#define XADCPS_CFR1_ALM_VCCINT_MASK 0x00000004U /**< Alarm 1 - VCCINT Enable */ +#define XADCPS_CFR1_ALM_TEMP_MASK 0x00000002U /**< Alarm 0 - Temperature */ +#define XADCPS_CFR1_OT_MASK 0x00000001U /**< Over Temperature Enable */ + +/*@}*/ + +/** + * @name Configuration Register 2 (CFR2) mask(s) + * @{ + */ +#define XADCPS_CFR2_CD_VALID_MASK 0xFF00U /** +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ----- -------- ----------------------------------------------------- +* 1.00a ssb 12/22/11 First release based on the XPS/AXI xadc driver +* +*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xadcps.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + + +/****************************************************************************/ +/** +* +* This function enables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mask is the bit-mask of the interrupts to be enabled. +* Bit positions of 1 will be enabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XADCPS_INTX_* bits defined in xadcps_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_IntrEnable(XAdcPs *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable the specified interrupts in the IPIER. + */ + RegValue = XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET); + RegValue &= ~(Mask & XADCPS_INTX_ALL_MASK); + XAdcPs_WriteReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET, + RegValue); +} + + +/****************************************************************************/ +/** +* +* This function disables the specified interrupts in the device. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mask is the bit-mask of the interrupts to be disabled. +* Bit positions of 1 will be disabled. Bit positions of 0 will +* keep the previous setting. This mask is formed by OR'ing +* XADCPS_INTX_* bits defined in xadcps_hw.h. +* +* @return None. +* +* @note None +* +*****************************************************************************/ +void XAdcPs_IntrDisable(XAdcPs *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Enable the specified interrupts in the IPIER. + */ + RegValue = XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET); + RegValue |= (Mask & XADCPS_INTX_ALL_MASK); + XAdcPs_WriteReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET, + RegValue); +} +/****************************************************************************/ +/** +* +* This function returns the enabled interrupts read from the Interrupt Mask +* Register (IPIER). Use the XADCPS_IPIXR_* constants defined in xadcps_hw.h to +* interpret the returned value. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the I. +* +* @note None. +* +*****************************************************************************/ +u32 XAdcPs_IntrGetEnabled(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Enable Register. + */ + return (~ XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_MASK_OFFSET) & XADCPS_INTX_ALL_MASK); +} + +/****************************************************************************/ +/** +* +* This function returns the interrupt status read from Interrupt Status +* Register(IPISR). Use the XADCPS_IPIXR_* constants defined in xadcps_hw.h +* to interpret the returned value. +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return A 32-bit value representing the contents of the IPISR. +* +* @note The device must be configured at hardware build time to include +* interrupt component for this function to work. +* +*****************************************************************************/ +u32 XAdcPs_IntrGetStatus(XAdcPs *InstancePtr) +{ + /* + * Assert the arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Return the value read from the Interrupt Status register. + */ + return XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_STS_OFFSET) & XADCPS_INTX_ALL_MASK; +} + +/****************************************************************************/ +/** +* +* This function clears the specified interrupts in the Interrupt Status +* Register (IPISR). +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* @param Mask is the bit-mask of the interrupts to be cleared. +* Bit positions of 1 will be cleared. Bit positions of 0 will not +* change the previous interrupt status. This mask is formed by +* OR'ing XADCPS_IPIXR_* bits which are defined in xadcps_hw.h. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XAdcPs_IntrClear(XAdcPs *InstancePtr, u32 Mask) +{ + u32 RegValue; + + /* + * Assert the arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Clear the specified interrupts in the Interrupt Status register. + */ + RegValue = XAdcPs_ReadReg(InstancePtr->Config.BaseAddress, + XADCPS_INT_STS_OFFSET); + RegValue &= (Mask & XADCPS_INTX_ALL_MASK); + XAdcPs_WriteReg(InstancePtr->Config.BaseAddress, XADCPS_INT_STS_OFFSET, + RegValue); + +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_selftest.c b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_selftest.c new file mode 100644 index 0000000..b144c7a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_selftest.c @@ -0,0 +1,116 @@ +/****************************************************************************** +* Copyright (C) 2011 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xadcps_selftest.c +* @addtogroup xadcps_v2_6 +* @{ +* +* This file contains a diagnostic self test function for the XAdcPs driver. +* The self test function does a simple read/write test of the Alarm Threshold +* Register. +* +* See xadcps.h for more information. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI xadc driver
+* 2.6   aad    11/02/20 Fix MISRAC Mandatory and Advisory errors.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xadcps.h" + +/************************** Constant Definitions ****************************/ + +/* + * The following constant defines the test value to be written + * to the Alarm Threshold Register + */ +#define XADCPS_ATR_TEST_VALUE 0x55U + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ + +/*****************************************************************************/ +/** +* +* Run a self-test on the driver/device. The test +* - Resets the device, +* - Writes a value into the Alarm Threshold register and reads it back +* for comparison. +* - Resets the device again. +* +* +* @param InstancePtr is a pointer to the XAdcPs instance. +* +* @return +* - XST_SUCCESS if the value read from the Alarm Threshold +* register is the same as the value written. +* - XST_FAILURE Otherwise +* +* @note This is a destructive test in that resets of the device are +* performed. Refer to the device specification for the +* device status after the reset operation. +* +******************************************************************************/ +int XAdcPs_SelfTest(XAdcPs *InstancePtr) +{ + int Status; + u32 RegValue; + + /* + * Assert the argument + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + /* + * Reset the device to get it back to its default state + */ + XAdcPs_Reset(InstancePtr); + + /* + * Write a value into the Alarm Threshold registers, read it back, and + * do the comparison + */ + XAdcPs_SetAlarmThreshold(InstancePtr, XADCPS_ATR_VCCINT_UPPER, + XADCPS_ATR_TEST_VALUE); + RegValue = XAdcPs_GetAlarmThreshold(InstancePtr, XADCPS_ATR_VCCINT_UPPER); + + if (RegValue == XADCPS_ATR_TEST_VALUE) { + Status = XST_SUCCESS; + } else { + Status = XST_FAILURE; + } + + /* + * Reset the device again to its default state. + */ + XAdcPs_Reset(InstancePtr); + /* + * Return the test result. + */ + return Status; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_sinit.c b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_sinit.c new file mode 100644 index 0000000..e06988a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xadcps/src/xadcps_sinit.c @@ -0,0 +1,78 @@ +/****************************************************************************** +* Copyright (C) 2011 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xadcps_sinit.c +* @addtogroup xadcps_v2_6 +* @{ +* +* This file contains the implementation of the XAdcPs driver's static +* initialization functionality. +* +* @note None. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- -----  -------- -----------------------------------------------------
+* 1.00a ssb    12/22/11 First release based on the XPS/AXI XADC driver
+* 2.6   aad    11/02/20 Fix MISRAC Mandatory and Advisory errors.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xadcps.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XAdcPs_Config XAdcPs_ConfigTable[]; + +/*****************************************************************************/ +/** +* +* This function looks up the device configuration based on the unique device ID. +* The table XAdcPs_ConfigTable contains the configuration info for each device +* in the system. +* +* @param DeviceId contains the ID of the device for which the +* device configuration pointer is to be returned. +* +* @return +* - A pointer to the configuration found. +* - NULL if the specified device ID was not found. +* +* @note None. +* +******************************************************************************/ +XAdcPs_Config *XAdcPs_LookupConfig(u16 DeviceId) +{ + XAdcPs_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < 1U; Index++) { + if (XAdcPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XAdcPs_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} +/** @} */ diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/data/xilffs.mld b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/data/xilffs.mld new file mode 100644 index 0000000..ef73eb5 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/data/xilffs.mld @@ -0,0 +1,44 @@ +############################################################################### +# Copyright (c) 2013 - 2022 Xilinx, Inc. All rights reserved. +# Copyright (C) 2022 - 2023 Advanced Micro Devices, Inc. All Rights Reserved. +# SPDX-License-Identifier: MIT +# +# Modification History +# +# Ver Who Date Changes +# ----- ---- -------- ----------------------------------------------- +# 1.00a hk/sg 10/17/13 First release +# 1.00 srm 02/16/18 Updated to pick up latest freertos port 10.0 +# 4.1 hk 11/21/18 Add additional LFN options +# 4.2 aru 07/10/19 Fix coverity warnings +############################################################################## + +OPTION psf_version = 2.1; + +BEGIN LIBRARY xilffs + OPTION drc = ffs_drc; + OPTION copyfiles = all; + OPTION REQUIRES_OS = (standalone freertos10_xilinx); + OPTION APP_LINKER_FLAGS = "-Wl,--start-group,-lxilffs,-lxil,-lgcc,-lc,--end-group"; + OPTION desc = "Generic Fat File System Library"; + OPTION VERSION = 5.0; + OPTION NAME = xilffs; + PARAM name = fs_interface, desc = "Enables file system with selected interface. Enter 1 for SD. Enter 2 for RAM", type = int, default = 1; + PARAM name = read_only, desc = "Enables the file system in Read_Only mode if true. ZynqMP fsbl will set this to true", type = bool, default = false; + PARAM name = enable_exfat, desc = "0:Disable exFAT, 1:Enable exFAT(Also Enables LFN)", type = bool, default = false; + PARAM name = use_lfn, desc = "Enables the Long File Name(LFN) support if non-zero. Disabled by default: 0, LFN with static working buffer: 1, Dynamic working buffer: 2 (on stack) or 3 (on heap) ", type = int, default = 0; + PARAM name = use_mkfs, desc = "Disable(0) or Enable(1) f_mkfs function. ZynqMP fsbl will set this to false", type = bool, default = true; + PARAM name = use_trim, desc = "Disable(0) or Enable(1) TRIM function. ZynqMP fsbl will set this to false", type = bool, default = false; + PARAM name = enable_multi_partition, desc = "0:Single partition, 1:Enable multiple partition", type = bool, default = false; + PARAM name = num_logical_vol, desc = "Number of volumes (logical drives, from 1 to 10) to be used.", type = int, default = 2; + PARAM name = use_strfunc, desc = "Enables the string functions (valid values 0 to 2).", type = int, default = 0; + PARAM name = set_fs_rpath, desc = "Configures relative path feature (valid values 0 to 2).", type = int, default = 0; + PARAM name = word_access, desc = "Enables word access for misaligned memory access platform", type = bool, default = true; + PARAM name = use_chmod, desc = "Enables use of CHMOD functionality for changing attributes (valid only with read_only set to false)", type = bool, default = false; + + BEGIN CATEGORY ramfs_options + PARAM name = ramfs_size, desc = "RAM FS size", type = int, default = 3145728; + PARAM name = ramfs_start_addr, desc = "RAM FS start address", type = int; + END CATEGORY + +END LIBRARY diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/data/xilffs.tcl b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/data/xilffs.tcl new file mode 100644 index 0000000..ac14532 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/data/xilffs.tcl @@ -0,0 +1,212 @@ +############################################################################### +# Copyright (c) 2013 - 2022 Xilinx, Inc. All rights reserved. +# SPDX-License-Identifier: MIT +# +# Modification History +# +# Ver Who Date Changes +# ----- ---- ------- ----------------------------------------------- +# 1.00a hk/sg 10/17/13 First release +# 2.0 hk 12/13/13 Modified to use new TCL API's +# 4.1 hk 11/21/18 Use additional LFN options +# +############################################################################## + +#--------------------------------------------- +# FFS_drc - check system configuration and make sure +# all components to run ISF are available. +#--------------------------------------------- + +proc ffs_drc {libhandle} { + + # Check if any IP instances that use FATFS are present + set sw_processor [hsi::get_sw_processor] + set processor [hsi::get_cells -hier [common::get_property HW_INSTANCE $sw_processor]] + + set ffs_periphs_list [get_ffs_periphs $processor] + + set fs_interface [common::get_property CONFIG.fs_interface $libhandle] + + # No need to check if fs_interface is RAM + if {$fs_interface != 2 && [llength $ffs_periphs_list] == 0} { + puts "WARNING : No interface that uses file system is available \n" + } + +} + +proc get_ffs_periphs {processor} { + set periphs_list [hsi::utils::get_proc_slave_periphs $processor] + set ffs_periphs_list {} + + global ffs_periphs_name_list + set ffs_periphs_name_list {} + + foreach periph $periphs_list { + set periphname [common::get_property IP_NAME $periph] + # Checks if SD instance is present + # This can be expanded to add more instances. + if {$periphname == "ps7_sdio" || $periphname == "psu_sd" || $periphname == "psv_pmc_sd" || $periphname == "psxl_pmc_sd" || $periphname == "psxl_pmc_emmc" || $periphname == "psx_pmc_sd" || $periphname == "psx_pmc_emmc"} { + lappend ffs_periphs_list $periph + lappend ffs_periphs_name_list $periphname + } + } + + return $ffs_periphs_list +} + +proc generate {libhandle} { + +} + + +#------- +# post_generate: called after generate called on all libraries +#------- +proc post_generate {libhandle} { + xgen_opts_file $libhandle +} + +#------- +# execs_generate: called after BSP's, libraries and drivers have been compiled +# This procedure builds the libisf.a library +#------- +proc execs_generate {libhandle} { + +} + + +proc xgen_opts_file {libhandle} { + + # Open xparameters.h file + set file_handle [hsi::utils::open_include_file "xparameters.h"] + + # Generate parameters for "file system with SD" and "MMC support" + puts $file_handle "/* Xilinx FAT File System Library (XilFFs) User Settings */" + set fs_interface [common::get_property CONFIG.fs_interface $libhandle] + set read_only [common::get_property CONFIG.read_only $libhandle] + set enable_exfat [common::get_property CONFIG.enable_exfat $libhandle] + set use_lfn [common::get_property CONFIG.use_lfn $libhandle] + set use_mkfs [common::get_property CONFIG.use_mkfs $libhandle] + set use_trim [common::get_property CONFIG.use_trim $libhandle] + set enable_multi_partition [common::get_property CONFIG.enable_multi_partition $libhandle] + set num_logical_vol [common::get_property CONFIG.num_logical_vol $libhandle] + set use_strfunc [common::get_property CONFIG.use_strfunc $libhandle] + set set_fs_rpath [common::get_property CONFIG.set_fs_rpath $libhandle] + set word_access [common::get_property CONFIG.word_access $libhandle] + set use_chmod [common::get_property CONFIG.use_chmod $libhandle] + + # do processor specific checks + set proc [hsi::get_sw_processor]; + set proc_type [common::get_property IP_NAME [hsi::get_cells -hier $proc]] + + if {$fs_interface == 2} { + set ramfs_size [common::get_property CONFIG.ramfs_size $libhandle] + set ramfs_start_addr [common::get_property CONFIG.ramfs_start_addr $libhandle] + + puts $file_handle "\#define FILE_SYSTEM_INTERFACE_RAM" + + puts $file_handle "\#define RAMFS_SIZE $ramfs_size" + + # Check if ram fs start address is defined? + # If not set default; Give warning in case of Microblaze + if {$ramfs_start_addr == ""} { + puts $file_handle "\#define RAMFS_START_ADDR 0x10000000" + + if {$proc_type == "microblaze"} { + puts "WARNING : Specify RAM FS start address \ + in system.mss for Microblaze\n" + } + } else { + puts $file_handle "\#define RAMFS_START_ADDR $ramfs_start_addr" + } + } + + + # Checking if SD with FATFS is enabled. + # This can be expanded to add more interfaces. + + global ffs_periphs_name_list + foreach periph $ffs_periphs_name_list { + + if {$periph == "ps7_sdio" || $periph == "psu_sd" || $periph == "psv_pmc_sd" || $periph == "psxl_pmc_sd" || $periph == "psxl_pmc_emmc" || $periph == "psx_pmc_sd" || $periph == "psx_pmc_emmc"} { + if {$fs_interface == 1} { + puts $file_handle "\#define FILE_SYSTEM_INTERFACE_SD" + break + } + } + } + + if {$fs_interface == 1 || $fs_interface == 2} { + if {$read_only == true} { + puts $file_handle "\#define FILE_SYSTEM_READ_ONLY" + } + if {$enable_exfat == true} { + puts $file_handle "\#define FILE_SYSTEM_FS_EXFAT" + set use_lfn 1 + } + if {$use_lfn > 0 && $use_lfn < 4} { + puts $file_handle "\#define FILE_SYSTEM_USE_LFN $use_lfn" + } + if {$use_mkfs == true} { + puts $file_handle "\#define FILE_SYSTEM_USE_MKFS" + } + if {$enable_multi_partition == true} { + puts $file_handle "\#define FILE_SYSTEM_MULTI_PARTITION" + } + if {$use_chmod == true} { + if {$read_only == false} { + puts $file_handle "\#define FILE_SYSTEM_USE_CHMOD" + } else { + puts "WARNING : Cannot Enable CHMOD in \ + Read Only Mode" + } + } + if {$use_trim == true} { + puts $file_handle "\#define FILE_SYSTEM_USE_TRIM" + } + if {$num_logical_vol > 10} { + puts "WARNING : File System supports only up to 10 logical drives\ + Setting back the num of vol to 10\n" + set num_logical_vol 10 + } + puts $file_handle "\#define FILE_SYSTEM_NUM_LOGIC_VOL $num_logical_vol" + if {$use_strfunc > 2} { + puts "WARNING : Invalid STRFUNC option, setting \ + back to 1\n" + set use_strfunc 1 + } + puts $file_handle "\#define FILE_SYSTEM_USE_STRFUNC $use_strfunc" + if {$set_fs_rpath > 2} { + puts "WARNING : Invalid FS_RPATH option, setting \ + back to 0\n" + set set_fs_rpath 0 + } + puts $file_handle "\#define FILE_SYSTEM_SET_FS_RPATH $set_fs_rpath" + + # MB does not allow word access from RAM + if {$proc_type != "microblaze" && $word_access == true} { + puts $file_handle "\#define FILE_SYSTEM_WORD_ACCESS" + } + } else { + error "ERROR: Invalid interface selected \n" + } + + close $file_handle + + # Copy the include files to the include directory + set srcdir [file join src include] + set dstdir [file join .. .. include] + + # Create dstdir if it does not exist + if { ! [file exists $dstdir] } { + file mkdir $dstdir + } + + # Get list of files in the srcdir + set sources [glob -join $srcdir *.h] + + # Copy each of the files in the list to dstdir + foreach source $sources { + file copy -force $source $dstdir + } +} diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/HTML_custom.css b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/HTML_custom.css new file mode 100644 index 0000000..26defe1 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/HTML_custom.css @@ -0,0 +1,1430 @@ +/* The standard CSS for doxygen 1.8.5 */ + +body{ + background: none repeat scroll 0 0 #FFFFFF; + color: #51626F; + font-family: arial,sans-serif !important; + font-size: 75% !important; + font-weight: normal !important; + margin-left: 10px; + font: 400 12px/15px arial,sans-serif; +} +.contents, .textblock { +font: 400 12px/15px arial,sans-serif; +} +.textblock ul, .contents ul{ + margin: 5px 0; + padding: 0; +} +.textblockol { + margin:5px 15px; + padding:0; + list-style-image: none; +} +.textblock li, .contents li { + margin: 0 0 2px 15px; + padding: 0 0 2px 2px; +} + +/* For hiding RHS TOC +.toc{ +display:none; +}*/ +/* For hiding RHS TOC*/ + +For hiding Nav Bar +.navpath, #nav-path{ +display:none; +} +/* For hiding Nav Bar*/ +/* For hiding extra navrows */ +#navrow2, #navrow3, #navrow4, #navrow5 { +display:none; +} +/* @group Heading Levels */ + +.title { + font: 400 14px/28px arial,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 9px 2px; + text-align: left; +} + +h2, h3 { + color: #E66A08 !important; + font-size: 1.2em !important; + line-height: 1.2em !important; + text-indent: 0 !important; +} +h4, h5{ + color: #E66A08 !important; + font-size: 1.2em !important; + line-height: 1.2em !important; +} +h5{ + font-size: 1.0em !important; + line-height: 1.0em !important; +} +h6{ + color: #E66A08 !important; + font-size: 1.0em !important; + line-height: 1.0em !important; +} +p { + padding-bottom: 0px !important; + font: 400 12px/15px arial,sans-serif; +} +li p { + padding-bottom: 0px !important; + margin: 0px; +} + +h1, h2.groupheader { + clear: both !important; + color: #627178 !important; + font-size: 1.4em !important; + font-weight: bold !important; + line-height: 28px !important; + margin-top: 0.6em !important; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + + +/*Hiding Tabs - Tushar +div.tabs +{ + visibility: hidden; +} */ + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #017bba; + font-weight: normal; + text-decoration: none; + /*font: 400 12px/15px;*/ +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; + /*font: 400 12px/15px;*/ +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 0px solid #C4CFE5; + background-color: #FFFFFF; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 0px; + margin: 0px; + background-color: #FFFFFF; + border: 0px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #51626F +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #E66A08 !important; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; + font: 400 12px/15px arial,sans-serif; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view when not used as main index */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; + font: 400 12px/15px arial,sans-serif; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #CCCCCC; + color: #51626F; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 5px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url(''); + background-repeat:repeat-x; + background-color: #FFFFFF; + margin: 0px; + border-bottom: 0px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; + font: 400 12px/15px arial,sans-serif; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 12px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; + padding: 12px; + +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 5px 0px; + text-align: right; + width: 100%; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 5px; + text-align: left; + width: 100%; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 11px solid #5373B4; +} + +.image +{ + text-align: left; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px arial,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/arrowdown.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/arrowdown.png new file mode 100644 index 0000000000000000000000000000000000000000..0b63f6d38c4b9ec907b820192ebe9724ed6eca22 GIT binary patch literal 246 zcmVkw!R34#Lv2LOS^S2tZA31X++9RY}n zChwn@Z)Wz*WWHH{)HDtJnq&A2hk$b-y(>?@z0iHr41EKCGp#T5?07*qoM6N<$f(V3Pvj6}9 literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/bc_s.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/bc_s.png new file mode 100644 index 0000000000000000000000000000000000000000..224b29aa9847d5a4b3902efd602b7ddf7d33e6c2 GIT binary patch literal 676 zcmV;V0$crwP)y__>=_9%My z{n931IS})GlGUF8K#6VIbs%684A^L3@%PlP2>_sk`UWPq@f;rU*V%rPy_ekbhXT&s z(GN{DxFv}*vZp`F>S!r||M`I*nOwwKX+BC~3P5N3-)Y{65c;ywYiAh-1*hZcToLHK ztpl1xomJ+Yb}K(cfbJr2=GNOnT!UFA7Vy~fBz8?J>XHsbZoDad^8PxfSa0GDgENZS zuLCEqzb*xWX2CG*b&5IiO#NzrW*;`VC9455M`o1NBh+(k8~`XCEEoC1Ybwf;vr4K3 zg|EB<07?SOqHp9DhLpS&bzgo70I+ghB_#)K7H%AMU3v}xuyQq9&Bm~++VYhF09a+U zl7>n7Jjm$K#b*FONz~fj;I->Bf;ule1prFN9FovcDGBkpg>)O*-}eLnC{6oZHZ$o% zXKW$;0_{8hxHQ>l;_*HATI(`7t#^{$(zLe}h*mqwOc*nRY9=?Sx4OOeVIfI|0V(V2 zBrW#G7Ss9wvzr@>H*`r>zE z+e8bOBgqIgldUJlG(YUDviMB`9+DH8n-s9SXRLyJHO1!=wY^79WYZMTa(wiZ!zP66 zA~!21vmF3H2{ngD;+`6j#~6j;$*f*G_2ZD1E;9(yaw7d-QnSCpK(cR1zU3qU0000< KMNUMnLSTYoA~SLT literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/bdwn.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/bdwn.png new file mode 100644 index 0000000000000000000000000000000000000000..940a0b950443a0bb1b216ac03c45b8a16c955452 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)H!3HEvS)PKZC{Gv1kP61Pb5HX&C2wk~_T + + + + + +xilffs: diskio.c File Reference + + + + + + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
diskio.c File Reference
+
+
+

Overview

+

This file is the glue layer between file system and driver.

+
    Description related to SD driver:
+    Process to use file system with SD
+    Select xilffs in SDK when creating a BSP
+    In SDK, set "fs_interface" to 1 to select SD interface.
+    This glue layer can currently be used only with one
+    SD controller enabled.
+    In order to use eMMC, in SDK set "Enable MMC" to 1. If not,
+    SD support is enabled by default.
+
+    Description:
+    This glue layer initializes the host controller and SD card
+    in disk_initialize. If SD card supports it, 4-bit mode and
+    high speed mode will be enabled.
+    The default block size is 512 bytes.
+    disk_read and disk_write functions are used to read and
+    write files using ADMA2 in polled mode.
+    The file system can be used to read from and write to an
+    SD card that is already formatted as FATFS.
+
+MODIFICATION HISTORY:
Ver     Who     Date            Changes
+----- ---- -------- -------------------------------------------------------
+1.00a hk   10/17/13 First release
+2.0   hk   02/12/14 Corrected status check in disk initialize. CR# 772072.
+2.1   hk   04/16/14 Move check for ExtCSD high speed bit set inside if
+                    condition for high speed support.
+                    Include xil_types.h irrespective of xsdps.h. CR# 797086.
+2.2   hk   07/28/14 Make changes to enable use of data cache.
+3.0     sk       12/04/14 Added support for micro SD without
+                                          WP/CD. CR# 810655.
+                                  Make changes for prototypes of disk_read and
+                                  disk_write according to latest version.
+                 12/15/14 Modified the code according to MISRAC 2012 Compliant.
+                                  Updated the FatFs to R0.10b
+                                  Removed alignment for local buffers as CacheInvalidate
+                                  will take care of it.
+        sg   03/03/15 Added card detection check logic
+             04/28/15 Card detection only in case of card detection signal
+3.1   sk   06/04/15 Added support for SD1.
+3.2   sk   11/24/15 Considered the slot type before checking the CD/WP pins.
+3.3   sk   04/01/15 Added one second delay for checking CD pin.
+3.4   sk   06/09/16 Added support for mkfs.
+3.8   mj   07/31/17 Added support for RAM based FATfs.
+      mn   12/04/17 Resolve errors in XilFFS for ARMCC compiler
+3.9   mn   04/18/18 Resolve build warnings for xilffs library
+      mn   07/06/18 Fix Cppcheck and Doxygen warnings
+4.2   mn   08/16/19 Initialize Status variables with failure values
+      mn   09/25/19 Check if the SD is powered on or not in disk_status()
+4.3   mn   02/24/20 Remove unused macro defines
+      mn   04/08/20 Set IsReady to '0' before calling XSdPs_CfgInitialize
+4.5   sk   03/31/21 Maintain discrete global variables for each controller.
+4.6   sk   07/20/21 Fixed compilation warning in RAM interface.
+4.8   sk   05/05/22 Replace standard lib functions with Xilinx functions.
Note
+
+ + + + + + + + + + + + + + + + +

+Functions

DSTATUS disk_status (BYTE pdrv)
 Gets the status of the disk. More...
 
DSTATUS disk_initialize (BYTE pdrv)
 Initializes the drive. More...
 
DRESULT disk_read (BYTE pdrv, BYTE *buff, LBA_t sector, UINT count)
 Reads the drive In case of SD, it reads the SD card using ADMA2 in polled mode. More...
 
DWORD get_fattime (void)
 This function is User Provided Timer Function for FatFs module. More...
 
DRESULT disk_write (BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count)
 Reads the drive In case of SD, it reads the SD card using ADMA2 in polled mode. More...
 
+

Function Documentation

+ +
+
+ + + + + + + + +
DSTATUS disk_initialize (BYTE pdrv)
+
+ +

Initializes the drive.

+

In case of SD, it initializes the host controller and the card. This function also selects additional settings such as bus width, speed and block size.

+
Parameters
+ + +
pdrv- Drive number
+
+
+
Returns
s - which contains an OR of the following information STA_NODISK Disk is not present STA_NOINIT Drive not initialized STA_PROTECT Drive is write protected 0 or only STA_PROTECT both indicate successful initialization.
+
Note
+ +

References disk_status().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DRESULT disk_read (BYTE pdrv,
BYTE * buff,
LBA_t sector,
UINT count 
)
+
+ +

Reads the drive In case of SD, it reads the SD card using ADMA2 in polled mode.

+
Parameters
+ + + + + +
pdrv- Drive number
*buff- Pointer to the data buffer to store read data
sector- Start sector number
count- Sector count
+
+
+
Returns
RES_OK Read successful STA_NOINIT Drive not initialized RES_ERROR Read not successful
+
Note
+ +

References disk_status().

+ +
+
+ +
+
+ + + + + + + + +
DSTATUS disk_status (BYTE pdrv)
+
+ +

Gets the status of the disk.

+

In case of SD, it checks whether card is present or not.

+
Parameters
+ + +
pdrv- Drive number
+
+
+
Returns
0 Status ok STA_NOINIT Drive not initialized STA_NODISK No medium in the drive STA_PROTECT Write protected
+
Note
In case Card detect signal is not connected, this function will not be able to check if card is present.
+ +

Referenced by disk_initialize(), disk_read(), and disk_write().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DRESULT disk_write (BYTE pdrv,
const BYTE * buff,
LBA_t sector,
UINT count 
)
+
+ +

Reads the drive In case of SD, it reads the SD card using ADMA2 in polled mode.

+
Parameters
+ + + + + +
pdrv- Drive number
*buff- Pointer to the data to be written
sector- Sector address
count- Sector count
+
+
+
Returns
RES_OK Read successful STA_NOINIT Drive not initialized RES_ERROR Read not successful
+
Note
+ +

References disk_status().

+ +
+
+ +
+
+ + + + + + + + +
DWORD get_fattime (void )
+
+ +

This function is User Provided Timer Function for FatFs module.

+
Returns
DWORD
+
Note
None
+ +
+
+
+
+ + + diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/diskio_8c.js b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/diskio_8c.js new file mode 100644 index 0000000..465b1fa --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/diskio_8c.js @@ -0,0 +1,8 @@ +var diskio_8c = +[ + [ "disk_initialize", "diskio_8c.html#a09cdaa6f36fa409bdf002727bff98eb1", null ], + [ "disk_read", "diskio_8c.html#a0711b1d03b833e9d73b3be1a6397f461", null ], + [ "disk_status", "diskio_8c.html#a8348ac5ee6d709420c02e45c111f4793", null ], + [ "disk_write", "diskio_8c.html#ac24448955ef914f54a499df1fb45689d", null ], + [ "get_fattime", "diskio_8c.html#af58b536abfd30f77213f4ecaf2ac52f5", null ] +]; \ No newline at end of file diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/dynsections.js b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/dynsections.js new file mode 100644 index 0000000..ed092c7 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/dynsections.js @@ -0,0 +1,97 @@ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} +function toggleLevel(level) +{ + $('table.directory tr').each(function(){ + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l + + + + + +xilffs: File List + + + + + + + + + + + +
+
+ + + + + + + +
+
xilffs +
+
Vitis Drivers API Documentation
+
+
+ + + +
+
+ +
+
+
+ +
+
+
+
File List
+
+
+
Here is a list of all documented files with brief descriptions:
+ + + +
o*diskio.cThis file is the glue layer between file system and driver
\*xilffs_polled_example.c
+
+
+
+ + + diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/files.js b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/files.js new file mode 100644 index 0000000..09094bd --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/files.js @@ -0,0 +1,5 @@ +var files = +[ + [ "diskio.c", "diskio_8c.html", "diskio_8c" ], + [ "xilffs_polled_example.c", "xilffs__polled__example_8c.html", "xilffs__polled__example_8c" ] +]; \ No newline at end of file diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2blank.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2blank.png new file mode 100644 index 0000000000000000000000000000000000000000..63c605bb4c3d941c921a4b6cfa74951e946bcb48 GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2cl.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2cl.png new file mode 100644 index 0000000000000000000000000000000000000000..132f6577bf7f085344904602815a260d29f55d9b GIT binary patch literal 453 zcmV;$0XqJPP)VBF;ev;toEj8_OB0EQg5eYilIj#JZG_m^33l3^k4mtzx!TVD?g)Y$ zrvwRDSqT!wLIM$dWCIa$vtxE|mzbTzu-y&$FvF6WA2a{Wr1g}`WdPT-0JzEZ0IxAv z-Z+ejZc&H;I5-pb_SUB}04j0^V)3t{`z<7asDl2Tw3w3sP%)0^8$bhEg)IOTBcRXv zFfq~3&gvJ$F-U7mpBW8z1GY~HK&7h4^YI~Orv~wLnC0PP_dAkv;nzX{9Q|8Gv=2ca z@v)c9T;D#h`TZ2X&&$ff2wedmot995de~-s3I)yauahg;7qn*?1n?F$e+PwP37}~; z1NKUk7reVK^7A;$QRW7qAx40HHUZ<|k3U%nz(Ec`#i+q9K!dgcROAlCS?`L= v>#=f?wF5ZND!1uAfQsk;KN^4&*8~0npJiJ%2dj9(00000NkvXXu0mjfWVFf_ literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2doc.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2doc.png new file mode 100644 index 0000000000000000000000000000000000000000..17edabff95f7b8da13c9516a04efe05493c29501 GIT binary patch literal 746 zcmV7=@pnbNXRFEm&G8P!&WHG=d)>K?YZ1bzou)2{$)) zumDct!>4SyxL;zgaG>wy`^Hv*+}0kUfCrz~BCOViSb$_*&;{TGGn2^x9K*!Sf0=lV zpP=7O;GA0*Jm*tTYj$IoXvimpnV4S1Z5f$p*f$Db2iq2zrVGQUz~yq`ahn7ck(|CE z7Gz;%OP~J6)tEZWDzjhL9h2hdfoU2)Nd%T<5Kt;Y0XLt&<@6pQx!nw*5`@bq#?l*?3z{Hlzoc=Pr>oB5(9i6~_&-}A(4{Q$>c>%rV&E|a(r&;?i5cQB=} zYSDU5nXG)NS4HEs0it2AHe2>shCyr7`6@4*6{r@8fXRbTA?=IFVWAQJL&H5H{)DpM#{W(GL+Idzf^)uRV@oB8u$ z8v{MfJbTiiRg4bza<41NAzrl{=3fl_D+$t+^!xlQ8S}{UtY`e z;;&9UhyZqQRN%2pot{*Ei0*4~hSF_3AH2@fKU!$NSflS>{@tZpDT4`M2WRTTVH+D? z)GFlEGGHe?koB}i|1w45!BF}N_q&^HJ&-tyR{(afC6H7|aml|tBBbv}55C5DNP8p3 z)~jLEO4Z&2hZmP^i-e%(@d!(E|KRafiU8Q5u(wU((j8un3OR*Hvj+t literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2folderclosed.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2folderclosed.png new file mode 100644 index 0000000000000000000000000000000000000000..bb8ab35edce8e97554e360005ee9fc5bffb36e66 GIT binary patch literal 616 zcmV-u0+;=XP)a9#ETzayK)T~Jw&MMH>OIr#&;dC}is*2Mqdf&akCc=O@`qC+4i z5Iu3w#1M@KqXCz8TIZd1wli&kkl2HVcAiZ8PUn5z_kG@-y;?yK06=cA0U%H0PH+kU zl6dp}OR(|r8-RG+YLu`zbI}5TlOU6ToR41{9=uz^?dGTNL;wIMf|V3`d1Wj3y!#6` zBLZ?xpKR~^2x}?~zA(_NUu3IaDB$tKma*XUdOZN~c=dLt_h_k!dbxm_*ibDM zlFX`g{k$X}yIe%$N)cn1LNu=q9_CS)*>A zsX_mM4L@`(cSNQKMFc$RtYbx{79#j-J7hk*>*+ZZhM4Hw?I?rsXCi#mRWJ=-0LGV5a-WR0Qgt<|Nqf)C-@80`5gIz45^_20000IqP)X=#(TiCT&PiIIVc55T}TU}EUh*{q$|`3@{d>{Tc9Bo>e= zfmF3!f>fbI9#GoEHh0f`i5)wkLpva0ztf%HpZneK?w-7AK@b4Itw{y|Zd3k!fH?q2 zlhckHd_V2M_X7+)U&_Xcfvtw60l;--DgZmLSw-Y?S>)zIqMyJ1#FwLU*%bl38ok+! zh78H87n`ZTS;uhzAR$M`zZ`bVhq=+%u9^$5jDplgxd44}9;IRqUH1YHH|@6oFe%z( zo4)_>E$F&^P-f(#)>(TrnbE>Pefs9~@iN=|)Rz|V`sGfHNrJ)0gJb8xx+SBmRf@1l zvuzt=vGfI)<-F9!o&3l?>9~0QbUDT(wFdnQPv%xdD)m*g%!20>Bc9iYmGAp<9YAa( z0QgYgTWqf1qN++Gqp z8@AYPTB3E|6s=WLG?xw0tm|U!o=&zd+H0oRYE;Dbx+Na9s^STqX|Gnq%H8s(nGDGJ j8vwW|`Ts`)fSK|Kx=IK@RG@g200000NkvXXu0mjfauFEA literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2lastnode.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2lastnode.png new file mode 100644 index 0000000000000000000000000000000000000000..63c605bb4c3d941c921a4b6cfa74951e946bcb48 GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2link.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2link.png new file mode 100644 index 0000000000000000000000000000000000000000..17edabff95f7b8da13c9516a04efe05493c29501 GIT binary patch literal 746 zcmV7=@pnbNXRFEm&G8P!&WHG=d)>K?YZ1bzou)2{$)) zumDct!>4SyxL;zgaG>wy`^Hv*+}0kUfCrz~BCOViSb$_*&;{TGGn2^x9K*!Sf0=lV zpP=7O;GA0*Jm*tTYj$IoXvimpnV4S1Z5f$p*f$Db2iq2zrVGQUz~yq`ahn7ck(|CE z7Gz;%OP~J6)tEZWDzjhL9h2hdfoU2)Nd%T<5Kt;Y0XLt&<@6pQx!nw*5`@bq#?l*?3z{Hlzoc=Pr>oB5(9i6~_&-}A(4{Q$>c>%rV&E|a(r&;?i5cQB=} zYSDU5nXG)NS4HEs0it2AHe2>shCyr7`6@4*6{r@8fXRbTA?=IFVWAQJL&H5H{)DpM#{W(GL+Idzf^)uRV@oB8u$ z8v{MfJbTiiRg4bza<41NAzrl{=3fl_D+$t+^!xlQ8S}{UtY`e z;;&9UhyZqQRN%2pot{*Ei0*4~hSF_3AH2@fKU!$NSflS>{@tZpDT4`M2WRTTVH+D? z)GFlEGGHe?koB}i|1w45!BF}N_q&^HJ&-tyR{(afC6H7|aml|tBBbv}55C5DNP8p3 z)~jLEO4Z&2hZmP^i-e%(@d!(E|KRafiU8Q5u(wU((j8un3OR*Hvj+t literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2mlastnode.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2mlastnode.png new file mode 100644 index 0000000000000000000000000000000000000000..0b63f6d38c4b9ec907b820192ebe9724ed6eca22 GIT binary patch literal 246 zcmVkw!R34#Lv2LOS^S2tZA31X++9RY}n zChwn@Z)Wz*WWHH{)HDtJnq&A2hk$b-y(>?@z0iHr41EKCGp#T5?07*qoM6N<$f(V3Pvj6}9 literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2mnode.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2mnode.png new file mode 100644 index 0000000000000000000000000000000000000000..0b63f6d38c4b9ec907b820192ebe9724ed6eca22 GIT binary patch literal 246 zcmVkw!R34#Lv2LOS^S2tZA31X++9RY}n zChwn@Z)Wz*WWHH{)HDtJnq&A2hk$b-y(>?@z0iHr41EKCGp#T5?07*qoM6N<$f(V3Pvj6}9 literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2mo.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2mo.png new file mode 100644 index 0000000000000000000000000000000000000000..4bfb80f76e65815989a9350ad79d8ce45380e2b1 GIT binary patch literal 403 zcmV;E0c`$>P)${!fXv7NWJ%@%u4(KapRY>T6_x;E zxE7kt!}Tiw8@d9Sd`rTGum>z#Q14vIm`wm1#-byD1muMi02@YNO5LRF0o!Y{`a!Ya z{^&p0Su|s705&2QxmqdexG+-zNKL3f@8gTQSJrKByfo+oNJ^-{|Mn||Q5SDwjQVsS zr1}7o5-QMs>gYIMD>GRw@$lT`z4r-_m{5U#cR{urD_)TOeY)(UD|qZ^&y`IVijqk~ xs(9-kWFr7E^!lgi8GsFK5kOY_{Xbgf0^etEU%fLevs?fG002ovPDHLkV1nB&vX1}& literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2node.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2node.png new file mode 100644 index 0000000000000000000000000000000000000000..63c605bb4c3d941c921a4b6cfa74951e946bcb48 GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2ns.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2ns.png new file mode 100644 index 0000000000000000000000000000000000000000..72e3d71c2892d6f00e259facebc88b45f6db2e35 GIT binary patch literal 388 zcmV-~0ek+5P)f+++#cT|!CkD&4pnIkeMEUEM*>`*9>+Juji$!h-mW%M^8s9957{3nvbrz^&=u<~TAUrFROkmt%^F~Ez+-c53Lv%iH3d38!Rv?K zrb&MYAhp;Gf<}wS;9ZZq2@;!uYG;=Z>~GKE^{HD4keu}lnyqhc>kWX^tQn|warJ~h zT+rtMkdz6aHoN%z(o|&wpu@@OpJnF_z{PA)6(FHw02iHslz^(N{4*+K9)QJHR87wT iTyp>aXaF{u2lxRou|^4tux6eB0000^P)R?RzRoKvklcaQ%HF6%rK2&ZgO(-ihJ_C zzrKgp4jgO( fd_(yg|3PpEQb#9`a?Pz_00000NkvXXu0mjftR`5K literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2pnode.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2pnode.png new file mode 100644 index 0000000000000000000000000000000000000000..c6ee22f937a07d1dbfc27c669d11f8ed13e2f152 GIT binary patch literal 229 zcmV^P)R?RzRoKvklcaQ%HF6%rK2&ZgO(-ihJ_C zzrKgp4jgO( fd_(yg|3PpEQb#9`a?Pz_00000NkvXXu0mjftR`5K literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2splitbar.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2splitbar.png new file mode 100644 index 0000000000000000000000000000000000000000..fe895f2c58179b471a22d8320b39a4bd7312ec8e GIT binary patch literal 314 zcmeAS@N?(olHy`uVBq!ia0vp^Yzz!63>-{AmhX=Jf(#6djGiuzAr*{o?=JLmPLyc> z_*`QK&+BH@jWrYJ7>r6%keRM@)Qyv8R=enp0jiI>aWlGyB58O zFVR20d+y`K7vDw(hJF3;>dD*3-?v=<8M)@x|EEGLnJsniYK!2U1 Y!`|5biEc?d1`HDhPgg&ebxsLQ02F6;9RL6T literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2vertline.png b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/ftv2vertline.png new file mode 100644 index 0000000000000000000000000000000000000000..63c605bb4c3d941c921a4b6cfa74951e946bcb48 GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/globals.html b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/globals.html new file mode 100644 index 0000000..8c1e7a5 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/globals.html @@ -0,0 +1,98 @@ + + + + + + +xilffs: APIs + + + + + + + + + + + +
+
+ + + + + + + +
+
xilffs +
+
Vitis Drivers API Documentation
+
+
+ + + + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+
+
+ + + diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/globals_func.html b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/globals_func.html new file mode 100644 index 0000000..a03fe6a --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/globals_func.html @@ -0,0 +1,98 @@ + + + + + + +xilffs: APIs + + + + + + + + + + + +
+
+ + + + + + + +
+
xilffs +
+
Vitis Drivers API Documentation
+
+
+ + + + +
+
+ +
+
+
+ +
+
+
+
+ + + diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/index.html b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/index.html new file mode 100644 index 0000000..a7ca53c --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/index.html @@ -0,0 +1,73 @@ + + + + + + +xilffs: Main Page + + + + + + + + + + + +
+
+ + + + + + + +
+
xilffs +
+
Vitis Drivers API Documentation
+
+
+ + + +
+
+ +
+
+
+ +
+
+
+
xilffs Documentation
+
+
+
+
+ + + diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/jquery.js b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/jquery.js new file mode 100644 index 0000000..3db33e6 --- /dev/null +++ b/bsp_z7/ps7_cortexa9_0/libsrc/xilffs/doc/html/api/jquery.js @@ -0,0 +1,72 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType; +if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1 +},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av); +ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length; +if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b +})}})(window); +/*! + * jQuery UI 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */ +(function(a,d){a.ui=a.ui||{};if(a.ui.version){return}a.extend(a.ui,{version:"1.8.18",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(e,f){return typeof e==="number"?this.each(function(){var g=this;setTimeout(function(){a(g).focus();if(f){f.call(g)}},e)}):this._focus.apply(this,arguments)},scrollParent:function(){var e;if((a.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){e=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(a.curCSS(this,"position",1))&&(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}else{e=this.parents().filter(function(){return(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!e.length?a(document):e},zIndex:function(h){if(h!==d){return this.css("zIndex",h)}if(this.length){var f=a(this[0]),e,g;while(f.length&&f[0]!==document){e=f.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){g=parseInt(f.css("zIndex"),10);if(!isNaN(g)&&g!==0){return g}}f=f.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});a.each(["Width","Height"],function(g,e){var f=e==="Width"?["Left","Right"]:["Top","Bottom"],h=e.toLowerCase(),k={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};function j(m,l,i,n){a.each(f,function(){l-=parseFloat(a.curCSS(m,"padding"+this,true))||0;if(i){l-=parseFloat(a.curCSS(m,"border"+this+"Width",true))||0}if(n){l-=parseFloat(a.curCSS(m,"margin"+this,true))||0}});return l}a.fn["inner"+e]=function(i){if(i===d){return k["inner"+e].call(this)}return this.each(function(){a(this).css(h,j(this,i)+"px")})};a.fn["outer"+e]=function(i,l){if(typeof i!=="number"){return k["outer"+e].call(this,i)}return this.each(function(){a(this).css(h,j(this,i,true,l)+"px")})}});function c(g,e){var j=g.nodeName.toLowerCase();if("area"===j){var i=g.parentNode,h=i.name,f;if(!g.href||!h||i.nodeName.toLowerCase()!=="map"){return false}f=a("img[usemap=#"+h+"]")[0];return !!f&&b(f)}return(/input|select|textarea|button|object/.test(j)?!g.disabled:"a"==j?g.href||e:e)&&b(g)}function b(e){return !a(e).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.extend(a.expr[":"],{data:function(g,f,e){return !!a.data(g,e[3])},focusable:function(e){return c(e,!isNaN(a.attr(e,"tabindex")))},tabbable:function(g){var e=a.attr(g,"tabindex"),f=isNaN(e);return(f||e>=0)&&c(g,!f)}});a(function(){var e=document.body,f=e.appendChild(f=document.createElement("div"));f.offsetHeight;a.extend(f.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});a.support.minHeight=f.offsetHeight===100;a.support.selectstart="onselectstart" in f;e.removeChild(f).style.display="none"});a.extend(a.ui,{plugin:{add:function(f,g,j){var h=a.ui[f].prototype;for(var e in j){h.plugins[e]=h.plugins[e]||[];h.plugins[e].push([g,j[e]])}},call:function(e,g,f){var j=e.plugins[g];if(!j||!e.element[0].parentNode){return}for(var h=0;h0){return true}h[e]=1;g=(h[e]>0);h[e]=0;return g},isOverAxis:function(f,e,g){return(f>e)&&(f<(e+g))},isOver:function(j,f,i,h,e,g){return a.ui.isOverAxis(j,i,e)&&a.ui.isOverAxis(f,h,g)}})})(jQuery);/*! + * jQuery UI Widget 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */ +(function(b,d){if(b.cleanData){var c=b.cleanData;b.cleanData=function(f){for(var g=0,h;(h=f[g])!=null;g++){try{b(h).triggerHandler("remove")}catch(j){}}c(f)}}else{var a=b.fn.remove;b.fn.remove=function(e,f){return this.each(function(){if(!f){if(!e||b.filter(e,[this]).length){b("*",this).add([this]).each(function(){try{b(this).triggerHandler("remove")}catch(g){}})}}return a.call(b(this),e,f)})}}b.widget=function(f,h,e){var g=f.split(".")[0],j;f=f.split(".")[1];j=g+"-"+f;if(!e){e=h;h=b.Widget}b.expr[":"][j]=function(k){return !!b.data(k,f)};b[g]=b[g]||{};b[g][f]=function(k,l){if(arguments.length){this._createWidget(k,l)}};var i=new h();i.options=b.extend(true,{},i.options);b[g][f].prototype=b.extend(true,i,{namespace:g,widgetName:f,widgetEventPrefix:b[g][f].prototype.widgetEventPrefix||f,widgetBaseClass:j},e);b.widget.bridge(f,b[g][f])};b.widget.bridge=function(f,e){b.fn[f]=function(i){var g=typeof i==="string",h=Array.prototype.slice.call(arguments,1),j=this;i=!g&&h.length?b.extend.apply(null,[true,i].concat(h)):i;if(g&&i.charAt(0)==="_"){return j}if(g){this.each(function(){var k=b.data(this,f),l=k&&b.isFunction(k[i])?k[i].apply(k,h):k;if(l!==k&&l!==d){j=l;return false}})}else{this.each(function(){var k=b.data(this,f);if(k){k.option(i||{})._init()}else{b.data(this,f,new e(i,this))}})}return j}};b.Widget=function(e,f){if(arguments.length){this._createWidget(e,f)}};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(f,g){b.data(g,this.widgetName,this);this.element=b(g);this.options=b.extend(true,{},this.options,this._getCreateOptions(),f);var e=this;this.element.bind("remove."+this.widgetName,function(){e.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(f,g){var e=f;if(arguments.length===0){return b.extend({},this.options)}if(typeof f==="string"){if(g===d){return this.options[f]}e={};e[f]=g}this._setOptions(e);return this},_setOptions:function(f){var e=this;b.each(f,function(g,h){e._setOption(g,h)});return this},_setOption:function(e,f){this.options[e]=f;if(e==="disabled"){this.widget()[f?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",f)}return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(e,f,g){var j,i,h=this.options[e];g=g||{};f=b.Event(f);f.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase();f.target=this.element[0];i=f.originalEvent;if(i){for(j in i){if(!(j in f)){f[j]=i[j]}}}this.element.trigger(f,g);return !(b.isFunction(h)&&h.call(this.element[0],f,g)===false||f.isDefaultPrevented())}}})(jQuery);/*! + * jQuery UI Mouse 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function(b,c){var a=false;b(document).mouseup(function(d){a=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var d=this;this.element.bind("mousedown."+this.widgetName,function(e){return d._mouseDown(e)}).bind("click."+this.widgetName,function(e){if(true===b.data(e.target,d.widgetName+".preventClickEvent")){b.removeData(e.target,d.widgetName+".preventClickEvent");e.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(f){if(a){return}(this._mouseStarted&&this._mouseUp(f));this._mouseDownEvent=f;var e=this,g=(f.which==1),d=(typeof this.options.cancel=="string"&&f.target.nodeName?b(f.target).closest(this.options.cancel).length:false);if(!g||d||!this._mouseCapture(f)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(f)&&this._mouseDelayMet(f)){this._mouseStarted=(this._mouseStart(f)!==false);if(!this._mouseStarted){f.preventDefault();return true}}if(true===b.data(f.target,this.widgetName+".preventClickEvent")){b.removeData(f.target,this.widgetName+".preventClickEvent")}this._mouseMoveDelegate=function(h){return e._mouseMove(h)};this._mouseUpDelegate=function(h){return e._mouseUp(h)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);f.preventDefault();a=true;return true},_mouseMove:function(d){if(b.browser.msie&&!(document.documentMode>=9)&&!d.button){return this._mouseUp(d)}if(this._mouseStarted){this._mouseDrag(d);return d.preventDefault()}if(this._mouseDistanceMet(d)&&this._mouseDelayMet(d)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,d)!==false);(this._mouseStarted?this._mouseDrag(d):this._mouseUp(d))}return !this._mouseStarted},_mouseUp:function(d){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;if(d.target==this._mouseDownEvent.target){b.data(d.target,this.widgetName+".preventClickEvent",true)}this._mouseStop(d)}return false},_mouseDistanceMet:function(d){return(Math.max(Math.abs(this._mouseDownEvent.pageX-d.pageX),Math.abs(this._mouseDownEvent.pageY-d.pageY))>=this.options.distance)},_mouseDelayMet:function(d){return this.mouseDelayMet},_mouseStart:function(d){},_mouseDrag:function(d){},_mouseStop:function(d){},_mouseCapture:function(d){return true}})})(jQuery);(function(c,d){c.widget("ui.resizable",c.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000},_create:function(){var f=this,k=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(k.aspectRatio),aspectRatio:k.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:k.helper||k.ghost||k.animate?k.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){this.element.wrap(c('
').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=k.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var l=this.handles.split(",");this.handles={};for(var g=0;g
');if(/sw|se|ne|nw/.test(j)){h.css({zIndex:++k.zIndex})}if("se"==j){h.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[j]=".ui-resizable-"+j;this.element.append(h)}}this._renderAxis=function(q){q=q||this.element;for(var n in this.handles){if(this.handles[n].constructor==String){this.handles[n]=c(this.handles[n],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var o=c(this.handles[n],this.element),p=0;p=/sw|ne|nw|se|n|s/.test(n)?o.outerHeight():o.outerWidth();var m=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");q.css(m,p);this._proportionallyResize()}if(!c(this.handles[n]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!f.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}f.axis=i&&i[1]?i[1]:"se"}});if(k.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){if(k.disabled){return}c(this).removeClass("ui-resizable-autohide");f._handles.show()},function(){if(k.disabled){return}if(!f.resizing){c(this).addClass("ui-resizable-autohide");f._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var e=function(g){c(g).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){e(this.element);var f=this.element;f.after(this.originalElement.css({position:f.css("position"),width:f.outerWidth(),height:f.outerHeight(),top:f.css("top"),left:f.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);e(this.originalElement);return this},_mouseCapture:function(f){var g=false;for(var e in this.handles){if(c(this.handles[e])[0]==f.target){g=true}}return !this.options.disabled&&g},_mouseStart:function(g){var j=this.options,f=this.element.position(),e=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(e.is(".ui-draggable")||(/absolute/).test(e.css("position"))){e.css({position:"absolute",top:f.top,left:f.left})}this._renderProxy();var k=b(this.helper.css("left")),h=b(this.helper.css("top"));if(j.containment){k+=c(j.containment).scrollLeft()||0;h+=c(j.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:k,top:h};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:k,top:h};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:g.pageX,top:g.pageY};this.aspectRatio=(typeof j.aspectRatio=="number")?j.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var i=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",i=="auto"?this.axis+"-resize":i);e.addClass("ui-resizable-resizing");this._propagate("start",g);return true},_mouseDrag:function(e){var h=this.helper,g=this.options,m={},q=this,j=this.originalMousePosition,n=this.axis;var r=(e.pageX-j.left)||0,p=(e.pageY-j.top)||0;var i=this._change[n];if(!i){return false}var l=i.apply(this,[e,r,p]),k=c.browser.msie&&c.browser.version<7,f=this.sizeDiff;this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey){l=this._updateRatio(l,e)}l=this._respectSize(l,e);this._propagate("resize",e);h.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(l);this._trigger("resize",e,this.ui());return false},_mouseStop:function(h){this.resizing=false;var i=this.options,m=this;if(this._helper){var g=this._proportionallyResizeElements,e=g.length&&(/textarea/i).test(g[0].nodeName),f=e&&c.ui.hasScroll(g[0],"left")?0:m.sizeDiff.height,k=e?0:m.sizeDiff.width;var n={width:(m.helper.width()-k),height:(m.helper.height()-f)},j=(parseInt(m.element.css("left"),10)+(m.position.left-m.originalPosition.left))||null,l=(parseInt(m.element.css("top"),10)+(m.position.top-m.originalPosition.top))||null;if(!i.animate){this.element.css(c.extend(n,{top:l,left:j}))}m.helper.height(m.size.height);m.helper.width(m.size.width);if(this._helper&&!i.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",h);if(this._helper){this.helper.remove()}return false},_updateVirtualBoundaries:function(g){var j=this.options,i,h,f,k,e;e={minWidth:a(j.minWidth)?j.minWidth:0,maxWidth:a(j.maxWidth)?j.maxWidth:Infinity,minHeight:a(j.minHeight)?j.minHeight:0,maxHeight:a(j.maxHeight)?j.maxHeight:Infinity};if(this._aspectRatio||g){i=e.minHeight*this.aspectRatio;f=e.minWidth/this.aspectRatio;h=e.maxHeight*this.aspectRatio;k=e.maxWidth/this.aspectRatio;if(i>e.minWidth){e.minWidth=i}if(f>e.minHeight){e.minHeight=f}if(hl.width),s=a(l.height)&&i.minHeight&&(i.minHeight>l.height);if(h){l.width=i.minWidth}if(s){l.height=i.minHeight}if(t){l.width=i.maxWidth}if(m){l.height=i.maxHeight}var f=this.originalPosition.left+this.originalSize.width,p=this.position.top+this.size.height;var k=/sw|nw|w/.test(q),e=/nw|ne|n/.test(q);if(h&&k){l.left=f-i.minWidth}if(t&&k){l.left=f-i.maxWidth}if(s&&e){l.top=p-i.minHeight}if(m&&e){l.top=p-i.maxHeight}var n=!l.width&&!l.height;if(n&&!l.left&&l.top){l.top=null}else{if(n&&!l.top&&l.left){l.left=null}}return l},_proportionallyResize:function(){var k=this.options;if(!this._proportionallyResizeElements.length){return}var g=this.helper||this.element;for(var f=0;f');var e=c.browser.msie&&c.browser.version<7,g=(e?1:0),h=(e?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+h,height:this.element.outerHeight()+h,position:"absolute",left:this.elementOffset.left-g+"px",top:this.elementOffset.top-g+"px",zIndex:++i.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(g,f,e){return{width:this.originalSize.width+f}},w:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{left:i.left+f,width:g.width-f}},n:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{top:i.top+e,height:g.height-e}},s:function(g,f,e){return{height:this.originalSize.height+e}},se:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},sw:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[g,f,e]))},ne:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},nw:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[g,f,e]))}},_propagate:function(f,e){c.ui.plugin.call(this,f,[e,this.ui()]);(f!="resize"&&this._trigger(f,e,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});c.extend(c.ui.resizable,{version:"1.8.18"});c.ui.plugin.add("resizable","alsoResize",{start:function(f,g){var e=c(this).data("resizable"),i=e.options;var h=function(j){c(j).each(function(){var k=c(this);k.data("resizable-alsoresize",{width:parseInt(k.width(),10),height:parseInt(k.height(),10),left:parseInt(k.css("left"),10),top:parseInt(k.css("top"),10)})})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.parentNode){if(i.alsoResize.length){i.alsoResize=i.alsoResize[0];h(i.alsoResize)}else{c.each(i.alsoResize,function(j){h(j)})}}else{h(i.alsoResize)}},resize:function(g,i){var f=c(this).data("resizable"),j=f.options,h=f.originalSize,l=f.originalPosition;var k={height:(f.size.height-h.height)||0,width:(f.size.width-h.width)||0,top:(f.position.top-l.top)||0,left:(f.position.left-l.left)||0},e=function(m,n){c(m).each(function(){var q=c(this),r=c(this).data("resizable-alsoresize"),p={},o=n&&n.length?n:q.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];c.each(o,function(s,u){var t=(r[u]||0)+(k[u]||0);if(t&&t>=0){p[u]=t||null}});q.css(p)})};if(typeof(j.alsoResize)=="object"&&!j.alsoResize.nodeType){c.each(j.alsoResize,function(m,n){e(m,n)})}else{e(j.alsoResize)}},stop:function(e,f){c(this).removeData("resizable-alsoresize")}});c.ui.plugin.add("resizable","animate",{stop:function(i,n){var p=c(this).data("resizable"),j=p.options;var h=p._proportionallyResizeElements,e=h.length&&(/textarea/i).test(h[0].nodeName),f=e&&c.ui.hasScroll(h[0],"left")?0:p.sizeDiff.height,l=e?0:p.sizeDiff.width;var g={width:(p.size.width-l),height:(p.size.height-f)},k=(parseInt(p.element.css("left"),10)+(p.position.left-p.originalPosition.left))||null,m=(parseInt(p.element.css("top"),10)+(p.position.top-p.originalPosition.top))||null; +p.element.animate(c.extend(g,m&&k?{top:m,left:k}:{}),{duration:j.animateDuration,easing:j.animateEasing,step:function(){var o={width:parseInt(p.element.css("width"),10),height:parseInt(p.element.css("height"),10),top:parseInt(p.element.css("top"),10),left:parseInt(p.element.css("left"),10)};if(h&&h.length){c(h[0]).css({width:o.width,height:o.height})}p._updateCache(o);p._propagate("resize",i)}})}});c.ui.plugin.add("resizable","containment",{start:function(f,r){var t=c(this).data("resizable"),j=t.options,l=t.element;var g=j.containment,k=(g instanceof c)?g.get(0):(/parent/.test(g))?l.parent().get(0):g;if(!k){return}t.containerElement=c(k);if(/document/.test(g)||g==document){t.containerOffset={left:0,top:0};t.containerPosition={left:0,top:0};t.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var n=c(k),i=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){i[p]=b(n.css("padding"+o))});t.containerOffset=n.offset();t.containerPosition=n.position();t.containerSize={height:(n.innerHeight()-i[3]),width:(n.innerWidth()-i[1])};var q=t.containerOffset,e=t.containerSize.height,m=t.containerSize.width,h=(c.ui.hasScroll(k,"left")?k.scrollWidth:m),s=(c.ui.hasScroll(k)?k.scrollHeight:e);t.parentData={element:k,left:q.left,top:q.top,width:h,height:s}}},resize:function(g,q){var t=c(this).data("resizable"),i=t.options,f=t.containerSize,p=t.containerOffset,m=t.size,n=t.position,r=t._aspectRatio||g.shiftKey,e={top:0,left:0},h=t.containerElement;if(h[0]!=document&&(/static/).test(h.css("position"))){e=p}if(n.left<(t._helper?p.left:0)){t.size.width=t.size.width+(t._helper?(t.position.left-p.left):(t.position.left-e.left));if(r){t.size.height=t.size.width/i.aspectRatio}t.position.left=i.helper?p.left:0}if(n.top<(t._helper?p.top:0)){t.size.height=t.size.height+(t._helper?(t.position.top-p.top):t.position.top);if(r){t.size.width=t.size.height*i.aspectRatio}t.position.top=t._helper?p.top:0}t.offset.left=t.parentData.left+t.position.left;t.offset.top=t.parentData.top+t.position.top;var l=Math.abs((t._helper?t.offset.left-e.left:(t.offset.left-e.left))+t.sizeDiff.width),s=Math.abs((t._helper?t.offset.top-e.top:(t.offset.top-p.top))+t.sizeDiff.height);var k=t.containerElement.get(0)==t.element.parent().get(0),j=/relative|absolute/.test(t.containerElement.css("position"));if(k&&j){l-=t.parentData.left}if(l+t.size.width>=t.parentData.width){t.size.width=t.parentData.width-l;if(r){t.size.height=t.size.width/t.aspectRatio}}if(s+t.size.height>=t.parentData.height){t.size.height=t.parentData.height-s;if(r){t.size.width=t.size.height*t.aspectRatio}}},stop:function(f,n){var q=c(this).data("resizable"),g=q.options,l=q.position,m=q.containerOffset,e=q.containerPosition,i=q.containerElement;var j=c(q.helper),r=j.offset(),p=j.outerWidth()-q.sizeDiff.width,k=j.outerHeight()-q.sizeDiff.height;if(q._helper&&!g.animate&&(/relative/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}if(q._helper&&!g.animate&&(/static/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}}});c.ui.plugin.add("resizable","ghost",{start:function(g,h){var e=c(this).data("resizable"),i=e.options,f=e.size;e.ghost=e.originalElement.clone();e.ghost.css({opacity:0.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:"");e.ghost.appendTo(e.helper)},resize:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost){e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})}},stop:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost&&e.helper){e.helper.get(0).removeChild(e.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(e,m){var p=c(this).data("resizable"),h=p.options,k=p.size,i=p.originalSize,j=p.originalPosition,n=p.axis,l=h._aspectRatio||e.shiftKey;h.grid=typeof h.grid=="number"?[h.grid,h.grid]:h.grid;var g=Math.round((k.width-i.width)/(h.grid[0]||1))*(h.grid[0]||1),f=Math.round((k.height-i.height)/(h.grid[1]||1))*(h.grid[1]||1);if(/^(se|s|e)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f}else{if(/^(ne)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f}else{if(/^(sw)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.left=j.left-g}else{p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f;p.position.left=j.left-g}}}}});var b=function(e){return parseInt(e,10)||0};var a=function(e){return !isNaN(parseInt(e,10))}})(jQuery);/*! + * jQuery hashchange event - v1.3 - 7/21/2010 + * http://benalman.com/projects/jquery-hashchange-plugin/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ +(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$('